Skip to content

Commit

Permalink
Merge pull request #22 from OussamaM1/implement-tree-view-flag
Browse files Browse the repository at this point in the history
✨ Implemented option to display directory in a tree view
  • Loading branch information
OussamaM1 authored Apr 5, 2024
2 parents f5df9a4 + c130153 commit e54d099
Show file tree
Hide file tree
Showing 6 changed files with 159 additions and 64 deletions.
1 change: 1 addition & 0 deletions cmd/flag.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ import "github.com/oussamaM1/treels/module"
// FlagDefinition func - defines flags for the application.
func FlagDefinition(flags *module.Flags) {
RootCommand.PersistentFlags().BoolVarP(&flags.ShowHidden, "all", "a", false, "List all files and directories")
RootCommand.PersistentFlags().BoolVarP(&flags.ShowTreeView, "tree", "t", false, "Tree view of the directory")
}
4 changes: 2 additions & 2 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ func Execute() {

func run(_ *cobra.Command, args []string) {
if utils.ValidateDirectoryArgs(args) {
service.ListDirectory(service.Options{Directory: args[len(args)-1], Flags: flag})
service.Dispatcher(module.Options{Directory: args[len(args)-1], Flags: flag})
} else if len(args) == 0 {
service.ListDirectory(service.Options{Flags: flag})
service.Dispatcher(module.Options{Flags: flag})
} else {
fmt.Println("❌ Usage: treels [options] <directory_path>")
}
Expand Down
9 changes: 8 additions & 1 deletion module/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,12 @@ package module

// Flags struct - represents flags for the application.
type Flags struct {
ShowHidden bool
ShowHidden bool
ShowTreeView bool
}

// Options struct - Contains configuration options for directory listing.
type Options struct {
Directory string
Flags Flags
}
61 changes: 0 additions & 61 deletions service/ls.go

This file was deleted.

100 changes: 100 additions & 0 deletions service/service.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
// Package service provides functionalities related to directory listing.
package service

import (
"fmt"
"log"
"os"
"path/filepath"
"sort"

"github.com/oussamaM1/treels/module"
)

const (
whiteSpaces = " " // Whitespaces
boxUpAndRight = "└── " // BOX DRAWINGS HEAVY UP AND RIGHT
boxLightVertical = "│ " // BOX DRAWINGS LIGHT VERTICAL
boxLightVerticalAndRight = "├── " // BOX DRAWINGS LIGHT VERTICAL AND RIGHT
)

// Dispatcher func - executes function based on flags
func Dispatcher(options module.Options) {
if options.Flags.ShowTreeView {
TreeDirectory(options, "", true)
} else {
ListDirectory(options)
}
}

// ListDirectory func - lists the content of the directory.
func ListDirectory(options module.Options) {
CheckDefaultDirectory(&options.Directory)

// Open and read the directory
files, d, err := readDirectory(options.Directory)
defer closeDirectory(d)
if err != nil {
log.Fatalf("Error reading directory: %s\n", err)
}

// Print files and directories
fmt.Printf("Files and directories in %s:\n", options.Directory)
for _, file := range files {
if !isHidden(file.Name()) || options.Flags.ShowHidden {
fmt.Println(file.Name())
}
}
}

// TreeDirectory func - displays a tree view of the directory.
func TreeDirectory(options module.Options, indent string, isLastFolder bool) {
CheckDefaultDirectory(&options.Directory)

// Open and read the directory
files, d, err := readDirectory(options.Directory)
defer closeDirectory(d)
if err != nil {
log.Fatalf("Error reading directory: %s\n", err)
}

// Sort files by name
sort.Slice(files, func(i, j int) bool {
return files[i].Name() < files[j].Name()
})

// Print files and directories
lastVisibleIndex := getLastVisibleIndex(files, options.Flags.ShowHidden)
for i, file := range files {
if !isHidden(file.Name()) || options.Flags.ShowHidden {
var prefix, childIndentNext string
if i == lastVisibleIndex && isLastFolder {
prefix = indent + boxUpAndRight
childIndentNext = indent + whiteSpaces
} else if i == lastVisibleIndex {
prefix = indent + boxUpAndRight
childIndentNext = indent + whiteSpaces
} else {
prefix = indent + boxLightVerticalAndRight
childIndentNext = indent + boxLightVertical
}

fmt.Println(prefix + file.Name())

if file.IsDir() {
newDirectory := filepath.Join(options.Directory, file.Name())
newIsLastFolder := i == lastVisibleIndex && isLastFolder
TreeDirectory(module.Options{Directory: newDirectory, Flags: module.Flags{ShowHidden: options.Flags.ShowHidden}}, childIndentNext, newIsLastFolder)
}
}
}
}

func getLastVisibleIndex(files []os.FileInfo, showHidden bool) int {
for i := len(files) - 1; i >= 0; i-- {
if !isHidden(files[i].Name()) || showHidden {
return i
}
}
return -1
}
48 changes: 48 additions & 0 deletions service/util.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// Package service - service/util.go
package service

import (
"log"
"os"
)

// CheckDefaultDirectory func - returns current working directory if no directory is specified
func CheckDefaultDirectory(directory *string) {
if *directory == "" {
// Get the current working directory - default value
var err error
*directory, err = os.Getwd()
log.Println(*directory)
if err != nil {
log.Fatalf("Error getting current working directory: %s\n", err)
}
}
}

// readDirectory func - opens and reads the directory.
func readDirectory(directory string) ([]os.FileInfo, *os.File, error) {
// Open the directory
d, err := os.Open(directory)
if err != nil {
return nil, nil, err
}
// Read the directory contents
files, err := d.Readdir(-1)
if err != nil {
return nil, nil, err
}
return files, d, nil
}

// closeDirectory func - closes the directory.
func closeDirectory(directory *os.File) {
err := directory.Close()
if err != nil {
log.Fatalf("Error while closing directory: %s\n", err)
}
}

// isHidden func - checks if the file name starts with a dot (hidden file).
func isHidden(name string) bool {
return len(name) > 0 && name[0] == '.'
}

0 comments on commit e54d099

Please sign in to comment.