9fans.net/go@v0.0.7/cmd/acme/internal/complete/complete.go (about) 1 // libcomplete/complete.c 2 3 package complete 4 5 import ( 6 "fmt" 7 "io/ioutil" 8 "strings" 9 "unicode/utf8" 10 ) 11 12 type Completion struct { 13 Progress bool /* whether forward progress has been made */ 14 Done bool /* whether the completion now represents a file or directory */ 15 Text string /* the string to advance, suffixed " " or "/" for file or directory */ 16 NumMatch int /* number of files that matched */ 17 Files []string /* files returned */ 18 } 19 20 func Complete(dir, s string) (*Completion, error) { 21 if strings.Contains(s, "/") { 22 return nil, fmt.Errorf("slash character in name argument to complete") 23 } 24 25 // Note: ioutil.ReadDir sorts, so no sort below. 26 dirs, err := ioutil.ReadDir(dir) 27 if err != nil { 28 return nil, err 29 } 30 31 // find the matches 32 c := new(Completion) 33 for _, info := range dirs { 34 if name := info.Name(); strings.HasPrefix(name, s) { 35 suffix := "" 36 if info.IsDir() { 37 suffix = "/" 38 } 39 c.Files = append(c.Files, name+suffix) 40 } 41 } 42 43 if len(c.Files) > 0 { 44 /* report interesting results */ 45 /* trim length back to longest common initial string */ 46 minlen := len(c.Files[0]) 47 for i := 1; i < len(c.Files); i++ { 48 minlen = longestprefixlength(c.Files[0], c.Files[i], minlen) 49 } 50 51 /* build the answer */ 52 c.Done = len(c.Files) == 1 53 c.Progress = c.Done || minlen > len(s) 54 c.Text = c.Files[0][len(s):minlen] 55 if c.Done && !strings.HasSuffix(c.Text, "/") { 56 c.Text += " " 57 } 58 c.NumMatch = len(c.Files) 59 } else { 60 /* no match, so return all possible strings */ 61 for _, info := range dirs { 62 suffix := "" 63 if info.IsDir() { 64 suffix = "/" 65 } 66 c.Files = append(c.Files, info.Name()+suffix) 67 } 68 } 69 return c, nil 70 } 71 72 func longestprefixlength(a, b string, n int) int { 73 var i int 74 for i = 0; i < n && i < len(a) && i < len(b); { 75 ra, wa := utf8.DecodeRuneInString(a) 76 rb, wb := utf8.DecodeRuneInString(b) 77 if ra != rb || wa != wb { 78 break 79 } 80 i += wa 81 } 82 return i 83 }