diff --git a/package.json b/package.json index 5e0efc2a..c9353276 100644 --- a/package.json +++ b/package.json @@ -169,6 +169,11 @@ "command": "go.browse.packages", "title": "Go: Browse Packages", "description": "Browse packages and Go files inside the packages." + }, + { + "command": "go.get.package", + "title": "Go: Get Package", + "description": "Run `go get -v` on the package on the current line." } ], "debuggers": [ diff --git a/src/goBrowsePackage.ts b/src/goBrowsePackage.ts index 820fd73e..380ad047 100644 --- a/src/goBrowsePackage.ts +++ b/src/goBrowsePackage.ts @@ -10,6 +10,7 @@ import cp = require('child_process'); import { getGoRuntimePath } from './goPath'; import path = require('path'); import { getAllPackages } from './goPackages'; +import { getImportPath } from './util'; export function browsePackages() { let selectedText = ''; @@ -23,7 +24,7 @@ export function browsePackages() { // if selection is empty, then get the whole line the cursor is currently on. selectedText = editor.document.lineAt(selection.active.line).text; } - selectedText = getImportPath(selectedText); + selectedText = getImportPath(selectedText) || selectedText.trim(); } showPackageFiles(selectedText, true); @@ -85,19 +86,3 @@ function showPackageList() { }); }); } - -function getImportPath(text: string): string { - // Catch cases like `import alias "importpath"` and `import "importpath"` - let singleLineImportMatches = text.match(/^\s*import\s+([a-z,A-Z,_,\.]\w*\s+)?\"([^\"]+)\"/); - if (singleLineImportMatches) { - return singleLineImportMatches[2]; - } - - // Catch cases like `alias "importpath"` and "importpath" - let groupImportMatches = text.match(/^\s*([a-z,A-Z,_,\.]\w*\s+)?\"([^\"]+)\"/); - if (groupImportMatches) { - return groupImportMatches[2]; - } - - return text.trim(); -} diff --git a/src/goGetPackage.ts b/src/goGetPackage.ts new file mode 100644 index 00000000..507752ec --- /dev/null +++ b/src/goGetPackage.ts @@ -0,0 +1,38 @@ +'use strict'; + +import vscode = require('vscode'); +import cp = require('child_process'); +import { getGoRuntimePath } from './goPath'; +import { getImportPath } from './util'; +import { outputChannel } from './goStatus'; + +export function goGetPackage() { + const editor = vscode.window.activeTextEditor; + const selection = editor.selection; + const selectedText = editor.document.lineAt(selection.active.line).text; + + const importPath = getImportPath(selectedText); + if (importPath === '') { + vscode.window.showErrorMessage('No import path to get'); + return; + } + + const goRuntimePath = getGoRuntimePath(); + if (!goRuntimePath) { + return vscode.window.showErrorMessage('Could not locate Go binaries. Make sure you have Go installed'); + } + + cp.execFile(goRuntimePath, ['get', '-v', importPath], (err, stdout, stderr) => { + // go get -v uses stderr to write output regardless of success or failure + if (stderr !== '') { + outputChannel.show(); + outputChannel.clear(); + outputChannel.appendLine(stderr); + + return; + } + + // go get -v doesn't write anything when the package already exists + vscode.window.showInformationMessage(`Package already exists: ${importPath}`); + }); +}; diff --git a/src/goMain.ts b/src/goMain.ts index 076d8d58..cd4db400 100644 --- a/src/goMain.ts +++ b/src/goMain.ts @@ -37,6 +37,7 @@ import { parseLiveFile } from './goLiveErrors'; import { GoReferencesCodeLensProvider } from './goReferencesCodelens'; import { implCursor } from './goImpl'; import { browsePackages } from './goBrowsePackage'; +import { goGetPackage } from './goGetPackage'; export let errorDiagnosticCollection: vscode.DiagnosticCollection; let warningDiagnosticCollection: vscode.DiagnosticCollection; @@ -283,6 +284,8 @@ export function activate(ctx: vscode.ExtensionContext): void { }); })); + ctx.subscriptions.push(vscode.commands.registerCommand('go.get.package', goGetPackage)); + vscode.languages.setLanguageConfiguration(GO_MODE.language, { indentationRules: { decreaseIndentPattern: /^\s*(\bcase\b.*:|\bdefault\b:|}[),]?|\)[,]?)$/, diff --git a/src/util.ts b/src/util.ts index 6454b473..65bd39c7 100644 --- a/src/util.ts +++ b/src/util.ts @@ -409,3 +409,22 @@ export function resolvePath(inputPath: string, workspaceRoot?: string): string { return resolveHomeDir(inputPath); } +/** + * Returns the import path in a passed in string. + * @param text The string to search for an import path + */ +export function getImportPath(text: string): string { + // Catch cases like `import alias "importpath"` and `import "importpath"` + let singleLineImportMatches = text.match(/^\s*import\s+([a-z,A-Z,_,\.]\w*\s+)?\"([^\"]+)\"/); + if (singleLineImportMatches) { + return singleLineImportMatches[2]; + } + + // Catch cases like `alias "importpath"` and "importpath" + let groupImportMatches = text.match(/^\s*([a-z,A-Z,_,\.]\w*\s+)?\"([^\"]+)\"/); + if (groupImportMatches) { + return groupImportMatches[2]; + } + + return ''; +} diff --git a/test/go.test.ts b/test/go.test.ts index c7f7a60f..d66236e2 100644 --- a/test/go.test.ts +++ b/test/go.test.ts @@ -22,6 +22,7 @@ import { documentSymbols } from '../src/goOutline'; import { listPackages } from '../src/goImport'; import { generateTestCurrentFile, generateTestCurrentPackage, generateTestCurrentFunction } from '../src/goGenerateTests'; import { getAllPackages } from '../src/goPackages'; +import { getImportPath } from '../src/util'; suite('Go Extension Tests', () => { let gopath = process.env['GOPATH']; @@ -738,4 +739,19 @@ It returns the number of bytes written and any write error encountered. assert.ok(false, `error in OpenTextDocument ${err}`); }).then(() => done(), done); }); + + test('getImportPath()', () => { + let testCases: [string, string][] = [ + ['import "github.com/sirupsen/logrus"', 'github.com/sirupsen/logrus'], + ['import "net/http"', 'net/http'], + ['"github.com/sirupsen/logrus"', 'github.com/sirupsen/logrus'], + ['', ''], + ['func foo(bar int) (int, error) {', ''], + ['// This is a comment, complete with punctuation.', ''] + ]; + + testCases.forEach(run => { + assert.equal(run[1], getImportPath(run[0])); + }); + }); });