7 Commits
Author SHA1 Message Date
Yash-Handa 4d775273cb tidy the module 2020-09-03 14:49:34 +05:30
Yash-Handa 474402d4f3 Added Complete git support !! 2020-09-03 14:45:31 +05:30
Yash-Handa 38d12c73ab Added git support to long and 1 format 2020-09-02 14:39:00 +05:30
Yash-Handa 8a44a87f95 Added basic git support 2020-09-02 14:31:49 +05:30
Yash-Handa 31972dd18f Added basic git support 2020-09-02 14:30:33 +05:30
Yash-Handa eea000f606 Added time formate flag 2020-08-30 14:25:02 +05:30
Yash-Handa 6679b87c63 Added Recursion 2020-08-30 12:48:45 +05:30
9 changed files with 626 additions and 97 deletions
+27 -1
View File
@@ -1,22 +1,48 @@
```txt
Usage: logo-ls [-1?aAdgGhlorSstUvVX] [files ...]
Usage: logo-ls [-1?aAcdDgGhiloRrSstUvVX] [-T value] [files ...]
-1 list one file per line.
-? display this help and exit
-a, --all do not ignore entries starting with .
-A, --almost-all do not list implied . and ..
-c, --disable-color
don't color icons, filenames and git status (use this to
print to a file)
-d, --directory list directories themselves, not their contents
-D, --disable-git-status
don't print git status of files, In recursive -R this flag
enables git-status
-g like -l, but do not list owner
-G, --no-group in a long listing, don't print group names
-h, --human-readable
with -l and -s, print sizes like 1K 234M 2G etc.
-i, --disable-icon
don't print icons of the files
-l use a long listing format
-o like -l, but do not list group information
-R, --recursive list subdirectories recursively, git-status is disabled by
default
-r, --reverse reverse order while sorting
-S sort by file size, largest first
-s, --size print the allocated size of each file, in blocks
-t sort by modification time, newest first
-T, --time-style=value
time/date format with -l; see time-style below [Stamp]
-U do not sort; list entries in directory order
-v natural sort of (version) numbers within text
-V, --version output version information and exit
-X sort alphabetically by entry extension
Possible value for --time-style (-T)
ANSIC "Mon Jan _2 15:04:05 2006"
UnixDate "Mon Jan _2 15:04:05 MST 2006"
RubyDate "Mon Jan 02 15:04:05 -0700 2006"
RFC822 "02 Jan 06 15:04 MST"
RFC822Z "02 Jan 06 15:04 -0700"
RFC850 "Monday, 02-Jan-06 15:04:05 MST"
RFC1123 "Mon, 02 Jan 2006 15:04:05 MST"
RFC1123Z "Mon, 02 Jan 2006 15:04:05 -0700"
RFC3339 "2006-01-02T15:04:05Z07:00"
Kitchen "3:04PM"
Stamp "Mon Jan _2 15:04:05" [Default]
StampMilli "Jan _2 15:04:05.000"
```
+122 -52
View File
@@ -1,5 +1,3 @@
// custom/ in-house implementation of go's tab-writer
// because ls shows table in column major fation and according to screen size
package ctw
import (
@@ -8,48 +6,72 @@ import (
"math"
)
func widthsSum(w []int, p int) int {
s := 0
for _, v := range w {
s += v + p
}
s -= p
return s
type CTW struct {
d [][]string // entire data passed to ctw
nw []int // widths of each fileName
gw []int // width of each git column
sw []int //width of each size column
ic []string // color of file icon of a row
cols int // zero based no of cols (or total cols -1)
showIcon bool
termW int
}
func findMax(arr []int) int {
max := 0
for _, v := range arr {
if v >= max {
max = v
}
}
/* each file comprises of 4 columns
|<---->|<---->|<------------------>|<--------->|
| size | icon | name+ext+indicator | gitStatus |
*/
return max
func New(termW int) *CTW {
t := new(CTW)
t.cols = 3
t.termW = termW
t.nw = make([]int, 0)
t.gw = make([]int, 0)
t.sw = make([]int, 0)
t.d = make([][]string, 0)
t.ic = make([]string, 0)
return t
}
//Ctw has complexity of no. of columns x no. of files
// termW is width of the terminal
func Ctw(buf *bytes.Buffer, data []string, termW int) {
dn := len(data) // length of data slice
func (w *CTW) AddRow(args ...string) {
// length checking for args
if len(args) != w.cols+1 {
return
}
w.sw = append(w.sw, len(args[0]))
w.nw = append(w.nw, len(args[2]))
w.gw = append(w.gw, len(args[3]))
if w.showIcon == false {
w.showIcon = len(args[1]) > 0
}
w.d = append(w.d, args)
}
func (w *CTW) IconColor(c string) {
w.ic = append(w.ic, c)
}
func (w *CTW) Flush(buf *bytes.Buffer) {
dn := len(w.d)
if dn == 0 {
return
}
const pad = 2 // padding b/w columns
var lens []int // slice of lengths of each element in the data slice
widths := make([]int, 0) // slice of widths of each column (don't use because it over run once)
var prevWidths []int // accurate widths value
for _, v := range data {
lens = append(lens, len(v))
}
pad := 2
iw := make([][4]int, 0) // slice of widths of each column (don't use because it over run once)
var widths [][4]int
prevj := 0 // prevj is previous jump value (row value if you may)
// for loop runs for all possible nos. of column (1,2,3,4....)
for {
cols := len(widths) + 1
widths = append(widths, 0)
cols := len(iw) + 1
iw = append(iw, [4]int{0, 0, 0, 0})
j := int(math.Ceil(float64(dn) / float64(cols))) // jump value corresponding to cols
if prevj == j { // removes redundant calculations
continue
@@ -58,49 +80,97 @@ func Ctw(buf *bytes.Buffer, data []string, termW int) {
e := j // end of column
// find optimal widths (width of each column and total no of columns)
for i := 0; i < cols && e <= dn; i++ {
widths[i] = findMax(lens[b:e])
iw[i] = w.colW(b, e)
b, e = e, e+j
}
// for last column if last column is not complete
if e-j < dn {
widths[cols-1] = findMax(lens[e-j : dn])
iw[cols-1] = w.colW(e-j, dn)
}
prevj = j
totW := widthsSum(widths, pad) //total width of the ls block
if totW > termW {
totW := widthsSum(iw, pad) //total width of the ls block
if totW > w.termW {
break
} else if totW > termW/2 { // if total width of the ls block is more than half of terminal
// copy widths to prevWidths
prevWidths = make([]int, len(widths))
for i := range widths {
prevWidths[i] = widths[i]
} else if totW >= w.termW/2 { // if total width of the ls block is more than half of terminal
// copy iw to widths
widths = make([][4]int, len(iw))
for i := range iw {
widths[i] = iw[i]
}
}
if cols == dn { // if content comes in one line of terminal
// copy widths to prevWidths
prevWidths = make([]int, len(widths))
for i := range widths {
prevWidths[i] = widths[i]
}
break
}
if cols == dn { // if content comes in one line of terminal
// copy widths to prevWidths
widths = make([][4]int, len(iw))
for i := range iw {
widths[i] = iw[i]
}
break
}
}
// total no of rows
rows := int(math.Ceil(float64(dn) / float64(len(prevWidths))))
rows := int(math.Ceil(float64(dn) / float64(len(widths))))
// loop to write entire ls block to buffer
for i := 0; i < rows; i++ {
for j := 0; j < len(prevWidths); j++ {
p := pad
for j := 0; j < len(widths); j++ {
if i+j*rows >= dn { // checks for last column if incomplete
continue
}
fmt.Fprintf(buf, "%-*s", prevWidths[j]+pad, data[i+j*rows])
if j == len(widths)-1 {
p = 0
}
w.printCell(buf, i+j*rows, widths[j])
fmt.Fprintf(buf, "%*s", p, "")
}
fmt.Fprintf(buf, "\n")
}
}
func (w *CTW) colW(b, e int) [4]int {
s, n, g := 0, 0, 0 // max od size column, name column, gitStatus column
for i := b; i < e; i++ {
if w.sw[i] > s {
s = w.sw[i]
}
if w.nw[i] > n {
n = w.nw[i]
}
if w.gw[i] > g {
g = w.gw[i]
}
}
ans := [4]int{0, 0, 0, 0}
if s > 0 {
ans[0] = s + 1
}
if w.showIcon {
ans[1] = 2
}
ans[2] = n
if g > 0 {
ans[3] = 2
}
return ans
}
func (w *CTW) printCell(buf *bytes.Buffer, i int, cs [4]int) {
if cs[0] > 0 {
fmt.Fprintf(buf, "%-*s ", cs[0]-1, w.d[i][0])
}
if w.showIcon {
fmt.Fprintf(buf, "%s%1s%s ", w.ic[i], w.d[i][1], white)
}
fmt.Fprintf(buf, "%s%-*s%s", getGitColor(w.d[i][3]), cs[2], w.d[i][2], white)
if cs[3] > 0 {
fmt.Fprintf(buf, " %s%1s%s", getGitColor(w.d[i][3]), w.d[i][3], white)
}
}
+80
View File
@@ -0,0 +1,80 @@
package ctw
import (
"bytes"
"fmt"
)
type LongCTW struct {
d [][]string // entire data passed to ctw
c []int // widths of each column
ic []string // color of file icon of a row
cols int // zero based no of cols (or total cols -1)
}
func NewLong(cols int) *LongCTW {
t := new(LongCTW)
t.cols = cols - 1
// initialize right size slice
t.c = make([]int, cols)
t.d = make([][]string, 0)
t.ic = make([]string, 0)
return t
}
func (l *LongCTW) AddRow(args ...string) {
// add length checking for args
if len(args) != l.cols+1 {
return
}
for i, v := range args {
if l.c[i] < len(v) {
l.c[i] = len(v)
}
}
l.d = append(l.d, args)
}
func (l *LongCTW) IconColor(c string) {
l.ic = append(l.ic, c)
}
func (l *LongCTW) Flush(buf *bytes.Buffer) {
var skipCol int = 0
for i, v := range l.c {
if v == 0 {
skipCol |= 1 << i
}
}
// explicitly setting git column to 1
l.c[l.cols] = 1
// explicitly setting icon column to 2
l.c[l.cols-2] = 1
for i, r := range l.d {
p := 0
f := true
for j, c := range r {
if (1<<j)&skipCol > 0 {
continue
}
if f == false {
p = 1
}
fmt.Fprintf(buf, "%*s", p, "")
if j == l.cols-2 {
fmt.Fprintf(buf, "%s%*s%s", l.ic[i], l.c[j], c, white)
} else if j >= l.cols-1 && (1<<l.cols)&skipCol == 0 {
color := getGitColor(r[l.cols])
fmt.Fprintf(buf, "%s%-*s%s", color, l.c[j], c, white)
} else {
fmt.Fprintf(buf, "%-*s", l.c[j], c)
}
f = false
}
fmt.Fprintln(buf)
}
}
+37
View File
@@ -0,0 +1,37 @@
package ctw
import "strings"
var (
white string = "\033[38;2;255;255;255m"
green string = "\033[38;2;055;183;021m"
brown string = "\033[38;2;192;154;107m"
)
func DisplayColor(b bool) {
if b == false {
white = ""
green = ""
brown = ""
}
}
func getGitColor(gitStatus string) string {
switch strings.Trim(gitStatus, " ") {
case "":
return white
case "U":
return green
default:
return brown
}
}
func widthsSum(w [][4]int, p int) int {
s := 0
for _, v := range w {
s += v[0] + v[1] + v[2] + v[3] + p
}
s -= p
return s
}
+86 -25
View File
@@ -4,12 +4,13 @@ package main
import (
"bytes"
"fmt"
"io"
"log"
"os"
"path/filepath"
"sort"
"strings"
"syscall"
"text/tabwriter"
"time"
"github.com/Yash-Handa/logo-ls/ctw"
@@ -23,13 +24,17 @@ type file struct {
modeBits uint32
owner, group string // use syscall package
blocks int64 // blocks required by the file multiply buy 512 to get block size
// 'U'-> untracked file 'M'-> Modified file '●'-> modified dir ' '-> Not Updated/ not in git repo
gitStatus string
icon string
iconColor string
}
type dir struct {
info *file
parent *file
files []*file // all child files and dirs
dirs []*file // for recursion contain only child dirs
files []*file // all child files and dirs
dirs []string // for recursion contain only child dirs
less func(int, int) bool
}
@@ -44,11 +49,18 @@ func newDir(d *os.File) (*dir, error) {
// filing current dir info
t.info = new(file)
t.info.name = "."
ds, err := d.Stat()
if err != nil {
return nil, err
}
// getting Git Status of the entire repository
var gitRepoStatus map[string]string // could be nil
if flagVector&flag_D == 0 {
gitRepoStatus = getFilesGitStatus(d.Name()) // returns map or nil
}
if curDir {
ds, err := d.Stat()
if err != nil {
return nil, err
}
t.info.size = ds.Size()
t.info.modTime = ds.ModTime()
if long {
@@ -92,9 +104,25 @@ func newDir(d *os.File) (*dir, error) {
f.blocks = s.Blocks
}
}
if flagVector&flag_i == 0 {
f.icon = "\uf15c"
if flagVector&flag_c == 0 {
f.iconColor = "\033[38;2;127;213;234m"
}
}
if gitRepoStatus != nil {
if v.IsDir() {
f.gitStatus = gitRepoStatus[v.Name()+"/"]
} else {
f.gitStatus = gitRepoStatus[v.Name()]
}
}
t.files = append(t.files, f)
if v.IsDir() {
t.dirs = append(t.dirs, f)
t.dirs = append(t.dirs, name+"/")
}
}
@@ -162,6 +190,37 @@ func newDir_ArgFiles(files []os.FileInfo) *dir {
return t
}
func newDirs_Recussion(d *os.File) {
dd, err := newDir(d)
d.Close()
if err != nil {
log.Printf("partial access to %q: %v\n", d.Name(), err)
_ = set_osExitCode(code_Minor)
}
// print the info of the files of the directory
io.Copy(os.Stdout, dd.print())
if len(dd.dirs) == 0 {
return
}
// at this point dd.print has sorted the children files
// but not using it instead printing children in directory order
temp := make([]string, len(dd.dirs))
for i, v := range dd.dirs {
temp[i] = filepath.Join(d.Name(), v)
}
for _, v := range temp {
fmt.Printf("\n%s:\n", v)
f, err := os.Open(v)
if err != nil {
log.Printf("cannot access %q: %v\n", v, err)
f.Close()
_ = set_osExitCode(code_Minor)
continue
}
newDirs_Recussion(f)
}
}
func (d *dir) print() *bytes.Buffer {
// take care of printing, extending symbolic links in long forms
@@ -174,38 +233,40 @@ func (d *dir) print() *bytes.Buffer {
}
buf := bytes.NewBuffer([]byte(""))
var w *tabwriter.Writer
switch {
case flagVector&(flag_l|flag_o|flag_g) > 0:
w = tabwriter.NewWriter(buf, 0, 0, 1, ' ', tabwriter.DiscardEmptyColumns)
fmtStr := "%s\t%s\t%s\t%s\t%s\t%s\t\n"
w := ctw.NewLong(9)
for _, v := range d.files {
if flagVector&flag_s > 0 {
fmt.Fprintf(w, "%s\t", getSizeInFormate(v.blocks*512))
w.AddRow(getSizeInFormate(v.blocks*512), v.mode, v.owner, v.group, getSizeInFormate(v.size), v.modTime.Format(timeFormate), v.icon, v.name+v.ext+v.indicator, v.gitStatus)
} else {
w.AddRow("", v.mode, v.owner, v.group, getSizeInFormate(v.size), v.modTime.Format(timeFormate), v.icon, v.name+v.ext+v.indicator, v.gitStatus)
}
fmt.Fprintf(w, fmtStr, v.mode, v.owner, v.group, getSizeInFormate(v.size), v.modTime.Format(time.Stamp), v.name+v.ext+v.indicator)
w.IconColor(v.iconColor)
}
w.Flush()
w.Flush(buf)
case flagVector&flag_1 > 0:
w = tabwriter.NewWriter(buf, 0, 0, 1, ' ', tabwriter.DiscardEmptyColumns)
w := ctw.NewLong(4)
for _, v := range d.files {
if flagVector&flag_s > 0 {
fmt.Fprintf(w, "%s\t", getSizeInFormate(v.blocks*512))
w.AddRow(getSizeInFormate(v.blocks*512), v.icon, v.name+v.ext+v.indicator, v.gitStatus)
} else {
w.AddRow("", v.icon, v.name+v.ext+v.indicator, v.gitStatus)
}
fmt.Fprintf(w, "%s\t\n", v.name+v.ext+v.indicator)
w.IconColor(v.iconColor)
}
w.Flush()
w.Flush(buf)
default:
// w = tabwriter.NewWriter(buf, 0, 0, 2, ' ', tabwriter.DiscardEmptyColumns)
temp := make([]string, len(d.files))
for i, v := range d.files {
s := ""
w := ctw.New(terminalWidth)
for _, v := range d.files {
if flagVector&flag_s > 0 {
s = getSizeInFormate(v.blocks*512) + " "
w.AddRow(getSizeInFormate(v.blocks*512), v.icon, v.name+v.ext+v.indicator, v.gitStatus)
} else {
w.AddRow("", v.icon, v.name+v.ext+v.indicator, v.gitStatus)
}
temp[i] = s + v.name + v.ext + v.indicator
w.IconColor(v.iconColor)
}
ctw.Ctw(buf, temp, terminalWidth)
w.Flush(buf)
}
return buf
}
+70
View File
@@ -0,0 +1,70 @@
package main
import (
"path/filepath"
"strings"
"github.com/go-git/go-git/v5"
)
func getRepoStatus(path string) (git.Status, string, error) {
op := git.PlainOpenOptions{DetectDotGit: true}
r, err := git.PlainOpenWithOptions(path, &op)
if err != nil {
return nil, "", err
}
w, err := r.Worktree()
if err != nil {
return nil, "", err
}
ws, err := w.Status()
if err != nil {
return nil, "", err
}
return ws, w.Filesystem.Root(), nil
}
func getFilesGitStatus(p string) map[string]string {
gitRepo, gitRoot, err := getRepoStatus(p)
if err != nil {
return nil
}
pAbs, err := filepath.Abs(p)
if err != nil {
return nil
}
t := make(map[string]string)
for i, v := range gitRepo {
i = gitFilePath(gitRoot+"/"+i, pAbs+"/")
if i == "" {
continue
}
dirs := strings.SplitAfter(i, "/")
d := ""
for j, seg := range dirs {
if j == len(dirs)-1 {
if v.Worktree == '?' {
t[i] = "U"
} else {
t[i] = string(v.Worktree)
}
} else {
d += seg
t[d] = "●"
}
}
}
return t
}
func gitFilePath(gitpath, dirpath string) string {
if strings.HasPrefix(gitpath, dirpath) {
return strings.TrimPrefix(gitpath, dirpath)
}
return ""
}
+1
View File
@@ -3,6 +3,7 @@ module github.com/Yash-Handa/logo-ls
go 1.15
require (
github.com/go-git/go-git/v5 v5.1.0
github.com/pborman/getopt/v2 v2.0.0
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a
)
+72
View File
@@ -1,10 +1,82 @@
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7 h1:uSoVVbwJiQipAclBbw+8quDsfcvFjOpI5iCf4p/cqCs=
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs=
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA=
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
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=
github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4=
github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E=
github.com/go-git/go-billy/v5 v5.0.0 h1:7NQHvd9FVid8VL4qVUMm8XifBK+2xCoZ2lSk0agRrHM=
github.com/go-git/go-billy/v5 v5.0.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0=
github.com/go-git/go-git-fixtures/v4 v4.0.1 h1:q+IFMfLx200Q3scvt2hN79JsEzy4AmBTp/pqnefH+Bc=
github.com/go-git/go-git-fixtures/v4 v4.0.1/go.mod h1:m+ICp2rF3jDhFgEZ/8yziagdT1C+ZpZcrJjappBCDSw=
github.com/go-git/go-git/v5 v5.1.0 h1:HxJn9g/E7eYvKW3Fm7Jt4ee8LXfPOm/H1cdDu8vEssk=
github.com/go-git/go-git/v5 v5.1.0/go.mod h1:ZKfuPUoY1ZqIG4QG9BDBh3G4gLM5zvPuSJAozQrZuyM=
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/imdario/mergo v0.3.9/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
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/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
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/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
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=
golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a h1:vclmkQCjlDX5OydZ9wv8rBCcS0QyQY66Mpf/7BZbInM=
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
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/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-20200302150141-5c8b2ff67527 h1:uYVVQ9WP/Ds2ROhcaGPeIdVq0RIXVLwsHlnvJ+cT1So=
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
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/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
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=
+131 -19
View File
@@ -6,7 +6,9 @@ import (
"log"
"os"
"sort"
"time"
"github.com/Yash-Handa/logo-ls/ctw"
"github.com/pborman/getopt/v2"
"golang.org/x/crypto/ssh/terminal"
)
@@ -18,8 +20,12 @@ const (
flag_l uint = 1 << iota
flag_a
flag_alpha // sort in alphabetic order (default)
flag_i // stop printing of icons
flag_c // stop printing of colors
flag_D // stop printing of git status
flag_A
flag_h
flag_R
flag_r
flag_S
flag_t
@@ -40,11 +46,39 @@ var flagVector uint
// terminal width for formatting
var terminalWidth int
// time formate
var timeFormate string
const (
code_OK int = iota
code_Minor
code_Serious
)
// os exit code (do not update manually)
var osExitCode int = code_OK
// only use set_osExitCode to update the value of osExitCode
func set_osExitCode(c int) int {
switch {
case c == code_Serious:
osExitCode = code_Serious
case c == code_Minor && osExitCode != code_Serious:
osExitCode = code_Minor
}
return osExitCode
}
func main() {
// content flags
f_a := getopt.BoolLong("all", 'a', "do not ignore entries starting with .")
f_A := getopt.BoolLong("almost-all", 'A', "do not list implied . and ..")
// disable Stuff
f_D := getopt.BoolLong("disable-git-status", 'D', "don't print git status of files, In recursive -R this flag enables git-status")
f_c := getopt.BoolLong("disable-color", 'c', "don't color icons, filenames and git status (use this to print to a file)")
f_i := getopt.BoolLong("disable-icon", 'i', "don't print icons of the files")
// display flags
f_1 := getopt.Bool('1', "list one file per line.")
f_d := getopt.BoolLong("directory", 'd', "list directories themselves, not their contents")
@@ -63,6 +97,8 @@ func main() {
f_t := getopt.Bool('t', "sort by modification time, newest first")
f_r := getopt.BoolLong("reverse", 'r', "reverse order while sorting")
f_R := getopt.BoolLong("recursive", 'R', "list subdirectories recursively, git-status is disabled by default")
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_help := getopt.Bool('?', "display this help and exit")
f_V := getopt.BoolLong("version", 'V', "output version information and exit")
@@ -72,19 +108,32 @@ func main() {
if err != nil {
// code to handle error
log.Printf("%v\nTry 'logo-ls -?' for more information.", err)
os.Exit(2)
os.Exit(set_osExitCode(code_Serious))
}
// if f_help is provided print help and exit(0)
if *f_help {
getopt.PrintUsage(os.Stdout)
os.Exit(0)
fmt.Println("\nPossible value for --time-style (-T)")
fmt.Printf("%-11s %-32q\n", "ANSIC", "Mon Jan _2 15:04:05 2006")
fmt.Printf("%-11s %-32q\n", "UnixDate", "Mon Jan _2 15:04:05 MST 2006")
fmt.Printf("%-11s %-32q\n", "RubyDate", "Mon Jan 02 15:04:05 -0700 2006")
fmt.Printf("%-11s %-32q\n", "RFC822", "02 Jan 06 15:04 MST")
fmt.Printf("%-11s %-32q\n", "RFC822Z", "02 Jan 06 15:04 -0700")
fmt.Printf("%-11s %-32q\n", "RFC850", "Monday, 02-Jan-06 15:04:05 MST")
fmt.Printf("%-11s %-32q\n", "RFC1123", "Mon, 02 Jan 2006 15:04:05 MST")
fmt.Printf("%-11s %-32q\n", "RFC1123Z", "Mon, 02 Jan 2006 15:04:05 -0700")
fmt.Printf("%-11s %-32q\n", "RFC3339", "2006-01-02T15:04:05Z07:00")
fmt.Printf("%-11s %-32q\n", "Kitchen", "3:04PM")
fmt.Printf("%-11s %-32q [Default]\n", "Stamp", "Mon Jan _2 15:04:05")
fmt.Printf("%-11s %-32q\n", "StampMilli", "Jan _2 15:04:05.000")
os.Exit(osExitCode)
}
// if f_V is provided version will be printed and exit(0)
if *f_V {
fmt.Printf("logo-ls %s\nCopyright (c) 2020 Yash Handa\nLicense MIT <https://opensource.org/licenses/MIT>.\nThis is free software: you are free to change and redistribute it.\nThere is NO WARRANTY, to the extent permitted by law.\n", "v0.0.0")
os.Exit(0)
fmt.Printf("logo-ls %s\nCopyright (c) 2020 Yash Handa\nLicense MIT <https://opensource.org/licenses/MIT>.\nThis is free software: you are free to change and redistribute it.\nThere is NO WARRANTY, to the extent permitted by law.\n", "v1.1.0")
os.Exit(osExitCode)
}
// set one of -A and -a priority -A > -a
@@ -116,6 +165,27 @@ func main() {
flagVector |= flag_r
}
// set recursion (-R) flag
if *f_R {
flagVector |= flag_R
}
// set disable-git-status (-D) flag
if *f_D && !*f_R || !*f_D && *f_R {
flagVector |= flag_D
}
// set disable-color (-c) flag
if *f_c {
flagVector |= flag_c
ctw.DisplayColor(false)
}
// set disable-icon (-i) flag
if *f_i {
flagVector |= flag_i
}
// set -1 flag
if *f_1 {
flagVector |= flag_1
@@ -131,6 +201,36 @@ func main() {
flagVector |= flag_G
}
// set time formate
switch *f_T {
case "Stamp":
timeFormate = time.Stamp
case "StampMilli":
timeFormate = time.StampMilli
case "Kitchen":
timeFormate = time.Kitchen
case "ANSIC":
timeFormate = time.ANSIC
case "UnixDate":
timeFormate = time.UnixDate
case "RubyDate":
timeFormate = time.RubyDate
case "RFC1123":
timeFormate = time.RFC1123
case "RFC1123Z":
timeFormate = time.RFC1123Z
case "RFC3339":
timeFormate = time.RFC3339
case "RFC822":
timeFormate = time.RFC822
case "RFC822Z":
timeFormate = time.RFC822Z
case "RFC850":
timeFormate = time.RFC850
default:
timeFormate = time.Stamp
}
// set -h flag
if *f_h {
flagVector |= flag_h
@@ -179,14 +279,14 @@ func main() {
if err != nil {
log.Printf("cannot access %q: %v\n", v, err)
d.Close()
defer os.Exit(2)
_ = set_osExitCode(code_Serious)
continue
}
ds, err := d.Stat()
if err != nil {
log.Printf("cannot access %q: %v\n", v, err)
d.Close()
defer os.Exit(2)
_ = set_osExitCode(code_Serious)
continue
}
if ds.IsDir() {
@@ -203,24 +303,36 @@ func main() {
}
// process and display all the dirs in arg
pName := len(dirs) > 1
for i, v := range args.dirs {
if pName {
if flagVector&flag_R > 0 {
// use recursive func
for i, v := range args.dirs {
if i > 0 {
fmt.Println()
}
fmt.Printf("%s:\n", v.Name())
newDirs_Recussion(v)
}
d, err := newDir(v)
v.Close()
if err != nil {
log.Printf("partial access to %q: %v\n", v.Name(), err)
defer os.Exit(2)
}
// print the info of the files of the directory
io.Copy(os.Stdout, d.print())
if i < len(args.dirs)-1 {
fmt.Println()
} else {
pName := len(dirs) > 1
for i, v := range args.dirs {
if pName {
fmt.Printf("%s:\n", v.Name())
}
d, err := newDir(v)
v.Close()
if err != nil {
log.Printf("partial access to %q: %v\n", v.Name(), err)
_ = set_osExitCode(code_Serious)
}
// print the info of the files of the directory
io.Copy(os.Stdout, d.print())
if i < len(args.dirs)-1 {
fmt.Println()
}
}
}
os.Exit(osExitCode)
}
func init() {