args.go 2.4 KB

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