├── .github
└── workflows
│ └── main.yml
├── .gitignore
├── .vscodeignore
├── CHANGELOG.md
├── LICENSE
├── README.md
├── images
├── examples
│ ├── block-clever.gif
│ ├── block-select.gif
│ ├── fast-array.gif
│ ├── fast-arrow.gif
│ ├── fast-curly.gif
│ ├── index.js
│ ├── macro-fragment.gif
│ ├── macro-quickopen.gif
│ ├── multipaste.gif
│ ├── quote-switch.gif
│ ├── template-var.gif
│ ├── toggle-endline.gif
│ └── toggle-maximize.gif
├── icon-small.png
└── icon.png
├── keybindings.json
├── package.json
├── src
├── config.ts
├── controlers
│ ├── block.ts
│ ├── jump.ts
│ ├── macro.ts
│ ├── maximize.ts
│ ├── multipast.ts
│ ├── string.ts
│ └── toggleEnd.ts
├── main.ts
├── models
│ ├── EditorBuilder.ts
│ └── RangeBuilder.ts
├── services
│ ├── commands.ts
│ ├── otherSelector.ts
│ ├── ownSelector.ts
│ ├── parser.ts
│ ├── selector.ts
│ └── string.ts
└── utils
│ ├── debug.ts
│ ├── editor.ts
│ ├── quote.ts
│ └── utils.ts
├── test
├── index.ts
└── main.test.ts
├── tsconfig.json
└── yarn.lock
/.github/workflows/main.yml:
--------------------------------------------------------------------------------
1 | on:
2 | push:
3 | tags:
4 | - "*"
5 |
6 | name: Deploy Extension
7 | jobs:
8 | deploy:
9 | runs-on: ubuntu-latest
10 | steps:
11 | - uses: actions/checkout@v2
12 | - uses: actions/setup-node@v1
13 | with:
14 | node-version: 12
15 | - run: yarn install --frozen-lockfile
16 | - name: Publish to Visual Studio Marketplace
17 | uses: HaaLeo/publish-vscode-extension@v0
18 | with:
19 | # refresh: https://dev.azure.com/davidbabel/_usersSettings/tokens
20 | pat: ${{ secrets.VS_MARKETPLACE_TOKEN }}
21 | registryUrl: https://marketplace.visualstudio.com
22 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | out
2 | node_modules
3 | vscode-reference.ts
4 | .vscode-test
--------------------------------------------------------------------------------
/.vscodeignore:
--------------------------------------------------------------------------------
1 | .vscode/**
2 | .vscode-test/**
3 | out/test/**
4 | test/**
5 | src/**
6 | **/*.map
7 | .gitignore
8 | tsconfig.json
9 | vsc-extension-quickstart.md
10 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Change Log
2 |
3 | All notable changes to the "clever" extension will be documented in this file.
4 |
5 | Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how to structure this file.
6 |
7 | ## [0.0.13] - 24-02-2021
8 |
9 | - add fast array inserting for windows users
10 | - change default windows bind suggestion to more accurate ones
11 | - bump typescript version
12 |
13 | ## [0.0.11] - a long time ago
14 |
15 | - Initial release
16 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 David B.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Clever Visual Studio Code
2 |
3 |
4 |
5 | **Clever vscode** was initially a personnal project to provide some missing features to the editor. It inspired from **Sublime Text**, **Google Chrome** and **iTerm** worflows.
6 |
7 | After sharing it with almost all my friends they motivate me to push it for cummunity.
8 |
9 | Suggestions, PR or ideas for embed macros are very welcome.
10 |
11 | Think about [rating and review](https://marketplace.visualstudio.com/items?itemName=davidbabel.Clever).
12 |
13 |
14 | ## Features
15 |
16 | Here are all the awesome current features of **Clever** (you can browse behaviour gifs below):
17 |
18 | - 🚀🚀🚀 [fast block select](#fast-block-select)
19 | - 💡 [maximise (toggle) the current editor](#toggle-maximise-current-editor)
20 | - ⚙️ [advanced macros system](#advanced-macros)
21 | - [Add fragment macro example](#add-fragment-macro-example)
22 | - [Sublime Text file navigation macro example](#sublime-text-file-navigation-macro-example)
23 | - [Rebind any key to another](#rebind-any-key-to-another)
24 | - 🚀🚀 [quick switch between string quotes ' → " → `](#quick-quotes-switch)
25 | - 🚀 [toggle endline with **","** or **";"** or **":"**](#toggle-endline)
26 | - 🚀 [insert incremental number or letter via multi cursor](#insert-incremental-numbers-or-letters)
27 | - 🚀 [fast cursor navigation / selection](#fast-cursor-navigation)
28 | - 🚀 [shortcut commands to](#shortcuts) :
29 | - [insert curly braces](#insert-curly-braces)
30 | - [insert array](#insert-array)
31 | - [insert arrow function](#insert-arrow-function)
32 | - [insert template string var](#insert-template-string-var)
33 | - ⚙️⚙️ [an advanced guide to improve vscode by config](#create-the-best-editor)
34 | - and more to come ...
35 | - and i'm aware of your ideas ([submit yours](#contribs))
36 |
37 | Every feature comes with keybinding suggestions. On install, this extension does not set any keybinding to prevent issues with different countries keyboard compatibility and allow you to only use the keybindings you need.
38 |
39 | So you have to set it manually in your `keybindings.json`. We are developpers, we made the `json` version ;)
40 |
41 | ## Fast block select
42 |
43 | _Demo_
44 |
45 | **Note** that this is a single same shortcut allowing this result :
46 |
47 | 
48 |
49 | _Binding suggestion:_
50 |
51 | ```json
52 | {
53 | "key": "ctrl+r",
54 | "mac": "cmd+r",
55 | "command": "clever.blockSelect.cleverSelect",
56 | "when": "editorTextFocus"
57 | }
58 | ```
59 |
60 | If needed, the following commands are also provided :
61 |
62 | ```js
63 | clever.blockSelect.quotes; // " " , ' ' , ` `
64 | clever.blockSelect.parenthesis; // ( )
65 | clever.blockSelect.squareBrackets; // [ ]
66 | clever.blockSelect.curlyBrackets; // { }
67 | clever.blockSelect.angleBrackets; //
68 | clever.blockSelect.inTag; // <> inTag >
69 | ```
70 |
71 | I recommand you to bind them to something like `cmd+k '` or `cmd+k (` etc ... It's very handy and may not create binding conflicts.
72 |
73 | ## Toggle maximise current editor
74 |
75 | _Demo_
76 |
77 | **Note:** this is especially helpfull on a side comparaison during commit diff
78 |
79 | 
80 |
81 | _Binding suggestion:_
82 |
83 | ```json
84 | {
85 | "key": "shift+ctrl+enter",
86 | "mac": "shift+cmd+enter",
87 | "command": "clever.maximize.toggleWithSidebar",
88 | "when": "editorTextFocus"
89 | }
90 | ```
91 |
92 | If needed, the following command is also provided :
93 |
94 | ```js
95 | clever.maximize.toggleWithoutSidebar;
96 | ```
97 |
98 | ## Advanced macros
99 |
100 | The Macro feature allows you to execute a list of vscode commands or any extensions commands, including "clever vscode" ones.
101 |
102 | It also provides two helpers commands (see examples below for API):
103 |
104 | - a `wait` helper to be able to manage async commands (especially extension ones which may miss to await callbacks).
105 | - a `type` helper to insert text, like a "programmatic snippet".
106 |
107 | Each macro is a "config / keybinding" combo. The wanted macro got a name, and an array of commands :
108 |
109 | ### Add fragment macro example
110 |
111 | _Demo_
112 |
113 | 
114 |
115 | _Configs_
116 |
117 | ```js
118 | {
119 | "clever.macros": {
120 | "exampleAddFragment": [ // macro name to remember in bindings
121 | "type:<>\n\n>", // type command with text param
122 | "cursorUp" // 2nd command
123 | ],
124 | "betterAddFragment": [
125 | "type:<>\n$1\n>" // type also support snippet syntax
126 | ]
127 | // "otherMacro": [/* commands list */]
128 | // ...
129 | }
130 | }
131 | ```
132 |
133 | _Binding suggestion:_
134 |
135 | ```json
136 | {
137 | "key": "whatever you want",
138 | "command": "clever.macros.betterAddFragment",
139 | "when": "editorTextFocus"
140 | }
141 | ```
142 |
143 | **Note:** to find every commands available, browse it in the shortcut palette `cmd+k cmd+s`
144 |
145 | ### Sublime Text file navigation macro example
146 |
147 | Another example, this macro allow to fastOpen a file without loosing focus from the file explorer (sublime text style).
148 |
149 | _Demo_
150 |
151 | 
152 |
153 | This workflow is amazing, it allows you to not use your mouse to open quickly multiple files. Check the [advanced config guide](#create-the-best-editor) to create a enhanced navigation system into vscode.
154 |
155 | _Configs_
156 |
157 | ```js
158 | {
159 | "clever.macros": {
160 | "fastOpenFile": [
161 | "list.select", // open current hover file
162 | "wait:20", // wait for 20ms before next (default 50ms)
163 | "workbench.action.focusSideBar" // send focus back to the file explorer
164 | ],
165 | "openAndKeepFile": [
166 | "list.select", // open current hover file
167 | "workbench.action.files.save", // this will keep the file open
168 | "wait:20", // wait for 20ms before next (default 50ms)
169 | "workbench.action.focusSideBar" // send focus back to the file explorer
170 | ],
171 | "openFile": [
172 | "list.select", // open current hover file
173 | "workbench.action.files.save", // this will keep the file open
174 | ]
175 | }
176 | }
177 | ```
178 |
179 | _Binding suggestion:_
180 |
181 | **Note:** to be able to map "enter" here you have to unbind it first. (see the [advanced config guide](#create-the-best-editor) to do so)
182 |
183 | ```js
184 | {
185 | "key": "right",
186 | "command": "clever.macros.fastOpenFile",
187 | "when": "explorerViewletVisible && filesExplorerFocus && !explorerResourceIsRoot && !inputFocus"
188 | },
189 | {
190 | // note : "enter" must be unbind first
191 | "key": "enter",
192 | "command": "clever.macros.openAndKeepFile",
193 | "when": "explorerViewletVisible && filesExplorerFocus && !explorerResourceIsRoot && !inputFocus"
194 | },
195 | {
196 | "key": "left",
197 | "command": "clever.macros.openFile",
198 | "when": "explorerViewletVisible && filesExplorerFocus && !explorerResourceIsRoot && !inputFocus"
199 | }
200 | ```
201 |
202 | ### Rebind any key to another
203 |
204 | The following will insert a `b` when you type a `j`. It works with any key, especially special characters.
205 |
206 | _Configs_
207 |
208 | ```js
209 | {
210 | "clever.macros": {
211 | "b": ["type:b"]
212 | }
213 | }
214 | ```
215 |
216 | _Binding example:_
217 |
218 | ```json
219 | {
220 | "key": "j",
221 | "command": "clever.macros.b",
222 | "when": "editorTextFocus"
223 | }
224 | ```
225 |
226 | ## Quick quotes switch
227 |
228 | _Demo_
229 |
230 | 
231 |
232 | _Binding suggestion:_
233 |
234 | ```json
235 | {
236 | "key": "alt+3",
237 | "mac": "cmd+`",
238 | "command": "clever.string.nextQuotes",
239 | "when": "editorTextFocus"
240 | }
241 | ```
242 |
243 | ## Toggle endline
244 |
245 | _Demo_
246 |
247 | 
248 |
249 | _Binding suggestion:_
250 |
251 | ```json
252 | ({
253 | "key": "ctrl+oem_period",
254 | "mac": "cmd+;",
255 | "command": "clever.toggleEnd.semicolon",
256 | "when": "editorTextFocus"
257 | },
258 | {
259 | "key": "ctrl+oem_2",
260 | "mac": "cmd+:",
261 | "command": "clever.toggleEnd.colon",
262 | "when": "editorTextFocus"
263 | },
264 | {
265 | "key": "ctrl+oem_comma",
266 | "mac": "cmd+[Comma]",
267 | "command": "clever.toggleEnd.comma",
268 | "when": "editorTextFocus"
269 | })
270 | ```
271 |
272 | ## Insert incremental numbers or letters
273 |
274 | _Demo_
275 |
276 | 
277 |
278 | _Binding suggestion:_
279 |
280 | ```json
281 | ({
282 | "key": "shift+ctrl+0",
283 | "mac": "shift+cmd+0",
284 | "command": "clever.multipast.0toN",
285 | "when": "editorTextFocus"
286 | },
287 | {
288 | "key": "shift+ctrl+1",
289 | "mac": "shift+cmd+1",
290 | "command": "clever.multipast.1toN",
291 | "when": "editorTextFocus"
292 | },
293 | {
294 | "key": "shift+ctrl+a",
295 | "mac": "shift+cmd+a",
296 | "command": "clever.multipast.atoN",
297 | "when": "editorTextFocus"
298 | },
299 | {
300 | "key": "shift+alt+ctrl+a",
301 | "mac": "shift+alt+cmd+a",
302 | "command": "clever.multipast.AtoN",
303 | "when": "editorTextFocus"
304 | })
305 | ```
306 |
307 | ## Fast cursor navigation
308 |
309 | _Demo_
310 |
311 | 
312 |
313 | _Configs_
314 |
315 | ```js
316 | // Clever: number of lines of small jumps
317 | "clever.fastJump.small.linesToJump": 5,
318 | // Clever: number of lines of large jumps
319 | "clever.fastJump.large.linesToJump": 10
320 | ```
321 |
322 | _Binding suggestion:_
323 |
324 | ```json
325 | ({
326 | "key": "ctrl+up",
327 | "mac": "cmd+up",
328 | "command": "clever.fastJump.small.up",
329 | "when": "editorTextFocus"
330 | },
331 | {
332 | "key": "ctrl+down",
333 | "mac": "cmd+down",
334 | "command": "clever.fastJump.small.down",
335 | "when": "editorTextFocus"
336 | },
337 | {
338 | "key": "shift+ctrl+up",
339 | "mac": "shift+cmd+up",
340 | "command": "clever.fastJump.small.selectUp",
341 | "when": "editorTextFocus"
342 | },
343 | {
344 | "key": "shift+ctrl+down",
345 | "mac": "shift+cmd+down",
346 | "command": "clever.fastJump.small.selectDown",
347 | "when": "editorTextFocus"
348 | },
349 | {
350 | "key": "alt+ctrl+pageup",
351 | "mac": "alt+cmd+pageup",
352 | "command": "clever.fastJump.big.up",
353 | "when": "editorTextFocus"
354 | },
355 | {
356 | "key": "alt+ctrl+pagedown",
357 | "mac": "alt+cmd+pagedown",
358 | "command": "clever.fastJump.big.down",
359 | "when": "editorTextFocus"
360 | },
361 | {
362 | "key": "shift+alt+ctrl+pageup",
363 | "mac": "shift+alt+cmd+pageup",
364 | "command": "clever.fastJump.big.selectUp",
365 | "when": "editorTextFocus"
366 | },
367 | {
368 | "key": "shift+alt+ctrl+pagedown",
369 | "mac": "shift+alt+cmd+pagedown",
370 | "command": "clever.fastJump.big.selectDown",
371 | "when": "editorTextFocus"
372 | })
373 | ```
374 |
375 | ## Shortcuts
376 |
377 | Clever also provide some usefull shortcuts out of the box.
378 |
379 | ### Insert curly braces
380 |
381 | _Demo_
382 |
383 | 
384 |
385 | _Binding suggestion:_
386 |
387 | ```json
388 | {
389 | "key": "alt-4",
390 | "mac": "cmd+{",
391 | "command": "clever.fastInsert.curly",
392 | "when": "editorTextFocus"
393 | }
394 | ```
395 |
396 | ### Insert array
397 |
398 | _Demo_
399 |
400 | 
401 |
402 | _Binding suggestion:_
403 |
404 | ```json
405 | {
406 | "key": "alt+5",
407 | "mac": "cmd+{",
408 | "command": "clever.fastInsert.array",
409 | "when": "editorTextFocus"
410 | },
411 | ```
412 |
413 | ### Insert arrow function
414 |
415 | _Demo_ (not related to intellisense, this is a keyboard shortcut)
416 |
417 | 
418 |
419 | _Binding suggestion:_
420 |
421 | ```json
422 | {
423 | "key": "ctrl+3",
424 | "mac": "cmd+=",
425 | "command": "clever.fastInsert.arrowFunction",
426 | "when": "editorTextFocus"
427 | }
428 | ```
429 |
430 | ### Insert template string var
431 |
432 | _Demo_
433 |
434 | 
435 |
436 | _Binding suggestion:_
437 |
438 | ```json
439 | {
440 | "key": "ctrl+oem_1",
441 | "mac": "cmd+$",
442 | "command": "clever.string.insertTemplateVar",
443 | "when": "editorTextFocus"
444 | }
445 | ```
446 |
447 | ## Create the best editor
448 |
449 | Here is a complete guide to custom your editor the right way.
450 |
451 | This does not need any extension, only modify the editor `settings.json` and `keybindings.json` the right way.
452 |
453 | // WIP
454 |
455 | Take a look at https://vscodecandothat.com/. You will learn a lot a things, for sure.
456 |
457 | ## Contribs
458 |
459 | If you want to help, find a bug or just correct an english mistake please [create an issue](https://github.com/DavidBabel/clever-vscode/issues).
460 |
461 | ## Inspirations & credits
462 |
463 | - document parser by Vilic : https://github.com/vilic/vscode-es-quotes
464 | - selecting library by dbankier https://github.com/dbankier/vscode-quick-select
465 |
466 | ## Why embed other libraries
467 |
468 | For me, the features provided by the embed library are from far, the big miss in vscode base commands. I had to modify some of it to add new awesome features.
469 |
470 | Also, as i said in introduction, i made this library for myself initially, and include them to be sure they will never disapear or stop to be maintained with a possible incompatible vscode version.
471 |
472 | ## License
473 |
474 | MIT. Copyright (c) David Babel.
475 |
476 | **Donations:** If you like this package, want it to be maintained and use it to makes millions, you can buy me [a coffee](https://www.paypal.me/devilhunter/2) ☕ or [a beer](https://www.paypal.me/devilhunter/4) 🍺.
477 |
--------------------------------------------------------------------------------
/images/examples/block-clever.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DavidBabel/clever-vscode/578a296a5c65d884ced1dc7e3d25e54db41f819c/images/examples/block-clever.gif
--------------------------------------------------------------------------------
/images/examples/block-select.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DavidBabel/clever-vscode/578a296a5c65d884ced1dc7e3d25e54db41f819c/images/examples/block-select.gif
--------------------------------------------------------------------------------
/images/examples/fast-array.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DavidBabel/clever-vscode/578a296a5c65d884ced1dc7e3d25e54db41f819c/images/examples/fast-array.gif
--------------------------------------------------------------------------------
/images/examples/fast-arrow.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DavidBabel/clever-vscode/578a296a5c65d884ced1dc7e3d25e54db41f819c/images/examples/fast-arrow.gif
--------------------------------------------------------------------------------
/images/examples/fast-curly.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DavidBabel/clever-vscode/578a296a5c65d884ced1dc7e3d25e54db41f819c/images/examples/fast-curly.gif
--------------------------------------------------------------------------------
/images/examples/index.js:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DavidBabel/clever-vscode/578a296a5c65d884ced1dc7e3d25e54db41f819c/images/examples/index.js
--------------------------------------------------------------------------------
/images/examples/macro-fragment.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DavidBabel/clever-vscode/578a296a5c65d884ced1dc7e3d25e54db41f819c/images/examples/macro-fragment.gif
--------------------------------------------------------------------------------
/images/examples/macro-quickopen.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DavidBabel/clever-vscode/578a296a5c65d884ced1dc7e3d25e54db41f819c/images/examples/macro-quickopen.gif
--------------------------------------------------------------------------------
/images/examples/multipaste.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DavidBabel/clever-vscode/578a296a5c65d884ced1dc7e3d25e54db41f819c/images/examples/multipaste.gif
--------------------------------------------------------------------------------
/images/examples/quote-switch.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DavidBabel/clever-vscode/578a296a5c65d884ced1dc7e3d25e54db41f819c/images/examples/quote-switch.gif
--------------------------------------------------------------------------------
/images/examples/template-var.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DavidBabel/clever-vscode/578a296a5c65d884ced1dc7e3d25e54db41f819c/images/examples/template-var.gif
--------------------------------------------------------------------------------
/images/examples/toggle-endline.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DavidBabel/clever-vscode/578a296a5c65d884ced1dc7e3d25e54db41f819c/images/examples/toggle-endline.gif
--------------------------------------------------------------------------------
/images/examples/toggle-maximize.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DavidBabel/clever-vscode/578a296a5c65d884ced1dc7e3d25e54db41f819c/images/examples/toggle-maximize.gif
--------------------------------------------------------------------------------
/images/icon-small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DavidBabel/clever-vscode/578a296a5c65d884ced1dc7e3d25e54db41f819c/images/icon-small.png
--------------------------------------------------------------------------------
/images/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DavidBabel/clever-vscode/578a296a5c65d884ced1dc7e3d25e54db41f819c/images/icon.png
--------------------------------------------------------------------------------
/keybindings.json:
--------------------------------------------------------------------------------
1 | {
2 | "keybindings": [
3 | {
4 | "command": "clever.blockSelect.cleverSelect",
5 | "key": "shift+ctrl+dd",
6 | "mac": "cmd+1",
7 | "when": "editorTextFocus"
8 | },
9 | {
10 | "command": "clever.blockSelect.quotes",
11 | "key": "shift+ctrl+dd",
12 | "mac": "cmd+2",
13 | "when": "editorTextFocus"
14 | },
15 | {
16 | "command": "clever.blockSelect.quotesBeta",
17 | "key": "shift+ctrl+dd",
18 | "mac": "cmd+8",
19 | "when": "editorTextFocus"
20 | },
21 | {
22 | "command": "clever.blockSelect.parenthesis",
23 | "key": "shift+ctrl+dd",
24 | "mac": "cmd+3",
25 | "when": "editorTextFocus"
26 | },
27 | {
28 | "command": "clever.blockSelect.squareBrackets",
29 | "key": "shift+ctrl+dd",
30 | "mac": "cmd+4",
31 | "when": "editorTextFocus"
32 | },
33 | {
34 | "command": "clever.blockSelect.curlyBrackets",
35 | "key": "shift+ctrl+dd",
36 | "mac": "cmd+5",
37 | "when": "editorTextFocus"
38 | },
39 | {
40 | "command": "clever.blockSelect.angleBrackets",
41 | "key": "shift+ctrl+dd",
42 | "mac": "cmd+6",
43 | "when": "editorTextFocus"
44 | },
45 | {
46 | "command": "clever.blockSelect.inTag",
47 | "key": "shift+ctrl+dd",
48 | "mac": "cmd+7",
49 | "when": "editorTextFocus"
50 | },
51 | {
52 | "command": "clever.rebind.•",
53 | "key": "alt+[IntlBackslash]",
54 | "when": "editorTextFocus"
55 | },
56 | {
57 | "command": "clever.rebind.",
58 | "key": "alt+1",
59 | "when": "editorTextFocus"
60 | },
61 | {
62 | "command": "clever.rebind.¶",
63 | "key": "alt+6",
64 | "when": "editorTextFocus"
65 | },
66 | {
67 | "command": "clever.rebind.®",
68 | "key": "alt+r",
69 | "when": "editorTextFocus"
70 | },
71 | {
72 | "command": "clever.rebind.†",
73 | "key": "alt+t",
74 | "when": "editorTextFocus"
75 | },
76 | {
77 | "command": "clever.rebind.º",
78 | "key": "alt+u",
79 | "when": "editorTextFocus"
80 | },
81 | {
82 | "command": "clever.rebind.π",
83 | "key": "alt+p",
84 | "when": "editorTextFocus"
85 | },
86 | {
87 | "command": "clever.rebind.‡",
88 | "key": "alt+q",
89 | "when": "editorTextFocus"
90 | },
91 | {
92 | "command": "clever.rebind.ƒ",
93 | "key": "alt+f",
94 | "when": "editorTextFocus"
95 | },
96 | {
97 | "command": "clever.rebind.fi",
98 | "key": "alt+g",
99 | "when": "editorTextFocus"
100 | },
101 | {
102 | "command": "clever.rebind.¬",
103 | "key": "alt+l",
104 | "when": "editorTextFocus"
105 | },
106 | {
107 | "command": "clever.rebind.µ",
108 | "key": "alt+m",
109 | "when": "editorTextFocus"
110 | },
111 | {
112 | "command": "clever.rebind.≈",
113 | "key": "alt+x",
114 | "when": "editorTextFocus"
115 | },
116 | {
117 | "command": "clever.rebind.©",
118 | "key": "alt+c",
119 | "when": "editorTextFocus"
120 | },
121 | {
122 | "command": "clever.rebind.◊",
123 | "key": "alt+v",
124 | "when": "editorTextFocus"
125 | },
126 | {
127 | "command": "clever.rebind.ß",
128 | "key": "alt+b",
129 | "when": "editorTextFocus"
130 | },
131 | {
132 | "command": "clever.rebind.∞",
133 | "key": "alt+[KeyM]",
134 | "when": "editorTextFocus"
135 | },
136 | {
137 | "command": "clever.rebind.…",
138 | "key": "alt+[Comma]",
139 | "when": "editorTextFocus"
140 | },
141 | {
142 | "command": "clever.rebind.÷",
143 | "key": "alt+[Period]",
144 | "when": "editorTextFocus"
145 | },
146 | {
147 | "command": "clever.rebind.≠",
148 | "key": "alt+=",
149 | "when": "editorTextFocus"
150 | }
151 | ]
152 | }
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "clever",
3 | "displayName": "Clever VSCode",
4 | "description": "Add many productivity usefull commands to vscode",
5 | "version": "0.1.1",
6 | "publisher": "davidbabel",
7 | "author": {
8 | "email": "babel.david@gmail.com",
9 | "name": "David Babel",
10 | "url": "https://github.com/DavidBabel/clever-vscode"
11 | },
12 | "license": "MIT",
13 | "engines": {
14 | "vscode": "^1.15.0"
15 | },
16 | "categories": [
17 | "Snippets",
18 | "Keymaps",
19 | "Other"
20 | ],
21 | "keywords": [
22 | "productivity",
23 | "macro",
24 | "macros",
25 | "smart",
26 | "clever",
27 | "better",
28 | "jump",
29 | "rebind",
30 | "indent",
31 | "format",
32 | "selection",
33 | "navigation",
34 | "maximize",
35 | "toggle"
36 | ],
37 | "activationEvents": [
38 | "*"
39 | ],
40 | "main": "./out/src/main",
41 | "icon": "images/icon.png",
42 | "homepage": "https://github.com/DavidBabel/clever-vscode/blob/master/README.md",
43 | "repository": {
44 | "type": "git",
45 | "url": "https://github.com/DavidBabel/clever-vscode.git"
46 | },
47 | "bugs": {
48 | "url": "https://github.com/DavidBabel/clever-vscode/issues"
49 | },
50 | "contributes": {
51 | "commands": [
52 | {
53 | "command": "clever.toggleEnd.semicolon",
54 | "title": "Clever: Toggle semicolon"
55 | },
56 | {
57 | "command": "clever.toggleEnd.colon",
58 | "title": "Clever: Toggle colon"
59 | },
60 | {
61 | "command": "clever.toggleEnd.comma",
62 | "title": "Clever: Toggle comma"
63 | },
64 | {
65 | "command": "clever.string.insertTemplateVar",
66 | "title": "Insert Template string"
67 | },
68 | {
69 | "command": "clever.string.nextQuotes",
70 | "title": "Switch to next quotes style"
71 | },
72 | {
73 | "command": "clever.multipast.0toN",
74 | "title": "Multi Paste from 0 to N"
75 | },
76 | {
77 | "command": "clever.multipast.1toN",
78 | "title": "Multi Paste from 1 to N"
79 | },
80 | {
81 | "command": "clever.multipast.atoN",
82 | "title": "Multi Paste from a to N"
83 | },
84 | {
85 | "command": "clever.multipast.AtoN",
86 | "title": "Multi Paste from A to N"
87 | },
88 | {
89 | "command": "clever.fastJump.small.up",
90 | "title": "Clever: fastJump up (small)"
91 | },
92 | {
93 | "command": "clever.fastJump.small.down",
94 | "title": "Clever: fastJump down (small)"
95 | },
96 | {
97 | "command": "clever.fastJump.small.selectUp",
98 | "title": "Clever: fastJump up with select (small)"
99 | },
100 | {
101 | "command": "clever.fastJump.small.selectDown",
102 | "title": "Clever: fastJump down with select (small)"
103 | },
104 | {
105 | "command": "clever.fastJump.big.up",
106 | "title": "Clever: fastJump up (big)"
107 | },
108 | {
109 | "command": "clever.fastJump.big.down",
110 | "title": "Clever: fastJump down (big)"
111 | },
112 | {
113 | "command": "clever.fastJump.big.selectUp",
114 | "title": "Clever: fastJump up with select (big)"
115 | },
116 | {
117 | "command": "clever.fastJump.big.selectDown",
118 | "title": "Clever: fastJump down with select (big)"
119 | },
120 | {
121 | "command": "clever.fastInsert.curly",
122 | "title": "Clever: fast add {curly} block at end of line"
123 | },
124 | {
125 | "command": "clever.fastInsert.array",
126 | "title": "Clever: fast add [] array block (usefull on windows)"
127 | },
128 | {
129 | "command": "clever.fastInsert.arrowFunction",
130 | "title": "Clever: fast add arrow function"
131 | },
132 | {
133 | "command": "clever.maximize.toggleWithSidebar",
134 | "title": "Clever: toggle maximize current editor (with sidebar)"
135 | },
136 | {
137 | "command": "clever.maximize.toggleWithoutSidebar",
138 | "title": "Clever: toggle maximize current editor (without sidebar)"
139 | },
140 | {
141 | "command": "clever.blockSelect.cleverSelect",
142 | "title": "Clever: cleverSelect"
143 | },
144 | {
145 | "command": "clever.blockSelect.quotes",
146 | "title": "Clever: Select current block quotes"
147 | },
148 | {
149 | "command": "clever.blockSelect.quotesBeta",
150 | "title": "Clever: Select current block quotesBeta"
151 | },
152 | {
153 | "command": "clever.blockSelect.parenthesis",
154 | "title": "Clever: Select current block parenthesis ()"
155 | },
156 | {
157 | "command": "clever.blockSelect.squareBrackets",
158 | "title": "Clever: Select current block squareBrackets []"
159 | },
160 | {
161 | "command": "clever.blockSelect.curlyBrackets",
162 | "title": "Clever: Select current block curlyBrackets {}"
163 | },
164 | {
165 | "command": "clever.blockSelect.angleBrackets",
166 | "title": "Clever: Select current block angleBrackets <>>"
167 | },
168 | {
169 | "command": "clever.blockSelect.inTag",
170 | "title": "Clever: Select current block inTag <>"
171 | }
172 | ],
173 | "configuration": {
174 | "type": "object",
175 | "title": "Clever Configuration",
176 | "properties": {
177 | "clever.macros": {
178 | "type": "object",
179 | "default": {},
180 | "description": "Clever: you can define macros here. see clever/README.md for more informations."
181 | },
182 | "clever.fastJump.small.linesToJump": {
183 | "type": "number",
184 | "default": 5,
185 | "description": "Clever: number of lines of small jumps"
186 | },
187 | "clever.fastJump.large.linesToJump": {
188 | "type": "number",
189 | "default": 10,
190 | "description": "Clever: number of lines of large jumps"
191 | }
192 | }
193 | }
194 | },
195 | "scripts": {
196 | "vscode:prepublish": "tsc -p ./",
197 | "compile": "tsc -watch -p ./",
198 | "postinstall": "node ./node_modules/vscode/bin/install",
199 | "test": "node ./node_modules/vscode/bin/test"
200 | },
201 | "devDependencies": {
202 | "@types/mocha": "^2.2.42",
203 | "@types/node": "^6.0.88",
204 | "mocha": "^3.5.0",
205 | "typescript": "^4.2.2",
206 | "vscode": "^1.1.5"
207 | }
208 | }
209 |
--------------------------------------------------------------------------------
/src/config.ts:
--------------------------------------------------------------------------------
1 | import {
2 | workspace as Workspace
3 | } from 'vscode';
4 |
5 | export const staticConfig = {
6 | macroDefaultWaitDelay: 50
7 | };
8 |
9 | export default function config(): any {
10 | return {
11 | ...staticConfig,
12 | ...Workspace.getConfiguration('clever')
13 | };
14 | }
15 |
--------------------------------------------------------------------------------
/src/controlers/block.ts:
--------------------------------------------------------------------------------
1 | import {
2 | window as Window,
3 | commands as Commands,
4 | Range,
5 | Position,
6 | Selection
7 | } from 'vscode';
8 | // import { blockSelect } from '../services/selector';
9 | import { prepareEdit } from '../utils/editor';
10 |
11 | export function deployBlock() {
12 | const editor = Window.activeTextEditor;
13 | const document = editor.document;
14 |
15 | // blockSelect();
16 | // prepareEdit((editBuilder, selection) => {
17 | // const initialText = document.getText(selection);
18 | // // const initialTextAsObject = JSON.parse(initialText);
19 | // let newText = initialText;
20 | // if ( selection.isSingleLine ) {
21 | // // let indentationChar = editor.options.insertSpaces ? ' ' : '\t';
22 | // // let levelOfIndent = newText.search(/\S/);
23 | // // let padding = indentationChar.repeat(levelOfIndent + editor.options.tabSize);
24 | // newText = initialText.replace(/,/g, ',\n');
25 | // newText = newText.replace(/{/g, '{\n');
26 | // newText = newText.replace(/}/g, '\n}');
27 | // // newText = newText.replace(/\n/g, '\n');
28 | // } else {
29 | // // remove multiples spaces
30 | // newText = initialText.replace(/\s+/g,' ');
31 | // }
32 | // editBuilder.replace(selection, newText);
33 |
34 | // // selection.intersection(new Range(selection.(1, 1), selection.translate(1, 1)))
35 | // editor.selection = new Selection(
36 | // new Position(selection.start.line, selection.start.character + 1),
37 | // new Position(selection.end.line, selection.end.character - 1),
38 | // );
39 | // });
40 | // Commands.executeCommand('editor.action.formatSelection');
41 | }
42 |
43 | export function imployBlock() {
44 |
45 | }
--------------------------------------------------------------------------------
/src/controlers/jump.ts:
--------------------------------------------------------------------------------
1 | import {
2 | commands as Commands
3 | } from 'vscode';
4 | import config from '../config';
5 | // import { prepareEdit } from "../utils/editor";
6 |
7 | type Jump = {
8 | size: number,
9 | direction: string
10 | };
11 |
12 | export const jumpSizes = {
13 | small: {
14 | up: {
15 | size: config().fastJump.small.linesToJump,
16 | direction: 'Up'
17 | },
18 | down: {
19 | size: config().fastJump.small.linesToJump,
20 | direction: 'Down'
21 | },
22 | },
23 | big: {
24 | up: {
25 | size: config().fastJump.large.linesToJump,
26 | direction: 'Up'
27 | },
28 | down: {
29 | size: config().fastJump.large.linesToJump,
30 | direction: 'Down'
31 | }
32 | }
33 | };
34 |
35 | export function jumpLines(jumpSizes: Jump) {
36 | const command = 'cursor' + jumpSizes.direction;
37 | for (let i = 0; i < jumpSizes.size; i++) {
38 | Commands.executeCommand(command);
39 | }
40 | }
41 |
42 | export function jumpSelectLines( jumpSizes: Jump) {
43 | const command = `cursor${jumpSizes.direction}Select`;
44 | for (let i = 0; i < jumpSizes.size; i++) {
45 | Commands.executeCommand(command);
46 | }
47 | }
--------------------------------------------------------------------------------
/src/controlers/macro.ts:
--------------------------------------------------------------------------------
1 | import config from "../config";
2 | import { executeCommands } from "../services/commands";
3 | import { insertSnippet } from "../services/string";
4 |
5 | export function executeMacro(macroName: string) {
6 | const commands = config().macros[macroName];
7 | if (commands) {
8 | executeCommands(commands);
9 | }
10 | }
11 |
12 | export function fastCurly() {
13 | executeCommands([
14 | "cursorEnd",
15 | "wait:60",
16 | insertSnippet.bind(null, " {\n\t$1\n}"),
17 | ]);
18 | }
19 | export function fastArray() {
20 | executeCommands([insertSnippet.bind(null, "[$1]")]);
21 | }
22 |
23 | export function fastArrowFunction() {
24 | insertSnippet("($1) => {\n\t$2\n}");
25 | }
26 |
27 | // TODO add more embed functions
28 | export function previewCurrentFile() {
29 | executeCommands(["list.select", "wait", "workbench.action.focusSideBar"]);
30 | }
31 |
32 | // export function closeCurrentOpened() {
33 | // executeCommands([
34 | // "list.select",
35 | // "wait",
36 | // "workbench.action.focusSideBar"
37 | // ]);
38 | // }
39 |
--------------------------------------------------------------------------------
/src/controlers/maximize.ts:
--------------------------------------------------------------------------------
1 | import {
2 | commands as Commands
3 | } from 'vscode';
4 |
5 | let currentlyExpended = false;
6 |
7 | export async function toggleMaximize(withSideBar: boolean = true) {
8 | if (currentlyExpended) {
9 | if (withSideBar) {
10 | await Commands.executeCommand('workbench.action.toggleSidebarVisibility');
11 | }
12 | await Commands.executeCommand('workbench.action.evenEditorWidths');
13 | await Commands.executeCommand('workbench.action.focusActiveEditorGroup');
14 | } else {
15 | await Commands.executeCommand('workbench.action.maximizeEditor');
16 | await Commands.executeCommand('workbench.action.maximizeEditor');
17 | }
18 | currentlyExpended = !currentlyExpended;
19 | }
20 |
21 |
--------------------------------------------------------------------------------
/src/controlers/multipast.ts:
--------------------------------------------------------------------------------
1 | import { prepareEdit } from "../utils/editor";
2 | import { nextToken } from '../utils/utils';
3 |
4 | export function multiPast(initChar: string|number) {
5 | let currentChar = initChar;
6 | prepareEdit((editBuilder, selection) => {
7 | editBuilder.insert(selection.start, currentChar.toString());
8 | currentChar = nextToken(currentChar);
9 | });
10 | }
11 |
--------------------------------------------------------------------------------
/src/controlers/string.ts:
--------------------------------------------------------------------------------
1 |
2 | import {
3 | window as Window,
4 | workspace as Workspace,
5 | SnippetString
6 | } from 'vscode';
7 | import { prepareEdit } from '../utils/editor';
8 | import { parse, findActiveStringTarget } from '../services/parser';
9 | import { getNextQuotes } from '../utils/quote';
10 | import config from '../config';
11 |
12 | export { insertBind, insertSnippet } from '../services/string';
13 | // export { insertBind, insertSnippet };
14 |
15 | export function toggleRebindActivation() {
16 | Workspace.getConfiguration('clever').update('disableRebindForEdit', !config().disableRebindForEdit);
17 | }
18 |
19 | export function nextQuotes() {
20 | try {
21 | prepareEdit((editBuilder, selection) => {
22 | const source = Window.activeTextEditor.document.getText();
23 | if (!source) return;
24 | const result = parse(source);
25 | if (!result || !result.stringTargets) return;
26 | const activeTarget = findActiveStringTarget(result.stringTargets, selection);
27 | if (!activeTarget) return;
28 | editBuilder.replace(activeTarget.range, getNextQuotes(activeTarget));
29 | });
30 | } catch (error) {
31 | // :)
32 | }
33 | }
--------------------------------------------------------------------------------
/src/controlers/toggleEnd.ts:
--------------------------------------------------------------------------------
1 | import { prepareEdit } from "../utils/editor";
2 |
3 | export function toggleEnd (char: string) {
4 | prepareEdit((editBuilder, selection, lines) => {
5 | lines.forEach(line => {
6 | if (line.text.endsWith(char)) {
7 | editBuilder.deleteEol(line, char.length);
8 | } else {
9 | editBuilder.insertEol(line, char);
10 | }
11 | });
12 | });
13 | }
14 |
--------------------------------------------------------------------------------
/src/main.ts:
--------------------------------------------------------------------------------
1 | import {
2 | commands as Commands,
3 | ExtensionContext,
4 | window as Window,
5 | } from "vscode";
6 | import config from "./config";
7 | import { jumpLines, jumpSelectLines, jumpSizes } from "./controlers/jump";
8 | import {
9 | executeMacro,
10 | fastArray,
11 | fastArrowFunction,
12 | fastCurly,
13 | previewCurrentFile,
14 | } from "./controlers/macro";
15 | import { toggleMaximize } from "./controlers/maximize";
16 | import { multiPast } from "./controlers/multipast";
17 | import { insertSnippet, nextQuotes } from "./controlers/string";
18 | import { toggleEnd } from "./controlers/toggleEnd";
19 | import {
20 | cleverSelect,
21 | matchingSelect,
22 | selectEitherQuote,
23 | } from "./services/selector";
24 |
25 | // import { matchingSelect } from './services/selector';
26 | // import { deployBlock, imployBlock } from './controlers/block';
27 |
28 | export function activate(context: ExtensionContext) {
29 | console.log('Congratulations, you are now "clever" than ever!');
30 |
31 | const _ = null;
32 | const r = (s: string, cb: (...args: any[]) => any) =>
33 | Commands.registerCommand(s, cb);
34 |
35 | context.subscriptions.push(
36 | r("clever.toggleEnd.comma", toggleEnd.bind(_, ",")),
37 | r("clever.toggleEnd.semicolon", toggleEnd.bind(_, ";")),
38 | r("clever.toggleEnd.colon", toggleEnd.bind(_, ":")),
39 | r("clever.string.insertTemplateVar", insertSnippet.bind(_, "${$1}")),
40 | r("clever.string.nextQuotes", nextQuotes),
41 | r("clever.multipast.0toN", multiPast.bind(_, 0)),
42 | r("clever.multipast.1toN", multiPast.bind(_, 1)),
43 | r("clever.multipast.atoN", multiPast.bind(_, "a")),
44 | r("clever.multipast.AtoN", multiPast.bind(_, "A")),
45 | r("clever.fastJump.small.up", jumpLines.bind(_, jumpSizes.small.up)),
46 | r("clever.fastJump.small.down", jumpLines.bind(_, jumpSizes.small.down)),
47 | r(
48 | "clever.fastJump.small.selectUp",
49 | jumpSelectLines.bind(_, jumpSizes.small.up)
50 | ),
51 | r(
52 | "clever.fastJump.small.selectDown",
53 | jumpSelectLines.bind(_, jumpSizes.small.down)
54 | ),
55 | r("clever.fastJump.big.up", jumpLines.bind(_, jumpSizes.big.up)),
56 | r("clever.fastJump.big.down", jumpLines.bind(_, jumpSizes.big.down)),
57 | r(
58 | "clever.fastJump.big.selectUp",
59 | jumpSelectLines.bind(_, jumpSizes.big.up)
60 | ),
61 | r(
62 | "clever.fastJump.big.selectDown",
63 | jumpSelectLines.bind(_, jumpSizes.big.down)
64 | ),
65 | r("clever.fastInsert.curly", fastCurly),
66 | r("clever.fastInsert.array", fastArray),
67 | r("clever.fastInsert.arrowFunction", fastArrowFunction),
68 | r("clever.embedMacro.previewCurrentFile", previewCurrentFile),
69 | // clever.closeHoverOpenedFile
70 | r("clever.maximize.toggleWithSidebar", toggleMaximize),
71 | r("clever.maximize.toggleWithoutSidebar", toggleMaximize.bind(_, false)),
72 | r("clever.blockSelect.cleverSelect", cleverSelect),
73 | r("clever.blockSelect.quotes", selectEitherQuote),
74 | r(
75 | "clever.blockSelect.parenthesis",
76 | matchingSelect.bind(_, { start_char: "(", end_char: ")" })
77 | ),
78 | r(
79 | "clever.blockSelect.squareBrackets",
80 | matchingSelect.bind(_, { start_char: "[", end_char: "]" })
81 | ),
82 | r(
83 | "clever.blockSelect.curlyBrackets",
84 | matchingSelect.bind(_, { start_char: "{", end_char: "}" })
85 | ),
86 | r(
87 | "clever.blockSelect.angleBrackets",
88 | matchingSelect.bind(_, { start_char: "<", end_char: ">" })
89 | ),
90 | r(
91 | "clever.blockSelect.inTag",
92 | matchingSelect.bind(_, { start_char: ">", end_char: "<" })
93 | )
94 | // clever.calculate
95 | // clever.block.deploy
96 | // clever.block.imploy
97 | // clever.block.toggleDeploy
98 | // clever.string.objectToJson
99 | // clever.string.jsonToObject
100 | );
101 | // macros
102 | Object.keys(config().macros).forEach((key) => {
103 | r("clever.macros." + key, executeMacro.bind(_, key));
104 | });
105 | }
106 |
107 | export function deactivate() {
108 | Window.showInformationMessage(
109 | "Hope to see you soon, please repport any issue."
110 | );
111 | }
112 |
--------------------------------------------------------------------------------
/src/models/EditorBuilder.ts:
--------------------------------------------------------------------------------
1 | import {
2 | TextLine,
3 | TextEditorEdit,
4 | Position,
5 | Range,
6 | Selection,
7 | EndOfLine
8 | } from 'vscode';
9 |
10 | export class EditorBuilder {
11 |
12 | vscEditor: TextEditorEdit;
13 |
14 | constructor(editor: TextEditorEdit) {
15 | this.vscEditor = editor;
16 | }
17 |
18 | // replaceNextChar(location: Position, value: string) {
19 | // this.replaceCharAt(location, value, +1);
20 | // }
21 |
22 | // replacePreviousChar(location: Position, value: string) {
23 | // this.replaceCharAt(location, value, -1);
24 | // }
25 |
26 | replaceCharAt(startLocation: Position, value: string, refPosition: number) {
27 | const endLocation = new Position(startLocation.line, startLocation.character + refPosition);
28 | this.replace(new Range(startLocation, endLocation), value);
29 | }
30 |
31 | deleteEol(currentLine: TextLine, length: number): void{
32 | const startDelete = new Position(currentLine.range.end.line, currentLine.range.end.character - length);
33 | this.vscEditor.delete(currentLine.range.with(startDelete));
34 | }
35 |
36 | insertEol(location: TextLine, text: string): void{
37 | this.vscEditor.insert(location.range.end, text);
38 | }
39 |
40 | // defaults
41 | replace(location: Position | Range | Selection, value: string): void {
42 | this.vscEditor.replace(location, value);
43 | }
44 |
45 | insert(location: Position, value: string): void {
46 | this.vscEditor.insert(location, value);
47 | }
48 |
49 | // _delete(location: Range | Selection): void{
50 | // this.vscEditor.delete(location);
51 | // }
52 |
53 | // _setEndOfLine(endOfLine: EndOfLine): void {
54 | // this.vscEditor.setEndOfLine(endOfLine);
55 | // }
56 |
57 | }
--------------------------------------------------------------------------------
/src/models/RangeBuilder.ts:
--------------------------------------------------------------------------------
1 | import { Position, Range } from 'vscode';
2 |
3 | interface IndexRange {
4 | start: number;
5 | end: number;
6 | }
7 |
8 | export class RangeBuilder {
9 | private indexRanges: IndexRange[];
10 |
11 | constructor(source: string) {
12 | let regex = /(.*)(\r?\n|$)/g;
13 |
14 | let indexRanges: IndexRange[] = [];
15 |
16 | while (true) {
17 | let groups = regex.exec(source);
18 | let lineText = groups[1];
19 | let lineEnding = groups[2];
20 |
21 | let lastIndex = regex.lastIndex - lineEnding.length;
22 |
23 | indexRanges.push({
24 | start: lastIndex - lineText.length,
25 | end: lastIndex
26 | });
27 |
28 | if (!lineEnding.length) {
29 | break;
30 | }
31 | }
32 |
33 | this.indexRanges = indexRanges;
34 | }
35 |
36 | getPosition(index: number): Position {
37 | let indexRanges = this.indexRanges;
38 |
39 | for (let i = 0; i < indexRanges.length; i++) {
40 | let indexRange = indexRanges[i];
41 | if (indexRange.end >= index) {
42 | if (indexRange.start <= index) {
43 | // Within range.
44 | return new Position(i, index - indexRange.start);
45 | } else {
46 | // End of line?
47 | let previousIndexRange = indexRanges[i - 1];
48 | return new Position(i, previousIndexRange.end - previousIndexRange.start + 1);
49 | }
50 | }
51 | }
52 | }
53 |
54 | getRange(startIndex: number, endIndex: number): Range {
55 | let start = this.getPosition(startIndex);
56 | let end = this.getPosition(endIndex);
57 | return new Range(start, end);
58 | }
59 | }
--------------------------------------------------------------------------------
/src/services/commands.ts:
--------------------------------------------------------------------------------
1 | import {
2 | commands as Commands
3 | } from 'vscode';
4 | import { insertBind } from '../controlers/string';
5 | import config from '../config';
6 |
7 | let executeSingleton = false;
8 |
9 | type CmdParam = {
10 | command: string,
11 | args: any[],
12 | }
13 |
14 | export function executeCommands(commands: Array) {
15 | if (executeSingleton) {
16 | return;
17 | }
18 | executeSingleton = true;
19 |
20 | const waitPattern = new RegExp('^wait(:([0-9]+)){0,1}$');
21 | const typePattern = new RegExp('^type:([\\s\\S]+)', 'gm');
22 | const loopFunction = async (i) => {
23 | if (i >= commands.length) {
24 | executeSingleton = false;
25 | return;
26 | }
27 | const command = commands[i];
28 | if (typeof command === 'function') {
29 | command();
30 | loopFunction(++i);
31 | } else if (typeof command === 'object') {
32 | await Commands.executeCommand(command.command, command.args);
33 | loopFunction(++i);
34 | } else {
35 | const foundWait = waitPattern.exec(command);
36 | const foundType = typePattern.exec(command);
37 | if (foundWait) {
38 | setTimeout(() => {
39 | loopFunction(++i);
40 | }, foundWait[2] && parseInt(foundWait[2]) || config().macroDefaultWaitDelay);
41 | } else if (foundType) {
42 | await insertBind(foundType[1])
43 | loopFunction(++i);
44 | } else {
45 | await Commands.executeCommand(command);
46 | loopFunction(++i);
47 | }
48 | }
49 | }
50 | loopFunction(0);
51 | }
--------------------------------------------------------------------------------
/src/services/otherSelector.ts:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | import * as vscode from 'vscode';
3 | export function activate(context: vscode.ExtensionContext) {
4 | let editor = vscode.window.activeTextEditor;
5 | let disposable = vscode.commands.registerCommand('extension.doDuplicate', () => {
6 | let activeSelections = editor.selections;
7 | // inline copy
8 | editor.edit(editBuilder => {
9 | // for multiple selections
10 | for (var i = 0; i < activeSelections.length; ++i) {
11 | editBuilder.insert(activeSelections[i].end, editor.document.getText(activeSelections[i]));
12 | }
13 | });
14 | // to keep the cursor where the user first put it
15 | editor.selections = activeSelections;
16 | });
17 | let disposable2 = vscode.commands.registerCommand('extension.doFastDeploy', () => {
18 | if (editor.selection.isSingleLine) {
19 | let lineNumber = new vscode.Position(editor.selection.start.line, 0);
20 | let endNumber = lineNumber.translate(1, 0);
21 | let stringToParse = editor.document.getText(new vscode.Range(lineNumber, endNumber));
22 | let indexOfSelection = editor.selection.active.character;
23 | let rangeOfBrackets = bracketSearch(stringToParse, indexOfSelection);
24 | let firstOpen = rangeOfBrackets[0]
25 | let firstClose = rangeOfBrackets[1];
26 | // if we fail to find brackets, we ignore the command
27 | if (firstClose == -1) return;
28 | editor.edit(editBuilder => {
29 | let indentationChar = editor.options.insertSpaces ? ' ' : '\t';
30 | let levelOfIndent = stringToParse.search(/\S/);
31 | let rangeToDelete = new vscode.Range(new vscode.Position(editor.selection.start.line, firstOpen),
32 | new vscode.Position(editor.selection.start.line, firstClose));
33 | let padding = indentationChar.repeat(levelOfIndent + editor.options.tabSize);
34 | let params = ('\n' + stringToParse.substring(+firstOpen, firstClose) + '\n').split(',').map(Function.prototype.call, String.prototype.trim);
35 | editBuilder.replace(rangeToDelete, ('\n' + padding + params.join(',' + '\n' + padding)) + '\n' + indentationChar.repeat(levelOfIndent));
36 |
37 | });
38 | }
39 | });
40 |
41 | context.subscriptions.push(disposable);
42 | }
43 |
44 | // tries to find the bracket pair at the active cursor level (ie will ignore parameters that
45 | // have brackets in them)
46 | function bracketSearch(str: string, index: number) {
47 | let unmatchedBrace = 0;
48 | let unmatchedParen = 0;
49 | let indexBrace, indexParen;
50 | for (let i = index; i <= str.length; ++i) {
51 | if (str[i] == '{') {
52 | unmatchedBrace++;
53 | }
54 | else if (str[i] == '(') {
55 | unmatchedParen++;
56 | }
57 | else if (str[i] == '}') {
58 | if (unmatchedBrace > 0) {
59 | unmatchedBrace--;
60 | } else {
61 | indexBrace = i;
62 | break;
63 | }
64 | }
65 | else if (str[i] == ')') {
66 | if (unmatchedParen > 0) {
67 | unmatchedParen--;
68 | } else {
69 | indexParen = i;
70 | break;
71 | }
72 | }
73 | }
74 | if (indexBrace) {
75 | unmatchedBrace = 0;
76 | for (let i = index; i >= 0; --i) {
77 | if (str[i] == '}') {
78 | unmatchedBrace++;
79 | }
80 | else if (str[i] == '{') {
81 | if (unmatchedBrace > 0) {
82 | unmatchedBrace--;
83 | } else {
84 | return [i + 1, indexBrace];
85 | }
86 | }
87 | }
88 | } else if (indexParen) {
89 | unmatchedParen = 0;
90 | for (let i = index; i >= 0; --i) {
91 | if (str[i] == ')') {
92 | unmatchedParen++;
93 | }
94 | else if (str[i] == '(') {
95 | if (unmatchedParen > 0) {
96 | unmatchedParen--;
97 | } else {
98 | return [i + 1, indexParen];
99 | }
100 | }
101 | }
102 | } else {
103 | return [-1, -1];
104 | }
105 | }
106 |
107 | // this method is called when your extension is deactivated
108 | export function deactivate() {
109 | }
110 |
--------------------------------------------------------------------------------
/src/services/ownSelector.ts:
--------------------------------------------------------------------------------
1 | import { Position } from 'vscode';
2 |
3 | const starters = ['"', "'", "`", "(", "[", '{'];
4 | const enders = ['"', "'", "`", ")", "]", '}'];
5 |
6 | // export function getPrevious(charList: string[], from: Position): Position {
7 |
8 | // }
9 |
10 | // export function getNext(charList: string[], from: Position): Position {
11 |
12 | // }
--------------------------------------------------------------------------------
/src/services/parser.ts:
--------------------------------------------------------------------------------
1 | import { Range, Position } from 'vscode';
2 | import { RangeBuilder } from '../models/RangeBuilder';
3 |
4 | /// excellent document parser by Vilic :
5 | // https://github.com/vilic/vscode-es-quotes
6 |
7 | export const enum StringType {
8 | singleQuoted,
9 | doubleQuoted,
10 | template
11 | }
12 |
13 | interface InterStringGroupTarget extends StringGroupTarget {
14 | bracketStack: string[];
15 | partials: InterStringTarget[];
16 | }
17 |
18 | export interface StringBodyTarget {
19 | /** ", ', ` or } */
20 | opening: string;
21 | /** ", ', ` or ${ */
22 | closing: string;
23 | type: StringType;
24 | body: string;
25 | range: Range;
26 | }
27 |
28 | export interface StringGroupTarget {
29 | partials: StringTarget[];
30 | hasLowPriorityOperator: boolean;
31 | whitespacesRangeAtBeginning: Range;
32 | whitespacesRangeAtEnd: Range;
33 | }
34 |
35 | export type StringTarget = StringBodyTarget | StringGroupTarget;
36 |
37 | type InterStringTarget = StringBodyTarget | InterStringGroupTarget;
38 |
39 | const parsingRegex = /* /$parsing/ */ /(\/\*[\s\S]*?(?:\*\/|$)|\/\/.*\r?\n)|(["'])((?:\\(?:\r\n|[^])|(?!\2|\\).)*)(\2)?|\/(?:\\.|\[(?:\\.|[^\]\\\r\n])*\]?|[^\\\/\r\n])+\/|(`)|([()\[\]{}])|([?&|+-]|&&|\|\||<<|>>>?)|(\s+)|[^]/g;
40 | const templateStringRegex = /* /$templateString/ */ /([`}])((?:\\[^]|(?!\$\{)[^`])*)(`|\$\{)?/g; // This comment is to fix highlighting: `
41 |
42 | /* /$parsing/ */
43 | const enum ParsingRegexIndex {
44 | comment = 1,
45 | quote,
46 | stringBody,
47 | closingQuote,
48 | templateStringQuote,
49 | bracket,
50 | operator,
51 | whitespace
52 | }
53 |
54 | /* /$templateString/ */
55 | const enum TemplateStringRegexIndex {
56 | quote = 1,
57 | stringBody,
58 | closingQuote
59 | }
60 |
61 | const bracketConsumptionPair: {
62 | [key: string]: string;
63 | } = {
64 | '}': '{',
65 | ']': '[',
66 | ')': '('
67 | };
68 |
69 | export interface ParseResult {
70 | defaultQuote: string;
71 | stringTargets: StringTarget[];
72 | }
73 |
74 | export function findActiveStringTarget(targets: StringTarget[], selection: Range): StringBodyTarget {
75 | for (let target of targets) {
76 | let partials = (target as StringGroupTarget).partials;
77 | if (partials) {
78 | let foundTarget = findActiveStringTarget(partials, selection);
79 | if (foundTarget) {
80 | return foundTarget;
81 | }
82 | } else {
83 | if ((target as StringBodyTarget).range.contains(selection)) {
84 | return target as StringBodyTarget;
85 | }
86 | }
87 | }
88 |
89 | return undefined;
90 | }
91 |
92 | export function parse(source: string): ParseResult {
93 | let rangeBuilder = new RangeBuilder(source);
94 |
95 | let rootStringTargets: InterStringTarget[] = [];
96 | let nestedStringTargetStack: InterStringTarget[] = [];
97 |
98 | let currentGroupTarget: InterStringGroupTarget;
99 | let currentStringTargets = rootStringTargets;
100 | let currentBracketStack: string[];
101 |
102 | let isNewGroupTarget: boolean;
103 |
104 | let groups: RegExpExecArray;
105 |
106 | let doubleQuotedCount = 0;
107 | let singleQuotedCount = 0;
108 |
109 | while (groups = parsingRegex.exec(source)) {
110 | let text = groups[0];
111 |
112 | isNewGroupTarget = false;
113 |
114 | if (groups[ParsingRegexIndex.comment]) {
115 | // Do nothing.
116 | } else if (groups[ParsingRegexIndex.quote]) {
117 | let quote = groups[ParsingRegexIndex.quote];
118 | let body = groups[ParsingRegexIndex.stringBody];
119 | let range = rangeBuilder.getRange(parsingRegex.lastIndex - text.length, parsingRegex.lastIndex);
120 |
121 | // TODO:
122 | // if (currentBracketStack && currentBracketStack.length) {
123 | // pushNestedTargetStack();
124 | // }
125 |
126 | let type: StringType;
127 |
128 | if (quote === '"') {
129 | type = StringType.doubleQuoted;
130 | doubleQuotedCount++;
131 | } else {
132 | type = StringType.singleQuoted;
133 | singleQuotedCount++;
134 | }
135 |
136 | let target: StringBodyTarget = {
137 | body,
138 | range,
139 | opening: quote,
140 | closing: quote,
141 | type
142 | };
143 |
144 | currentStringTargets.push(target);
145 | } else if (
146 | groups[ParsingRegexIndex.templateStringQuote] || (
147 | nestedStringTargetStack.length &&
148 | currentBracketStack.indexOf('{') < 0 &&
149 | groups[ParsingRegexIndex.bracket] === '}'
150 | )
151 | ) {
152 | if (groups[ParsingRegexIndex.templateStringQuote]) {
153 | // `abc${123}def`
154 | // ^
155 | pushNestedTargetStack();
156 | } else {
157 | // `abc${123}def`
158 | // ^
159 | popNestedTargetStack();
160 | }
161 |
162 | templateStringRegex.lastIndex = parsingRegex.lastIndex - groups[0].length;
163 |
164 | // The match below should always success.
165 | let templateStringGroups = templateStringRegex.exec(source);
166 | let templateStringText = templateStringGroups[0];
167 |
168 | parsingRegex.lastIndex = templateStringRegex.lastIndex;
169 |
170 | let body = templateStringGroups[TemplateStringRegexIndex.stringBody];
171 |
172 | let range = rangeBuilder.getRange(
173 | templateStringRegex.lastIndex - templateStringText.length,
174 | templateStringRegex.lastIndex
175 | );
176 |
177 | let openingQuote = templateStringGroups[TemplateStringRegexIndex.quote];
178 | let closingQuote = templateStringGroups[TemplateStringRegexIndex.closingQuote] || '`';
179 |
180 | let target: StringBodyTarget = {
181 | body,
182 | range,
183 | opening: openingQuote,
184 | closing: closingQuote,
185 | type: StringType.template
186 | };
187 |
188 | currentStringTargets.push(target);
189 |
190 | if (closingQuote === '${') {
191 | // `abc${123}def`
192 | // ^
193 | pushNestedTargetStack();
194 | } else {
195 | // `abc${123}def`
196 | // ^
197 | popNestedTargetStack();
198 | }
199 | } else if (currentBracketStack) {
200 | if (groups[ParsingRegexIndex.bracket]) {
201 | let bracket = groups[ParsingRegexIndex.bracket];
202 |
203 | if (bracket in bracketConsumptionPair) {
204 | let bra = bracketConsumptionPair[bracket];
205 | if (currentBracketStack.length && bra === currentBracketStack[currentBracketStack.length - 1]) {
206 | currentBracketStack.pop();
207 | } else {
208 | // Otherwise there might be some syntax error, but we don't really care.
209 | console.warn(`Mismatched right bracket "${bracket}".`);
210 | }
211 | } else {
212 | currentBracketStack.push(bracket);
213 | }
214 | } else if (!currentBracketStack.length && groups[ParsingRegexIndex.operator]) {
215 | currentGroupTarget.hasLowPriorityOperator = true;
216 | }
217 | }
218 |
219 | if (currentGroupTarget) {
220 | if (groups[ParsingRegexIndex.whitespace]) {
221 | let range = rangeBuilder.getRange(parsingRegex.lastIndex - text.length, parsingRegex.lastIndex);
222 |
223 | if (currentGroupTarget.whitespacesRangeAtBeginning instanceof Range) {
224 | currentGroupTarget.whitespacesRangeAtEnd = range;
225 | } else {
226 | currentGroupTarget.whitespacesRangeAtBeginning = range;
227 | }
228 | } else if (!isNewGroupTarget) {
229 | if (currentGroupTarget.whitespacesRangeAtBeginning instanceof Range) {
230 | let start = rangeBuilder.getPosition(parsingRegex.lastIndex);
231 | let range = new Range(start, start);
232 |
233 | currentGroupTarget.whitespacesRangeAtEnd = range;
234 | } else {
235 | let end = rangeBuilder.getPosition(parsingRegex.lastIndex - text.length);
236 | let range = new Range(end, end);
237 |
238 | currentGroupTarget.whitespacesRangeAtBeginning = range;
239 | }
240 | }
241 | }
242 | }
243 |
244 | finalizeTargets(rootStringTargets);
245 |
246 | return {
247 | defaultQuote: singleQuotedCount < doubleQuotedCount ? '"' : "'",
248 | stringTargets: rootStringTargets
249 | };
250 |
251 | function pushNestedTargetStack(): void {
252 | let target: InterStringGroupTarget = {
253 | partials: [],
254 | bracketStack: [],
255 | hasLowPriorityOperator: false,
256 | whitespacesRangeAtBeginning: undefined,
257 | whitespacesRangeAtEnd: undefined
258 | };
259 |
260 | currentStringTargets.push(target);
261 |
262 | currentGroupTarget = target;
263 | currentStringTargets = target.partials;
264 | currentBracketStack = target.bracketStack;
265 | nestedStringTargetStack.push(target);
266 |
267 | isNewGroupTarget = true;
268 | }
269 |
270 | function popNestedTargetStack(): void {
271 | nestedStringTargetStack.pop();
272 |
273 | let lastIndex = nestedStringTargetStack.length - 1;
274 |
275 | if (lastIndex < 0) {
276 | currentGroupTarget = undefined;
277 | currentStringTargets = rootStringTargets;
278 | currentBracketStack = undefined;
279 | } else {
280 | let target = nestedStringTargetStack[lastIndex] as InterStringGroupTarget;
281 | currentGroupTarget = target;
282 | currentStringTargets = target.partials;
283 | currentBracketStack = target.bracketStack;
284 | }
285 | }
286 |
287 | function finalizeTargets(targets: InterStringTarget[]) {
288 | for (let i = 0; i < targets.length; i++) {
289 | let target = targets[i] as InterStringGroupTarget;
290 |
291 | if (target.partials) {
292 | delete target.bracketStack;
293 |
294 | finalizeTargets(target.partials);
295 | }
296 | }
297 | }
298 | }
299 |
300 | export function isStringGroupTarget(target: StringGroupTarget | StringBodyTarget): target is StringGroupTarget {
301 | return !!(target as StringGroupTarget).partials;
302 | }
303 |
304 | export function isStringBodyTarget(target: StringGroupTarget | StringBodyTarget): target is StringBodyTarget {
305 | return !(target as StringGroupTarget).partials;
306 | }
--------------------------------------------------------------------------------
/src/services/selector.ts:
--------------------------------------------------------------------------------
1 | // good selecting library by dbankier
2 | // https://github.com/dbankier/vscode-quick-select/blob/master/src/extension.ts
3 |
4 | import * as vscode from 'vscode';
5 |
6 | function findOccurances(doc: vscode.TextDocument, line: number, char: string): Array {
7 | var content = doc.lineAt(line);
8 | var matches = (content.text + "hack").split(char).reduce((acc, p) => {
9 | var len = p.length + 1;
10 | if (acc.length > 0) {
11 | len += acc[acc.length - 1];
12 | }
13 | acc.push(len);
14 | return acc;
15 | }, []);
16 | matches.pop();
17 | return matches;
18 | }
19 |
20 | function findNext(doc: vscode.TextDocument, line: number, char: string, start_index: number = 0, nest_char: string = undefined, nested: number = 0): vscode.Position {
21 | if (line === doc.lineCount) { return undefined };
22 | var occurances = findOccurances(doc, line, char).filter(n => n >= start_index);
23 | var nests = nest_char ? findOccurances(doc, line, nest_char).filter(n => n >= start_index) : [];
24 | var occurance_index = 0;
25 | var nests_index = 0;
26 | while ((occurance_index < occurances.length || nests_index < nests.length) && nested >= 0) {
27 | if (occurances[occurance_index] < nests[nests_index] || !nests[nests_index]) {
28 | if (nested === 0) {
29 | return new vscode.Position(line, occurances[occurance_index]);
30 | }
31 | nested--
32 | occurance_index++;
33 | } else if (nests[nests_index] < occurances[occurance_index] || !occurances[occurance_index]) {
34 | nested++;
35 | nests_index++;
36 | }
37 | }
38 | return findNext(doc, ++line, char, 0, nest_char, nested);
39 | }
40 |
41 | function findPrevious(doc: vscode.TextDocument, line: number, char: string, start_index?: number, nest_char: string = undefined, nested: number = 0): vscode.Position {
42 | if (line === -1) { return undefined };
43 | if (start_index === undefined) { start_index = doc.lineAt(line).text.length; }
44 | var occurances = findOccurances(doc, line, char).filter(n => n <= start_index);
45 | var nests = nest_char ? findOccurances(doc, line, nest_char).filter(n => n <= start_index) : [];
46 | var occurance_index = occurances.length - 1;
47 | var nests_index = nests.length - 1;
48 | while ((occurance_index > -1 || nests_index > -1) && nested >= 0) {
49 | if (occurances[occurance_index] > nests[nests_index] || !nests[nests_index]) {
50 | if (nested === 0) {
51 | return new vscode.Position(line, occurances[occurance_index]);
52 | }
53 | nested--
54 | occurance_index--;
55 | } else if (nests[nests_index] > occurances[occurance_index] || !occurances[occurance_index]) {
56 | nested++;
57 | nests_index--;
58 | }
59 | }
60 | return findPrevious(doc, --line, char, undefined, nest_char, nested);
61 | }
62 |
63 | function findSingleSelect(s: vscode.Selection, doc: vscode.TextDocument, char: string, outer?: boolean, multiline?: boolean) {
64 | let { line, character } = s.active;
65 | let matches = findOccurances(doc, line, char);
66 | let next = matches.find(a => a > character);
67 | let next_index = matches.indexOf(next);
68 | let offset = outer ? char.length : 0;
69 | if (matches.length > 1 && matches.length % 2 === 0) {
70 | // Jump inside the next matching pair
71 | if (next === -1) { return s }
72 | if (next_index % 2 !== 0) {
73 | next_index--;
74 | }
75 | //Automatically grow to outer selection
76 | if (!outer &&
77 | new vscode.Position(line, matches[next_index]).isEqual(s.anchor) &&
78 | new vscode.Position(line, matches[next_index + 1] - 1).isEqual(s.end)) {
79 | offset = char.length
80 | }
81 | return new vscode.Selection(
82 | new vscode.Position(line, matches[next_index] - offset),
83 | new vscode.Position(line, matches[next_index + 1] - 1 + offset)
84 | );
85 | } else if (multiline) {
86 | let start_pos = findPrevious(doc, line, char, character) || new vscode.Position(line, matches[next_index])
87 | if (!start_pos) { return s };
88 | let end_pos: vscode.Position = findNext(doc, start_pos.line, char, start_pos.character + 1);
89 | //Automatically grow to outer selection
90 | if (!outer &&
91 | start_pos.isEqual(s.anchor) &&
92 | new vscode.Position(end_pos.line, end_pos.character - 1).isEqual(s.end)) {
93 | offset = char.length
94 | }
95 | if (start_pos && end_pos) {
96 | start_pos = new vscode.Position(start_pos.line, start_pos.character - offset);
97 | end_pos = new vscode.Position(end_pos.line, end_pos.character - 1 + offset);
98 | return new vscode.Selection(start_pos, end_pos)
99 | }
100 | }
101 | return s;
102 |
103 | }
104 |
105 | export function selectEitherQuote(updateSelect: boolean = true) {
106 | let editor = vscode.window.activeTextEditor;
107 | if (!editor) { return; };
108 | let doc = editor.document
109 | let sel = editor.selections
110 | const selectionsResult = sel.map((s: vscode.Selection) => {
111 | let selections = ['"', "'", "`"].map(char => findSingleSelect(s, doc, char, false, char === '`'))
112 | .filter(sel => sel !== s)
113 | .filter(sel => sel.start.isBeforeOrEqual(s.start) && sel.end.isAfterOrEqual(s.end))
114 | .sort((a, b) => a.start.isBefore(b.start) ? 1 : -1)
115 | if (selections.length > 0) {
116 | return selections[0]
117 | }
118 | return s;
119 | })
120 |
121 | if (updateSelect) {
122 | editor.selections = selectionsResult
123 | }
124 |
125 | return selectionsResult
126 | }
127 |
128 | interface MatchingSelectOptions { start_char: string, end_char: string, outer?: boolean }
129 | export function matchingSelect(
130 | { start_char, end_char, outer = false }: MatchingSelectOptions,
131 | updateSelect: boolean = true
132 | ) {
133 | let editor = vscode.window.activeTextEditor;
134 | if (!editor) { return; };
135 | let doc = editor.document
136 | let sel = editor.selections
137 | let success = false;
138 | let start_offset = outer ? start_char.length : 0;
139 | let end_offset = outer ? end_char.length : 0;
140 | const selections = sel.map(s => {
141 | let { line, character } = s.active;
142 | let starts = findOccurances(doc, line, start_char);
143 | // let ends = findOccurances(doc, line, end_char);
144 | let start = starts.find(a => a > character);
145 | // let end = ends.find(a => a > character);
146 | let start_index = starts.indexOf(start);
147 | // let end_index = ends.indexOf(end);
148 | let start_pos: vscode.Position = findPrevious(doc, line, start_char, character, end_char) || new vscode.Position(line, starts[start_index]);
149 | if (!start_pos) { return s };
150 | let end_pos: vscode.Position = findNext(doc, start_pos.line, end_char, start_pos.character + 1, start_char);
151 | if (start_pos && end_pos) {
152 | success = true;
153 | //Automatically grow to outer selection
154 | if (!outer &&
155 | start_pos.isEqual(s.anchor) &&
156 | new vscode.Position(end_pos.line, end_pos.character - 1).isEqual(s.end)) {
157 | start_offset = start_char.length;
158 | end_offset = end_char.length;
159 | }
160 | start_pos = new vscode.Position(start_pos.line, start_pos.character - start_offset);
161 | end_pos = new vscode.Position(end_pos.line, end_pos.character - 1 + end_offset);
162 |
163 | return new vscode.Selection(start_pos, end_pos)
164 | }
165 | return s;
166 | })
167 | if (updateSelect) {
168 | editor.selections = selections
169 | if (success && start_char === "<") {
170 | vscode.commands.executeCommand("editor.action.addSelectionToNextFindMatch")
171 | }
172 | }
173 | return selections
174 | }
175 |
176 | export function cleverSelect() {
177 | let editor = vscode.window.activeTextEditor;
178 | if (!editor) { return; };
179 | // let doc = editor.document
180 | let sel = editor.selections
181 | editor.selections = sel.map((s: vscode.Selection) => {
182 | let selectionsBlocks = [
183 | { start_char: "(", end_char: ")" },
184 | { start_char: "[", end_char: "]" },
185 | { start_char: "{", end_char: "}" },
186 | { start_char: "<", end_char: ">" },
187 | { start_char: ">", end_char: "<" }
188 | ].map(opt => {
189 | const selections = matchingSelect(opt, false)
190 | if (selections && selections.length > 0) {
191 | return selections[0]
192 | }
193 | return s
194 | })
195 |
196 | const selections = [
197 | ...selectionsBlocks,
198 | ...selectEitherQuote(false)
199 | ].filter(sel => sel.start !== s.start)
200 | .filter(
201 | sel =>
202 | sel.start.isBeforeOrEqual(s.start) &&
203 | sel.end.isAfterOrEqual(s.end)
204 | )
205 | .sort((a, b) => a.start.isBefore(b.start) ? 1 : -1)
206 |
207 | if (selections && selections.length > 0) {
208 | return selections[0]
209 | }
210 | return s
211 | })
212 | }
--------------------------------------------------------------------------------
/src/services/string.ts:
--------------------------------------------------------------------------------
1 |
2 | import {
3 | window as Window,
4 | SnippetString
5 | } from 'vscode';
6 | import config from '../config';
7 |
8 | export function insertSnippet(text: string) {
9 | Window.activeTextEditor.insertSnippet(new SnippetString(text));
10 | }
11 |
12 | export function insertBind(configChar: string) {
13 | // if(!config().disableRebindForEdit && config().rebind[configChar]) {
14 | // insertSnippet(config().rebind[configChar]);
15 | // } else {
16 | insertSnippet(configChar);
17 | // }
18 | }
19 |
--------------------------------------------------------------------------------
/src/utils/debug.ts:
--------------------------------------------------------------------------------
1 | import {
2 | window as Window
3 | } from 'vscode';
4 |
5 | export function alert(message: string) {
6 | Window.showInformationMessage(message);
7 | }
--------------------------------------------------------------------------------
/src/utils/editor.ts:
--------------------------------------------------------------------------------
1 |
2 | import {
3 | Selection,
4 | TextLine,
5 | window as Window
6 | } from 'vscode';
7 | import {EditorBuilder} from '../models/EditorBuilder';
8 | import {sortSelections} from '../utils/utils';
9 |
10 | function getLines(selection: Selection): Array {
11 | const lines: Array = [];
12 | for (var i = selection.start.line; i < selection.end.line + 1; i++) {
13 | lines.push(Window.activeTextEditor.document.lineAt(i));
14 | }
15 | return lines;
16 | }
17 |
18 | export function prepareEdit(
19 | cb: (
20 | editBuilder: EditorBuilder,
21 | selection: Selection,
22 | lines: Array
23 | ) => void,
24 | withSortSelections: boolean = true ) {
25 | const activeTextEditor = Window.activeTextEditor;
26 | activeTextEditor.edit((editBuilder) => {
27 | let selections = activeTextEditor.selections;
28 | if(withSortSelections){
29 | selections = sortSelections(selections);
30 | }
31 | selections.forEach((selection) => {
32 | cb(new EditorBuilder(editBuilder), selection, getLines(selection));
33 | });
34 | });
35 | }
36 |
--------------------------------------------------------------------------------
/src/utils/quote.ts:
--------------------------------------------------------------------------------
1 | import { StringBodyTarget } from '../services/parser';
2 |
3 | const quotes = {
4 | '"': {
5 | next: "'",
6 | current: '"',
7 | previous: "`",
8 | },
9 | "'": {
10 | next: "`",
11 | current: "'",
12 | previous: '"',
13 | },
14 | '`': {
15 | next: '"',
16 | current: '`',
17 | previous: "'",
18 | }
19 | }
20 |
21 | export function getNextQuotes(activeTarget: StringBodyTarget) : string {
22 | const quote = quotes[activeTarget.opening];
23 | const currentEscaped = new RegExp('\\\\' + quote.current, 'g');
24 | const nextToEscape = new RegExp(quote.next, 'g');
25 | const final = activeTarget.body
26 | .replace(currentEscaped, quote.current)
27 | .replace(nextToEscape, '\\' + quote.next);
28 |
29 | return quote.next + final + quote.next;
30 | }
--------------------------------------------------------------------------------
/src/utils/utils.ts:
--------------------------------------------------------------------------------
1 | import {
2 | Selection
3 | } from 'vscode';
4 |
5 | export function wait(ms: number): Promise {
6 | return new Promise(function(resolve) {
7 | setTimeout(resolve, ms);
8 | });
9 | }
10 |
11 | export function nextToken(c: string|number) : string|number {
12 | if(typeof c === 'string') {
13 | if( c === 'Z') {
14 | return 'A';
15 | } else if (c === 'z') {
16 | return 'a';
17 | } else {
18 | return String.fromCharCode(c.charCodeAt(0) + 1);
19 | }
20 | } else {
21 | return ++c;
22 | }
23 | }
24 |
25 | export function sortSelections(selections: Array) {
26 | return selections.sort((previous: Selection, next: Selection) : number => {
27 | const lineIsSmaller = previous.start.line < next.start.line;
28 | const lineIsEqual = previous.start.line === next.start.line;
29 | const characterIsSmaller = previous.start.character < next.start.character;
30 | const characterIsEqual = previous.start.character === next.start.character;
31 | if(lineIsEqual) {
32 | if(characterIsEqual) {
33 | return 0;
34 | } else if (characterIsSmaller) {
35 | return -1;
36 | } else {
37 | return 1;
38 | }
39 | } else if ( lineIsSmaller ) {
40 | return -1;
41 | } else {
42 | return 1;
43 | }
44 | });
45 | }
--------------------------------------------------------------------------------
/test/index.ts:
--------------------------------------------------------------------------------
1 | //
2 | // PLEASE DO NOT MODIFY / DELETE UNLESS YOU KNOW WHAT YOU ARE DOING
3 | //
4 | // This file is providing the test runner to use when running extension tests.
5 | // By default the test runner in use is Mocha based.
6 | //
7 | // You can provide your own test runner if you want to override it by exporting
8 | // a function run(testRoot: string, clb: (error:Error) => void) that the extension
9 | // host can call to run the tests. The test runner is expected to use console.log
10 | // to report the results back to the caller. When the tests are finished, return
11 | // a possible error to the callback or null if none.
12 |
13 | var testRunner = require('vscode/lib/testrunner');
14 |
15 | // You can directly control Mocha options by uncommenting the following lines
16 | // See https://github.com/mochajs/mocha/wiki/Using-mocha-programmatically#set-options for more info
17 | testRunner.configure({
18 | ui: 'tdd', // the TDD UI is being used in extension.test.ts (suite, test, etc.)
19 | useColors: true // colored output from test results
20 | });
21 |
22 | module.exports = testRunner;
--------------------------------------------------------------------------------
/test/main.test.ts:
--------------------------------------------------------------------------------
1 |
2 | import * as assert from 'assert';
3 | import * as vscode from 'vscode';
4 | import * as myExtension from '../src/main';
5 |
6 | // Defines a Mocha test suite to group tests of similar kind together
7 | suite("Extension Tests", () => {
8 |
9 | // Defines a Mocha unit test
10 | test("Something 1", () => {
11 | assert.equal(-1, [1, 2, 3].indexOf(5));
12 | assert.equal(-1, [1, 2, 3].indexOf(0));
13 | });
14 | });
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "module": "commonjs",
4 | "target": "es6",
5 | "outDir": "out",
6 | "lib": [
7 | "es6"
8 | ],
9 | "sourceMap": true,
10 | "rootDir": "."
11 | },
12 | "exclude": [
13 | "node_modules",
14 | ".vscode-test"
15 | ]
16 | }
--------------------------------------------------------------------------------
/yarn.lock:
--------------------------------------------------------------------------------
1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
2 | # yarn lockfile v1
3 |
4 |
5 | "@tootallnate/once@1":
6 | version "1.1.2"
7 | resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82"
8 | integrity sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==
9 |
10 | "@types/mocha@^2.2.42":
11 | version "2.2.48"
12 | resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-2.2.48.tgz#3523b126a0b049482e1c3c11877460f76622ffab"
13 | integrity sha512-nlK/iyETgafGli8Zh9zJVCTicvU3iajSkRwOh3Hhiva598CMqNJ4NcVCGMTGKpGpTYj/9R8RLzS9NAykSSCqGw==
14 |
15 | "@types/node@^6.0.88":
16 | version "6.14.13"
17 | resolved "https://registry.yarnpkg.com/@types/node/-/node-6.14.13.tgz#b6649578fc0b5dac88c4ef48a46cab33c50a6c72"
18 | integrity sha512-J1F0XJ/9zxlZel5ZlbeSuHW2OpabrUAqpFuC2sm2I3by8sERQ8+KCjNKUcq8QHuzpGMWiJpo9ZxeHrqrP2KzQw==
19 |
20 | agent-base@4, agent-base@^4.3.0:
21 | version "4.3.0"
22 | resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.3.0.tgz#8165f01c436009bccad0b1d122f05ed770efc6ee"
23 | integrity sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==
24 | dependencies:
25 | es6-promisify "^5.0.0"
26 |
27 | agent-base@6:
28 | version "6.0.2"
29 | resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77"
30 | integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==
31 | dependencies:
32 | debug "4"
33 |
34 | balanced-match@^1.0.0:
35 | version "1.0.0"
36 | resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
37 | integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c=
38 |
39 | brace-expansion@^1.1.7:
40 | version "1.1.11"
41 | resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
42 | integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==
43 | dependencies:
44 | balanced-match "^1.0.0"
45 | concat-map "0.0.1"
46 |
47 | browser-stdout@1.3.0:
48 | version "1.3.0"
49 | resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.0.tgz#f351d32969d32fa5d7a5567154263d928ae3bd1f"
50 | integrity sha1-81HTKWnTL6XXpVZxVCY9korjvR8=
51 |
52 | browser-stdout@1.3.1:
53 | version "1.3.1"
54 | resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60"
55 | integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==
56 |
57 | buffer-from@^1.0.0:
58 | version "1.1.1"
59 | resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef"
60 | integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==
61 |
62 | commander@2.15.1:
63 | version "2.15.1"
64 | resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f"
65 | integrity sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==
66 |
67 | commander@2.9.0:
68 | version "2.9.0"
69 | resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4"
70 | integrity sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=
71 | dependencies:
72 | graceful-readlink ">= 1.0.0"
73 |
74 | concat-map@0.0.1:
75 | version "0.0.1"
76 | resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
77 | integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
78 |
79 | debug@2.6.8:
80 | version "2.6.8"
81 | resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.8.tgz#e731531ca2ede27d188222427da17821d68ff4fc"
82 | integrity sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=
83 | dependencies:
84 | ms "2.0.0"
85 |
86 | debug@3.1.0:
87 | version "3.1.0"
88 | resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
89 | integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==
90 | dependencies:
91 | ms "2.0.0"
92 |
93 | debug@4:
94 | version "4.3.1"
95 | resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee"
96 | integrity sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==
97 | dependencies:
98 | ms "2.1.2"
99 |
100 | debug@^3.1.0:
101 | version "3.2.7"
102 | resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a"
103 | integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==
104 | dependencies:
105 | ms "^2.1.1"
106 |
107 | diff@3.2.0:
108 | version "3.2.0"
109 | resolved "https://registry.yarnpkg.com/diff/-/diff-3.2.0.tgz#c9ce393a4b7cbd0b058a725c93df299027868ff9"
110 | integrity sha1-yc45Okt8vQsFinJck98pkCeGj/k=
111 |
112 | diff@3.5.0:
113 | version "3.5.0"
114 | resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12"
115 | integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==
116 |
117 | es6-promise@^4.0.3:
118 | version "4.2.8"
119 | resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a"
120 | integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==
121 |
122 | es6-promisify@^5.0.0:
123 | version "5.0.0"
124 | resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203"
125 | integrity sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=
126 | dependencies:
127 | es6-promise "^4.0.3"
128 |
129 | escape-string-regexp@1.0.5:
130 | version "1.0.5"
131 | resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
132 | integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=
133 |
134 | fs.realpath@^1.0.0:
135 | version "1.0.0"
136 | resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
137 | integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8=
138 |
139 | glob@7.1.1:
140 | version "7.1.1"
141 | resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8"
142 | integrity sha1-gFIR3wT6rxxjo2ADBs31reULLsg=
143 | dependencies:
144 | fs.realpath "^1.0.0"
145 | inflight "^1.0.4"
146 | inherits "2"
147 | minimatch "^3.0.2"
148 | once "^1.3.0"
149 | path-is-absolute "^1.0.0"
150 |
151 | glob@7.1.2:
152 | version "7.1.2"
153 | resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15"
154 | integrity sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==
155 | dependencies:
156 | fs.realpath "^1.0.0"
157 | inflight "^1.0.4"
158 | inherits "2"
159 | minimatch "^3.0.4"
160 | once "^1.3.0"
161 | path-is-absolute "^1.0.0"
162 |
163 | glob@^7.1.2:
164 | version "7.1.6"
165 | resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6"
166 | integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==
167 | dependencies:
168 | fs.realpath "^1.0.0"
169 | inflight "^1.0.4"
170 | inherits "2"
171 | minimatch "^3.0.4"
172 | once "^1.3.0"
173 | path-is-absolute "^1.0.0"
174 |
175 | "graceful-readlink@>= 1.0.0":
176 | version "1.0.1"
177 | resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725"
178 | integrity sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=
179 |
180 | growl@1.10.5:
181 | version "1.10.5"
182 | resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e"
183 | integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==
184 |
185 | growl@1.9.2:
186 | version "1.9.2"
187 | resolved "https://registry.yarnpkg.com/growl/-/growl-1.9.2.tgz#0ea7743715db8d8de2c5ede1775e1b45ac85c02f"
188 | integrity sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8=
189 |
190 | has-flag@^1.0.0:
191 | version "1.0.0"
192 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa"
193 | integrity sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=
194 |
195 | has-flag@^3.0.0:
196 | version "3.0.0"
197 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
198 | integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0=
199 |
200 | he@1.1.1:
201 | version "1.1.1"
202 | resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd"
203 | integrity sha1-k0EP0hsAlzUVH4howvJx80J+I/0=
204 |
205 | http-proxy-agent@^2.1.0:
206 | version "2.1.0"
207 | resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz#e4821beef5b2142a2026bd73926fe537631c5405"
208 | integrity sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==
209 | dependencies:
210 | agent-base "4"
211 | debug "3.1.0"
212 |
213 | http-proxy-agent@^4.0.1:
214 | version "4.0.1"
215 | resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz#8a8c8ef7f5932ccf953c296ca8291b95aa74aa3a"
216 | integrity sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==
217 | dependencies:
218 | "@tootallnate/once" "1"
219 | agent-base "6"
220 | debug "4"
221 |
222 | https-proxy-agent@^2.2.1:
223 | version "2.2.4"
224 | resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz#4ee7a737abd92678a293d9b34a1af4d0d08c787b"
225 | integrity sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==
226 | dependencies:
227 | agent-base "^4.3.0"
228 | debug "^3.1.0"
229 |
230 | https-proxy-agent@^5.0.0:
231 | version "5.0.0"
232 | resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz#e2a90542abb68a762e0a0850f6c9edadfd8506b2"
233 | integrity sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==
234 | dependencies:
235 | agent-base "6"
236 | debug "4"
237 |
238 | inflight@^1.0.4:
239 | version "1.0.6"
240 | resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
241 | integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=
242 | dependencies:
243 | once "^1.3.0"
244 | wrappy "1"
245 |
246 | inherits@2:
247 | version "2.0.4"
248 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
249 | integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
250 |
251 | json3@3.3.2:
252 | version "3.3.2"
253 | resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.2.tgz#3c0434743df93e2f5c42aee7b19bcb483575f4e1"
254 | integrity sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=
255 |
256 | lodash._baseassign@^3.0.0:
257 | version "3.2.0"
258 | resolved "https://registry.yarnpkg.com/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz#8c38a099500f215ad09e59f1722fd0c52bfe0a4e"
259 | integrity sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=
260 | dependencies:
261 | lodash._basecopy "^3.0.0"
262 | lodash.keys "^3.0.0"
263 |
264 | lodash._basecopy@^3.0.0:
265 | version "3.0.1"
266 | resolved "https://registry.yarnpkg.com/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz#8da0e6a876cf344c0ad8a54882111dd3c5c7ca36"
267 | integrity sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=
268 |
269 | lodash._basecreate@^3.0.0:
270 | version "3.0.3"
271 | resolved "https://registry.yarnpkg.com/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz#1bc661614daa7fc311b7d03bf16806a0213cf821"
272 | integrity sha1-G8ZhYU2qf8MRt9A78WgGoCE8+CE=
273 |
274 | lodash._getnative@^3.0.0:
275 | version "3.9.1"
276 | resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5"
277 | integrity sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=
278 |
279 | lodash._isiterateecall@^3.0.0:
280 | version "3.0.9"
281 | resolved "https://registry.yarnpkg.com/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz#5203ad7ba425fae842460e696db9cf3e6aac057c"
282 | integrity sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=
283 |
284 | lodash.create@3.1.1:
285 | version "3.1.1"
286 | resolved "https://registry.yarnpkg.com/lodash.create/-/lodash.create-3.1.1.tgz#d7f2849f0dbda7e04682bb8cd72ab022461debe7"
287 | integrity sha1-1/KEnw29p+BGgruM1yqwIkYd6+c=
288 | dependencies:
289 | lodash._baseassign "^3.0.0"
290 | lodash._basecreate "^3.0.0"
291 | lodash._isiterateecall "^3.0.0"
292 |
293 | lodash.isarguments@^3.0.0:
294 | version "3.1.0"
295 | resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a"
296 | integrity sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=
297 |
298 | lodash.isarray@^3.0.0:
299 | version "3.0.4"
300 | resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-3.0.4.tgz#79e4eb88c36a8122af86f844aa9bcd851b5fbb55"
301 | integrity sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=
302 |
303 | lodash.keys@^3.0.0:
304 | version "3.1.2"
305 | resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-3.1.2.tgz#4dbc0472b156be50a0b286855d1bd0b0c656098a"
306 | integrity sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=
307 | dependencies:
308 | lodash._getnative "^3.0.0"
309 | lodash.isarguments "^3.0.0"
310 | lodash.isarray "^3.0.0"
311 |
312 | minimatch@3.0.4, minimatch@^3.0.2, minimatch@^3.0.4:
313 | version "3.0.4"
314 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
315 | integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==
316 | dependencies:
317 | brace-expansion "^1.1.7"
318 |
319 | minimist@0.0.8:
320 | version "0.0.8"
321 | resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
322 | integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=
323 |
324 | mkdirp@0.5.1:
325 | version "0.5.1"
326 | resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903"
327 | integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=
328 | dependencies:
329 | minimist "0.0.8"
330 |
331 | mocha@^3.5.0:
332 | version "3.5.3"
333 | resolved "https://registry.yarnpkg.com/mocha/-/mocha-3.5.3.tgz#1e0480fe36d2da5858d1eb6acc38418b26eaa20d"
334 | integrity sha512-/6na001MJWEtYxHOV1WLfsmR4YIynkUEhBwzsb+fk2qmQ3iqsi258l/Q2MWHJMImAcNpZ8DEdYAK72NHoIQ9Eg==
335 | dependencies:
336 | browser-stdout "1.3.0"
337 | commander "2.9.0"
338 | debug "2.6.8"
339 | diff "3.2.0"
340 | escape-string-regexp "1.0.5"
341 | glob "7.1.1"
342 | growl "1.9.2"
343 | he "1.1.1"
344 | json3 "3.3.2"
345 | lodash.create "3.1.1"
346 | mkdirp "0.5.1"
347 | supports-color "3.1.2"
348 |
349 | mocha@^5.2.0:
350 | version "5.2.0"
351 | resolved "https://registry.yarnpkg.com/mocha/-/mocha-5.2.0.tgz#6d8ae508f59167f940f2b5b3c4a612ae50c90ae6"
352 | integrity sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ==
353 | dependencies:
354 | browser-stdout "1.3.1"
355 | commander "2.15.1"
356 | debug "3.1.0"
357 | diff "3.5.0"
358 | escape-string-regexp "1.0.5"
359 | glob "7.1.2"
360 | growl "1.10.5"
361 | he "1.1.1"
362 | minimatch "3.0.4"
363 | mkdirp "0.5.1"
364 | supports-color "5.4.0"
365 |
366 | ms@2.0.0:
367 | version "2.0.0"
368 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
369 | integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=
370 |
371 | ms@2.1.2:
372 | version "2.1.2"
373 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
374 | integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
375 |
376 | ms@^2.1.1:
377 | version "2.1.3"
378 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
379 | integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
380 |
381 | once@^1.3.0:
382 | version "1.4.0"
383 | resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
384 | integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E=
385 | dependencies:
386 | wrappy "1"
387 |
388 | path-is-absolute@^1.0.0:
389 | version "1.0.1"
390 | resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
391 | integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18=
392 |
393 | semver@^5.4.1:
394 | version "5.7.1"
395 | resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
396 | integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
397 |
398 | source-map-support@^0.5.0:
399 | version "0.5.19"
400 | resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61"
401 | integrity sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==
402 | dependencies:
403 | buffer-from "^1.0.0"
404 | source-map "^0.6.0"
405 |
406 | source-map@^0.6.0:
407 | version "0.6.1"
408 | resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
409 | integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
410 |
411 | supports-color@3.1.2:
412 | version "3.1.2"
413 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.1.2.tgz#72a262894d9d408b956ca05ff37b2ed8a6e2a2d5"
414 | integrity sha1-cqJiiU2dQIuVbKBf83su2KbiotU=
415 | dependencies:
416 | has-flag "^1.0.0"
417 |
418 | supports-color@5.4.0:
419 | version "5.4.0"
420 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.4.0.tgz#1c6b337402c2137605efe19f10fec390f6faab54"
421 | integrity sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==
422 | dependencies:
423 | has-flag "^3.0.0"
424 |
425 | typescript@^4.2.2:
426 | version "4.2.2"
427 | resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.2.2.tgz#1450f020618f872db0ea17317d16d8da8ddb8c4c"
428 | integrity sha512-tbb+NVrLfnsJy3M59lsDgrzWIflR4d4TIUjz+heUnHZwdF7YsrMTKoRERiIvI2lvBG95dfpLxB21WZhys1bgaQ==
429 |
430 | vscode-test@^0.4.1:
431 | version "0.4.3"
432 | resolved "https://registry.yarnpkg.com/vscode-test/-/vscode-test-0.4.3.tgz#461ebf25fc4bc93d77d982aed556658a2e2b90b8"
433 | integrity sha512-EkMGqBSefZH2MgW65nY05rdRSko15uvzq4VAPM5jVmwYuFQKE7eikKXNJDRxL+OITXHB6pI+a3XqqD32Y3KC5w==
434 | dependencies:
435 | http-proxy-agent "^2.1.0"
436 | https-proxy-agent "^2.2.1"
437 |
438 | vscode@^1.1.5:
439 | version "1.1.37"
440 | resolved "https://registry.yarnpkg.com/vscode/-/vscode-1.1.37.tgz#c2a770bee4bb3fff765e2b72c7bcc813b8a6bb0a"
441 | integrity sha512-vJNj6IlN7IJPdMavlQa1KoFB3Ihn06q1AiN3ZFI/HfzPNzbKZWPPuiU+XkpNOfGU5k15m4r80nxNPlM7wcc0wg==
442 | dependencies:
443 | glob "^7.1.2"
444 | http-proxy-agent "^4.0.1"
445 | https-proxy-agent "^5.0.0"
446 | mocha "^5.2.0"
447 | semver "^5.4.1"
448 | source-map-support "^0.5.0"
449 | vscode-test "^0.4.1"
450 |
451 | wrappy@1:
452 | version "1.0.2"
453 | resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
454 | integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
455 |
--------------------------------------------------------------------------------