mirror of
https://github.com/cursorless-dev/cursorless.git
synced 2024-10-05 05:17:38 +03:00
Added selection type paragraph (#125)
* added selection type paragraph * include empty line for paragraph delimiter * Update src/processTargets.ts Co-authored-by: Pokey Rule <pokey.rule@gmail.com> * expand the limited range four paragraph Co-authored-by: Pokey Rule <pokey.rule@gmail.com>
This commit is contained in:
parent
f5775d29c5
commit
f102b62785
@ -99,7 +99,7 @@ export type SelectionType =
|
||||
| "character"
|
||||
| "token"
|
||||
| "line"
|
||||
| "block"
|
||||
| "paragraph"
|
||||
| "document";
|
||||
export type Position = "before" | "after" | "contents";
|
||||
export type InsideOutsideType = "inside" | "outside" | null;
|
||||
|
@ -441,7 +441,7 @@ export function inferRangeEndTarget(
|
||||
function getContentSelectionType(contents: string[]): SelectionType {
|
||||
if (contents.every((string) => string.endsWith("\n"))) {
|
||||
if (contents.every((string) => string.startsWith("\n"))) {
|
||||
return "block";
|
||||
return "paragraph";
|
||||
}
|
||||
return "line";
|
||||
}
|
||||
|
@ -10,23 +10,18 @@ export function performInsideOutsideAdjustment(
|
||||
selection.insideOutsideType ?? preferredInsideOutsideType;
|
||||
|
||||
if (insideOutsideType === "outside") {
|
||||
const delimiterRange =
|
||||
selection.selectionContext.trailingDelimiterRange ??
|
||||
selection.selectionContext.leadingDelimiterRange;
|
||||
|
||||
const usedSelection =
|
||||
selection.selectionContext.outerSelection ??
|
||||
selection.selection.selection;
|
||||
|
||||
if (delimiterRange == null) {
|
||||
return update(selection, {
|
||||
selection: {
|
||||
selection: () => usedSelection,
|
||||
},
|
||||
});
|
||||
}
|
||||
const delimiterRange =
|
||||
selection.selectionContext.trailingDelimiterRange ??
|
||||
selection.selectionContext.leadingDelimiterRange;
|
||||
|
||||
const range = usedSelection.union(delimiterRange);
|
||||
const range =
|
||||
delimiterRange != null
|
||||
? usedSelection.union(delimiterRange)
|
||||
: usedSelection;
|
||||
|
||||
return update(selection, {
|
||||
selection: {
|
||||
|
@ -2,7 +2,7 @@ import { concat, range, zip } from "lodash";
|
||||
import update from "immutability-helper";
|
||||
import { SyntaxNode } from "web-tree-sitter";
|
||||
import * as vscode from "vscode";
|
||||
import { Selection, Range } from "vscode";
|
||||
import { Selection, Range, Position } from "vscode";
|
||||
import { nodeMatchers } from "./languages";
|
||||
import {
|
||||
Mark,
|
||||
@ -253,57 +253,47 @@ function createTypedSelection(
|
||||
selection: SelectionWithEditor,
|
||||
selectionContext: SelectionContext
|
||||
): TypedSelection {
|
||||
const { selectionType, insideOutsideType } = target;
|
||||
let start: vscode.Position;
|
||||
let end: vscode.Position;
|
||||
const { selectionType, insideOutsideType, position } = target;
|
||||
const { document } = selection.editor;
|
||||
|
||||
switch (selectionType) {
|
||||
case "token":
|
||||
return {
|
||||
selection,
|
||||
selectionType,
|
||||
position,
|
||||
insideOutsideType,
|
||||
selectionContext: getTokenSelectionContext(selection, selectionContext),
|
||||
insideOutsideType: target.insideOutsideType ?? null,
|
||||
position: target.position,
|
||||
};
|
||||
|
||||
case "line":
|
||||
const originalSelectionStart = selection.selection.start;
|
||||
const originalSelectionEnd = selection.selection.end;
|
||||
|
||||
const startLine = selection.editor.document.lineAt(
|
||||
originalSelectionStart
|
||||
);
|
||||
const endLine = selection.editor.document.lineAt(originalSelectionEnd);
|
||||
start = new vscode.Position(
|
||||
originalSelectionStart.line,
|
||||
case "line": {
|
||||
const startLine = document.lineAt(selection.selection.start);
|
||||
const endLine = document.lineAt(selection.selection.end);
|
||||
const start = new Position(
|
||||
startLine.lineNumber,
|
||||
startLine.firstNonWhitespaceCharacterIndex
|
||||
);
|
||||
end = endLine.range.end;
|
||||
const end = endLine.range.end;
|
||||
|
||||
const isSelectionReversed = selection.selection.isReversed;
|
||||
const anchor = isSelectionReversed ? start : end;
|
||||
const active = isSelectionReversed ? end : start;
|
||||
const newSelection = new Selection(anchor, active);
|
||||
selection = {
|
||||
selection: newSelection,
|
||||
editor: selection.editor,
|
||||
};
|
||||
const newSelection = update(selection, {
|
||||
selection: (s) =>
|
||||
s.isReversed ? new Selection(end, start) : new Selection(start, end),
|
||||
});
|
||||
|
||||
return {
|
||||
selection,
|
||||
selection: newSelection,
|
||||
selectionType,
|
||||
selectionContext: getLineSelectionContext(selection, selectionContext),
|
||||
insideOutsideType: target.insideOutsideType ?? null,
|
||||
position: target.position,
|
||||
position,
|
||||
insideOutsideType,
|
||||
selectionContext: getLineSelectionContext(newSelection),
|
||||
};
|
||||
case "document":
|
||||
const document = selection.editor.document;
|
||||
// From https://stackoverflow.com/a/46427868
|
||||
}
|
||||
|
||||
case "document": {
|
||||
const firstLine = document.lineAt(0);
|
||||
const lastLine = document.lineAt(document.lineCount - 1);
|
||||
start = firstLine.range.start;
|
||||
end = lastLine.range.end;
|
||||
const start = firstLine.range.start;
|
||||
const end = lastLine.range.end;
|
||||
|
||||
return {
|
||||
selection: update(selection, {
|
||||
@ -313,11 +303,51 @@ function createTypedSelection(
|
||||
: new Selection(start, end),
|
||||
}),
|
||||
selectionType,
|
||||
position,
|
||||
insideOutsideType,
|
||||
selectionContext,
|
||||
insideOutsideType: target.insideOutsideType ?? null,
|
||||
position: target.position,
|
||||
};
|
||||
case "block":
|
||||
}
|
||||
|
||||
case "paragraph": {
|
||||
let startLine = document.lineAt(selection.selection.start);
|
||||
while (startLine.lineNumber > 0) {
|
||||
const line = document.lineAt(startLine.lineNumber - 1);
|
||||
if (line.isEmptyOrWhitespace) {
|
||||
break;
|
||||
}
|
||||
startLine = line;
|
||||
}
|
||||
const lineCount = document.lineCount;
|
||||
let endLine = document.lineAt(selection.selection.end);
|
||||
while (endLine.lineNumber + 1 < lineCount) {
|
||||
const line = document.lineAt(endLine.lineNumber + 1);
|
||||
if (line.isEmptyOrWhitespace) {
|
||||
break;
|
||||
}
|
||||
endLine = line;
|
||||
}
|
||||
|
||||
const start = new Position(
|
||||
startLine.lineNumber,
|
||||
startLine.firstNonWhitespaceCharacterIndex
|
||||
);
|
||||
const end = endLine.range.end;
|
||||
|
||||
const newSelection = update(selection, {
|
||||
selection: (s) =>
|
||||
s.isReversed ? new Selection(end, start) : new Selection(start, end),
|
||||
});
|
||||
|
||||
return {
|
||||
selection: newSelection,
|
||||
position,
|
||||
selectionType,
|
||||
insideOutsideType,
|
||||
selectionContext: getParagraphSelectionContext(newSelection),
|
||||
};
|
||||
}
|
||||
|
||||
case "character":
|
||||
throw new Error("Not implemented");
|
||||
}
|
||||
@ -428,11 +458,11 @@ function isSelectionContextEmpty(selectionContext: SelectionContext) {
|
||||
}
|
||||
|
||||
function getLineSelectionContext(
|
||||
selection: SelectionWithEditor,
|
||||
selectionContext: SelectionContext
|
||||
selection: SelectionWithEditor
|
||||
): SelectionContext {
|
||||
const document = selection.editor.document;
|
||||
const { start, end } = selection.selection;
|
||||
const { document } = selection.editor;
|
||||
const start = selection.selection.start;
|
||||
const end = selection.selection.end;
|
||||
|
||||
const leadingDelimiterRange =
|
||||
start.line > 0
|
||||
@ -446,14 +476,9 @@ function getLineSelectionContext(
|
||||
|
||||
const trailingDelimiterRange =
|
||||
end.line + 1 < document.lineCount
|
||||
? new Range(end.line, 0, end.line + 1, 0)
|
||||
? new Range(end.line, end.character, end.line + 1, 0)
|
||||
: null;
|
||||
|
||||
// Didn't find any delimiters
|
||||
if (leadingDelimiterRange == null && trailingDelimiterRange == null) {
|
||||
return selectionContext;
|
||||
}
|
||||
|
||||
// Outer selection contains the entire lines
|
||||
const outerSelection = new Selection(
|
||||
start.line,
|
||||
@ -462,9 +487,65 @@ function getLineSelectionContext(
|
||||
selection.editor.document.lineAt(end.line).range.end.character
|
||||
);
|
||||
|
||||
const isInDelimitedList =
|
||||
leadingDelimiterRange != null || trailingDelimiterRange != null;
|
||||
|
||||
return {
|
||||
isInDelimitedList: true,
|
||||
containingListDelimiter: "\n",
|
||||
isInDelimitedList,
|
||||
containingListDelimiter: isInDelimitedList ? "\n" : undefined,
|
||||
leadingDelimiterRange,
|
||||
trailingDelimiterRange,
|
||||
outerSelection,
|
||||
};
|
||||
}
|
||||
|
||||
function getParagraphSelectionContext(
|
||||
selection: SelectionWithEditor
|
||||
): SelectionContext {
|
||||
const { document } = selection.editor;
|
||||
const start = selection.selection.start;
|
||||
const end = selection.selection.end;
|
||||
|
||||
let leadingLine = document.lineAt(selection.selection.start);
|
||||
while (leadingLine.lineNumber > 0) {
|
||||
leadingLine = document.lineAt(leadingLine.lineNumber - 1);
|
||||
if (!leadingLine.isEmptyOrWhitespace) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const lineCount = document.lineCount;
|
||||
let trailingLine = document.lineAt(selection.selection.end);
|
||||
while (trailingLine.lineNumber + 1 < lineCount) {
|
||||
trailingLine = document.lineAt(trailingLine.lineNumber + 1);
|
||||
if (!trailingLine.isEmptyOrWhitespace) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const leadingDelimiterRange =
|
||||
leadingLine.lineNumber !== start.line
|
||||
? new Range(leadingLine.range.end, start)
|
||||
: null;
|
||||
const trailingDelimiterRange =
|
||||
trailingLine.lineNumber !== end.line
|
||||
? new Range(end, trailingLine.range.start)
|
||||
: null;
|
||||
|
||||
// Outer selection contains the entire lines
|
||||
const outerSelection = new Selection(
|
||||
start.line,
|
||||
0,
|
||||
end.line,
|
||||
selection.editor.document.lineAt(end.line).range.end.character
|
||||
);
|
||||
|
||||
const isInDelimitedList =
|
||||
leadingDelimiterRange != null || trailingDelimiterRange != null;
|
||||
|
||||
return {
|
||||
isInDelimitedList,
|
||||
containingListDelimiter: isInDelimitedList ? "\n\n" : undefined,
|
||||
leadingDelimiterRange,
|
||||
trailingDelimiterRange,
|
||||
outerSelection,
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { SelectionType } from "./Types";
|
||||
|
||||
export function isLineSelectionType(selectionType: SelectionType) {
|
||||
return selectionType === "line" || selectionType === "block";
|
||||
return selectionType === "line" || selectionType === "paragraph";
|
||||
}
|
||||
|
@ -330,7 +330,7 @@ const fixture: Fixture[] = [
|
||||
},
|
||||
end: {
|
||||
type: "primitive",
|
||||
selectionType: "block",
|
||||
selectionType: "paragraph",
|
||||
mark: {
|
||||
type: "decoratedSymbol",
|
||||
symbolColor: "red",
|
||||
@ -349,7 +349,7 @@ const fixture: Fixture[] = [
|
||||
mark: {
|
||||
type: "cursor",
|
||||
},
|
||||
selectionType: "block",
|
||||
selectionType: "paragraph",
|
||||
position: "contents",
|
||||
modifier: {
|
||||
type: "identity",
|
||||
@ -362,7 +362,7 @@ const fixture: Fixture[] = [
|
||||
symbolColor: "red",
|
||||
character: "h",
|
||||
},
|
||||
selectionType: "block",
|
||||
selectionType: "paragraph",
|
||||
position: "contents",
|
||||
modifier: {
|
||||
type: "identity",
|
||||
@ -786,7 +786,7 @@ const fixture: Fixture[] = [
|
||||
symbolColor: "default",
|
||||
character: "f",
|
||||
},
|
||||
selectionType: "block",
|
||||
selectionType: "paragraph",
|
||||
position: "after",
|
||||
modifier: {
|
||||
type: "identity",
|
||||
@ -817,7 +817,7 @@ const fixture: Fixture[] = [
|
||||
mark: {
|
||||
type: "cursor",
|
||||
},
|
||||
selectionType: "block",
|
||||
selectionType: "paragraph",
|
||||
position: "after",
|
||||
modifier: {
|
||||
type: "identity",
|
||||
@ -848,7 +848,7 @@ const fixture: Fixture[] = [
|
||||
mark: {
|
||||
type: "cursor",
|
||||
},
|
||||
selectionType: "block",
|
||||
selectionType: "paragraph",
|
||||
position: "contents",
|
||||
modifier: {
|
||||
type: "identity",
|
||||
@ -908,7 +908,7 @@ const fixture: Fixture[] = [
|
||||
mark: {
|
||||
type: "cursor",
|
||||
},
|
||||
selectionType: "block",
|
||||
selectionType: "paragraph",
|
||||
position: "contents",
|
||||
modifier: {
|
||||
type: "identity",
|
||||
@ -1814,7 +1814,7 @@ const fixture: Fixture[] = [
|
||||
end: {
|
||||
type: "primitive",
|
||||
position: "end",
|
||||
selectionType: "block",
|
||||
selectionType: "paragraph",
|
||||
},
|
||||
},
|
||||
],
|
||||
@ -1839,7 +1839,7 @@ const fixture: Fixture[] = [
|
||||
mark: {
|
||||
type: "cursor",
|
||||
},
|
||||
selectionType: "block",
|
||||
selectionType: "paragraph",
|
||||
position: "end",
|
||||
modifier: {
|
||||
type: "identity",
|
||||
|
Loading…
Reference in New Issue
Block a user