diff --git a/.opencode/rules/golang-cli.md b/.opencode/rules/golang-cli.md deleted file mode 100644 index 5eceb65..0000000 --- a/.opencode/rules/golang-cli.md +++ /dev/null @@ -1,120 +0,0 @@ ---- -name: golang-cli -description: > - Guidance for building, extending, and reviewing this Go Cobra CLI. Use when - changing command wiring, flags, filesystem traversal, terminal rendering, - service-layer errors, or treels-style cmd/service/module/utils boundaries. ---- - -# Go CLI Development Rules - -These rules are tailored to `github.com/oussamaM1/treels`, a Go 1.24 Cobra CLI -that combines `tree` and `ls` behavior with colored and icon-aware terminal -output. - -## Architecture - -Keep the package boundaries simple: - -```text -main.go calls cmd.Execute() only -cmd/ Cobra command construction, args, flags, process exit -service/ directory validation, traversal, counting, rendering orchestration -module/ plain data types and constants -utils/ pure helpers shared by cmd/service -``` - -Rules: -- `main.go` stays tiny and only calls `cmd.Execute()`. -- `cmd/` may import `service`, `module`, and Cobra. -- `service/` may import `module` and `utils`; it must not import `cmd`. -- `module/` must not depend on `cmd` or `service`. -- Do not add package-level mutable command state unless there is a strong reason. - -## Cobra Commands - -Use a command factory so tests get isolated command instances: - -```go -func Execute() { - if err := newRootCmd().Execute(); err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(1) - } -} - -func newRootCmd() *cobra.Command { - var flags module.Flags - cmd := &cobra.Command{ - Use: "treels [path]", - Args: cobra.MaximumNArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - options := module.Options{Flags: flags} - if len(args) == 1 { - options.Directory = args[0] - } - return service.Dispatcher(options) - }, - } - FlagDefinition(cmd, &flags) - cmd.SilenceUsage = true - return cmd -} -``` - -Rules: -- Use `RunE`, not `Run`, for commands that can fail. -- Register flags against the command instance passed to `FlagDefinition`. -- Keep filesystem validation in `service`, not `cmd`. -- Let `cmd.Execute()` be the only place that calls `os.Exit`. - -## Service Errors - -Service code must return errors instead of terminating the process. - -Rules: -- Never call `log.Fatal`, `panic`, or `os.Exit` from `service/`, `utils/`, or - `module/`. -- Validate and default the directory before printing any output. -- Wrap filesystem errors with the path involved, for example - `fmt.Errorf("read directory %q: %w", path, err)`. -- Close opened directories on both success and failure paths. -- Return partial tree/list output only when that behavior is intentional and - covered by tests. - -## Rendering - -Rendering should be testable without replacing global stdout. - -Rules: -- Public CLI entry points may write to `os.Stdout`. -- Internal service rendering helpers should accept an `io.Writer`. -- Tests should pass a `bytes.Buffer` and assert on stable substrings. -- Do not assert terminal width, ANSI color escapes, or Nerd Font glyphs unless - the test controls those conditions. - -## Filesystem Traversal - -Rules: -- Use `filepath.Join`, `filepath.Base`, and other path-aware stdlib helpers. -- Use `t.TempDir()` in tests; do not depend on the repository tree or `/tmp`. -- Hidden files are names whose first byte is `'.'`. -- Keep directory counting and file counting behavior explicit in tests whenever - changing traversal. - -## CI Contract - -Before considering CLI changes ready, run the same checks as `.github/workflows` -expects: - -```bash -go mod tidy -go mod verify -go vet ./... -go build ./... -go test ./... -``` - -Also run `go test -race ./...` locally for service or command changes. If -dependencies change, ensure `go mod tidy` leaves `go.mod` and `go.sum` in the -intended state. diff --git a/.opencode/rules/golang-unit-testing.md b/.opencode/rules/golang-unit-testing.md deleted file mode 100644 index cd3c8c9..0000000 --- a/.opencode/rules/golang-unit-testing.md +++ /dev/null @@ -1,123 +0,0 @@ ---- -name: golang-unit-testing -description: > - Guidance for deterministic Go tests in this repo. Use when adding or - reviewing tests for Cobra commands, filesystem traversal, service rendering, - utility validation, or CI behavior. ---- - -# Go Unit Testing Rules - -These rules target the `treels` codebase: Go 1.24, Cobra, and packages split -across `cmd`, `service`, `module`, and `utils`. - -## Test Placement - -Rules: -- Put tests beside the code under test. -- Prefer the same package when testing unexported helpers such as `newRootCmd`, - `dispatcher`, `isHidden`, or rendering helpers. -- Use black-box `package foo_test` only when intentionally testing the public API. - -## Table Tests - -Use named subtests for behavior matrices: - -```go -func TestIsHidden(t *testing.T) { - tests := []struct { - name string - input string - want bool - }{ - {name: "dot file", input: ".gitignore", want: true}, - {name: "regular file", input: "main.go", want: false}, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if got := isHidden(tt.input); got != tt.want { - t.Fatalf("isHidden(%q) = %v, want %v", tt.input, got, tt.want) - } - }) - } -} -``` - -Rules: -- Case names describe behavior, not case numbers. -- Use `t.Fatalf` when later assertions would be meaningless. -- Use `t.Errorf` when a subtest can report several independent mismatches. - -## Filesystem Tests - -Rules: -- Always use `t.TempDir()` for fixture roots. -- Create files and directories in-process with helpers that call `t.Helper()`. -- Do not rely on permissions tests unless they are skipped or guarded for root - and platform differences. -- Avoid tests that depend on the developer's current working directory. - -## Command Tests - -Rules: -- Test Cobra commands through `newRootCmd()` so flags and args are isolated per - test. -- Use `cmd.SetArgs(...)`; do not mutate `os.Args`. -- Cover invalid paths, too many args, and at least one successful flag path when - command behavior changes. -- Keep command tests focused on command wiring; service output details belong in - `service` tests. - -## Output Tests - -Rules: -- Prefer `io.Writer` injection and `bytes.Buffer` over replacing `os.Stdout`. -- Assert stable substrings such as file names, connectors, and summary counts. -- Do not assert exact spacing from grid output unless terminal width is - controlled by the test. -- Avoid assertions on ANSI colors or icons unless the test disables icons or - controls the rendering mode. - -## Error Tests - -Every changed error path should have a test. - -Cover: -- missing path -- path is a regular file -- too many CLI args -- read/open errors where deterministic -- no partial output before validation failures - -## CI Contract - -The GitHub workflows currently run: - -```bash -go mod tidy -go mod verify -go vet ./... -go build -v ./... -go test -v ./... -golangci-lint -``` - -Before finishing test work, run at least: - -```bash -go test ./... -go vet ./... -go test -race ./... -``` - -For code intended to merge, also run: - -```bash -go mod tidy -go mod verify -go build ./... -``` - -If `golangci-lint` is installed locally, run `golangci-lint run`; otherwise say -that local lint verification was not available. diff --git a/service/service_test.go b/service/service_test.go index fbcda11..2995193 100644 --- a/service/service_test.go +++ b/service/service_test.go @@ -6,6 +6,7 @@ import ( "path/filepath" "strings" "testing" + "time" "github.com/oussamaM1/treels/module" ) @@ -125,6 +126,92 @@ func TestHumanReadableSize(t *testing.T) { } } +func TestResolveFileIconStyle(t *testing.T) { + tests := []struct { + name string + fileName string + wantIcon string + wantColor string + }{ + { + name: "filename specific icon takes precedence", + fileName: "README.md", + wantIcon: module.ReadmeIcon, + wantColor: module.Cyan, + }, + { + name: "known extension is case insensitive", + fileName: "main.GO", + wantIcon: module.GoLangIcon, + wantColor: module.LightBlue, + }, + { + name: "multi-part config filename", + fileName: ".eslintrc.json", + wantIcon: module.ESLintIcon, + wantColor: module.Purple, + }, + { + name: "unknown extension falls back to file icon", + fileName: "archive.unknown", + wantIcon: module.FileIcon, + wantColor: "", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := resolveFileIconStyle(tt.fileName) + if got.icon != tt.wantIcon || got.color != tt.wantColor { + t.Fatalf("resolveFileIconStyle(%q) = %+v, want icon %q and color %q", tt.fileName, got, tt.wantIcon, tt.wantColor) + } + }) + } +} + +func TestResolveFolderIconStyle(t *testing.T) { + tests := []struct { + name string + folderName string + wantIcon string + wantColor string + }{ + { + name: "git folder", + folderName: ".git", + wantIcon: module.GitIcon, + wantColor: module.Orange, + }, + { + name: "default folder", + folderName: "pkg", + wantIcon: module.FolderIcon, + wantColor: module.Pink, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := resolveFolderIconStyle(tt.folderName) + if got.icon != tt.wantIcon || got.color != tt.wantColor { + t.Fatalf("resolveFolderIconStyle(%q) = %+v, want icon %q and color %q", tt.folderName, got, tt.wantIcon, tt.wantColor) + } + }) + } +} + +func TestFormatFileWithOptions_HideIcon(t *testing.T) { + file := fakeFileInfo{name: "main.go"} + + got := formatFileWithOptions("", file, module.Flags{HideIcon: true}) + if strings.Contains(got, module.GoLangIcon) { + t.Fatalf("formatFileWithOptions() = %q, want no file icon", got) + } + if got != "main.go" { + t.Fatalf("formatFileWithOptions() = %q, want plain file name", got) + } +} + func TestReadDirectory_FilePath(t *testing.T) { path := filepath.Join(t.TempDir(), "regular.txt") mustWriteFile(t, path, "content") @@ -174,3 +261,36 @@ func mustMkdir(t *testing.T, path string) { t.Fatalf("Mkdir(%q) error = %v", path, err) } } + +type fakeFileInfo struct { + name string + size int64 + isDir bool +} + +func (f fakeFileInfo) Name() string { + return f.name +} + +func (f fakeFileInfo) Size() int64 { + return f.size +} + +func (f fakeFileInfo) Mode() os.FileMode { + if f.isDir { + return os.ModeDir + } + return 0 +} + +func (f fakeFileInfo) ModTime() time.Time { + return time.Time{} +} + +func (f fakeFileInfo) IsDir() bool { + return f.isDir +} + +func (f fakeFileInfo) Sys() interface{} { + return nil +} diff --git a/service/util.go b/service/util.go index 3da5d3d..e5244f7 100644 --- a/service/util.go +++ b/service/util.go @@ -4,12 +4,13 @@ package service import ( "fmt" "io" - - "github.com/oussamaM1/treels/module" - "golang.org/x/term" "os" + "path/filepath" "sort" "strings" + + "github.com/oussamaM1/treels/module" + "golang.org/x/term" ) // Define constant for formatting @@ -18,6 +19,611 @@ const ( IconFolderFormat = "%s%s%s%s %s%s" ) +type iconStyle struct { + color string + icon string +} + +var defaultFileIconStyle = iconStyle{icon: module.FileIcon} + +var defaultFolderIconStyle = iconStyle{ + color: module.Pink, + icon: module.FolderIcon, +} + +var folderIconStyles = map[string]iconStyle{ + module.Github: { + color: module.Orange, + icon: module.GitIcon, + }, + module.GitFolder: { + color: module.Orange, + icon: module.GitIcon, + }, + module.IntellijFolder: { + color: module.LightBlue, + icon: module.IntellijIcon, + }, +} + +var filenameIconStyles = map[string]iconStyle{ + module.Readme: { + color: module.Cyan, + icon: module.ReadmeIcon, + }, + module.ReadmeMd: { + color: module.Cyan, + icon: module.ReadmeIcon, + }, + module.Gitignore: { + color: module.Orange, + icon: module.GitIcon, + }, + module.TsConfig: { + color: module.Blue, + icon: module.TypeScriptIcon, + }, + module.WebpackConfig: { + color: module.Blue, + icon: module.WebpackIcon, + }, + module.ViteConfig: { + color: module.Purple, + icon: module.ViteIcon, + }, + module.Requirements: { + color: module.Blue, + icon: module.PipIcon, + }, + module.CargoToml: { + color: module.Orange, + icon: module.CargoIcon, + }, + module.CargoLock: { + color: module.Orange, + icon: module.CargoIcon, + }, + module.Gemfile: { + color: module.Red, + icon: module.RubyIcon, + }, + module.Dockerfile: { + color: module.Cyan, + icon: module.DockerIcon, + }, + module.Pom: { + color: module.Red, + icon: module.MavenIcon, + }, + module.Makefile: { + color: module.Orange, + icon: module.MakefileIcon, + }, + module.CMakeLists: { + color: module.Red, + icon: module.CMakeIcon, + }, + module.PackageJSON: { + color: module.Red, + icon: module.NPMIcon, + }, + module.Jenkinsfile: { + color: module.Red, + icon: module.CIIcon, + }, + module.Vagrantfile: { + color: module.Blue, + icon: module.VagrantIcon, + }, + module.Procfile: { + color: module.Purple, + icon: module.CIIcon, + }, + module.License: { + color: module.Yellow, + icon: module.LicenseIcon, + }, + module.LicenseMd: { + color: module.Yellow, + icon: module.LicenseIcon, + }, +} + +var extensionIconStyles = map[string]iconStyle{ + module.Go: { + color: module.LightBlue, + icon: module.GoLangIcon, + }, + module.Mod: { + color: module.LightBlue, + icon: module.GoLangIcon, + }, + module.Sum: { + color: module.LightBlue, + icon: module.GoLangIcon, + }, + module.Md: { + color: module.Grey, + icon: module.MarkdownIcon, + }, + module.Yaml: { + color: module.LightGreen, + icon: module.YamlIcon, + }, + module.Yml: { + color: module.LightGreen, + icon: module.YamlIcon, + }, + module.YmlCI: { + color: module.LightGreen, + icon: module.YamlIcon, + }, + module.JSON: { + color: module.Yellow, + icon: module.JSONIcon, + }, + module.SQL: { + color: module.Red, + icon: module.DatabaseIcon, + }, + module.Pls: { + color: module.Red, + icon: module.DatabaseIcon, + }, + module.Plb: { + color: module.Red, + icon: module.DatabaseIcon, + }, + module.Psql: { + color: module.Red, + icon: module.DatabaseIcon, + }, + module.Sqlite: { + color: module.LightBlue, + icon: module.SQLiteIcon, + }, + module.Db: { + color: module.LightBlue, + icon: module.SQLiteIcon, + }, + module.Java: { + color: module.LightRed, + icon: module.JavaLangIcon, + }, + module.Class: { + color: module.LightRed, + icon: module.JavaLangIcon, + }, + module.Scala: { + color: module.Red, + icon: module.ScalaIcon, + }, + module.Cpp: { + color: module.LightBlue, + icon: module.CppLangIcon, + }, + module.C: { + color: module.LightBlue, + icon: module.CLangIcon, + }, + module.Js: { + color: module.LightYellow, + icon: module.JavascriptLangIcon, + }, + module.Jsx: { + color: module.Cyan, + icon: module.ReactIcon, + }, + module.Ts: { + color: module.Blue, + icon: module.TypeScriptIcon, + }, + module.Tsx: { + color: module.Blue, + icon: module.TypeScriptIcon, + }, + module.HTML: { + color: module.Orange, + icon: module.HTMLIcon, + }, + module.Htm: { + color: module.Orange, + icon: module.HTMLIcon, + }, + module.CSS: { + color: module.LightBlue, + icon: module.CSSIcon, + }, + module.Scss: { + color: module.LightBlue, + icon: module.CSSIcon, + }, + module.Sass: { + color: module.LightBlue, + icon: module.CSSIcon, + }, + module.Less: { + color: module.Blue, + icon: module.LessIcon, + }, + module.Vue: { + color: module.LightGreen, + icon: module.VueIcon, + }, + module.Svelte: { + color: module.Orange, + icon: module.SvelteIcon, + }, + module.Py: { + color: module.Blue, + icon: module.PythonLangIcon, + }, + module.Pyproject: { + color: module.Blue, + icon: module.PoetryIcon, + }, + module.PoetryLock: { + color: module.Blue, + icon: module.PoetryIcon, + }, + module.Rs: { + color: module.Orange, + icon: module.RustLangIcon, + }, + module.Rb: { + color: module.Red, + icon: module.RubyIcon, + }, + module.Rake: { + color: module.Red, + icon: module.RubyIcon, + }, + module.Php: { + color: module.Purple, + icon: module.PHPIcon, + }, + module.Swift: { + color: module.Orange, + icon: module.SwiftIcon, + }, + module.Kt: { + color: module.Purple, + icon: module.KotlinIcon, + }, + module.Kts: { + color: module.Purple, + icon: module.KotlinIcon, + }, + module.Cs: { + color: module.Green, + icon: module.CSharpIcon, + }, + module.Csx: { + color: module.Green, + icon: module.CSharpIcon, + }, + module.Dart: { + color: module.Cyan, + icon: module.DartIcon, + }, + module.Ex: { + color: module.Purple, + icon: module.ElixirIcon, + }, + module.Exs: { + color: module.Purple, + icon: module.ElixirIcon, + }, + module.Hs: { + color: module.Purple, + icon: module.HaskellIcon, + }, + module.Clj: { + color: module.Green, + icon: module.ClojureIcon, + }, + module.R: { + color: module.Blue, + icon: module.RIcon, + }, + module.Rmd: { + color: module.Blue, + icon: module.RIcon, + }, + module.Lua: { + color: module.Blue, + icon: module.LuaIcon, + }, + module.Pl: { + color: module.Blue, + icon: module.PerlIcon, + }, + module.Pm: { + color: module.Blue, + icon: module.PerlIcon, + }, + module.XML: { + color: module.Orange, + icon: module.XMLIcon, + }, + module.Graphql: { + color: module.Magenta, + icon: module.GraphQLIcon, + }, + module.Gql: { + color: module.Magenta, + icon: module.GraphQLIcon, + }, + module.Prisma: { + color: module.Blue, + icon: module.PrismaIcon, + }, + module.Proto: { + color: module.Blue, + icon: module.ProtoIcon, + }, + module.Wasm: { + color: module.Purple, + icon: module.WasmIcon, + }, + module.Sh: { + color: module.Green, + icon: module.ShellIcon, + }, + module.Bash: { + color: module.Green, + icon: module.ShellIcon, + }, + module.Zsh: { + color: module.Green, + icon: module.ShellIcon, + }, + module.Dockerignore: { + color: module.Cyan, + icon: module.DockerIcon, + }, + module.Conf: { + color: module.Grey, + icon: module.ConfigIcon, + }, + module.Cfg: { + color: module.Grey, + icon: module.ConfigIcon, + }, + module.Ini: { + color: module.Grey, + icon: module.ConfigIcon, + }, + module.Env: { + color: module.Grey, + icon: module.ConfigIcon, + }, + module.Toml: { + color: module.Grey, + icon: module.TomlIcon, + }, + module.Editorconfig: { + color: module.Grey, + icon: module.EditorConfigIcon, + }, + module.Eslintrc: { + color: module.Purple, + icon: module.ESLintIcon, + }, + module.EslintrcJSON: { + color: module.Purple, + icon: module.ESLintIcon, + }, + module.Prettierrc: { + color: module.Grey, + icon: module.PrettierIcon, + }, + module.Prettierignore: { + color: module.Grey, + icon: module.PrettierIcon, + }, + module.Babelrc: { + color: module.Yellow, + icon: module.BabelIcon, + }, + module.Make: { + color: module.Orange, + icon: module.MakefileIcon, + }, + module.Cmake: { + color: module.Red, + icon: module.CMakeIcon, + }, + module.Gradle: { + color: module.Green, + icon: module.GradleIcon, + }, + module.GradleKts: { + color: module.Green, + icon: module.GradleIcon, + }, + module.Tf: { + color: module.Purple, + icon: module.TerraformIcon, + }, + module.Tfvars: { + color: module.Purple, + icon: module.TerraformIcon, + }, + module.Nix: { + color: module.Blue, + icon: module.NixIcon, + }, + module.Png: { + color: module.Magenta, + icon: module.ImageIcon, + }, + module.Jpg: { + color: module.Magenta, + icon: module.ImageIcon, + }, + module.Jpeg: { + color: module.Magenta, + icon: module.ImageIcon, + }, + module.Gif: { + color: module.Magenta, + icon: module.ImageIcon, + }, + module.Svg: { + color: module.Magenta, + icon: module.ImageIcon, + }, + module.Ico: { + color: module.Magenta, + icon: module.ImageIcon, + }, + module.Mp4: { + color: module.Purple, + icon: module.VideoIcon, + }, + module.Avi: { + color: module.Purple, + icon: module.VideoIcon, + }, + module.Mov: { + color: module.Purple, + icon: module.VideoIcon, + }, + module.Mkv: { + color: module.Purple, + icon: module.VideoIcon, + }, + module.Mp3: { + color: module.Cyan, + icon: module.AudioIcon, + }, + module.Wav: { + color: module.Cyan, + icon: module.AudioIcon, + }, + module.Flac: { + color: module.Cyan, + icon: module.AudioIcon, + }, + module.Zip: { + color: module.Yellow, + icon: module.ArchiveIcon, + }, + module.Tar: { + color: module.Yellow, + icon: module.ArchiveIcon, + }, + module.Gz: { + color: module.Yellow, + icon: module.ArchiveIcon, + }, + module.Rar: { + color: module.Yellow, + icon: module.ArchiveIcon, + }, + module.SevenZ: { + color: module.Yellow, + icon: module.ArchiveIcon, + }, + module.Pdf: { + color: module.Red, + icon: module.PDFIcon, + }, + module.Doc: { + color: module.Blue, + icon: module.WordIcon, + }, + module.Docx: { + color: module.Blue, + icon: module.WordIcon, + }, + module.Xls: { + color: module.Green, + icon: module.ExcelIcon, + }, + module.Xlsx: { + color: module.Green, + icon: module.ExcelIcon, + }, + module.Ppt: { + color: module.Orange, + icon: module.PowerPointIcon, + }, + module.Pptx: { + color: module.Orange, + icon: module.PowerPointIcon, + }, + module.Ttf: { + color: module.Grey, + icon: module.FontIcon, + }, + module.Otf: { + color: module.Grey, + icon: module.FontIcon, + }, + module.Woff: { + color: module.Grey, + icon: module.FontIcon, + }, + module.Woff2: { + color: module.Grey, + icon: module.FontIcon, + }, + module.Exe: { + color: module.Red, + icon: module.BinaryIcon, + }, + module.Dll: { + color: module.Red, + icon: module.BinaryIcon, + }, + module.So: { + color: module.Red, + icon: module.BinaryIcon, + }, + module.Dylib: { + color: module.Red, + icon: module.BinaryIcon, + }, + module.Lock: { + color: module.Yellow, + icon: module.LockIcon, + }, + module.Key: { + color: module.Yellow, + icon: module.CertificateIcon, + }, + module.Pem: { + color: module.Yellow, + icon: module.CertificateIcon, + }, + module.Crt: { + color: module.Yellow, + icon: module.CertificateIcon, + }, + module.Pub: { + color: module.Yellow, + icon: module.CertificateIcon, + }, + module.Cer: { + color: module.Yellow, + icon: module.CertificateIcon, + }, + module.P12: { + color: module.Yellow, + icon: module.CertificateIcon, + }, + module.Log: { + color: module.Grey, + icon: module.LogIcon, + }, + module.Txt: { + color: module.Grey, + icon: module.TextIcon, + }, +} + // CheckDefaultDirectory func - returns current working directory if no directory is specified func CheckDefaultDirectory(directory *string) error { if *directory == "" { @@ -71,363 +677,58 @@ func isHidden(name string) bool { // printWithIconAndPrefix func - prints files and folder with icons and prefix func printWithIconAndPrefix(prefix string, file os.FileInfo) string { - var format string - // Directory icon logic if file.IsDir() { - switch { - case strings.HasSuffix(file.Name(), module.Github), strings.HasSuffix(file.Name(), module.GitFolder): - format = printIconFolders(prefix, file, module.GitFolder) - case strings.HasSuffix(file.Name(), module.IntellijFolder): - format = printIconFolders(prefix, file, module.IntellijFolder) - default: - format = printIconFolders(prefix, file, module.FolderIcon) - } - return format + return formatFolderWithIcon(prefix, file.Name()) } - // File icon logic - switch { - case strings.HasSuffix(file.Name(), module.Go), strings.HasSuffix(file.Name(), module.Mod), strings.HasSuffix(file.Name(), module.Sum): - format = printIconFiles(prefix, file, module.Go) - case strings.HasSuffix(file.Name(), module.Md): - format = printIconFiles(prefix, file, module.Md) - case file.Name() == module.Readme, file.Name() == module.ReadmeMd: - format = printIconFiles(prefix, file, module.Readme) - case strings.HasSuffix(file.Name(), module.Gitignore): - format = printIconFiles(prefix, file, module.Gitignore) - case strings.HasSuffix(file.Name(), module.Yaml), strings.HasSuffix(file.Name(), module.Yml), strings.HasSuffix(file.Name(), module.YmlCI): - format = printIconFiles(prefix, file, module.Yml) - case strings.HasSuffix(file.Name(), module.JSON): - format = printIconFiles(prefix, file, module.JSON) - case file.Name() == module.TsConfig: - format = printIconFiles(prefix, file, module.TsConfig) - case strings.HasSuffix(file.Name(), module.SQL), strings.HasSuffix(file.Name(), module.Pls), strings.HasSuffix(file.Name(), module.Plb), strings.HasSuffix(file.Name(), module.Psql): - format = printIconFiles(prefix, file, module.SQL) - case strings.HasSuffix(file.Name(), module.Sqlite), strings.HasSuffix(file.Name(), module.Db): - format = printIconFiles(prefix, file, module.Sqlite) - case strings.HasSuffix(file.Name(), module.Java), strings.HasSuffix(file.Name(), module.Class): - format = printIconFiles(prefix, file, module.Java) - case strings.HasSuffix(file.Name(), module.Scala): - format = printIconFiles(prefix, file, module.Scala) - case strings.HasSuffix(file.Name(), module.Cpp): - format = printIconFiles(prefix, file, module.Cpp) - case strings.HasSuffix(file.Name(), module.C): - format = printIconFiles(prefix, file, module.C) - case strings.HasSuffix(file.Name(), module.Js): - format = printIconFiles(prefix, file, module.Js) - case file.Name() == module.WebpackConfig: - format = printIconFiles(prefix, file, module.WebpackConfig) - case file.Name() == module.ViteConfig: - format = printIconFiles(prefix, file, module.ViteConfig) - case strings.HasSuffix(file.Name(), module.Jsx): - format = printIconFiles(prefix, file, module.Jsx) - case strings.HasSuffix(file.Name(), module.Ts), strings.HasSuffix(file.Name(), module.Tsx): - format = printIconFiles(prefix, file, module.Ts) - case strings.HasSuffix(file.Name(), module.HTML), strings.HasSuffix(file.Name(), module.Htm): - format = printIconFiles(prefix, file, module.HTML) - case strings.HasSuffix(file.Name(), module.CSS), strings.HasSuffix(file.Name(), module.Scss), strings.HasSuffix(file.Name(), module.Sass): - format = printIconFiles(prefix, file, module.CSS) - case strings.HasSuffix(file.Name(), module.Less): - format = printIconFiles(prefix, file, module.Less) - case strings.HasSuffix(file.Name(), module.Vue): - format = printIconFiles(prefix, file, module.Vue) - case strings.HasSuffix(file.Name(), module.Svelte): - format = printIconFiles(prefix, file, module.Svelte) - case strings.HasSuffix(file.Name(), module.Py): - format = printIconFiles(prefix, file, module.Py) - case file.Name() == module.Requirements: - format = printIconFiles(prefix, file, module.Requirements) - case strings.HasSuffix(file.Name(), module.Pyproject), strings.HasSuffix(file.Name(), module.PoetryLock): - format = printIconFiles(prefix, file, module.Pyproject) - case strings.HasSuffix(file.Name(), module.Rs): - format = printIconFiles(prefix, file, module.Rs) - case file.Name() == module.CargoToml, file.Name() == module.CargoLock: - format = printIconFiles(prefix, file, module.CargoToml) - case strings.HasSuffix(file.Name(), module.Rb), strings.HasSuffix(file.Name(), module.Rake), file.Name() == module.Gemfile: - format = printIconFiles(prefix, file, module.Rb) - case strings.HasSuffix(file.Name(), module.Php): - format = printIconFiles(prefix, file, module.Php) - case strings.HasSuffix(file.Name(), module.Swift): - format = printIconFiles(prefix, file, module.Swift) - case strings.HasSuffix(file.Name(), module.Kt), strings.HasSuffix(file.Name(), module.Kts): - format = printIconFiles(prefix, file, module.Kt) - case strings.HasSuffix(file.Name(), module.Cs), strings.HasSuffix(file.Name(), module.Csx): - format = printIconFiles(prefix, file, module.Cs) - case strings.HasSuffix(file.Name(), module.Dart): - format = printIconFiles(prefix, file, module.Dart) - case strings.HasSuffix(file.Name(), module.Ex), strings.HasSuffix(file.Name(), module.Exs): - format = printIconFiles(prefix, file, module.Ex) - case strings.HasSuffix(file.Name(), module.Hs): - format = printIconFiles(prefix, file, module.Hs) - case strings.HasSuffix(file.Name(), module.Clj): - format = printIconFiles(prefix, file, module.Clj) - case strings.HasSuffix(file.Name(), module.R), strings.HasSuffix(file.Name(), module.Rmd): - format = printIconFiles(prefix, file, module.R) - case strings.HasSuffix(file.Name(), module.Lua): - format = printIconFiles(prefix, file, module.Lua) - case strings.HasSuffix(file.Name(), module.Pl), strings.HasSuffix(file.Name(), module.Pm): - format = printIconFiles(prefix, file, module.Pl) - case strings.HasSuffix(file.Name(), module.XML): - format = printIconFiles(prefix, file, module.XML) - case file.Name() == module.Pom: - format = printIconFiles(prefix, file, module.Pom) - case strings.HasSuffix(file.Name(), module.Graphql), strings.HasSuffix(file.Name(), module.Gql): - format = printIconFiles(prefix, file, module.Graphql) - case strings.HasSuffix(file.Name(), module.Prisma): - format = printIconFiles(prefix, file, module.Prisma) - case strings.HasSuffix(file.Name(), module.Proto): - format = printIconFiles(prefix, file, module.Proto) - case strings.HasSuffix(file.Name(), module.Wasm): - format = printIconFiles(prefix, file, module.Wasm) - case strings.HasSuffix(file.Name(), module.Sh), strings.HasSuffix(file.Name(), module.Bash), strings.HasSuffix(file.Name(), module.Zsh): - format = printIconFiles(prefix, file, module.Sh) - case file.Name() == module.Dockerfile, strings.HasSuffix(file.Name(), module.Dockerignore): - format = printIconFiles(prefix, file, module.Dockerfile) - case strings.HasSuffix(file.Name(), module.Conf), strings.HasSuffix(file.Name(), module.Cfg), strings.HasSuffix(file.Name(), module.Ini), strings.HasSuffix(file.Name(), module.Env): - format = printIconFiles(prefix, file, module.Conf) - case strings.HasSuffix(file.Name(), module.Toml): - format = printIconFiles(prefix, file, module.Toml) - case strings.HasSuffix(file.Name(), module.Editorconfig): - format = printIconFiles(prefix, file, module.Editorconfig) - case strings.HasSuffix(file.Name(), module.Eslintrc), strings.HasSuffix(file.Name(), module.EslintrcJSON): - format = printIconFiles(prefix, file, module.Eslintrc) - case strings.HasSuffix(file.Name(), module.Prettierrc), strings.HasSuffix(file.Name(), module.Prettierignore): - format = printIconFiles(prefix, file, module.Prettierrc) - case strings.HasSuffix(file.Name(), module.Babelrc): - format = printIconFiles(prefix, file, module.Babelrc) - case file.Name() == module.Makefile, strings.HasSuffix(file.Name(), module.Make): - format = printIconFiles(prefix, file, module.Makefile) - case file.Name() == module.CMakeLists, strings.HasSuffix(file.Name(), module.Cmake): - format = printIconFiles(prefix, file, module.CMakeLists) - case file.Name() == module.PackageJSON: - format = printIconFiles(prefix, file, module.PackageJSON) - case strings.HasSuffix(file.Name(), module.Gradle), strings.HasSuffix(file.Name(), module.GradleKts): - format = printIconFiles(prefix, file, module.Gradle) - case file.Name() == module.Jenkinsfile: - format = printIconFiles(prefix, file, module.Jenkinsfile) - case file.Name() == module.Vagrantfile: - format = printIconFiles(prefix, file, module.Vagrantfile) - case file.Name() == module.Procfile: - format = printIconFiles(prefix, file, module.Procfile) - case strings.HasSuffix(file.Name(), module.Tf), strings.HasSuffix(file.Name(), module.Tfvars): - format = printIconFiles(prefix, file, module.Tf) - case strings.HasSuffix(file.Name(), module.Nix): - format = printIconFiles(prefix, file, module.Nix) - case strings.HasSuffix(file.Name(), module.Png), strings.HasSuffix(file.Name(), module.Jpg), strings.HasSuffix(file.Name(), module.Jpeg), strings.HasSuffix(file.Name(), module.Gif), strings.HasSuffix(file.Name(), module.Svg), strings.HasSuffix(file.Name(), module.Ico): - format = printIconFiles(prefix, file, module.Png) - case strings.HasSuffix(file.Name(), module.Mp4), strings.HasSuffix(file.Name(), module.Avi), strings.HasSuffix(file.Name(), module.Mov), strings.HasSuffix(file.Name(), module.Mkv): - format = printIconFiles(prefix, file, module.Mp4) - case strings.HasSuffix(file.Name(), module.Mp3), strings.HasSuffix(file.Name(), module.Wav), strings.HasSuffix(file.Name(), module.Flac): - format = printIconFiles(prefix, file, module.Mp3) - case strings.HasSuffix(file.Name(), module.Zip), strings.HasSuffix(file.Name(), module.Tar), strings.HasSuffix(file.Name(), module.Gz), strings.HasSuffix(file.Name(), module.Rar), strings.HasSuffix(file.Name(), module.SevenZ): - format = printIconFiles(prefix, file, module.Zip) - case strings.HasSuffix(file.Name(), module.Pdf): - format = printIconFiles(prefix, file, module.Pdf) - case strings.HasSuffix(file.Name(), module.Doc), strings.HasSuffix(file.Name(), module.Docx): - format = printIconFiles(prefix, file, module.Doc) - case strings.HasSuffix(file.Name(), module.Xls), strings.HasSuffix(file.Name(), module.Xlsx): - format = printIconFiles(prefix, file, module.Xls) - case strings.HasSuffix(file.Name(), module.Ppt), strings.HasSuffix(file.Name(), module.Pptx): - format = printIconFiles(prefix, file, module.Ppt) - case strings.HasSuffix(file.Name(), module.Ttf), strings.HasSuffix(file.Name(), module.Otf), strings.HasSuffix(file.Name(), module.Woff), strings.HasSuffix(file.Name(), module.Woff2): - format = printIconFiles(prefix, file, module.Ttf) - case strings.HasSuffix(file.Name(), module.Exe), strings.HasSuffix(file.Name(), module.Dll), strings.HasSuffix(file.Name(), module.So), strings.HasSuffix(file.Name(), module.Dylib): - format = printIconFiles(prefix, file, module.Exe) - case file.Name() == module.License, file.Name() == module.LicenseMd: - format = printIconFiles(prefix, file, module.License) - case strings.HasSuffix(file.Name(), module.Lock): - format = printIconFiles(prefix, file, module.Lock) - case strings.HasSuffix(file.Name(), module.Key), strings.HasSuffix(file.Name(), module.Pem), strings.HasSuffix(file.Name(), module.Crt), strings.HasSuffix(file.Name(), module.Pub), strings.HasSuffix(file.Name(), module.Cer), strings.HasSuffix(file.Name(), module.P12): - format = printIconFiles(prefix, file, module.Key) - case strings.HasSuffix(file.Name(), module.Log): - format = printIconFiles(prefix, file, module.Log) - case strings.HasSuffix(file.Name(), module.Txt): - format = printIconFiles(prefix, file, module.Txt) - default: - // Default file icon - format = printIconFiles(prefix, file, module.FileIcon) + return formatFileWithIcon(prefix, file.Name()) +} + +func formatFileWithIcon(prefix, name string) string { + style := resolveFileIconStyle(name) + if style.color == "" { + return fmt.Sprintf("%s%s %s", prefix, style.icon, name) } - return format + return fmt.Sprintf(IconFileFormat, prefix, style.color, style.icon, module.Reset, name) } -// printIconFiles func - prints files with icons -func printIconFiles(prefix string, file os.FileInfo, extension string) string { - var format string - switch extension { - case module.Go, module.Mod, module.Sum: - format = fmt.Sprintf(IconFileFormat, prefix, module.LightBlue, module.GoLangIcon, module.Reset, file.Name()) - case module.Md: - format = fmt.Sprintf(IconFileFormat, prefix, module.Grey, module.MarkdownIcon, module.Reset, file.Name()) - case module.Readme, module.ReadmeMd: - format = fmt.Sprintf(IconFileFormat, prefix, module.Cyan, module.ReadmeIcon, module.Reset, file.Name()) - case module.Gitignore: - format = fmt.Sprintf(IconFileFormat, prefix, module.Orange, module.GitIcon, module.Reset, file.Name()) - case module.JSON: - format = fmt.Sprintf(IconFileFormat, prefix, module.Yellow, module.JSONIcon, module.Reset, file.Name()) - case module.TsConfig: - format = fmt.Sprintf(IconFileFormat, prefix, module.Blue, module.TypeScriptIcon, module.Reset, file.Name()) - case module.Yml, module.Yaml, module.YmlCI: - format = fmt.Sprintf(IconFileFormat, prefix, module.LightGreen, module.YamlIcon, module.Reset, file.Name()) - case module.Pls, module.Plb, module.SQL, module.Psql: - format = fmt.Sprintf(IconFileFormat, prefix, module.Red, module.DatabaseIcon, module.Reset, file.Name()) - case module.Sqlite, module.Db: - format = fmt.Sprintf(IconFileFormat, prefix, module.LightBlue, module.SQLiteIcon, module.Reset, file.Name()) - case module.Java, module.Class: - format = fmt.Sprintf(IconFileFormat, prefix, module.LightRed, module.JavaLangIcon, module.Reset, file.Name()) - case module.Scala: - format = fmt.Sprintf(IconFileFormat, prefix, module.Red, module.ScalaIcon, module.Reset, file.Name()) - case module.Cpp: - format = fmt.Sprintf(IconFileFormat, prefix, module.LightBlue, module.CppLangIcon, module.Reset, file.Name()) - case module.C: - format = fmt.Sprintf(IconFileFormat, prefix, module.LightBlue, module.CLangIcon, module.Reset, file.Name()) - case module.Js: - format = fmt.Sprintf(IconFileFormat, prefix, module.LightYellow, module.JavascriptLangIcon, module.Reset, file.Name()) - case module.WebpackConfig: - format = fmt.Sprintf(IconFileFormat, prefix, module.Blue, module.WebpackIcon, module.Reset, file.Name()) - case module.ViteConfig: - format = fmt.Sprintf(IconFileFormat, prefix, module.Purple, module.ViteIcon, module.Reset, file.Name()) - case module.Rs: - format = fmt.Sprintf(IconFileFormat, prefix, module.Orange, module.RustLangIcon, module.Reset, file.Name()) - case module.CargoToml, module.CargoLock: - format = fmt.Sprintf(IconFileFormat, prefix, module.Orange, module.CargoIcon, module.Reset, file.Name()) - case module.Py: - format = fmt.Sprintf(IconFileFormat, prefix, module.Blue, module.PythonLangIcon, module.Reset, file.Name()) - case module.Requirements: - format = fmt.Sprintf(IconFileFormat, prefix, module.Blue, module.PipIcon, module.Reset, file.Name()) - case module.Pyproject, module.PoetryLock: - format = fmt.Sprintf(IconFileFormat, prefix, module.Blue, module.PoetryIcon, module.Reset, file.Name()) - case module.Ts, module.Tsx: - format = fmt.Sprintf(IconFileFormat, prefix, module.Blue, module.TypeScriptIcon, module.Reset, file.Name()) - case module.HTML, module.Htm: - format = fmt.Sprintf(IconFileFormat, prefix, module.Orange, module.HTMLIcon, module.Reset, file.Name()) - case module.CSS, module.Scss, module.Sass: - format = fmt.Sprintf(IconFileFormat, prefix, module.LightBlue, module.CSSIcon, module.Reset, file.Name()) - case module.Less: - format = fmt.Sprintf(IconFileFormat, prefix, module.Blue, module.LessIcon, module.Reset, file.Name()) - case module.Jsx: - format = fmt.Sprintf(IconFileFormat, prefix, module.Cyan, module.ReactIcon, module.Reset, file.Name()) - case module.Vue: - format = fmt.Sprintf(IconFileFormat, prefix, module.LightGreen, module.VueIcon, module.Reset, file.Name()) - case module.Svelte: - format = fmt.Sprintf(IconFileFormat, prefix, module.Orange, module.SvelteIcon, module.Reset, file.Name()) - case module.Dart: - format = fmt.Sprintf(IconFileFormat, prefix, module.Cyan, module.DartIcon, module.Reset, file.Name()) - case module.Ex, module.Exs: - format = fmt.Sprintf(IconFileFormat, prefix, module.Purple, module.ElixirIcon, module.Reset, file.Name()) - case module.Hs: - format = fmt.Sprintf(IconFileFormat, prefix, module.Purple, module.HaskellIcon, module.Reset, file.Name()) - case module.Clj: - format = fmt.Sprintf(IconFileFormat, prefix, module.Green, module.ClojureIcon, module.Reset, file.Name()) - case module.R, module.Rmd: - format = fmt.Sprintf(IconFileFormat, prefix, module.Blue, module.RIcon, module.Reset, file.Name()) - case module.Lua: - format = fmt.Sprintf(IconFileFormat, prefix, module.Blue, module.LuaIcon, module.Reset, file.Name()) - case module.Pl, module.Pm: - format = fmt.Sprintf(IconFileFormat, prefix, module.Blue, module.PerlIcon, module.Reset, file.Name()) - case module.Dockerfile, module.Dockerignore: - format = fmt.Sprintf(IconFileFormat, prefix, module.Cyan, module.DockerIcon, module.Reset, file.Name()) - case module.Sh, module.Bash, module.Zsh: - format = fmt.Sprintf(IconFileFormat, prefix, module.Green, module.ShellIcon, module.Reset, file.Name()) - case module.Rb, module.Rake, module.Gemfile: - format = fmt.Sprintf(IconFileFormat, prefix, module.Red, module.RubyIcon, module.Reset, file.Name()) - case module.Php: - format = fmt.Sprintf(IconFileFormat, prefix, module.Purple, module.PHPIcon, module.Reset, file.Name()) - case module.Swift: - format = fmt.Sprintf(IconFileFormat, prefix, module.Orange, module.SwiftIcon, module.Reset, file.Name()) - case module.Kt, module.Kts: - format = fmt.Sprintf(IconFileFormat, prefix, module.Purple, module.KotlinIcon, module.Reset, file.Name()) - case module.Cs, module.Csx: - format = fmt.Sprintf(IconFileFormat, prefix, module.Green, module.CSharpIcon, module.Reset, file.Name()) - case module.XML: - format = fmt.Sprintf(IconFileFormat, prefix, module.Orange, module.XMLIcon, module.Reset, file.Name()) - case module.Pom: - format = fmt.Sprintf(IconFileFormat, prefix, module.Red, module.MavenIcon, module.Reset, file.Name()) - case module.Graphql, module.Gql: - format = fmt.Sprintf(IconFileFormat, prefix, module.Magenta, module.GraphQLIcon, module.Reset, file.Name()) - case module.Prisma: - format = fmt.Sprintf(IconFileFormat, prefix, module.Blue, module.PrismaIcon, module.Reset, file.Name()) - case module.Proto: - format = fmt.Sprintf(IconFileFormat, prefix, module.Blue, module.ProtoIcon, module.Reset, file.Name()) - case module.Wasm: - format = fmt.Sprintf(IconFileFormat, prefix, module.Purple, module.WasmIcon, module.Reset, file.Name()) - case module.Pdf: - format = fmt.Sprintf(IconFileFormat, prefix, module.Red, module.PDFIcon, module.Reset, file.Name()) - case module.Doc, module.Docx: - format = fmt.Sprintf(IconFileFormat, prefix, module.Blue, module.WordIcon, module.Reset, file.Name()) - case module.Xls, module.Xlsx: - format = fmt.Sprintf(IconFileFormat, prefix, module.Green, module.ExcelIcon, module.Reset, file.Name()) - case module.Ppt, module.Pptx: - format = fmt.Sprintf(IconFileFormat, prefix, module.Orange, module.PowerPointIcon, module.Reset, file.Name()) - case module.Ttf, module.Otf, module.Woff, module.Woff2: - format = fmt.Sprintf(IconFileFormat, prefix, module.Grey, module.FontIcon, module.Reset, file.Name()) - case module.Exe, module.Dll, module.So, module.Dylib: - format = fmt.Sprintf(IconFileFormat, prefix, module.Red, module.BinaryIcon, module.Reset, file.Name()) - case module.Png, module.Jpg, module.Jpeg, module.Gif, module.Svg, module.Ico: - format = fmt.Sprintf(IconFileFormat, prefix, module.Magenta, module.ImageIcon, module.Reset, file.Name()) - case module.Mp4, module.Avi, module.Mov, module.Mkv: - format = fmt.Sprintf(IconFileFormat, prefix, module.Purple, module.VideoIcon, module.Reset, file.Name()) - case module.Mp3, module.Wav, module.Flac: - format = fmt.Sprintf(IconFileFormat, prefix, module.Cyan, module.AudioIcon, module.Reset, file.Name()) - case module.Zip, module.Tar, module.Gz, module.Rar, module.SevenZ: - format = fmt.Sprintf(IconFileFormat, prefix, module.Yellow, module.ArchiveIcon, module.Reset, file.Name()) - case module.Txt: - format = fmt.Sprintf(IconFileFormat, prefix, module.Grey, module.TextIcon, module.Reset, file.Name()) - case module.Conf, module.Cfg, module.Ini, module.Env: - format = fmt.Sprintf(IconFileFormat, prefix, module.Grey, module.ConfigIcon, module.Reset, file.Name()) - case module.Toml: - format = fmt.Sprintf(IconFileFormat, prefix, module.Grey, module.TomlIcon, module.Reset, file.Name()) - case module.Editorconfig: - format = fmt.Sprintf(IconFileFormat, prefix, module.Grey, module.EditorConfigIcon, module.Reset, file.Name()) - case module.Eslintrc, module.EslintrcJSON: - format = fmt.Sprintf(IconFileFormat, prefix, module.Purple, module.ESLintIcon, module.Reset, file.Name()) - case module.Prettierrc, module.Prettierignore: - format = fmt.Sprintf(IconFileFormat, prefix, module.Grey, module.PrettierIcon, module.Reset, file.Name()) - case module.Babelrc: - format = fmt.Sprintf(IconFileFormat, prefix, module.Yellow, module.BabelIcon, module.Reset, file.Name()) - case module.License, module.LicenseMd: - format = fmt.Sprintf(IconFileFormat, prefix, module.Yellow, module.LicenseIcon, module.Reset, file.Name()) - case module.Lock: - format = fmt.Sprintf(IconFileFormat, prefix, module.Yellow, module.LockIcon, module.Reset, file.Name()) - case module.Key, module.Pem, module.Crt, module.Pub, module.Cer, module.P12: - format = fmt.Sprintf(IconFileFormat, prefix, module.Yellow, module.CertificateIcon, module.Reset, file.Name()) - case module.Log: - format = fmt.Sprintf(IconFileFormat, prefix, module.Grey, module.LogIcon, module.Reset, file.Name()) - case module.Makefile, module.Make: - format = fmt.Sprintf(IconFileFormat, prefix, module.Orange, module.MakefileIcon, module.Reset, file.Name()) - case module.CMakeLists, module.Cmake: - format = fmt.Sprintf(IconFileFormat, prefix, module.Red, module.CMakeIcon, module.Reset, file.Name()) - case module.PackageJSON: - format = fmt.Sprintf(IconFileFormat, prefix, module.Red, module.NPMIcon, module.Reset, file.Name()) - case module.Gradle, module.GradleKts: - format = fmt.Sprintf(IconFileFormat, prefix, module.Green, module.GradleIcon, module.Reset, file.Name()) - case module.Jenkinsfile: - format = fmt.Sprintf(IconFileFormat, prefix, module.Red, module.CIIcon, module.Reset, file.Name()) - case module.Vagrantfile: - format = fmt.Sprintf(IconFileFormat, prefix, module.Blue, module.VagrantIcon, module.Reset, file.Name()) - case module.Procfile: - format = fmt.Sprintf(IconFileFormat, prefix, module.Purple, module.CIIcon, module.Reset, file.Name()) - case module.Tf, module.Tfvars: - format = fmt.Sprintf(IconFileFormat, prefix, module.Purple, module.TerraformIcon, module.Reset, file.Name()) - case module.Nix: - format = fmt.Sprintf(IconFileFormat, prefix, module.Blue, module.NixIcon, module.Reset, file.Name()) - default: - format = fmt.Sprintf("%s%s %s", prefix, module.FileIcon, file.Name()) +func formatFolderWithIcon(prefix, name string) string { + style := resolveFolderIconStyle(name) + return fmt.Sprintf(IconFolderFormat, prefix, module.Bold, style.color, style.icon, name, module.Reset) +} + +func resolveFileIconStyle(name string) iconStyle { + if style, ok := filenameIconStyles[name]; ok { + return style } - return format + + lowerName := strings.ToLower(name) + if style, ok := filenameIconStyles[lowerName]; ok { + return style + } + + if style, ok := extensionIconStyles[lowerName]; ok { + return style + } + + extension := strings.ToLower(filepath.Ext(name)) + if style, ok := extensionIconStyles[extension]; ok { + return style + } + + return defaultFileIconStyle } -// printIconFolders func - prints folders with icons -func printIconFolders(prefix string, file os.FileInfo, extension string) string { - var format string - switch extension { - case module.Github, module.GitFolder: - format = fmt.Sprintf(IconFolderFormat, prefix, module.Bold, module.Orange, module.GitIcon, file.Name(), module.Reset) - case module.IntellijFolder: - format = fmt.Sprintf(IconFolderFormat, prefix, module.Bold, module.LightBlue, module.IntellijIcon, file.Name(), module.Reset) - default: - format = fmt.Sprintf(IconFolderFormat, prefix, module.Bold, module.Pink, module.FolderIcon, file.Name(), module.Reset) +func resolveFolderIconStyle(name string) iconStyle { + if style, ok := folderIconStyles[name]; ok { + return style } - return format + + if style, ok := folderIconStyles[strings.ToLower(name)]; ok { + return style + } + + return defaultFolderIconStyle } // printFilesAndFolderWithoutIcons func - prints Files/Folder without icons