| /*--------------------------------------------------------- |
| * Copyright (C) Microsoft Corporation. All rights reserved. |
| * Licensed under the MIT License. See LICENSE in the project root for license information. |
| *--------------------------------------------------------*/ |
| |
| 'use strict'; |
| |
| import cp = require('child_process'); |
| import vscode = require('vscode'); |
| import { getGoConfig } from './config'; |
| import { toolExecutionEnvironment } from './goEnv'; |
| import { promptForMissingTool, promptForUpdatingTool } from './goInstallTools'; |
| import { byteOffsetAt, getBinPath, getFileArchive } from './util'; |
| |
| // Interface for the output from gomodifytags |
| interface GomodifytagsOutput { |
| start: number; |
| end: number; |
| lines: string[]; |
| } |
| |
| // Interface for settings configuration for adding and removing tags |
| interface GoTagsConfig { |
| [key: string]: any; |
| tags: string; |
| options: string; |
| promptForTags: boolean; |
| template: string; |
| } |
| |
| export function addTags(commandArgs: GoTagsConfig) { |
| const args = getCommonArgs(); |
| if (!args) { |
| return; |
| } |
| |
| getTagsAndOptions(<GoTagsConfig>getGoConfig()['addTags'], commandArgs).then(( |
| [tags, options, transformValue, template]) => { |
| if (!tags && !options) { |
| return; |
| } |
| if (tags) { |
| args.push('--add-tags'); |
| args.push(tags); |
| } |
| if (options) { |
| args.push('--add-options'); |
| args.push(options); |
| } |
| if (transformValue) { |
| args.push('--transform'); |
| args.push(transformValue); |
| } |
| if (template) { |
| args.push('--template'); |
| args.push(template); |
| } |
| runGomodifytags(args); |
| }); |
| } |
| |
| export function removeTags(commandArgs: GoTagsConfig) { |
| const args = getCommonArgs(); |
| if (!args) { |
| return; |
| } |
| |
| getTagsAndOptions(<GoTagsConfig>getGoConfig()['removeTags'], commandArgs).then(([tags, options]) => { |
| if (!tags && !options) { |
| args.push('--clear-tags'); |
| args.push('--clear-options'); |
| } |
| if (tags) { |
| args.push('--remove-tags'); |
| args.push(tags); |
| } |
| if (options) { |
| args.push('--remove-options'); |
| args.push(options); |
| } |
| runGomodifytags(args); |
| }); |
| } |
| |
| function getCommonArgs(): string[] { |
| const editor = vscode.window.activeTextEditor; |
| if (!editor) { |
| vscode.window.showInformationMessage('No editor is active.'); |
| return; |
| } |
| if (!editor.document.fileName.endsWith('.go')) { |
| vscode.window.showInformationMessage('Current file is not a Go file.'); |
| return; |
| } |
| const args = ['-modified', '-file', editor.document.fileName, '-format', 'json']; |
| if ( |
| editor.selection.start.line === editor.selection.end.line && |
| editor.selection.start.character === editor.selection.end.character |
| ) { |
| // Add tags to the whole struct |
| const offset = byteOffsetAt(editor.document, editor.selection.start); |
| args.push('-offset'); |
| args.push(offset.toString()); |
| } else if (editor.selection.start.line <= editor.selection.end.line) { |
| // Add tags to selected lines |
| args.push('-line'); |
| args.push(`${editor.selection.start.line + 1},${editor.selection.end.line + 1}`); |
| } |
| |
| return args; |
| } |
| |
| function getTagsAndOptions(config: GoTagsConfig, commandArgs: GoTagsConfig): Thenable<string[]> { |
| const tags = commandArgs && commandArgs.hasOwnProperty('tags') ? commandArgs['tags'] : config['tags']; |
| const options = commandArgs && commandArgs.hasOwnProperty('options') ? commandArgs['options'] : config['options']; |
| const promptForTags = |
| commandArgs && commandArgs.hasOwnProperty('promptForTags') |
| ? commandArgs['promptForTags'] |
| : config['promptForTags']; |
| const transformValue: string = |
| commandArgs && commandArgs.hasOwnProperty('transform') ? commandArgs['transform'] : config['transform']; |
| const format: string = |
| commandArgs && commandArgs.hasOwnProperty('template') ? commandArgs['template'] : config['template']; |
| |
| if (!promptForTags) { |
| return Promise.resolve([tags, options, transformValue, format]); |
| } |
| |
| return vscode.window |
| .showInputBox({ |
| value: tags, |
| prompt: 'Enter comma separated tag names' |
| }) |
| .then((inputTags) => { |
| return vscode.window |
| .showInputBox({ |
| value: options, |
| prompt: 'Enter comma separated options' |
| }) |
| .then((inputOptions) => { |
| return vscode.window |
| .showInputBox({ |
| value: transformValue, |
| prompt: 'Enter transform value' |
| }) |
| .then((transformOption) => { |
| return vscode.window |
| .showInputBox({ |
| value: format, |
| prompt: 'Enter template value' |
| }) |
| .then((template) => { |
| return [inputTags, inputOptions, transformOption, template]; |
| }); |
| }); |
| }); |
| }); |
| } |
| |
| function runGomodifytags(args: string[]) { |
| const gomodifytags = getBinPath('gomodifytags'); |
| const editor = vscode.window.activeTextEditor; |
| const input = getFileArchive(editor.document); |
| const p = cp.execFile(gomodifytags, args, { env: toolExecutionEnvironment() }, (err, stdout, stderr) => { |
| if (err && (<any>err).code === 'ENOENT') { |
| promptForMissingTool('gomodifytags'); |
| return; |
| } |
| if (err && (<any>err).code === 2 && args.indexOf('--template') > 0) { |
| vscode.window.showInformationMessage(`Cannot modify tags: you might be using a` + |
| `version that does not support --template`); |
| promptForUpdatingTool('gomodifytags'); |
| return; |
| } |
| if (err) { |
| vscode.window.showInformationMessage(`Cannot modify tags: ${stderr}`); |
| return; |
| } |
| const output = <GomodifytagsOutput>JSON.parse(stdout); |
| vscode.window.activeTextEditor.edit((editBuilder) => { |
| editBuilder.replace(new vscode.Range(output.start - 1, 0, output.end, 0), output.lines.join('\n') + '\n'); |
| }); |
| }); |
| if (p.pid) { |
| p.stdin.end(input); |
| } |
| } |