Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ pr -dir /path/to/your/folder
| `--ext` | Filter files by extension | All files | `pr --ext .go` |
| `--output` | Save output to file | Terminal output | `pr --output output.txt` |
| `--no-color` | Disable colored output | Colors enabled | `pr --no-color` |
| `--hidden` | Include hidden files | Not included | `pr --hidden` |

### Sorting Flags

Expand Down
2 changes: 2 additions & 0 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ func main() {
flag.StringVar(&config.ExecColor, "exec-color", "red", "Color for executables (e.g., red, green, blue)")
flag.StringVar(&config.SortBy, "sort-by", "name", "Sort by 'name', 'size', or 'time'")
flag.StringVar(&config.Order, "order", "asc", "Sort order 'asc' or 'desc'")
flag.BoolVar(&config.IncludeHidden, "hidden", false, "Include hidden files and directories")

// Add --exclude flag to specify exclusion patterns
flag.Func("exclude", "Exclude files/directories matching the pattern (can be specified multiple times)", func(pattern string) error {
Expand All @@ -41,5 +42,6 @@ func main() {
config.ExcludePatterns,
config.SortBy,
config.Order,
config.IncludeHidden,
)
}
26 changes: 15 additions & 11 deletions pkg/printer/printer.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ type Config struct {
ExcludePatterns []string
SortBy string // "name", "size", "time"
Order string // "asc", "desc"
IncludeHidden bool
}

var colorMap = map[string]color.Attribute{
Expand Down Expand Up @@ -53,13 +54,15 @@ func HandleFlags(config Config) {
config.DirPath,
config.OutputPath,
config.ExtFilter,
!config.NoColor, config.OutputFormat,
!config.NoColor,
config.OutputFormat,
config.DirColor,
config.FileColor,
config.ExecColor,
config.ExcludePatterns,
config.SortBy,
config.Order)
config.Order,
config.IncludeHidden)
}

// PrintProjectStructure prints the directory structure of the given root directory.
Expand All @@ -74,18 +77,19 @@ func PrintProjectStructure(
execColorName string,
excludePatterns []string,
sortBy string,
order string) {
order string,
includeHidden bool) {
absRoot, err := filepath.Abs(root)
if err != nil {
fmt.Println("Error getting absolute path:", err)
return
}

if format == "text" {
dirCount, fileCount := getTreeOutput(absRoot, extFilter, useColor, dirColorName, fileColorName, execColorName, excludePatterns, sortBy, order)
dirCount, fileCount := getTreeOutput(absRoot, extFilter, useColor, dirColorName, fileColorName, execColorName, excludePatterns, sortBy, order, includeHidden)
fmt.Printf("\n%d directories, %d files\n", dirCount, fileCount)
} else {
tree := buildTree(absRoot, extFilter, excludePatterns, sortBy, order)
tree := buildTree(absRoot, extFilter, excludePatterns, sortBy, order, includeHidden)
var output string
switch format {
case "json":
Expand All @@ -102,15 +106,15 @@ func PrintProjectStructure(
return
}

fmt.Print(output)
fmt.Println(output)

if outputFile != "" {
writeToFile(output, outputFile)
}
}
}

func getTreeOutput(root string, extFilter string, useColor bool, dirColorName string, fileColorName string, execColorName string, excludePatterns []string, sortBy string, order string) (int, int) {
func getTreeOutput(root string, extFilter string, useColor bool, dirColorName string, fileColorName string, execColorName string, excludePatterns []string, sortBy string, order string, includeHidden bool) (int, int) {
dirCount := 0
fileCount := 0

Expand All @@ -135,7 +139,7 @@ func getTreeOutput(root string, extFilter string, useColor bool, dirColorName st
sortEntries(entries, sortBy, order)

for i, entry := range entries {
if strings.HasPrefix(entry.Name(), ".") {
if !includeHidden && strings.HasPrefix(entry.Name(), ".") {
continue
}

Expand Down Expand Up @@ -239,7 +243,7 @@ type Node struct {
}

// buildTree constructs a tree of Nodes from the directory structure
func buildTree(currentDir string, extFilter string, excludePatterns []string, sortBy string, order string) *Node {
func buildTree(currentDir string, extFilter string, excludePatterns []string, sortBy string, order string, includeHidden bool) *Node {
dir, err := os.Open(currentDir)
if err != nil {
return nil
Expand All @@ -260,7 +264,7 @@ func buildTree(currentDir string, extFilter string, excludePatterns []string, so
}

for _, entry := range entries {
if strings.HasPrefix(entry.Name(), ".") {
if !includeHidden && strings.HasPrefix(entry.Name(), ".") {
continue
}

Expand All @@ -270,7 +274,7 @@ func buildTree(currentDir string, extFilter string, excludePatterns []string, so
}

if entry.IsDir() {
child := buildTree(filepath.Join(currentDir, entry.Name()), extFilter, excludePatterns, sortBy, order)
child := buildTree(filepath.Join(currentDir, entry.Name()), extFilter, excludePatterns, sortBy, order, includeHidden)
if child != nil {
node.Children = append(node.Children, child)
}
Expand Down
6 changes: 3 additions & 3 deletions pkg/printer/printer_bench_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ func BenchmarkPrintProjectStructure(b *testing.B) {
// Run the benchmark
b.ResetTimer() // Reset the timer to exclude setup time
for i := 0; i < b.N; i++ {
PrintProjectStructure(".", "", "", false, "text", "blue", "green", "red", []string{}, "name", "asc")
PrintProjectStructure(".", "", "", false, "text", "blue", "green", "red", []string{}, "name", "asc", false)
}
}

Expand All @@ -43,7 +43,7 @@ func BenchmarkPrintProjectStructure_JSON(b *testing.B) {

b.ResetTimer()
for i := 0; i < b.N; i++ {
PrintProjectStructure(".", "", "", false, "json", "blue", "green", "red", []string{}, "name", "asc")
PrintProjectStructure(".", "", "", false, "json", "blue", "green", "red", []string{}, "name", "asc", false)
}
}

Expand All @@ -61,7 +61,7 @@ func BenchmarkPrintProjectStructure_LargeDirectory(b *testing.B) {

b.ResetTimer() // Reset the timer to exclude setup time
for i := 0; i < b.N; i++ {
PrintProjectStructure(".", "", "", false, "text", "blue", "green", "red", []string{}, "name", "asc")
PrintProjectStructure(".", "", "", false, "text", "blue", "green", "red", []string{}, "name", "asc", false)
}
}

Expand Down
33 changes: 22 additions & 11 deletions pkg/printer/printer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ func TestPrintProjectStructure(t *testing.T) {
// Test text output
t.Run("TextOutput", func(t *testing.T) {
output := captureOutput(func() {
PrintProjectStructure(".", "", "", false, "text", "blue", "green", "red", []string{}, "name", "asc")
PrintProjectStructure(".", "", "", false, "text", "blue", "green", "red", []string{}, "name", "asc", false)
})

rootName := filepath.Base(tmpDir)
Expand Down Expand Up @@ -57,7 +57,7 @@ func TestPrintProjectStructure(t *testing.T) {
// Test JSON output
t.Run("JSONOutput", func(t *testing.T) {
output := captureOutput(func() {
PrintProjectStructure(".", "", "", false, "json", "blue", "green", "red", []string{}, "name", "asc")
PrintProjectStructure(".", "", "", false, "json", "blue", "green", "red", []string{}, "name", "asc", false)
})

// Verify that the output is valid JSON
Expand All @@ -70,7 +70,7 @@ func TestPrintProjectStructure(t *testing.T) {
// Test XML output
t.Run("XMLOutput", func(t *testing.T) {
output := captureOutput(func() {
PrintProjectStructure(".", "", "", false, "xml", "blue", "green", "red", []string{}, "name", "asc")
PrintProjectStructure(".", "", "", false, "xml", "blue", "green", "red", []string{}, "name", "asc", false)
})

// Verify that the output is valid XML
Expand All @@ -83,7 +83,7 @@ func TestPrintProjectStructure(t *testing.T) {
// Test YAML output
t.Run("YAMLOutput", func(t *testing.T) {
output := captureOutput(func() {
PrintProjectStructure(".", "", "", false, "yaml", "blue", "green", "red", []string{}, "name", "asc")
PrintProjectStructure(".", "", "", false, "yaml", "blue", "green", "red", []string{}, "name", "asc", false)
})

// Verify that the output is valid YAML
Expand All @@ -96,7 +96,7 @@ func TestPrintProjectStructure(t *testing.T) {
// Test exclusion patterns
t.Run("ExclusionPatterns", func(t *testing.T) {
output := captureOutput(func() {
PrintProjectStructure(".", "", "", false, "text", "blue", "green", "red", []string{"*.go"}, "name", "asc")
PrintProjectStructure(".", "", "", false, "text", "blue", "green", "red", []string{"*.go"}, "name", "asc", false)
})

rootName := filepath.Base(tmpDir)
Expand All @@ -120,7 +120,7 @@ func TestPrintProjectStructure(t *testing.T) {
// Test sorting by name (ascending)
t.Run("SortByNameAsc", func(t *testing.T) {
output := captureOutput(func() {
PrintProjectStructure(".", "", "", false, "text", "blue", "green", "red", []string{}, "name", "asc")
PrintProjectStructure(".", "", "", false, "text", "blue", "green", "red", []string{}, "name", "asc", false)
})

// Verify that the output is sorted by name in ascending order
Expand All @@ -131,7 +131,7 @@ func TestPrintProjectStructure(t *testing.T) {
// Test sorting by name (descending)
t.Run("SortByNameDesc", func(t *testing.T) {
output := captureOutput(func() {
PrintProjectStructure(".", "", "", false, "text", "blue", "green", "red", []string{}, "name", "desc")
PrintProjectStructure(".", "", "", false, "text", "blue", "green", "red", []string{}, "name", "desc", false)
})

// Verify that the output is sorted by name in descending order
Expand All @@ -142,7 +142,7 @@ func TestPrintProjectStructure(t *testing.T) {
// Test sorting by size (ascending)
t.Run("SortBySizeAsc", func(t *testing.T) {
output := captureOutput(func() {
PrintProjectStructure(".", "", "", false, "text", "blue", "green", "red", []string{}, "size", "asc")
PrintProjectStructure(".", "", "", false, "text", "blue", "green", "red", []string{}, "size", "asc", false)
})

// Verify that the output is sorted by size in ascending order
Expand All @@ -153,7 +153,7 @@ func TestPrintProjectStructure(t *testing.T) {
// Test sorting by size (descending)
t.Run("SortBySizeDesc", func(t *testing.T) {
output := captureOutput(func() {
PrintProjectStructure(".", "", "", false, "text", "blue", "green", "red", []string{}, "size", "desc")
PrintProjectStructure(".", "", "", false, "text", "blue", "green", "red", []string{}, "size", "desc", false)
})

// Verify that the output is sorted by size in descending order
Expand All @@ -164,7 +164,7 @@ func TestPrintProjectStructure(t *testing.T) {
// Test sorting by time (ascending)
t.Run("SortByTimeAsc", func(t *testing.T) {
output := captureOutput(func() {
PrintProjectStructure(".", "", "", false, "text", "blue", "green", "red", []string{}, "time", "asc")
PrintProjectStructure(".", "", "", false, "text", "blue", "green", "red", []string{}, "time", "asc", false)
})

// Verify that the output is sorted by time in ascending order
Expand All @@ -175,13 +175,24 @@ func TestPrintProjectStructure(t *testing.T) {
// Test sorting by time (descending)
t.Run("SortByTimeDesc", func(t *testing.T) {
output := captureOutput(func() {
PrintProjectStructure(".", "", "", false, "text", "blue", "green", "red", []string{}, "time", "desc")
PrintProjectStructure(".", "", "", false, "text", "blue", "green", "red", []string{}, "time", "desc", false)
})

// Verify that the output is sorted by time in descending order
// You can add specific checks based on your expected output
t.Log(output)
})

// Test including hidden files
t.Run("IncludeHidden", func(t *testing.T) {
output := captureOutput(func() {
PrintProjectStructure(".", "", "", false, "text", "blue", "green", "red", []string{}, "name", "asc", true)
})

// Verify that the output includes the hidden files
// You can add specific checks based on your expected output
t.Log(output)
})
}

// createTestProjectStructure creates a sample project structure for testing.
Expand Down
Loading