├── .gitignore ├── .vscode ├── launch.json ├── settings.json └── tasks.json ├── .vscodeignore ├── LICENSE.TXT ├── README.md ├── images ├── dec.gif ├── default.gif ├── hex.gif ├── icon.ico ├── icon.png ├── icon.svg └── settings.png ├── package.json ├── src ├── NumInserter.ts ├── TSSprintf.ts └── extension.ts ├── test ├── extension.test.ts └── index.ts ├── tsconfig.json ├── typings ├── node.d.ts └── vscode-typings.d.ts └── vsc-extension-quickstart.md /.gitignore: -------------------------------------------------------------------------------- 1 | out 2 | node_modules -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | // A launch configuration that compiles the extension and then opens it inside a new window 2 | { 3 | "version": "0.1.0", 4 | "configurations": [ 5 | { 6 | "name": "Launch Extension", 7 | "type": "extensionHost", 8 | "request": "launch", 9 | "runtimeExecutable": "${execPath}", 10 | "args": ["--extensionDevelopmentPath=${workspaceRoot}" ], 11 | "stopOnEntry": false, 12 | "sourceMaps": true, 13 | "outDir": "${workspaceRoot}/out/src", 14 | "preLaunchTask": "npm" 15 | }, 16 | { 17 | "name": "Launch Tests", 18 | "type": "extensionHost", 19 | "request": "launch", 20 | "runtimeExecutable": "${execPath}", 21 | "args": ["--extensionDevelopmentPath=${workspaceRoot}", "--extensionTestsPath=${workspaceRoot}/out/test" ], 22 | "stopOnEntry": false, 23 | "sourceMaps": true, 24 | "outDir": "${workspaceRoot}/out/test", 25 | "preLaunchTask": "npm" 26 | } 27 | ] 28 | } 29 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | // Place your settings in this file to overwrite default and user settings. 2 | { 3 | "files.exclude": { 4 | "out": false // set this to true to hide the "out" folder with the compiled JS files 5 | }, 6 | "search.exclude": { 7 | "out": true // set this to false to include "out" folder in search results 8 | }, 9 | "typescript.tsdk": "./node_modules/typescript/lib" // we want to use the TS server from our node_modules folder to control its version 10 | } -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | // Available variables which can be used inside of strings. 2 | // ${workspaceRoot}: the root folder of the team 3 | // ${file}: the current opened file 4 | // ${fileBasename}: the current opened file's basename 5 | // ${fileDirname}: the current opened file's dirname 6 | // ${fileExtname}: the current opened file's extension 7 | // ${cwd}: the current working directory of the spawned process 8 | 9 | // A task runner that calls a custom npm script that compiles the extension. 10 | { 11 | "version": "0.1.0", 12 | 13 | // we want to run npm 14 | "command": "npm", 15 | 16 | // the command is a shell script 17 | "isShellCommand": true, 18 | 19 | // show the output window only if unrecognized errors occur. 20 | "showOutput": "silent", 21 | 22 | // we run the custom script "compile" as defined in package.json 23 | "args": ["run", "compile", "--loglevel", "silent"], 24 | 25 | // The tsc compiler is started in watching mode 26 | "isWatching": true, 27 | 28 | // use the standard tsc in watch mode problem matcher to find compile problems in the output. 29 | "problemMatcher": "$tsc-watch" 30 | } -------------------------------------------------------------------------------- /.vscodeignore: -------------------------------------------------------------------------------- 1 | .vscode/** 2 | typings/** 3 | out/test/** 4 | test/** 5 | src/** 6 | **/*.map 7 | .gitignore 8 | tsconfig.json 9 | vsc-extension-quickstart.md 10 | -------------------------------------------------------------------------------- /LICENSE.TXT: -------------------------------------------------------------------------------- 1 | Insert Numbers License: 2 | GPL 3 | 4 | sprintf.js License: 5 | printf.js is licensed under the terms of the 3-clause BSD license. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # README 2 | ## Insert Numbers for Visual Studio Code 3 | An extension to insert increasing numbers. 4 | 5 | ![default behavior](images/default.gif) 6 | 7 | ## Usage 8 | * Command: `Insert Numbers` 9 | * Keybindings: `ctrl+alt+n` on Windows and Linux or `cmd+alt+n` on OSX 10 | 11 | ## Control format 12 | The format of the inserted numbers is controlled by a C-Style format string using in a sprintf function. 13 | 14 | There are two ways to change the default format string. 15 | * You can change your `settings.json` file to modify the default value: 16 | 17 | ![settings](images/settings.png) 18 | 19 | * You can input format string in the `InputBox` each time you toggle insert. The format string can be a single string like `%02d`: 20 | 21 | ![dec format](images/dec.gif) 22 | 23 | or with start number and step, like `%08X:0:4`: 24 | 25 | ![input format](images/hex.gif) 26 | 27 | ### Note 28 | * Do not input more than one type specifier in a format string. If you want to input more than one number, you can do it another time. 29 | * Do not input `':'` in format string. 30 | 31 | ## Thanks 32 | * [sprintf.js](https://github.com/alexei/sprintf.js) 33 | 34 | ## For more information or bug reports 35 | * [GitHub](https://github.com/Inori/vscode-InsertNumbers/) 36 | 37 | ## Changes 38 | * Version 0.9.0: April 29, 2016 39 | 40 | First version 41 | 42 | 43 | *Enjoy!* 44 | -------------------------------------------------------------------------------- /images/dec.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Inori/vscode-InsertNumbers/581e2ee45c96d0b68d6c19c5ebd3961ff9f614f3/images/dec.gif -------------------------------------------------------------------------------- /images/default.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Inori/vscode-InsertNumbers/581e2ee45c96d0b68d6c19c5ebd3961ff9f614f3/images/default.gif -------------------------------------------------------------------------------- /images/hex.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Inori/vscode-InsertNumbers/581e2ee45c96d0b68d6c19c5ebd3961ff9f614f3/images/hex.gif -------------------------------------------------------------------------------- /images/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Inori/vscode-InsertNumbers/581e2ee45c96d0b68d6c19c5ebd3961ff9f614f3/images/icon.ico -------------------------------------------------------------------------------- /images/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Inori/vscode-InsertNumbers/581e2ee45c96d0b68d6c19c5ebd3961ff9f614f3/images/icon.png -------------------------------------------------------------------------------- /images/icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | Created by potrace 1.13, written by Peter Selinger 2001-2015 9 | 10 | 12 | 14 | 16 | 21 | 22 | 24 | 28 | 38 | 42 | 44 | 47 | 49 | 51 | 54 | 55 | 57 | 60 | 62 | 63 | 65 | 67 | 69 | 71 | 74 | 86 | 88 | 114 | 121 | 123 | 130 | 132 | 134 | 136 | 137 | 138 | 140 | 144 | 146 | 148 | 150 | 151 | 152 | 153 | 154 | -------------------------------------------------------------------------------- /images/settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Inori/vscode-InsertNumbers/581e2ee45c96d0b68d6c19c5ebd3961ff9f614f3/images/settings.png -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "insertnumbers", 3 | "displayName": "Insert Numbers", 4 | "description": "Insert increasing numbers", 5 | "icon": "images/icon.ico", 6 | "version": "0.9.1", 7 | "publisher": "Asuka", 8 | "license": "SEE LICENSE IN LICENSE.TXT", 9 | "homepage": "https://github.com/Inori/vscode-InsertNumbers", 10 | "galleryBanner": { 11 | "color": "#0000FF", 12 | "theme": "dark" 13 | }, 14 | "repository": { 15 | "type": "git", 16 | "url": "https://github.com/Inori/vscode-InsertNumbers.git" 17 | }, 18 | "bugs": { 19 | "url": "https://github.com/Inori/vscode-InsertNumbers/issues", 20 | "email": "bingkan@outlook.com" 21 | }, 22 | "categories": [ 23 | "Other" 24 | ], 25 | "engines": { 26 | "vscode": "^1.0.0" 27 | }, 28 | "activationEvents": [ 29 | "onCommand:extension.insertNumbers" 30 | ], 31 | "main": "./out/src/extension", 32 | "contributes": { 33 | "commands": [{ 34 | "command": "extension.insertNumbers", 35 | "title": "Insert Numbers" 36 | }], 37 | 38 | "keybindings": [{ 39 | "command": "extension.insertNumbers", 40 | "key": "ctrl+alt+n", 41 | "mac": "cmd+alt+n", 42 | "when": "editorTextFocus" 43 | }] 44 | }, 45 | "scripts": { 46 | "vscode:prepublish": "node ./node_modules/vscode/bin/compile", 47 | "compile": "node ./node_modules/vscode/bin/compile -watch -p ./", 48 | "postinstall": "node ./node_modules/vscode/bin/install" 49 | }, 50 | "devDependencies": { 51 | "typescript": "^1.8.5", 52 | "vscode": "^0.11.0" 53 | } 54 | } -------------------------------------------------------------------------------- /src/NumInserter.ts: -------------------------------------------------------------------------------- 1 | ///// 2 | 3 | 'use strict'; 4 | // The module 'vscode' contains the VS Code extensibility API 5 | // Import the module and reference it with the alias vscode in your code below 6 | import * as vscode from 'vscode'; 7 | import { TSSprintf } from './TSSprintf'; 8 | 9 | 10 | interface IInsertSettngs 11 | { 12 | formatStr : string; 13 | start : number; 14 | step : number; 15 | } 16 | 17 | /** 18 | * InsertSettngs 19 | */ 20 | export class InsertSettngs implements IInsertSettngs 21 | { 22 | 23 | public formatStr : string; 24 | public start : number; 25 | public step : number; 26 | 27 | private _disposable: vscode.Disposable; 28 | 29 | constructor() 30 | { 31 | let subscriptions: vscode.Disposable[] = []; 32 | vscode.workspace.onDidChangeConfiguration(this.updateSettings, this, subscriptions); 33 | this._disposable = vscode.Disposable.from(...subscriptions); 34 | 35 | this.updateSettings(); 36 | } 37 | 38 | 39 | private updateSettings() 40 | { 41 | var settings = vscode.workspace.getConfiguration("insertnum"); 42 | if (!settings) 43 | { 44 | return; 45 | } 46 | 47 | //TODO: format check. 48 | this.formatStr = settings.get("formatstr"); 49 | if (!this.formatStr) 50 | { 51 | this.formatStr = "%d"; 52 | } 53 | 54 | this.start = settings.get("start"); 55 | if (!this.start) 56 | { 57 | this.start = 0; 58 | } 59 | 60 | this.step = settings.get("step"); 61 | if (!this.step) 62 | { 63 | this.step = 1; 64 | } 65 | 66 | } 67 | 68 | public dispose() 69 | { 70 | this._disposable.dispose(); 71 | } 72 | } 73 | 74 | /** 75 | * NumInserter 76 | */ 77 | export class NumInserter 78 | { 79 | 80 | private _settings : InsertSettngs; 81 | 82 | constructor(settings : InsertSettngs) 83 | { 84 | this._settings = settings; 85 | } 86 | 87 | private insertNumbers(settings : IInsertSettngs) 88 | { 89 | let textEditor = vscode.window.activeTextEditor; 90 | 91 | const selections : vscode.Selection[] = textEditor.selections; 92 | 93 | const formatStr = settings.formatStr; 94 | const start = settings.start; 95 | const step = settings.step; 96 | 97 | let cur = start; 98 | 99 | textEditor.edit 100 | ( 101 | function (builder) 102 | { 103 | for (var i = 0; i < selections.length; i++) 104 | { 105 | let str = TSSprintf.sprintf(formatStr, cur); 106 | cur += step; 107 | 108 | builder.replace(selections[i], str); 109 | } 110 | } 111 | ) 112 | } 113 | 114 | private parseUserInput(input : string) : IInsertSettngs 115 | { 116 | if (!input) { 117 | return; 118 | } 119 | 120 | let retSettings : IInsertSettngs = { 121 | formatStr : "%d", 122 | start : 0, 123 | step : 1 124 | }; 125 | 126 | //A simple check. :) 127 | if (!input.includes("%")) { 128 | vscode.window.showErrorMessage("Wrong format string."); 129 | return; 130 | } 131 | 132 | // eg... "%d:1:2" 133 | if (input.includes(":")) { 134 | 135 | let paramList = input.split(":", 3); 136 | 137 | retSettings.formatStr = paramList[0]; 138 | 139 | const strStart = paramList[1]; 140 | const strStep = paramList[2]; 141 | 142 | if (strStart.includes(".")) { 143 | retSettings.start = parseFloat(strStart); 144 | } 145 | else{ 146 | retSettings.start = parseInt(strStart); 147 | } 148 | 149 | if (strStep.includes(".")) { 150 | retSettings.step = parseFloat(strStep); 151 | } 152 | else{ 153 | retSettings.step = parseInt(strStep); 154 | } 155 | } 156 | //eg... "%d" 157 | else{ 158 | retSettings.formatStr = input; 159 | } 160 | 161 | return retSettings; 162 | } 163 | 164 | public processInsert() 165 | { 166 | //Input default numbers first. 167 | this.insertNumbers(this._settings); 168 | 169 | 170 | const opt : vscode.InputBoxOptions = { 171 | placeHolder : "default: %d:0:1", 172 | prompt : "Input format or format:start:step" 173 | } 174 | const input = vscode.window.showInputBox(opt); 175 | 176 | if (!input) 177 | { 178 | return; 179 | } 180 | 181 | let parseUserInput = this.parseUserInput; 182 | let insertNumbers = this.insertNumbers; 183 | 184 | let newSettings = null; 185 | 186 | input.then(function (val:string) { 187 | 188 | newSettings = parseUserInput(val); 189 | 190 | if (!newSettings) { 191 | return; 192 | } 193 | 194 | insertNumbers(newSettings); 195 | }) 196 | 197 | } 198 | 199 | 200 | public dispose() 201 | { 202 | this._settings.dispose(); 203 | } 204 | } -------------------------------------------------------------------------------- /src/TSSprintf.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * TSSprintf 5 | */ 6 | export class TSSprintf { 7 | 8 | private static re = { 9 | not_string: /[^s]/, 10 | not_bool: /[^t]/, 11 | not_type: /[^T]/, 12 | not_primitive: /[^v]/, 13 | number: /[diefg]/, 14 | numeric_arg: /bcdiefguxX/, 15 | json: /[j]/, 16 | not_json: /[^j]/, 17 | text: /^[^\x25]+/, 18 | modulo: /^\x25{2}/, 19 | placeholder: /^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-gijostTuvxX])/, 20 | key: /^([a-z_][a-z_\d]*)/i, 21 | key_access: /^\.([a-z_][a-z_\d]*)/i, 22 | index_access: /^\[(\d+)\]/, 23 | sign: /^[\+\-]/ 24 | }; 25 | 26 | private static preformattedPadding = { 27 | '0': ['', '0', '00', '000', '0000', '00000', '000000', '0000000'], 28 | ' ': ['', ' ', ' ', ' ', ' ', ' ', ' ', ' '], 29 | '_': ['', '_', '__', '___', '____', '_____', '______', '_______'], 30 | }; 31 | 32 | private static cache = {} 33 | 34 | constructor() { 35 | } 36 | 37 | public static sprintf(format: string, ...args: any[]): string { 38 | var key = format, cache = this.cache; 39 | 40 | if (!(cache[key] && cache.hasOwnProperty(key))) { 41 | cache[key] = this.parse(key); 42 | } 43 | return this.format(cache[key], args); 44 | } 45 | 46 | private static format(parse_tree, argv) { 47 | var cursor = 0, tree_length = parse_tree.length, node_type = '', arg, output = [], i, k, match, pad, pad_character, pad_length, is_positive = true, sign = ''; 48 | for (i = 0; i < tree_length; i++) { 49 | node_type = this.get_type(parse_tree[i]); 50 | if (node_type === 'string') { 51 | output[output.length] = parse_tree[i]; 52 | } 53 | else if (node_type === 'array') { 54 | match = parse_tree[i]; // convenience purposes only 55 | if (match[2]) { 56 | arg = argv[cursor]; 57 | for (k = 0; k < match[2].length; k++) { 58 | if (!arg.hasOwnProperty(match[2][k])) { 59 | throw new Error(TSSprintf.sprintf('[sprintf] property "%s" does not exist', match[2][k])); 60 | } 61 | arg = arg[match[2][k]]; 62 | } 63 | } 64 | else if (match[1]) { 65 | arg = argv[match[1]]; 66 | } 67 | else { 68 | arg = argv[cursor++]; 69 | } 70 | if (this.re.not_type.test(match[8]) && this.re.not_primitive.test(match[8]) && this.get_type(arg) == 'function') { 71 | arg = arg(); 72 | } 73 | if (this.re.numeric_arg.test(match[8]) && (this.get_type(arg) != 'number' && isNaN(arg))) { 74 | throw new TypeError(TSSprintf.sprintf("[sprintf] expecting number but found %s", this.get_type(arg))); 75 | } 76 | if (this.re.number.test(match[8])) { 77 | is_positive = arg >= 0; 78 | } 79 | switch (match[8]) { 80 | case 'b': 81 | arg = parseInt(arg, 10).toString(2); 82 | break; 83 | case 'c': 84 | arg = String.fromCharCode(parseInt(arg, 10)); 85 | break; 86 | case 'd': 87 | case 'i': 88 | arg = parseInt(arg, 10); 89 | break; 90 | case 'j': 91 | arg = JSON.stringify(arg, null, match[6] ? parseInt(match[6]) : 0); 92 | break; 93 | case 'e': 94 | arg = match[7] ? parseFloat(arg).toExponential(match[7]) : parseFloat(arg).toExponential(); 95 | break; 96 | case 'f': 97 | arg = match[7] ? parseFloat(arg).toFixed(match[7]) : parseFloat(arg); 98 | break; 99 | case 'g': 100 | arg = match[7] ? parseFloat(arg).toPrecision(match[7]) : parseFloat(arg); 101 | break; 102 | case 'o': 103 | arg = arg.toString(8); 104 | break; 105 | case 's': 106 | arg = String(arg); 107 | arg = (match[7] ? arg.substring(0, match[7]) : arg); 108 | break; 109 | case 't': 110 | arg = String(!!arg); 111 | arg = (match[7] ? arg.substring(0, match[7]) : arg); 112 | break; 113 | case 'T': 114 | arg = this.get_type(arg); 115 | arg = (match[7] ? arg.substring(0, match[7]) : arg); 116 | break; 117 | case 'u': 118 | arg = parseInt(arg, 10) >>> 0; 119 | break; 120 | case 'v': 121 | arg = arg.valueOf(); 122 | arg = (match[7] ? arg.substring(0, match[7]) : arg); 123 | break; 124 | case 'x': 125 | arg = parseInt(arg, 10).toString(16); 126 | break; 127 | case 'X': 128 | arg = parseInt(arg, 10).toString(16).toUpperCase(); 129 | break; 130 | } 131 | if (this.re.json.test(match[8])) { 132 | output[output.length] = arg; 133 | } 134 | else { 135 | if (this.re.number.test(match[8]) && (!is_positive || match[3])) { 136 | sign = is_positive ? '+' : '-'; 137 | arg = arg.toString().replace(this.re.sign, ''); 138 | } 139 | else { 140 | sign = ''; 141 | } 142 | pad_character = match[4] ? match[4] === '0' ? '0' : match[4].charAt(1) : ' '; 143 | pad_length = match[6] - (sign + arg).length; 144 | pad = match[6] ? (pad_length > 0 ? this.str_repeat(pad_character, pad_length) : '') : ''; 145 | output[output.length] = match[5] ? sign + arg + pad : (pad_character === '0' ? sign + pad + arg : pad + sign + arg); 146 | } 147 | } 148 | } 149 | return output.join(''); 150 | } 151 | 152 | private static parse(fmt){ 153 | var _fmt = fmt, match = [], parse_tree = [], arg_names = 0; 154 | while (_fmt) { 155 | if ((match = this.re.text.exec(_fmt)) !== null) { 156 | parse_tree[parse_tree.length] = match[0]; 157 | } 158 | else if ((match = this.re.modulo.exec(_fmt)) !== null) { 159 | parse_tree[parse_tree.length] = '%'; 160 | } 161 | else if ((match = this.re.placeholder.exec(_fmt)) !== null) { 162 | if (match[2]) { 163 | arg_names |= 1; 164 | var field_list = [], replacement_field = match[2], field_match = []; 165 | if ((field_match = this.re.key.exec(replacement_field)) !== null) { 166 | field_list[field_list.length] = field_match[1]; 167 | while ((replacement_field = replacement_field.substring(field_match[0].length)) !== '') { 168 | if ((field_match = this.re.key_access.exec(replacement_field)) !== null) { 169 | field_list[field_list.length] = field_match[1]; 170 | } 171 | else if ((field_match = this.re.index_access.exec(replacement_field)) !== null) { 172 | field_list[field_list.length] = field_match[1]; 173 | } 174 | else { 175 | throw new SyntaxError("[sprintf] failed to parse named argument key"); 176 | } 177 | } 178 | } 179 | else { 180 | throw new SyntaxError("[sprintf] failed to parse named argument key"); 181 | } 182 | match[2] = field_list; 183 | } 184 | else { 185 | arg_names |= 2; 186 | } 187 | if (arg_names === 3) { 188 | throw new Error("[sprintf] mixing positional and named placeholders is not (yet) supported"); 189 | } 190 | parse_tree[parse_tree.length] = match; 191 | } 192 | else { 193 | throw new SyntaxError("[sprintf] unexpected placeholder"); 194 | } 195 | _fmt = _fmt.substring(match[0].length); 196 | } 197 | return parse_tree; 198 | } 199 | 200 | private static get_type(variable){ 201 | if (typeof variable === 'number') { 202 | return 'number'; 203 | } 204 | else if (typeof variable === 'string') { 205 | return 'string'; 206 | } 207 | else { 208 | return Object.prototype.toString.call(variable).slice(8, -1).toLowerCase(); 209 | } 210 | } 211 | 212 | private static str_repeat(input, multiplier) { 213 | if (multiplier >= 0 && multiplier <= 7 && this.preformattedPadding[input]) { 214 | return this.preformattedPadding[input][multiplier]; 215 | } 216 | return Array(multiplier + 1).join(input); 217 | } 218 | } -------------------------------------------------------------------------------- /src/extension.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | // The module 'vscode' contains the VS Code extensibility API 3 | // Import the module and reference it with the alias vscode in your code below 4 | import * as vscode from 'vscode'; 5 | import {NumInserter, InsertSettngs} from './NumInserter' 6 | 7 | // this method is called when your extension is activated 8 | // your extension is activated the very first time the command is executed 9 | export function activate(context: vscode.ExtensionContext) { 10 | 11 | // Use the console to output diagnostic information (console.log) and errors (console.error) 12 | // This line of code will only be executed once when your extension is activated 13 | //console.log('Congratulations, your extension "insertnumbers" is now active!'); 14 | let settings = new InsertSettngs(); 15 | let inserter = new NumInserter(settings); 16 | // The command has been defined in the package.json file 17 | // Now provide the implementation of the command with registerCommand 18 | // The commandId parameter must match the command field in package.json 19 | let disposable = vscode.commands.registerCommand('extension.insertNumbers', () => { 20 | // The code you place here will be executed every time your command is executed 21 | 22 | inserter.processInsert(); 23 | // Display a message box to the user 24 | //vscode.window.showInformationMessage('Insert Numbers!'); 25 | }); 26 | 27 | context.subscriptions.push(disposable); 28 | context.subscriptions.push(settings); 29 | context.subscriptions.push(inserter); 30 | } 31 | 32 | // this method is called when your extension is deactivated 33 | export function deactivate() { 34 | } 35 | 36 | -------------------------------------------------------------------------------- /test/extension.test.ts: -------------------------------------------------------------------------------- 1 | // 2 | // Note: This example test is leveraging the Mocha test framework. 3 | // Please refer to their documentation on https://mochajs.org/ for help. 4 | // 5 | 6 | // The module 'assert' provides assertion methods from node 7 | import * as assert from 'assert'; 8 | 9 | // You can import and use all API from the 'vscode' module 10 | // as well as import your extension to test it 11 | import * as vscode from 'vscode'; 12 | import * as myExtension from '../src/extension'; 13 | 14 | // Defines a Mocha test suite to group tests of similar kind together 15 | suite("Extension Tests", () => { 16 | 17 | // Defines a Mocha unit test 18 | test("Something 1", () => { 19 | assert.equal(-1, [1, 2, 3].indexOf(5)); 20 | assert.equal(-1, [1, 2, 3].indexOf(0)); 21 | }); 22 | }); -------------------------------------------------------------------------------- /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; -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "es5", 5 | "outDir": "out", 6 | "noLib": true, 7 | "sourceMap": true, 8 | "rootDir": "." 9 | }, 10 | "exclude": [ 11 | "node_modules" 12 | ] 13 | } -------------------------------------------------------------------------------- /typings/node.d.ts: -------------------------------------------------------------------------------- 1 | /// -------------------------------------------------------------------------------- /typings/vscode-typings.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /vsc-extension-quickstart.md: -------------------------------------------------------------------------------- 1 | # Welcome to your first VS Code Extension 2 | 3 | ## What's in the folder 4 | * This folder contains all of the files necessary for your extension 5 | * `package.json` - this is the manifest file in which you declare your extension and command. 6 | The sample plugin registers a command and defines its title and command name. With this information 7 | VS Code can show the command in the command palette. It doesn’t yet need to load the plugin. 8 | * `src/extension.ts` - this is the main file where you will provide the implementation of your command. 9 | The file exports one function, `activate`, which is called the very first time your extension is 10 | activated (in this case by executing the command). Inside the `activate` function we call `registerCommand`. 11 | We pass the function containing the implementation of the command as the second parameter to 12 | `registerCommand`. 13 | 14 | ## Get up and running straight away 15 | * press `F5` to open a new window with your extension loaded 16 | * run your command from the command palette by pressing (`Ctrl+Shift+P` or `Cmd+Shift+P` on Mac) and typing `Hello World` 17 | * set breakpoints in your code inside `src/extension.ts` to debug your extension 18 | * find output from your extension in the debug console 19 | 20 | ## Make changes 21 | * you can relaunch the extension from the debug toolbar after changing code in `src/extension.ts` 22 | * you can also reload (`Ctrl+R` or `Cmd+R` on Mac) the VS Code window with your extension to load your changes 23 | 24 | ## Explore the API 25 | * you can open the full set of our API when you open the file `node_modules/vscode/vscode.d.ts` 26 | 27 | ## Run tests 28 | * open the debug viewlet (`Ctrl+Shift+D` or `Cmd+Shift+D` on Mac) and from the launch configuration dropdown pick `Launch Tests` 29 | * press `F5` to run the tests in a new window with your extension loaded 30 | * see the output of the test result in the debug console 31 | * make changes to `test/extension.test.ts` or create new test files inside the `test` folder 32 | * by convention, the test runner will only consider files matching the name pattern `**.test.ts` 33 | * you can create folders inside the `test` folder to structure your tests any way you want --------------------------------------------------------------------------------