From 1f6611026be85211a7bdedd31a7f4348921f4883 Mon Sep 17 00:00:00 2001 From: Christian Piccolo Date: Wed, 20 Oct 2021 16:53:05 -0400 Subject: [PATCH] feat: adding support for copy SourceGraph URL --- package.json | 12 ++++++++ src/extension.ts | 79 ++++++++++++++++++++++++++++++++---------------- src/git/index.ts | 2 +- 3 files changed, 66 insertions(+), 27 deletions(-) diff --git a/package.json b/package.json index f8100b67..5552a1e2 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ ], "activationEvents": [ "onCommand:extension.open", + "onCommand:extension.copyUrl", "onCommand:extension.search.selection", "onCommand:extension.search" ], @@ -28,6 +29,10 @@ "command": "extension.open", "title": "Sourcegraph: Open" }, + { + "command": "extension.copyUrl", + "title": "Sourcegraph: Copy Url" + }, { "command": "extension.search.selection", "title": "Sourcegraph: Search Selection" @@ -74,6 +79,13 @@ "default": {}, "description": "For each item in this object, replace key with value in the remote url." }, + "sourcegraph.remoteRegexUrlReplacements": { + "type": [ + "object" + ], + "default": {}, + "description": "For each item in this object, replace RegEx key with value in the remote url." + }, "sourcegraph.defaultBranch": { "type": [ "string" diff --git a/src/extension.ts b/src/extension.ts index 7d27cd35..3f42a5f8 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -1,7 +1,7 @@ import open from 'open' import * as vscode from 'vscode' import { getSourcegraphUrl } from './config' -import { repoInfo } from './git' +import { repoInfo, RepositoryInfo } from './git' // eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires const { version } = require('../package.json') @@ -23,6 +23,23 @@ const handleCommandErrors =

(command: (...args: P) => Pr } } +/** + * Returns the Sourcegraph URL for a cursor selection. + */ +const getSelectionSourcegraphUrl = (editor: vscode.TextEditor, repositoryInfo: RepositoryInfo): string => { + const { remoteURL, branch, fileRelative } = repositoryInfo + return `${getSourcegraphUrl()}/-/editor` + + `?remote_url=${encodeURIComponent(remoteURL)}` + + `&branch=${encodeURIComponent(branch)}` + + `&file=${encodeURIComponent(fileRelative)}` + + `&editor=${encodeURIComponent('VSCode')}` + + `&version=${encodeURIComponent(version)}` + + `&start_row=${encodeURIComponent(String(editor.selection.start.line))}` + + `&start_col=${encodeURIComponent(String(editor.selection.start.character))}` + + `&end_row=${encodeURIComponent(String(editor.selection.end.line))}` + + `&end_col=${encodeURIComponent(String(editor.selection.end.character))}` +} + /** * The command implementation for opening a cursor selection on Sourcegraph. */ @@ -35,21 +52,24 @@ async function openCommand(): Promise { if (!repositoryInfo) { return } - const { remoteURL, branch, fileRelative } = repositoryInfo - // Open in browser. - await open( - `${getSourcegraphUrl()}/-/editor` + - `?remote_url=${encodeURIComponent(remoteURL)}` + - `&branch=${encodeURIComponent(branch)}` + - `&file=${encodeURIComponent(fileRelative)}` + - `&editor=${encodeURIComponent('VSCode')}` + - `&version=${encodeURIComponent(version)}` + - `&start_row=${encodeURIComponent(String(editor.selection.start.line))}` + - `&start_col=${encodeURIComponent(String(editor.selection.start.character))}` + - `&end_row=${encodeURIComponent(String(editor.selection.end.line))}` + - `&end_col=${encodeURIComponent(String(editor.selection.end.character))}` - ) + await open(getSelectionSourcegraphUrl(editor, repositoryInfo)) +} + +/** + * The command implementation for copying the Sourcegraph URL of a cursor selection. + */ +async function copyUrlCommand(): Promise { + const editor = vscode.window.activeTextEditor + if (!editor) { + throw new Error('No active editor') + } + const repositoryInfo = await repoInfo(editor.document.uri.fsPath) + if (!repositoryInfo) { + return + } + // Copy to clipboard. + await vscode.env.clipboard.writeText(getSelectionSourcegraphUrl(editor, repositoryInfo)) } /** @@ -74,12 +94,12 @@ async function searchSelectionCommand(): Promise { // Search in browser. await open( `${getSourcegraphUrl()}/-/editor` + - `?remote_url=${encodeURIComponent(remoteURL)}` + - `&branch=${encodeURIComponent(branch)}` + - `&file=${encodeURIComponent(fileRelative)}` + - `&editor=${encodeURIComponent('VSCode')}` + - `&version=${encodeURIComponent(version)}` + - `&search=${encodeURIComponent(query)}` + `?remote_url=${encodeURIComponent(remoteURL)}` + + `&branch=${encodeURIComponent(branch)}` + + `&file=${encodeURIComponent(fileRelative)}` + + `&editor=${encodeURIComponent('VSCode')}` + + `&version=${encodeURIComponent(version)}` + + `&search=${encodeURIComponent(query)}` ) } @@ -101,11 +121,18 @@ async function searchCommand(): Promise { */ export function activate(context: vscode.ExtensionContext): void { // Register our extension commands (see package.json). - context.subscriptions.push(vscode.commands.registerCommand('extension.open', handleCommandErrors(openCommand))) - context.subscriptions.push( - vscode.commands.registerCommand('extension.search.selection', handleCommandErrors(searchSelectionCommand)) - ) - context.subscriptions.push(vscode.commands.registerCommand('extension.search', handleCommandErrors(searchCommand))) + context.subscriptions.push(vscode.commands.registerCommand( + 'extension.open', + handleCommandErrors(openCommand))) + context.subscriptions.push(vscode.commands.registerCommand( + 'extension.copyUrl', + handleCommandErrors(copyUrlCommand))) + context.subscriptions.push(vscode.commands.registerCommand( + 'extension.search.selection', + handleCommandErrors(searchSelectionCommand))) + context.subscriptions.push(vscode.commands.registerCommand( + 'extension.search', + handleCommandErrors(searchCommand))) } export function deactivate(): void { diff --git a/src/git/index.ts b/src/git/index.ts index 862518e4..b055995f 100644 --- a/src/git/index.ts +++ b/src/git/index.ts @@ -5,7 +5,7 @@ import { gitHelpers } from './helpers' import { Branch, gitRemoteNameAndBranch } from './remoteNameAndBranch' import { gitRemoteUrlWithReplacements } from './remoteUrl' -interface RepositoryInfo extends Branch { +export interface RepositoryInfo extends Branch { /** Git repository remote URL */ remoteURL: string