Skip to content

Commit

Permalink
Merge pull request #2427 from BetterThanTomorrow/wip/rayat/paredit/ki…
Browse files Browse the repository at this point in the history
…ll-left

Paredit - Introduce killLeft

* Fixes #2426
  • Loading branch information
PEZ authored Mar 21, 2024
2 parents 16c867d + 67cbe56 commit f2c7167
Show file tree
Hide file tree
Showing 14 changed files with 1,255 additions and 50 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ Changes to Calva.

## [Unreleased]

- [Add Paredit Kill Left equivalent to Kill Right](https://github.com/BetterThanTomorrow/calva/issues/2426)
- Fix: Certain `paredit.killRight` edges cases on Windows.

## [2.0.424] - 2024-03-17

- [Add command for revealing the **Calva says** output channel](https://github.com/BetterThanTomorrow/calva/issues/2436)
Expand Down
Binary file added docs/site/images/paredit/kill-left.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 2 additions & 1 deletion docs/site/paredit.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,8 @@ Default keybinding | Action | Description
`ctrl+alt+shift` `k`<br>`ctrl+alt+shift` `j` | **Drag Sexp Forward Up**<br>**Drag Sexp Backward Down** | Moves the current form up/out of the current list, *forwards*, and down/in to the preceding list, *backwards*, keeping the cursor within the sexpr being dragged.<br> ![](images/paredit/drag-forward-up-backward-down.gif)
`ctrl+shift+c` | **Convolute** | ¯\\\_(ツ)_/¯ <br> ![](images/paredit/convolute.gif)
`ctrl+shift+delete` | **Kill Sexp Forward** | Deletes the next form in the same enclosing form as the cursor.<br> ![](images/paredit/kill-forward-sexp.gif)
`ctrl+k` | **Kill Right** | Delete forward to the end of the current form or the first newline.<br> ![](images/paredit/kill-right.gif)
`ctrl+k ctrl+k` (win/linux)<br>`ctrl+k` (mac) | **Kill Right** | Delete forward to the end of the current form or the first newline.<br> ![](images/paredit/kill-right.gif)
`ctrl+k ctrl+h` (win/linux)<br>`cmd+backspace` (mac) | **Kill Left** | Delete backward to the start of the current form or the start of the line.<br> ![](images/paredit/kill-left.gif)
`ctrl+alt+backspace` | **Kill Sexp Backward** | Deletes the previous form in the same enclosing form as the cursor.<br> ![](images/paredit/kill-backward-sexp.gif)
`ctrl+delete` | **Kill List Forward** | Deletes everything from the cursor to the closing of the current enclosing form.<br> ![](images/paredit/kill-close-list.gif)
`ctrl+backspace` | **Kill List Backward** | Deletes everything from the cursor to the opening of the current enclosing form.<br> ![](images/paredit/kill-open-list.gif)
Expand Down
13 changes: 13 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -1740,6 +1740,12 @@
"title": "Kill/Delete Right",
"enablement": "editorLangId == clojure"
},
{
"category": "Calva Paredit",
"command": "paredit.killLeft",
"title": "Kill/Delete Left",
"enablement": "editorLangId == clojure"
},
{
"category": "Calva Paredit",
"command": "paredit.killSexpForward",
Expand Down Expand Up @@ -2488,6 +2494,13 @@
"linux": "ctrl+k ctrl+k",
"when": "calva:keybindingsEnabled && editorLangId == clojure && editorTextFocus && !selectionAnchorSet && paredit:keyMap =~ /original|strict/"
},
{
"command": "paredit.killLeft",
"mac": "cmd+backspace",
"win": "ctrl+k ctrl+h",
"linux": "ctrl+k ctrl+h",
"when": "calva:keybindingsEnabled && editorLangId == clojure && editorTextFocus && !selectionAnchorSet && paredit:keyMap =~ /original|strict/"
},
{
"command": "paredit.killSexpForward",
"key": "ctrl+shift+delete",
Expand Down
16 changes: 9 additions & 7 deletions src/calva-fmt/src/format.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ export async function formatRange(document: vscode.TextDocument, range: vscode.R
export async function formatPositionInfo(
editor: vscode.TextEditor,
onType: boolean = false,
extraConfig = {}
extraConfig: CljFmtConfig = {}
) {
const doc: vscode.TextDocument = editor.document;
const index = doc.offsetAt(editor.selections[0].active);
Expand Down Expand Up @@ -142,11 +142,13 @@ export async function formatPositionInfo(
};
}

function _calculateFormatRange(
config: { 'format-depth'?: number },
cursor: LispTokenCursor,
index: number
) {
interface CljFmtConfig {
'format-depth'?: number;
'align-associative?'?: boolean;
'remove-multiple-non-indenting-spaces?'?: boolean;
}

function _calculateFormatRange(config: CljFmtConfig, cursor: LispTokenCursor, index: number) {
const formatDepth = config?.['format-depth'] ?? _formatDepth(cursor);
const rangeForTopLevelForm = cursor.rangeForDefun(index, false);
const topLevelStartCursor = cursor.doc.getTokenCursor(rangeForTopLevelForm[0]);
Expand Down Expand Up @@ -195,7 +197,7 @@ function _formatDepth(cursor: LispTokenCursor) {
export async function formatPosition(
editor: vscode.TextEditor,
onType: boolean = false,
extraConfig = {}
extraConfig: CljFmtConfig = {}
): Promise<boolean> {
const doc: vscode.TextDocument = editor.document,
formattedInfo = await formatPositionInfo(editor, onType, extraConfig);
Expand Down
31 changes: 21 additions & 10 deletions src/cursor-doc/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,17 @@ export class ModelEdit<T extends ModelEditFunction> {
* even if the selection is in reverse.
*/
export type ModelEditRange = [start: number, end: number];
/**
* A range with direction representing a cursor/selection in a document.
* Is a tuple of [anchor, active] where each is an offset.
* It is a selection if `anchor` != `active`, otherwise, it's a cursor.
* 'Direction' here means if `anchor` is greater than `active`, the selection is
* from right to left, and vice versa.
*
* This type is only nominal and for documentation purposes, it's technically the
* same as `ModelEditRange`
*/
export type ModelEditDirectedRange = [anchor: number, active: number];

/**
* Naming notes for Model Selections:
Expand Down Expand Up @@ -447,13 +458,13 @@ export class LineInputModel implements EditableModel {
if (st[0] != en[0]) {
lines.push(this.lines[en[0]].text.substring(0, en[1]));
}
return lines.join('\n');
return lines.join(this.lineEnding);
}

/**
* Returns the row and column for a given text offset in this model.
*/
getRowCol(offset: number): [number, number] {
getRowCol(offset: number): [row: number, col: number] {
for (let i = 0; i < this.lines.length; i++) {
if (offset > this.lines[i].text.length) {
offset -= this.lines[i].text.length + this.lineEndingLength;
Expand All @@ -469,9 +480,9 @@ export class LineInputModel implements EditableModel {
* the model.
*
* @param offset The offset in the line model.
* @returns [number, number] The start and the index of the word in the model.
* @returns {ModelEditRange} The start and the index of the word in the model.
*/
getWordSelection(offset: number): [number, number] {
getWordSelection(offset: number): ModelEditRange {
const stopChars = [' ', '"', ';', '.', '(', ')', '[', ']', '{', '}', '\t', '\n', '\r'],
[row, column] = this.getRowCol(offset),
text = this.lines[row].text;
Expand Down Expand Up @@ -559,8 +570,8 @@ export class LineInputModel implements EditableModel {
start: number,
end: number,
text: string,
oldSelection?: [number, number],
newSelection?: [number, number]
oldSelection?: ModelEditRange,
newSelection?: ModelEditRange
) {
const t1 = new Date();

Expand Down Expand Up @@ -630,8 +641,8 @@ export class LineInputModel implements EditableModel {
insertString(
offset: number,
text: string,
oldSelection?: [number, number],
newSelection?: [number, number]
oldSelection?: ModelEditRange,
newSelection?: ModelEditRange
): number {
this.changeRange(offset, offset, text, oldSelection, newSelection);
return text.length;
Expand All @@ -649,8 +660,8 @@ export class LineInputModel implements EditableModel {
deleteRange(
offset: number,
count: number,
oldSelection?: [number, number],
newSelection?: [number, number]
oldSelection?: ModelEditRange,
newSelection?: ModelEditRange
) {
this.changeRange(offset, offset + count, '', oldSelection, newSelection);
}
Expand Down
Loading

0 comments on commit f2c7167

Please sign in to comment.