Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/extensions/git/src/gitEditor.ts
5239 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
import * as path from 'path';
6
import { CancellationToken, DocumentLink, DocumentLinkProvider, l10n, Range, TabInputText, TextDocument, Uri, window, workspace } from 'vscode';
7
import { IIPCHandler, IIPCServer } from './ipc/ipcServer';
8
import { ITerminalEnvironmentProvider } from './terminal';
9
import { EmptyDisposable, IDisposable } from './util';
10
import { Model } from './model';
11
import { Repository } from './repository';
12
13
interface GitEditorRequest {
14
commitMessagePath?: string;
15
}
16
17
export class GitEditor implements IIPCHandler, ITerminalEnvironmentProvider {
18
19
private env: { [key: string]: string };
20
private disposable: IDisposable = EmptyDisposable;
21
22
readonly featureDescription = 'git editor';
23
24
constructor(ipc?: IIPCServer) {
25
if (ipc) {
26
this.disposable = ipc.registerHandler('git-editor', this);
27
}
28
29
this.env = {
30
GIT_EDITOR: `"${path.join(__dirname, ipc ? 'git-editor.sh' : 'git-editor-empty.sh')}"`,
31
VSCODE_GIT_EDITOR_NODE: process.execPath,
32
VSCODE_GIT_EDITOR_EXTRA_ARGS: '',
33
VSCODE_GIT_EDITOR_MAIN: path.join(__dirname, 'git-editor-main.js')
34
};
35
}
36
37
async handle({ commitMessagePath }: GitEditorRequest): Promise<boolean> {
38
if (commitMessagePath) {
39
const uri = Uri.file(commitMessagePath);
40
const doc = await workspace.openTextDocument(uri);
41
await window.showTextDocument(doc, { preview: false });
42
43
return new Promise((c) => {
44
const onDidClose = window.tabGroups.onDidChangeTabs(async (tabs) => {
45
if (tabs.closed.some(t => t.input instanceof TabInputText && t.input.uri.toString() === uri.toString())) {
46
onDidClose.dispose();
47
return c(true);
48
}
49
});
50
});
51
}
52
53
return Promise.resolve(false);
54
}
55
56
getEnv(): { [key: string]: string } {
57
const config = workspace.getConfiguration('git');
58
return config.get<boolean>('useEditorAsCommitInput') ? this.env : {};
59
}
60
61
getTerminalEnv(): { [key: string]: string } {
62
const config = workspace.getConfiguration('git');
63
return config.get<boolean>('useEditorAsCommitInput') && config.get<boolean>('terminalGitEditor') ? this.env : {};
64
}
65
66
dispose(): void {
67
this.disposable.dispose();
68
}
69
}
70
71
export class GitEditorDocumentLinkProvider implements DocumentLinkProvider {
72
private readonly _regex = /^#\s+(modified|new file|deleted|renamed|copied|type change):\s+(?<file1>.*?)(?:\s+->\s+(?<file2>.*))*$/gm;
73
74
constructor(private readonly _model: Model) { }
75
76
provideDocumentLinks(document: TextDocument, token: CancellationToken): DocumentLink[] {
77
if (token.isCancellationRequested) {
78
return [];
79
}
80
81
const repository = this._model.getRepository(document.uri);
82
if (!repository) {
83
return [];
84
}
85
86
const links: DocumentLink[] = [];
87
for (const match of document.getText().matchAll(this._regex)) {
88
if (!match.groups) {
89
continue;
90
}
91
92
const { file1, file2 } = match.groups;
93
94
if (file1) {
95
links.push(this._createDocumentLink(repository, document, match, file1));
96
}
97
if (file2) {
98
links.push(this._createDocumentLink(repository, document, match, file2));
99
}
100
}
101
102
return links;
103
}
104
105
private _createDocumentLink(repository: Repository, document: TextDocument, match: RegExpExecArray, file: string): DocumentLink {
106
const startIndex = match[0].indexOf(file);
107
const startPosition = document.positionAt(match.index + startIndex);
108
const endPosition = document.positionAt(match.index + startIndex + file.length);
109
110
const documentLink = new DocumentLink(
111
new Range(startPosition, endPosition),
112
Uri.file(path.join(repository.root, file)));
113
documentLink.tooltip = l10n.t('Open File');
114
115
return documentLink;
116
}
117
}
118
119