github.com/jmigpin/editor@v1.6.0/core/listdir.go (about) 1 package core 2 3 import ( 4 "context" 5 "io" 6 "os" 7 "path/filepath" 8 "sort" 9 "strings" 10 11 "github.com/jmigpin/editor/util/parseutil" 12 ) 13 14 func ListDirERow(erow *ERow, filepath string, tree, hidden bool) { 15 erow.Exec.RunAsync(func(ctx context.Context, rw io.ReadWriter) error { 16 return ListDirContext(ctx, rw, erow.Info.Name(), tree, hidden) 17 }) 18 } 19 20 //---------- 21 22 func ListDirContext(ctx context.Context, w io.Writer, filepath string, tree, hidden bool) error { 23 // "../" at the top 24 u := ".." + string(os.PathSeparator) 25 if _, err := w.Write([]byte(u + "\n")); err != nil { 26 return err 27 } 28 29 return listDirContext(ctx, w, filepath, "", tree, hidden) 30 } 31 32 func listDirContext(ctx context.Context, w io.Writer, fpath, addedFilepath string, tree, hidden bool) error { 33 fp2 := filepath.Join(fpath, addedFilepath) 34 35 out := func(s string) bool { 36 _, err := w.Write([]byte(s)) 37 return err == nil 38 } 39 40 f, err := os.Open(fp2) 41 if err != nil { 42 out(err.Error()) 43 return nil 44 } 45 46 fis, err := f.Readdir(-1) 47 f.Close() // close as soon as possible 48 if err != nil { 49 out(err.Error()) 50 return nil 51 } 52 53 // stop on context 54 if ctx.Err() != nil { 55 return ctx.Err() 56 } 57 58 sort.Sort(ByListOrder(fis)) 59 60 for _, fi := range fis { 61 // stop on context 62 if ctx.Err() != nil { 63 return ctx.Err() 64 } 65 66 name := fi.Name() 67 68 if !hidden && strings.HasPrefix(name, ".") { 69 continue 70 } 71 72 name2 := filepath.Join(addedFilepath, name) 73 if fi.IsDir() { 74 name2 += string(os.PathSeparator) 75 } 76 s := parseutil.EscapeFilename(name2) + "\n" 77 if !out(s) { 78 return nil 79 } 80 81 if fi.IsDir() && tree { 82 afp := filepath.Join(addedFilepath, name) 83 err := listDirContext(ctx, w, fpath, afp, tree, hidden) 84 if err != nil { 85 return err 86 } 87 } 88 } 89 return nil 90 } 91 92 //---------- 93 94 type ByListOrder []os.FileInfo 95 96 func (a ByListOrder) Len() int { 97 return len(a) 98 } 99 func (a ByListOrder) Swap(i, j int) { 100 a[i], a[j] = a[j], a[i] 101 } 102 func (a ByListOrder) Less(i, j int) bool { 103 ei := a[i] 104 ej := a[j] 105 iname := strings.ToLower(ei.Name()) 106 jname := strings.ToLower(ej.Name()) 107 if ei.IsDir() && ej.IsDir() { 108 return iname < jname 109 } 110 if ei.IsDir() { 111 return true 112 } 113 if ej.IsDir() { 114 return false 115 } 116 return iname < jname 117 }