@@ -8,12 +8,13 @@ import {
8
8
add ,
9
9
concat ,
10
10
divide ,
11
+ int ,
11
12
modulo ,
12
13
multiply ,
13
14
str ,
14
15
subtract ,
15
16
} from '../../vimscript/expression/build' ;
16
- import { EvaluationContext } from '../../vimscript/expression/evaluate' ;
17
+ import { EvaluationContext , toInt , toString } from '../../vimscript/expression/evaluate' ;
17
18
import {
18
19
envVariableParser ,
19
20
expressionParser ,
@@ -27,7 +28,6 @@ import {
27
28
Expression ,
28
29
OptionExpression ,
29
30
RegisterExpression ,
30
- Value ,
31
31
VariableExpression ,
32
32
} from '../../vimscript/expression/types' ;
33
33
import { displayValue } from '../../vimscript/expression/displayValue' ;
@@ -37,6 +37,11 @@ type Unpack = {
37
37
type : 'unpack' ;
38
38
names : string [ ] ;
39
39
} ;
40
+ type Index = {
41
+ type : 'index' ;
42
+ variable : VariableExpression ;
43
+ index : Expression ;
44
+ } ;
40
45
41
46
export type LetCommandOperation = '=' | '+=' | '-=' | '*=' | '/=' | '%=' | '.=' | '..=' ;
42
47
export type LetCommandVariable =
@@ -47,7 +52,7 @@ export type LetCommandVariable =
47
52
export type LetCommandArgs =
48
53
| {
49
54
operation : LetCommandOperation ;
50
- variable : LetCommandVariable | Unpack ;
55
+ variable : LetCommandVariable | Unpack | Index ;
51
56
expression : Expression ;
52
57
lock : boolean ;
53
58
}
@@ -81,8 +86,16 @@ const unpackParser: Parser<Unpack> = sepBy(varNameParser, string(',').trim(optWh
81
86
names,
82
87
} ) ) ;
83
88
89
+ const indexParser : Parser < Index > = seq (
90
+ variableParser ,
91
+ expressionParser . wrap ( string ( '[' ) . then ( optWhitespace ) , optWhitespace . then ( string ( ']' ) ) ) ,
92
+ ) . map ( ( [ variable , index ] ) => ( {
93
+ type : 'index' ,
94
+ variable,
95
+ index,
96
+ } ) ) ;
97
+
84
98
export class LetCommand extends ExCommand {
85
- // TODO: Support indexing
86
99
// TODO: Support slicing
87
100
public static readonly argParser = ( lock : boolean ) =>
88
101
alt < LetCommand > (
@@ -92,7 +105,7 @@ export class LetCommand extends ExCommand {
92
105
// `:let {var} .= {expr}`
93
106
whitespace . then (
94
107
seq (
95
- alt < LetCommandVariable | Unpack > ( letVarParser , unpackParser ) ,
108
+ alt < LetCommandVariable | Unpack | Index > ( unpackParser , indexParser , letVarParser ) ,
96
109
operationParser . trim ( optWhitespace ) ,
97
110
expressionParser ,
98
111
) . map (
@@ -141,30 +154,34 @@ export class LetCommand extends ExCommand {
141
154
}
142
155
}
143
156
144
- let value = context . evaluate ( this . args . expression ) ;
145
- if ( variable . type === 'variable' ) {
157
+ const value = context . evaluate ( this . args . expression ) ;
158
+ const newValue = ( _var : Expression ) => {
146
159
if ( this . args . operation === '+=' ) {
147
- value = context . evaluate ( add ( variable , value ) ) ;
160
+ return context . evaluate ( add ( _var , value ) ) ;
148
161
} else if ( this . args . operation === '-=' ) {
149
- value = context . evaluate ( subtract ( variable , value ) ) ;
162
+ return context . evaluate ( subtract ( _var , value ) ) ;
150
163
} else if ( this . args . operation === '*=' ) {
151
- value = context . evaluate ( multiply ( variable , value ) ) ;
164
+ return context . evaluate ( multiply ( _var , value ) ) ;
152
165
} else if ( this . args . operation === '/=' ) {
153
- value = context . evaluate ( divide ( variable , value ) ) ;
166
+ return context . evaluate ( divide ( _var , value ) ) ;
154
167
} else if ( this . args . operation === '%=' ) {
155
- value = context . evaluate ( modulo ( variable , value ) ) ;
168
+ return context . evaluate ( modulo ( _var , value ) ) ;
156
169
} else if ( this . args . operation === '.=' ) {
157
- value = context . evaluate ( concat ( variable , value ) ) ;
170
+ return context . evaluate ( concat ( _var , value ) ) ;
158
171
} else if ( this . args . operation === '..=' ) {
159
- value = context . evaluate ( concat ( variable , value ) ) ;
172
+ return context . evaluate ( concat ( _var , value ) ) ;
160
173
}
161
- context . setVariable ( variable , value , this . args . lock ) ;
174
+ return value ;
175
+ } ;
176
+
177
+ if ( variable . type === 'variable' ) {
178
+ context . setVariable ( variable , newValue ( variable ) , this . args . lock ) ;
162
179
} else if ( variable . type === 'register' ) {
163
180
// TODO
164
181
} else if ( variable . type === 'option' ) {
165
182
// TODO
166
183
} else if ( variable . type === 'env_variable' ) {
167
- value = str ( env [ variable . name ] ?? '' ) ;
184
+ // TODO
168
185
} else if ( variable . type === 'unpack' ) {
169
186
// TODO: Support :let [a, b; rest] = ["aval", "bval", 3, 4]
170
187
if ( value . type !== 'list' ) {
@@ -176,13 +193,33 @@ export class LetCommand extends ExCommand {
176
193
if ( variable . names . length > value . items . length ) {
177
194
throw VimError . fromCode ( ErrorCode . MoreTargetsThanListItems ) ;
178
195
}
179
- for ( let i = 0 ; i < variable . names . length ; i ++ ) {
180
- await new LetCommand ( {
181
- operation : this . args . operation ,
182
- variable : { type : 'variable' , namespace : undefined , name : variable . names [ i ] } ,
183
- expression : value . items [ i ] ,
184
- lock : this . args . lock ,
185
- } ) . execute ( vimState ) ;
196
+ for ( const name of variable . names ) {
197
+ const item : VariableExpression = { type : 'variable' , namespace : undefined , name } ;
198
+ context . setVariable ( item , newValue ( item ) , this . args . lock ) ;
199
+ }
200
+ } else if ( variable . type === 'index' ) {
201
+ const varValue = context . evaluate ( variable . variable ) ;
202
+ if ( varValue . type === 'list' ) {
203
+ const idx = toInt ( context . evaluate ( variable . index ) ) ;
204
+ const newItem = newValue ( {
205
+ type : 'index' ,
206
+ expression : variable . variable ,
207
+ index : int ( idx ) ,
208
+ } ) ;
209
+ varValue . items [ idx ] = newItem ;
210
+ context . setVariable ( variable . variable , varValue , this . args . lock ) ;
211
+ } else if ( varValue . type === 'dict_val' ) {
212
+ const key = toString ( context . evaluate ( variable . index ) ) ;
213
+ const newItem = newValue ( {
214
+ type : 'entry' ,
215
+ expression : variable . variable ,
216
+ entryName : key ,
217
+ } ) ;
218
+ varValue . items . set ( key , newItem ) ;
219
+ context . setVariable ( variable . variable , varValue , this . args . lock ) ;
220
+ } else {
221
+ // TODO: Support blobs
222
+ throw VimError . fromCode ( ErrorCode . CanOnlyIndexAListDictionaryOrBlob ) ;
186
223
}
187
224
}
188
225
}
0 commit comments