mirror of
https://github.com/ckaczor/vscode-gitlens.git
synced 2026-01-14 01:25:43 -05:00
Adds experimental commands for Open in GitHub
This commit is contained in:
20
package.json
20
package.json
@@ -354,7 +354,7 @@
|
||||
"gitlens.experimental.openInHostingProvider": {
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"description": "(experimental) Specifies whether or not to show Open X in Hosting Provider commands in quick picks"
|
||||
"description": "(experimental) Specifies whether or not to show Open X in Hosting Provider commands in relevant quick picks"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -477,6 +477,16 @@
|
||||
"command": "gitlens.openChangedFiles",
|
||||
"title": "Open Changed Files",
|
||||
"category": "GitLens"
|
||||
},
|
||||
{
|
||||
"command": "gitlens.openCommitInHostingProvider",
|
||||
"title": "Open Line Commit in Hosting Provider",
|
||||
"category": "GitLens"
|
||||
},
|
||||
{
|
||||
"command": "gitlens.openFileInHostingProvider",
|
||||
"title": "Open File in Hosting Provider",
|
||||
"category": "GitLens"
|
||||
}
|
||||
],
|
||||
"menus": {
|
||||
@@ -572,6 +582,14 @@
|
||||
{
|
||||
"command": "gitlens.openChangedFiles",
|
||||
"when": "gitlens:enabled"
|
||||
},
|
||||
{
|
||||
"command": "gitlens.openCommitInHostingProvider",
|
||||
"when": "editorTextFocus && gitlens:enabled && gitlens:isBlameable && config.gitlens.experimental.openInHostingProvider"
|
||||
},
|
||||
{
|
||||
"command": "gitlens.openFileInHostingProvider",
|
||||
"when": "editorTextFocus && gitlens:enabled && config.gitlens.experimental.openInHostingProvider"
|
||||
}
|
||||
],
|
||||
"explorer/context": [
|
||||
|
||||
@@ -16,6 +16,9 @@ export * from './commands/diffWithNext';
|
||||
export * from './commands/diffWithPrevious';
|
||||
export * from './commands/diffWithWorking';
|
||||
export * from './commands/openChangedFiles';
|
||||
export * from './commands/openCommitInHostingProvider';
|
||||
export * from './commands/openFileInHostingProvider';
|
||||
export * from './commands/openInHostingProvider';
|
||||
export * from './commands/showBlame';
|
||||
export * from './commands/showBlameHistory';
|
||||
export * from './commands/showFileHistory';
|
||||
|
||||
@@ -2,7 +2,15 @@
|
||||
import { commands, Disposable, TextEditor, TextEditorEdit, Uri, window, workspace } from 'vscode';
|
||||
import { BuiltInCommands } from '../constants';
|
||||
|
||||
export type Commands = 'gitlens.closeUnchangedFiles' | 'gitlens.copyMessageToClipboard' | 'gitlens.copyShaToClipboard' | 'gitlens.diffDirectory' | 'gitlens.diffWithBranch' | 'gitlens.diffWithNext' | 'gitlens.diffWithPrevious' | 'gitlens.diffLineWithPrevious' | 'gitlens.diffWithWorking' | 'gitlens.diffLineWithWorking' | 'gitlens.openChangedFiles' | 'gitlens.showBlame' | 'gitlens.showBlameHistory' | 'gitlens.showFileHistory' | 'gitlens.showLastQuickPick' | 'gitlens.showQuickBranchHistory' | 'gitlens.showQuickCommitDetails' | 'gitlens.showQuickCommitFileDetails' | 'gitlens.showQuickFileHistory' | 'gitlens.showQuickRepoHistory' | 'gitlens.showQuickRepoStatus' | 'gitlens.toggleBlame' | 'gitlens.toggleCodeLens';
|
||||
export type Commands = 'gitlens.closeUnchangedFiles' | 'gitlens.copyMessageToClipboard' | 'gitlens.copyShaToClipboard' |
|
||||
'gitlens.diffDirectory' | 'gitlens.diffWithBranch' | 'gitlens.diffWithNext' | 'gitlens.diffWithPrevious' | 'gitlens.diffLineWithPrevious' | 'gitlens.diffWithWorking' | 'gitlens.diffLineWithWorking' |
|
||||
'gitlens.openChangedFiles' | 'gitlens.openCommitInHostingProvider' | 'gitlens.openFileInHostingProvider' | 'gitlens.openInHostingProvider' |
|
||||
'gitlens.showBlame' | 'gitlens.showBlameHistory' | 'gitlens.showFileHistory' |
|
||||
'gitlens.showLastQuickPick' | 'gitlens.showQuickBranchHistory' |
|
||||
'gitlens.showQuickCommitDetails' | 'gitlens.showQuickCommitFileDetails' |
|
||||
'gitlens.showQuickFileHistory' | 'gitlens.showQuickRepoHistory' |
|
||||
'gitlens.showQuickRepoStatus' |
|
||||
'gitlens.toggleBlame' | 'gitlens.toggleCodeLens';
|
||||
export const Commands = {
|
||||
CloseUnchangedFiles: 'gitlens.closeUnchangedFiles' as Commands,
|
||||
CopyMessageToClipboard: 'gitlens.copyMessageToClipboard' as Commands,
|
||||
@@ -15,6 +23,9 @@ export const Commands = {
|
||||
DiffWithWorking: 'gitlens.diffWithWorking' as Commands,
|
||||
DiffLineWithWorking: 'gitlens.diffLineWithWorking' as Commands,
|
||||
OpenChangedFiles: 'gitlens.openChangedFiles' as Commands,
|
||||
OpenCommitInHostingProvider: 'gitlens.openCommitInHostingProvider' as Commands,
|
||||
OpenFileInHostingProvider: 'gitlens.openFileInHostingProvider' as Commands,
|
||||
OpenInHostingProvider: 'gitlens.openInHostingProvider' as Commands,
|
||||
ShowBlame: 'gitlens.showBlame' as Commands,
|
||||
ShowBlameHistory: 'gitlens.showBlameHistory' as Commands,
|
||||
ShowFileHistory: 'gitlens.showFileHistory' as Commands,
|
||||
|
||||
46
src/commands/openCommitInHostingProvider.ts
Normal file
46
src/commands/openCommitInHostingProvider.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
'use strict';
|
||||
import { Arrays } from '../system';
|
||||
import { commands, TextEditor, TextEditorEdit, Uri, window } from 'vscode';
|
||||
import { ActiveEditorCommand, Commands } from './commands';
|
||||
import { GitCommit, GitService, GitUri } from '../gitService';
|
||||
import { Logger } from '../logger';
|
||||
|
||||
export class OpenCommitInHostingProviderCommand extends ActiveEditorCommand {
|
||||
|
||||
constructor(private git: GitService, private repoPath: string) {
|
||||
super(Commands.OpenCommitInHostingProvider);
|
||||
}
|
||||
|
||||
async execute(editor: TextEditor, edit: TextEditorEdit, uri?: Uri) {
|
||||
if (!(uri instanceof Uri)) {
|
||||
if (!editor || !editor.document) return undefined;
|
||||
uri = editor.document.uri;
|
||||
}
|
||||
|
||||
if (editor && editor.document && editor.document.isDirty) return undefined;
|
||||
|
||||
const gitUri = await GitUri.fromUri(uri, this.git);
|
||||
const line = (editor && editor.selection.active.line) || gitUri.offset;
|
||||
|
||||
try {
|
||||
const blameline = line - gitUri.offset;
|
||||
if (blameline < 0) return undefined;
|
||||
|
||||
const blame = await this.git.getBlameForLine(gitUri, blameline);
|
||||
if (!blame) return window.showWarningMessage(`Unable to open commit in hosting provider. File is probably not under source control`);
|
||||
|
||||
let commit = blame.commit;
|
||||
// If the line is uncommitted, find the previous commit
|
||||
if (commit.isUncommitted) {
|
||||
commit = new GitCommit(commit.repoPath, commit.previousSha, commit.previousFileName, commit.author, commit.date, commit.message);
|
||||
}
|
||||
|
||||
const remotes = Arrays.uniqueBy(await this.git.getRemotes(this.repoPath), _ => _.url, _ => !!_.provider);
|
||||
return commands.executeCommand(Commands.OpenInHostingProvider, uri, remotes, 'commit', [commit.sha]);
|
||||
}
|
||||
catch (ex) {
|
||||
Logger.error('[GitLens.OpenCommitInHostingProviderCommand]', ex);
|
||||
return window.showErrorMessage(`Unable to open commit in hosting provider. See output channel for more details`);
|
||||
}
|
||||
}
|
||||
}
|
||||
31
src/commands/openFileInHostingProvider.ts
Normal file
31
src/commands/openFileInHostingProvider.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
'use strict';
|
||||
import { Arrays } from '../system';
|
||||
import { commands, TextEditor, TextEditorEdit, Uri, window } from 'vscode';
|
||||
import { ActiveEditorCommand, Commands } from './commands';
|
||||
import { GitService, GitUri } from '../gitService';
|
||||
import { Logger } from '../logger';
|
||||
|
||||
export class OpenFileInHostingProviderCommand extends ActiveEditorCommand {
|
||||
|
||||
constructor(private git: GitService, private repoPath: string) {
|
||||
super(Commands.OpenFileInHostingProvider);
|
||||
}
|
||||
|
||||
async execute(editor: TextEditor, edit: TextEditorEdit, uri?: Uri) {
|
||||
if (!(uri instanceof Uri)) {
|
||||
if (!editor || !editor.document) return undefined;
|
||||
uri = editor.document.uri;
|
||||
}
|
||||
|
||||
const gitUri = await GitUri.fromUri(uri, this.git);
|
||||
|
||||
try {
|
||||
const remotes = Arrays.uniqueBy(await this.git.getRemotes(this.repoPath), _ => _.url, _ => !!_.provider);
|
||||
return commands.executeCommand(Commands.OpenInHostingProvider, uri, remotes, 'file', [gitUri.getRelativePath(), gitUri.sha]);
|
||||
}
|
||||
catch (ex) {
|
||||
Logger.error('[GitLens.OpenFileInHostingProviderCommand]', ex);
|
||||
return window.showErrorMessage(`Unable to open file in hosting provider. See output channel for more details`);
|
||||
}
|
||||
}
|
||||
}
|
||||
53
src/commands/openInHostingProvider.ts
Normal file
53
src/commands/openInHostingProvider.ts
Normal file
@@ -0,0 +1,53 @@
|
||||
'use strict';
|
||||
import { TextEditor, Uri, window } from 'vscode';
|
||||
import { ActiveEditorCommand, Commands } from './commands';
|
||||
import { GitRemote, HostingProviderOpenType } from '../gitService';
|
||||
import { Logger } from '../logger';
|
||||
import { CommandQuickPickItem, OpenRemoteCommandQuickPickItem, RemotesQuickPick } from '../quickPicks';
|
||||
|
||||
export class OpenInHostingProviderCommand extends ActiveEditorCommand {
|
||||
|
||||
constructor() {
|
||||
super(Commands.OpenInHostingProvider);
|
||||
}
|
||||
|
||||
async execute(editor: TextEditor, uri?: Uri, remotes?: GitRemote[], type?: HostingProviderOpenType, args?: string[], name?: string, goBackCommand?: CommandQuickPickItem) {
|
||||
if (!(uri instanceof Uri)) {
|
||||
uri = editor && editor.document && editor.document.uri;
|
||||
}
|
||||
|
||||
try {
|
||||
if (!remotes) return undefined;
|
||||
|
||||
if (remotes.length === 1) {
|
||||
const command = new OpenRemoteCommandQuickPickItem(remotes[0], type, ...args, name);
|
||||
return command.execute();
|
||||
}
|
||||
|
||||
let placeHolder: string;
|
||||
switch (type) {
|
||||
case 'branch':
|
||||
placeHolder = `open ${args[0]} branch in\u2026`;
|
||||
break;
|
||||
case 'commit':
|
||||
const shortSha = args[0].substring(0, 8);
|
||||
placeHolder = `open commit ${shortSha} in\u2026`;
|
||||
break;
|
||||
case 'file':
|
||||
const shortFileSha = (args[1] && args[1].substring(0, 8)) || '';
|
||||
const shaSuffix = shortFileSha ? ` \u00a0\u2022\u00a0 ${shortFileSha}` : '';
|
||||
|
||||
placeHolder = `open ${args[0]}${shaSuffix} in\u2026`;
|
||||
break;
|
||||
}
|
||||
|
||||
const pick = await RemotesQuickPick.show(remotes, placeHolder, type, args, name, goBackCommand);
|
||||
return pick && pick.execute();
|
||||
|
||||
}
|
||||
catch (ex) {
|
||||
Logger.error('[GitLens.OpenInHostingProviderCommand]', ex);
|
||||
return window.showErrorMessage(`Unable to open in hosting provider. See output channel for more details`);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import { BlameAnnotationController } from './blameAnnotationController';
|
||||
import { configureCssCharacters } from './blameAnnotationFormatter';
|
||||
import { CommandContext, setCommandContext } from './commands';
|
||||
import { CloseUnchangedFilesCommand, OpenChangedFilesCommand } from './commands';
|
||||
import { OpenCommitInHostingProviderCommand, OpenFileInHostingProviderCommand, OpenInHostingProviderCommand } from './commands';
|
||||
import { CopyMessageToClipboardCommand, CopyShaToClipboardCommand } from './commands';
|
||||
import { DiffDirectoryCommand, DiffLineWithPreviousCommand, DiffLineWithWorkingCommand, DiffWithBranchCommand, DiffWithNextCommand, DiffWithPreviousCommand, DiffWithWorkingCommand} from './commands';
|
||||
import { ShowBlameCommand, ToggleBlameCommand } from './commands';
|
||||
@@ -101,6 +102,9 @@ export async function activate(context: ExtensionContext) {
|
||||
context.subscriptions.push(new DiffWithNextCommand(git));
|
||||
context.subscriptions.push(new DiffWithPreviousCommand(git));
|
||||
context.subscriptions.push(new DiffWithWorkingCommand(git));
|
||||
context.subscriptions.push(new OpenCommitInHostingProviderCommand(git, repoPath));
|
||||
context.subscriptions.push(new OpenFileInHostingProviderCommand(git, repoPath));
|
||||
context.subscriptions.push(new OpenInHostingProviderCommand());
|
||||
context.subscriptions.push(new ShowBlameCommand(annotationController));
|
||||
context.subscriptions.push(new ToggleBlameCommand(annotationController));
|
||||
context.subscriptions.push(new ShowBlameHistoryCommand(git));
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
'use strict';
|
||||
import { QuickPickOptions, window } from 'vscode';
|
||||
import { Commands } from '../commands';
|
||||
import { GitRemote, HostingProviderOpenType } from '../gitService';
|
||||
import { CommandQuickPickItem, getQuickPickIgnoreFocusOut } from './quickPicks';
|
||||
import * as path from 'path';
|
||||
@@ -32,12 +33,6 @@ export class OpenRemoteCommandQuickPickItem extends CommandQuickPickItem {
|
||||
|
||||
export class OpenRemotesCommandQuickPickItem extends CommandQuickPickItem {
|
||||
|
||||
private goBackCommand: CommandQuickPickItem;
|
||||
private name: string;
|
||||
private placeHolder: string;
|
||||
private remotes: GitRemote[];
|
||||
private type: HostingProviderOpenType;
|
||||
|
||||
constructor(remotes: GitRemote[], type: 'branch', branch: string, goBackCommand?: CommandQuickPickItem);
|
||||
constructor(remotes: GitRemote[], type: 'commit', sha: string, goBackCommand?: CommandQuickPickItem);
|
||||
constructor(remotes: GitRemote[], type: 'file', fileName: string, sha?: string, name?: string, goBackCommand?: CommandQuickPickItem);
|
||||
@@ -81,35 +76,19 @@ export class OpenRemotesCommandQuickPickItem extends CommandQuickPickItem {
|
||||
super({
|
||||
label: `$(link-external) Open ${name} in ${remote.provider.name}`,
|
||||
description: `\u00a0 \u2014 \u00a0\u00a0 $(repo) ${remote.provider.path} \u00a0\u2022\u00a0 ${description}`
|
||||
}, undefined, undefined);
|
||||
}
|
||||
else {
|
||||
const provider = remotes.every(_ => _.provider.name === remote.provider.name)
|
||||
? remote.provider.name
|
||||
: 'Hosting Provider';
|
||||
}, Commands.OpenInHostingProvider, [undefined, remotes, type, [branchOrShaOrFileName, fileSha], name, goBackCommand]);
|
||||
|
||||
super({
|
||||
label: `$(link-external) Open ${name} in ${provider}\u2026`,
|
||||
description: `\u00a0 \u2014 \u00a0\u00a0 ${description}`
|
||||
}, undefined, undefined);
|
||||
return;
|
||||
}
|
||||
|
||||
this.goBackCommand = goBackCommand;
|
||||
this.name = name;
|
||||
this.placeHolder = placeHolder;
|
||||
this.remotes = remotes;
|
||||
this.type = type;
|
||||
this.args = [branchOrShaOrFileName, fileSha];
|
||||
}
|
||||
const provider = remotes.every(_ => _.provider.name === remote.provider.name)
|
||||
? remote.provider.name
|
||||
: 'Hosting Provider';
|
||||
|
||||
async execute(): Promise<{}> {
|
||||
if (this.remotes.length === 1) {
|
||||
const command = new OpenRemoteCommandQuickPickItem(this.remotes[0], this.type, ...this.args);
|
||||
return command.execute();
|
||||
}
|
||||
|
||||
const pick = await RemotesQuickPick.show(this.remotes, this.placeHolder, this.type, this.args, this.name, this.goBackCommand);
|
||||
return pick && pick.execute();
|
||||
super({
|
||||
label: `$(link-external) Open ${name} in ${provider}\u2026`,
|
||||
description: `\u00a0 \u2014 \u00a0\u00a0 ${description}`
|
||||
}, Commands.OpenInHostingProvider, [undefined, remotes, type, [branchOrShaOrFileName, fileSha], name, goBackCommand]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user