diff --git a/README.md b/README.md index f8ded6e..7e1f727 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,16 @@ # Azure CLI Tools -Scrapbooks for developing and running commands with the [Azure CLI](https://aka.ms/AzureCLI2). +Scrapbooks for developing and running commands with the +[Azure CLI](https://aka.ms/AzureCLI2). Create `.azcli` files and use these features: -- IntelliSense for commands and their arguments. -- Snippets for commands, inserting required arguments automatically. -- Run the current command in the integrated terminal. -- Run the current command and show its output in a side-by-side editor. -- Show documentation on mouse hover. -- Display current subscription and defaults in status bar. + +- IntelliSense for commands and their arguments. +- Snippets for commands, inserting required arguments automatically. +- Run the current command in the integrated terminal. +- Run the current command and show its output in a side-by-side editor. +- Show documentation on mouse hover. +- Display current subscription and defaults in status bar. ![Azure CLI Tools in Action](images/in_action.gif) @@ -16,54 +18,70 @@ Create `.azcli` files and use these features: ### 0.5.0 -- PR [Support multiline commands when running in editor](https://github.com/Microsoft/vscode-azurecli/pull/61) by [@mburleigh](https://github.com/mburleigh). +- PR + [Support multiline commands when running in editor](https://github.com/Microsoft/vscode-azurecli/pull/61) + by [@mburleigh](https://github.com/mburleigh). ### 0.4.6 -- PR [Add status bar item to indicate progress](https://github.com/Microsoft/vscode-azurecli/pull/56) by [@mburleigh](https://github.com/mburleigh). -- PR [Open results in new editor](https://github.com/Microsoft/vscode-azurecli/pull/55) by [@mburleigh](https://github.com/mburleigh). -- Fix [Use CLIConfig](https://github.com/Microsoft/vscode-azurecli/issues/52). +- PR + [Add status bar item to indicate progress](https://github.com/Microsoft/vscode-azurecli/pull/56) + by [@mburleigh](https://github.com/mburleigh). +- PR + [Open results in new editor](https://github.com/Microsoft/vscode-azurecli/pull/55) + by [@mburleigh](https://github.com/mburleigh). +- Fix [Use CLIConfig](https://github.com/Microsoft/vscode-azurecli/issues/52). ### 0.4.5 -- Fix [Read defaults_section_name from config](https://github.com/Microsoft/vscode-azurecli/issues/50). +- Fix + [Read defaults_section_name from config](https://github.com/Microsoft/vscode-azurecli/issues/50). ### 0.4.4 -- Fix [wrong argument names](https://github.com/Microsoft/vscode-azurecli/issues/44). +- Fix + [wrong argument names](https://github.com/Microsoft/vscode-azurecli/issues/44). ### 0.4.3 -- Fix [Extension complaining az not on PATH](https://github.com/Microsoft/vscode-azurecli/issues/46). +- Fix + [Extension complaining az not on PATH](https://github.com/Microsoft/vscode-azurecli/issues/46). ### 0.4.2 -- Fix [no IntelliSense with latest Azure CLI](https://github.com/Microsoft/vscode-azurecli/issues/35). +- Fix + [no IntelliSense with latest Azure CLI](https://github.com/Microsoft/vscode-azurecli/issues/35). ### 0.4.1 -- Fix [Azure CLI installed with Homebrew](https://github.com/Microsoft/vscode-azurecli/issues/25). +- Fix + [Azure CLI installed with Homebrew](https://github.com/Microsoft/vscode-azurecli/issues/25). ### 0.4.0 -- Support for Azure CLI >=2.0.24 +- Support for Azure CLI >=2.0.24 ### 0.3.0 -- Fix [delayed completion proposals on Windows](https://github.com/Microsoft/vscode-azurecli/issues/19). -- Fix [completion proposals hang when az crashes](https://github.com/Microsoft/vscode-azurecli/issues/20). +- Fix + [delayed completion proposals on Windows](https://github.com/Microsoft/vscode-azurecli/issues/19). +- Fix + [completion proposals hang when az crashes](https://github.com/Microsoft/vscode-azurecli/issues/20). ### 0.2.0 -- Add 'Azure' marketplace category. -- Fix [failure when running commands in the Terminal](https://github.com/Microsoft/vscode-azurecli/issues/16). +- Add 'Azure' marketplace category. +- Fix + [failure when running commands in the Terminal](https://github.com/Microsoft/vscode-azurecli/issues/16). ### 0.1.0 -- Improve argument sort order in IntelliSense. -- Fix handling of spaces in az's path on Windows. Did not work with MSI install. -- Fix version check for older versions. Should show a message asking to update az. -- Smaller bugfixes. +- Improve argument sort order in IntelliSense. +- Fix handling of spaces in az's path on Windows. Did not work with MSI + install. +- Fix version check for older versions. Should show a message asking to update + az. +- Smaller bugfixes. ### 0.0.1 @@ -71,11 +89,19 @@ Initial release. ## Contributing -File bugs and feature requests in [GitHub Issues](https://github.com/Microsoft/vscode-azurecli/issues). +File bugs and feature requests in +[GitHub Issues](https://github.com/Microsoft/vscode-azurecli/issues). -Checkout the source code in the [GitHub Repository](https://github.com/Microsoft/vscode-azurecli). +Checkout the source code in the +[GitHub Repository](https://github.com/Microsoft/vscode-azurecli). -This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. +This project has adopted the +[Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). +For more information see the +[Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or +contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any +additional questions or comments. ## License + [MIT](LICENSE) diff --git a/Source/azService.ts b/Source/azService.ts index 25a2c82..8462aca 100644 --- a/Source/azService.ts +++ b/Source/azService.ts @@ -67,7 +67,7 @@ export class AzService { private listeners: { [sequence: number]: ( err: undefined | any, - response: Message | undefined, + response: Message | undefined ) => void; } = {}; private nextSequenceNumber = 1; @@ -81,7 +81,7 @@ export class AzService { async getCompletions( query: CompletionQuery, - onCancel: (handle: () => void) => void, + onCancel: (handle: () => void) => void ): Promise { try { return this.send(query, onCancel); @@ -97,20 +97,20 @@ export class AzService { async getHover( command: Command, - onCancel: (handle: () => void) => void, + onCancel: (handle: () => void) => void ): Promise { return this.send( { request: "hover", command, }, - onCancel, + onCancel ); } private async send( data: T, - onCancel?: (handle: () => void) => void, + onCancel?: (handle: () => void) => void ): Promise { const process = await this.getProcess(); return new Promise((resolve, reject) => { @@ -161,7 +161,7 @@ export class AzService { throw "wrongVersion"; } const pythonLocation = (/^Python location '([^']*)'/m.exec( - stdout, + stdout ) || [])[1]; const processOptions = await this.getSpawnProcessOptions(); return this.spawn(pythonLocation, processOptions); @@ -180,7 +180,7 @@ export class AzService { if (binPath.startsWith(cellarBasePath)) { const installPath = binPath.substr( 0, - binPath.indexOf("/", cellarBasePath.length), + binPath.indexOf("/", cellarBasePath.length) ); const libPath = `${installPath}/libexec/lib`; const entries = await readdir(libPath); @@ -202,10 +202,10 @@ export class AzService { const process = spawn( join( __dirname, - `../../service/az-service${isWindows ? ".bat" : ""}`, + `../../service/az-service${isWindows ? ".bat" : ""}` ), [pythonLocation], - processOptions, + processOptions ); process.stdout.setEncoding("utf8"); process.stdout.on("data", (data) => { @@ -237,7 +237,7 @@ export class AzService { delete this.listeners[sequence]; listener( `Python process terminated with exit code ${code}, signal ${signal}.`, - undefined, + undefined ); } }); diff --git a/Source/extension.ts b/Source/extension.ts index 30f5a4d..d16d87c 100644 --- a/Source/extension.ts +++ b/Source/extension.ts @@ -46,24 +46,18 @@ export function activate(context: ExtensionContext) { languages.registerCompletionItemProvider( "azcli", new AzCompletionItemProvider(azService), - " ", - ), + " " + ) ); context.subscriptions.push( - languages.registerHoverProvider( - "azcli", - new AzHoverProvider(azService), - ), + languages.registerHoverProvider("azcli", new AzHoverProvider(azService)) ); const status = new StatusBarInfo(azService); context.subscriptions.push(status); context.subscriptions.push(new RunLineInTerminal()); context.subscriptions.push(new RunLineInEditor(status)); context.subscriptions.push( - commands.registerCommand( - "ms-azurecli.installAzureCLI", - installAzureCLI, - ), + commands.registerCommand("ms-azurecli.installAzureCLI", installAzureCLI) ); } @@ -81,7 +75,7 @@ class AzCompletionItemProvider implements CompletionItemProvider { provideCompletionItems( document: TextDocument, position: Position, - token: CancellationToken, + token: CancellationToken ): ProviderResult { const line = document.lineAt(position).text; const parsed = parse(line); @@ -116,9 +110,9 @@ class AzCompletionItemProvider implements CompletionItemProvider { subcommand: subcommand.slice(1).join(" "), argument, arguments: args, - } + } : {}, - token.onCancellationRequested, + token.onCancellationRequested ) .then((completions) => completions.map( @@ -132,7 +126,7 @@ class AzCompletionItemProvider implements CompletionItemProvider { }) => { const item = new CompletionItem( name, - completionKinds[kind], + completionKinds[kind] ); if (snippet) { item.insertText = new SnippetString(snippet); @@ -149,8 +143,8 @@ class AzCompletionItemProvider implements CompletionItemProvider { item.sortText = sortText; } return item; - }, - ), + } + ) ); } @@ -160,7 +154,7 @@ class AzCompletionItemProvider implements CompletionItemProvider { for (const match of allMatches( /-[^\s"']*|"[^"]*"|'[^']*'|[^\s"']+/g, line, - 0, + 0 )) { if (match.startsWith("-")) { name = match as string; @@ -184,7 +178,7 @@ class AzHoverProvider implements HoverProvider { provideHover( document: TextDocument, position: Position, - token: CancellationToken, + token: CancellationToken ): ProviderResult { const line = document.lineAt(position.line).text; const command = parse(line); @@ -202,7 +196,7 @@ class AzHoverProvider implements HoverProvider { return this.azService .getHover( { subcommand }, - token.onCancellationRequested, + token.onCancellationRequested ) .then( (text) => @@ -213,9 +207,9 @@ class AzHoverProvider implements HoverProvider { position.line, node.offset, position.line, - node.offset + node.length, - ), - ), + node.offset + node.length + ) + ) ); } } else if (node.kind === "argument_name") { @@ -226,7 +220,7 @@ class AzHoverProvider implements HoverProvider { return this.azService .getHover( { subcommand, argument: node.text }, - token.onCancellationRequested, + token.onCancellationRequested ) .then( (text) => @@ -237,9 +231,9 @@ class AzHoverProvider implements HoverProvider { position.line, node.offset, position.line, - node.offset + node.length, - ), - ), + node.offset + node.length + ) + ) ); } } @@ -254,14 +248,14 @@ class RunLineInTerminal { this.disposables.push( commands.registerTextEditorCommand( "ms-azurecli.runLineInTerminal", - (editor) => this.run(editor), - ), + (editor) => this.run(editor) + ) ); } private run(editor: TextEditor) { return commands.executeCommand( - "workbench.action.terminal.runSelectedText", + "workbench.action.terminal.runSelectedText" ); } @@ -289,26 +283,24 @@ class RunLineInEditor { this.disposables.push( commands.registerTextEditorCommand( "ms-azurecli.toggleLiveQuery", - (editor) => this.toggleQuery(editor), - ), + (editor) => this.toggleQuery(editor) + ) ); this.disposables.push( commands.registerTextEditorCommand( "ms-azurecli.runLineInEditor", - (editor) => this.run(editor), - ), + (editor) => this.run(editor) + ) ); this.disposables.push( - workspace.onDidCloseTextDocument((document) => - this.close(document), - ), + workspace.onDidCloseTextDocument((document) => this.close(document)) ); this.disposables.push( - workspace.onDidChangeTextDocument((event) => this.change(event)), + workspace.onDidChangeTextDocument((event) => this.change(event)) ); this.commandRunningStatusBarItem = window.createStatusBarItem( - StatusBarAlignment.Left, + StatusBarAlignment.Left ); this.disposables.push(this.commandRunningStatusBarItem); } @@ -322,7 +314,7 @@ class RunLineInEditor { const t0 = Date.now(); if (this.runningCommandCount === 1) { this.statusBarItemText = l10n.t( - "Azure CLI: Waiting for response", + "Azure CLI: Waiting for response" ); this.statusBarUpdateInterval = setInterval(() => { if (this.runningCommandCount === 1) { @@ -345,35 +337,31 @@ class RunLineInEditor { this.query = undefined; // TODO return this.findResultDocument() .then((document) => - window.showTextDocument(document, ViewColumn.Two, true), + window.showTextDocument(document, ViewColumn.Two, true) ) .then((target) => replaceContent( target, JSON.stringify({ [l10n.t("Running command")]: command, - }) + "\n", + }) + "\n" ) .then(() => exec(command)) .then( ({ stdout }) => stdout, ({ stdout, stderr }) => - JSON.stringify( - { stderr, stdout }, - null, - " ", - ), + JSON.stringify({ stderr, stdout }, null, " ") ) .then((content) => replaceContent(target, content) .then( () => (this.parsedResult = - JSON.parse(content)), + JSON.parse(content)) ) - .then(undefined, (err) => {}), + .then(undefined, (err) => {}) ) - .then(() => this.commandFinished(t0)), + .then(() => this.commandFinished(t0)) ) .then(undefined, console.error); } @@ -400,8 +388,8 @@ class RunLineInEditor { if (source.document.lineAt(lineNumber).text.length === 0) { window.showInformationMessage( l10n.t( - "Please put the cursor on a line that contains a command (or part of a command).", - ), + "Please put the cursor on a line that contains a command (or part of a command)." + ) ); return ""; } @@ -419,7 +407,7 @@ class RunLineInEditor { // this will be the first (maybe only) line of the command var command = this.stripComments( - source.document.lineAt(lineNumber).text, + source.document.lineAt(lineNumber).text ); while (command.trim().endsWith(this.continuationCharacter)) { @@ -438,15 +426,15 @@ class RunLineInEditor { // single line command return this.stripComments( source.document.getText( - new Range(selectionStart, selectionEnd), - ), + new Range(selectionStart, selectionEnd) + ) ); } else { // multiline command command = this.stripComments( source.document .lineAt(selectionStart.line) - .text.substring(selectionStart.character), + .text.substring(selectionStart.character) ); for ( let index = selectionStart.line + 1; @@ -458,12 +446,12 @@ class RunLineInEditor { } var line = this.stripComments( - source.document.lineAt(index).text, + source.document.lineAt(index).text ); if (line.trim().toLowerCase().startsWith(commandPrefix)) { window.showErrorMessage( - l10n.t("Multiple command selection not supported"), + l10n.t("Multiple command selection not supported") ); return ""; } @@ -522,7 +510,7 @@ class RunLineInEditor { this.runningCommandCount -= 1; this.statusBarItemText = l10n.t( "Azure CLI: Executed in {0} milliseconds", - Date.now() - startTime, + Date.now() - startTime ); this.commandRunningStatusBarItem.text = this.statusBarItemText; @@ -532,7 +520,7 @@ class RunLineInEditor { // hide status bar item after 10 seconds to keep status bar uncluttered this.hideStatusBarItemTimeout = setTimeout( () => this.commandRunningStatusBarItem.hide(), - 10000, + 10000 ); } } @@ -585,7 +573,7 @@ class RunLineInEditor { private updateResult() { if (this.resultDocument && this.parsedResult) { const resultEditor = window.visibleTextEditors.find( - (editor) => editor.document === this.resultDocument, + (editor) => editor.document === this.resultDocument ); if (resultEditor) { try { @@ -595,7 +583,7 @@ class RunLineInEditor { : this.parsedResult; replaceContent( resultEditor, - JSON.stringify(result, null, " "), + JSON.stringify(result, null, " ") ).then(undefined, console.error); } catch (err: any) { if (!(err && err.name === "ParserError")) { @@ -609,7 +597,7 @@ class RunLineInEditor { private getQueryArgument(line: string) { return ( (/\s--query\s+("([^"]*)"|'([^']*)'|([^\s"']+))/.exec( - line, + line ) as string[]) || [] ).filter((group) => !!group)[2]; } @@ -629,10 +617,10 @@ class StatusBarInfo { constructor(private azService: AzService) { this.disposables.push( - (this.info = window.createStatusBarItem(StatusBarAlignment.Left)), + (this.info = window.createStatusBarItem(StatusBarAlignment.Left)) ); this.disposables.push( - window.onDidChangeActiveTextEditor(() => this.update()), + window.onDidChangeActiveTextEditor(() => this.update()) ); this.disposables.push({ dispose: () => this.timer && clearTimeout(this.timer), @@ -686,7 +674,7 @@ function replaceContent(editor: TextEditor, content: string) { const document = editor.document; const all = new Range( new Position(0, 0), - document.lineAt(document.lineCount - 1).range.end, + document.lineAt(document.lineCount - 1).range.end ); const edit = new WorkspaceEdit(); edit.replace(document.uri, all, content); diff --git a/Source/parser.ts b/Source/parser.ts index cb7adcd..789ed8a 100644 --- a/Source/parser.ts +++ b/Source/parser.ts @@ -42,10 +42,10 @@ export function parse(line: string) { kind: subcommand ? "subcommand" : isArgument - ? "argument_name" - : isComment - ? "comment" - : "argument_value", + ? "argument_name" + : isComment + ? "comment" + : "argument_value", offset: regex.lastIndex - length, length, text, @@ -88,6 +88,6 @@ export function parse(line: string) { export function findNode(command: Command, offset: number) { return command.tokens.find( (token) => - token.offset <= offset && token.offset + token.length > offset, + token.offset <= offset && token.offset + token.length > offset ); } diff --git a/language-configuration.json b/language-configuration.json index 15a1b3f..77e0118 100644 --- a/language-configuration.json +++ b/language-configuration.json @@ -2,7 +2,11 @@ "comments": { "lineComment": "#" }, - "brackets": [["{", "}"], ["[", "]"], ["(", ")"]], + "brackets": [ + ["{", "}"], + ["[", "]"], + ["(", ")"] + ], "autoClosingPairs": [ ["{", "}"], ["[", "]"],