github.com/gechr/complete@v0.0.0-20191016221035-401475e3ce1e/args.go (about) 1 package complete 2 3 import ( 4 "os" 5 "path/filepath" 6 "strings" 7 "unicode" 8 ) 9 10 // Args describes command line arguments 11 type Args struct { 12 // All lists of all arguments in command line (not including the command itself) 13 All []string 14 // Completed lists of all completed arguments in command line, 15 // If the last one is still being typed - no space after it, 16 // it won't appear in this list of arguments. 17 Completed []string 18 // Last argument in command line, the one being typed, if the last 19 // character in the command line is a space, this argument will be empty, 20 // otherwise this would be the last word. 21 Last string 22 // LastCompleted is the last argument that was fully typed. 23 // If the last character in the command line is space, this would be the 24 // last word, otherwise, it would be the word before that. 25 LastCompleted string 26 } 27 28 // Directory gives the directory of the current written 29 // last argument if it represents a file name being written. 30 // in case that it is not, we fall back to the current directory. 31 // 32 // Deprecated. 33 func (a Args) Directory() string { 34 if info, err := os.Stat(a.Last); err == nil && info.IsDir() { 35 return fixPathForm(a.Last, a.Last) 36 } 37 dir := filepath.Dir(a.Last) 38 if info, err := os.Stat(dir); err != nil || !info.IsDir() { 39 return "./" 40 } 41 return fixPathForm(a.Last, dir) 42 } 43 44 func newArgs(line string) Args { 45 var ( 46 all []string 47 completed []string 48 ) 49 parts := splitFields(line) 50 if len(parts) > 0 { 51 all = parts[1:] 52 completed = removeLast(parts[1:]) 53 } 54 return Args{ 55 All: all, 56 Completed: completed, 57 Last: last(parts), 58 LastCompleted: last(completed), 59 } 60 } 61 62 // splitFields returns a list of fields from the given command line. 63 // If the last character is space, it appends an empty field in the end 64 // indicating that the field before it was completed. 65 // If the last field is of the form "a=b", it splits it to two fields: "a", "b", 66 // So it can be completed. 67 func splitFields(line string) []string { 68 parts := strings.Fields(line) 69 70 // Add empty field if the last field was completed. 71 if len(line) > 0 && unicode.IsSpace(rune(line[len(line)-1])) { 72 parts = append(parts, "") 73 } 74 75 // Treat the last field if it is of the form "a=b" 76 parts = splitLastEqual(parts) 77 return parts 78 } 79 80 func splitLastEqual(line []string) []string { 81 if len(line) == 0 { 82 return line 83 } 84 parts := strings.Split(line[len(line)-1], "=") 85 return append(line[:len(line)-1], parts...) 86 } 87 88 func (a Args) from(i int) Args { 89 if i > len(a.All) { 90 i = len(a.All) 91 } 92 a.All = a.All[i:] 93 94 if i > len(a.Completed) { 95 i = len(a.Completed) 96 } 97 a.Completed = a.Completed[i:] 98 return a 99 } 100 101 func removeLast(a []string) []string { 102 if len(a) > 0 { 103 return a[:len(a)-1] 104 } 105 return a 106 } 107 108 func last(args []string) string { 109 if len(args) == 0 { 110 return "" 111 } 112 return args[len(args)-1] 113 }