Skip to content

Commit

Permalink
Merge pull request #13 from zyadtaha/add-hidden-flag
Browse files Browse the repository at this point in the history
Add option to include hidden files and directories
  • Loading branch information
Ahmedhossamdev authored Jan 25, 2025
2 parents 9733ea3 + 164f593 commit 1058c86
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 25 deletions.
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

0 comments on commit 1058c86

Please sign in to comment.