Skip to content

Instantly share code, notes, and snippets.

@ptflp
Last active December 4, 2020 15:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ptflp/528c74a387350b80fe9d955900779434 to your computer and use it in GitHub Desktop.
Save ptflp/528c74a387350b80fe9d955900779434 to your computer and use it in GitHub Desktop.
Linux tree command, realized on golang (Draft)
package main
import (
"fmt"
"log"
"os"
"path/filepath"
"strings"
)
const (
PrefixIntentEmpty = " "
PrefixIntentEmptySlash = "│ "
PrefixTreeNext = "├──"
PrefixTreeLast = "└──"
)
const (
PathSeparator = string(os.PathSeparator)
CurrentRelativePath = "."
FirstFile = 0
)
type file struct {
last bool
path string
child []*file
os.FileInfo
}
var m = make(map[string]*file, 1 << 4)
func main() {
list := make([]*file, 0, 1 << 4)
err := filepath.Walk(CurrentRelativePath,
func(path string, info os.FileInfo, err error) error {
if err != nil {
return nil
}
f := &file{
FileInfo: info,
child: nil,
path: path,
}
if info.IsDir() {
m[path] = f
}
if strings.Count(path, PathSeparator) == 0 {
list = append(list, f)
} else {
i := strings.LastIndex(path, PathSeparator)
if v, ok := m[path[:i]]; ok {
v.child = append(m[path[:i]].child, f)
m[path[:i]].child = v.child
}
}
return nil
})
if err != nil && len(list) < 1{
log.Fatal(err)
}
recursivePrint(list)
}
func recursivePrint(l []*file) {
for i := range l {
var prefix string
if i+1 == len(l) {
l[i].last = true
}
sp := strings.Split(l[i].path, PathSeparator)
if len(sp) == 1 {
if i == FirstFile {
fmt.Println(l[i].Name())
}
if i != FirstFile {
if !l[i].last {
fmt.Println(PrefixTreeNext, l[i].Name())
}
if l[i].last {
fmt.Println(PrefixTreeLast, l[i].Name())
}
}
}
if len(sp) > 1 {
for i := range sp {
if i == FirstFile {
if !m[sp[FirstFile]].last {
prefix = PrefixIntentEmptySlash
continue
}
if m[sp[FirstFile]].last {
prefix = PrefixIntentEmpty
continue
}
}
if i+1 != len(sp) && i != FirstFile {
key := strings.Join(sp[:i+1], PathSeparator)
if v, ok := m[key]; ok {
if !v.last {
prefix += PrefixIntentEmptySlash
}
if v.last {
prefix += PrefixIntentEmpty
}
}
}
}
if !l[i].last {
prefix += PrefixTreeNext
}
if l[i].last {
prefix += PrefixTreeLast
}
fmt.Println(prefix, l[i].Name())
}
recursivePrint(l[i].child)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment