mirror of
https://github.com/Yash-Handa/logo-ls.git
synced 2026-08-24 10:13:42 -05:00
304 lines
7.2 KiB
Go
304 lines
7.2 KiB
Go
// this file contain dir type definition
|
|
package main
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"io"
|
|
"log"
|
|
"os"
|
|
"path/filepath"
|
|
"sort"
|
|
"strings"
|
|
"syscall"
|
|
"time"
|
|
|
|
"github.com/Yash-Handa/logo-ls/ctw"
|
|
)
|
|
|
|
type file struct {
|
|
name, ext, indicator string
|
|
modTime time.Time
|
|
size int64 // in bytes
|
|
mode string
|
|
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 []string // for recursion contain only child dirs
|
|
less func(int, int) bool
|
|
}
|
|
|
|
// define methods on *dir type only not on file type
|
|
|
|
func newDir(d *os.File) (*dir, error) {
|
|
// some flag variable combinations
|
|
var long, curDir, showHidden bool = flagVector&(flag_l|flag_o|flag_g) > 0, flagVector&(flag_a|flag_d) > 0, flagVector&(flag_a|flag_A) > 0
|
|
|
|
t := new(dir)
|
|
|
|
// 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 {
|
|
t.info.size = ds.Size()
|
|
t.info.modTime = ds.ModTime()
|
|
if long {
|
|
t.info.mode = ds.Mode().String()
|
|
t.info.modeBits = uint32(ds.Mode())
|
|
t.info.owner, t.info.group = getOwnerGroupInfo(ds)
|
|
}
|
|
if flagVector&flag_s > 0 {
|
|
if s, ok := ds.Sys().(*syscall.Stat_t); ok {
|
|
t.info.blocks = s.Blocks
|
|
}
|
|
}
|
|
if flagVector&flag_i == 0 {
|
|
t.info.icon = iDef["diropen"].getGlyph()
|
|
if flagVector&flag_c == 0 {
|
|
t.info.iconColor = iDef["diropen"].getColor(1)
|
|
}
|
|
}
|
|
}
|
|
|
|
// don't fill files info if the -d flag is passed
|
|
if flagVector&flag_d > 0 {
|
|
t.files = append(t.files, t.info)
|
|
return t, nil
|
|
}
|
|
|
|
files, err := d.Readdir(0)
|
|
for _, v := range files {
|
|
name := v.Name()
|
|
if !showHidden && strings.HasPrefix(name, ".") {
|
|
continue
|
|
}
|
|
|
|
f := new(file)
|
|
f.ext = filepath.Ext(name)
|
|
f.name = name[0 : len(name)-len(f.ext)]
|
|
f.indicator = getIndicator(v.Mode())
|
|
f.size = v.Size()
|
|
f.modTime = v.ModTime()
|
|
if long {
|
|
f.mode = v.Mode().String()
|
|
f.modeBits = uint32(v.Mode())
|
|
f.owner, f.group = getOwnerGroupInfo(v)
|
|
}
|
|
if flagVector&flag_s > 0 {
|
|
if s, ok := v.Sys().(*syscall.Stat_t); ok {
|
|
f.blocks = s.Blocks
|
|
}
|
|
}
|
|
|
|
if flagVector&flag_i == 0 {
|
|
f.icon, f.iconColor = getIcon(f.name, f.ext, f.indicator)
|
|
if flagVector&flag_c != 0 {
|
|
f.iconColor = ""
|
|
}
|
|
}
|
|
|
|
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, name+"/")
|
|
}
|
|
}
|
|
|
|
// if -a flag is passed then only eval parent dir and append to files
|
|
if flagVector&flag_a > 0 {
|
|
t.files = append(t.files, t.info)
|
|
p, err := filepath.Abs(d.Name())
|
|
if err != nil {
|
|
// partial *dir (without parent dir) and error
|
|
return t, err
|
|
}
|
|
pp := filepath.Dir(p)
|
|
pds, err := os.Lstat(pp)
|
|
if err != nil {
|
|
// partial *dir (without parent dir) and error
|
|
return t, err
|
|
}
|
|
t.parent = new(file)
|
|
t.parent.name = ".."
|
|
t.parent.size = pds.Size()
|
|
t.parent.modTime = pds.ModTime()
|
|
if long {
|
|
t.parent.mode = pds.Mode().String()
|
|
t.parent.modeBits = uint32(pds.Mode())
|
|
t.parent.owner, t.parent.group = getOwnerGroupInfo(pds)
|
|
}
|
|
if flagVector&flag_s > 0 {
|
|
if s, ok := pds.Sys().(*syscall.Stat_t); ok {
|
|
t.parent.blocks = s.Blocks
|
|
}
|
|
}
|
|
if flagVector&flag_i == 0 {
|
|
t.parent.icon = iDef["diropen"].getGlyph()
|
|
if flagVector&flag_c == 0 {
|
|
t.parent.iconColor = iDef["diropen"].getColor(1)
|
|
}
|
|
}
|
|
t.files = append(t.files, t.parent)
|
|
}
|
|
|
|
// return *dir with no error
|
|
// or partial *dir with error (produced by Readdir)
|
|
return t, err
|
|
}
|
|
|
|
func newDir_ArgFiles(files []os.FileInfo) *dir {
|
|
var long bool = flagVector&(flag_l|flag_o|flag_g) > 0
|
|
|
|
t := new(dir)
|
|
|
|
for _, v := range files {
|
|
name := v.Name()
|
|
f := new(file)
|
|
f.ext = filepath.Ext(name)
|
|
f.name = name[0 : len(name)-len(f.ext)]
|
|
f.indicator = getIndicator(v.Mode())
|
|
f.size = v.Size()
|
|
f.modTime = v.ModTime()
|
|
if long {
|
|
f.mode = v.Mode().String()
|
|
f.modeBits = uint32(v.Mode())
|
|
f.owner, f.group = getOwnerGroupInfo(v)
|
|
}
|
|
if flagVector&flag_s > 0 {
|
|
if s, ok := v.Sys().(*syscall.Stat_t); ok {
|
|
f.blocks = s.Blocks
|
|
}
|
|
}
|
|
if flagVector&flag_i == 0 {
|
|
f.icon, f.iconColor = getIcon(f.name, f.ext, f.indicator)
|
|
if flagVector&flag_c != 0 {
|
|
f.iconColor = ""
|
|
}
|
|
}
|
|
t.files = append(t.files, f)
|
|
}
|
|
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", openDir+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
|
|
|
|
//sorting
|
|
lessFuncGenerator(d)
|
|
if flagVector&flag_U == 0 && flagVector&flag_r > 0 {
|
|
sort.Sort(sort.Reverse(d))
|
|
} else {
|
|
sort.Sort(d)
|
|
}
|
|
|
|
buf := bytes.NewBuffer([]byte(""))
|
|
switch {
|
|
case flagVector&(flag_l|flag_o|flag_g) > 0:
|
|
w := ctw.NewLong(9)
|
|
for _, v := range d.files {
|
|
if flagVector&flag_s > 0 {
|
|
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)
|
|
}
|
|
w.IconColor(v.iconColor)
|
|
}
|
|
w.Flush(buf)
|
|
case flagVector&flag_1 > 0:
|
|
w := ctw.NewLong(4)
|
|
for _, v := range d.files {
|
|
if flagVector&flag_s > 0 {
|
|
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)
|
|
}
|
|
w.IconColor(v.iconColor)
|
|
}
|
|
w.Flush(buf)
|
|
default:
|
|
w := ctw.New(terminalWidth)
|
|
for _, v := range d.files {
|
|
if flagVector&flag_s > 0 {
|
|
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)
|
|
}
|
|
w.IconColor(v.iconColor)
|
|
}
|
|
w.Flush(buf)
|
|
}
|
|
return buf
|
|
}
|
|
|
|
// sorting functions
|
|
func (d *dir) Len() int {
|
|
return len(d.files)
|
|
}
|
|
|
|
func (d *dir) Swap(i, j int) {
|
|
d.files[i], d.files[j] = d.files[j], d.files[i]
|
|
}
|
|
|
|
func (d *dir) Less(i, j int) bool {
|
|
return d.less(i, j)
|
|
}
|