Skip to content

Commit d04696a

Browse files
author
Eric Amodio
committed
Adds code actions to open diffs
Adds context menus for toggling blame Adds context menus for opening diffs More refactoring and many bug fixes
1 parent ebb1085 commit d04696a

File tree

8 files changed

+339
-153
lines changed

8 files changed

+339
-153
lines changed

package.json

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,47 @@
2323
"main": "./out/src/extension",
2424
"contributes": {
2525
"commands": [{
26-
"command": "git.action.showBlame",
27-
"title": "Show Git Blame",
28-
"category": "Git"
29-
}]
26+
"command": "gitlens.showBlame",
27+
"title": "GitLens: Show Git Blame",
28+
"category": "GitLens"
29+
},
30+
{
31+
"command": "gitlens.toggleBlame",
32+
"title": "GitLens: Toggle Git Blame",
33+
"category": "GitLens"
34+
},
35+
{
36+
"command": "gitlens.diffWithPrevious",
37+
"title": "GitLens: Diff Commit with Previous",
38+
"category": "GitLens"
39+
},
40+
{
41+
"command": "gitlens.diffWithWorking",
42+
"title": "GitLens: Diff Commit with Working Tree",
43+
"category": "GitLens"
44+
}],
45+
"menus": {
46+
"editor/title": [{
47+
"when": "editorTextFocus",
48+
"command": "gitlens.toggleBlame",
49+
"group": "gitlens"
50+
}],
51+
"editor/context": [{
52+
"when": "editorTextFocus",
53+
"command": "gitlens.toggleBlame",
54+
"group": "[email protected]"
55+
},
56+
{
57+
"when": "editorTextFocus && editorHasCodeActionsProvider",
58+
"command": "gitlens.diffWithWorking",
59+
"group": "[email protected]"
60+
},
61+
{
62+
"when": "editorTextFocus && editorHasCodeActionsProvider",
63+
"command": "gitlens.diffWithPrevious",
64+
"group": "[email protected]"
65+
}]
66+
}
3067
},
3168
"activationEvents": [
3269
"*"

src/commands.ts

Lines changed: 58 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
'use strict'
2-
import {commands, DecorationOptions, Disposable, OverviewRulerLane, Position, Range, TextEditorDecorationType, Uri, window} from 'vscode';
2+
import {commands, DecorationOptions, Disposable, OverviewRulerLane, Position, Range, TextEditor, TextEditorEdit, TextEditorDecorationType, Uri, window} from 'vscode';
33
import {Commands, VsCodeCommands} from './constants';
44
import GitProvider from './gitProvider';
55
import GitBlameController from './gitBlameController';
@@ -11,7 +11,7 @@ abstract class Command extends Disposable {
1111

1212
constructor(command: Commands) {
1313
super(() => this.dispose());
14-
this._subscriptions = commands.registerCommand(command, this.execute.bind(this));
14+
this._subscriptions = commands.registerCommand(command, this.execute, this);
1515
}
1616

1717
dispose() {
@@ -21,19 +21,43 @@ abstract class Command extends Disposable {
2121
abstract execute(...args): any;
2222
}
2323

24-
export class BlameCommand extends Command {
24+
abstract class EditorCommand extends Disposable {
25+
private _subscriptions: Disposable;
26+
27+
constructor(command: Commands) {
28+
super(() => this.dispose());
29+
this._subscriptions = commands.registerTextEditorCommand(command, this.execute, this);
30+
}
31+
32+
dispose() {
33+
this._subscriptions && this._subscriptions.dispose();
34+
}
35+
36+
abstract execute(editor: TextEditor, edit: TextEditorEdit, ...args): any;
37+
}
38+
39+
export class ShowBlameCommand extends EditorCommand {
2540
constructor(private git: GitProvider, private blameController: GitBlameController) {
2641
super(Commands.ShowBlame);
2742
}
2843

29-
execute(uri?: Uri, range?: Range, sha?: string) {
30-
const editor = window.activeTextEditor;
31-
if (!editor) return;
32-
33-
if (!range) {
34-
range = editor.document.validateRange(new Range(0, 0, 1000000, 1000000));
44+
execute(editor: TextEditor, edit: TextEditorEdit, uri?: Uri, sha?: string) {
45+
if (sha) {
46+
return this.blameController.toggleBlame(editor, sha);
3547
}
3648

49+
const activeLine = editor.selection.active.line;
50+
return this.git.getBlameForLine(editor.document.fileName, activeLine)
51+
.then(blame => this.blameController.showBlame(editor, blame.commit.sha));
52+
}
53+
}
54+
55+
export class ToggleBlameCommand extends EditorCommand {
56+
constructor(private git: GitProvider, private blameController: GitBlameController) {
57+
super(Commands.ToggleBlame);
58+
}
59+
60+
execute(editor: TextEditor, edit: TextEditorEdit, uri?: Uri, sha?: string) {
3761
if (sha) {
3862
return this.blameController.toggleBlame(editor, sha);
3963
}
@@ -44,15 +68,15 @@ export class BlameCommand extends Command {
4468
}
4569
}
4670

47-
export class HistoryCommand extends Command {
71+
export class ShowHistoryCommand extends EditorCommand {
4872
constructor(private git: GitProvider) {
4973
super(Commands.ShowHistory);
5074
}
5175

52-
execute(uri?: Uri, range?: Range, position?: Position) {
76+
execute(editor: TextEditor, edit: TextEditorEdit, uri?: Uri, range?: Range, position?: Position) {
5377
// If the command is executed manually -- treat it as a click on the root lens (i.e. show blame for the whole file)
5478
if (!uri) {
55-
const doc = window.activeTextEditor && window.activeTextEditor.document;
79+
const doc = editor.document;
5680
if (doc) {
5781
uri = doc.uri;
5882
range = doc.validateRange(new Range(0, 0, 1000000, 1000000));
@@ -68,28 +92,41 @@ export class HistoryCommand extends Command {
6892
}
6993
}
7094

71-
export class DiffWithPreviousCommand extends Command {
95+
export class DiffWithPreviousCommand extends EditorCommand {
7296
constructor(private git: GitProvider) {
7397
super(Commands.DiffWithPrevious);
7498
}
7599

76-
execute(uri?: Uri, sha?: string, compareWithSha?: string) {
77-
// TODO: Execute these in parallel rather than series
78-
return this.git.getVersionedFile(uri.path, sha).then(source => {
79-
this.git.getVersionedFile(uri.path, compareWithSha).then(compare => {
100+
execute(editor: TextEditor, edit: TextEditorEdit, uri?: Uri, sha?: string, compareWithSha?: string) {
101+
if (!sha) {
102+
return this.git.getBlameForLine(uri.path, editor.selection.active.line)
103+
.then(blame => commands.executeCommand(Commands.DiffWithPrevious, uri, blame.commit.sha, blame.commit.previousSha));
104+
}
105+
106+
if (!compareWithSha) {
107+
return window.showInformationMessage(`Commit ${sha} has no previous commit`);
108+
}
109+
110+
return Promise.all([this.git.getVersionedFile(uri.path, sha), this.git.getVersionedFile(uri.path, compareWithSha)])
111+
.then(values => {
112+
const [source, compare] = values;
80113
const fileName = basename(uri.path);
81114
return commands.executeCommand(VsCodeCommands.Diff, Uri.file(compare), Uri.file(source), `${fileName} (${compareWithSha}) ↔ ${fileName} (${sha})`);
82-
})
83-
});
115+
});
84116
}
85117
}
86118

87-
export class DiffWithWorkingCommand extends Command {
119+
export class DiffWithWorkingCommand extends EditorCommand {
88120
constructor(private git: GitProvider) {
89121
super(Commands.DiffWithWorking);
90122
}
91123

92-
execute(uri?: Uri, sha?: string) {
124+
execute(editor: TextEditor, edit: TextEditorEdit, uri?: Uri, sha?: string) {
125+
if (!sha) {
126+
return this.git.getBlameForLine(uri.path, editor.selection.active.line)
127+
.then(blame => commands.executeCommand(Commands.DiffWithWorking, uri, blame.commit.sha));
128+
};
129+
93130
return this.git.getVersionedFile(uri.path, sha).then(compare => {
94131
const fileName = basename(uri.path);
95132
return commands.executeCommand(VsCodeCommands.Diff, Uri.file(compare), uri, `${fileName} (${sha}) ↔ ${fileName} (index)`);

src/constants.ts

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,16 @@
11
'use strict'
22

3-
export type WorkspaceState = 'hasGitHistoryExtension' | 'repoPath';
4-
export const WorkspaceState = {
5-
HasGitHistoryExtension: 'hasGitHistoryExtension' as WorkspaceState,
6-
RepoPath: 'repoPath' as WorkspaceState
7-
}
8-
9-
export const RepoPath: string = 'repoPath';
3+
export const DiagnosticCollectionName = 'gitlens';
4+
export const DiagnosticSource = 'GitLens';
5+
export const RepoPath = 'repoPath';
106

11-
export type Commands = 'git.action.diffWithPrevious' | 'git.action.diffWithWorking' | 'git.action.showBlame' | 'git.action.showHistory';
7+
export type Commands = 'gitlens.diffWithPrevious' | 'gitlens.diffWithWorking' | 'gitlens.showBlame' | 'gitlens.showHistory' | 'gitlens.toggleBlame';
128
export const Commands = {
13-
DiffWithPrevious: 'git.action.diffWithPrevious' as Commands,
14-
DiffWithWorking: 'git.action.diffWithWorking' as Commands,
15-
ShowBlame: 'git.action.showBlame' as Commands,
16-
ShowHistory: 'git.action.showHistory' as Commands,
9+
DiffWithPrevious: 'gitlens.diffWithPrevious' as Commands,
10+
DiffWithWorking: 'gitlens.diffWithWorking' as Commands,
11+
ShowBlame: 'gitlens.showBlame' as Commands,
12+
ShowHistory: 'gitlens.showHistory' as Commands,
13+
ToggleBlame: 'gitlens.toggleBlame' as Commands,
1714
}
1815

1916
export type DocumentSchemes = 'file' | 'git' | 'gitblame';
@@ -29,4 +26,10 @@ export const VsCodeCommands = {
2926
ExecuteDocumentSymbolProvider: 'vscode.executeDocumentSymbolProvider' as VsCodeCommands,
3027
ExecuteCodeLensProvider: 'vscode.executeCodeLensProvider' as VsCodeCommands,
3128
ShowReferences: 'editor.action.showReferences' as VsCodeCommands
29+
}
30+
31+
export type WorkspaceState = 'hasGitHistoryExtension' | 'repoPath';
32+
export const WorkspaceState = {
33+
HasGitHistoryExtension: 'hasGitHistoryExtension' as WorkspaceState,
34+
RepoPath: 'repoPath' as WorkspaceState
3235
}

src/extension.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
'use strict';
22
import {CodeLens, DocumentSelector, ExtensionContext, extensions, languages, OverviewRulerLane, window, workspace} from 'vscode';
3-
import GitCodeLensProvider from './gitCodeLensProvider';
43
import GitContentProvider from './gitContentProvider';
54
import GitBlameCodeLensProvider from './gitBlameCodeLensProvider';
65
import GitBlameContentProvider from './gitBlameContentProvider';
76
import GitBlameController from './gitBlameController';
87
import GitProvider from './gitProvider';
9-
import {BlameCommand, DiffWithPreviousCommand, DiffWithWorkingCommand, HistoryCommand} from './commands';
8+
import {DiffWithPreviousCommand, DiffWithWorkingCommand, ShowBlameCommand, ShowHistoryCommand, ToggleBlameCommand} from './commands';
109
import {WorkspaceState} from './constants';
1110

1211
// this method is called when your extension is activated
@@ -30,14 +29,14 @@ export function activate(context: ExtensionContext) {
3029
context.subscriptions.push(workspace.registerTextDocumentContentProvider(GitContentProvider.scheme, new GitContentProvider(context, git)));
3130
context.subscriptions.push(workspace.registerTextDocumentContentProvider(GitBlameContentProvider.scheme, new GitBlameContentProvider(context, git)));
3231

33-
context.subscriptions.push(languages.registerCodeLensProvider(GitCodeLensProvider.selector, new GitCodeLensProvider(context, git)));
3432
context.subscriptions.push(languages.registerCodeLensProvider(GitBlameCodeLensProvider.selector, new GitBlameCodeLensProvider(context, git)));
3533

3634
const blameController = new GitBlameController(context, git);
3735
context.subscriptions.push(blameController);
3836

39-
context.subscriptions.push(new BlameCommand(git, blameController));
40-
context.subscriptions.push(new HistoryCommand(git));
37+
context.subscriptions.push(new ShowBlameCommand(git, blameController));
38+
context.subscriptions.push(new ToggleBlameCommand(git, blameController));
39+
context.subscriptions.push(new ShowHistoryCommand(git));
4140
context.subscriptions.push(new DiffWithPreviousCommand(git));
4241
context.subscriptions.push(new DiffWithWorkingCommand(git));
4342
}).catch(reason => console.warn(reason));

0 commit comments

Comments
 (0)