@@ -16,8 +16,18 @@ var sanitizer = strings.NewReplacer(
16
16
"\t " , `` ,
17
17
)
18
18
19
- // TODO verify these are correct/complete (copied from bash)
20
- var quoter = strings .NewReplacer (
19
+ var quotingReplacer = strings .NewReplacer (
20
+ `'` , `'\''` ,
21
+ )
22
+
23
+ var quotingEscapingReplacer = strings .NewReplacer (
24
+ `\` , `\\` ,
25
+ `"` , `\"` ,
26
+ `$` , `\$` ,
27
+ "`" , "\\ `" ,
28
+ )
29
+
30
+ var defaultReplacer = strings .NewReplacer (
21
31
`\` , `\\` ,
22
32
`&` , `\&` ,
23
33
`<` , `\<` ,
@@ -41,11 +51,17 @@ var quoter = strings.NewReplacer(
41
51
`~` , `\~` ,
42
52
)
43
53
54
+ // additional replacement for use with `_describe` in shell script
55
+ var describeReplacer = strings .NewReplacer (
56
+ `\` , `\\` ,
57
+ `:` , `\:` ,
58
+ )
59
+
44
60
func quoteValue (s string ) string {
45
61
if strings .HasPrefix (s , "~/" ) || NamedDirectories .Matches (s ) {
46
- return "~" + quoter .Replace (strings .TrimPrefix (s , "~" )) // assume file path expansion
62
+ return "~" + defaultReplacer .Replace (strings .TrimPrefix (s , "~" )) // assume file path expansion
47
63
}
48
- return quoter .Replace (s )
64
+ return defaultReplacer .Replace (s )
49
65
}
50
66
51
67
type state int
@@ -60,12 +76,18 @@ const (
60
76
// Values need to end with `'` as well.
61
77
// Weirdly regardless whether there are additional quotes within the word.
62
78
QUOTING_STATE
63
- // Word starts and ends with quotes .
79
+ // Word starts and ends with `"` .
64
80
// Space suffix somehow ends up within the quotes.
65
81
// `"action"<TAB>`
66
82
// `"action "<CURSOR>`
67
83
// Workaround for now is to force nospace.
68
- FULLY_QUOTED_STATE
84
+ FULL_QUOTING_ESCAPING_STATE
85
+ // Word starts and ends with `'`.
86
+ // Space suffix somehow ends up within the quotes.
87
+ // `'action'<TAB>`
88
+ // `'action '<CURSOR>`
89
+ // Workaround for now is to force nospace.
90
+ FULL_QUOTING_STATE
69
91
)
70
92
71
93
// ActionRawValues formats values for zsh
@@ -74,13 +96,16 @@ func ActionRawValues(currentWord string, meta common.Meta, values common.RawValu
74
96
state := DEFAULT_STATE
75
97
if err == nil {
76
98
rawValue := splitted .CurrentToken ().RawValue
99
+ // TODO use token state to determine actual state (might have mixture).
77
100
switch {
78
101
case regexp .MustCompile (`^'$|^'.*[^']$` ).MatchString (rawValue ):
79
102
state = QUOTING_STATE
80
103
case regexp .MustCompile (`^"$|^".*[^"]$` ).MatchString (rawValue ):
81
104
state = QUOTING_ESCAPING_STATE
82
- case regexp .MustCompile (`^".*"$|^'.*'$` ).MatchString (rawValue ):
83
- state = FULLY_QUOTED_STATE
105
+ case regexp .MustCompile (`^".*"$` ).MatchString (rawValue ):
106
+ state = FULL_QUOTING_ESCAPING_STATE
107
+ case regexp .MustCompile (`^'.*'$` ).MatchString (rawValue ):
108
+ state = FULL_QUOTING_STATE
84
109
}
85
110
}
86
111
@@ -97,26 +122,37 @@ func ActionRawValues(currentWord string, meta common.Meta, values common.RawValu
97
122
displays := make ([]string , len (values ))
98
123
for index , val := range values {
99
124
value := sanitizer .Replace (val .Value )
100
- value = quoteValue (value )
101
- value = strings .ReplaceAll (value , `\` , `\\` ) // TODO find out why `_describe` needs another backslash
102
- value = strings .ReplaceAll (value , `:` , `\:` ) // TODO find out why `_describe` needs another backslash
103
125
104
126
switch state {
105
- // TODO depending on state value needs to be formatted differently
106
- // TODO backspace strings are currently an issue
107
- case QUOTING_STATE :
108
- value = value + `'`
109
127
case QUOTING_ESCAPING_STATE :
128
+ value = quotingEscapingReplacer .Replace (value )
129
+ value = describeReplacer .Replace (value )
110
130
value = value + `"`
131
+ case QUOTING_STATE :
132
+ value = quotingReplacer .Replace (value )
133
+ value = describeReplacer .Replace (value )
134
+ value = value + `'`
135
+ case FULL_QUOTING_ESCAPING_STATE :
136
+ value = quotingEscapingReplacer .Replace (value )
137
+ value = describeReplacer .Replace (value )
138
+ case FULL_QUOTING_STATE :
139
+ value = quotingReplacer .Replace (value )
140
+ value = describeReplacer .Replace (value )
141
+ default :
142
+ value = quoteValue (value )
143
+ value = describeReplacer .Replace (value )
111
144
}
112
145
113
- if ! meta .Nospace .Matches (val .Value ) && state != FULLY_QUOTED_STATE {
114
- value += " "
146
+ if ! meta .Nospace .Matches (val .Value ) {
147
+ switch state {
148
+ case FULL_QUOTING_ESCAPING_STATE , FULL_QUOTING_STATE : // nospace workaround
149
+ default :
150
+ value += " "
151
+ }
115
152
}
116
153
117
154
display := sanitizer .Replace (val .Display )
118
- display = strings .ReplaceAll (display , `\` , `\\` ) // TODO find out why `_describe` needs another backslash
119
- display = strings .ReplaceAll (display , `:` , `\:` ) // TODO find out why `_describe` needs another backslash
155
+ display = describeReplacer .Replace (display ) // TODO check if this needs to be applied to description as well
120
156
description := sanitizer .Replace (val .Description )
121
157
122
158
vals [index ] = value
0 commit comments