From 3f5942d9319a3944b8cbd56f5b6b59d4967e5db9 Mon Sep 17 00:00:00 2001 From: Nimaoth Date: Thu, 14 Mar 2024 23:08:06 +0100 Subject: [PATCH] more vim keybinding improvements --- config/keybindings_vim.nim | 114 ++++++++++++++++++++++++--- scripting/absytree_internal.nim | 11 ++- scripting/absytree_internal_wasm.nim | 10 ++- scripting/editor_text_api.nim | 14 +++- scripting/editor_text_api_wasm.nim | 59 ++++++++++++-- src/text/text_document.nim | 4 +- src/text/text_editor.nim | 15 ++-- 7 files changed, 192 insertions(+), 35 deletions(-) diff --git a/config/keybindings_vim.nim b/config/keybindings_vim.nim index 92795efb..e3d96ccb 100644 --- a/config/keybindings_vim.nim +++ b/config/keybindings_vim.nim @@ -1,6 +1,6 @@ -import std/[strutils, macros, genasts, unicode] +import std/[strutils, macros, genasts, sequtils] import absytree_runtime, keybindings_normal -import misc/[timer, util, myjsonutils] +import misc/[timer, util, myjsonutils, custom_unicode] import input_api infof"import vim keybindings" @@ -64,6 +64,7 @@ proc vimSelectLine(editor: TextDocumentEditor) {.expose("vim-select-line").} = proc vimSelectLastCursor(editor: TextDocumentEditor) {.expose("vim-select-last-cursor").} = # infof"vimSelectLastCursor" editor.selections = editor.selections.mapIt(it.last.toSelection) + editor.updateTargetColumn() proc vimSelectLast(editor: TextDocumentEditor, move: string, count: int = 1) {.expose("vim-select-last").} = # infof"vimSelectLast '{move}' {count}" @@ -71,6 +72,7 @@ proc vimSelectLast(editor: TextDocumentEditor, move: string, count: int = 1) {.e for i in 0.. {texts}" + + editor.addNextCheckpoint "insert" + editor.selections = editor.edit(editor.selections, texts, inclusiveEnd=true) + editor.setMode "normal" + proc vimSelectMove(editor: TextDocumentEditor, move: string, count: int = 1) {.expose("vim-select-move").} = # infof"vimSelectMove '{move}' {count}" let (action, arg) = move.parseAction for i in 0.. 0: + return res[0] else: return '\0' @@ -312,6 +346,33 @@ proc vimMotionSurround*(editor: TextDocumentEditor, cursor: Cursor, count: int, # infof"vimMotionSurround: found nothing {result}" return +proc vimMoveToMatching(editor: TextDocumentEditor) {.expose("vim-move-to-matching").} = + let c = editor.getText(editor.selection.last.toSelection, inclusiveEnd=true) + if c.len == 0: + return + + let (open, close, last) = case c[0] + of '(': ('(', ')', true) + of '{': ('{', '}', true) + of '[': ('[', ']', true) + of '<': ('<', '>', true) + of ')': ('(', ')', false) + of '}': ('{', '}', false) + of ']': ('[', ']', false) + of '>': ('<', '>', false) + of '"': ('"', '"', true) + of '\'': ('\'', '\'', true) + else: return + + let selection = editor.vimMotionSurround(editor.selection.last, 0, open, close, false) + if last: + editor.selection = selection.last.toSelection + else: + editor.selection = selection.first.toSelection + + editor.scrollToCursor Last + editor.updateTargetColumn() + proc vimMotionSurroundBracesInner*(editor: TextDocumentEditor, cursor: Cursor, count: int): Selection = vimMotionSurround(editor, cursor, count, '{', '}', true) proc vimMotionSurroundBracesOuter*(editor: TextDocumentEditor, cursor: Cursor, count: int): Selection = vimMotionSurround(editor, cursor, count, '{', '}', false) proc vimMotionSurroundParensInner*(editor: TextDocumentEditor, cursor: Cursor, count: int): Selection = vimMotionSurround(editor, cursor, count, '(', ')', true) @@ -403,6 +464,7 @@ proc vimSelectTextObject(editor: TextDocumentEditor, textObject: string, backwar ) editor.scrollToCursor(Last) + editor.updateTargetColumn() proc vimSelectSurrounding(editor: TextDocumentEditor, textObject: string, backwards: bool = false, allowEmpty: bool = false, count: int = 1, textObjectRange: VimTextObjectRange = Inner) {.expose("vim-select-surrounding").} = # infof"vimSelectSurrounding({textObject}, {textObjectRange}, {backwards}, {allowEmpty}, {count})" @@ -417,6 +479,7 @@ proc vimSelectSurrounding(editor: TextDocumentEditor, textObject: string, backwa ) editor.scrollToCursor(Last) + editor.updateTargetColumn() proc moveSelectionNext(editor: TextDocumentEditor, move: string, backwards: bool = false, allowEmpty: bool = false, count: int = 1) {.expose("move-selection-next").} = # infof"moveSelectionNext '{move}' {count} {backwards} {allowEmpty}" @@ -446,6 +509,7 @@ proc moveSelectionNext(editor: TextDocumentEditor, move: string, backwards: bool ) editor.scrollToCursor(Last) + editor.updateTargetColumn() proc moveSelectionEnd(editor: TextDocumentEditor, move: string, backwards: bool = false, allowEmpty: bool = false, count: int = 1) {.expose("move-selection-end").} = # infof"moveSelectionEnd '{move}' {count} {backwards} {allowEmpty}" @@ -474,6 +538,7 @@ proc moveSelectionEnd(editor: TextDocumentEditor, move: string, backwards: bool ) editor.scrollToCursor(Last) + editor.updateTargetColumn() proc moveParagraph(editor: TextDocumentEditor, backwards: bool, count: int = 1) {.expose("move-paragraph").} = let which = getOption[SelectionCursor](editor.getContextWithMode("editor.text.cursor.movement"), SelectionCursor.Both) @@ -494,6 +559,7 @@ proc moveParagraph(editor: TextDocumentEditor, backwards: bool, count: int = 1) editor.vimSelectLine() editor.scrollToCursor(Last) + editor.updateTargetColumn() proc vimDeleteLeft*(editor: TextDocumentEditor) = yankedLines = selectLines @@ -511,6 +577,7 @@ proc vimMoveCursorColumn(editor: TextDocumentEditor, direction: int, count: int editor.moveCursorColumn(direction * max(count, 1), wrap=false, includeAfter=vimCursorIncludeEol) if selectLines: editor.vimSelectLine() + editor.updateTargetColumn() proc vimMoveCursorLine(editor: TextDocumentEditor, direction: int, count: int = 1) {.expose("vim-move-cursor-line").} = editor.moveCursorLine(direction * max(count, 1), includeAfter=vimCursorIncludeEol) @@ -521,11 +588,13 @@ proc vimMoveFirst(editor: TextDocumentEditor, move: string) {.expose("vim-move-f editor.moveFirst(move) if selectLines: editor.vimSelectLine() + editor.updateTargetColumn() proc vimMoveLast(editor: TextDocumentEditor, move: string) {.expose("vim-move-last").} = editor.moveLast(move) if selectLines: editor.vimSelectLine() + editor.updateTargetColumn() proc vimMoveToEndOfLine(editor: TextDocumentEditor, count: int = 1) = # infof"vimMoveToEndOfLine {count}" @@ -534,10 +603,12 @@ proc vimMoveToEndOfLine(editor: TextDocumentEditor, count: int = 1) = editor.moveCursorLine(count - 1) editor.moveLast("vim-line") editor.scrollToCursor Last + editor.updateTargetColumn() proc vimMoveCursorLineFirstChar(editor: TextDocumentEditor, direction: int, count: int = 1) = editor.moveCursorLine(direction * max(count, 1)) editor.moveFirst "line-no-indent" + editor.updateTargetColumn() proc vimMoveToStartOfLine(editor: TextDocumentEditor, count: int = 1) = # infof"vimMoveToStartOfLine {count}" @@ -546,6 +617,7 @@ proc vimMoveToStartOfLine(editor: TextDocumentEditor, count: int = 1) = editor.moveCursorLine(count - 1) editor.moveFirst "line-no-indent" editor.scrollToCursor Last + editor.updateTargetColumn() proc vimPaste(editor: TextDocumentEditor, register: string = "") {.expose("vim-paste").} = # infof"vimPaste {register}, lines: {yankedLines}" @@ -638,8 +710,12 @@ proc loadVimKeybindings*() {.scriptActionWasmNims("load-vim-keybindings").} = # Normal mode addCommand "editor", ":", "command-line" - addTextCommandBlock "", "": editor.setMode("normal") - addTextCommandBlock "", "": editor.setMode("normal") + addTextCommandBlock "", "": + editor.selection = editor.selection + editor.setMode("normal") + addTextCommandBlock "", "": + editor.selection = editor.selection + editor.setMode("normal") addTextCommandBlock "", ".": replayCommands(".") addCommand "editor.text.normal", "@", "", proc(editor: TextDocumentEditor, c: string) = @@ -737,6 +813,7 @@ proc loadVimKeybindings*() {.scriptActionWasmNims("load-vim-keybindings").} = addSubCommandWithCountBlock "", "move", "|": editor.selections = editor.selections.mapIt((it.last.line, count).toSelection) editor.scrollToCursor Last + editor.updateTargetColumn() # navigation (vertical) addSubCommandWithCount "", "move", "k", "vim-move-cursor-line", -1 @@ -764,10 +841,9 @@ proc loadVimKeybindings*() {.scriptActionWasmNims("load-vim-keybindings").} = editor.moveFirst "line-no-indent" editor.scrollToCursor Last - addSubCommandWithCountBlock "", "move", "": + addSubCommandWithCountBlock "", "move", "%": if count == 0: - # todo: find matching bracket - discard + editor.vimMoveToMatching() else: let line = clamp((count * editor.lineCount) div 100, 0, editor.lineCount - 1) let which = getOption[SelectionCursor](editor.getContextWithMode("editor.text.cursor.movement"), SelectionCursor.Both) @@ -793,6 +869,7 @@ proc loadVimKeybindings*() {.scriptActionWasmNims("load-vim-keybindings").} = arr.add newJString("file") discard editor.runAction("move-last", arr) editor.setMode("insert") + editor.updateTargetColumn() # Scrolling addTextCommand "", "", "scroll-lines", 1 @@ -811,6 +888,7 @@ proc loadVimKeybindings*() {.scriptActionWasmNims("load-vim-keybindings").} = if editor.getCommandCount != 0: editor.selection = (editor.getCommandCount, 0).toSelection editor.moveFirst "line-no-indent" + editor.vimFinishMotion() editor.setCursorScrollOffset getVimLineMargin() * platformTotalLineHeight() addTextCommandBlock "", "zt": @@ -879,9 +957,6 @@ proc loadVimKeybindings*() {.scriptActionWasmNims("load-vim-keybindings").} = editor.setMode "insert" editor.addNextCheckpoint "insert" - addTextCommand "", "", "set-mode", "normal" - addTextCommand "", "", "set-mode", "normal" - # Text object motions addSubCommandWithCount "", "move", "w", "move-selection-next", "vim-word", false, true addSubCommandWithCount "", "move", "", "move-selection-next", "vim-word", false, true @@ -955,6 +1030,16 @@ proc loadVimKeybindings*() {.scriptActionWasmNims("load-vim-keybindings").} = editor.vimYankSelection() selectLines = false + # replace + addTextCommand "", "r", "set-mode", "replace" + setHandleInputs "editor.text.replace", true + setTextInputHandler "replace", proc(editor: TextDocumentEditor, input: string): bool = + editor.vimReplace(input) + return true + + addTextCommand "replace", "", "vim-replace", " " + addTextCommand "replace", "", "set-mode", "normal" + # Deleting text addTextCommand "", "x", vimDeleteRight addTextCommand "", "", vimDeleteRight @@ -1054,4 +1139,7 @@ proc loadVimKeybindings*() {.scriptActionWasmNims("load-vim-keybindings").} = addTextCommand "", "", "vim-undo" addTextCommand "", "", "vim-redo" addTextCommand "", "", "toggle-line-comment" + addTextCommand "", "", "print-undo-history" + addTextCommand "", "", "add-cursor-above" + addTextCommand "", "", "add-cursor-below" addTextCommand "", "", "print-undo-history" \ No newline at end of file diff --git a/scripting/absytree_internal.nim b/scripting/absytree_internal.nim index f576917e..4ccf8ac7 100644 --- a/scripting/absytree_internal.nim +++ b/scripting/absytree_internal.nim @@ -34,13 +34,13 @@ proc editor_text_getContextWithMode_string_TextDocumentEditor_string_impl*( self: TextDocumentEditor; context: string): string = discard proc editor_text_updateTargetColumn_void_TextDocumentEditor_SelectionCursor_impl*( - self: TextDocumentEditor; cursor: SelectionCursor) = + self: TextDocumentEditor; cursor: SelectionCursor = Last) = discard proc editor_text_invertSelection_void_TextDocumentEditor_impl*( self: TextDocumentEditor) = discard -proc editor_text_getText_string_TextDocumentEditor_Selection_impl*( - self: TextDocumentEditor; selection: Selection): string = +proc editor_text_getText_string_TextDocumentEditor_Selection_bool_impl*( + self: TextDocumentEditor; selection: Selection; inclusiveEnd: bool = false): string = discard proc editor_text_insert_seq_Selection_TextDocumentEditor_seq_Selection_string_bool_bool_impl*( self: TextDocumentEditor; selections: seq[Selection]; text: string; @@ -50,6 +50,11 @@ proc editor_text_delete_seq_Selection_TextDocumentEditor_seq_Selection_bool_bool self: TextDocumentEditor; selections: seq[Selection]; notify: bool = true; record: bool = true; inclusiveEnd: bool = false): seq[Selection] = discard +proc editor_text_edit_seq_Selection_TextDocumentEditor_seq_Selection_seq_string_bool_bool_bool_impl*( + self: TextDocumentEditor; selections: seq[Selection]; texts: seq[string]; + notify: bool = true; record: bool = true; inclusiveEnd: bool = false): seq[ + Selection] = + discard proc editor_text_selectPrev_void_TextDocumentEditor_impl*( self: TextDocumentEditor) = discard diff --git a/scripting/absytree_internal_wasm.nim b/scripting/absytree_internal_wasm.nim index 51766ef5..b313e2bb 100644 --- a/scripting/absytree_internal_wasm.nim +++ b/scripting/absytree_internal_wasm.nim @@ -23,17 +23,21 @@ proc editor_text_mode_string_TextDocumentEditor_impl(self: TextDocumentEditor): proc editor_text_getContextWithMode_string_TextDocumentEditor_string_impl( self: TextDocumentEditor; context: string): string {.importc.} proc editor_text_updateTargetColumn_void_TextDocumentEditor_SelectionCursor_impl( - self: TextDocumentEditor; cursor: SelectionCursor) {.importc.} + self: TextDocumentEditor; cursor: SelectionCursor = Last) {.importc.} proc editor_text_invertSelection_void_TextDocumentEditor_impl( self: TextDocumentEditor) {.importc.} -proc editor_text_getText_string_TextDocumentEditor_Selection_impl( - self: TextDocumentEditor; selection: Selection): string {.importc.} +proc editor_text_getText_string_TextDocumentEditor_Selection_bool_impl( + self: TextDocumentEditor; selection: Selection; inclusiveEnd: bool = false): string {.importc.} proc editor_text_insert_seq_Selection_TextDocumentEditor_seq_Selection_string_bool_bool_impl( self: TextDocumentEditor; selections: seq[Selection]; text: string; notify: bool = true; record: bool = true): seq[Selection] {.importc.} proc editor_text_delete_seq_Selection_TextDocumentEditor_seq_Selection_bool_bool_bool_impl( self: TextDocumentEditor; selections: seq[Selection]; notify: bool = true; record: bool = true; inclusiveEnd: bool = false): seq[Selection] {.importc.} +proc editor_text_edit_seq_Selection_TextDocumentEditor_seq_Selection_seq_string_bool_bool_bool_impl( + self: TextDocumentEditor; selections: seq[Selection]; texts: seq[string]; + notify: bool = true; record: bool = true; inclusiveEnd: bool = false): seq[ + Selection] {.importc.} proc editor_text_selectPrev_void_TextDocumentEditor_impl( self: TextDocumentEditor) {.importc.} proc editor_text_selectNext_void_TextDocumentEditor_impl( diff --git a/scripting/editor_text_api.nim b/scripting/editor_text_api.nim index 9e36bac8..812b9d9f 100644 --- a/scripting/editor_text_api.nim +++ b/scripting/editor_text_api.nim @@ -42,14 +42,17 @@ proc getContextWithMode*(self: TextDocumentEditor; context: string): string = ## Appends the current mode to context editor_text_getContextWithMode_string_TextDocumentEditor_string_impl(self, context) -proc updateTargetColumn*(self: TextDocumentEditor; cursor: SelectionCursor) = +proc updateTargetColumn*(self: TextDocumentEditor; + cursor: SelectionCursor = Last) = editor_text_updateTargetColumn_void_TextDocumentEditor_SelectionCursor_impl( self, cursor) proc invertSelection*(self: TextDocumentEditor) = ## Inverts the current selection. Discards all but the last cursor. editor_text_invertSelection_void_TextDocumentEditor_impl(self) -proc getText*(self: TextDocumentEditor; selection: Selection): string = - editor_text_getText_string_TextDocumentEditor_Selection_impl(self, selection) +proc getText*(self: TextDocumentEditor; selection: Selection; + inclusiveEnd: bool = false): string = + editor_text_getText_string_TextDocumentEditor_Selection_bool_impl(self, + selection, inclusiveEnd) proc insert*(self: TextDocumentEditor; selections: seq[Selection]; text: string; notify: bool = true; record: bool = true): seq[Selection] = editor_text_insert_seq_Selection_TextDocumentEditor_seq_Selection_string_bool_bool_impl( @@ -59,6 +62,11 @@ proc delete*(self: TextDocumentEditor; selections: seq[Selection]; inclusiveEnd: bool = false): seq[Selection] = editor_text_delete_seq_Selection_TextDocumentEditor_seq_Selection_bool_bool_bool_impl( self, selections, notify, record, inclusiveEnd) +proc edit*(self: TextDocumentEditor; selections: seq[Selection]; + texts: seq[string]; notify: bool = true; record: bool = true; + inclusiveEnd: bool = false): seq[Selection] = + editor_text_edit_seq_Selection_TextDocumentEditor_seq_Selection_seq_string_bool_bool_bool_impl( + self, selections, texts, notify, record, inclusiveEnd) proc selectPrev*(self: TextDocumentEditor) = editor_text_selectPrev_void_TextDocumentEditor_impl(self) proc selectNext*(self: TextDocumentEditor) = diff --git a/scripting/editor_text_api_wasm.nim b/scripting/editor_text_api_wasm.nim index fc4d2599..4574ff8b 100644 --- a/scripting/editor_text_api_wasm.nim +++ b/scripting/editor_text_api_wasm.nim @@ -228,7 +228,8 @@ proc getContextWithMode*(self: TextDocumentEditor; context: string): string = proc editor_text_updateTargetColumn_void_TextDocumentEditor_SelectionCursor_wasm( arg: cstring): cstring {.importc.} -proc updateTargetColumn*(self: TextDocumentEditor; cursor: SelectionCursor) = +proc updateTargetColumn*(self: TextDocumentEditor; + cursor: SelectionCursor = Last) = var argsJson = newJArray() argsJson.add block: when TextDocumentEditor is JsonNode: @@ -259,9 +260,10 @@ proc invertSelection*(self: TextDocumentEditor) = argsJsonString.cstring) -proc editor_text_getText_string_TextDocumentEditor_Selection_wasm(arg: cstring): cstring {. - importc.} -proc getText*(self: TextDocumentEditor; selection: Selection): string = +proc editor_text_getText_string_TextDocumentEditor_Selection_bool_wasm( + arg: cstring): cstring {.importc.} +proc getText*(self: TextDocumentEditor; selection: Selection; + inclusiveEnd: bool = false): string = var argsJson = newJArray() argsJson.add block: when TextDocumentEditor is JsonNode: @@ -273,8 +275,13 @@ proc getText*(self: TextDocumentEditor; selection: Selection): string = selection else: selection.toJson() + argsJson.add block: + when bool is JsonNode: + inclusiveEnd + else: + inclusiveEnd.toJson() let argsJsonString = $argsJson - let res {.used.} = editor_text_getText_string_TextDocumentEditor_Selection_wasm( + let res {.used.} = editor_text_getText_string_TextDocumentEditor_Selection_bool_wasm( argsJsonString.cstring) result = parseJson($res).jsonTo(typeof(result)) @@ -352,6 +359,48 @@ proc delete*(self: TextDocumentEditor; selections: seq[Selection]; result = parseJson($res).jsonTo(typeof(result)) +proc editor_text_edit_seq_Selection_TextDocumentEditor_seq_Selection_seq_string_bool_bool_bool_wasm( + arg: cstring): cstring {.importc.} +proc edit*(self: TextDocumentEditor; selections: seq[Selection]; + texts: seq[string]; notify: bool = true; record: bool = true; + inclusiveEnd: bool = false): seq[Selection] = + var argsJson = newJArray() + argsJson.add block: + when TextDocumentEditor is JsonNode: + self + else: + self.toJson() + argsJson.add block: + when seq[Selection] is JsonNode: + selections + else: + selections.toJson() + argsJson.add block: + when seq[string] is JsonNode: + texts + else: + texts.toJson() + argsJson.add block: + when bool is JsonNode: + notify + else: + notify.toJson() + argsJson.add block: + when bool is JsonNode: + record + else: + record.toJson() + argsJson.add block: + when bool is JsonNode: + inclusiveEnd + else: + inclusiveEnd.toJson() + let argsJsonString = $argsJson + let res {.used.} = editor_text_edit_seq_Selection_TextDocumentEditor_seq_Selection_seq_string_bool_bool_bool_wasm( + argsJsonString.cstring) + result = parseJson($res).jsonTo(typeof(result)) + + proc editor_text_selectPrev_void_TextDocumentEditor_wasm(arg: cstring): cstring {. importc.} proc selectPrev*(self: TextDocumentEditor) = diff --git a/src/text/text_document.nim b/src/text/text_document.nim index 9f8e95d9..df76548e 100644 --- a/src/text/text_document.nim +++ b/src/text/text_document.nim @@ -971,9 +971,9 @@ proc insert*(self: TextDocument, selections: openArray[Selection], oldSelection: self.nextCheckpoints = @[] -proc edit*(self: TextDocument, selections: openArray[Selection], oldSelection: openArray[Selection], texts: openArray[string], notify: bool = true, record: bool = true): seq[Selection] = +proc edit*(self: TextDocument, selections: openArray[Selection], oldSelection: openArray[Selection], texts: openArray[string], notify: bool = true, record: bool = true, inclusiveEnd: bool = false): seq[Selection] = let selections = selections.map (s) => s.normalized - result = self.delete(selections, oldSelection, false, record=record) + result = self.delete(selections, oldSelection, record=record, inclusiveEnd=inclusiveEnd) result = self.insert(result, oldSelection, texts, record=record) proc doUndo(self: TextDocument, op: UndoOp, oldSelection: openArray[Selection], useOldSelection: bool, redoOps: var seq[UndoOp]): seq[Selection] = diff --git a/src/text/text_editor.nim b/src/text/text_editor.nim index 68cf58a9..f93fa830 100644 --- a/src/text/text_editor.nim +++ b/src/text/text_editor.nim @@ -111,7 +111,7 @@ proc showCompletionWindow(self: TextDocumentEditor) proc refilterCompletions(self: TextDocumentEditor) proc getSelectionForMove*(self: TextDocumentEditor, cursor: Cursor, move: string, count: int = 0): Selection proc extendSelectionWithMove*(self: TextDocumentEditor, selection: Selection, move: string, count: int = 0): Selection -proc updateTargetColumn*(self: TextDocumentEditor, cursor: SelectionCursor) +proc updateTargetColumn*(self: TextDocumentEditor, cursor: SelectionCursor = Last) proc updateInlayHints*(self: TextDocumentEditor) proc clampCursor*(self: TextDocumentEditor, cursor: Cursor, includeAfter: bool = true): Cursor = self.document.clampCursor(cursor, includeAfter) @@ -581,22 +581,25 @@ proc getContextWithMode(self: TextDocumentEditor, context: string): string {.exp ## Appends the current mode to context return context & "." & $self.currentMode -proc updateTargetColumn*(self: TextDocumentEditor, cursor: SelectionCursor) {.expose("editor.text").} = +proc updateTargetColumn*(self: TextDocumentEditor, cursor: SelectionCursor = Last) {.expose("editor.text").} = self.targetColumn = self.getCursor(cursor).column proc invertSelection(self: TextDocumentEditor) {.expose("editor.text").} = ## Inverts the current selection. Discards all but the last cursor. self.selection = (self.selection.last, self.selection.first) -proc getText(self: TextDocumentEditor, selection: Selection): string {.expose("editor.text").} = - return self.document.contentString(selection) +proc getText*(self: TextDocumentEditor, selection: Selection, inclusiveEnd: bool = false): string {.expose("editor.text").} = + return self.document.contentString(selection, inclusiveEnd) -proc insert(self: TextDocumentEditor, selections: seq[Selection], text: string, notify: bool = true, record: bool = true): seq[Selection] {.expose("editor.text").} = +proc insert*(self: TextDocumentEditor, selections: seq[Selection], text: string, notify: bool = true, record: bool = true): seq[Selection] {.expose("editor.text").} = return self.document.insert(selections, self.selections, [text], notify, record) -proc delete(self: TextDocumentEditor, selections: seq[Selection], notify: bool = true, record: bool = true, inclusiveEnd: bool = false): seq[Selection] {.expose("editor.text").} = +proc delete*(self: TextDocumentEditor, selections: seq[Selection], notify: bool = true, record: bool = true, inclusiveEnd: bool = false): seq[Selection] {.expose("editor.text").} = return self.document.delete(selections, self.selections, notify, record, inclusiveEnd=inclusiveEnd) +proc edit*(self: TextDocumentEditor, selections: seq[Selection], texts: seq[string], notify: bool = true, record: bool = true, inclusiveEnd: bool = false): seq[Selection] {.expose("editor.text").} = + return self.document.edit(selections, self.selections, texts, notify, record, inclusiveEnd=inclusiveEnd) + proc selectPrev(self: TextDocumentEditor) {.expose("editor.text").} = if self.selectionHistory.len > 0: let selection = self.selectionHistory.popLast