vscode#Selection TypeScript Examples
The following examples show how to use
vscode#Selection.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: utils.spec.ts From memo with MIT License | 7 votes |
describe('getRefUriUnderCursor()', () => {
beforeEach(closeEditorsAndCleanWorkspace);
afterEach(closeEditorsAndCleanWorkspace);
it('should return reference uri under cursor', async () => {
const name0 = rndName();
const name1 = rndName();
await createFile(`${name0}.md`);
await createFile(`${name1}.md`, `[[${name0}]]`);
const doc = await openTextDocument(`${name1}.md`);
const editor = await window.showTextDocument(doc);
editor.selection = new Selection(0, 2, 0, 2);
expect(getRefUriUnderCursor()!.fsPath).toContain(`${name0}.md`);
});
it('should not return reference uri under cursor', async () => {
const name0 = rndName();
const name1 = rndName();
await createFile(`${name0}.md`);
await createFile(`${name1}.md`, ` [[${name0}]]`);
const doc = await openTextDocument(`${name1}.md`);
const editor = await window.showTextDocument(doc);
editor.selection = new Selection(0, 0, 0, 0);
expect(getRefUriUnderCursor()).toBeNull();
});
});
Example #2
Source File: WorkspaceWatcher.ts From dendron with GNU Affero General Public License v3.0 | 6 votes |
static moveCursorPastFrontmatter(editor: TextEditor) {
const ctx = "moveCursorPastFrontmatter";
const nodePosition = RemarkUtils.getNodePositionPastFrontmatter(
editor.document.getText()
);
const startFsPath = editor.document.uri.fsPath;
if (!_.isUndefined(nodePosition)) {
const position = VSCodeUtils.point2VSCodePosition(nodePosition.end, {
line: 1,
});
// If the user opened the document with something like the search window,
// then VSCode is supposed to move the cursor to where the match is.
// But if we move the cursor here, then it overwrites VSCode's move.
// Worse, when VSCode calls this function the cursor hasn't updated yet
// so the location will still be 0, so we have to delay a bit to let it update first.
Wrap.setTimeout(() => {
// Since we delayed, a new document could have opened. Make sure we're still in the document we expect
if (
VSCodeUtils.getActiveTextEditor()?.document.uri.fsPath === startFsPath
) {
const { line, character } = editor.selection.active;
// Move the cursor, but only if it hasn't already been moved by VSCode, another extension, or a very quick user
if (line === 0 && character === 0) {
editor.selection = new Selection(position, position);
} else {
Logger.debug({
ctx,
msg: "not moving cursor because the cursor was moved before we could get to it",
});
}
} else {
Logger.debug({
ctx,
msg: "not moving cursor because the document changed before we could move it",
});
}
}, MOVE_CURSOR_PAST_FRONTMATTER_DELAY);
}
}
Example #3
Source File: documentActions.ts From vscode-todo-md with MIT License | 6 votes |
/**
* Reveal the line/task in the file.
*
* Move cursor, reveal range, highlight the line for a moment
*/
export async function revealTask(lineNumber: number, document?: TextDocument) {
const documentToReveal = document ?? await getActiveOrDefaultDocument();
const editor = await window.showTextDocument(documentToReveal);
const range = new Range(lineNumber, 0, lineNumber, 0);
editor.selection = new Selection(range.start, range.end);
editor.revealRange(range, TextEditorRevealType.Default);
// Highlight for a short time revealed range
const lineHighlightDecorationType = window.createTextEditorDecorationType({
backgroundColor: '#ffa30468',
isWholeLine: true,
});
editor.setDecorations(lineHighlightDecorationType, [range]);
setTimeout(() => {
editor.setDecorations(lineHighlightDecorationType, []);
}, 700);
}
Example #4
Source File: goto-definition.ts From al-objid with MIT License | 6 votes |
async function goToManifest({ goto }: GoToDefinitionCommandContext<NinjaALRange>) {
const { uri } = goto.app.manifest;
const idRanges = await getIdRanges(uri);
if (!idRanges) {
return;
}
const editor = await window.showTextDocument(uri);
const from = `${goto.range?.from}`;
const to = `${goto.range?.to}`;
switch (goto.type) {
case GoToDefinitionType.IdRanges:
editor.selection = new Selection(idRanges!.range.start, idRanges!.range.end);
break;
case GoToDefinitionType.Range:
const range = idRanges.children.find(
c =>
c.children.find(c => c.name === "from" && c.detail === from) &&
c.children.find(c => c.name === "to" && c.detail === to)
);
if (range) {
editor.selection = new Selection(range.range.start, range.range.end);
}
break;
}
}
Example #5
Source File: codeActionProvider.ts From dendron with GNU Affero General Public License v3.0 | 6 votes |
doctorFrontmatterProvider: CodeActionProvider = {
provideCodeActions: sentryReportingCallback(
(
_document: TextDocument,
_range: Range | Selection,
context: CodeActionContext,
_token: CancellationToken
) => {
// No-op if we're not in a Dendron Workspace
if (!DendronExtension.isActive()) {
return;
}
// Only provide fix frontmatter action if the diagnostic is correct
const diagnostics = context.diagnostics.filter(
(item) => item.code === BAD_FRONTMATTER_CODE
);
if (diagnostics.length !== 0) {
const action: CodeAction = {
title: "Fix the frontmatter",
diagnostics,
isPreferred: true,
kind: CodeActionKind.QuickFix,
command: {
command: new DoctorCommand(ExtensionProvider.getExtension()).key,
title: "Fix the frontmatter",
arguments: [
{ scope: "file", action: DoctorActionsEnum.FIX_FRONTMATTER },
],
},
};
return [action];
}
return undefined;
}
),
}
Example #6
Source File: InsertNoteCommand.ts From dendron with GNU Affero General Public License v3.0 | 6 votes |
async execute(opts: CommandOpts) {
const ctx = "InsertNoteCommand";
opts = _.defaults(opts, { closeAndOpenFile: true });
Logger.info({ ctx, opts });
const templates = opts.picks.map((pick) => {
return pick.body;
});
const txt = templates.join("\n");
const snippet = new SnippetString(txt);
const editor = VSCodeUtils.getActiveTextEditor()!;
const pos = editor.selection.active;
const selection = new Selection(pos, pos);
await editor.insertSnippet(snippet, selection);
AnalyticsUtils.track(ExtensionEvents.DeprecationNoticeShow, {
source: DENDRON_COMMANDS.INSERT_NOTE.key,
});
window
.showWarningMessage(
"Heads up that InsertNote is being deprecated and will be replaced with the 'Apply Template' command",
"See whats changed"
)
.then((resp) => {
if (resp === "See whats changed") {
AnalyticsUtils.track(ExtensionEvents.DeprecationNoticeAccept, {
source: DENDRON_COMMANDS.INSERT_NOTE.key,
});
VSCodeUtils.openLink(
"https://wiki.dendron.so/notes/ftohqknticu6bw4cfmzskq6"
);
}
});
return txt;
}
Example #7
Source File: CopyNoteRef.ts From dendron with GNU Affero General Public License v3.0 | 6 votes |
hasNextHeader(opts: { selection: Selection }) {
const { selection } = opts;
const lineEndForSelection = selection.end.line;
const editor = VSCodeUtils.getActiveTextEditor() as TextEditor;
const lineEndForDoc = editor.document.lineCount;
const text = editor.document.getText(
new Range(
new Position(lineEndForSelection + 1, 0),
new Position(lineEndForDoc, 0)
)
);
return !_.isNull(text.match(/^#+\s/m));
}
Example #8
Source File: ConvertCandidateLink.ts From dendron with GNU Affero General Public License v3.0 | 6 votes |
async execute(_opts: CommandOpts) {
const { location, text } = _opts;
await commands.executeCommand("vscode.open", location.uri);
const editor = VSCodeUtils.getActiveTextEditor()!;
const selection = editor.document.getText(location.range);
const preConversionOffset = selection.indexOf(text);
const convertedSelection = selection.replace(text, `[[${text}]]`);
await editor.edit((editBuilder) => {
editBuilder.replace(location.range, convertedSelection);
});
const postConversionSelectionRange = new Selection(
new Position(
location.range.start.line,
location.range.start.character + preConversionOffset
),
new Position(
location.range.end.line,
location.range.start.character + preConversionOffset + text.length + 4
)
);
editor.selection = postConversionSelectionRange;
return;
}
Example #9
Source File: WSUtilsV2.ts From dendron with GNU Affero General Public License v3.0 | 6 votes |
async trySelectRevealNonNoteAnchor(
editor: TextEditor,
anchor: DNoteAnchorBasic
): Promise<void> {
let position: Position | undefined;
switch (anchor.type) {
case "line":
// Line anchors are direct line numbers from the start
position = new Position(anchor.line - 1 /* line 1 is index 0 */, 0);
break;
case "block":
// We don't parse non note files for anchors, so read the document and find where the anchor is
position = editor?.document.positionAt(
editor?.document.getText().indexOf(AnchorUtils.anchor2string(anchor))
);
break;
default:
// not supported for non-note files
position = undefined;
}
if (position) {
// if we did find the anchor, then select and scroll to it
editor.selection = new Selection(position, position);
editor.revealRange(editor.selection);
}
}
Example #10
Source File: editor-utils.ts From vscode-code-review with MIT License | 6 votes |
clearSelection = (editor: TextEditor): void => {
if (hasSelection(editor)) {
editor.selections = [new Selection(new Position(0, 0), new Position(0, 0))];
}
}
Example #11
Source File: new-trongate-module.command.ts From trongate-vscode with MIT License | 6 votes |
// Helper Function to open the controller file and place curosr at good position
function openEditorAndPutCursorAtGoodPosition(
targetDirectory,
moduleName,
isViewTemplate
) {
const validatedModuleName = validateModuleName(moduleName);
const upperModuleName = makeFirstLetterGoUpper(validatedModuleName);
const controllerLocation = `${targetDirectory}/${validatedModuleName}/controllers/${upperModuleName}.php`;
var setting: vscode.Uri = Uri.file(controllerLocation);
setting = setting.fsPath;
workspace.openTextDocument(setting).then((document) =>
window.showTextDocument(document).then((e) => {
e.selections =
isViewTemplate === "no"
? [new Selection(new Position(0, 5), new Position(0, 5))]
: [new Selection(new Position(0, 5), new Position(0, 5))];
})
);
}
Example #12
Source File: createSimilarTask.ts From vscode-todo-md with MIT License | 6 votes |
export async function createSimilarTask(editor: TextEditor) {
// Create a task with all the tags, projects and contexts of another task
const selection = editor.selection;
const task = getTaskAtLineExtension(selection.start.line);
if (!task) {
return;
}
const line = editor.document.lineAt(task.lineNumber);
const edit = new WorkspaceEdit();
const tagsAsString = task.tags.map(tag => ` #${tag}`).join('');
const projectsAsString = task.projects.map(project => `+${project}`).join(' ');
const contextsAsString = task.contexts.map(context => `@${context}`).join(' ');
let newTaskAsString = tagsAsString;
newTaskAsString += projectsAsString ? ` ${projectsAsString}` : '';
newTaskAsString += contextsAsString ? ` ${contextsAsString}` : '';
edit.insert(editor.document.uri, new Position(line.rangeIncludingLineBreak.end.line, line.rangeIncludingLineBreak.end.character), `${newTaskAsString}\n`);
await applyEdit(edit, editor.document);
editor.selection = new Selection(line.lineNumber + 1, 0, line.lineNumber + 1, 0);
}
Example #13
Source File: infoview.ts From vscode-lean4 with Apache License 2.0 | 6 votes |
private async revealEditorSelection(uri: Uri, selection?: Range) {
let editor: TextEditor | undefined;
for (const e of window.visibleTextEditors) {
if (e.document.uri.toString() === uri.toString()) {
editor = e;
break;
}
}
if (!editor) {
const c = window.activeTextEditor ? window.activeTextEditor.viewColumn : ViewColumn.One;
editor = await window.showTextDocument(uri, { viewColumn: c, preserveFocus: false });
}
if (selection !== undefined) {
editor.revealRange(selection, TextEditorRevealType.InCenterIfOutsideViewport);
editor.selection = new Selection(selection.start, selection.end);
// ensure the text document has the keyboard focus.
await window.showTextDocument(editor.document, { viewColumn: editor.viewColumn, preserveFocus: false });
}
}
Example #14
Source File: ALDocumentationQuickFix.ts From vscode-alxmldocumentation with MIT License | 5 votes |
public provideCodeActions(document: TextDocument, range: Range | Selection, context: CodeActionContext, token: CancellationToken): ProviderResult<(CodeAction | Command)[]> {
this.QuickFixActions = [];
return new Promise(resolve => {
resolve(this.ProvideCodeActionsAsync(document, range, context, token));
});
}
Example #15
Source File: md.ts From dendron with GNU Affero General Public License v3.0 | 5 votes |
getURLAt = (editor: vscode.TextEditor | undefined): string => {
if (editor) {
const docText = editor.document.getText();
const offsetStart = editor.document.offsetAt(editor.selection.start);
const offsetEnd = editor.document.offsetAt(editor.selection.end);
const selectedText = docText.substring(offsetStart, offsetEnd);
const selectUri = true;
const validUriChars = "A-Za-z0-9-._~:/?#@!$&'*+,;%=\\\\";
const invalidUriChars = ["[^", validUriChars, "]"].join("");
const regex = new RegExp(invalidUriChars);
if (selectedText !== "" && regex.test(selectedText)) {
return "";
}
const leftSplit = docText.substring(0, offsetStart).split(regex);
const leftText = leftSplit[leftSplit.length - 1];
const selectStart = offsetStart - leftText.length;
const rightSplit = docText.substring(offsetEnd, docText.length);
const rightText = rightSplit.substring(0, regex.exec(rightSplit)?.index);
const selectEnd = offsetEnd + rightText.length;
if (selectEnd && selectStart) {
if (
selectStart >= 0 &&
selectStart < selectEnd &&
selectEnd <= docText.length
) {
if (selectUri) {
editor.selection = new Selection(
editor.document.positionAt(selectStart),
editor.document.positionAt(selectEnd)
);
editor.revealRange(editor.selection);
}
return [leftText, selectedText, rightText].join("");
}
}
}
return "";
}
Example #16
Source File: editor.ts From dendron with GNU Affero General Public License v3.0 | 5 votes |
/**
* Utility method to check if the selected text is a broken wikilink
*/
export async function isBrokenWikilink({
editor,
selection,
note,
engine,
}: {
editor: TextEditor;
selection: vscode.Selection;
note: NoteProps;
engine: DEngineClient;
}): Promise<boolean> {
const line = editor.document.lineAt(selection.start.line).text;
const proc = MDUtilsV5.procRemarkParse(
{ mode: ProcMode.FULL },
{
dest: DendronASTDest.MD_DENDRON,
engine,
vault: note.vault,
fname: note.fname,
}
);
const parsedLine = proc.parse(line);
let link: WikiLinkNoteV4 | UserTag | HashTag | undefined;
let type: DECORATION_TYPES | undefined;
let fname: string;
await MdastUtils.visitAsync(
parsedLine,
[
DendronASTTypes.WIKI_LINK,
DendronASTTypes.USERTAG,
DendronASTTypes.HASHTAG,
],
async (linkvalue) => {
link = linkvalue as WikiLinkNoteV4 | UserTag | HashTag;
if (!link) return false;
fname = link.type === DendronASTTypes.WIKI_LINK ? link.value : link.fname;
type = (await linkedNoteType({ fname, engine })).type;
return false;
}
);
return type === DECORATION_TYPES.brokenWikilink;
}
Example #17
Source File: editor.ts From dendron with GNU Affero General Public License v3.0 | 5 votes |
export async function getSelectionAnchors(opts: {
editor: TextEditor;
selection?: Selection;
doStartAnchor?: boolean;
doEndAnchor?: boolean;
engine: DEngineClient;
}): Promise<{ startAnchor?: string; endAnchor?: string }> {
const { editor, selection, doStartAnchor, doEndAnchor, engine } = _.defaults(
opts,
{ doStartAnchor: true, doEndAnchor: true }
);
if (_.isUndefined(selection)) return {};
const { start, end } = selection;
// first check if there's an existing anchor
let startAnchor = doStartAnchor
? getAnchorAt({ editor, position: start, engine })
: undefined;
// does the user have only a single
const singleLine =
// single line selected
start.line === end.line ||
// the first line selected in full, nothing on second line (default behavior when double clicking on a line)
(start.line + 1 === end.line && end.character === 0);
// does the user have any amount of text selected?
const hasSelectedRegion =
start.line !== end.line || start.character !== end.character;
// first check if there's an existing anchor
let endAnchor: string | undefined;
if (!singleLine && doEndAnchor)
endAnchor = getAnchorAt({ editor, position: end, engine });
// if we found both anchors already, just return them.
if (!_.isUndefined(startAnchor) && !_.isUndefined(endAnchor))
return { startAnchor, endAnchor };
// otherwise, we'll need to edit the document to insert block anchors
await editor.edit((editBuilder) => {
if (_.isUndefined(startAnchor) && doStartAnchor && hasSelectedRegion)
startAnchor = addOrGetAnchorAt({
editBuilder,
editor,
position: start,
engine,
});
if (_.isUndefined(endAnchor) && doEndAnchor && !singleLine)
endAnchor = addOrGetAnchorAt({
editBuilder,
editor,
position: end,
engine,
});
});
return { startAnchor, endAnchor };
}
Example #18
Source File: infoview.ts From vscode-lean4 with Apache License 2.0 | 5 votes |
private async handleInsertText(text: string, kind: TextInsertKind, uri?: Uri, pos?: Position) {
let editor: TextEditor | undefined
if (uri) {
editor = window.visibleTextEditors.find(e => e.document.uri === uri);
} else {
editor = window.activeTextEditor;
if (!editor) { // sometimes activeTextEditor is null.
editor = window.visibleTextEditors.find(e => e.document.languageId === 'lean4');
}
}
if (!editor) {
// user must have switch away from any lean source file in which case we don't know
// what to do here. TODO: show a popup error? Or should we use the last uri used in
// sendPosition and automatically activate that editor?
return;
}
pos = pos ? pos : editor.selection.active;
if (kind === 'above') {
// in this case, assume that we actually want to insert at the same
// indentation level as the neighboring text
const current_line = editor.document.lineAt(pos.line);
const spaces = current_line.firstNonWhitespaceCharacterIndex;
const margin_str = [...Array(spaces).keys()].map(x => ' ').join('');
let new_command = text.replace(/\n/g, '\n' + margin_str);
new_command = `${margin_str}${new_command}\n`;
const insertPosition = current_line.range.start;
await editor.edit((builder) => {
builder.insert(insertPosition, new_command);
});
} else {
await editor.edit((builder) => {
if (pos) builder.insert(pos, text);
});
editor.selection = new Selection(pos, pos)
}
// ensure the text document has the keyboard focus.
await window.showTextDocument(editor.document, { viewColumn: editor.viewColumn, preserveFocus: false });
}
Example #19
Source File: openReferenceInDefaultApp.spec.ts From memo with MIT License | 5 votes |
describe('openReferenceInDefaultApp command', () => {
beforeEach(async () => {
await closeEditorsAndCleanWorkspace();
(open as unknown as jest.Mock).mockClear();
});
afterEach(async () => {
await closeEditorsAndCleanWorkspace();
(open as unknown as jest.Mock).mockClear();
});
it('should call open command-line tool when editor selection is within the reference', async () => {
const name0 = rndName();
const name1 = rndName();
await createFile(`${name0}.md`);
await createFile(`${name1}.md`, `[[${name0}]]`);
const doc = await openTextDocument(`${name1}.md`);
const editor = await window.showTextDocument(doc);
editor.selection = new Selection(0, 2, 0, 2);
await openReferenceInDefaultApp();
expect(open).toHaveBeenCalledWith(path.join(getWorkspaceFolder()!, `${name0}.md`));
});
it('should call open command-line tool when editor selection is outside of the reference', async () => {
const name0 = rndName();
const name1 = rndName();
await createFile(`${name0}.md`);
await createFile(`${name1}.md`, ` [[${name0}]]`);
const doc = await openTextDocument(`${name1}.md`);
const editor = await window.showTextDocument(doc);
editor.selection = new Selection(0, 0, 0, 0);
await openReferenceInDefaultApp();
expect(open).not.toBeCalled();
});
});
Example #20
Source File: testUtilsv2.ts From dendron with GNU Affero General Public License v3.0 | 5 votes |
static getPresetWikiLinkSelection = (opts?: {
line?: number;
char?: number;
}) =>
new Selection(
LocationTestUtils.getPresetWikiLinkPosition(opts),
LocationTestUtils.getPresetWikiLinkPosition(opts)
);
Example #21
Source File: PasteFile.ts From dendron with GNU Affero General Public License v3.0 | 5 votes |
async execute(opts: CommandOpts) {
const { filePath } = opts;
const editor = VSCodeUtils.getActiveTextEditor();
if (!editor) {
const error = DendronError.createFromStatus({
status: ERROR_STATUS.INVALID_STATE,
message: "no active editor",
});
Logger.error({ error });
return { error };
}
const uri = editor.document.uri;
const ext = ExtensionProvider.getExtension();
const { vaults, wsRoot } = ext.getDWorkspace();
if (
!WorkspaceUtils.isPathInWorkspace({ vaults, wsRoot, fpath: uri.fsPath })
) {
const error = DendronError.createFromStatus({
status: ERROR_STATUS.INVALID_STATE,
message: "not in a vault",
});
Logger.error({ error });
return { error };
}
const vault = VaultUtils.getVaultByFilePath({
vaults,
wsRoot,
fsPath: uri.fsPath,
});
const vpath = vault2Path({ vault, wsRoot });
const suffix = path.join("assets", cleanFname(path.basename(filePath)));
const dstPath = path.join(vpath, suffix);
if (!fs.existsSync(filePath)) {
const error = DendronError.createFromStatus({
status: ERROR_STATUS.INVALID_STATE,
message: `${filePath} does not exist`,
});
Logger.error({ error });
return { error };
}
if (fs.existsSync(dstPath)) {
const error = DendronError.createFromStatus({
status: ERROR_STATUS.INVALID_STATE,
message: `${dstPath} already exists`,
});
Logger.error({ error });
return { error };
}
fs.ensureDirSync(path.dirname(dstPath));
fs.copyFileSync(filePath, dstPath);
window.showInformationMessage(`${filePath} moved to ${dstPath}`);
const pos = editor.selection.active;
await editor.edit((builder) => {
const txt = `[${path.basename(dstPath)}](${suffix})`;
const selection = new Selection(pos, pos);
builder.replace(selection, txt);
});
return {
fpath: dstPath,
};
}
Example #22
Source File: VSCodeApi.ts From vscode-alxmldocumentation with MIT License | 5 votes |
public GetSelectionByPosition(anchor: Position, active: Position): Selection {
return new Selection(anchor, active);
}
Example #23
Source File: CopyNoteURL.ts From dendron with GNU Affero General Public License v3.0 | 5 votes |
isHeader(text: string, selection: Selection) {
return text.startsWith("#") && selection.start.line === selection.end.line;
}
Example #24
Source File: editor-utils.test.ts From vscode-code-review with MIT License | 5 votes |
suite('Editor Utils', () => {
let editorStub: TextEditor;
let lastSetDecorationConf: TextEditorDecorationType | undefined;
let lastSetDecorationSelection: Selection[] | undefined;
beforeEach(() => {
editorStub = ({
selections: [new Selection(new Position(0, 1), new Position(2, 6))],
setDecorations: (conf: TextEditorDecorationType, selection: Selection[]) => {
lastSetDecorationConf = conf;
lastSetDecorationSelection = selection;
},
} as unknown) as TextEditor;
});
afterEach(() => {
lastSetDecorationConf = undefined;
lastSetDecorationSelection = undefined;
});
suite('clearSelection', () => {
test('should mutate selection and reset everything to 0', () => {
clearSelection(editorStub);
assert.deepStrictEqual(editorStub.selections, [new Selection(new Position(0, 0), new Position(0, 0))]);
});
});
suite('hasSelection', () => {
test('should detect an active selection', () => {
const result = hasSelection(editorStub);
assert.ok(result);
});
test('should detect no active selection when no positions are set', () => {
editorStub.selections = [];
const result = hasSelection(editorStub);
assert.strictEqual(result, false);
});
test('should detect no active selection when selection positions (start, end) are equal', () => {
editorStub.selections = [new Selection(new Position(2, 5), new Position(2, 5))];
const result = hasSelection(editorStub);
assert.strictEqual(result, false);
});
});
suite('getSelectionStringDefinition', () => {
test('should return a string representing the current selection', () => {
assert.strictEqual(getSelectionStringDefinition(editorStub), '1:1-3:6');
});
test('should return an empty string representing when no selection is active', () => {
editorStub.selections = [];
assert.strictEqual(getSelectionStringDefinition(editorStub), '');
});
});
suite('getSelectionRanges', () => {
test('should return a range for the current selection', () => {
const ranges = getSelectionRanges(editorStub);
assert.strictEqual(ranges.length, 1);
assert.strictEqual(ranges[0].start.line, 0);
assert.strictEqual(ranges[0].start.character, 1);
assert.strictEqual(ranges[0].end.line, 2);
assert.strictEqual(ranges[0].end.character, 6);
});
});
suite('isValidColorDefinition', () => {
test('should determine if a color value is RGBA or HEX', () => {
// empty and invalid
assert.strictEqual(isValidColorDefinition(''), false);
assert.strictEqual(isValidColorDefinition('ffffff'), false);
assert.strictEqual(isValidColorDefinition('#11'), false);
assert.strictEqual(isValidColorDefinition('#22222'), false);
assert.strictEqual(isValidColorDefinition('#3333333'), false);
assert.strictEqual(isValidColorDefinition('some-other'), false);
assert.strictEqual(isValidColorDefinition('rgb(10,20,44)'), false);
assert.strictEqual(isValidColorDefinition('rgba(,20,44)'), false);
assert.strictEqual(isValidColorDefinition('rgba(23)'), false);
assert.strictEqual(isValidColorDefinition('rgba(23,34)'), false);
assert.strictEqual(isValidColorDefinition('rgba(23,34)'), false);
assert.strictEqual(isValidColorDefinition('rgba(10,20,44)'), false);
assert.strictEqual(isValidColorDefinition('rgba(100,200,300,1.1)'), false);
// hex
assert.strictEqual(isValidColorDefinition('#fff'), true);
assert.strictEqual(isValidColorDefinition('#FFF'), true);
assert.strictEqual(isValidColorDefinition('#dddd'), true);
assert.strictEqual(isValidColorDefinition('#DDDD'), true);
assert.strictEqual(isValidColorDefinition('#ababab'), true);
assert.strictEqual(isValidColorDefinition('#ABABAB'), true);
assert.strictEqual(isValidColorDefinition('#ababab33'), true);
assert.strictEqual(isValidColorDefinition('#ABABAB33'), true);
// rgba
assert.strictEqual(isValidColorDefinition('rgba(100,200,300,0.8)'), true);
});
});
suite('themeColorForPriority', () => {
test('should colorize the given selection with decoration', () => {
assert.deepStrictEqual(themeColorForPriority(3), new ThemeColor('codereview.priority.red'));
assert.deepStrictEqual(themeColorForPriority(2), new ThemeColor('codereview.priority.yellow'));
assert.deepStrictEqual(themeColorForPriority(1), new ThemeColor('codereview.priority.green'));
assert.strictEqual(themeColorForPriority(0), undefined);
});
});
suite('symbolForPriority', () => {
test('should colorize the given selection with decoration', () => {
assert.strictEqual(symbolForPriority(3), '⇡');
assert.strictEqual(symbolForPriority(2), '⇢');
assert.strictEqual(symbolForPriority(1), '⇣');
assert.strictEqual(symbolForPriority(0), undefined);
});
});
});
Example #25
Source File: decoration-utils.test.ts From vscode-code-review with MIT License | 5 votes |
suite('Decoration Utils', () => {
let editorStub: TextEditor;
let lastSetDecorationConf: TextEditorDecorationType | undefined;
let lastSetDecorationSelection!: Selection[] | DecorationOptions[] | undefined;
beforeEach(() => {
editorStub = ({
selections: [new Selection(new Position(0, 1), new Position(2, 6))],
setDecorations: (conf: TextEditorDecorationType, selection: Selection[]) => {
lastSetDecorationConf = conf;
lastSetDecorationSelection = selection;
},
} as unknown) as TextEditor;
});
afterEach(() => {
lastSetDecorationConf = undefined;
lastSetDecorationSelection = undefined;
});
suite('underlineDecoration', () => {
test('should underline comments', () => {
const contextStub = {
asAbsolutePath: (p) => p,
} as ExtensionContext;
const deco = new Decorations(contextStub);
const csvEntries = [{ lines: '1:0-3:4|9:0-11:3' } as CsvEntry, { lines: '17:3-19:2' } as CsvEntry];
const decoration = deco.underlineDecoration(csvEntries, editorStub);
const decorationOptions = lastSetDecorationSelection as DecorationOptions[];
assert.ok(deco);
assert.deepStrictEqual(lastSetDecorationConf, deco.decorationDeclarationType);
assert.strictEqual(decorationOptions[0].range.start.line, 0);
assert.strictEqual(decorationOptions[0].range.start.character, 0);
assert.strictEqual(decorationOptions[0].range.end.line, 2);
assert.strictEqual(decorationOptions[0].range.end.character, 4);
assert.strictEqual(decorationOptions[1].range.start.line, 8);
assert.strictEqual(decorationOptions[1].range.start.character, 0);
assert.strictEqual(decorationOptions[1].range.end.line, 10);
assert.strictEqual(decorationOptions[1].range.end.character, 3);
assert.strictEqual(decorationOptions[2].range.start.line, 16);
assert.strictEqual(decorationOptions[2].range.start.character, 3);
assert.strictEqual(decorationOptions[2].range.end.line, 18);
assert.strictEqual(decorationOptions[2].range.end.character, 2);
});
});
suite('commentIconDecoration', () => {
test('should underline comments', () => {
const contextStub = {
asAbsolutePath: (p) => p,
} as ExtensionContext;
const deco = new Decorations(contextStub);
const csvEntries = [{ lines: '1:0-3:4|9:0-11:3' } as CsvEntry, { lines: '17:3-19:2' } as CsvEntry];
const decoration = deco.commentIconDecoration(csvEntries, editorStub);
const decorationOptions = lastSetDecorationSelection as DecorationOptions[];
assert.ok(deco);
assert.deepStrictEqual(lastSetDecorationConf, deco.commentDecorationType);
assert.strictEqual(decorationOptions[0].range.start.line, 0);
assert.strictEqual(decorationOptions[0].range.start.character, 1024);
assert.strictEqual(decorationOptions[0].range.end.line, 0);
assert.strictEqual(decorationOptions[0].range.end.character, 1024);
assert.strictEqual(decorationOptions[1].range.start.line, 8);
assert.strictEqual(decorationOptions[1].range.start.character, 1024);
assert.strictEqual(decorationOptions[1].range.end.line, 8);
assert.strictEqual(decorationOptions[1].range.end.character, 1024);
assert.strictEqual(decorationOptions[2].range.start.line, 16);
assert.strictEqual(decorationOptions[2].range.start.character, 1024);
assert.strictEqual(decorationOptions[2].range.end.line, 16);
assert.strictEqual(decorationOptions[2].range.end.character, 1024);
});
});
suite('colorizedBackgroundDecoration', () => {
test('should colorize the given selection with decoration', () => {
const selections = [new Range(new Position(2, 5), new Position(2, 5))];
const decoration = colorizedBackgroundDecoration(selections, editorStub, '#fdfdfd');
assert.ok(decoration);
assert.deepStrictEqual(lastSetDecorationConf, decoration);
assert.deepStrictEqual(lastSetDecorationSelection, selections);
});
});
});
Example #26
Source File: formatting.ts From twee3-language-tools with MIT License | 5 votes |
/**
* Add or remove `startPattern`/`endPattern` according to the context
* @param editor
* @param options The undo/redo behavior
* @param cursor cursor position
* @param range range to be replaced
* @param isSelected is this range selected
* @param startPtn
* @param endPtn
*/
function wrapRange(editor: TextEditor, wsEdit: WorkspaceEdit, shifts: [Position, number][], newSelections: Selection[], i: number, shift: number, cursor: Position, range: Range, isSelected: boolean, startPtn: string, endPtn: string) {
let text = editor.document.getText(range);
const prevSelection = newSelections[i];
const ptnLength = (startPtn + endPtn).length;
let newCursorPos = cursor.with({ character: cursor.character + shift });
let newSelection: Selection;
if (isWrapped(text, startPtn, endPtn)) {
// remove start/end patterns from range
wsEdit.replace(editor.document.uri, range, text.substr(startPtn.length, text.length - ptnLength));
shifts.push([range.end, -ptnLength]);
// Fix cursor position
if (!isSelected) {
if (!range.isEmpty) { // means quick styling
if (cursor.character === range.end.character) {
newCursorPos = cursor.with({ character: cursor.character + shift - ptnLength });
} else {
newCursorPos = cursor.with({ character: cursor.character + shift - startPtn.length });
}
} else { // means `**|**` -> `|`
newCursorPos = cursor.with({ character: cursor.character + shift + startPtn.length });
}
newSelection = new Selection(newCursorPos, newCursorPos);
} else {
newSelection = new Selection(
prevSelection.start.with({ character: prevSelection.start.character + shift }),
prevSelection.end.with({ character: prevSelection.end.character + shift - ptnLength })
);
}
} else {
// add start/end patterns around range
wsEdit.replace(editor.document.uri, range, startPtn + text + endPtn);
shifts.push([range.end, ptnLength]);
// Fix cursor position
if (!isSelected) {
if (!range.isEmpty) { // means quick styling
if (cursor.character === range.end.character) {
newCursorPos = cursor.with({ character: cursor.character + shift + ptnLength });
} else {
newCursorPos = cursor.with({ character: cursor.character + shift + startPtn.length });
}
} else { // means `|` -> `**|**`
newCursorPos = cursor.with({ character: cursor.character + shift + startPtn.length });
}
newSelection = new Selection(newCursorPos, newCursorPos);
} else {
newSelection = new Selection(
prevSelection.start.with({ character: prevSelection.start.character + shift }),
prevSelection.end.with({ character: prevSelection.end.character + shift + ptnLength })
);
}
}
newSelections[i] = newSelection;
}
Example #27
Source File: formatting.ts From twee3-language-tools with MIT License | 5 votes |
export function styleByWrapping(editor: TextEditor, startPattern: string, endPattern = startPattern) {
let selections = editor.selections;
let batchEdit = new WorkspaceEdit();
let shifts: [Position, number][] = [];
let newSelections: Selection[] = selections.slice();
for (const [i, selection] of selections.entries()) {
let cursorPos = selection.active;
const shift = shifts.map(([pos, s]) => (selection.start.line === pos.line && selection.start.character >= pos.character) ? s : 0)
.reduce((a, b) => a + b, 0);
if (selection.isEmpty) {
const context = getContext(editor, cursorPos, startPattern, endPattern);
// Patterns are added for SugarCube
// No selected text
if (
startPattern === endPattern &&
["**", "*", "__", "_", "//", "''"].includes(startPattern) &&
context === `${startPattern}text|${endPattern}`
) {
// `**text|**` to `**text**|`
let newCursorPos = cursorPos.with({ character: cursorPos.character + shift + endPattern.length });
newSelections[i] = new Selection(newCursorPos, newCursorPos);
continue;
} else if (context === `${startPattern}|${endPattern}`) {
// `**|**` to `|`
let start = cursorPos.with({ character: cursorPos.character - startPattern.length });
let end = cursorPos.with({ character: cursorPos.character + endPattern.length });
wrapRange(editor, batchEdit, shifts, newSelections, i, shift, cursorPos, new Range(start, end), false, startPattern, endPattern);
} else {
// Select word under cursor
// The markdown extension uses a custom regex very similar to this one for their def
// of word. This removes the exclusion of certain characters since formats use them.
let wordRange = editor.document.getWordRangeAtPosition(cursorPos, /(-?\d*\.\d\w*)|([^\!\@\#\%\^\&\(\)\-\=\+\[\{\]\}\\\|\;\:\"\,\.\<\>\?\s\,\。\《\》\?\;\:\‘\“\’\”\(\)\【\】\、]+)/g);
if (wordRange == undefined) {
wordRange = selection;
}
// One special case: toggle strikethrough in task list
const currentTextLine = editor.document.lineAt(cursorPos.line);
if (startPattern === '~~' && /^\s*[\*\+\-] (\[[ x]\] )? */g.test(currentTextLine.text)) {
let match = currentTextLine.text.match(/^\s*[\*\+\-] (\[[ x]\] )? */g) as RegExpMatchArray;
wordRange = currentTextLine.range.with(new Position(cursorPos.line, match[0].length));
}
wrapRange(editor, batchEdit, shifts, newSelections, i, shift, cursorPos, wordRange, false, startPattern, endPattern);
}
} else {
// Text selected
wrapRange(editor, batchEdit, shifts, newSelections, i, shift, cursorPos, selection, true, startPattern, endPattern);
}
}
return workspace.applyEdit(batchEdit).then(() => {
editor.selections = newSelections;
});
}
Example #28
Source File: ALDocumentationQuickFix.ts From vscode-alxmldocumentation with MIT License | 5 votes |
private async ProvideCodeActionsAsync(document: TextDocument, range: Range | Selection, context: CodeActionContext, token: CancellationToken): Promise<(CodeAction | Command)[] | null | undefined> {
let alObject: ALObject | null = await ALSyntaxUtil.GetALObject(document);
if (alObject === null) {
return;
}
context.diagnostics.filter(diagnostics => diagnostics.source === ALXmlDocDiagnosticPrefix).forEach(diagnostic => {
if (diagnostic === undefined) {
return;
}
let diagCodes: Array<string> = [];
if (diagnostic.code!.toString().indexOf(',') !== -1) { // multiple diagnostic codes
diagnostic.code!.toString().split(', ').forEach(diagnosticCode => {
diagCodes.push(diagnosticCode);
});
} else { // just one diagnostic code
diagCodes.push(diagnostic.code!.toString());
}
diagCodes.forEach(diagnosticCode => {
let alProcedure: ALProcedure | undefined;
if ((diagnosticCode !== ALXmlDocDiagnosticCode.ObjectDocumentationMissing) && (diagnosticCode !== ALXmlDocDiagnosticCode.ParameterUnnecessary)) {
alProcedure = alObject?.Procedures?.find(alProcedure => (alProcedure.LineNo === range.start.line));
if (alProcedure === undefined) {
console.error(`[ProvideCodeActionsAsync] - Unable to locate ALProcedure object for diagnostics entry. Please report this error at https://github.com/365businessdev/vscode-alxmldocumentation/issues`);
return;
}
}
switch (diagnosticCode) {
case ALXmlDocDiagnosticCode.DocumentationMissing:
this.AddDocumentationMissingCodeAction(alProcedure, diagnostic);
break;
case ALXmlDocDiagnosticCode.SummaryMissing:
this.AddSummaryDocumentationMissingCodeAction(alProcedure, diagnostic);
break;
case ALXmlDocDiagnosticCode.ParameterMissing:
this.AddParameterDocumentationMissingCodeAction(alProcedure, diagnostic);
break;
case ALXmlDocDiagnosticCode.ReturnTypeMissing:
this.AddReturnDocumentationMissingCodeAction(alProcedure, diagnostic);
break;
case ALXmlDocDiagnosticCode.ParameterUnnecessary:
this.AddUnnecessaryParameterDocumentationMissingCodeAction(alProcedure, diagnostic);
break;
case ALXmlDocDiagnosticCode.ObjectDocumentationMissing:
this.AddObjectDocumentationMissingCodeAction(alObject, diagnostic);
break;
}
});
});
return this.QuickFixActions;
}
Example #29
Source File: goto-definition.ts From al-objid with MIT License | 4 votes |
async function goToConfiguration({ goto }: GoToDefinitionCommandContext<NinjaALRange>) {
const { uri } = goto.app.config;
const from = `${goto.range?.from}`;
const to = `${goto.range?.to}`;
let selection: Selection | undefined;
let selections: Selection[] = [];
let idRanges: DocumentSymbol | undefined;
let objectRanges: DocumentSymbol | undefined;
let objectTypeRanges: DocumentSymbol | undefined;
let logicalRanges: DocumentSymbol[] | undefined;
switch (goto.type) {
case GoToDefinitionType.IdRanges:
idRanges = await getIdRanges(uri);
selection = new Selection(idRanges!.range.start, idRanges!.range.end);
break;
case GoToDefinitionType.ObjectRanges:
objectRanges = await getObjectRanges(uri);
selection = new Selection(objectRanges!.range.start, objectRanges!.range.end);
break;
case GoToDefinitionType.LogicalName:
logicalRanges = await getNamedLogicalRanges(uri, goto.logicalName!);
if (!logicalRanges || logicalRanges.length === 0) {
return;
}
for (let range of logicalRanges!) {
selections.push(new Selection(range.range.start, range.range.end));
}
break;
case GoToDefinitionType.Range:
logicalRanges = await getNamedLogicalRanges(uri, goto.range!.description);
if (!logicalRanges || logicalRanges.length === 0) {
return;
}
const range = logicalRanges.find(
r =>
r.children.find(c => c.name === "from" && c.detail === from) &&
r.children.find(c => c.name === "to" && c.detail === to)
);
if (range) {
selection = new Selection(range.range.start, range.range.end);
}
break;
case GoToDefinitionType.ObjectType:
objectTypeRanges = await getObjectTypeRanges(uri, goto.objectType!);
if (objectTypeRanges) {
selection = new Selection(objectTypeRanges.range.start, objectTypeRanges.range.end);
}
break;
case GoToDefinitionType.ObjectTypeRanges:
objectTypeRanges = await getObjectTypeRanges(uri, goto.objectType!);
const logicalObjectTypeRanges = objectTypeRanges?.children.filter(c =>
c.children.find(c => c.name === "description" && c.detail === goto.logicalName!)
);
if (!logicalObjectTypeRanges) {
return;
}
for (let range of logicalObjectTypeRanges) {
selections.push(new Selection(range.range.start, range.range.end));
}
break;
case GoToDefinitionType.ObjectTypeRange:
objectTypeRanges = await getObjectTypeRanges(uri, goto.objectType!);
const logicalObjectTypeRange = objectTypeRanges?.children.find(
c =>
c.children.find(c => c.name === "description" && c.detail === goto.range!.description) &&
c.children.find(c => c.name === "from" && c.detail === from) &&
c.children.find(c => c.name === "to" && c.detail === to)
);
if (logicalObjectTypeRange) {
selection = new Selection(logicalObjectTypeRange.range.start, logicalObjectTypeRange.range.end);
}
}
if (!selection && selections.length === 0) {
return;
}
const editor = await window.showTextDocument(uri);
if (selection) {
editor.selection = selection;
editor.revealRange(new Range(selection.start, selection.end));
} else {
editor.selections = selections;
const firstSelection = selections.reduce(
(previous, current) => (current.start.line < previous.start.line ? current : previous),
selections[0]
);
const lastSelection = selections.reduce(
(previous, current) => (current.end.line > previous.end.line ? current : previous),
selections[0]
);
editor.revealRange(new Range(firstSelection.start, lastSelection.end));
}
}