Browse Source

Adds ref range support to terminal links

Adds git command support to terminal links
main
Eric Amodio 4 years ago
parent
commit
90880e4901
7 changed files with 80 additions and 20 deletions
  1. +2
    -2
      src/commands/git/cherry-pick.ts
  2. +2
    -2
      src/commands/git/log.ts
  3. +7
    -3
      src/commands/git/search.ts
  4. +7
    -3
      src/commands/git/switch.ts
  5. +4
    -4
      src/commands/gitCommands.ts
  6. +5
    -1
      src/commands/quickCommand.ts
  7. +53
    -5
      src/terminal/linkProvider.ts

+ 2
- 2
src/commands/git/cherry-pick.ts View File

@ -74,8 +74,8 @@ export class CherryPickGitCommand extends QuickCommand {
state.repo.cherryPick(...state.flags, ...state.references.map(c => c.ref).reverse());
}
isMatch(name: string) {
return super.isMatch(name) || name === 'cherry';
isFuzzyMatch(name: string) {
return super.isFuzzyMatch(name) || name === 'cherry';
}
protected async *steps(state: PartialStepState<State>): StepGenerator {

+ 2
- 2
src/commands/git/log.ts View File

@ -70,8 +70,8 @@ export class LogGitCommand extends QuickCommand {
return false;
}
isMatch(name: string) {
return super.isMatch(name) || name === 'history';
isFuzzyMatch(name: string) {
return super.isFuzzyMatch(name) || name === 'log';
}
protected async *steps(state: PartialStepState<State>): StepGenerator {

+ 7
- 3
src/commands/git/search.ts View File

@ -34,7 +34,7 @@ interface State extends Required {
}
export interface SearchGitCommandArgs {
readonly command: 'search';
readonly command: 'search' | 'grep';
prefillOnly?: boolean;
state?: Partial<State>;
}
@ -81,8 +81,12 @@ export class SearchGitCommand extends QuickCommand {
return false;
}
isMatch(name: string) {
return super.isMatch(name) || name === 'grep';
isMatch(key: string) {
return super.isMatch(key) || key === 'grep';
}
isFuzzyMatch(name: string) {
return super.isFuzzyMatch(name) || name === 'grep';
}
protected async *steps(state: PartialStepState<State>): StepGenerator {

+ 7
- 3
src/commands/git/switch.ts View File

@ -34,7 +34,7 @@ interface State {
type SwitchStepState<T extends State = State> = ExcludeSome<StepState<T>, 'repos', string | string[] | Repository>;
export interface SwitchGitCommandArgs {
readonly command: 'switch';
readonly command: 'switch' | 'checkout';
confirm?: boolean;
state?: Partial<State>;
}
@ -78,8 +78,12 @@ export class SwitchGitCommand extends QuickCommand {
));
}
isMatch(name: string) {
return super.isMatch(name) || name === 'checkout';
isMatch(key: string) {
return super.isMatch(key) || key === 'checkout';
}
isFuzzyMatch(name: string) {
return super.isFuzzyMatch(name) || name === 'checkout';
}
protected async *steps(state: PartialStepState<State>): StepGenerator {

+ 4
- 4
src/commands/gitCommands.ts View File

@ -715,11 +715,11 @@ class PickCommandStep implements QuickPickStep {
new RebaseGitCommand(args?.command === 'rebase' ? args : undefined),
new ResetGitCommand(args?.command === 'reset' ? args : undefined),
new RevertGitCommand(args?.command === 'revert' ? args : undefined),
new SearchGitCommand(args?.command === 'search' ? args : undefined),
new SearchGitCommand(args?.command === 'search' || args?.command === 'grep' ? args : undefined),
new ShowGitCommand(args?.command === 'show' ? args : undefined),
new StashGitCommand(args?.command === 'stash' ? args : undefined),
new StatusGitCommand(args?.command === 'status' ? args : undefined),
new SwitchGitCommand(args?.command === 'switch' ? args : undefined),
new SwitchGitCommand(args?.command === 'switch' || args?.command === 'checkout' ? args : undefined),
new TagGitCommand(args?.command === 'tag' ? args : undefined),
];
@ -734,10 +734,10 @@ class PickCommandStep implements QuickPickStep {
find(commandName: string, fuzzy: boolean = false) {
if (fuzzy) {
const cmd = commandName.toLowerCase();
return this.items.find(c => c.isMatch(cmd)) ?? this.hiddenItems.find(c => c.isMatch(cmd));
return this.items.find(c => c.isFuzzyMatch(cmd)) ?? this.hiddenItems.find(c => c.isFuzzyMatch(cmd));
}
return this.items.find(c => c.key === commandName) ?? this.hiddenItems.find(c => c.key === commandName);
return this.items.find(c => c.isMatch(commandName)) ?? this.hiddenItems.find(c => c.isMatch(commandName));
}
setCommand(command: QuickCommand | undefined, via: 'menu' | 'command'): void {

+ 5
- 1
src/commands/quickCommand.ts View File

@ -142,7 +142,11 @@ export abstract class QuickCommand implements QuickPickItem {
: !Container.config.gitCommands.skipConfirmations.includes(this.skipConfirmKey);
}
isMatch(name: string) {
isMatch(key: string) {
return this.key === key;
}
isFuzzyMatch(name: string) {
return this.label === name;
}

+ 53
- 5
src/terminal/linkProvider.ts View File

@ -1,10 +1,18 @@
'use strict';
import { commands, Disposable, TerminalLink, TerminalLinkContext, TerminalLinkProvider, window } from 'vscode';
import { Commands, ShowQuickBranchHistoryCommandArgs, ShowQuickCommitCommandArgs } from '../commands';
import {
Commands,
GitCommandsCommandArgs,
ShowQuickBranchHistoryCommandArgs,
ShowQuickCommitCommandArgs,
} from '../commands';
import { Container } from '../container';
import { GitReference } from '../git/git';
const commandsRegexShared = /\b(g(?:it)?\b\s*)\b(branch|checkout|cherry-pick|fetch|grep|log|merge|pull|push|rebase|reset|revert|show|stash|status|tag)\b/gi;
const refRegexShared = /\b((?!\/)(?!\S*\/\/)(?!\S*@\{)(?!@$)(?!\S*\\)[^\000-\037\177 ~^:?*[]+(?<!\.lock)(?<!\/)(?<!\.))\b/gi;
const rangeRegex = /^[0-9a-f]{7,40}\.\.\.?[0-9a-f]{7,40}$/;
const shaRegex = /^[0-9a-f]{7,40}$/;
const refRegex = /\b((?!\S*\/\.)(?!\S*\.\.)(?!\/)(?!\S*\/\/)(?!\S*@\{)(?!@$)(?!\S*\\)[^\000-\037\177 ~^:?*[]+(?<!\.lock)(?<!\/)(?<!\.))\b/gi;
interface GitTerminalLink<T = object> extends TerminalLink {
command: {
@ -35,11 +43,30 @@ export class GitTerminalLinkProvider implements Disposable, TerminalLinkProvider
const branchesAndTags = await Container.git.getBranchesAndOrTags(repoPath);
// Don't use the shared regex instance directly, because we can be called reentrantly (because of the awaits below)
const regex = new RegExp(refRegex, refRegex.flags);
const refRegex = new RegExp(refRegexShared, refRegexShared.flags);
const commandsRegex = new RegExp(commandsRegexShared, commandsRegexShared.flags);
let match;
do {
match = regex.exec(context.line);
match = commandsRegex.exec(context.line);
if (match != null) {
const [_, git, command] = match;
const link: GitTerminalLink<GitCommandsCommandArgs> = {
startIndex: match.index + git.length,
length: command.length,
tooltip: 'Open in Git Command Palette',
command: {
command: Commands.GitCommands,
args: {
command: command as GitCommandsCommandArgs['command'],
},
},
};
links.push(link);
}
match = refRegex.exec(context.line);
if (match == null) break;
const [_, ref] = match;
@ -82,7 +109,28 @@ export class GitTerminalLinkProvider implements Disposable, TerminalLinkProvider
continue;
}
if (!shaRegex.test(ref)) continue;
if (!shaRegex.test(ref)) {
if (rangeRegex.test(ref)) {
const link: GitTerminalLink<GitCommandsCommandArgs> = {
startIndex: match.index,
length: ref.length,
tooltip: 'Show Commits',
command: {
command: Commands.GitCommands,
args: {
command: 'log',
state: {
repo: repoPath,
reference: GitReference.create(ref, repoPath, { refType: 'revision' }),
},
},
},
};
links.push(link);
}
continue;
}
if (await Container.git.validateReference(repoPath, ref)) {
const link: GitTerminalLink<ShowQuickCommitCommandArgs> = {

Loading…
Cancel
Save