package main import ( "flag" "fmt" "io/fs" "os" "strconv" "github.com/fatih/color" ) func usage() { //TODO: Fill this out fmt.Fprintf(os.Stderr, "Usage:\n") os.Exit(1) } func check(err error) { if err != nil { fmt.Fprintf(os.Stderr, "%s\n", err) //panic(err) //not sure about this :/ } } func GetFileSize(fi fs.FileInfo) (size string) { switch fileSizeFloat := float64(fi.Size()); { case fileSizeFloat > (1024 * 1024 * 1024): //GB fileSizeFloat /= (1024 * 1024 * 1024) size = strconv.FormatFloat(fileSizeFloat, 'f', 1, 64) return size + "G" case fileSizeFloat > (1024 * 1024): //MB fileSizeFloat /= (1024 * 1024) size = strconv.FormatFloat(fileSizeFloat, 'f', 1, 64) return size + "M" case fileSizeFloat > 1024: //KB fileSizeFloat /= 1024 size = strconv.FormatFloat(fileSizeFloat, 'f', 1, 64) return size + "K" case fileSizeFloat > 0: //B size = strconv.FormatFloat(fileSizeFloat, 'f', 0, 64) return size default: return "0" } } func GetFileModTime(fi fs.FileInfo) (mod string) { //day month short time HH:MM day := strconv.Itoa(fi.ModTime().Day()) month := fi.ModTime().Month().String() timeH := strconv.Itoa(fi.ModTime().Hour()) timeM := strconv.Itoa(fi.ModTime().Minute()) if len(day) == 1 { day = " " + day } if len(timeH) <= 1 { timeH = "0" + timeH } if len(timeM) <= 1 { timeM = "0" + timeM } mod = day + " " + month[0:3] + " " + timeH + ":" + timeM return mod } func GetFilePerm(file fs.FileInfo) (perms string) { perms = "" mode := file.Mode() //Owner perms += (string(mode.String()[0])) //d at the start for dir for i := 1; i < 4; i++ { perms += (string(mode.String()[i])) } //Group for i := 4; i < 7; i++ { perms += (string(mode.String()[i])) } //Other for i := 7; i < 10; i++ { perms += (string(mode.String()[i])) } return perms } func PrintHeaders() { headersOutput := color.New(color.FgHiBlack).Add(color.Underline) headersOutput.Printf("%-10s ", "Type") headersOutput.Printf("%7s ", "Size") headersOutput.Printf("%5s ", "Time") headersOutput.Printf("%11s\n", "Name") } func PrintWithoutL(content []fs.DirEntry, isFlagAEnable *bool) { dirOutput := color.New(color.FgMagenta, color.Bold) fileOutput := color.New(color.FgWhite, color.Bold) for _, item := range content { //check if the item is a hidden item (starts with . ) if item.Name()[:1] == "." && !*isFlagAEnable { continue //skip the file } //check if item is dir if item.IsDir() { dirOutput.Printf(" %s ", item.Name()) } else { fileOutput.Printf(" %s ", item.Name()) } } fmt.Println() } func PrintWithL(content []fs.DirEntry, isFlagAEnable *bool) { dirOutput := color.New(color.FgMagenta, color.Bold) fileOutput := color.New(color.FgWhite, color.Bold) PrintHeaders() for _, item := range content { //we now need extra info from the files fi, err := os.Stat(item.Name()) check(err) fPerm := GetFilePerm(fi) fDirSize := "-" fSize := GetFileSize(fi) fModTime := GetFileModTime(fi) //check if the item is a hidden item (starts with . ) if item.Name()[:1] == "." && !*isFlagAEnable { continue //skip the file } //check if item is dir if item.IsDir() { dirOutput.Printf("%s %7s %7s\t%s\n", fPerm, fDirSize, fModTime, item.Name()) } else { fmt.Printf("%7s %7s %4s", fPerm, fSize, fModTime) fileOutput.Printf("\t%s\n", item.Name()) } } fmt.Println() } func main() { var flagNoColor = flag.Bool("no-colour", false, "Disable color output") var flagEnableL = flag.Bool("l", false, "Enable ls -l output") var flagEnableA = flag.Bool("a", false, "Enable ls -a output") flag.Parse() if *flagNoColor { color.NoColor = true } //check if we can read the directory pwd := os.Getenv("PWD") content, err := os.ReadDir(pwd) check(err) if !*flagEnableL { PrintWithoutL(content, flagEnableA) } else { PrintWithL(content, flagEnableA) } }