Merge branch 'master' into master
This commit is contained in:
commit
1e0094545c
7 changed files with 69 additions and 227 deletions
|
@ -66,7 +66,7 @@ This project incorporates components from the projects listed below. The origina
|
|||
59. vscode-codicons version 0.0.1 (https://github.com/microsoft/vscode-codicons)
|
||||
60. vscode-logfile-highlighter version 2.8.0 (https://github.com/emilast/vscode-logfile-highlighter)
|
||||
61. vscode-swift version 0.0.1 (https://github.com/owensd/vscode-swift)
|
||||
62. Web Background Synchronization (https://github.com/WICG/BackgroundSync)
|
||||
62. Web Background Synchronization (https://github.com/WICG/background-sync)
|
||||
|
||||
|
||||
%% atom/language-clojure NOTICES AND INFORMATION BEGIN HERE
|
||||
|
|
|
@ -16,3 +16,8 @@ jobs:
|
|||
vmImage: macOS-latest
|
||||
steps:
|
||||
- template: build/azure-pipelines/darwin/continuous-build-darwin.yml
|
||||
|
||||
trigger:
|
||||
branches:
|
||||
exclude:
|
||||
- electron-11.x.y
|
||||
|
|
|
@ -1,12 +1,7 @@
|
|||
pool:
|
||||
vmImage: "Ubuntu-16.04"
|
||||
|
||||
trigger:
|
||||
branches:
|
||||
include: ["master"]
|
||||
pr:
|
||||
branches:
|
||||
include: ["master"]
|
||||
trigger: none
|
||||
|
||||
steps:
|
||||
- task: NodeTool@0
|
||||
|
|
|
@ -131,9 +131,17 @@ function createInlineRange(document: vscode.TextDocument, cursorPosition: vscode
|
|||
const lineText = document.lineAt(cursorPosition.line).text;
|
||||
const boldSelection = createBoldRange(lineText, cursorPosition.character, cursorPosition.line, parent);
|
||||
const italicSelection = createOtherInlineRange(lineText, cursorPosition.character, cursorPosition.line, true, parent);
|
||||
const linkSelection = createLinkRange(lineText, cursorPosition.character, cursorPosition.line, boldSelection ? boldSelection : italicSelection || parent);
|
||||
let comboSelection: vscode.SelectionRange | undefined;
|
||||
if (boldSelection && italicSelection && !boldSelection.range.isEqual(italicSelection.range)) {
|
||||
if (boldSelection.range.contains(italicSelection.range)) {
|
||||
comboSelection = createOtherInlineRange(lineText, cursorPosition.character, cursorPosition.line, true, boldSelection);
|
||||
} else if (italicSelection.range.contains(boldSelection.range)) {
|
||||
comboSelection = createBoldRange(lineText, cursorPosition.character, cursorPosition.line, italicSelection);
|
||||
}
|
||||
}
|
||||
const linkSelection = createLinkRange(lineText, cursorPosition.character, cursorPosition.line, comboSelection || boldSelection || italicSelection || parent);
|
||||
const inlineCodeBlockSelection = createOtherInlineRange(lineText, cursorPosition.character, cursorPosition.line, false, linkSelection || parent);
|
||||
return inlineCodeBlockSelection || linkSelection || boldSelection || italicSelection;
|
||||
return inlineCodeBlockSelection || linkSelection || comboSelection || boldSelection || italicSelection;
|
||||
}
|
||||
|
||||
function createFencedRange(token: Token, cursorLine: number, document: vscode.TextDocument, parent?: vscode.SelectionRange): vscode.SelectionRange {
|
||||
|
@ -154,61 +162,31 @@ function createFencedRange(token: Token, cursorLine: number, document: vscode.Te
|
|||
}
|
||||
|
||||
function createBoldRange(lineText: string, cursorChar: number, cursorLine: number, parent?: vscode.SelectionRange): vscode.SelectionRange | undefined {
|
||||
// find closest ** that occurs before cursor position
|
||||
let startBold = lineText.substring(0, cursorChar).lastIndexOf('**');
|
||||
|
||||
// find closest ** that occurs after the start **
|
||||
const endBoldIndex = lineText.substring(startBold + 2).indexOf('**');
|
||||
let endBold = startBold + 2 + lineText.substring(startBold + 2).indexOf('**');
|
||||
|
||||
if (startBold >= 0 && endBoldIndex >= 0 && startBold + 1 < endBold && startBold <= cursorChar && endBold >= cursorChar) {
|
||||
const range = new vscode.Range(cursorLine, startBold, cursorLine, endBold + 2);
|
||||
// **content cursor content** so select content then ** on both sides
|
||||
const contentRange = new vscode.Range(cursorLine, startBold + 2, cursorLine, endBold);
|
||||
return new vscode.SelectionRange(contentRange, new vscode.SelectionRange(range, parent));
|
||||
} else if (startBold >= 0) {
|
||||
// **content**cursor or **content*cursor*
|
||||
// find end ** from end of start ** to end of line (since the cursor is within the end stars)
|
||||
let adjustedEnd = startBold + 2 + lineText.substring(startBold + 2).indexOf('**');
|
||||
startBold = lineText.substring(0, adjustedEnd - 2).lastIndexOf('**');
|
||||
if (adjustedEnd >= 0 && cursorChar === adjustedEnd || cursorChar === adjustedEnd + 1) {
|
||||
if (lineText.charAt(adjustedEnd + 1) === '*') {
|
||||
// *cursor* so need to extend end to include the second *
|
||||
adjustedEnd += 1;
|
||||
}
|
||||
return new vscode.SelectionRange(new vscode.Range(cursorLine, startBold, cursorLine, adjustedEnd + 1), parent);
|
||||
}
|
||||
} else if (endBold > 0) {
|
||||
// cursor**content** or *cursor*content**
|
||||
// find start ** from start of string to cursor + 2 (since the cursor is within the start stars)
|
||||
const adjustedStart = lineText.substring(0, cursorChar + 2).lastIndexOf('**');
|
||||
endBold = adjustedStart + 2 + lineText.substring(adjustedStart + 2).indexOf('**');
|
||||
if (adjustedStart >= 0 && adjustedStart === cursorChar || adjustedStart === cursorChar - 1) {
|
||||
return new vscode.SelectionRange(new vscode.Range(cursorLine, adjustedStart, cursorLine, endBold + 2), parent);
|
||||
}
|
||||
const regex = /(?:^|(?<=\s))(?:\*\*\s*([^*]+)(?:\*\s*([^*]+)\s*?\*)*([^*]+)\s*?\*\*)/g;
|
||||
const matches = [...lineText.matchAll(regex)].filter(match => lineText.indexOf(match[0]) <= cursorChar && lineText.indexOf(match[0]) + match[0].length >= cursorChar);
|
||||
if (matches.length > 0) {
|
||||
// should only be one match, so select first and index 0 contains the entire match
|
||||
const bold = matches[0][0];
|
||||
const startIndex = lineText.indexOf(bold);
|
||||
const cursorOnStars = cursorChar === startIndex || cursorChar === startIndex + 1 || cursorChar === startIndex + bold.length || cursorChar === startIndex + bold.length - 1;
|
||||
const contentAndStars = new vscode.SelectionRange(new vscode.Range(cursorLine, startIndex, cursorLine, startIndex + bold.length), parent);
|
||||
const content = new vscode.SelectionRange(new vscode.Range(cursorLine, startIndex + 2, cursorLine, startIndex + bold.length - 2), contentAndStars);
|
||||
return cursorOnStars ? contentAndStars : content;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function createOtherInlineRange(lineText: string, cursorChar: number, cursorLine: number, isItalic: boolean, parent?: vscode.SelectionRange): vscode.SelectionRange | undefined {
|
||||
const type = isItalic ? '*' : '`';
|
||||
const start = lineText.substring(0, cursorChar + 1).lastIndexOf(type);
|
||||
let end = lineText.substring(cursorChar).indexOf(type);
|
||||
|
||||
if (start >= 0 && end >= 0) {
|
||||
end += cursorChar;
|
||||
// ensure there's no * or ` before end
|
||||
const intermediate = lineText.substring(start + 1, end - 1).indexOf(type);
|
||||
if (intermediate < 0) {
|
||||
const range = new vscode.Range(cursorLine, start, cursorLine, end + 1);
|
||||
if (cursorChar > start && cursorChar <= end) {
|
||||
// within the content so select content then include the stars or backticks
|
||||
const contentRange = new vscode.Range(cursorLine, start + 1, cursorLine, end);
|
||||
return new vscode.SelectionRange(contentRange, new vscode.SelectionRange(range, parent));
|
||||
} else if (cursorChar === start) {
|
||||
return new vscode.SelectionRange(range, parent);
|
||||
}
|
||||
}
|
||||
const regex = isItalic ? /(?:^|(?<=\s))(?:\*\s*([^*]+)(?:\*\*\s*([^*]+)\s*?\*\*)*([^*]+)\s*?\*)/g : /\`[^\`]*\`/g;
|
||||
const matches = [...lineText.matchAll(regex)].filter(match => lineText.indexOf(match[0]) <= cursorChar && lineText.indexOf(match[0]) + match[0].length >= cursorChar);
|
||||
if (matches.length > 0) {
|
||||
// should only be one match, so select first and index 0 contains the entire match
|
||||
const match = matches[0][0];
|
||||
const startIndex = lineText.indexOf(match);
|
||||
const cursorOnType = cursorChar === startIndex || cursorChar === startIndex + match.length;
|
||||
const contentAndType = new vscode.SelectionRange(new vscode.Range(cursorLine, startIndex, cursorLine, startIndex + match.length), parent);
|
||||
const content = new vscode.SelectionRange(new vscode.Range(cursorLine, startIndex + 1, cursorLine, startIndex + match.length - 1), contentAndType);
|
||||
return cursorOnType ? contentAndType : content;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
@ -228,11 +206,12 @@ function createLinkRange(lineText: string, cursorChar: number, cursorLine: numbe
|
|||
// determine if cursor is within [text] or (url) in order to know which should be selected
|
||||
const nearestType = cursorChar >= lineText.indexOf(linkText) && cursorChar < lineText.indexOf(linkText) + linkText.length ? linkText : url;
|
||||
|
||||
const indexOfType = lineText.indexOf(nearestType);
|
||||
// determine if cursor is on a bracket or paren and if so, return the [content] or (content), skipping over the content range
|
||||
const cursorOnType = cursorChar === lineText.indexOf(nearestType) || cursorChar === lineText.indexOf(nearestType) + nearestType.length;
|
||||
const cursorOnType = cursorChar === indexOfType || cursorChar === indexOfType + nearestType.length;
|
||||
|
||||
const contentAndNearestType = new vscode.SelectionRange(new vscode.Range(cursorLine, lineText.indexOf(nearestType), cursorLine, lineText.indexOf(nearestType) + nearestType.length), linkRange);
|
||||
const content = new vscode.SelectionRange(new vscode.Range(cursorLine, lineText.indexOf(nearestType) + 1, cursorLine, lineText.indexOf(nearestType) + nearestType.length - 1), contentAndNearestType);
|
||||
const contentAndNearestType = new vscode.SelectionRange(new vscode.Range(cursorLine, indexOfType, cursorLine, indexOfType + nearestType.length), linkRange);
|
||||
const content = new vscode.SelectionRange(new vscode.Range(cursorLine, indexOfType + 1, cursorLine, indexOfType + nearestType.length - 1), contentAndNearestType);
|
||||
return cursorOnType ? contentAndNearestType : content;
|
||||
}
|
||||
return undefined;
|
||||
|
|
|
@ -520,10 +520,10 @@ suite('markdown.SmartSelect', () => {
|
|||
`paragraph`,
|
||||
`## sub header`,
|
||||
`- list`,
|
||||
`- stuff here [text]**${CURSOR}items in here** and **here**`,
|
||||
`- stuff here [text] **${CURSOR}items in here** and **here**`,
|
||||
`- list`
|
||||
));
|
||||
assertNestedRangesEqual(ranges![0], [6, 21, 6, 44], [6, 19, 6, 46], [6, 0, 6, 59], [5, 0, 7, 6], [4, 0, 7, 6], [1, 0, 7, 6], [0, 0, 7, 6]);
|
||||
assertNestedRangesEqual(ranges![0], [6, 22, 6, 45], [6, 20, 6, 47], [6, 0, 6, 60], [5, 0, 7, 6], [4, 0, 7, 6], [1, 0, 7, 6], [0, 0, 7, 6]);
|
||||
});
|
||||
test('Smart select link in paragraph with multiple links', async () => {
|
||||
const ranges = await getSelectionRangesForDocument(
|
||||
|
@ -567,6 +567,27 @@ suite('markdown.SmartSelect', () => {
|
|||
));
|
||||
assertNestedRangesEqual(ranges![0], [0, 2, 0, 21], [0, 1, 0, 22], [0, 1, 0, 42], [0, 1, 0, 42], [0, 0, 0, 43], [0, 0, 0, 43]);
|
||||
});
|
||||
test('Smart select italic on end', async () => {
|
||||
const ranges = await getSelectionRangesForDocument(
|
||||
joinLines(
|
||||
`*word1 word2 word3${CURSOR}*`
|
||||
));
|
||||
assertNestedRangesEqual(ranges![0], [0, 1, 0, 28], [0, 0, 0, 29], [0, 0, 0, 29]);
|
||||
});
|
||||
test('Smart select italic then bold', async () => {
|
||||
const ranges = await getSelectionRangesForDocument(
|
||||
joinLines(
|
||||
`outer text **bold words *italic ${CURSOR} words* bold words** outer text`
|
||||
));
|
||||
assertNestedRangesEqual(ranges![0], [0, 25, 0, 48], [0, 24, 0, 49], [0, 13, 0, 60], [0, 11, 0, 62], [0, 0, 0, 73]);
|
||||
});
|
||||
test('Smart select bold then italic', async () => {
|
||||
const ranges = await getSelectionRangesForDocument(
|
||||
joinLines(
|
||||
`outer text *italic words **bold ${CURSOR} words** italic words* outer text`
|
||||
));
|
||||
assertNestedRangesEqual(ranges![0], [0, 27, 0, 48], [0, 25, 0, 50], [0, 12, 0, 63], [0, 11, 0, 64], [0, 0, 0, 75]);
|
||||
});
|
||||
});
|
||||
|
||||
function assertNestedLineNumbersEqual(range: vscode.SelectionRange, ...expectedRanges: [number, number][]) {
|
||||
|
|
|
@ -1,163 +0,0 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Disposable, DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { INotebookEditorContribution, INotebookEditor } from '../../notebookBrowser';
|
||||
import { registerNotebookContribution } from '../../notebookEditorExtensions';
|
||||
import { ISCMService } from 'vs/workbench/contrib/scm/common/scm';
|
||||
import { createProviderComparer } from 'vs/workbench/contrib/scm/browser/dirtydiffDecorator';
|
||||
import { first, ThrottledDelayer } from 'vs/base/common/async';
|
||||
import { INotebookService } from '../../../common/notebookService';
|
||||
import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel';
|
||||
import { FileService } from 'vs/platform/files/common/fileService';
|
||||
import { IFileService } from 'vs/platform/files/common/files';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
|
||||
export class SCMController extends Disposable implements INotebookEditorContribution {
|
||||
static id: string = 'workbench.notebook.findController';
|
||||
private _lastDecorationId: string[] = [];
|
||||
private _localDisposable = new DisposableStore();
|
||||
private _originalDocument: NotebookTextModel | undefined = undefined;
|
||||
private _originalResourceDisposableStore = new DisposableStore();
|
||||
private _diffDelayer = new ThrottledDelayer<void>(200);
|
||||
|
||||
private _lastVersion = -1;
|
||||
|
||||
|
||||
constructor(
|
||||
private readonly _notebookEditor: INotebookEditor,
|
||||
@IFileService private readonly _fileService: FileService,
|
||||
@ISCMService private readonly _scmService: ISCMService,
|
||||
@INotebookService private readonly _notebookService: INotebookService
|
||||
|
||||
) {
|
||||
super();
|
||||
|
||||
if (!this._notebookEditor.isEmbedded) {
|
||||
this._register(this._notebookEditor.onDidChangeModel(() => {
|
||||
this._localDisposable.clear();
|
||||
this._originalResourceDisposableStore.clear();
|
||||
this._diffDelayer.cancel();
|
||||
this.update();
|
||||
|
||||
if (this._notebookEditor.textModel) {
|
||||
this._localDisposable.add(this._notebookEditor.textModel.onDidChangeContent((e) => {
|
||||
this.update();
|
||||
}));
|
||||
}
|
||||
}));
|
||||
|
||||
this._register(this._notebookEditor.onWillDispose(() => {
|
||||
this._localDisposable.clear();
|
||||
this._originalResourceDisposableStore.clear();
|
||||
}));
|
||||
|
||||
this.update();
|
||||
}
|
||||
}
|
||||
|
||||
private async _resolveNotebookDocument(uri: URI, viewType: string) {
|
||||
const providers = this._scmService.repositories.map(r => r.provider);
|
||||
const rootedProviders = providers.filter(p => !!p.rootUri);
|
||||
|
||||
rootedProviders.sort(createProviderComparer(uri));
|
||||
|
||||
const result = await first(rootedProviders.map(p => () => p.getOriginalResource(uri)));
|
||||
|
||||
if (!result) {
|
||||
this._originalDocument = undefined;
|
||||
this._originalResourceDisposableStore.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
if (result.toString() === this._originalDocument?.uri.toString()) {
|
||||
// original document not changed
|
||||
return;
|
||||
}
|
||||
|
||||
this._originalResourceDisposableStore.add(this._fileService.watch(result));
|
||||
this._originalResourceDisposableStore.add(this._fileService.onDidFilesChange(e => {
|
||||
if (e.contains(result)) {
|
||||
this._originalDocument = undefined;
|
||||
this._originalResourceDisposableStore.clear();
|
||||
this.update();
|
||||
}
|
||||
}));
|
||||
|
||||
const originalDocument = await this._notebookService.resolveNotebook(viewType, result, false);
|
||||
this._originalResourceDisposableStore.add({
|
||||
dispose: () => {
|
||||
this._originalDocument?.dispose();
|
||||
this._originalDocument = undefined;
|
||||
}
|
||||
});
|
||||
|
||||
this._originalDocument = originalDocument;
|
||||
}
|
||||
|
||||
async update() {
|
||||
if (!this._diffDelayer) {
|
||||
return;
|
||||
}
|
||||
|
||||
await this._diffDelayer
|
||||
.trigger(async () => {
|
||||
const modifiedDocument = this._notebookEditor.textModel;
|
||||
if (!modifiedDocument) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._lastVersion >= modifiedDocument.versionId) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._lastVersion = modifiedDocument.versionId;
|
||||
await this._resolveNotebookDocument(modifiedDocument.uri, modifiedDocument.viewType);
|
||||
|
||||
if (!this._originalDocument) {
|
||||
this._clear();
|
||||
return;
|
||||
}
|
||||
|
||||
// const diff = new LcsDiff(new CellSequence(this._originalDocument), new CellSequence(modifiedDocument));
|
||||
// const diffResult = diff.ComputeDiff(false);
|
||||
|
||||
// const decorations: INotebookDeltaDecoration[] = [];
|
||||
// diffResult.changes.forEach(change => {
|
||||
// if (change.originalLength === 0) {
|
||||
// // doesn't exist in original
|
||||
// for (let i = 0; i < change.modifiedLength; i++) {
|
||||
// decorations.push({
|
||||
// handle: modifiedDocument.cells[change.modifiedStart + i].handle,
|
||||
// options: { gutterClassName: 'nb-gutter-cell-inserted' }
|
||||
// });
|
||||
// }
|
||||
// } else {
|
||||
// if (change.modifiedLength === 0) {
|
||||
// // diff.deleteCount
|
||||
// // removed from original
|
||||
// } else {
|
||||
// // modification
|
||||
// for (let i = 0; i < change.modifiedLength; i++) {
|
||||
// decorations.push({
|
||||
// handle: modifiedDocument.cells[change.modifiedStart + i].handle,
|
||||
// options: { gutterClassName: 'nb-gutter-cell-changed' }
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
|
||||
|
||||
// this._lastDecorationId = this._notebookEditor.deltaCellDecorations(this._lastDecorationId, decorations);
|
||||
});
|
||||
}
|
||||
|
||||
private _clear() {
|
||||
this._lastDecorationId = this._notebookEditor.deltaCellDecorations(this._lastDecorationId, []);
|
||||
}
|
||||
}
|
||||
|
||||
registerNotebookContribution(SCMController.id, SCMController);
|
|
@ -535,6 +535,11 @@
|
|||
cursor: grab;
|
||||
}
|
||||
|
||||
.monaco-workbench .notebookOverlay.notebook-editor-editable > .cell-list-container > .monaco-list > .monaco-scrollable-element > .scrollbar.visible {
|
||||
z-index: 50;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.monaco-workbench .notebookOverlay .monaco-list .monaco-list-row .cell-focus-indicator .codicon:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue