From 7ba39795ab8702cfcc99fd83e7474ed0d532ed15 Mon Sep 17 00:00:00 2001 From: Rostislav Khlebnikov Date: Thu, 9 Feb 2023 15:52:34 -0800 Subject: [PATCH] Add --group-directories-first --- e2e_test.go | 10 ++- go.mod | 26 +++++-- go.sum | 19 ++--- internal/api/api.go | 9 ++- internal/dir/dir.go | 5 ++ internal/dir/formatterStuff.go | 133 +++++++++++++++++++++++---------- testdata/logo-ls--help.snap | 4 +- testdata/logo-ls-Ae.snap | 11 +++ testdata/logo-ls-Rae.snap | 32 ++++++++ testdata/logo-ls-Re.snap | 17 +++++ testdata/logo-ls-ae.snap | 13 ++++ testdata/logo-ls-ie.snap | 9 +++ testdata/logo-ls-re.snap | 9 +++ testdata/logo-ls-shRae.snap | 32 ++++++++ testdata/logo-ls-she.snap | 9 +++ 15 files changed, 276 insertions(+), 62 deletions(-) create mode 100644 testdata/logo-ls-Ae.snap create mode 100644 testdata/logo-ls-Rae.snap create mode 100644 testdata/logo-ls-Re.snap create mode 100644 testdata/logo-ls-ae.snap create mode 100644 testdata/logo-ls-ie.snap create mode 100644 testdata/logo-ls-re.snap create mode 100644 testdata/logo-ls-shRae.snap create mode 100644 testdata/logo-ls-she.snap diff --git a/e2e_test.go b/e2e_test.go index 9068191..61736c7 100644 --- a/e2e_test.go +++ b/e2e_test.go @@ -81,13 +81,21 @@ func TestE2E(t *testing.T) { }{ {args: []string{"-1"}, testFile: "logo-ls.snap", td: "Testing normal execution"}, {args: []string{"-1a"}, testFile: "logo-ls-a.snap", td: "Testing -a (all) execution"}, + {args: []string{"-1ae"}, testFile: "logo-ls-ae.snap", td: "Testing -ae (all) execution (group dirs)"}, {args: []string{"-1A"}, testFile: "logo-ls-A.snap", td: "Testing -A (almost all) execution"}, + {args: []string{"-1Ae"}, testFile: "logo-ls-Ae.snap", td: "Testing -Ae (almost all) execution (group dirs)"}, {args: []string{"-1i"}, testFile: "logo-ls-i.snap", td: "Testing -i (no icon) execution"}, + {args: []string{"-1ie"}, testFile: "logo-ls-ie.snap", td: "Testing -ie (no icon) execution (group dirs)"}, {args: []string{"-1r"}, testFile: "logo-ls-r.snap", td: "Testing -r (reverse) execution"}, + {args: []string{"-1re"}, testFile: "logo-ls-re.snap", td: "Testing -re (reverse) execution (group dirs)"}, {args: []string{"-1sh"}, testFile: "logo-ls-sh.snap", td: "Testing -sh (human readable size) execution"}, + {args: []string{"-1she"}, testFile: "logo-ls-she.snap", td: "Testing -she (human readable size) execution (group dirs)"}, {args: []string{"-1R"}, testFile: "logo-ls-R.snap", td: "Testing -R (recursive) execution"}, + {args: []string{"-1Re"}, testFile: "logo-ls-Re.snap", td: "Testing -Re (recursive) execution (group dirs)"}, {args: []string{"-1Ra"}, testFile: "logo-ls-Ra.snap", td: "Testing -Ra (recursive, all) execution"}, + {args: []string{"-1Rae"}, testFile: "logo-ls-Rae.snap", td: "Testing -Rae (recursive, all) execution (group dirs)"}, {args: []string{"-1shRa"}, testFile: "logo-ls-shRa.snap", td: "Testing -shRa execution"}, + {args: []string{"-1shRae"}, testFile: "logo-ls-shRae.snap", td: "Testing -shRae execution (group dirs)"}, {args: []string{"-V"}, testFile: "logo-ls-V.snap", td: "Testing -V option prints version"}, {args: []string{"-?"}, testFile: "logo-ls--help.snap", td: "Testing -? (help) prints help message"}, } @@ -119,7 +127,7 @@ func TestE2E(t *testing.T) { } if bytes.Compare(cmdData, fileData) != 0 { - t.Fatalf("expected output of the command:\n-----------\n%s\n=============\nbut got:\n-----------\n%s", fileData, cmdData) + t.Fatalf("expected output of the command with args %s:\n-----------\n%s\n=============\nbut got:\n-----------\n%s", test.args, fileData, cmdData) } }) } diff --git a/go.mod b/go.mod index 87c7deb..441faf9 100644 --- a/go.mod +++ b/go.mod @@ -1,16 +1,30 @@ module github.com/Yash-Handa/logo-ls -go 1.15 +go 1.18 require ( - github.com/Microsoft/go-winio v0.4.16 // indirect github.com/go-git/go-git/v5 v5.2.0 - github.com/imdario/mergo v0.3.11 // indirect - github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 // indirect github.com/mattn/go-colorable v0.1.7 github.com/pborman/getopt/v2 v2.0.0 - github.com/xanzy/ssh-agent v0.3.0 // indirect golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad +) + +require golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 // indirect + +require ( + github.com/Microsoft/go-winio v0.4.16 // indirect + github.com/emirpasic/gods v1.12.0 // indirect + github.com/go-git/gcfg v1.5.0 // indirect + github.com/go-git/go-billy/v5 v5.0.0 // indirect + github.com/imdario/mergo v0.3.11 // indirect + github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect + github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 // indirect + github.com/mattn/go-isatty v0.0.12 // indirect + github.com/mitchellh/go-homedir v1.1.0 // indirect + github.com/sergi/go-diff v1.1.0 // indirect + github.com/xanzy/ssh-agent v0.3.0 // indirect + golang.org/x/exp v0.0.0-20230206171751-46f607a40771 golang.org/x/net v0.0.0-20201224014010-6772e930b67b // indirect - golang.org/x/sys v0.0.0-20201223074533-0d417f636930 // indirect + golang.org/x/sys v0.1.0 // indirect + gopkg.in/warnings.v0 v0.1.2 // indirect ) diff --git a/go.sum b/go.sum index 4f785a4..ccd8eef 100644 --- a/go.sum +++ b/go.sum @@ -1,4 +1,3 @@ -github.com/Microsoft/go-winio v0.4.14 h1:+hMXMk01us9KgxGb7ftKQt2Xpf5hH/yky+TDA+qxleU= github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= github.com/Microsoft/go-winio v0.4.16 h1:FtSW/jqD+l4ba5iPBj9CODVtgfYAD8w2wS923g/cFDk= github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= @@ -14,7 +13,6 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg= github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= -github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BHsljHzVlRcyQhjrss6TZTdY2VfCqZPbv5k3iBFa2ZQ= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0= github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= @@ -26,16 +24,14 @@ github.com/go-git/go-git-fixtures/v4 v4.0.2-0.20200613231340-f56387b50c12 h1:PbK github.com/go-git/go-git-fixtures/v4 v4.0.2-0.20200613231340-f56387b50c12/go.mod h1:m+ICp2rF3jDhFgEZ/8yziagdT1C+ZpZcrJjappBCDSw= github.com/go-git/go-git/v5 v5.2.0 h1:YPBLG/3UK1we1ohRkncLjaXWLW+HKp5QNM/jTli2JgI= github.com/go-git/go-git/v5 v5.2.0/go.mod h1:kh02eMX+wdqqxgNMEyq8YgwlIOsDOa9homkUq1PoTMs= -github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/imdario/mergo v0.3.9 h1:UauaLniWCFHWd+Jp9oCEkTBj8VO/9DKg3PV3VCNMDIg= +github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= github.com/imdario/mergo v0.3.9/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.11 h1:3tnifQM4i+fbajXKBHXWEH+KvNHqojZ778UH75j3bGA= github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= -github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd h1:Coekwdh0v2wtGp9Gmz1Ze3eVRAWJMLokvN3QjdzCHLY= github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 h1:DowS9hvgyYSX4TO5NpyC606/Z4SxnNYbT+WX27or6Ck= github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= @@ -55,7 +51,6 @@ github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWb github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/pborman/getopt/v2 v2.0.0 h1:Tn8XVmhb93Wbc346Tk4P6KutfpMVp+iztUzkZrTSyB4= github.com/pborman/getopt/v2 v2.0.0/go.mod h1:4NtW75ny4eBw9fO1bhtNdYTlZKYX5/tBLtsOpwKIKd0= -github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -69,7 +64,6 @@ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/xanzy/ssh-agent v0.2.1 h1:TCbipTQL2JiiCprBWx9frJ2eJlCYT00NmctrHxVAr70= github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4= github.com/xanzy/ssh-agent v0.3.0 h1:wUMzuKtKilRgBAD1sUb8gOwwRr2FGoBVumcjoOACClI= github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0= @@ -78,31 +72,29 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad h1:DN0cp81fZ3njFcrLCytUHRSUkqBjfTo4Tx9RJTWs0EY= golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= +golang.org/x/exp v0.0.0-20230206171751-46f607a40771 h1:xP7rWLUr1e1n2xkK5YB4LI0hPEy3LJC6Wk+D4pGlOJg= +golang.org/x/exp v0.0.0-20230206171751-46f607a40771/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20200301022130-244492dfa37a h1:GuSPYbZzB5/dcLNCwLQLsg3obCJtX9IJhpXkvY7kzk0= golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201224014010-6772e930b67b h1:iFwSg7t5GZmB/Q5TjiEAsdoLDrdJRC1RiF2WhuV29Qw= golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190221075227-b4e8571b14e0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527 h1:uYVVQ9WP/Ds2ROhcaGPeIdVq0RIXVLwsHlnvJ+cT1So= golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201223074533-0d417f636930 h1:vRgIt+nup/B/BwIS0g2oC0haq0iqbV3ZA+u6+0TlNCo= -golang.org/x/sys v0.0.0-20201223074533-0d417f636930/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= @@ -114,7 +106,6 @@ gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/internal/api/api.go b/internal/api/api.go index 828155f..8a475a6 100644 --- a/internal/api/api.go +++ b/internal/api/api.go @@ -1,4 +1,4 @@ -//This file contains the cli API and configs it +// This file contains the cli API and configs it package api import ( @@ -38,6 +38,7 @@ const ( Flag_o Flag_g Flag_G + Flag_groupDirs ) // flagVector has all the options set in it. Each bit represent an option. @@ -88,6 +89,7 @@ func Bootstrap() { f_r := getopt.BoolLong("reverse", 'r', "reverse order while sorting") f_R := getopt.BoolLong("recursive", 'R', "list subdirectories recursively") f_T := getopt.EnumLong("time-style", 'T', []string{"Stamp", "StampMilli", "Kitchen", "ANSIC", "UnixDate", "RubyDate", "RFC1123", "RFC1123Z", "RFC3339", "RFC822", "RFC822Z", "RFC850"}, "Stamp", "time/date format with -l; see time-style below") + f_groupDirs := getopt.BoolLong("group-directories-first", 'e', "group directories before files") f_help := getopt.BoolLong("help", '?', "display this help and exit") f_V := getopt.BoolLong("version", 'V', "output version information and exit") @@ -133,6 +135,11 @@ func Bootstrap() { FlagVector |= Flag_r } + // set group directories first flag + if *f_groupDirs { + FlagVector |= Flag_groupDirs + } + // set recursion (-R) flag if *f_R { FlagVector |= Flag_R diff --git a/internal/dir/dir.go b/internal/dir/dir.go index c56f94c..3f8b13f 100644 --- a/internal/dir/dir.go +++ b/internal/dir/dir.go @@ -27,6 +27,7 @@ type file struct { name, ext, indicator string modTime time.Time size int64 // in bytes + isDir bool mode string modeBits uint32 owner, group string // use syscall package @@ -56,6 +57,7 @@ func New(d *os.File) (*dir, error) { // filing current dir info t.info = new(file) t.info.name = "." + t.info.isDir = true ds, err := d.Stat() if err != nil { return nil, err @@ -108,6 +110,7 @@ func New(d *os.File) (*dir, error) { f.indicator = getIndicator(v.Mode()) f.size = v.Size() f.modTime = v.ModTime() + f.isDir = v.IsDir() if long { f.mode = v.Mode().String() f.modeBits = uint32(v.Mode()) @@ -156,6 +159,7 @@ func New(d *os.File) (*dir, error) { t.parent.name = ".." t.parent.size = pds.Size() t.parent.modTime = pds.ModTime() + t.parent.isDir = true if long { t.parent.mode = pds.Mode().String() t.parent.modeBits = uint32(pds.Mode()) @@ -191,6 +195,7 @@ func New_ArgFiles(files []os.FileInfo) *dir { f.indicator = getIndicator(v.Mode()) f.size = v.Size() f.modTime = v.ModTime() + f.isDir = v.IsDir() if long { f.mode = v.Mode().String() f.modeBits = uint32(v.Mode()) diff --git a/internal/dir/formatterStuff.go b/internal/dir/formatterStuff.go index f9381da..c3dab3f 100644 --- a/internal/dir/formatterStuff.go +++ b/internal/dir/formatterStuff.go @@ -7,69 +7,124 @@ import ( "github.com/Yash-Handa/logo-ls/assets" "github.com/Yash-Handa/logo-ls/internal/api" + "golang.org/x/exp/constraints" ) -func mainSort(a, b string) bool { - switch a { - case ".", "..": - default: - a = strings.TrimPrefix(a, ".") +func threeWayCompare[K constraints.Ordered](i,j K) int { + if i < j { + return -1 + } + if j < i { + return 1 } - switch b { + return 0 +} + +func cleanupName(name string) string { + switch name { case ".", "..": default: - b = strings.TrimPrefix(b, ".") + name = strings.TrimPrefix(name, ".") + } + + return strings.ToLower(name) +} + +func indexCmp(d *dir, i, j int) int { + return threeWayCompare(i, j) +} + +func nameCmp(d *dir, i, j int) int { + return strings.Compare(cleanupName(d.files[i].name + d.files[i].ext), cleanupName(d.files[j].name + d.files[j].ext)) +} + +func naturalCmp(d *dir, i, j int) int { + return threeWayCompare(d.files[i].name + d.files[i].ext, d.files[j].name + d.files[j].ext) +} + +func extCmp(d *dir, i, j int) int { + return strings.Compare(cleanupName(d.files[i].ext), cleanupName(d.files[j].ext)) +} + +func sizeCmp(d *dir, i, j int) int { + // size comparison is largest first, so negate the result + return -threeWayCompare(d.files[i].size, d.files[j].size) +} + +func dirFlagCmp(d *dir, i, j int) int { + // directory flag compare, directories first + if d.files[i].isDir == d.files[j].isDir { + return 0 + } + if d.files[i].isDir { + return -1 } - return strings.ToLower(a) < strings.ToLower(b) + return 1 +} + +func dirFlagCmpReverse(d *dir, i, j int) int { + return -dirFlagCmp(d, i, j) } +func modTimeCmp(d *dir, i, j int) int { + if d.files[i].modTime.After(d.files[j].modTime) { + return -1 + } + if d.files[i].modTime.Before(d.files[j].modTime) { + return 1 + } + return 0 +} + +func doCompare(d *dir, i, j int, funcs [] func(d *dir, i,j int) int) bool { + for k := len(funcs)-1; k >= 0; k-- { + var result = funcs[k](d, i, j) + switch result { + case -1: return true + case 1: return false + case 0: // do nothing, go to the next comparator + } + } + return false +} + + // Custom less functions func lessFuncGenerator(d *dir) { + var compareFuncs = []func(d *dir, i,j int) int{} + switch { case (api.FlagVector & api.Flag_alpha) > 0: - // sort by alphabetical order of name.ext - d.less = func(i, j int) bool { - return mainSort(d.files[i].name+d.files[i].ext, d.files[j].name+d.files[j].ext) - } + compareFuncs = append(compareFuncs, nameCmp) case (api.FlagVector & api.Flag_S) > 0: // sort by file size, largest first - d.less = func(i, j int) bool { - if d.files[i].size > d.files[j].size { - return true - } else if d.files[i].size == d.files[j].size { - return mainSort(d.files[i].name+d.files[i].ext, d.files[j].name+d.files[j].ext) - } else { - return false - } - } + compareFuncs = append(compareFuncs, nameCmp, sizeCmp) case (api.FlagVector & api.Flag_t) > 0: // sort by modification time, newest first // not sorting by alphabetical order because equality is quite rare - d.less = func(i, j int) bool { - return d.files[i].modTime.After(d.files[j].modTime) - } + compareFuncs = append(compareFuncs, modTimeCmp) case (api.FlagVector & api.Flag_X) > 0: // sort alphabetically by entry extension - d.less = func(i, j int) bool { - if mainSort(d.files[i].ext, d.files[j].ext) { - return true - } else if strings.ToLower(d.files[i].ext) == strings.ToLower(d.files[j].ext) { - return mainSort(d.files[i].name+d.files[i].ext, d.files[j].name+d.files[j].ext) - } else { - return false - } - } + compareFuncs = append(compareFuncs, nameCmp, extCmp) case (api.FlagVector & api.Flag_v) > 0: // natural sort of (version) numbers within text - d.less = func(i, j int) bool { - return d.files[i].name+d.files[i].ext < d.files[j].name+d.files[j].ext - } + compareFuncs = append(compareFuncs, naturalCmp) default: - // no sorting - d.less = func(i, j int) bool { - return i < j + compareFuncs = append(compareFuncs, indexCmp) + } + + if (api.FlagVector & api.Flag_groupDirs) > 0 { + if (api.FlagVector & api.Flag_r) > 0 { + // Reverse the order of dir vs files if reverse flag is on + compareFuncs = append(compareFuncs, dirFlagCmpReverse) + } else { + compareFuncs = append(compareFuncs, dirFlagCmp) } } + + d.less = func(i, j int) bool { + return doCompare(d, i, j, compareFuncs) + } } // get Owner and Group info diff --git a/testdata/logo-ls--help.snap b/testdata/logo-ls--help.snap index ae75aff..b306f45 100644 --- a/testdata/logo-ls--help.snap +++ b/testdata/logo-ls--help.snap @@ -1,6 +1,6 @@ List information about the FILEs with ICONS and GIT STATUS (the current dir by default). Sort entries alphabetically if none of -tvSUX is specified. -Usage: logo-ls [-1?aAcdDgGhiloRrSstUvVX] [-T value] [files ...] +Usage: logo-ls [-1?aAcdDegGhiloRrSstUvVX] [-T value] [files ...] -1 list one file per line. -?, --help display this help and exit -a, --all do not ignore entries starting with . @@ -10,6 +10,8 @@ Usage: logo-ls [-1?aAcdDgGhiloRrSstUvVX] [-T value] [files ...] print to a file) -d, --directory list directories themselves, not their contents -D, --git-status print git status of files + -e, --group-directories-first + group directories before files -g like -l, but do not list owner -G, --no-group in a long listing, don't print group names -h, --human-readable diff --git a/testdata/logo-ls-Ae.snap b/testdata/logo-ls-Ae.snap new file mode 100644 index 0000000..189aec3 --- /dev/null +++ b/testdata/logo-ls-Ae.snap @@ -0,0 +1,11 @@ +⠀Downloads/ +⠀.privateDir/ +⠀testDir/ +ﳑ⠀1test.go +⠀2test.js +⠀3test.py +⠀abc.css +⠀abc.sass +⠀.abc.txt +⠀Dockerfile +נּ⠀test.routes.tsx diff --git a/testdata/logo-ls-Rae.snap b/testdata/logo-ls-Rae.snap new file mode 100644 index 0000000..255fff0 --- /dev/null +++ b/testdata/logo-ls-Rae.snap @@ -0,0 +1,32 @@ +ﱮ testdata/dirEnv: +ﱮ⠀. +ﱮ⠀.. +⠀Downloads/ +⠀.privateDir/ +⠀testDir/ +ﳑ⠀1test.go +⠀2test.js +⠀3test.py +⠀abc.css +⠀abc.sass +⠀.abc.txt +⠀Dockerfile +נּ⠀test.routes.tsx + +ﱮ testdata/dirEnv/.privateDir: +ﱮ⠀. +ﱮ⠀.. +ﳑ⠀1test.go +⠀2test.js +⠀abc.txt + +ﱮ testdata/dirEnv/Downloads: +ﱮ⠀. +ﱮ⠀.. + +ﱮ testdata/dirEnv/testDir: +ﱮ⠀. +ﱮ⠀.. +ﳑ⠀1test.go +⠀2test.js +⠀abc.txt diff --git a/testdata/logo-ls-Re.snap b/testdata/logo-ls-Re.snap new file mode 100644 index 0000000..72f2dc0 --- /dev/null +++ b/testdata/logo-ls-Re.snap @@ -0,0 +1,17 @@ +ﱮ testdata/dirEnv: +⠀Downloads/ +⠀testDir/ +ﳑ⠀1test.go +⠀2test.js +⠀3test.py +⠀abc.css +⠀abc.sass +⠀Dockerfile +נּ⠀test.routes.tsx + +ﱮ testdata/dirEnv/Downloads: + +ﱮ testdata/dirEnv/testDir: +ﳑ⠀1test.go +⠀2test.js +⠀abc.txt diff --git a/testdata/logo-ls-ae.snap b/testdata/logo-ls-ae.snap new file mode 100644 index 0000000..856d15e --- /dev/null +++ b/testdata/logo-ls-ae.snap @@ -0,0 +1,13 @@ +ﱮ⠀. +ﱮ⠀.. +⠀Downloads/ +⠀.privateDir/ +⠀testDir/ +ﳑ⠀1test.go +⠀2test.js +⠀3test.py +⠀abc.css +⠀abc.sass +⠀.abc.txt +⠀Dockerfile +נּ⠀test.routes.tsx diff --git a/testdata/logo-ls-ie.snap b/testdata/logo-ls-ie.snap new file mode 100644 index 0000000..c4a70b8 --- /dev/null +++ b/testdata/logo-ls-ie.snap @@ -0,0 +1,9 @@ +Downloads/ +testDir/ +1test.go +2test.js +3test.py +abc.css +abc.sass +Dockerfile +test.routes.tsx diff --git a/testdata/logo-ls-re.snap b/testdata/logo-ls-re.snap new file mode 100644 index 0000000..eadbe1f --- /dev/null +++ b/testdata/logo-ls-re.snap @@ -0,0 +1,9 @@ +⠀testDir/ +⠀Downloads/ +נּ⠀test.routes.tsx +⠀Dockerfile +⠀abc.sass +⠀abc.css +⠀3test.py +⠀2test.js +ﳑ⠀1test.go diff --git a/testdata/logo-ls-shRae.snap b/testdata/logo-ls-shRae.snap new file mode 100644 index 0000000..03bb5fe --- /dev/null +++ b/testdata/logo-ls-shRae.snap @@ -0,0 +1,32 @@ +ﱮ testdata/dirEnv: +4.0K⠀ﱮ⠀. +4.0K⠀ﱮ⠀.. +4.0K⠀⠀Downloads/ +4.0K⠀⠀.privateDir/ +4.0K⠀⠀testDir/ +4.0K⠀ﳑ⠀1test.go +4.0K⠀⠀2test.js +4.0K⠀⠀3test.py +4.0K⠀⠀abc.css +4.0K⠀⠀abc.sass +4.0K⠀⠀.abc.txt +4.0K⠀⠀Dockerfile +4.0K⠀נּ⠀test.routes.tsx + +ﱮ testdata/dirEnv/.privateDir: +4.0K⠀ﱮ⠀. +4.0K⠀ﱮ⠀.. +4.0K⠀ﳑ⠀1test.go +4.0K⠀⠀2test.js +4.0K⠀⠀abc.txt + +ﱮ testdata/dirEnv/Downloads: +4.0K⠀ﱮ⠀. +4.0K⠀ﱮ⠀.. + +ﱮ testdata/dirEnv/testDir: +4.0K⠀ﱮ⠀. +4.0K⠀ﱮ⠀.. +4.0K⠀ﳑ⠀1test.go +4.0K⠀⠀2test.js +4.0K⠀⠀abc.txt diff --git a/testdata/logo-ls-she.snap b/testdata/logo-ls-she.snap new file mode 100644 index 0000000..d12b4a3 --- /dev/null +++ b/testdata/logo-ls-she.snap @@ -0,0 +1,9 @@ +4.0K⠀⠀Downloads/ +4.0K⠀⠀testDir/ +4.0K⠀ﳑ⠀1test.go +4.0K⠀⠀2test.js +4.0K⠀⠀3test.py +4.0K⠀⠀abc.css +4.0K⠀⠀abc.sass +4.0K⠀⠀Dockerfile +4.0K⠀נּ⠀test.routes.tsx