├── .gitignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── arguments.go ├── colors.go ├── compile ├── example ├── .dockerignore ├── .eslintrc.cjs ├── .eslintrc.js ├── .mongorc.js ├── Cargo.lock ├── Cargo.toml ├── Dockerfile ├── a.js ├── bar.txt ├── deploy ├── fd0 ├── foo.txt ├── go.mod ├── go.sum ├── package.json ├── scripts ├── src │ ├── .npmignore │ ├── Brewfile │ ├── Jenkinsfile │ ├── Justfile │ ├── MAINTAINERS │ ├── Makefile │ ├── Vagrantfile │ ├── foo.ai │ ├── foo.apk │ ├── foo.as │ ├── foo.asm │ ├── foo.avro │ ├── foo.bf │ ├── foo.bson │ ├── foo.bzl │ ├── foo.c │ ├── foo.cfg │ ├── foo.clj │ ├── foo.coffee │ ├── foo.conf │ ├── foo.cpp │ ├── foo.cr │ ├── foo.crt │ ├── foo.cs │ ├── foo.cson │ ├── foo.css │ ├── foo.d │ ├── foo.dart │ ├── foo.db │ ├── foo.diff │ ├── foo.doc │ ├── foo.dockerfile │ ├── foo.dpkg │ ├── foo.elm │ ├── foo.env │ ├── foo.epub │ ├── foo.erl │ ├── foo.ex │ ├── foo.f │ ├── foo.flac │ ├── foo.fs │ ├── foo.gb │ ├── foo.gform │ ├── foo.gleam │ ├── foo.go │ ├── foo.graphql │ ├── foo.groovy │ ├── foo.gv │ ├── foo.h │ ├── foo.hs │ ├── foo.html │ ├── foo.hx │ ├── foo.ics │ ├── foo.iml │ ├── foo.ini │ ├── foo.ino │ ├── foo.ipsw │ ├── foo.iso │ ├── foo.java │ ├── foo.jl │ ├── foo.jpg │ ├── foo.js │ ├── foo.json │ ├── foo.jsx │ ├── foo.ko │ ├── foo.kt │ ├── foo.less │ ├── foo.lock │ ├── foo.log │ ├── foo.lua │ ├── foo.m │ ├── foo.md │ ├── foo.mjs │ ├── foo.ml │ ├── foo.mp4 │ ├── foo.mustache │ ├── foo.nc │ ├── foo.nim │ ├── foo.otf │ ├── foo.patch │ ├── foo.pdf │ ├── foo.php │ ├── foo.pl │ ├── foo.ppt │ ├── foo.prisma │ ├── foo.ps1 │ ├── foo.psd │ ├── foo.py │ ├── foo.r │ ├── foo.rb │ ├── foo.rdb │ ├── foo.rpm │ ├── foo.rs │ ├── foo.rss │ ├── foo.rst │ ├── foo.rubydoc │ ├── foo.sass │ ├── foo.scala │ ├── foo.sh │ ├── foo.sixel │ ├── foo.sol │ ├── foo.sql │ ├── foo.sqlite │ ├── foo.sqlite3 │ ├── foo.styl │ ├── foo.svelte │ ├── foo.svg │ ├── foo.swift │ ├── foo.tex │ ├── foo.tf │ ├── foo.tfrecord │ ├── foo.toml │ ├── foo.ts │ ├── foo.twig │ ├── foo.txt │ ├── foo.vim │ ├── foo.vue │ ├── foo.windows │ ├── foo.xls │ ├── foo.xml │ ├── foo.yaml │ ├── foo.zig │ ├── foo.zip │ ├── gruntfile.js │ ├── gulpfile.js │ └── passwd ├── thing.conf ├── vite.config.js └── z.js ├── file-icons.go ├── go.mod ├── go.sum ├── img ├── demo-1.png ├── demo-2.png ├── demo-3.png ├── demo-4.png ├── ls-go.png └── warp-logo.png ├── ls-go.go ├── ls-unix.go ├── ls-windows.go ├── release.sh ├── snap └── snapcraft.yaml ├── sort.go └── test /.gitignore: -------------------------------------------------------------------------------- 1 | .foo* 2 | .perm/ 3 | ls-go 4 | ls-go-* 5 | ls-go_* 6 | *.swp 7 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ### 2020-05-29 2 | - Make some dark colors easier to see. 3 | - Symlink paths shown by default on -l option. 4 | - Fix more bugs with symlink display. 5 | 6 | ### 2020-05-15 7 | - Fix bug with broken symlinks. 8 | 9 | ### 2018-06-16 10 | - Fix the calculation of kB, MB, GB, etc. which have graduations of 1024, not 1000. 11 | - Add more precision to the file sizes. 12 | - For block and char devices, show major and minor device numbers, instead of simply displaying 0 for file size. 13 | 14 | ### 2018-01-22 15 | 16 | - Fix permission string generation to produce the same output as `ls -l`. 17 | - Add --backwards option to reverse sort order. 18 | - Add more file types and icons. 19 | - Remove seconds from timestamps. 20 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Andrew Carlson 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![ls-go](./img/ls-go.png) 2 | 3 | A more colorful, user-friendly implementation of `ls` written in [Go](https://golang.org/). 4 | 5 | You want to be able to glean a lot of information as quickly as possible from `ls`. 6 | Colors can help your mind parse the information. 7 | You can configure `ls` to color the output a little bit. 8 | Configuring `ls` is a hassle though, and the colors are limited. 9 | 10 | Instead, you can use `ls-go`. 11 | It is highly colored by default. 12 | It has much fewer flags so you can get the behavior you want more easily. 13 | The colors are beautiful and semantic. 14 | A terminal with xterm-256 colors is **required*.* 15 | 16 | ## Features 17 | 18 | - [x] *Should* work on Linux, MacOS, and Windows. 19 | - [x] Outputs beautiful, semantic colors by default. 20 | - [x] Show paths to symlinks, and explicitly show broken links (`-L`). 21 | - [x] Recurse down subdirectories (`-r`). 22 | - [x] Emojis, if you're into that (`-i`). 23 | - [x] Supports [Nerd Fonts](https://github.com/ryanoasis/nerd-fonts) (`-n`). 24 | - [x] Dark or light backgrounds (`-I`). 25 | 26 | ## Usage 27 | 28 | Basic usage: 29 | 30 | ![show basic usage](./img/demo-1.png) 31 | 32 | Of course, you can use an alias to save some typing and get your favorite options: 33 | 34 | ![show fancier options](./img/demo-2.png) 35 | 36 | 37 | ### Nerd Font Support 38 | 39 | `ls-go` works with [Nerd Fonts](https://github.com/ryanoasis/nerd-fonts). 40 | Simply add `--nerd-font` or `-n` to get file-specific icons. 41 | This won't work unless you have a Nerd Font installed and selected in your terminal emulator. 42 | 43 | ![show with nerd font icons](./img/demo-3.png) 44 | 45 | ### Light Background Theme 46 | 47 | Has an option for white backgrounds. 48 | 49 | ![show on white background](./img/demo-4.png) 50 | 51 | ``` 52 | usage: ls-go [] [...] 53 | 54 | Flags: 55 | -h, --help Show context-sensitive help (also try --help-long and --help-man). 56 | -a, --all show hidden files 57 | -b, --bytes include size 58 | -m, --mdate include modification date 59 | -o, --owner include owner and group 60 | -N, --nogroup hide group 61 | -p, --perms include permissions for owner, group, and other 62 | -l, --long include size, date, owner, and permissions 63 | -d, --dirs only show directories 64 | -f, --files only show files 65 | -L, --links show paths for symlinks 66 | -R, --link-rel show symlinks as relative paths if shorter than absolute path 67 | -s, --size sort items by size 68 | -t, --time sort items by time 69 | -k, --kind sort items by extension 70 | -B, --backwards reverse the sort order of --size, --time, or --kind 71 | -S, --stats show statistics 72 | -i, --icons show folder icon before dirs 73 | -n, --nerd-font show nerd font glyphs before file names 74 | -r, --recurse traverse all dirs recursively 75 | -F, --find=FIND filter items with a regexp 76 | -I, --light output colors for light-bachground themes 77 | 78 | Args: 79 | [] the files(s) and/or folder(s) to display 80 | ``` 81 | 82 | ## Install 83 | 84 | If you have Golang installed: 85 | 86 | ```sh 87 | go install github.com/acarl005/ls-go@latest 88 | ``` 89 | 90 | On MacOS with Homebrew: 91 | 92 | ```sh 93 | brew install acarl005/homebrew-formulas/ls-go 94 | ``` 95 | 96 | On Linux with Snap: 97 | 98 | ```sh 99 | sudo snap install ls-go 100 | ``` 101 | 102 | Or, you can download the latest pre-compiled binary from the [releases page](https://github.com/acarl005/ls-go/releases). 103 | 104 | ## Credits 105 | 106 | ![Warp Terminal logo](./img/warp-logo.png) 107 | 108 | Screenshots taken using [Warp Terminal](https://www.warp.dev/). 109 | 110 | This is inspired by [athityakumar/colorls](https://github.com/athityakumar/colorls) and [monsterkodi/color-ls](https://github.com/monsterkodi/color-ls), ported to Go, with various modifications. 111 | 112 | ## Known Issues 113 | 114 | It fails on directories without executable permissions. 115 | The standard `/bin/ls` will also fail when reading non-executable directories, 116 | but only with certain options, like `ls -l`, `ls --color=always` (or `ls -G` on MacOS). 117 | This is because file metadata is needed to determine things like colors, 118 | and directories need to be executable to obtain the metadata of the contents. 119 | For example: 120 | 121 | ```sh 122 | # create dir without -x permission 123 | $ mkdir -m 644 test 124 | 125 | # add a file 126 | $ sudo touch test/foo 127 | 128 | # plain `ls` still works 129 | $ /bin/ls test 130 | foo 131 | 132 | # but `ls -l` fails 133 | $ /bin/ls -l test 134 | 135 | # and so does ls-go 136 | $ ls-go test 137 | ``` 138 | 139 | ## Contributing 140 | 141 | Contributions are muchly appreciated! 142 | Want to add a glyph for another file type? 143 | Did I forget an edge case? 144 | Is there another option that would be useful? 145 | Submit a PR! 146 | You might want to submit an issue first to make sure it's something I'd want to add though. 147 | 148 | -------------------------------------------------------------------------------- /arguments.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | 6 | kingpin "gopkg.in/alecthomas/kingpin.v2" 7 | ) 8 | 9 | // declare the struct that holds all the arguments 10 | type arguments struct { 11 | paths *[]string 12 | version *bool 13 | all *bool 14 | bytes *bool 15 | mdate *bool 16 | owner *bool 17 | nogroup *bool 18 | perms *bool 19 | long *bool 20 | dirs *bool 21 | files *bool 22 | links *bool 23 | linkRel *bool 24 | sortSize *bool 25 | sortTime *bool 26 | sortKind *bool 27 | backwards *bool 28 | stats *bool 29 | icons *bool 30 | nerdfont *bool 31 | recurse *bool 32 | find *string 33 | light *bool 34 | } 35 | 36 | var args = arguments{ 37 | kingpin.Arg("paths", "the files(s) and/or folder(s) to display").Default(".").Strings(), 38 | kingpin.Flag("version", "print version and exit").Short('v').Bool(), 39 | kingpin.Flag("all", "show hidden files").Short('a').Bool(), 40 | kingpin.Flag("bytes", "include size").Short('b').Bool(), 41 | kingpin.Flag("mdate", "include modification date").Short('m').Bool(), 42 | kingpin.Flag("owner", "include owner and group").Short('o').Bool(), 43 | kingpin.Flag("nogroup", "hide group").Short('N').Bool(), 44 | kingpin.Flag("perms", "include permissions for owner, group, and other").Short('p').Bool(), 45 | kingpin.Flag("long", "include size, date, owner, and permissions").Short('l').Bool(), 46 | kingpin.Flag("dirs", "only show directories").Short('d').Bool(), 47 | kingpin.Flag("files", "only show files").Short('f').Bool(), 48 | kingpin.Flag("links", "show paths for symlinks").Short('L').Bool(), 49 | kingpin.Flag("link-rel", "show symlinks as relative paths if shorter than absolute path").Short('R').Bool(), 50 | kingpin.Flag("size", "sort items by size").Short('s').Bool(), 51 | kingpin.Flag("time", "sort items by time").Short('t').Bool(), 52 | kingpin.Flag("kind", "sort items by extension").Short('k').Bool(), 53 | kingpin.Flag("backwards", "reverse the sort order of --size, --time, or --kind").Short('B').Bool(), 54 | kingpin.Flag("stats", "show statistics").Short('S').Bool(), 55 | kingpin.Flag("icons", "show folder icon before dirs").Short('i').Bool(), 56 | kingpin.Flag("nerd-font", "show nerd font glyphs before file names").Short('n').Bool(), 57 | kingpin.Flag("recurse", "traverse all dirs recursively").Short('r').Bool(), 58 | kingpin.Flag("find", "filter items with a regexp").Short('F').String(), 59 | kingpin.Flag("light", "output colors for light-bachground themes").Short('I').Bool(), 60 | } 61 | 62 | func argsPostParse() { 63 | if *args.long { 64 | args.bytes = &True 65 | args.mdate = &True 66 | args.owner = &True 67 | args.perms = &True 68 | args.links = &True 69 | } 70 | if *args.dirs && *args.files { 71 | log.Fatal("--dirs and --files cannot both be set") 72 | } 73 | if *args.nerdfont && *args.icons { 74 | log.Fatal("--nerd-font and --icons cannot both be set") 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /colors.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "math" 6 | "strconv" 7 | "strings" 8 | ) 9 | 10 | // see the 256-color codes 11 | // http://i.stack.imgur.com/UQVe5.png 12 | 13 | type Color int8 14 | 15 | const ( 16 | Black Color = 0 17 | Red = 1 18 | Green = 2 19 | Yellow = 3 20 | Blue = 4 21 | Magenta = 5 22 | Cyan = 6 23 | White = 7 24 | BrightBlack = 60 25 | BrightRed = 61 26 | BrightGreen = 62 27 | BrightYellow = 63 28 | BrightBlue = 64 29 | BrightMagenta = 65 30 | BrightCyan = 66 31 | BrightWhite = 67 32 | ) 33 | 34 | var lightThemeMap = map[int]int{ 35 | 67: 0, 36 | 7: 60, 37 | 60: 7, 38 | 0: 67, 39 | } 40 | 41 | func applyTheme(index int) int { 42 | if *args.light { 43 | newIndex, hasNewIndex := lightThemeMap[index] 44 | if hasNewIndex { 45 | return newIndex 46 | } else if index >= 60 { 47 | return index - 60 48 | } 49 | return index + 60 50 | } 51 | return index 52 | } 53 | 54 | func NamedFg(color Color) string { 55 | index := applyTheme(int(color)) 56 | colored := []string{"\x1b[", strconv.Itoa(index + 30), "m"} 57 | return strings.Join(colored, "") 58 | } 59 | 60 | func NamedBg(color Color) string { 61 | index := applyTheme(int(color)) 62 | colored := []string{"\x1b[", strconv.Itoa(index + 40), "m"} 63 | return strings.Join(colored, "") 64 | } 65 | 66 | // Fg wraps an 8-bit foreground color code in the ANSI escape sequence 67 | func Fg(code int) string { 68 | colored := []string{"\x1b[38;5;", strconv.Itoa(code), "m"} 69 | return strings.Join(colored, "") 70 | } 71 | 72 | // Bg wraps an 8-bit background color code in the ANSI escape sequence 73 | func Bg(code int) string { 74 | colored := []string{"\x1b[48;5;", strconv.Itoa(code), "m"} 75 | return strings.Join(colored, "") 76 | } 77 | 78 | func avg(a float64, b float64) int { 79 | m := (a + b) / 2 80 | return int(math.Ceil(m)) 81 | } 82 | 83 | // Rgb2code converts RGB values (up to 5) to an 8-bit color code 84 | func Rgb2code(r int, g int, b int, theme bool) int { 85 | if theme && *args.light { 86 | r_, g_, b_ := float64(r), float64(g), float64(b) 87 | r = 5 - avg(g_, b_) 88 | g = 5 - avg(r_, b_) 89 | b = 5 - avg(r_, g_) 90 | } 91 | code := 36*r + 6*g + b + 16 92 | if code < 16 || 231 < code { 93 | panic(fmt.Errorf("Invalid RGB values (%d, %d, %d)", r, g, b)) 94 | } 95 | return code 96 | } 97 | 98 | // Gray2code converts a scalar of "grayness" to an 8-bit color code 99 | func Gray2code(lightness int) int { 100 | if *args.light { 101 | lightness = 23 - lightness 102 | } 103 | code := lightness + 232 104 | if code < 232 || 255 < code { 105 | panic(fmt.Errorf("Invalid lightness value (%d) for gray", lightness)) 106 | } 107 | return code 108 | } 109 | 110 | // FgRGB converts RGB values (up to 5) to an ANSI-escaped foreground 8-bit color code 111 | func FgRGB(r int, g int, b int) string { 112 | return Fg(Rgb2code(r, g, b, false)) 113 | } 114 | 115 | // Theme-sensitive version 116 | func FgRGBT(r int, g int, b int) string { 117 | return Fg(Rgb2code(r, g, b, true)) 118 | } 119 | 120 | // BgRGB converts RGB values (up to 5) to an ANSI-escaped background 8-bit color code 121 | func BgRGB(r int, g int, b int) string { 122 | return Bg(Rgb2code(r, g, b, false)) 123 | } 124 | 125 | // Theme-sensitive version 126 | func BgRGBT(r int, g int, b int) string { 127 | return Bg(Rgb2code(r, g, b, true)) 128 | } 129 | 130 | // FgGray converts a scalar of "grayness" to an ANSI-escaped foreground 8-bit color code 131 | func FgGray(lightness int) string { 132 | return Fg(Gray2code(lightness)) 133 | } 134 | 135 | // BgGray converts a scalar of "grayness" to an ANSI-escaped background 8-bit color code 136 | func BgGray(lightness int) string { 137 | return Bg(Gray2code(lightness)) 138 | } 139 | 140 | const ( 141 | // Reset undoes ANSI color codes 142 | Reset = "\x1b[0m" 143 | Bold = "\x1b[1m" 144 | ) 145 | 146 | var ( 147 | // FileColor is a mapping of filetypes to colors 148 | FileColor map[string]FileColorConfig 149 | 150 | // SizeColor has the color mappings for ranges of file sizes 151 | SizeColor map[string]string 152 | 153 | // ConfigColor holds mappings for other various colors 154 | ConfigColor map[string]map[string]string 155 | 156 | // PermsColor holds color mappings for users and groups 157 | PermsColor map[string]map[string]string 158 | ) 159 | 160 | var ( 161 | // FileAliases converts alternative extensions to their canonical mapping in FileColor 162 | FileAliases = map[string]string{ 163 | "s": "asm", 164 | "b": "bf", 165 | "c++": "c", 166 | "cc": "c", 167 | "cpp": "c", 168 | "cs": "c", 169 | "cxx": "c", 170 | "d": "c", 171 | "h": "c", 172 | "h++": "c", 173 | "hh": "c", 174 | "hpp": "c", 175 | "hxx": "c", 176 | "pxd": "c", 177 | "cljc": "clj", 178 | "cljs": "clj", 179 | "class": "compiled", 180 | "elc": "compiled", 181 | "hi": "compiled", 182 | "o": "compiled", 183 | "pyc": "compiled", 184 | "7z": "compress", 185 | "Z": "compress", 186 | "bz2": "compress", 187 | "deb": "compress", 188 | "dmg": "compress", 189 | "dpkg": "compress", 190 | "gz": "compress", 191 | "iso": "compress", 192 | "jar": "compress", 193 | "lzma": "compress", 194 | "par": "compress", 195 | "rar": "compress", 196 | "rpm": "compress", 197 | "tar": "compress", 198 | "tc": "compress", 199 | "tgz": "compress", 200 | "txz": "compress", 201 | "whl": "compress", 202 | "xz": "compress", 203 | "z": "compress", 204 | "zip": "compress", 205 | "less": "css", 206 | "sass": "css", 207 | "scss": "css", 208 | "styl": "css", 209 | "djvu": "document", 210 | "doc": "document", 211 | "docx": "document", 212 | "dvi": "document", 213 | "eml": "document", 214 | "fotd": "document", 215 | "odp": "document", 216 | "odt": "document", 217 | "pdf": "document", 218 | "ppt": "document", 219 | "pptx": "document", 220 | "rtf": "document", 221 | "xls": "document", 222 | "xlsx": "document", 223 | "f03": "f", 224 | "f77": "f", 225 | "f90": "f", 226 | "f95": "f", 227 | "for": "f", 228 | "fpp": "f", 229 | "ftn": "f", 230 | "fsi": "fs", 231 | "fsscript": "fs", 232 | "fsx": "fs", 233 | "dna": "gb", 234 | "gsh": "groovy", 235 | "gvy": "groovy", 236 | "gy": "groovy", 237 | "htm": "html", 238 | "xhtml": "html", 239 | "bson": "js", 240 | "jade": "js", 241 | "json": "js", 242 | "mjs": "js", 243 | "ts": "js", 244 | "cjs": "js", 245 | "tsx": "jsx", 246 | "cjsx": "jsx", 247 | "mat": "m", 248 | "markdown": "md", 249 | "mkd": "md", 250 | "rst": "md", 251 | "sml": "ml", 252 | "mli": "ml", 253 | "aac": "media", 254 | "alac": "media", 255 | "audio": "media", 256 | "avi": "media", 257 | "bmp": "media", 258 | "cbr": "media", 259 | "cbz": "media", 260 | "eps": "media", 261 | "flac": "media", 262 | "flv": "media", 263 | "gif": "media", 264 | "glp": "media", 265 | "gltf": "media", 266 | "ico": "media", 267 | "image": "media", 268 | "jpeg": "media", 269 | "jpg": "media", 270 | "m2v": "media", 271 | "m4a": "media", 272 | "mka": "media", 273 | "mkv": "media", 274 | "mov": "media", 275 | "mp3": "media", 276 | "mp4": "media", 277 | "mpeg": "media", 278 | "mpg": "media", 279 | "nef": "media", 280 | "ogg": "media", 281 | "ogm": "media", 282 | "ogv": "media", 283 | "opus": "media", 284 | "orf": "media", 285 | "pbm": "media", 286 | "pgm": "media", 287 | "png": "media", 288 | "pnm": "media", 289 | "ppm": "media", 290 | "pxm": "media", 291 | "sixel": "media", 292 | "stl": "media", 293 | "svg": "media", 294 | "tif": "media", 295 | "tiff": "media", 296 | "video": "media", 297 | "vob": "media", 298 | "wav": "media", 299 | "webm": "media", 300 | "webp": "media", 301 | "wma": "media", 302 | "wmv": "media", 303 | "xpm": "media", 304 | "php3": "php", 305 | "php4": "php", 306 | "php5": "php", 307 | "phpt": "php", 308 | "phtml": "php", 309 | "ipynb": "py", 310 | "pickle": "py", 311 | "pkl": "py", 312 | "pyx": "py", 313 | "bash": "sh", 314 | "csh": "sh", 315 | "fish": "sh", 316 | "ksh": "sh", 317 | "ps1": "sh", 318 | "zsh": "sh", 319 | "plpgsql": "sql", 320 | "plsql": "sql", 321 | "psql": "sql", 322 | "tsql": "sql", 323 | "vimrc": "vim", 324 | } 325 | ) 326 | 327 | type FileColorConfig struct { 328 | light string 329 | dark string 330 | themeSwitch bool 331 | } 332 | 333 | func generateColors() { 334 | FileColor = map[string]FileColorConfig{ 335 | "as": {FgRGB(5, 0, 0), FgRGB(3, 0, 0), true}, 336 | "asm": {FgRGBT(5, 4, 3), FgRGBT(5, 3, 1), false}, 337 | "apk": {FgRGB(1, 5, 0), FgRGB(1, 3, 0), true}, 338 | "bf": {FgRGBT(5, 4, 3), FgRGBT(5, 3, 1), false}, 339 | "bzl": {FgRGB(1, 5, 0), FgRGB(1, 3, 0), true}, 340 | "c": {FgRGB(0, 3, 5), FgRGB(0, 1, 5), true}, 341 | "clj": {FgRGB(5, 1, 2), FgRGB(4, 0, 2), true}, 342 | "coffee": {FgRGB(3, 2, 0), FgRGB(2, 1, 0), true}, 343 | "cr": {FgRGB(1, 5, 0), FgRGB(1, 3, 0), true}, 344 | "cson": {FgRGB(3, 2, 0), FgRGB(2, 1, 0), true}, 345 | "css": {FgRGB(5, 3, 5), FgRGB(5, 1, 5), true}, 346 | "dart": {FgRGB(0, 4, 3), FgRGB(0, 2, 3), true}, 347 | "diff": {FgRGB(0, 5, 0), FgRGB(5, 0, 0), true}, 348 | "elm": {FgRGB(0, 5, 5), FgRGB(0, 3, 5), true}, 349 | "erl": {FgRGB(4, 0, 1), FgRGB(2, 0, 1), true}, 350 | "ex": {FgRGB(2, 1, 5), FgRGB(1, 0, 5), true}, 351 | "f": {FgRGB(5, 2, 0), FgRGB(2, 1, 0), true}, 352 | "fs": {FgRGB(0, 4, 5), FgRGB(0, 2, 4), true}, 353 | "gb": {FgRGB(0, 4, 3), FgRGB(0, 2, 1), true}, 354 | "gleam": {FgRGB(5, 3, 5), FgRGB(5, 1, 5), true}, 355 | "go": {FgRGB(2, 5, 3), FgRGB(2, 3, 3), true}, 356 | "graphql": {FgRGB(5, 3, 5), FgRGB(5, 1, 5), true}, 357 | "groovy": {FgRGBT(5, 4, 3), FgRGBT(5, 3, 1), false}, 358 | "gv": {FgRGB(3, 2, 5), FgRGB(2, 1, 5), true}, 359 | "hs": {FgRGB(2, 1, 5), FgRGB(1, 0, 5), true}, 360 | "html": {FgRGB(1, 5, 5), FgRGB(1, 3, 3), true}, 361 | "hx": {FgRGB(5, 2, 0), FgRGB(2, 1, 0), true}, 362 | "ino": {FgRGB(0, 4, 3), FgRGB(0, 2, 1), true}, 363 | "java": {FgRGB(3, 2, 0), FgRGB(2, 1, 0), true}, 364 | "jl": {FgRGB(3, 2, 5), FgRGB(2, 1, 5), true}, 365 | "js": {FgRGB(4, 4, 0), FgRGB(2, 2, 0), true}, 366 | "jsx": {FgRGB(1, 5, 5), FgRGB(1, 3, 3), true}, 367 | "kt": {FgRGB(2, 1, 5), FgRGB(1, 0, 5), true}, 368 | "lock": {FgGray(11), FgGray(7), false}, 369 | "log": {FgGray(11), FgGray(7), false}, 370 | "lua": {FgRGB(0, 3, 5), FgRGB(0, 1, 5), true}, 371 | "m": {FgRGBT(5, 4, 3), FgRGBT(5, 3, 1), false}, 372 | "md": {FgRGB(1, 5, 5), FgRGB(1, 3, 3), true}, 373 | "ml": {FgRGB(5, 2, 0), FgRGB(2, 1, 0), true}, 374 | "nim": {FgRGB(4, 4, 0), FgRGB(2, 2, 0), true}, 375 | "nix": {FgRGB(0, 3, 5), FgRGB(0, 1, 5), true}, 376 | "php": {FgRGB(0, 3, 4), FgRGB(0, 2, 2), true}, 377 | "pl": {FgRGB(2, 1, 5), FgRGB(1, 0, 5), true}, 378 | "py": {FgRGB(0, 4, 0), FgRGB(0, 2, 0), true}, 379 | "r": {FgRGB(0, 5, 5), FgRGB(0, 3, 5), true}, 380 | "rb": {FgRGB(5, 1, 0), FgRGB(3, 1, 0), true}, 381 | "rs": {FgRGB(4, 3, 0), FgRGB(2, 2, 0), true}, 382 | "scala": {FgRGB(5, 0, 0), FgRGB(3, 0, 0), true}, 383 | "sh": {FgRGB(4, 0, 4), FgRGB(2, 0, 2), true}, 384 | "sol": {FgRGB(0, 3, 5), FgRGB(0, 1, 5), true}, 385 | "sql": {FgRGB(4, 5, 3), FgRGB(3, 4, 0), true}, 386 | "svelte": {FgRGB(5, 2, 0), FgRGB(5, 0, 0), true}, 387 | "swift": {FgRGBT(5, 4, 3), FgRGBT(5, 3, 1), false}, 388 | "vim": {FgRGB(0, 4, 0), FgRGB(0, 2, 0), true}, 389 | "vue": {FgRGB(0, 4, 3), FgRGB(0, 2, 1), true}, 390 | "xml": {FgRGB(1, 5, 5), FgRGB(1, 3, 3), true}, 391 | "zig": {FgRGB(4, 4, 0), FgRGB(2, 2, 0), true}, 392 | 393 | "compiled": {FgGray(11), FgGray(7), false}, 394 | "compress": {FgRGB(5, 0, 0), FgRGB(3, 0, 0), true}, 395 | "document": {FgRGB(5, 0, 0), FgRGB(3, 0, 0), true}, 396 | "media": {FgRGB(3, 2, 5), FgRGB(2, 1, 5), true}, 397 | "_default": {FgGray(20), FgGray(11), false}, 398 | } 399 | 400 | SizeColor = map[string]string{ 401 | "B": FgRGBT(0, 1, 5), 402 | "K": FgRGBT(0, 2, 5), 403 | "M": FgRGBT(1, 4, 5), 404 | "G": FgRGBT(2, 5, 5), 405 | "T": FgRGBT(3, 5, 5), 406 | } 407 | 408 | ConfigColor = map[string]map[string]string{ 409 | "dir": { 410 | "name": Bold + BgRGBT(0, 0, 2) + FgGray(23), 411 | }, 412 | ".dir": { 413 | "name": Bold + BgRGBT(0, 0, 1) + FgGray(18), 414 | }, 415 | "folderHeader": { 416 | "arrow": NamedFg(Yellow), 417 | "main": BgGray(2) + NamedFg(Yellow), 418 | "slash": FgGray(5), 419 | "lastFolder": Bold + NamedFg(BrightYellow), 420 | "error": NamedFg(BrightYellow) + NamedBg(Red), 421 | }, 422 | "link": { 423 | "name": NamedFg(BrightGreen), 424 | "nameDir": Bold + BgRGBT(0, 0, 2) + NamedFg(BrightCyan), 425 | "arrow": NamedFg(BrightGreen), 426 | "arrowDir": NamedFg(BrightCyan), 427 | "broken": NamedFg(BrightRed), 428 | }, 429 | "device": { 430 | "name": Bold + BgGray(3) + NamedFg(BrightYellow), // /dev 431 | }, 432 | "socket": { 433 | "name": Bold + BgRGBT(1, 0, 1) + FgGray(23), 434 | }, 435 | "pipe": { 436 | "name": Bold + BgRGBT(2, 1, 0) + FgGray(23), 437 | }, 438 | "stats": { 439 | "text": BgGray(2) + FgGray(15), 440 | "number": FgRGBT(0, 2, 3), 441 | "ms": FgRGBT(0, 3, 5), 442 | }, 443 | } 444 | 445 | PermsColor = map[string]map[string]string{ 446 | "user": { 447 | "root": FgRGB(5, 0, 2), 448 | "daemon": FgRGB(4, 2, 1), 449 | "_self": FgRGB(0, 5, 0), 450 | "_default": FgRGB(0, 3, 3), 451 | }, 452 | "group": { 453 | "wheel": FgRGB(3, 0, 0), 454 | "staff": FgRGB(0, 2, 0), 455 | "admin": FgRGB(2, 2, 0), 456 | "_default": FgRGB(2, 0, 2), 457 | }, 458 | "other": { 459 | "_default": FgGray(15), 460 | }, 461 | } 462 | } 463 | -------------------------------------------------------------------------------- /compile: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -xe 4 | 5 | GOOS=darwin GOARCH=amd64 go build -o ls-go-darwin-amd64 6 | GOOS=darwin GOARCH=arm64 go build -o ls-go-darwin-arm64 7 | 8 | GOOS=linux GOARCH=amd64 go build -o ls-go-linux-amd64 9 | GOOS=linux GOARCH=386 go build -o ls-go-linux-386 10 | GOOS=linux GOARCH=arm64 go build -o ls-go-linux-arm64 11 | 12 | #GOOS=windows GOARCH=amd64 go build -o ls-go-windows-amd64 13 | #GOOS=windows GOARCH=386 go build -o ls-go-windows-386 14 | -------------------------------------------------------------------------------- /example/.dockerignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/.dockerignore -------------------------------------------------------------------------------- /example/.eslintrc.cjs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/.eslintrc.cjs -------------------------------------------------------------------------------- /example/.eslintrc.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/.eslintrc.js -------------------------------------------------------------------------------- /example/.mongorc.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/.mongorc.js -------------------------------------------------------------------------------- /example/Cargo.lock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/Cargo.lock -------------------------------------------------------------------------------- /example/Cargo.toml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/Cargo.toml -------------------------------------------------------------------------------- /example/Dockerfile: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/Dockerfile -------------------------------------------------------------------------------- /example/a.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/a.js -------------------------------------------------------------------------------- /example/bar.txt: -------------------------------------------------------------------------------- 1 | foo.txt -------------------------------------------------------------------------------- /example/deploy: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/deploy -------------------------------------------------------------------------------- /example/fd0: -------------------------------------------------------------------------------- 1 | /dev/fd/0 -------------------------------------------------------------------------------- /example/foo.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/foo.txt -------------------------------------------------------------------------------- /example/go.mod: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/go.mod -------------------------------------------------------------------------------- /example/go.sum: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/go.sum -------------------------------------------------------------------------------- /example/package.json: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/package.json -------------------------------------------------------------------------------- /example/scripts: -------------------------------------------------------------------------------- 1 | files -------------------------------------------------------------------------------- /example/src/.npmignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/.npmignore -------------------------------------------------------------------------------- /example/src/Brewfile: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/Brewfile -------------------------------------------------------------------------------- /example/src/Jenkinsfile: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/Jenkinsfile -------------------------------------------------------------------------------- /example/src/Justfile: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/Justfile -------------------------------------------------------------------------------- /example/src/MAINTAINERS: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/MAINTAINERS -------------------------------------------------------------------------------- /example/src/Makefile: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/Makefile -------------------------------------------------------------------------------- /example/src/Vagrantfile: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/Vagrantfile -------------------------------------------------------------------------------- /example/src/foo.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.ai -------------------------------------------------------------------------------- /example/src/foo.apk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.apk -------------------------------------------------------------------------------- /example/src/foo.as: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.as -------------------------------------------------------------------------------- /example/src/foo.asm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.asm -------------------------------------------------------------------------------- /example/src/foo.avro: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.avro -------------------------------------------------------------------------------- /example/src/foo.bf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.bf -------------------------------------------------------------------------------- /example/src/foo.bson: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.bson -------------------------------------------------------------------------------- /example/src/foo.bzl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.bzl -------------------------------------------------------------------------------- /example/src/foo.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.c -------------------------------------------------------------------------------- /example/src/foo.cfg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.cfg -------------------------------------------------------------------------------- /example/src/foo.clj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.clj -------------------------------------------------------------------------------- /example/src/foo.coffee: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.coffee -------------------------------------------------------------------------------- /example/src/foo.conf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.conf -------------------------------------------------------------------------------- /example/src/foo.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.cpp -------------------------------------------------------------------------------- /example/src/foo.cr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.cr -------------------------------------------------------------------------------- /example/src/foo.crt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.crt -------------------------------------------------------------------------------- /example/src/foo.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.cs -------------------------------------------------------------------------------- /example/src/foo.cson: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.cson -------------------------------------------------------------------------------- /example/src/foo.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.css -------------------------------------------------------------------------------- /example/src/foo.d: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.d -------------------------------------------------------------------------------- /example/src/foo.dart: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.dart -------------------------------------------------------------------------------- /example/src/foo.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.db -------------------------------------------------------------------------------- /example/src/foo.diff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.diff -------------------------------------------------------------------------------- /example/src/foo.doc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.doc -------------------------------------------------------------------------------- /example/src/foo.dockerfile: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.dockerfile -------------------------------------------------------------------------------- /example/src/foo.dpkg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.dpkg -------------------------------------------------------------------------------- /example/src/foo.elm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.elm -------------------------------------------------------------------------------- /example/src/foo.env: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.env -------------------------------------------------------------------------------- /example/src/foo.epub: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.epub -------------------------------------------------------------------------------- /example/src/foo.erl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.erl -------------------------------------------------------------------------------- /example/src/foo.ex: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.ex -------------------------------------------------------------------------------- /example/src/foo.f: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.f -------------------------------------------------------------------------------- /example/src/foo.flac: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.flac -------------------------------------------------------------------------------- /example/src/foo.fs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.fs -------------------------------------------------------------------------------- /example/src/foo.gb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.gb -------------------------------------------------------------------------------- /example/src/foo.gform: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.gform -------------------------------------------------------------------------------- /example/src/foo.gleam: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.gleam -------------------------------------------------------------------------------- /example/src/foo.go: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.go -------------------------------------------------------------------------------- /example/src/foo.graphql: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.graphql -------------------------------------------------------------------------------- /example/src/foo.groovy: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.groovy -------------------------------------------------------------------------------- /example/src/foo.gv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.gv -------------------------------------------------------------------------------- /example/src/foo.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.h -------------------------------------------------------------------------------- /example/src/foo.hs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.hs -------------------------------------------------------------------------------- /example/src/foo.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.html -------------------------------------------------------------------------------- /example/src/foo.hx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.hx -------------------------------------------------------------------------------- /example/src/foo.ics: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.ics -------------------------------------------------------------------------------- /example/src/foo.iml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.iml -------------------------------------------------------------------------------- /example/src/foo.ini: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.ini -------------------------------------------------------------------------------- /example/src/foo.ino: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.ino -------------------------------------------------------------------------------- /example/src/foo.ipsw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.ipsw -------------------------------------------------------------------------------- /example/src/foo.iso: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.iso -------------------------------------------------------------------------------- /example/src/foo.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.java -------------------------------------------------------------------------------- /example/src/foo.jl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.jl -------------------------------------------------------------------------------- /example/src/foo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.jpg -------------------------------------------------------------------------------- /example/src/foo.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.js -------------------------------------------------------------------------------- /example/src/foo.json: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.json -------------------------------------------------------------------------------- /example/src/foo.jsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.jsx -------------------------------------------------------------------------------- /example/src/foo.ko: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.ko -------------------------------------------------------------------------------- /example/src/foo.kt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.kt -------------------------------------------------------------------------------- /example/src/foo.less: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.less -------------------------------------------------------------------------------- /example/src/foo.lock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.lock -------------------------------------------------------------------------------- /example/src/foo.log: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.log -------------------------------------------------------------------------------- /example/src/foo.lua: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.lua -------------------------------------------------------------------------------- /example/src/foo.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.m -------------------------------------------------------------------------------- /example/src/foo.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.md -------------------------------------------------------------------------------- /example/src/foo.mjs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.mjs -------------------------------------------------------------------------------- /example/src/foo.ml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.ml -------------------------------------------------------------------------------- /example/src/foo.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.mp4 -------------------------------------------------------------------------------- /example/src/foo.mustache: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.mustache -------------------------------------------------------------------------------- /example/src/foo.nc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.nc -------------------------------------------------------------------------------- /example/src/foo.nim: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.nim -------------------------------------------------------------------------------- /example/src/foo.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.otf -------------------------------------------------------------------------------- /example/src/foo.patch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.patch -------------------------------------------------------------------------------- /example/src/foo.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.pdf -------------------------------------------------------------------------------- /example/src/foo.php: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.php -------------------------------------------------------------------------------- /example/src/foo.pl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.pl -------------------------------------------------------------------------------- /example/src/foo.ppt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.ppt -------------------------------------------------------------------------------- /example/src/foo.prisma: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.prisma -------------------------------------------------------------------------------- /example/src/foo.ps1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.ps1 -------------------------------------------------------------------------------- /example/src/foo.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.psd -------------------------------------------------------------------------------- /example/src/foo.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.py -------------------------------------------------------------------------------- /example/src/foo.r: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.r -------------------------------------------------------------------------------- /example/src/foo.rb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.rb -------------------------------------------------------------------------------- /example/src/foo.rdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.rdb -------------------------------------------------------------------------------- /example/src/foo.rpm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.rpm -------------------------------------------------------------------------------- /example/src/foo.rs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.rs -------------------------------------------------------------------------------- /example/src/foo.rss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.rss -------------------------------------------------------------------------------- /example/src/foo.rst: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.rst -------------------------------------------------------------------------------- /example/src/foo.rubydoc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.rubydoc -------------------------------------------------------------------------------- /example/src/foo.sass: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.sass -------------------------------------------------------------------------------- /example/src/foo.scala: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.scala -------------------------------------------------------------------------------- /example/src/foo.sh: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.sh -------------------------------------------------------------------------------- /example/src/foo.sixel: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.sixel -------------------------------------------------------------------------------- /example/src/foo.sol: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.sol -------------------------------------------------------------------------------- /example/src/foo.sql: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.sql -------------------------------------------------------------------------------- /example/src/foo.sqlite: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.sqlite -------------------------------------------------------------------------------- /example/src/foo.sqlite3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.sqlite3 -------------------------------------------------------------------------------- /example/src/foo.styl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.styl -------------------------------------------------------------------------------- /example/src/foo.svelte: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.svelte -------------------------------------------------------------------------------- /example/src/foo.svg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.svg -------------------------------------------------------------------------------- /example/src/foo.swift: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.swift -------------------------------------------------------------------------------- /example/src/foo.tex: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.tex -------------------------------------------------------------------------------- /example/src/foo.tf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.tf -------------------------------------------------------------------------------- /example/src/foo.tfrecord: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.tfrecord -------------------------------------------------------------------------------- /example/src/foo.toml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.toml -------------------------------------------------------------------------------- /example/src/foo.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.ts -------------------------------------------------------------------------------- /example/src/foo.twig: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.twig -------------------------------------------------------------------------------- /example/src/foo.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.txt -------------------------------------------------------------------------------- /example/src/foo.vim: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.vim -------------------------------------------------------------------------------- /example/src/foo.vue: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.vue -------------------------------------------------------------------------------- /example/src/foo.windows: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.windows -------------------------------------------------------------------------------- /example/src/foo.xls: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.xls -------------------------------------------------------------------------------- /example/src/foo.xml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.xml -------------------------------------------------------------------------------- /example/src/foo.yaml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.yaml -------------------------------------------------------------------------------- /example/src/foo.zig: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.zig -------------------------------------------------------------------------------- /example/src/foo.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/foo.zip -------------------------------------------------------------------------------- /example/src/gruntfile.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/gruntfile.js -------------------------------------------------------------------------------- /example/src/gulpfile.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/gulpfile.js -------------------------------------------------------------------------------- /example/src/passwd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/src/passwd -------------------------------------------------------------------------------- /example/thing.conf: -------------------------------------------------------------------------------- 1 | notexist.conf -------------------------------------------------------------------------------- /example/vite.config.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/vite.config.js -------------------------------------------------------------------------------- /example/z.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/example/z.js -------------------------------------------------------------------------------- /file-icons.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "strings" 5 | ) 6 | 7 | func getIconForFile(name, ext string) string { 8 | // default icon for all files. try to find a better one though... 9 | icon := icons["file"] 10 | 11 | // resolve aliased extensions 12 | extKey := strings.ToLower(ext) 13 | alias, hasAlias := aliases[extKey] 14 | if hasAlias { 15 | extKey = alias 16 | } 17 | 18 | // see if we can find a better icon based on extension alone 19 | betterIcon, hasBetterIcon := icons[extKey] 20 | if hasBetterIcon { 21 | icon = betterIcon 22 | } 23 | 24 | // now look for icons based on full names 25 | fullName := name 26 | if ext != "" { 27 | fullName += "." + ext 28 | } 29 | 30 | fullName = strings.ToLower(fullName) 31 | fullAlias, hasFullAlias := aliases[fullName] 32 | if hasFullAlias { 33 | fullName = fullAlias 34 | } 35 | bestIcon, hasBestIcon := icons[fullName] 36 | if hasBestIcon { 37 | icon = bestIcon 38 | } 39 | return icon 40 | } 41 | 42 | func getIconForFolder(name string) string { 43 | icon := folders["folder"] 44 | betterIcon, hasBetterIcon := folders[name] 45 | if hasBetterIcon { 46 | icon = betterIcon 47 | } 48 | return icon 49 | } 50 | 51 | var icons = map[string]string{ 52 | "ai": "\ue7b4", 53 | "android": "\ue70e", 54 | "apple": "\uf179", 55 | "as": "\ue60b", 56 | "asm": "󰘚", 57 | "audio": "\uf1c7", 58 | "avro": "\ue60b", 59 | "bf": "\uf067", 60 | "binary": "\uf471", 61 | "bzl": "\ue63a", 62 | "c": "\ue61e", 63 | "cfg": "\uf423", 64 | "clj": "\ue768", 65 | "coffee": "\ue751", 66 | "conf": "\ue615", 67 | "cpp": "\ue61d", 68 | "cfm": "\ue645", 69 | "cr": "\ue62f", 70 | "cs": "\ue648", 71 | "cson": "\ue601", 72 | "css": "\ue749", 73 | "cu": "\ue64b", 74 | "d": "\ue7af", 75 | "dart": "\ue64c", 76 | "db": "\uf1c0", 77 | "deb": "\uf306", 78 | "diff": "\uf440", 79 | "doc": "\uf1c2", 80 | "dockerfile": "\ue650", 81 | "dpkg": "\uf17c", 82 | "ebook": "\uf02d", 83 | "elm": "\ue62c", 84 | "env": "\uf462", 85 | "erl": "\ue7b1", 86 | "ex": "\ue62d", 87 | "f": "󱈚", 88 | "file": "\uf15b", 89 | "font": "\uf031", 90 | "fs": "\ue7a7", 91 | "gb": "\ue272", 92 | "gform": "\uf298", 93 | "git": "\ue702", 94 | "go": "\ue724", 95 | "graphql": "\ue662", 96 | "gleam": "★", 97 | "glp": "󰆧", 98 | "groovy": "\ue775", 99 | "gruntfile.js": "\ue74c", 100 | "gulpfile.js": "\ue610", 101 | "gv": "\ue225", 102 | "h": "\uf0fd", 103 | "haml": "\ue664", 104 | "hs": "\ue777", 105 | "html": "\uf13b", 106 | "hx": "\ue666", 107 | "ics": "\uf073", 108 | "image": "\uf1c5", 109 | "iml": "\ue7b5", 110 | "ini": "󰅪", 111 | "ino": "\ue255", 112 | "iso": "󰋊", 113 | "jade": "\ue66c", 114 | "java": "\ue738", 115 | "jenkinsfile": "\ue767", 116 | "jl": "\ue624", 117 | "js": "\ue781", 118 | "json": "\ue60b", 119 | "jsx": "\ue7ba", 120 | "key": "\uf43d", 121 | "ko": "\uebc6", 122 | "kt": "\ue634", 123 | "less": "\ue758", 124 | "lock": "\uf023", 125 | "log": "\uf18d", 126 | "lua": "\ue620", 127 | "maintainers": "\uf0c0", 128 | "makefile": "\ue20f", 129 | "md": "\uf48a", 130 | "mjs": "\ue718", 131 | "ml": "󰘧", 132 | "mustache": "\ue60f", 133 | "nc": "󰋁", 134 | "nim": "\ue677", 135 | "nix": "\uf313", 136 | "npmignore": "\ue71e", 137 | "package": "󰏗", 138 | "passwd": "\uf023", 139 | "patch": "\uf440", 140 | "pdf": "\uf1c1", 141 | "php": "\ue608", 142 | "pl": "\ue7a1", 143 | "prisma": "\ue684", 144 | "ppt": "\uf1c4", 145 | "psd": "\ue7b8", 146 | "pwsh": "󰨊", 147 | "py": "\ue606", 148 | "r": "\ue68a", 149 | "rb": "\ue21e", 150 | "rdb": "\ue76d", 151 | "rpm": "\uf17c", 152 | "rs": "\ue7a8", 153 | "rss": "\uf09e", 154 | "rst": "󰅫", 155 | "rubydoc": "\ue73b", 156 | "sass": "\ue603", 157 | "scala": "\ue737", 158 | "shell": "\uf489", 159 | "shp": "󰙞", 160 | "sol": "󰡪", 161 | "sqlite": "\ue7c4", 162 | "styl": "\ue600", 163 | "svelte": "\ue697", 164 | "swift": "\ue755", 165 | "tex": "\u222b", 166 | "tf": "\ue69a", 167 | "toml": "󰅪", 168 | "ts": "󰛦", 169 | "twig": "\ue61c", 170 | "txt": "\uf15c", 171 | "vagrantfile": "\ue21e", 172 | "video": "\uf03d", 173 | "vim": "\ue62b", 174 | "vue": "\ue6a0", 175 | "windows": "\uf17a", 176 | "xls": "\uf1c3", 177 | "xml": "\ue796", 178 | "yml": "\ue601", 179 | "zig": "\ue6a9", 180 | "zip": "\uf410", 181 | } 182 | 183 | var aliases = map[string]string{ 184 | "apk": "android", 185 | "gradle": "android", 186 | "ds_store": "apple", 187 | "localized": "apple", 188 | "m": "apple", 189 | "mm": "apple", 190 | "s": "asm", 191 | "aac": "audio", 192 | "alac": "audio", 193 | "flac": "audio", 194 | "m4a": "audio", 195 | "mka": "audio", 196 | "mp3": "audio", 197 | "ogg": "audio", 198 | "opus": "audio", 199 | "wav": "audio", 200 | "wma": "audio", 201 | "b": "bf", 202 | "bson": "binary", 203 | "feather": "binary", 204 | "mat": "binary", 205 | "o": "binary", 206 | "pb": "binary", 207 | "pickle": "binary", 208 | "pkl": "binary", 209 | "tfrecord": "binary", 210 | "conf": "cfg", 211 | "config": "cfg", 212 | "cljc": "clj", 213 | "cljs": "clj", 214 | "editorconfig": "conf", 215 | "rc": "conf", 216 | "c++": "cpp", 217 | "cc": "cpp", 218 | "cxx": "cpp", 219 | "scss": "css", 220 | "sql": "db", 221 | "docx": "doc", 222 | "gdoc": "doc", 223 | "dockerignore": "dockerfile", 224 | "epub": "ebook", 225 | "ipynb": "ebook", 226 | "mobi": "ebook", 227 | "f03": "f", 228 | "f77": "f", 229 | "f90": "f", 230 | "f95": "f", 231 | "for": "f", 232 | "fpp": "f", 233 | "ftn": "f", 234 | "eot": "font", 235 | "otf": "font", 236 | "ttf": "font", 237 | "woff": "font", 238 | "woff2": "font", 239 | "fsi": "fs", 240 | "fsscript": "fs", 241 | "fsx": "fs", 242 | "dna": "gb", 243 | "gitattributes": "git", 244 | "gitconfig": "git", 245 | "gitignore": "git", 246 | "gitignore_global": "git", 247 | "gitmirrorall": "git", 248 | "gitmodules": "git", 249 | "gltf": "glp", 250 | "gsh": "groovy", 251 | "gvy": "groovy", 252 | "gy": "groovy", 253 | "h++": "h", 254 | "hh": "h", 255 | "hpp": "h", 256 | "hxx": "h", 257 | "lhs": "hs", 258 | "htm": "html", 259 | "xhtml": "html", 260 | "bmp": "image", 261 | "cbr": "image", 262 | "cbz": "image", 263 | "dvi": "image", 264 | "eps": "image", 265 | "gif": "image", 266 | "ico": "image", 267 | "jpeg": "image", 268 | "jpg": "image", 269 | "nef": "image", 270 | "orf": "image", 271 | "pbm": "image", 272 | "pgm": "image", 273 | "png": "image", 274 | "pnm": "image", 275 | "ppm": "image", 276 | "pxm": "image", 277 | "sixel": "image", 278 | "stl": "image", 279 | "svg": "image", 280 | "tif": "image", 281 | "tiff": "image", 282 | "webp": "image", 283 | "xpm": "image", 284 | "disk": "iso", 285 | "dmg": "iso", 286 | "img": "iso", 287 | "ipsw": "iso", 288 | "smi": "iso", 289 | "vhd": "iso", 290 | "vhdx": "iso", 291 | "vmdk": "iso", 292 | "jar": "java", 293 | "cjs": "js", 294 | "properties": "json", 295 | "webmanifest": "json", 296 | "tsx": "jsx", 297 | "cjsx": "jsx", 298 | "cer": "key", 299 | "crt": "key", 300 | "der": "key", 301 | "gpg": "key", 302 | "p7b": "key", 303 | "pem": "key", 304 | "pfx": "key", 305 | "pgp": "key", 306 | "license": "key", 307 | "codeowners": "maintainers", 308 | "credits": "maintainers", 309 | "cmake": "makefile", 310 | "justfile": "makefile", 311 | "markdown": "md", 312 | "mkd": "md", 313 | "rdoc": "md", 314 | "readme": "md", 315 | "mli": "ml", 316 | "sml": "ml", 317 | "netcdf": "nc", 318 | "brewfile": "package", 319 | "cargo.toml": "package", 320 | "cargo.lock": "package", 321 | "go.mod": "package", 322 | "go.sum": "package", 323 | "pyproject.toml": "package", 324 | "poetry.lock": "package", 325 | "package.json": "package", 326 | "pipfile": "package", 327 | "pipfile.lock": "package", 328 | "php3": "php", 329 | "php4": "php", 330 | "php5": "php", 331 | "phpt": "php", 332 | "phtml": "php", 333 | "gslides": "ppt", 334 | "pptx": "ppt", 335 | "ps1": "pwsh", 336 | "psd1": "pwsh", 337 | "psm1": "pwsh", 338 | "pxd": "py", 339 | "pyc": "py", 340 | "pyx": "py", 341 | "whl": "py", 342 | "rdata": "r", 343 | "rds": "r", 344 | "rmd": "r", 345 | "gemfile": "rb", 346 | "gemspec": "rb", 347 | "guardfile": "rb", 348 | "procfile": "rb", 349 | "rakefile": "rb", 350 | "rspec": "rb", 351 | "rspec_parallel": "rb", 352 | "rspec_status": "rb", 353 | "ru": "rb", 354 | "erb": "rubydoc", 355 | "slim": "rubydoc", 356 | "awk": "shell", 357 | "bash": "shell", 358 | "bash_history": "shell", 359 | "bash_profile": "shell", 360 | "bashrc": "shell", 361 | "csh": "shell", 362 | "fish": "shell", 363 | "ksh": "shell", 364 | "sh": "shell", 365 | "zsh": "shell", 366 | "zsh-theme": "shell", 367 | "zshrc": "shell", 368 | "plpgsql": "sql", 369 | "plsql": "sql", 370 | "psql": "sql", 371 | "tsql": "sql", 372 | "sl3": "sqlite", 373 | "sqlite3": "sqlite", 374 | "stylus": "styl", 375 | "cls": "tex", 376 | "avi": "video", 377 | "flv": "video", 378 | "m2v": "video", 379 | "mkv": "video", 380 | "mov": "video", 381 | "mp4": "video", 382 | "mpeg": "video", 383 | "mpg": "video", 384 | "ogm": "video", 385 | "ogv": "video", 386 | "vob": "video", 387 | "webm": "video", 388 | "vimrc": "vim", 389 | "bat": "windows", 390 | "cmd": "windows", 391 | "exe": "windows", 392 | "csv": "xls", 393 | "gsheet": "xls", 394 | "xlsx": "xls", 395 | "plist": "xml", 396 | "xul": "xml", 397 | "yaml": "yml", 398 | "7z": "zip", 399 | "Z": "zip", 400 | "bz2": "zip", 401 | "gz": "zip", 402 | "lzma": "zip", 403 | "par": "zip", 404 | "rar": "zip", 405 | "tar": "zip", 406 | "tc": "zip", 407 | "tgz": "zip", 408 | "txz": "zip", 409 | "xz": "zip", 410 | "z": "zip", 411 | } 412 | 413 | var folders = map[string]string{ 414 | ".atom": "\ue764", 415 | ".aws": "\ue7ad", 416 | ".docker": "\ue7b0", 417 | ".gem": "\ue21e", 418 | ".git": "\ue5fb", 419 | ".git-credential-cache": "\ue5fb", 420 | ".github": "\ue5fd", 421 | ".npm": "\ue5fa", 422 | ".nvm": "\ue718", 423 | ".rvm": "\ue21e", 424 | ".Trash": "\uf1f8", 425 | ".vscode": "\ue70c", 426 | ".vim": "\ue62b", 427 | "config": "\ue5fc", 428 | "folder": "\uf07c", 429 | "hidden": "\uf023", 430 | "node_modules": "\ue5fa", 431 | } 432 | 433 | var otherIcons = map[string]string{ 434 | "link": "\uf0c1", 435 | "linkDir": "\uf0c1", 436 | "brokenLink": "\uf127", 437 | "device": "\uf0a0", 438 | "socket": "\uf1e6", 439 | "pipe": "\ufce3", 440 | } 441 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/acarl005/ls-go 2 | 3 | go 1.19 4 | 5 | require ( 6 | github.com/acarl005/textcol v0.0.0 7 | github.com/mattn/go-colorable v0.1.13 8 | github.com/willf/pad v0.0.0-20200313202418-172aa767f2a4 9 | golang.org/x/sys v0.0.0-20221010170243-090e33056c14 10 | gopkg.in/alecthomas/kingpin.v2 v2.2.6 11 | ) 12 | 13 | require ( 14 | github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d // indirect 15 | github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 // indirect 16 | github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect 17 | github.com/mattn/go-isatty v0.0.16 // indirect 18 | github.com/stretchr/testify v1.8.0 // indirect 19 | ) 20 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d h1:licZJFw2RwpHMqeKTCYkitsPqHNxTmd4SNR5r94FGM8= 2 | github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d/go.mod h1:asat636LX7Bqt5lYEZ27JNDcqxfjdBQuJ/MM4CN/Lzo= 3 | github.com/acarl005/textcol v0.0.0 h1:39UH8Ojpl8SMMKho1HgoQ8mQ7no4281u6SN/MyT5EU4= 4 | github.com/acarl005/textcol v0.0.0/go.mod h1:o8VbpDKrBLFfZtTo/AXk03Zn3dQHYOLJ8v//eaDtl78= 5 | github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM= 6 | github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= 7 | github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 h1:s6gZFSlWYmbqAuRjVTiNNhvNRfY2Wxp9nhfyel4rklc= 8 | github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE= 9 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 10 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 11 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 12 | github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= 13 | github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= 14 | github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= 15 | github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= 16 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 17 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 18 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 19 | github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= 20 | github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= 21 | github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 22 | github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= 23 | github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= 24 | github.com/willf/pad v0.0.0-20200313202418-172aa767f2a4 h1:Y+IMUhhlO9FLTZpNrUAMWOr7Lh0tHDKu0nrDVhp6A7o= 25 | github.com/willf/pad v0.0.0-20200313202418-172aa767f2a4/go.mod h1:+pVHwmjc9CH7ugBFxESIwQkXkVj0gUj4cFp63TLwP1Y= 26 | golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 27 | golang.org/x/sys v0.0.0-20221010170243-090e33056c14 h1:k5II8e6QD8mITdi+okbbmR/cIyEbeXLBhy5Ha4nevyc= 28 | golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 29 | gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc= 30 | gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= 31 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 32 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 33 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 34 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 35 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 36 | -------------------------------------------------------------------------------- /img/demo-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/img/demo-1.png -------------------------------------------------------------------------------- /img/demo-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/img/demo-2.png -------------------------------------------------------------------------------- /img/demo-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/img/demo-3.png -------------------------------------------------------------------------------- /img/demo-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/img/demo-4.png -------------------------------------------------------------------------------- /img/ls-go.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/img/ls-go.png -------------------------------------------------------------------------------- /img/warp-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acarl005/ls-go/29066878b772c55ce6347eed04859e2a1338872b/img/warp-logo.png -------------------------------------------------------------------------------- /ls-go.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "io/ioutil" 6 | "math" 7 | "os" 8 | "path" 9 | "path/filepath" 10 | "regexp" 11 | "sort" 12 | "strconv" 13 | "strings" 14 | "time" 15 | 16 | "github.com/acarl005/textcol" 17 | colorable "github.com/mattn/go-colorable" 18 | "github.com/willf/pad" 19 | kingpin "gopkg.in/alecthomas/kingpin.v2" 20 | ) 21 | 22 | const VERSION = "1.0.1" 23 | 24 | // Wraps the file stat info and string to be printed. 25 | type DisplayItem struct { 26 | display string 27 | info os.FileInfo 28 | basename string 29 | ext string 30 | link *LinkInfo 31 | } 32 | 33 | func (item DisplayItem) Filename() string { 34 | return item.basename + "." + item.ext 35 | } 36 | 37 | func (item DisplayItem) IsHidden() bool { 38 | return item.basename == "" || item.basename[0] == '.' 39 | } 40 | 41 | // Wraps link stat info and whether the link points to valid file. 42 | type LinkInfo struct { 43 | path string 44 | info os.FileInfo 45 | broken bool 46 | } 47 | 48 | var ( 49 | // True is a helper varable to help make pointers to `true`. 50 | True = true 51 | // Prefixes for metric units. 52 | sizeUnits = []string{"B", "K", "M", "G", "T", "P", "E"} 53 | // Uses the "reference time" 54 | // https://golang.org/pkg/time/#Time.Format 55 | dateFormat = "02.Jan'06" 56 | timeFormat = "15:04" 57 | // Keeps track of execution time. 58 | start int64 59 | // Write to this to allow ANSI color codes to be compatible on Windows. 60 | stdout = colorable.NewColorableStdout() 61 | ) 62 | 63 | func main() { 64 | textcol.Output = stdout 65 | 66 | start = time.Now().UnixNano() 67 | // auto-generate help text for the command with -h 68 | kingpin.CommandLine.HelpFlag.Short('h') 69 | 70 | // parse the arguments and populate the struct 71 | kingpin.Parse() 72 | argsPostParse() 73 | 74 | if *args.version { 75 | fmt.Println("v" + VERSION) 76 | return 77 | } 78 | 79 | generateColors() 80 | 81 | // separate the directories from the regular files 82 | dirs := []string{} 83 | files := []os.FileInfo{} 84 | for _, pathStr := range *args.paths { 85 | fileStat, err := os.Stat(pathStr) 86 | if err != nil && strings.Contains(err.Error(), "no such file or directory") { 87 | printErrorHeader(err, prettifyPath(pathStr)) 88 | continue 89 | } else { 90 | check(err) 91 | } 92 | if fileStat.IsDir() { 93 | dirs = append(dirs, pathStr) 94 | } else { 95 | files = append(files, fileStat) 96 | } 97 | } 98 | 99 | // list files first 100 | if len(files) > 0 { 101 | pwd := os.Getenv("PWD") 102 | listFiles(pwd, &files, true) 103 | } 104 | 105 | // then list the contents of each directory 106 | for i, dir := range dirs { 107 | // print a blank line between directories, but not before the first one 108 | if i > 0 { 109 | fmt.Fprintln(stdout, "") 110 | } 111 | listDir(dir) 112 | } 113 | } 114 | 115 | func listDir(pathStr string) { 116 | items, err := ioutil.ReadDir(pathStr) 117 | // if we couldn't read the folder, print a "header" with error message and use error-looking colors 118 | if err != nil { 119 | if strings.Contains(err.Error(), "no such file or directory") || strings.Contains(err.Error(), "permission denied") { 120 | printErrorHeader(err, prettifyPath(pathStr)) 121 | return 122 | } 123 | check(err) 124 | } 125 | 126 | // filter by the regexp if one was passed 127 | if len(*args.find) > 0 { 128 | filteredItems := []os.FileInfo{} 129 | for _, fileInfo := range items { 130 | re, err := regexp.Compile(*args.find) 131 | check(err) 132 | if re.MatchString(fileInfo.Name()) { 133 | filteredItems = append(filteredItems, fileInfo) 134 | } 135 | } 136 | items = filteredItems 137 | } 138 | 139 | if !(len(*args.find) > 0 && len(items) == 0) && 140 | !(len(*args.paths) == 1 && (*args.paths)[0] == "." && !*args.recurse) { 141 | printFolderHeader(pathStr) 142 | } 143 | 144 | if len(items) > 0 { 145 | listFiles(pathStr, &items, false) 146 | } 147 | 148 | if *args.recurse { 149 | for _, item := range items { 150 | if item.IsDir() && (item.Name()[0] != '.' || *args.all) { 151 | fmt.Fprintln(stdout, "") // put a blank line between directories 152 | listDir(path.Join(pathStr, item.Name())) 153 | } 154 | } 155 | } 156 | } 157 | 158 | func listFiles(parentDir string, items *[]os.FileInfo, forceDotfiles bool) { 159 | absPath, err := filepath.Abs(parentDir) 160 | check(err) 161 | 162 | // collect all the contents here 163 | files := []*DisplayItem{} 164 | dirs := []*DisplayItem{} 165 | 166 | // to help with formatting, we need to know the length of the longest name to add appropriate padding 167 | longestOwnerName := 0 168 | longestGroupName := 0 169 | if *args.owner { 170 | for _, fileInfo := range *items { 171 | owner, group := getOwnerAndGroup(&fileInfo) 172 | longestOwnerName = max(longestOwnerName, len(owner)) 173 | longestGroupName = max(longestGroupName, len(group)) 174 | } 175 | } 176 | 177 | for _, fileInfo := range *items { 178 | // if this is a dotfile (hidden file) 179 | if fileInfo.Name()[0] == '.' { 180 | // we can skip everything with this file if we aren't using the `all` option 181 | if !*args.all && !forceDotfiles { 182 | continue 183 | } 184 | } 185 | 186 | basename, ext := splitExt(fileInfo.Name()) 187 | 188 | displayItem := DisplayItem{ 189 | info: fileInfo, 190 | ext: ext, 191 | basename: basename, 192 | } 193 | 194 | // read some info about linked file if this item is a symlink 195 | if fileInfo.Mode()&os.ModeSymlink != 0 { 196 | getLinkInfo(&displayItem, absPath) 197 | } 198 | 199 | if fileInfo.IsDir() || (fileInfo.Mode()&os.ModeSymlink != 0 && 200 | displayItem.link.info != nil && 201 | displayItem.link.info.IsDir()) { 202 | if *args.files { 203 | continue 204 | } else { 205 | dirs = append(dirs, &displayItem) 206 | } 207 | } else { 208 | if *args.dirs { 209 | continue 210 | } else { 211 | files = append(files, &displayItem) 212 | } 213 | } 214 | 215 | owner, group := getOwnerAndGroup(&fileInfo) 216 | ownerColor, groupColor := getOwnerAndGroupColors(owner, group) 217 | 218 | if *args.perms { 219 | displayItem.display += permString(fileInfo, ownerColor, groupColor) 220 | } 221 | 222 | if *args.owner { 223 | paddedOwner := pad.Right(owner, longestOwnerName, " ") 224 | ownerInfo := []string{Reset + ownerColor + paddedOwner} 225 | if !*args.nogroup { 226 | paddedGroup := pad.Right(group, longestGroupName, " ") 227 | ownerInfo = append(ownerInfo, groupColor+paddedGroup) 228 | } 229 | ownerInfo = append(ownerInfo, Reset) 230 | displayItem.display += strings.Join(ownerInfo, " ") 231 | } 232 | 233 | if *args.bytes { 234 | if fileInfo.Mode()&os.ModeDevice != 0 { 235 | displayItem.display += deviceNumbers(path.Join(absPath, fileInfo.Name())) 236 | } else { 237 | displayItem.display += sizeString(fileInfo.Size()) 238 | } 239 | } 240 | 241 | if *args.mdate { 242 | displayItem.display += timeString(fileInfo.ModTime()) 243 | } 244 | 245 | displayItem.display += nameString(&displayItem) 246 | 247 | if *args.links && fileInfo.Mode()&os.ModeSymlink != 0 { 248 | displayItem.display += linkString(&displayItem, absPath) 249 | } 250 | } 251 | 252 | if *args.sortTime { 253 | sort.Sort(ByTime(dirs)) 254 | sort.Sort(ByTime(files)) 255 | if *args.backwards { 256 | reverse(dirs) 257 | reverse(files) 258 | } 259 | } 260 | 261 | if *args.sortSize { 262 | sort.Sort(BySize(files)) 263 | if *args.backwards { 264 | reverse(files) 265 | } 266 | } 267 | 268 | if *args.sortKind { 269 | sort.Sort(ByKind(files)) 270 | if *args.backwards { 271 | reverse(files) 272 | } 273 | } 274 | 275 | // combine the items together again after sorting 276 | allItems := append(dirs, files...) 277 | 278 | // if using "long" display, just print one item per line 279 | if *args.bytes || *args.mdate || *args.owner || *args.perms || *args.long { 280 | for _, item := range allItems { 281 | fmt.Fprintln(stdout, item.display) 282 | } 283 | } else { 284 | // but if not, try to format in columns, link `ls` would 285 | strs := []string{} 286 | for _, item := range allItems { 287 | strs = append(strs, item.display) 288 | } 289 | textcol.PrintColumns(&strs, 2) 290 | } 291 | 292 | if *args.stats { 293 | printStats(len(files), len(dirs)) 294 | } 295 | } 296 | 297 | func getLinkInfo(item *DisplayItem, absPath string) { 298 | fullPath := path.Join(absPath, item.info.Name()) 299 | linkPath, err1 := os.Readlink(fullPath) 300 | check(err1) 301 | 302 | linkFullPath := linkPath 303 | if linkPath[0] != '/' { 304 | linkFullPath = path.Join(absPath, linkPath) 305 | } 306 | 307 | linkInfo, err2 := os.Stat(linkFullPath) 308 | if *args.linkRel { 309 | linkRel, _ := filepath.Rel(absPath, linkPath) 310 | if linkRel != "" && len(linkRel) <= len(linkPath) { 311 | // i prefer the look of these relative paths prepended with ./ 312 | if linkRel[0] != '.' { 313 | linkPath = "./" + linkRel 314 | } else { 315 | linkPath = linkRel 316 | } 317 | } 318 | } 319 | 320 | link := LinkInfo{ 321 | path: linkPath, 322 | } 323 | item.link = &link 324 | if linkInfo != nil { 325 | link.info = linkInfo 326 | } else if strings.Contains(err2.Error(), "no such file or directory") { 327 | link.broken = true 328 | } else if !strings.Contains(err2.Error(), "permission denied") { 329 | check(err2) 330 | } 331 | } 332 | 333 | func nameString(item *DisplayItem) string { 334 | mode := item.info.Mode() 335 | name := item.info.Name() 336 | if mode&os.ModeDir != 0 { 337 | return dirString(item) 338 | } else if mode&os.ModeSymlink != 0 { 339 | if !item.link.broken && item.link.info.IsDir() { 340 | color := ConfigColor["link"]["nameDir"] 341 | if *args.nerdfont { 342 | var linkIcon string 343 | if item.link.broken { 344 | linkIcon = otherIcons["brokenLink"] 345 | } else { 346 | linkIcon = otherIcons["linkDir"] 347 | } 348 | return color + linkIcon + " " + name + " " + Reset 349 | } else if *args.icons { 350 | return color + "🔗 " + name + " " + Reset 351 | } else { 352 | return color + " " + name + " " + Reset 353 | } 354 | } else { 355 | color := ConfigColor["link"]["name"] 356 | if *args.nerdfont { 357 | var linkIcon string 358 | if item.link.broken { 359 | linkIcon = otherIcons["brokenLink"] 360 | } else { 361 | linkIcon = otherIcons["link"] 362 | } 363 | return color + linkIcon + " " + name + " " + Reset 364 | } else if *args.icons { 365 | return color + "🔗 " + name + " " + Reset 366 | } else { 367 | return color + " " + name + " " + Reset 368 | } 369 | } 370 | } else if mode&os.ModeDevice != 0 { 371 | color := ConfigColor["device"]["name"] 372 | if *args.nerdfont { 373 | return color + otherIcons["device"] + " " + name + " " + Reset 374 | } else if *args.icons { 375 | return color + "💽 " + name + " " + Reset 376 | } else { 377 | return color + " " + name + " " + Reset 378 | } 379 | } else if mode&os.ModeNamedPipe != 0 { 380 | color := ConfigColor["pipe"]["name"] 381 | if *args.nerdfont { 382 | return color + otherIcons["pipe"] + " " + name + " " + Reset 383 | } else if *args.icons { 384 | return color + "🛢 " + name + " " + Reset 385 | } else { 386 | return color + " " + name + " " + Reset 387 | } 388 | } else if mode&os.ModeSocket != 0 { 389 | color := ConfigColor["socket"]["name"] 390 | if *args.nerdfont { 391 | return color + otherIcons["socket"] + " " + name + " " + Reset 392 | } else if *args.icons { 393 | return color + "🔌 " + name + " " + Reset 394 | } else { 395 | return color + " " + name + " " + Reset 396 | } 397 | } 398 | return fileString(item) 399 | } 400 | 401 | func linkString(item *DisplayItem, absPath string) string { 402 | colors := ConfigColor["link"] 403 | displayStrings := []string{} 404 | if item.link.info == nil && item.link.broken { 405 | displayStrings = append(displayStrings, colors["broken"]+"►", item.link.path+Reset) 406 | } else if item.link.info != nil { 407 | linkname, linkext := splitExt(item.link.path) 408 | displayItem := DisplayItem{ 409 | info: item.link.info, 410 | basename: linkname, 411 | ext: linkext, 412 | } 413 | arrowColor := colors["arrow"] 414 | if displayItem.info.IsDir() { 415 | arrowColor = colors["arrowDir"] 416 | } 417 | displayStrings = append(displayStrings, arrowColor+"►", nameString(&displayItem)) 418 | } else { 419 | displayStrings = append(displayStrings, item.link.path) 420 | } 421 | return strings.Join(displayStrings, " ") 422 | } 423 | 424 | func fileString(item *DisplayItem) string { 425 | key := strings.ToLower(item.ext) 426 | // figure out which color to choose 427 | colors := FileColor["_default"] 428 | alias, hasAlias := FileAliases[key] 429 | if hasAlias { 430 | key = alias 431 | } 432 | betterColor, hasBetterColor := FileColor[key] 433 | if hasBetterColor { 434 | colors = betterColor 435 | } 436 | 437 | ext := item.ext 438 | if ext != "" { 439 | ext = "." + ext 440 | } 441 | 442 | mainColor := colors.light 443 | accentColor := colors.dark 444 | if *args.light && colors.themeSwitch { 445 | mainColor = colors.dark 446 | accentColor = colors.light 447 | } 448 | // in some cases files have icons if front 449 | // if nerd font enabled, then it'll be a file-specific icon, or if its an executable script, a little shell icon 450 | // if the regular --icons flag is used instead, then it will show a ">_" only if the file is executable 451 | icon := "" 452 | executable := isExecutableScript(item) 453 | if *args.nerdfont { 454 | if executable { 455 | icon = mainColor + getIconForFile("", "shell") + " " 456 | } else { 457 | icon = mainColor + getIconForFile(item.basename, item.ext) + " " 458 | } 459 | } else if *args.icons { 460 | if executable { 461 | icon = BgGray(1) + NamedFg(BrightGreen) + ">_" + Reset + " " 462 | } 463 | } else { 464 | icon = " " 465 | } 466 | 467 | displayStrings := []string{icon} 468 | 469 | if item.IsHidden() { 470 | displayStrings = append(displayStrings, accentColor, item.basename, ext, Reset) 471 | } else { 472 | displayStrings = append(displayStrings, mainColor, item.basename, accentColor, ext, Reset) 473 | } 474 | return strings.Join(displayStrings, "") 475 | } 476 | 477 | // check for executable permissions 478 | func isExecutableScript(item *DisplayItem) bool { 479 | if item.info.Mode()&0111 != 0 && item.info.Mode().IsRegular() { 480 | return true 481 | } 482 | return false 483 | } 484 | 485 | func dirString(item *DisplayItem) string { 486 | colors := ConfigColor["dir"] 487 | if item.basename == "" { 488 | colors = ConfigColor[".dir"] 489 | } 490 | displayStrings := []string{colors["name"]} 491 | icon := "" 492 | if *args.icons { 493 | displayStrings = append(displayStrings, "📂 ") 494 | } else if *args.nerdfont { 495 | icon = getIconForFolder(item.info.Name()) + " " 496 | displayStrings = append(displayStrings, icon) 497 | } else { 498 | displayStrings = append(displayStrings, " ") 499 | } 500 | ext := item.ext 501 | if ext != "" { 502 | ext = "." + ext 503 | } 504 | displayStrings = append(displayStrings, item.basename, colors["ext"], ext, " ", Reset) 505 | return strings.Join(displayStrings, "") 506 | } 507 | 508 | func rwxString(mode os.FileMode, i uint, color string) string { 509 | bits := mode >> (i * 3) 510 | coloredStrings := []string{color} 511 | if bits&4 != 0 { 512 | coloredStrings = append(coloredStrings, "r") 513 | } else { 514 | coloredStrings = append(coloredStrings, "-") 515 | } 516 | if bits&2 != 0 { 517 | coloredStrings = append(coloredStrings, "w") 518 | } else { 519 | coloredStrings = append(coloredStrings, "-") 520 | } 521 | if i == 0 && mode&os.ModeSticky != 0 { 522 | if bits&1 != 0 { 523 | coloredStrings = append(coloredStrings, "t") 524 | } else { 525 | coloredStrings = append(coloredStrings, "T") 526 | } 527 | } else { 528 | if bits&1 != 0 { 529 | coloredStrings = append(coloredStrings, "x") 530 | } else { 531 | coloredStrings = append(coloredStrings, "-") 532 | } 533 | } 534 | return strings.Join(coloredStrings, "") 535 | } 536 | 537 | // generates the permissions string, ya know like "drwxr-xr-x" and stuff like that 538 | func permString(info os.FileInfo, ownerColor string, groupColor string) string { 539 | defaultColor := PermsColor["other"]["_default"] 540 | 541 | // info.Mode().String() does not produce the same output as `ls`, so we must build that string manually 542 | mode := info.Mode() 543 | // this "type" is not the file extension, but type as far as the OS is concerned 544 | filetype := "-" 545 | if mode&os.ModeDir != 0 { 546 | filetype = "d" 547 | } else if mode&os.ModeSymlink != 0 { 548 | filetype = "l" 549 | } else if mode&os.ModeDevice != 0 { 550 | if mode&os.ModeCharDevice == 0 { 551 | filetype = "b" // block device 552 | } else { 553 | filetype = "c" // character device 554 | } 555 | } else if mode&os.ModeNamedPipe != 0 { 556 | filetype = "p" 557 | } else if mode&os.ModeSocket != 0 { 558 | filetype = "s" 559 | } 560 | coloredStrings := []string{defaultColor, filetype, " "} 561 | coloredStrings = append(coloredStrings, rwxString(mode, 2, ownerColor)) 562 | coloredStrings = append(coloredStrings, rwxString(mode, 1, groupColor)) 563 | coloredStrings = append(coloredStrings, rwxString(mode, 0, defaultColor), Reset, " ") 564 | return strings.Join(coloredStrings, "") 565 | } 566 | 567 | // Convert an integer number of bytes to a human-readable string using metric units with IEC binary 568 | // prefixes, e.g. 10240 becomes "10 KiB", but we only show 1-letter units like "K". 569 | func sizeString(size int64) string { 570 | sizeFloat := float64(size) 571 | for i, unit := range sizeUnits { 572 | base := math.Pow(1024, float64(i)) 573 | if sizeFloat < base*1024 { 574 | var sizeStr string 575 | if i == 0 { 576 | sizeStr = strconv.FormatInt(size, 10) 577 | } else { 578 | value := sizeFloat / base 579 | if value < 1000 { 580 | sizeStr = fmt.Sprintf("%.2f", value) 581 | } else { 582 | sizeStr = fmt.Sprintf("%.1f", value) 583 | } 584 | } 585 | return SizeColor[unit] + pad.Left(sizeStr, 6, " ") + unit + " " + Reset 586 | } 587 | } 588 | return strconv.Itoa(int(size)) 589 | } 590 | 591 | func timeString(modtime time.Time) string { 592 | dateStr := modtime.Format(dateFormat) 593 | timeStr := modtime.Format(timeFormat) 594 | hour, err := strconv.Atoi(timeStr[0:2]) 595 | check(err) 596 | // Generate a color based on the hour of the day. darkest at midnight and lightest at noon. 597 | timeColor := 14 - int(8*math.Cos(math.Pi*float64(hour)/12)) 598 | colored := []string{FgGray(22) + dateStr, FgGray(timeColor) + timeStr, Reset} 599 | return strings.Join(colored, " ") 600 | } 601 | 602 | // When we list out any subdirectories, print those paths conspicuously above the contents. This helps with 603 | // visual separation. 604 | func printFolderHeader(pathStr string) { 605 | colors := ConfigColor["folderHeader"] 606 | headerString := colors["arrow"] + "►" + colors["main"] + " " 607 | prettyPath := prettifyPath(pathStr) 608 | 609 | if prettyPath == "/" { 610 | headerString += "/" 611 | } else { 612 | folders := strings.Split(prettyPath, "/") 613 | coloredFolders := make([]string, 0, len(folders)) 614 | for i, folder := range folders { 615 | // Use different color for the last folder in the path. 616 | if i == len(folders)-1 { 617 | coloredFolders = append(coloredFolders, colors["lastFolder"]+folder) 618 | } else { 619 | coloredFolders = append(coloredFolders, colors["main"]+folder) 620 | } 621 | } 622 | headerString += strings.Join(coloredFolders, colors["slash"]+"/") 623 | } 624 | 625 | fmt.Fprintln(stdout, headerString+" "+Reset) 626 | } 627 | 628 | func printErrorHeader(err error, pathStr string) { 629 | fmt.Fprintln(stdout, ConfigColor["folderHeader"]["error"]+"► "+pathStr+Reset) 630 | fmt.Fprintln(stdout, err.Error()) 631 | } 632 | 633 | func prettifyPath(pathStr string) string { 634 | prettyPath, err := filepath.Abs(pathStr) 635 | check(err) 636 | pwd := os.Getenv("PWD") 637 | home := os.Getenv("HOME") 638 | 639 | if strings.HasPrefix(prettyPath, pwd) { 640 | prettyPath = "." + prettyPath[len(pwd):] 641 | } else if strings.HasPrefix(prettyPath, home) { 642 | prettyPath = "~" + prettyPath[len(home):] 643 | } 644 | return prettyPath 645 | } 646 | 647 | func getOwnerAndGroupColors(owner string, group string) (string, string) { 648 | if owner == os.Getenv("USER") { 649 | owner = "_self" 650 | } 651 | ownerColor := PermsColor["user"][owner] 652 | if ownerColor == "" { 653 | ownerColor = PermsColor["user"]["_default"] 654 | } 655 | groupColor := PermsColor["group"][group] 656 | if groupColor == "" { 657 | groupColor = PermsColor["group"]["_default"] 658 | } 659 | return ownerColor, groupColor 660 | } 661 | 662 | func printStats(numFiles, numDirs int) { 663 | colors := ConfigColor["stats"] 664 | end := time.Now().UnixNano() 665 | microSeconds := (end - start) / int64(time.Microsecond) 666 | milliSeconds := float64(microSeconds) / 1000 667 | statStrings := []string{ 668 | colors["text"], 669 | colors["number"] + strconv.Itoa(numDirs), 670 | colors["text"] + "dirs", 671 | colors["number"] + strconv.Itoa(numFiles), 672 | colors["text"] + "files", 673 | colors["ms"] + fmt.Sprintf("%.2f", milliSeconds), 674 | colors["text"] + "ms", 675 | Reset, 676 | } 677 | fmt.Fprintln(stdout, strings.Join(statStrings, " ")) 678 | } 679 | 680 | func splitExt(filename string) (basepath, ext string) { 681 | basename := filepath.Base(filename) 682 | ext = filepath.Ext(filename) 683 | basepath = strings.TrimSuffix(basename, ext) 684 | if len(ext) > 0 { 685 | ext = ext[1:] 686 | } 687 | return 688 | } 689 | 690 | // Go doesn't provide a `Max` function for ints like it does for floats (wtf?) 691 | func max(a int, b int) int { 692 | if a > b { 693 | return a 694 | } 695 | return b 696 | } 697 | 698 | func check(err error) { 699 | if err != nil { 700 | panic(err) 701 | } 702 | } 703 | -------------------------------------------------------------------------------- /ls-unix.go: -------------------------------------------------------------------------------- 1 | //go:build !windows 2 | 3 | package main 4 | 5 | import ( 6 | "fmt" 7 | "os" 8 | "os/user" 9 | "strconv" 10 | "strings" 11 | "syscall" 12 | 13 | "github.com/willf/pad" 14 | "golang.org/x/sys/unix" 15 | ) 16 | 17 | func getOwnerAndGroup(fileInfo *os.FileInfo) (string, string) { 18 | statT := (*fileInfo).Sys().(*syscall.Stat_t) 19 | uid := fmt.Sprint(statT.Uid) 20 | gid := fmt.Sprint(statT.Gid) 21 | owner, err := user.LookupId(uid) 22 | var ownerName string 23 | if err == nil { 24 | ownerName = owner.Username 25 | } else { 26 | ownerName = uid 27 | } 28 | 29 | group, err := user.LookupGroupId(gid) 30 | var groupName string 31 | if err == nil { 32 | groupName = group.Name 33 | } else { 34 | groupName = gid 35 | } 36 | return ownerName, groupName 37 | } 38 | 39 | func deviceNumbers(absPath string) string { 40 | stat := syscall.Stat_t{} 41 | err := syscall.Stat(absPath, &stat) 42 | check(err) 43 | major := strconv.FormatInt(int64(unix.Major(uint64(stat.Rdev))), 10) 44 | minor := strconv.FormatInt(int64(unix.Minor(uint64(stat.Rdev))), 10) 45 | return pad.Left(strings.Join([]string{major, minor}, ","), 7, " ") + " " + Reset 46 | } 47 | -------------------------------------------------------------------------------- /ls-windows.go: -------------------------------------------------------------------------------- 1 | //go:build windows 2 | 3 | package main 4 | 5 | import ( 6 | "os" 7 | "strconv" 8 | "strings" 9 | "syscall" 10 | "unsafe" 11 | 12 | "github.com/willf/pad" 13 | "golang.org/x/sys/windows" 14 | ) 15 | 16 | var ( 17 | libadvapi32 = syscall.NewLazyDLL("advapi32.dll") 18 | procGetFileSecurity = libadvapi32.NewProc("GetFileSecurityW") 19 | procGetSecurityDescriptorOwner = libadvapi32.NewProc("GetSecurityDescriptorOwner") 20 | ) 21 | 22 | func getOwnerAndGroup(fileInfo *os.FileInfo) (string, string) { 23 | path := (*fileInfo).Name() 24 | 25 | var needed uint32 26 | procGetFileSecurity.Call( 27 | uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(path))), 28 | 0x00000001, /* OWNER_SECURITY_INFORMATION */ 29 | 0, 30 | 0, 31 | uintptr(unsafe.Pointer(&needed))) 32 | buf := make([]byte, needed) 33 | r1, _, err := procGetFileSecurity.Call( 34 | uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(path))), 35 | 0x00000001, /* OWNER_SECURITY_INFORMATION */ 36 | uintptr(unsafe.Pointer(&buf[0])), 37 | uintptr(needed), 38 | uintptr(unsafe.Pointer(&needed))) 39 | if r1 == 0 && err != nil { 40 | return "", "" 41 | } 42 | var ownerDefaulted uint32 43 | var sid *syscall.SID 44 | r1, _, err = procGetSecurityDescriptorOwner.Call( 45 | uintptr(unsafe.Pointer(&buf[0])), 46 | uintptr(unsafe.Pointer(&sid)), 47 | uintptr(unsafe.Pointer(&ownerDefaulted))) 48 | if r1 == 0 && err != nil { 49 | return "", "" 50 | } 51 | uid, gid, _, err := sid.LookupAccount("") 52 | if r1 == 0 && err != nil { 53 | return "", "" 54 | } 55 | return uid, gid 56 | } 57 | 58 | func deviceNumbers(absPath string) string { 59 | stat := syscall.Stat_t{} 60 | err := syscall.Stat(absPath, &stat) 61 | check(err) 62 | major := strconv.FormatInt(int64(windows.Major(uint64(stat.Rdev))), 10) 63 | minor := strconv.FormatInt(int64(windows.Minor(uint64(stat.Rdev))), 10) 64 | return pad.Left(strings.Join([]string{major, minor}, ","), 7, " ") + " " + Reset 65 | } 66 | -------------------------------------------------------------------------------- /release.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -ex 3 | 4 | if ! command -v gh >/dev/null; then 5 | echo must install gh 6 | echo brew install gh 7 | exit 1 8 | fi 9 | 10 | TAG=$(grep 'VERSION =' ls-go.go | grep -oE '\d+\.\d+.\d+') 11 | 12 | git tag --force latest 13 | git tag -a "v$TAG" -m "release v$TAG" 14 | 15 | git push origin master --tags --force 16 | 17 | ./compile 18 | 19 | gh release create "v$TAG" 20 | gh release upload "v$TAG" ls-go-* 21 | -------------------------------------------------------------------------------- /snap/snapcraft.yaml: -------------------------------------------------------------------------------- 1 | name: ls-go 2 | version: git 3 | summary: A more colorful, user-friendly implementation of `ls` written in Go 4 | license: MIT 5 | description: | 6 | You want to be able to glean a lot of information as quickly as possible from `ls`. 7 | Colors can help your mind parse the information. 8 | You can configure `ls` to color the output a little bit. 9 | Configuring `ls` is a hassle though, and the colors are limited. 10 | Instead, you can use `ls-go`. It is highly colored by default. 11 | It has much fewer flags so you can get the behavior you want more easily. 12 | The colors are beautiful and semantic. A terminal with xterm-256 colors is _required_. 13 | source-code: https://github.com/acarl005/ls-go 14 | base: core22 15 | grade: stable 16 | confinement: classic 17 | 18 | apps: 19 | ls-go: 20 | command: bin/ls-go 21 | plugs: 22 | - home 23 | 24 | architectures: 25 | - build-on: amd64 26 | - build-on: arm64 27 | - build-on: i368 28 | 29 | parts: 30 | ls-go: 31 | plugin: go 32 | build-snaps: [go/latest/stable] 33 | source: https://github.com/acarl005/ls-go 34 | source-type: git 35 | -------------------------------------------------------------------------------- /sort.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | // BySize tells `sort.Sort` how to sort by file size 4 | type BySize []*DisplayItem 5 | 6 | func (s BySize) Less(i, j int) bool { 7 | return s[i].info.Size() < s[j].info.Size() 8 | } 9 | func (s BySize) Len() int { 10 | return len(s) 11 | } 12 | func (s BySize) Swap(i, j int) { 13 | s[i], s[j] = s[j], s[i] 14 | } 15 | 16 | // ByTime tells `sort.Sort` how to sort by last modified time 17 | type ByTime []*DisplayItem 18 | 19 | func (s ByTime) Less(i, j int) bool { 20 | return s[i].info.ModTime().Unix() < s[j].info.ModTime().Unix() 21 | } 22 | func (s ByTime) Len() int { 23 | return len(s) 24 | } 25 | func (s ByTime) Swap(i, j int) { 26 | s[i], s[j] = s[j], s[i] 27 | } 28 | 29 | // ByKind tells `sort.Sort` how to sort by file extension 30 | type ByKind []*DisplayItem 31 | 32 | func (s ByKind) Less(i, j int) bool { 33 | var kindi, kindj string 34 | 35 | if s[i].IsHidden() { 36 | kindi = "." + s[i].ext 37 | } else if s[i].ext == "" { 38 | kindi = "0" 39 | } else { 40 | kindi = s[i].ext 41 | } 42 | 43 | if s[j].IsHidden() { 44 | kindj = "." + s[j].ext 45 | } else if s[j].ext == "" { 46 | kindj = "0" 47 | } else { 48 | kindj = s[j].ext 49 | } 50 | 51 | if kindi == kindj { 52 | return s[i].basename < s[j].basename 53 | } 54 | return kindi < kindj 55 | } 56 | func (s ByKind) Len() int { 57 | return len(s) 58 | } 59 | func (s ByKind) Swap(i, j int) { 60 | s[i], s[j] = s[j], s[i] 61 | } 62 | 63 | func reverse(s []*DisplayItem) { 64 | for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 { 65 | s[i], s[j] = s[j], s[i] 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /test: -------------------------------------------------------------------------------- 1 | #/bin/bash 2 | 3 | # run this script with watchman: watchman-make -p '**/*.go' test --run './test' 4 | 5 | set -e 6 | 7 | go build 8 | 9 | ./ls-go "$@" example 10 | ./ls-go -a "$@" example 11 | ./ls-go -al "$@" example 12 | ./ls-go -ali "$@" example 13 | ./ls-go -alnkSr "$@" example 14 | ./ls-go -alnk "$@" notexist 15 | --------------------------------------------------------------------------------