@dst0/p-tui 0.4.41 → 5.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/autocomplete.d.ts.map +1 -1
- package/dist/autocomplete.js.map +1 -1
- package/dist/components/box.d.ts +3 -1
- package/dist/components/box.d.ts.map +1 -1
- package/dist/components/box.js +19 -10
- package/dist/components/box.js.map +1 -1
- package/dist/components/cancellable-loader.d.ts.map +1 -1
- package/dist/components/cancellable-loader.js.map +1 -1
- package/dist/components/editor/constants.d.ts +9 -0
- package/dist/components/editor/constants.d.ts.map +1 -0
- package/dist/components/editor/constants.js +12 -0
- package/dist/components/editor/constants.js.map +1 -0
- package/dist/components/editor/editor-methods/autocomplete-matching.d.ts +29 -0
- package/dist/components/editor/editor-methods/autocomplete-matching.d.ts.map +1 -0
- package/dist/components/editor/editor-methods/autocomplete-matching.js +104 -0
- package/dist/components/editor/editor-methods/autocomplete-matching.js.map +1 -0
- package/dist/components/editor/editor-methods/autocomplete-request.d.ts +14 -0
- package/dist/components/editor/editor-methods/autocomplete-request.d.ts.map +1 -0
- package/dist/components/editor/editor-methods/autocomplete-request.js +72 -0
- package/dist/components/editor/editor-methods/autocomplete-request.js.map +1 -0
- package/dist/components/editor/editor-methods/backspace-cursor.d.ts +9 -0
- package/dist/components/editor/editor-methods/backspace-cursor.d.ts.map +1 -0
- package/dist/components/editor/editor-methods/backspace-cursor.js +122 -0
- package/dist/components/editor/editor-methods/backspace-cursor.js.map +1 -0
- package/dist/components/editor/editor-methods/configuration.d.ts +17 -0
- package/dist/components/editor/editor-methods/configuration.d.ts.map +1 -0
- package/dist/components/editor/editor-methods/configuration.js +107 -0
- package/dist/components/editor/editor-methods/configuration.js.map +1 -0
- package/dist/components/editor/editor-methods/cursor-movement.d.ts +7 -0
- package/dist/components/editor/editor-methods/cursor-movement.d.ts.map +1 -0
- package/dist/components/editor/editor-methods/cursor-movement.js +112 -0
- package/dist/components/editor/editor-methods/cursor-movement.js.map +1 -0
- package/dist/components/editor/editor-methods/input-handling.d.ts +3 -0
- package/dist/components/editor/editor-methods/input-handling.d.ts.map +1 -0
- package/dist/components/editor/editor-methods/input-handling.js +257 -0
- package/dist/components/editor/editor-methods/input-handling.js.map +1 -0
- package/dist/components/editor/editor-methods/paste-submit.d.ts +7 -0
- package/dist/components/editor/editor-methods/paste-submit.d.ts.map +1 -0
- package/dist/components/editor/editor-methods/paste-submit.js +105 -0
- package/dist/components/editor/editor-methods/paste-submit.js.map +1 -0
- package/dist/components/editor/editor-methods/render.d.ts +3 -0
- package/dist/components/editor/editor-methods/render.d.ts.map +1 -0
- package/dist/components/editor/editor-methods/render.js +114 -0
- package/dist/components/editor/editor-methods/render.js.map +1 -0
- package/dist/components/editor/editor-methods/text-insertion.d.ts +4 -0
- package/dist/components/editor/editor-methods/text-insertion.d.ts.map +1 -0
- package/dist/components/editor/editor-methods/text-insertion.js +91 -0
- package/dist/components/editor/editor-methods/text-insertion.js.map +1 -0
- package/dist/components/editor/editor-methods/text-layout.d.ts +15 -0
- package/dist/components/editor/editor-methods/text-layout.d.ts.map +1 -0
- package/dist/components/editor/editor-methods/text-layout.js +129 -0
- package/dist/components/editor/editor-methods/text-layout.js.map +1 -0
- package/dist/components/editor/editor-methods/vertical-movement.d.ts +8 -0
- package/dist/components/editor/editor-methods/vertical-movement.d.ts.map +1 -0
- package/dist/components/editor/editor-methods/vertical-movement.js +123 -0
- package/dist/components/editor/editor-methods/vertical-movement.js.map +1 -0
- package/dist/components/editor/editor-methods/word-operations.d.ts +19 -0
- package/dist/components/editor/editor-methods/word-operations.d.ts.map +1 -0
- package/dist/components/editor/editor-methods/word-operations.js +122 -0
- package/dist/components/editor/editor-methods/word-operations.js.map +1 -0
- package/dist/components/editor/editor-methods/yank-undo.d.ts +11 -0
- package/dist/components/editor/editor-methods/yank-undo.d.ts.map +1 -0
- package/dist/components/editor/editor-methods/yank-undo.js +132 -0
- package/dist/components/editor/editor-methods/yank-undo.js.map +1 -0
- package/dist/components/editor/editor.d.ts +67 -0
- package/dist/components/editor/editor.d.ts.map +1 -0
- package/dist/components/editor/editor.js +93 -0
- package/dist/components/editor/editor.js.map +1 -0
- package/dist/components/editor/helpers.d.ts +3 -0
- package/dist/components/editor/helpers.d.ts.map +1 -0
- package/dist/components/editor/helpers.js +3 -0
- package/dist/components/editor/helpers.js.map +1 -0
- package/dist/components/editor/index.d.ts +4 -0
- package/dist/components/editor/index.d.ts.map +1 -0
- package/dist/components/editor/index.js +3 -0
- package/dist/components/editor/index.js.map +1 -0
- package/dist/components/editor/paste-marker.d.ts +5 -0
- package/dist/components/editor/paste-marker.d.ts.map +1 -0
- package/dist/components/editor/paste-marker.js +134 -0
- package/dist/components/editor/paste-marker.js.map +1 -0
- package/dist/components/editor/trigger-patterns.d.ts +4 -0
- package/dist/components/editor/trigger-patterns.d.ts.map +1 -0
- package/dist/components/editor/trigger-patterns.js +11 -0
- package/dist/components/editor/trigger-patterns.js.map +1 -0
- package/dist/components/editor/types.d.ts +25 -0
- package/dist/components/editor/types.d.ts.map +1 -0
- package/dist/components/editor/types.js +2 -0
- package/dist/components/editor/types.js.map +1 -0
- package/dist/components/editor.d.ts +1 -253
- package/dist/components/editor.d.ts.map +1 -1
- package/dist/components/editor.js +1 -1915
- package/dist/components/editor.js.map +1 -1
- package/dist/components/image.d.ts.map +1 -1
- package/dist/components/image.js.map +1 -1
- package/dist/components/input/constants.d.ts +2 -0
- package/dist/components/input/constants.d.ts.map +1 -0
- package/dist/components/input/constants.js +3 -0
- package/dist/components/input/constants.js.map +1 -0
- package/dist/components/input/index.d.ts +2 -0
- package/dist/components/input/index.d.ts.map +1 -0
- package/dist/components/input/index.js +2 -0
- package/dist/components/input/index.js.map +1 -0
- package/dist/components/input/input-methods/input-handling.d.ts +3 -0
- package/dist/components/input/input-methods/input-handling.d.ts.map +1 -0
- package/dist/components/input/input-methods/input-handling.js +145 -0
- package/dist/components/input/input-methods/input-handling.js.map +1 -0
- package/dist/components/input/input-methods/render.d.ts +3 -0
- package/dist/components/input/input-methods/render.d.ts.map +1 -0
- package/dist/components/input/input-methods/render.js +62 -0
- package/dist/components/input/input-methods/render.js.map +1 -0
- package/dist/components/input/input-methods/text-editing.d.ts +17 -0
- package/dist/components/input/input-methods/text-editing.d.ts.map +1 -0
- package/dist/components/input/input-methods/text-editing.js +145 -0
- package/dist/components/input/input-methods/text-editing.js.map +1 -0
- package/dist/components/input/input-methods/value-access.d.ts +4 -0
- package/dist/components/input/input-methods/value-access.d.ts.map +1 -0
- package/dist/components/input/input-methods/value-access.js +20 -0
- package/dist/components/input/input-methods/value-access.js.map +1 -0
- package/dist/components/input/input.d.ts +37 -0
- package/dist/components/input/input.d.ts.map +1 -0
- package/dist/components/input/input.js +77 -0
- package/dist/components/input/input.js.map +1 -0
- package/dist/components/input/types.d.ts +5 -0
- package/dist/components/input/types.d.ts.map +1 -0
- package/dist/components/input/types.js +2 -0
- package/dist/components/input/types.js.map +1 -0
- package/dist/components/input.d.ts +1 -36
- package/dist/components/input.d.ts.map +1 -1
- package/dist/components/input.js +1 -377
- package/dist/components/input.js.map +1 -1
- package/dist/components/loader.d.ts.map +1 -1
- package/dist/components/loader.js.map +1 -1
- package/dist/components/markdown/constants.d.ts +4 -0
- package/dist/components/markdown/constants.d.ts.map +1 -0
- package/dist/components/markdown/constants.js +8 -0
- package/dist/components/markdown/constants.js.map +1 -0
- package/dist/components/markdown/index.d.ts +3 -0
- package/dist/components/markdown/index.d.ts.map +1 -0
- package/dist/components/markdown/index.js +2 -0
- package/dist/components/markdown/index.js.map +1 -0
- package/dist/components/markdown/markdown-methods/inline-rendering.d.ts +7 -0
- package/dist/components/markdown/markdown-methods/inline-rendering.d.ts.map +1 -0
- package/dist/components/markdown/markdown-methods/inline-rendering.js +95 -0
- package/dist/components/markdown/markdown-methods/inline-rendering.js.map +1 -0
- package/dist/components/markdown/markdown-methods/list-table-helpers.d.ts +7 -0
- package/dist/components/markdown/markdown-methods/list-table-helpers.d.ts.map +1 -0
- package/dist/components/markdown/markdown-methods/list-table-helpers.js +61 -0
- package/dist/components/markdown/markdown-methods/list-table-helpers.js.map +1 -0
- package/dist/components/markdown/markdown-methods/table-rendering.d.ts +5 -0
- package/dist/components/markdown/markdown-methods/table-rendering.d.ts.map +1 -0
- package/dist/components/markdown/markdown-methods/table-rendering.js +146 -0
- package/dist/components/markdown/markdown-methods/table-rendering.js.map +1 -0
- package/dist/components/markdown/markdown-methods/text-rendering.d.ts +6 -0
- package/dist/components/markdown/markdown-methods/text-rendering.d.ts.map +1 -0
- package/dist/components/markdown/markdown-methods/text-rendering.js +115 -0
- package/dist/components/markdown/markdown-methods/text-rendering.js.map +1 -0
- package/dist/components/markdown/markdown-methods/theming.d.ts +6 -0
- package/dist/components/markdown/markdown-methods/theming.d.ts.map +1 -0
- package/dist/components/markdown/markdown-methods/theming.js +41 -0
- package/dist/components/markdown/markdown-methods/theming.js.map +1 -0
- package/dist/components/markdown/markdown-methods/token-rendering.d.ts +5 -0
- package/dist/components/markdown/markdown-methods/token-rendering.d.ts.map +1 -0
- package/dist/components/markdown/markdown-methods/token-rendering.js +142 -0
- package/dist/components/markdown/markdown-methods/token-rendering.js.map +1 -0
- package/dist/components/markdown/markdown.d.ts +32 -0
- package/dist/components/markdown/markdown.d.ts.map +1 -0
- package/dist/components/markdown/markdown.js +72 -0
- package/dist/components/markdown/markdown.js.map +1 -0
- package/dist/components/markdown/strictstrikethroughtokenizer.d.ts +6 -0
- package/dist/components/markdown/strictstrikethroughtokenizer.d.ts.map +1 -0
- package/dist/components/markdown/strictstrikethroughtokenizer.js +18 -0
- package/dist/components/markdown/strictstrikethroughtokenizer.js.map +1 -0
- package/dist/components/markdown/types.d.ts +42 -0
- package/dist/components/markdown/types.d.ts.map +1 -0
- package/dist/components/markdown/types.js +2 -0
- package/dist/components/markdown/types.js.map +1 -0
- package/dist/components/markdown.d.ts +1 -96
- package/dist/components/markdown.d.ts.map +1 -1
- package/dist/components/markdown.js +1 -653
- package/dist/components/markdown.js.map +1 -1
- package/dist/components/select-list.d.ts.map +1 -1
- package/dist/components/select-list.js +8 -3
- package/dist/components/select-list.js.map +1 -1
- package/dist/components/settings-list.d.ts.map +1 -1
- package/dist/components/settings-list.js +2 -6
- package/dist/components/settings-list.js.map +1 -1
- package/dist/components/spacer.d.ts.map +1 -1
- package/dist/components/spacer.js.map +1 -1
- package/dist/components/text.d.ts.map +1 -1
- package/dist/components/text.js +2 -2
- package/dist/components/text.js.map +1 -1
- package/dist/components/truncated-text.d.ts.map +1 -1
- package/dist/components/truncated-text.js.map +1 -1
- package/dist/editor-component.d.ts.map +1 -1
- package/dist/editor-component.js.map +1 -1
- package/dist/fuzzy.d.ts.map +1 -1
- package/dist/fuzzy.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/keybindings.d.ts.map +1 -1
- package/dist/keybindings.js.map +1 -1
- package/dist/keys.d.ts.map +1 -1
- package/dist/keys.js +145 -14
- package/dist/keys.js.map +1 -1
- package/dist/kill-ring.d.ts.map +1 -1
- package/dist/kill-ring.js.map +1 -1
- package/dist/native-modifiers.d.ts +9 -0
- package/dist/native-modifiers.d.ts.map +1 -1
- package/dist/native-modifiers.js +5 -0
- package/dist/native-modifiers.js.map +1 -1
- package/dist/stdin-buffer.d.ts +3 -0
- package/dist/stdin-buffer.d.ts.map +1 -1
- package/dist/stdin-buffer.js +24 -21
- package/dist/stdin-buffer.js.map +1 -1
- package/dist/terminal/constants.d.ts +9 -0
- package/dist/terminal/constants.d.ts.map +1 -0
- package/dist/terminal/constants.js +10 -0
- package/dist/terminal/constants.js.map +1 -0
- package/dist/terminal/helpers.d.ts +6 -0
- package/dist/terminal/helpers.d.ts.map +1 -0
- package/dist/terminal/helpers.js +23 -0
- package/dist/terminal/helpers.js.map +1 -0
- package/dist/terminal/index.d.ts +4 -0
- package/dist/terminal/index.d.ts.map +1 -0
- package/dist/terminal/index.js +3 -0
- package/dist/terminal/index.js.map +1 -0
- package/dist/terminal/processterminal-methods/cursor-screen.d.ts +11 -0
- package/dist/terminal/processterminal-methods/cursor-screen.d.ts.map +1 -0
- package/dist/terminal/processterminal-methods/cursor-screen.js +50 -0
- package/dist/terminal/processterminal-methods/cursor-screen.js.map +1 -0
- package/dist/terminal/processterminal-methods/keyboard-protocol.d.ts +14 -0
- package/dist/terminal/processterminal-methods/keyboard-protocol.d.ts.map +1 -0
- package/dist/terminal/processterminal-methods/keyboard-protocol.js +147 -0
- package/dist/terminal/processterminal-methods/keyboard-protocol.js.map +1 -0
- package/dist/terminal/processterminal-methods/terminal-io.d.ts +9 -0
- package/dist/terminal/processterminal-methods/terminal-io.d.ts.map +1 -0
- package/dist/terminal/processterminal-methods/terminal-io.js +153 -0
- package/dist/terminal/processterminal-methods/terminal-io.js.map +1 -0
- package/dist/terminal/processterminal.d.ts +49 -0
- package/dist/terminal/processterminal.d.ts.map +1 -0
- package/dist/terminal/processterminal.js +129 -0
- package/dist/terminal/processterminal.js.map +1 -0
- package/dist/terminal/types.d.ts +31 -0
- package/dist/terminal/types.d.ts.map +1 -0
- package/dist/terminal/types.js +2 -0
- package/dist/terminal/types.js.map +1 -0
- package/dist/terminal-colors.d.ts +2 -0
- package/dist/terminal-colors.d.ts.map +1 -1
- package/dist/terminal-colors.js +17 -5
- package/dist/terminal-colors.js.map +1 -1
- package/dist/terminal-image.d.ts.map +1 -1
- package/dist/terminal-image.js.map +1 -1
- package/dist/terminal.d.ts +1 -109
- package/dist/terminal.d.ts.map +1 -1
- package/dist/terminal.js +1 -432
- package/dist/terminal.js.map +1 -1
- package/dist/tui/constants.d.ts +3 -0
- package/dist/tui/constants.d.ts.map +1 -0
- package/dist/tui/constants.js +3 -0
- package/dist/tui/constants.js.map +1 -0
- package/dist/tui/container.d.ts +10 -0
- package/dist/tui/container.d.ts.map +1 -0
- package/dist/tui/container.js +31 -0
- package/dist/tui/container.js.map +1 -0
- package/dist/tui/helpers.d.ts +8 -0
- package/dist/tui/helpers.d.ts.map +1 -0
- package/dist/tui/helpers.js +53 -0
- package/dist/tui/helpers.js.map +1 -0
- package/dist/tui/index.d.ts +6 -0
- package/dist/tui/index.d.ts.map +1 -0
- package/dist/tui/index.js +5 -0
- package/dist/tui/index.js.map +1 -0
- package/dist/tui/tui-methods/configuration.d.ts +20 -0
- package/dist/tui/tui-methods/configuration.d.ts.map +1 -0
- package/dist/tui/tui-methods/configuration.js +131 -0
- package/dist/tui/tui-methods/configuration.js.map +1 -0
- package/dist/tui/tui-methods/cursor-background.d.ts +10 -0
- package/dist/tui/tui-methods/cursor-background.d.ts.map +1 -0
- package/dist/tui/tui-methods/cursor-background.js +52 -0
- package/dist/tui/tui-methods/cursor-background.js.map +1 -0
- package/dist/tui/tui-methods/incremental-render.d.ts +17 -0
- package/dist/tui/tui-methods/incremental-render.d.ts.map +1 -0
- package/dist/tui/tui-methods/incremental-render.js +259 -0
- package/dist/tui/tui-methods/incremental-render.js.map +1 -0
- package/dist/tui/tui-methods/input-handling.d.ts +5 -0
- package/dist/tui/tui-methods/input-handling.d.ts.map +1 -0
- package/dist/tui/tui-methods/input-handling.js +111 -0
- package/dist/tui/tui-methods/input-handling.js.map +1 -0
- package/dist/tui/tui-methods/line-compositing.d.ts +7 -0
- package/dist/tui/tui-methods/line-compositing.d.ts.map +1 -0
- package/dist/tui/tui-methods/line-compositing.js +61 -0
- package/dist/tui/tui-methods/line-compositing.js.map +1 -0
- package/dist/tui/tui-methods/overlay-compositing.d.ts +12 -0
- package/dist/tui/tui-methods/overlay-compositing.d.ts.map +1 -0
- package/dist/tui/tui-methods/overlay-compositing.js +123 -0
- package/dist/tui/tui-methods/overlay-compositing.js.map +1 -0
- package/dist/tui/tui-methods/overlay-layout.d.ts +11 -0
- package/dist/tui/tui-methods/overlay-layout.d.ts.map +1 -0
- package/dist/tui/tui-methods/overlay-layout.js +124 -0
- package/dist/tui/tui-methods/overlay-layout.js.map +1 -0
- package/dist/tui/tui-methods/overlay-management.d.ts +11 -0
- package/dist/tui/tui-methods/overlay-management.d.ts.map +1 -0
- package/dist/tui/tui-methods/overlay-management.js +152 -0
- package/dist/tui/tui-methods/overlay-management.js.map +1 -0
- package/dist/tui/tui-methods/render-pipeline.d.ts +3 -0
- package/dist/tui/tui-methods/render-pipeline.d.ts.map +1 -0
- package/dist/tui/tui-methods/render-pipeline.js +176 -0
- package/dist/tui/tui-methods/render-pipeline.js.map +1 -0
- package/dist/tui/tui-methods/render-width-error.d.ts +3 -0
- package/dist/tui/tui-methods/render-width-error.d.ts.map +1 -0
- package/dist/tui/tui-methods/render-width-error.js +28 -0
- package/dist/tui/tui-methods/render-width-error.js.map +1 -0
- package/dist/tui/tui-methods/terminal-control.d.ts +8 -0
- package/dist/tui/tui-methods/terminal-control.d.ts.map +1 -0
- package/dist/tui/tui-methods/terminal-control.js +101 -0
- package/dist/tui/tui-methods/terminal-control.js.map +1 -0
- package/dist/tui/tui.d.ts +59 -0
- package/dist/tui/tui.d.ts.map +1 -0
- package/dist/tui/tui.js +78 -0
- package/dist/tui/tui.js.map +1 -0
- package/dist/tui/types.d.ts +124 -0
- package/dist/tui/types.d.ts.map +1 -0
- package/dist/tui/types.js +2 -0
- package/dist/tui/types.js.map +1 -0
- package/dist/tui.d.ts +1 -254
- package/dist/tui.d.ts.map +1 -1
- package/dist/tui.js +1 -1344
- package/dist/tui.js.map +1 -1
- package/dist/undo-stack.d.ts.map +1 -1
- package/dist/undo-stack.js.map +1 -1
- package/dist/utils/ansi-wrapping.d.ts +5 -0
- package/dist/utils/ansi-wrapping.d.ts.map +1 -0
- package/dist/utils/ansi-wrapping.js +52 -0
- package/dist/utils/ansi-wrapping.js.map +1 -0
- package/dist/utils/ansicodetracker.d.ts +27 -0
- package/dist/utils/ansicodetracker.d.ts.map +1 -0
- package/dist/utils/ansicodetracker.js +222 -0
- package/dist/utils/ansicodetracker.js.map +1 -0
- package/dist/utils/column-slicing.d.ts +12 -0
- package/dist/utils/column-slicing.d.ts.map +1 -0
- package/dist/utils/column-slicing.js +111 -0
- package/dist/utils/column-slicing.js.map +1 -0
- package/dist/utils/column-truncation.d.ts +2 -0
- package/dist/utils/column-truncation.d.ts.map +1 -0
- package/dist/utils/column-truncation.js +129 -0
- package/dist/utils/column-truncation.js.map +1 -0
- package/dist/utils/constants.d.ts +12 -0
- package/dist/utils/constants.d.ts.map +1 -0
- package/dist/utils/constants.js +12 -0
- package/dist/utils/constants.js.map +1 -0
- package/dist/utils/index.d.ts +8 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +8 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/install-delegated-methods.d.ts +5 -0
- package/dist/utils/install-delegated-methods.d.ts.map +1 -0
- package/dist/utils/install-delegated-methods.js +27 -0
- package/dist/utils/install-delegated-methods.js.map +1 -0
- package/dist/utils/segmentation.d.ts +10 -0
- package/dist/utils/segmentation.d.ts.map +1 -0
- package/dist/utils/segmentation.js +111 -0
- package/dist/utils/segmentation.js.map +1 -0
- package/dist/utils/terminal-output.d.ts +10 -0
- package/dist/utils/terminal-output.d.ts.map +1 -0
- package/dist/utils/terminal-output.js +122 -0
- package/dist/utils/terminal-output.js.map +1 -0
- package/dist/utils/types.d.ts +7 -0
- package/dist/utils/types.d.ts.map +1 -0
- package/dist/utils/types.js +2 -0
- package/dist/utils/types.js.map +1 -0
- package/dist/utils/width-truncation.d.ts +6 -0
- package/dist/utils/width-truncation.d.ts.map +1 -0
- package/dist/utils/width-truncation.js +121 -0
- package/dist/utils/width-truncation.js.map +1 -0
- package/dist/utils/word-wrapping.d.ts +4 -0
- package/dist/utils/word-wrapping.d.ts.map +1 -0
- package/dist/utils/word-wrapping.js +139 -0
- package/dist/utils/word-wrapping.js.map +1 -0
- package/dist/utils.d.ts +1 -84
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +1 -1059
- package/dist/utils.js.map +1 -1
- package/dist/word-navigation.d.ts.map +1 -1
- package/dist/word-navigation.js.map +1 -1
- package/package.json +2 -1
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
export function do_computeVerticalMoveColumn(self, currentVisualCol, sourceMaxVisualCol, targetMaxVisualCol) {
|
|
2
|
+
const hasPreferred = self.preferredVisualCol !== null; // P
|
|
3
|
+
const cursorInMiddle = currentVisualCol < sourceMaxVisualCol; // S
|
|
4
|
+
const targetTooShort = targetMaxVisualCol < currentVisualCol; // T
|
|
5
|
+
if (!hasPreferred || cursorInMiddle) {
|
|
6
|
+
if (targetTooShort) {
|
|
7
|
+
// Cases 2 and 7
|
|
8
|
+
self.preferredVisualCol = currentVisualCol;
|
|
9
|
+
return targetMaxVisualCol;
|
|
10
|
+
}
|
|
11
|
+
// Cases 1 and 6
|
|
12
|
+
self.preferredVisualCol = null;
|
|
13
|
+
return currentVisualCol;
|
|
14
|
+
}
|
|
15
|
+
const targetCantFitPreferred = targetMaxVisualCol < self.preferredVisualCol; // U
|
|
16
|
+
if (targetTooShort || targetCantFitPreferred) {
|
|
17
|
+
// Cases 4 and 5
|
|
18
|
+
return targetMaxVisualCol;
|
|
19
|
+
}
|
|
20
|
+
// Case 3
|
|
21
|
+
const result = self.preferredVisualCol;
|
|
22
|
+
self.preferredVisualCol = null;
|
|
23
|
+
return result;
|
|
24
|
+
}
|
|
25
|
+
export function do_moveToLineStart(self) {
|
|
26
|
+
self.lastAction = null;
|
|
27
|
+
self.setCursorCol(0);
|
|
28
|
+
}
|
|
29
|
+
export function do_moveToLineEnd(self) {
|
|
30
|
+
self.lastAction = null;
|
|
31
|
+
const currentLine = self.state.lines[self.state.cursorLine] || "";
|
|
32
|
+
self.setCursorCol(currentLine.length);
|
|
33
|
+
}
|
|
34
|
+
export function do_deleteToStartOfLine(self) {
|
|
35
|
+
self.exitHistoryBrowsing();
|
|
36
|
+
const currentLine = self.state.lines[self.state.cursorLine] || "";
|
|
37
|
+
if (self.state.cursorCol > 0) {
|
|
38
|
+
self.pushUndoSnapshot();
|
|
39
|
+
// Calculate text to be deleted and save to kill ring (backward deletion = prepend)
|
|
40
|
+
const deletedText = currentLine.slice(0, self.state.cursorCol);
|
|
41
|
+
self.killRing.push(deletedText, { prepend: true, accumulate: self.lastAction === "kill" });
|
|
42
|
+
self.lastAction = "kill";
|
|
43
|
+
// Delete from start of line up to cursor
|
|
44
|
+
self.state.lines[self.state.cursorLine] = currentLine.slice(self.state.cursorCol);
|
|
45
|
+
self.setCursorCol(0);
|
|
46
|
+
}
|
|
47
|
+
else if (self.state.cursorLine > 0) {
|
|
48
|
+
self.pushUndoSnapshot();
|
|
49
|
+
// At start of line - merge with previous line, treating newline as deleted text
|
|
50
|
+
self.killRing.push("\n", { prepend: true, accumulate: self.lastAction === "kill" });
|
|
51
|
+
self.lastAction = "kill";
|
|
52
|
+
const previousLine = self.state.lines[self.state.cursorLine - 1] || "";
|
|
53
|
+
self.state.lines[self.state.cursorLine - 1] = previousLine + currentLine;
|
|
54
|
+
self.state.lines.splice(self.state.cursorLine, 1);
|
|
55
|
+
self.state.cursorLine--;
|
|
56
|
+
self.setCursorCol(previousLine.length);
|
|
57
|
+
}
|
|
58
|
+
if (self.onChange) {
|
|
59
|
+
self.onChange(self.getText());
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
export function do_deleteToEndOfLine(self) {
|
|
63
|
+
self.exitHistoryBrowsing();
|
|
64
|
+
const currentLine = self.state.lines[self.state.cursorLine] || "";
|
|
65
|
+
if (self.state.cursorCol < currentLine.length) {
|
|
66
|
+
self.pushUndoSnapshot();
|
|
67
|
+
// Calculate text to be deleted and save to kill ring (forward deletion = append)
|
|
68
|
+
const deletedText = currentLine.slice(self.state.cursorCol);
|
|
69
|
+
self.killRing.push(deletedText, { prepend: false, accumulate: self.lastAction === "kill" });
|
|
70
|
+
self.lastAction = "kill";
|
|
71
|
+
// Delete from cursor to end of line
|
|
72
|
+
self.state.lines[self.state.cursorLine] = currentLine.slice(0, self.state.cursorCol);
|
|
73
|
+
}
|
|
74
|
+
else if (self.state.cursorLine < self.state.lines.length - 1) {
|
|
75
|
+
self.pushUndoSnapshot();
|
|
76
|
+
// At end of line - merge with next line, treating newline as deleted text
|
|
77
|
+
self.killRing.push("\n", { prepend: false, accumulate: self.lastAction === "kill" });
|
|
78
|
+
self.lastAction = "kill";
|
|
79
|
+
const nextLine = self.state.lines[self.state.cursorLine + 1] || "";
|
|
80
|
+
self.state.lines[self.state.cursorLine] = currentLine + nextLine;
|
|
81
|
+
self.state.lines.splice(self.state.cursorLine + 1, 1);
|
|
82
|
+
}
|
|
83
|
+
if (self.onChange) {
|
|
84
|
+
self.onChange(self.getText());
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
export function do_deleteWordBackwards(self) {
|
|
88
|
+
self.exitHistoryBrowsing();
|
|
89
|
+
const currentLine = self.state.lines[self.state.cursorLine] || "";
|
|
90
|
+
// If at start of line, behave like backspace at column 0 (merge with previous line)
|
|
91
|
+
if (self.state.cursorCol === 0) {
|
|
92
|
+
if (self.state.cursorLine > 0) {
|
|
93
|
+
self.pushUndoSnapshot();
|
|
94
|
+
// Treat newline as deleted text (backward deletion = prepend)
|
|
95
|
+
self.killRing.push("\n", { prepend: true, accumulate: self.lastAction === "kill" });
|
|
96
|
+
self.lastAction = "kill";
|
|
97
|
+
const previousLine = self.state.lines[self.state.cursorLine - 1] || "";
|
|
98
|
+
self.state.lines[self.state.cursorLine - 1] = previousLine + currentLine;
|
|
99
|
+
self.state.lines.splice(self.state.cursorLine, 1);
|
|
100
|
+
self.state.cursorLine--;
|
|
101
|
+
self.setCursorCol(previousLine.length);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
self.pushUndoSnapshot();
|
|
106
|
+
// Save lastAction before cursor movement (moveWordBackwards resets it)
|
|
107
|
+
const wasKill = self.lastAction === "kill";
|
|
108
|
+
const oldCursorCol = self.state.cursorCol;
|
|
109
|
+
self.moveWordBackwards();
|
|
110
|
+
const deleteFrom = self.state.cursorCol;
|
|
111
|
+
self.setCursorCol(oldCursorCol);
|
|
112
|
+
const deletedText = currentLine.slice(deleteFrom, self.state.cursorCol);
|
|
113
|
+
self.killRing.push(deletedText, { prepend: true, accumulate: wasKill });
|
|
114
|
+
self.lastAction = "kill";
|
|
115
|
+
self.state.lines[self.state.cursorLine] =
|
|
116
|
+
currentLine.slice(0, deleteFrom) + currentLine.slice(self.state.cursorCol);
|
|
117
|
+
self.setCursorCol(deleteFrom);
|
|
118
|
+
}
|
|
119
|
+
if (self.onChange) {
|
|
120
|
+
self.onChange(self.getText());
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=vertical-movement.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vertical-movement.js","sourceRoot":"","sources":["../../../../src/components/editor/editor-methods/vertical-movement.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Editor } from \"../editor.ts\";\n\nexport function do_computeVerticalMoveColumn(\n self: Editor,\n currentVisualCol: number,\n sourceMaxVisualCol: number,\n targetMaxVisualCol: number,\n): number {\n const hasPreferred = self.preferredVisualCol !== null; // P\n const cursorInMiddle = currentVisualCol < sourceMaxVisualCol; // S\n const targetTooShort = targetMaxVisualCol < currentVisualCol; // T\n\n if (!hasPreferred || cursorInMiddle) {\n if (targetTooShort) {\n // Cases 2 and 7\n self.preferredVisualCol = currentVisualCol;\n return targetMaxVisualCol;\n }\n\n // Cases 1 and 6\n self.preferredVisualCol = null;\n return currentVisualCol;\n }\n\n const targetCantFitPreferred = targetMaxVisualCol < self.preferredVisualCol!; // U\n if (targetTooShort || targetCantFitPreferred) {\n // Cases 4 and 5\n return targetMaxVisualCol;\n }\n\n // Case 3\n const result = self.preferredVisualCol!;\n self.preferredVisualCol = null;\n return result;\n}\n\nexport function do_moveToLineStart(self: Editor): void {\n self.lastAction = null;\n self.setCursorCol(0);\n}\n\nexport function do_moveToLineEnd(self: Editor): void {\n self.lastAction = null;\n const currentLine = self.state.lines[self.state.cursorLine] || \"\";\n self.setCursorCol(currentLine.length);\n}\n\nexport function do_deleteToStartOfLine(self: Editor): void {\n self.exitHistoryBrowsing();\n\n const currentLine = self.state.lines[self.state.cursorLine] || \"\";\n\n if (self.state.cursorCol > 0) {\n self.pushUndoSnapshot();\n\n // Calculate text to be deleted and save to kill ring (backward deletion = prepend)\n const deletedText = currentLine.slice(0, self.state.cursorCol);\n self.killRing.push(deletedText, { prepend: true, accumulate: self.lastAction === \"kill\" });\n self.lastAction = \"kill\";\n\n // Delete from start of line up to cursor\n self.state.lines[self.state.cursorLine] = currentLine.slice(self.state.cursorCol);\n self.setCursorCol(0);\n } else if (self.state.cursorLine > 0) {\n self.pushUndoSnapshot();\n\n // At start of line - merge with previous line, treating newline as deleted text\n self.killRing.push(\"\\n\", { prepend: true, accumulate: self.lastAction === \"kill\" });\n self.lastAction = \"kill\";\n\n const previousLine = self.state.lines[self.state.cursorLine - 1] || \"\";\n self.state.lines[self.state.cursorLine - 1] = previousLine + currentLine;\n self.state.lines.splice(self.state.cursorLine, 1);\n self.state.cursorLine--;\n self.setCursorCol(previousLine.length);\n }\n\n if (self.onChange) {\n self.onChange(self.getText());\n }\n}\n\nexport function do_deleteToEndOfLine(self: Editor): void {\n self.exitHistoryBrowsing();\n\n const currentLine = self.state.lines[self.state.cursorLine] || \"\";\n\n if (self.state.cursorCol < currentLine.length) {\n self.pushUndoSnapshot();\n\n // Calculate text to be deleted and save to kill ring (forward deletion = append)\n const deletedText = currentLine.slice(self.state.cursorCol);\n self.killRing.push(deletedText, { prepend: false, accumulate: self.lastAction === \"kill\" });\n self.lastAction = \"kill\";\n\n // Delete from cursor to end of line\n self.state.lines[self.state.cursorLine] = currentLine.slice(0, self.state.cursorCol);\n } else if (self.state.cursorLine < self.state.lines.length - 1) {\n self.pushUndoSnapshot();\n\n // At end of line - merge with next line, treating newline as deleted text\n self.killRing.push(\"\\n\", { prepend: false, accumulate: self.lastAction === \"kill\" });\n self.lastAction = \"kill\";\n\n const nextLine = self.state.lines[self.state.cursorLine + 1] || \"\";\n self.state.lines[self.state.cursorLine] = currentLine + nextLine;\n self.state.lines.splice(self.state.cursorLine + 1, 1);\n }\n\n if (self.onChange) {\n self.onChange(self.getText());\n }\n}\n\nexport function do_deleteWordBackwards(self: Editor): void {\n self.exitHistoryBrowsing();\n\n const currentLine = self.state.lines[self.state.cursorLine] || \"\";\n\n // If at start of line, behave like backspace at column 0 (merge with previous line)\n if (self.state.cursorCol === 0) {\n if (self.state.cursorLine > 0) {\n self.pushUndoSnapshot();\n\n // Treat newline as deleted text (backward deletion = prepend)\n self.killRing.push(\"\\n\", { prepend: true, accumulate: self.lastAction === \"kill\" });\n self.lastAction = \"kill\";\n\n const previousLine = self.state.lines[self.state.cursorLine - 1] || \"\";\n self.state.lines[self.state.cursorLine - 1] = previousLine + currentLine;\n self.state.lines.splice(self.state.cursorLine, 1);\n self.state.cursorLine--;\n self.setCursorCol(previousLine.length);\n }\n } else {\n self.pushUndoSnapshot();\n\n // Save lastAction before cursor movement (moveWordBackwards resets it)\n const wasKill = self.lastAction === \"kill\";\n\n const oldCursorCol = self.state.cursorCol;\n self.moveWordBackwards();\n const deleteFrom = self.state.cursorCol;\n self.setCursorCol(oldCursorCol);\n\n const deletedText = currentLine.slice(deleteFrom, self.state.cursorCol);\n self.killRing.push(deletedText, { prepend: true, accumulate: wasKill });\n self.lastAction = \"kill\";\n\n self.state.lines[self.state.cursorLine] =\n currentLine.slice(0, deleteFrom) + currentLine.slice(self.state.cursorCol);\n self.setCursorCol(deleteFrom);\n }\n\n if (self.onChange) {\n self.onChange(self.getText());\n }\n}\n"]}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Editor } from "../editor.ts";
|
|
2
|
+
export declare function do_deleteWordForward(self: Editor): void;
|
|
3
|
+
export declare function do_handleForwardDelete(self: Editor): void;
|
|
4
|
+
export declare function do_buildVisualLineMap(self: Editor, width: number): Array<{
|
|
5
|
+
logicalLine: number;
|
|
6
|
+
startCol: number;
|
|
7
|
+
length: number;
|
|
8
|
+
}>;
|
|
9
|
+
export declare function do_findVisualLineAt(_self: Editor, visualLines: Array<{
|
|
10
|
+
logicalLine: number;
|
|
11
|
+
startCol: number;
|
|
12
|
+
length: number;
|
|
13
|
+
}>, line: number, col: number): number;
|
|
14
|
+
export declare function do_findCurrentVisualLine(self: Editor, visualLines: Array<{
|
|
15
|
+
logicalLine: number;
|
|
16
|
+
startCol: number;
|
|
17
|
+
length: number;
|
|
18
|
+
}>): number;
|
|
19
|
+
//# sourceMappingURL=word-operations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"word-operations.d.ts","sourceRoot":"","sources":["../../../../src/components/editor/editor-methods/word-operations.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAG3C,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAuCvD;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAgDzD;AAED,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,GACZ,KAAK,CAAC;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAyBlE;AAED,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,KAAK,CAAC;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,EAC7E,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,MAAM,GACV,MAAM,CAaR;AAED,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,KAAK,CAAC;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,GAC5E,MAAM,CAER","sourcesContent":["import { visibleWidth } from \"../../../utils.ts\";\nimport type { Editor } from \"../editor.ts\";\nimport { wordWrapLine } from \"../paste-marker.ts\";\n\nexport function do_deleteWordForward(self: Editor): void {\n self.exitHistoryBrowsing();\n\n const currentLine = self.state.lines[self.state.cursorLine] || \"\";\n\n // If at end of line, merge with next line (delete the newline)\n if (self.state.cursorCol >= currentLine.length) {\n if (self.state.cursorLine < self.state.lines.length - 1) {\n self.pushUndoSnapshot();\n\n // Treat newline as deleted text (forward deletion = append)\n self.killRing.push(\"\\n\", { prepend: false, accumulate: self.lastAction === \"kill\" });\n self.lastAction = \"kill\";\n\n const nextLine = self.state.lines[self.state.cursorLine + 1] || \"\";\n self.state.lines[self.state.cursorLine] = currentLine + nextLine;\n self.state.lines.splice(self.state.cursorLine + 1, 1);\n }\n } else {\n self.pushUndoSnapshot();\n\n // Save lastAction before cursor movement (moveWordForwards resets it)\n const wasKill = self.lastAction === \"kill\";\n\n const oldCursorCol = self.state.cursorCol;\n self.moveWordForwards();\n const deleteTo = self.state.cursorCol;\n self.setCursorCol(oldCursorCol);\n\n const deletedText = currentLine.slice(self.state.cursorCol, deleteTo);\n self.killRing.push(deletedText, { prepend: false, accumulate: wasKill });\n self.lastAction = \"kill\";\n\n self.state.lines[self.state.cursorLine] = currentLine.slice(0, self.state.cursorCol) + currentLine.slice(deleteTo);\n }\n\n if (self.onChange) {\n self.onChange(self.getText());\n }\n}\n\nexport function do_handleForwardDelete(self: Editor): void {\n self.exitHistoryBrowsing();\n self.lastAction = null;\n\n const currentLine = self.state.lines[self.state.cursorLine] || \"\";\n\n if (self.state.cursorCol < currentLine.length) {\n self.pushUndoSnapshot();\n\n // Delete grapheme at cursor position (handles emojis, combining characters, etc.)\n const afterCursor = currentLine.slice(self.state.cursorCol);\n\n // Find the first grapheme at cursor\n const graphemes = [...self.segment(afterCursor, \"grapheme\")];\n const firstGrapheme = graphemes[0];\n const graphemeLength = firstGrapheme ? firstGrapheme.segment.length : 1;\n\n const before = currentLine.slice(0, self.state.cursorCol);\n const after = currentLine.slice(self.state.cursorCol + graphemeLength);\n self.state.lines[self.state.cursorLine] = before + after;\n } else if (self.state.cursorLine < self.state.lines.length - 1) {\n self.pushUndoSnapshot();\n\n // At end of line - merge with next line\n const nextLine = self.state.lines[self.state.cursorLine + 1] || \"\";\n self.state.lines[self.state.cursorLine] = currentLine + nextLine;\n self.state.lines.splice(self.state.cursorLine + 1, 1);\n }\n\n if (self.onChange) {\n self.onChange(self.getText());\n }\n\n // Update or re-trigger autocomplete after forward delete\n if (self.autocompleteState) {\n self.updateAutocomplete();\n } else {\n const currentLine = self.state.lines[self.state.cursorLine] || \"\";\n const textBeforeCursor = currentLine.slice(0, self.state.cursorCol);\n // Slash command context\n if (self.isInSlashCommandContext(textBeforeCursor)) {\n self.tryTriggerAutocomplete();\n }\n // Symbol-based completion context like @, #, or provider triggers\n else if (self.autocompleteTriggerPattern.test(textBeforeCursor)) {\n self.tryTriggerAutocomplete();\n }\n }\n}\n\nexport function do_buildVisualLineMap(\n self: Editor,\n width: number,\n): Array<{ logicalLine: number; startCol: number; length: number }> {\n const visualLines: Array<{ logicalLine: number; startCol: number; length: number }> = [];\n\n for (let i = 0; i < self.state.lines.length; i++) {\n const line = self.state.lines[i] || \"\";\n const lineVisWidth = visibleWidth(line);\n if (line.length === 0) {\n // Empty line still takes one visual line\n visualLines.push({ logicalLine: i, startCol: 0, length: 0 });\n } else if (lineVisWidth <= width) {\n visualLines.push({ logicalLine: i, startCol: 0, length: line.length });\n } else {\n // Line needs wrapping - use word-aware wrapping\n const chunks = wordWrapLine(line, width, [...self.segment(line, \"grapheme\")]);\n for (const chunk of chunks) {\n visualLines.push({\n logicalLine: i,\n startCol: chunk.startIndex,\n length: chunk.endIndex - chunk.startIndex,\n });\n }\n }\n }\n\n return visualLines;\n}\n\nexport function do_findVisualLineAt(\n _self: Editor,\n visualLines: Array<{ logicalLine: number; startCol: number; length: number }>,\n line: number,\n col: number,\n): number {\n for (let i = 0; i < visualLines.length; i++) {\n const vl = visualLines[i];\n if (!vl || vl.logicalLine !== line) continue;\n const offset = col - vl.startCol;\n // Cursor is in self segment if it's within range. For the last\n // segment of a logical line, cursor can be at length (end position)\n const isLastSegmentOfLine = i === visualLines.length - 1 || visualLines[i + 1]?.logicalLine !== vl.logicalLine;\n if (offset >= 0 && (offset < vl.length || (isLastSegmentOfLine && offset === vl.length))) {\n return i;\n }\n }\n return visualLines.length - 1;\n}\n\nexport function do_findCurrentVisualLine(\n self: Editor,\n visualLines: Array<{ logicalLine: number; startCol: number; length: number }>,\n): number {\n return self.findVisualLineAt(visualLines, self.state.cursorLine, self.state.cursorCol);\n}\n"]}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { visibleWidth } from "../../../utils.js";
|
|
2
|
+
import { wordWrapLine } from "../paste-marker.js";
|
|
3
|
+
export function do_deleteWordForward(self) {
|
|
4
|
+
self.exitHistoryBrowsing();
|
|
5
|
+
const currentLine = self.state.lines[self.state.cursorLine] || "";
|
|
6
|
+
// If at end of line, merge with next line (delete the newline)
|
|
7
|
+
if (self.state.cursorCol >= currentLine.length) {
|
|
8
|
+
if (self.state.cursorLine < self.state.lines.length - 1) {
|
|
9
|
+
self.pushUndoSnapshot();
|
|
10
|
+
// Treat newline as deleted text (forward deletion = append)
|
|
11
|
+
self.killRing.push("\n", { prepend: false, accumulate: self.lastAction === "kill" });
|
|
12
|
+
self.lastAction = "kill";
|
|
13
|
+
const nextLine = self.state.lines[self.state.cursorLine + 1] || "";
|
|
14
|
+
self.state.lines[self.state.cursorLine] = currentLine + nextLine;
|
|
15
|
+
self.state.lines.splice(self.state.cursorLine + 1, 1);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
self.pushUndoSnapshot();
|
|
20
|
+
// Save lastAction before cursor movement (moveWordForwards resets it)
|
|
21
|
+
const wasKill = self.lastAction === "kill";
|
|
22
|
+
const oldCursorCol = self.state.cursorCol;
|
|
23
|
+
self.moveWordForwards();
|
|
24
|
+
const deleteTo = self.state.cursorCol;
|
|
25
|
+
self.setCursorCol(oldCursorCol);
|
|
26
|
+
const deletedText = currentLine.slice(self.state.cursorCol, deleteTo);
|
|
27
|
+
self.killRing.push(deletedText, { prepend: false, accumulate: wasKill });
|
|
28
|
+
self.lastAction = "kill";
|
|
29
|
+
self.state.lines[self.state.cursorLine] = currentLine.slice(0, self.state.cursorCol) + currentLine.slice(deleteTo);
|
|
30
|
+
}
|
|
31
|
+
if (self.onChange) {
|
|
32
|
+
self.onChange(self.getText());
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
export function do_handleForwardDelete(self) {
|
|
36
|
+
self.exitHistoryBrowsing();
|
|
37
|
+
self.lastAction = null;
|
|
38
|
+
const currentLine = self.state.lines[self.state.cursorLine] || "";
|
|
39
|
+
if (self.state.cursorCol < currentLine.length) {
|
|
40
|
+
self.pushUndoSnapshot();
|
|
41
|
+
// Delete grapheme at cursor position (handles emojis, combining characters, etc.)
|
|
42
|
+
const afterCursor = currentLine.slice(self.state.cursorCol);
|
|
43
|
+
// Find the first grapheme at cursor
|
|
44
|
+
const graphemes = [...self.segment(afterCursor, "grapheme")];
|
|
45
|
+
const firstGrapheme = graphemes[0];
|
|
46
|
+
const graphemeLength = firstGrapheme ? firstGrapheme.segment.length : 1;
|
|
47
|
+
const before = currentLine.slice(0, self.state.cursorCol);
|
|
48
|
+
const after = currentLine.slice(self.state.cursorCol + graphemeLength);
|
|
49
|
+
self.state.lines[self.state.cursorLine] = before + after;
|
|
50
|
+
}
|
|
51
|
+
else if (self.state.cursorLine < self.state.lines.length - 1) {
|
|
52
|
+
self.pushUndoSnapshot();
|
|
53
|
+
// At end of line - merge with next line
|
|
54
|
+
const nextLine = self.state.lines[self.state.cursorLine + 1] || "";
|
|
55
|
+
self.state.lines[self.state.cursorLine] = currentLine + nextLine;
|
|
56
|
+
self.state.lines.splice(self.state.cursorLine + 1, 1);
|
|
57
|
+
}
|
|
58
|
+
if (self.onChange) {
|
|
59
|
+
self.onChange(self.getText());
|
|
60
|
+
}
|
|
61
|
+
// Update or re-trigger autocomplete after forward delete
|
|
62
|
+
if (self.autocompleteState) {
|
|
63
|
+
self.updateAutocomplete();
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
const currentLine = self.state.lines[self.state.cursorLine] || "";
|
|
67
|
+
const textBeforeCursor = currentLine.slice(0, self.state.cursorCol);
|
|
68
|
+
// Slash command context
|
|
69
|
+
if (self.isInSlashCommandContext(textBeforeCursor)) {
|
|
70
|
+
self.tryTriggerAutocomplete();
|
|
71
|
+
}
|
|
72
|
+
// Symbol-based completion context like @, #, or provider triggers
|
|
73
|
+
else if (self.autocompleteTriggerPattern.test(textBeforeCursor)) {
|
|
74
|
+
self.tryTriggerAutocomplete();
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
export function do_buildVisualLineMap(self, width) {
|
|
79
|
+
const visualLines = [];
|
|
80
|
+
for (let i = 0; i < self.state.lines.length; i++) {
|
|
81
|
+
const line = self.state.lines[i] || "";
|
|
82
|
+
const lineVisWidth = visibleWidth(line);
|
|
83
|
+
if (line.length === 0) {
|
|
84
|
+
// Empty line still takes one visual line
|
|
85
|
+
visualLines.push({ logicalLine: i, startCol: 0, length: 0 });
|
|
86
|
+
}
|
|
87
|
+
else if (lineVisWidth <= width) {
|
|
88
|
+
visualLines.push({ logicalLine: i, startCol: 0, length: line.length });
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
// Line needs wrapping - use word-aware wrapping
|
|
92
|
+
const chunks = wordWrapLine(line, width, [...self.segment(line, "grapheme")]);
|
|
93
|
+
for (const chunk of chunks) {
|
|
94
|
+
visualLines.push({
|
|
95
|
+
logicalLine: i,
|
|
96
|
+
startCol: chunk.startIndex,
|
|
97
|
+
length: chunk.endIndex - chunk.startIndex,
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return visualLines;
|
|
103
|
+
}
|
|
104
|
+
export function do_findVisualLineAt(_self, visualLines, line, col) {
|
|
105
|
+
for (let i = 0; i < visualLines.length; i++) {
|
|
106
|
+
const vl = visualLines[i];
|
|
107
|
+
if (!vl || vl.logicalLine !== line)
|
|
108
|
+
continue;
|
|
109
|
+
const offset = col - vl.startCol;
|
|
110
|
+
// Cursor is in self segment if it's within range. For the last
|
|
111
|
+
// segment of a logical line, cursor can be at length (end position)
|
|
112
|
+
const isLastSegmentOfLine = i === visualLines.length - 1 || visualLines[i + 1]?.logicalLine !== vl.logicalLine;
|
|
113
|
+
if (offset >= 0 && (offset < vl.length || (isLastSegmentOfLine && offset === vl.length))) {
|
|
114
|
+
return i;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return visualLines.length - 1;
|
|
118
|
+
}
|
|
119
|
+
export function do_findCurrentVisualLine(self, visualLines) {
|
|
120
|
+
return self.findVisualLineAt(visualLines, self.state.cursorLine, self.state.cursorCol);
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=word-operations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"word-operations.js","sourceRoot":"","sources":["../../../../src/components/editor/editor-methods/word-operations.ts"],"names":[],"mappings":"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","sourcesContent":["import { visibleWidth } from \"../../../utils.ts\";\nimport type { Editor } from \"../editor.ts\";\nimport { wordWrapLine } from \"../paste-marker.ts\";\n\nexport function do_deleteWordForward(self: Editor): void {\n self.exitHistoryBrowsing();\n\n const currentLine = self.state.lines[self.state.cursorLine] || \"\";\n\n // If at end of line, merge with next line (delete the newline)\n if (self.state.cursorCol >= currentLine.length) {\n if (self.state.cursorLine < self.state.lines.length - 1) {\n self.pushUndoSnapshot();\n\n // Treat newline as deleted text (forward deletion = append)\n self.killRing.push(\"\\n\", { prepend: false, accumulate: self.lastAction === \"kill\" });\n self.lastAction = \"kill\";\n\n const nextLine = self.state.lines[self.state.cursorLine + 1] || \"\";\n self.state.lines[self.state.cursorLine] = currentLine + nextLine;\n self.state.lines.splice(self.state.cursorLine + 1, 1);\n }\n } else {\n self.pushUndoSnapshot();\n\n // Save lastAction before cursor movement (moveWordForwards resets it)\n const wasKill = self.lastAction === \"kill\";\n\n const oldCursorCol = self.state.cursorCol;\n self.moveWordForwards();\n const deleteTo = self.state.cursorCol;\n self.setCursorCol(oldCursorCol);\n\n const deletedText = currentLine.slice(self.state.cursorCol, deleteTo);\n self.killRing.push(deletedText, { prepend: false, accumulate: wasKill });\n self.lastAction = \"kill\";\n\n self.state.lines[self.state.cursorLine] = currentLine.slice(0, self.state.cursorCol) + currentLine.slice(deleteTo);\n }\n\n if (self.onChange) {\n self.onChange(self.getText());\n }\n}\n\nexport function do_handleForwardDelete(self: Editor): void {\n self.exitHistoryBrowsing();\n self.lastAction = null;\n\n const currentLine = self.state.lines[self.state.cursorLine] || \"\";\n\n if (self.state.cursorCol < currentLine.length) {\n self.pushUndoSnapshot();\n\n // Delete grapheme at cursor position (handles emojis, combining characters, etc.)\n const afterCursor = currentLine.slice(self.state.cursorCol);\n\n // Find the first grapheme at cursor\n const graphemes = [...self.segment(afterCursor, \"grapheme\")];\n const firstGrapheme = graphemes[0];\n const graphemeLength = firstGrapheme ? firstGrapheme.segment.length : 1;\n\n const before = currentLine.slice(0, self.state.cursorCol);\n const after = currentLine.slice(self.state.cursorCol + graphemeLength);\n self.state.lines[self.state.cursorLine] = before + after;\n } else if (self.state.cursorLine < self.state.lines.length - 1) {\n self.pushUndoSnapshot();\n\n // At end of line - merge with next line\n const nextLine = self.state.lines[self.state.cursorLine + 1] || \"\";\n self.state.lines[self.state.cursorLine] = currentLine + nextLine;\n self.state.lines.splice(self.state.cursorLine + 1, 1);\n }\n\n if (self.onChange) {\n self.onChange(self.getText());\n }\n\n // Update or re-trigger autocomplete after forward delete\n if (self.autocompleteState) {\n self.updateAutocomplete();\n } else {\n const currentLine = self.state.lines[self.state.cursorLine] || \"\";\n const textBeforeCursor = currentLine.slice(0, self.state.cursorCol);\n // Slash command context\n if (self.isInSlashCommandContext(textBeforeCursor)) {\n self.tryTriggerAutocomplete();\n }\n // Symbol-based completion context like @, #, or provider triggers\n else if (self.autocompleteTriggerPattern.test(textBeforeCursor)) {\n self.tryTriggerAutocomplete();\n }\n }\n}\n\nexport function do_buildVisualLineMap(\n self: Editor,\n width: number,\n): Array<{ logicalLine: number; startCol: number; length: number }> {\n const visualLines: Array<{ logicalLine: number; startCol: number; length: number }> = [];\n\n for (let i = 0; i < self.state.lines.length; i++) {\n const line = self.state.lines[i] || \"\";\n const lineVisWidth = visibleWidth(line);\n if (line.length === 0) {\n // Empty line still takes one visual line\n visualLines.push({ logicalLine: i, startCol: 0, length: 0 });\n } else if (lineVisWidth <= width) {\n visualLines.push({ logicalLine: i, startCol: 0, length: line.length });\n } else {\n // Line needs wrapping - use word-aware wrapping\n const chunks = wordWrapLine(line, width, [...self.segment(line, \"grapheme\")]);\n for (const chunk of chunks) {\n visualLines.push({\n logicalLine: i,\n startCol: chunk.startIndex,\n length: chunk.endIndex - chunk.startIndex,\n });\n }\n }\n }\n\n return visualLines;\n}\n\nexport function do_findVisualLineAt(\n _self: Editor,\n visualLines: Array<{ logicalLine: number; startCol: number; length: number }>,\n line: number,\n col: number,\n): number {\n for (let i = 0; i < visualLines.length; i++) {\n const vl = visualLines[i];\n if (!vl || vl.logicalLine !== line) continue;\n const offset = col - vl.startCol;\n // Cursor is in self segment if it's within range. For the last\n // segment of a logical line, cursor can be at length (end position)\n const isLastSegmentOfLine = i === visualLines.length - 1 || visualLines[i + 1]?.logicalLine !== vl.logicalLine;\n if (offset >= 0 && (offset < vl.length || (isLastSegmentOfLine && offset === vl.length))) {\n return i;\n }\n }\n return visualLines.length - 1;\n}\n\nexport function do_findCurrentVisualLine(\n self: Editor,\n visualLines: Array<{ logicalLine: number; startCol: number; length: number }>,\n): number {\n return self.findVisualLineAt(visualLines, self.state.cursorLine, self.state.cursorCol);\n}\n"]}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Editor } from "../editor.ts";
|
|
2
|
+
export declare function do_insertYankedText(self: Editor, text: string): void;
|
|
3
|
+
export declare function do_deleteYankedText(self: Editor): void;
|
|
4
|
+
export declare function do_pushUndoSnapshot(self: Editor): void;
|
|
5
|
+
export declare function do_undo(self: Editor): void;
|
|
6
|
+
export declare function do_jumpToChar(self: Editor, char: string, direction: "forward" | "backward"): void;
|
|
7
|
+
export declare function do_moveWordForwards(self: Editor): void;
|
|
8
|
+
export declare function do_isSlashMenuAllowed(self: Editor): boolean;
|
|
9
|
+
export declare function do_isAtStartOfMessage(self: Editor): boolean;
|
|
10
|
+
export declare function do_isInSlashCommandContext(self: Editor, textBeforeCursor: string): boolean;
|
|
11
|
+
//# sourceMappingURL=yank-undo.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"yank-undo.d.ts","sourceRoot":"","sources":["../../../../src/components/editor/editor-methods/yank-undo.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAG3C,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAqCpE;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAoCtD;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAEtD;AAED,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAU1C;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,GAAG,UAAU,GAAG,IAAI,CAwBjG;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAmBtD;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE3D;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAK3D;AAED,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAE1F","sourcesContent":["import { findWordForward } from \"../../../word-navigation.ts\";\nimport type { Editor } from \"../editor.ts\";\nimport { isPasteMarker } from \"../paste-marker.ts\";\n\nexport function do_insertYankedText(self: Editor, text: string): void {\n self.exitHistoryBrowsing();\n const lines = text.split(\"\\n\");\n\n if (lines.length === 1) {\n // Single line - insert at cursor\n const currentLine = self.state.lines[self.state.cursorLine] || \"\";\n const before = currentLine.slice(0, self.state.cursorCol);\n const after = currentLine.slice(self.state.cursorCol);\n self.state.lines[self.state.cursorLine] = before + text + after;\n self.setCursorCol(self.state.cursorCol + text.length);\n } else {\n // Multi-line insert\n const currentLine = self.state.lines[self.state.cursorLine] || \"\";\n const before = currentLine.slice(0, self.state.cursorCol);\n const after = currentLine.slice(self.state.cursorCol);\n\n // First line merges with text before cursor\n self.state.lines[self.state.cursorLine] = before + (lines[0] || \"\");\n\n // Insert middle lines\n for (let i = 1; i < lines.length - 1; i++) {\n self.state.lines.splice(self.state.cursorLine + i, 0, lines[i] || \"\");\n }\n\n // Last line merges with text after cursor\n const lastLineIndex = self.state.cursorLine + lines.length - 1;\n self.state.lines.splice(lastLineIndex, 0, (lines[lines.length - 1] || \"\") + after);\n\n // Update cursor position\n self.state.cursorLine = lastLineIndex;\n self.setCursorCol((lines[lines.length - 1] || \"\").length);\n }\n\n if (self.onChange) {\n self.onChange(self.getText());\n }\n}\n\nexport function do_deleteYankedText(self: Editor): void {\n const yankedText = self.killRing.peek();\n if (!yankedText) return;\n\n const yankLines = yankedText.split(\"\\n\");\n\n if (yankLines.length === 1) {\n // Single line - delete backward from cursor\n const currentLine = self.state.lines[self.state.cursorLine] || \"\";\n const deleteLen = yankedText.length;\n const before = currentLine.slice(0, self.state.cursorCol - deleteLen);\n const after = currentLine.slice(self.state.cursorCol);\n self.state.lines[self.state.cursorLine] = before + after;\n self.setCursorCol(self.state.cursorCol - deleteLen);\n } else {\n // Multi-line delete - cursor is at end of last yanked line\n const startLine = self.state.cursorLine - (yankLines.length - 1);\n const startCol = (self.state.lines[startLine] || \"\").length - (yankLines[0] || \"\").length;\n\n // Get text after cursor on current line\n const afterCursor = (self.state.lines[self.state.cursorLine] || \"\").slice(self.state.cursorCol);\n\n // Get text before yank start position\n const beforeYank = (self.state.lines[startLine] || \"\").slice(0, startCol);\n\n // Remove all lines from startLine to cursorLine and replace with merged line\n self.state.lines.splice(startLine, yankLines.length, beforeYank + afterCursor);\n\n // Update cursor\n self.state.cursorLine = startLine;\n self.setCursorCol(startCol);\n }\n\n if (self.onChange) {\n self.onChange(self.getText());\n }\n}\n\nexport function do_pushUndoSnapshot(self: Editor): void {\n self.undoStack.push(self.state);\n}\n\nexport function do_undo(self: Editor): void {\n self.exitHistoryBrowsing();\n const snapshot = self.undoStack.pop();\n if (!snapshot) return;\n Object.assign(self.state, snapshot);\n self.lastAction = null;\n self.preferredVisualCol = null;\n if (self.onChange) {\n self.onChange(self.getText());\n }\n}\n\nexport function do_jumpToChar(self: Editor, char: string, direction: \"forward\" | \"backward\"): void {\n self.lastAction = null;\n const isForward = direction === \"forward\";\n const lines = self.state.lines;\n\n const end = isForward ? lines.length : -1;\n const step = isForward ? 1 : -1;\n\n for (let lineIdx = self.state.cursorLine; lineIdx !== end; lineIdx += step) {\n const line = lines[lineIdx] || \"\";\n const isCurrentLine = lineIdx === self.state.cursorLine;\n\n // Current line: start after/before cursor; other lines: search full line\n const searchFrom = isCurrentLine ? (isForward ? self.state.cursorCol + 1 : self.state.cursorCol - 1) : undefined;\n\n const idx = isForward ? line.indexOf(char, searchFrom) : line.lastIndexOf(char, searchFrom);\n\n if (idx !== -1) {\n self.state.cursorLine = lineIdx;\n self.setCursorCol(idx);\n return;\n }\n }\n // No match found - cursor stays in place\n}\n\nexport function do_moveWordForwards(self: Editor): void {\n self.lastAction = null;\n const currentLine = self.state.lines[self.state.cursorLine] || \"\";\n\n // If at end of line, move to start of next line\n if (self.state.cursorCol >= currentLine.length) {\n if (self.state.cursorLine < self.state.lines.length - 1) {\n self.state.cursorLine++;\n self.setCursorCol(0);\n }\n return;\n }\n\n self.setCursorCol(\n findWordForward(currentLine, self.state.cursorCol, {\n segment: (text) => self.segment(text, \"word\"),\n isAtomicSegment: isPasteMarker,\n }),\n );\n}\n\nexport function do_isSlashMenuAllowed(self: Editor): boolean {\n return self.state.cursorLine === 0;\n}\n\nexport function do_isAtStartOfMessage(self: Editor): boolean {\n if (!self.isSlashMenuAllowed()) return false;\n const currentLine = self.state.lines[self.state.cursorLine] || \"\";\n const beforeCursor = currentLine.slice(0, self.state.cursorCol);\n return beforeCursor.trim() === \"\" || beforeCursor.trim() === \"/\";\n}\n\nexport function do_isInSlashCommandContext(self: Editor, textBeforeCursor: string): boolean {\n return self.isSlashMenuAllowed() && textBeforeCursor.trimStart().startsWith(\"/\");\n}\n"]}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { findWordForward } from "../../../word-navigation.js";
|
|
2
|
+
import { isPasteMarker } from "../paste-marker.js";
|
|
3
|
+
export function do_insertYankedText(self, text) {
|
|
4
|
+
self.exitHistoryBrowsing();
|
|
5
|
+
const lines = text.split("\n");
|
|
6
|
+
if (lines.length === 1) {
|
|
7
|
+
// Single line - insert at cursor
|
|
8
|
+
const currentLine = self.state.lines[self.state.cursorLine] || "";
|
|
9
|
+
const before = currentLine.slice(0, self.state.cursorCol);
|
|
10
|
+
const after = currentLine.slice(self.state.cursorCol);
|
|
11
|
+
self.state.lines[self.state.cursorLine] = before + text + after;
|
|
12
|
+
self.setCursorCol(self.state.cursorCol + text.length);
|
|
13
|
+
}
|
|
14
|
+
else {
|
|
15
|
+
// Multi-line insert
|
|
16
|
+
const currentLine = self.state.lines[self.state.cursorLine] || "";
|
|
17
|
+
const before = currentLine.slice(0, self.state.cursorCol);
|
|
18
|
+
const after = currentLine.slice(self.state.cursorCol);
|
|
19
|
+
// First line merges with text before cursor
|
|
20
|
+
self.state.lines[self.state.cursorLine] = before + (lines[0] || "");
|
|
21
|
+
// Insert middle lines
|
|
22
|
+
for (let i = 1; i < lines.length - 1; i++) {
|
|
23
|
+
self.state.lines.splice(self.state.cursorLine + i, 0, lines[i] || "");
|
|
24
|
+
}
|
|
25
|
+
// Last line merges with text after cursor
|
|
26
|
+
const lastLineIndex = self.state.cursorLine + lines.length - 1;
|
|
27
|
+
self.state.lines.splice(lastLineIndex, 0, (lines[lines.length - 1] || "") + after);
|
|
28
|
+
// Update cursor position
|
|
29
|
+
self.state.cursorLine = lastLineIndex;
|
|
30
|
+
self.setCursorCol((lines[lines.length - 1] || "").length);
|
|
31
|
+
}
|
|
32
|
+
if (self.onChange) {
|
|
33
|
+
self.onChange(self.getText());
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
export function do_deleteYankedText(self) {
|
|
37
|
+
const yankedText = self.killRing.peek();
|
|
38
|
+
if (!yankedText)
|
|
39
|
+
return;
|
|
40
|
+
const yankLines = yankedText.split("\n");
|
|
41
|
+
if (yankLines.length === 1) {
|
|
42
|
+
// Single line - delete backward from cursor
|
|
43
|
+
const currentLine = self.state.lines[self.state.cursorLine] || "";
|
|
44
|
+
const deleteLen = yankedText.length;
|
|
45
|
+
const before = currentLine.slice(0, self.state.cursorCol - deleteLen);
|
|
46
|
+
const after = currentLine.slice(self.state.cursorCol);
|
|
47
|
+
self.state.lines[self.state.cursorLine] = before + after;
|
|
48
|
+
self.setCursorCol(self.state.cursorCol - deleteLen);
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
// Multi-line delete - cursor is at end of last yanked line
|
|
52
|
+
const startLine = self.state.cursorLine - (yankLines.length - 1);
|
|
53
|
+
const startCol = (self.state.lines[startLine] || "").length - (yankLines[0] || "").length;
|
|
54
|
+
// Get text after cursor on current line
|
|
55
|
+
const afterCursor = (self.state.lines[self.state.cursorLine] || "").slice(self.state.cursorCol);
|
|
56
|
+
// Get text before yank start position
|
|
57
|
+
const beforeYank = (self.state.lines[startLine] || "").slice(0, startCol);
|
|
58
|
+
// Remove all lines from startLine to cursorLine and replace with merged line
|
|
59
|
+
self.state.lines.splice(startLine, yankLines.length, beforeYank + afterCursor);
|
|
60
|
+
// Update cursor
|
|
61
|
+
self.state.cursorLine = startLine;
|
|
62
|
+
self.setCursorCol(startCol);
|
|
63
|
+
}
|
|
64
|
+
if (self.onChange) {
|
|
65
|
+
self.onChange(self.getText());
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
export function do_pushUndoSnapshot(self) {
|
|
69
|
+
self.undoStack.push(self.state);
|
|
70
|
+
}
|
|
71
|
+
export function do_undo(self) {
|
|
72
|
+
self.exitHistoryBrowsing();
|
|
73
|
+
const snapshot = self.undoStack.pop();
|
|
74
|
+
if (!snapshot)
|
|
75
|
+
return;
|
|
76
|
+
Object.assign(self.state, snapshot);
|
|
77
|
+
self.lastAction = null;
|
|
78
|
+
self.preferredVisualCol = null;
|
|
79
|
+
if (self.onChange) {
|
|
80
|
+
self.onChange(self.getText());
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
export function do_jumpToChar(self, char, direction) {
|
|
84
|
+
self.lastAction = null;
|
|
85
|
+
const isForward = direction === "forward";
|
|
86
|
+
const lines = self.state.lines;
|
|
87
|
+
const end = isForward ? lines.length : -1;
|
|
88
|
+
const step = isForward ? 1 : -1;
|
|
89
|
+
for (let lineIdx = self.state.cursorLine; lineIdx !== end; lineIdx += step) {
|
|
90
|
+
const line = lines[lineIdx] || "";
|
|
91
|
+
const isCurrentLine = lineIdx === self.state.cursorLine;
|
|
92
|
+
// Current line: start after/before cursor; other lines: search full line
|
|
93
|
+
const searchFrom = isCurrentLine ? (isForward ? self.state.cursorCol + 1 : self.state.cursorCol - 1) : undefined;
|
|
94
|
+
const idx = isForward ? line.indexOf(char, searchFrom) : line.lastIndexOf(char, searchFrom);
|
|
95
|
+
if (idx !== -1) {
|
|
96
|
+
self.state.cursorLine = lineIdx;
|
|
97
|
+
self.setCursorCol(idx);
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
// No match found - cursor stays in place
|
|
102
|
+
}
|
|
103
|
+
export function do_moveWordForwards(self) {
|
|
104
|
+
self.lastAction = null;
|
|
105
|
+
const currentLine = self.state.lines[self.state.cursorLine] || "";
|
|
106
|
+
// If at end of line, move to start of next line
|
|
107
|
+
if (self.state.cursorCol >= currentLine.length) {
|
|
108
|
+
if (self.state.cursorLine < self.state.lines.length - 1) {
|
|
109
|
+
self.state.cursorLine++;
|
|
110
|
+
self.setCursorCol(0);
|
|
111
|
+
}
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
self.setCursorCol(findWordForward(currentLine, self.state.cursorCol, {
|
|
115
|
+
segment: (text) => self.segment(text, "word"),
|
|
116
|
+
isAtomicSegment: isPasteMarker,
|
|
117
|
+
}));
|
|
118
|
+
}
|
|
119
|
+
export function do_isSlashMenuAllowed(self) {
|
|
120
|
+
return self.state.cursorLine === 0;
|
|
121
|
+
}
|
|
122
|
+
export function do_isAtStartOfMessage(self) {
|
|
123
|
+
if (!self.isSlashMenuAllowed())
|
|
124
|
+
return false;
|
|
125
|
+
const currentLine = self.state.lines[self.state.cursorLine] || "";
|
|
126
|
+
const beforeCursor = currentLine.slice(0, self.state.cursorCol);
|
|
127
|
+
return beforeCursor.trim() === "" || beforeCursor.trim() === "/";
|
|
128
|
+
}
|
|
129
|
+
export function do_isInSlashCommandContext(self, textBeforeCursor) {
|
|
130
|
+
return self.isSlashMenuAllowed() && textBeforeCursor.trimStart().startsWith("/");
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=yank-undo.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"yank-undo.js","sourceRoot":"","sources":["../../../../src/components/editor/editor-methods/yank-undo.ts"],"names":[],"mappings":"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","sourcesContent":["import { findWordForward } from \"../../../word-navigation.ts\";\nimport type { Editor } from \"../editor.ts\";\nimport { isPasteMarker } from \"../paste-marker.ts\";\n\nexport function do_insertYankedText(self: Editor, text: string): void {\n self.exitHistoryBrowsing();\n const lines = text.split(\"\\n\");\n\n if (lines.length === 1) {\n // Single line - insert at cursor\n const currentLine = self.state.lines[self.state.cursorLine] || \"\";\n const before = currentLine.slice(0, self.state.cursorCol);\n const after = currentLine.slice(self.state.cursorCol);\n self.state.lines[self.state.cursorLine] = before + text + after;\n self.setCursorCol(self.state.cursorCol + text.length);\n } else {\n // Multi-line insert\n const currentLine = self.state.lines[self.state.cursorLine] || \"\";\n const before = currentLine.slice(0, self.state.cursorCol);\n const after = currentLine.slice(self.state.cursorCol);\n\n // First line merges with text before cursor\n self.state.lines[self.state.cursorLine] = before + (lines[0] || \"\");\n\n // Insert middle lines\n for (let i = 1; i < lines.length - 1; i++) {\n self.state.lines.splice(self.state.cursorLine + i, 0, lines[i] || \"\");\n }\n\n // Last line merges with text after cursor\n const lastLineIndex = self.state.cursorLine + lines.length - 1;\n self.state.lines.splice(lastLineIndex, 0, (lines[lines.length - 1] || \"\") + after);\n\n // Update cursor position\n self.state.cursorLine = lastLineIndex;\n self.setCursorCol((lines[lines.length - 1] || \"\").length);\n }\n\n if (self.onChange) {\n self.onChange(self.getText());\n }\n}\n\nexport function do_deleteYankedText(self: Editor): void {\n const yankedText = self.killRing.peek();\n if (!yankedText) return;\n\n const yankLines = yankedText.split(\"\\n\");\n\n if (yankLines.length === 1) {\n // Single line - delete backward from cursor\n const currentLine = self.state.lines[self.state.cursorLine] || \"\";\n const deleteLen = yankedText.length;\n const before = currentLine.slice(0, self.state.cursorCol - deleteLen);\n const after = currentLine.slice(self.state.cursorCol);\n self.state.lines[self.state.cursorLine] = before + after;\n self.setCursorCol(self.state.cursorCol - deleteLen);\n } else {\n // Multi-line delete - cursor is at end of last yanked line\n const startLine = self.state.cursorLine - (yankLines.length - 1);\n const startCol = (self.state.lines[startLine] || \"\").length - (yankLines[0] || \"\").length;\n\n // Get text after cursor on current line\n const afterCursor = (self.state.lines[self.state.cursorLine] || \"\").slice(self.state.cursorCol);\n\n // Get text before yank start position\n const beforeYank = (self.state.lines[startLine] || \"\").slice(0, startCol);\n\n // Remove all lines from startLine to cursorLine and replace with merged line\n self.state.lines.splice(startLine, yankLines.length, beforeYank + afterCursor);\n\n // Update cursor\n self.state.cursorLine = startLine;\n self.setCursorCol(startCol);\n }\n\n if (self.onChange) {\n self.onChange(self.getText());\n }\n}\n\nexport function do_pushUndoSnapshot(self: Editor): void {\n self.undoStack.push(self.state);\n}\n\nexport function do_undo(self: Editor): void {\n self.exitHistoryBrowsing();\n const snapshot = self.undoStack.pop();\n if (!snapshot) return;\n Object.assign(self.state, snapshot);\n self.lastAction = null;\n self.preferredVisualCol = null;\n if (self.onChange) {\n self.onChange(self.getText());\n }\n}\n\nexport function do_jumpToChar(self: Editor, char: string, direction: \"forward\" | \"backward\"): void {\n self.lastAction = null;\n const isForward = direction === \"forward\";\n const lines = self.state.lines;\n\n const end = isForward ? lines.length : -1;\n const step = isForward ? 1 : -1;\n\n for (let lineIdx = self.state.cursorLine; lineIdx !== end; lineIdx += step) {\n const line = lines[lineIdx] || \"\";\n const isCurrentLine = lineIdx === self.state.cursorLine;\n\n // Current line: start after/before cursor; other lines: search full line\n const searchFrom = isCurrentLine ? (isForward ? self.state.cursorCol + 1 : self.state.cursorCol - 1) : undefined;\n\n const idx = isForward ? line.indexOf(char, searchFrom) : line.lastIndexOf(char, searchFrom);\n\n if (idx !== -1) {\n self.state.cursorLine = lineIdx;\n self.setCursorCol(idx);\n return;\n }\n }\n // No match found - cursor stays in place\n}\n\nexport function do_moveWordForwards(self: Editor): void {\n self.lastAction = null;\n const currentLine = self.state.lines[self.state.cursorLine] || \"\";\n\n // If at end of line, move to start of next line\n if (self.state.cursorCol >= currentLine.length) {\n if (self.state.cursorLine < self.state.lines.length - 1) {\n self.state.cursorLine++;\n self.setCursorCol(0);\n }\n return;\n }\n\n self.setCursorCol(\n findWordForward(currentLine, self.state.cursorCol, {\n segment: (text) => self.segment(text, \"word\"),\n isAtomicSegment: isPasteMarker,\n }),\n );\n}\n\nexport function do_isSlashMenuAllowed(self: Editor): boolean {\n return self.state.cursorLine === 0;\n}\n\nexport function do_isAtStartOfMessage(self: Editor): boolean {\n if (!self.isSlashMenuAllowed()) return false;\n const currentLine = self.state.lines[self.state.cursorLine] || \"\";\n const beforeCursor = currentLine.slice(0, self.state.cursorCol);\n return beforeCursor.trim() === \"\" || beforeCursor.trim() === \"/\";\n}\n\nexport function do_isInSlashCommandContext(self: Editor, textBeforeCursor: string): boolean {\n return self.isSlashMenuAllowed() && textBeforeCursor.trimStart().startsWith(\"/\");\n}\n"]}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import type { AutocompleteProvider } from "../../autocomplete.ts";
|
|
2
|
+
import { KillRing } from "../../kill-ring.ts";
|
|
3
|
+
import type { Component, Focusable, TUI } from "../../tui.ts";
|
|
4
|
+
import { UndoStack } from "../../undo-stack.ts";
|
|
5
|
+
import { type DelegatedMethods } from "../../utils/install-delegated-methods.ts";
|
|
6
|
+
import type { SelectList } from "../select-list.ts";
|
|
7
|
+
import * as autocompleteMatchingDelegates from "./editor-methods/autocomplete-matching.ts";
|
|
8
|
+
import * as autocompleteRequestDelegates from "./editor-methods/autocomplete-request.ts";
|
|
9
|
+
import * as backspaceCursorDelegates from "./editor-methods/backspace-cursor.ts";
|
|
10
|
+
import * as configurationDelegates from "./editor-methods/configuration.ts";
|
|
11
|
+
import * as cursorMovementDelegates from "./editor-methods/cursor-movement.ts";
|
|
12
|
+
import * as inputHandlingDelegates from "./editor-methods/input-handling.ts";
|
|
13
|
+
import * as pasteSubmitDelegates from "./editor-methods/paste-submit.ts";
|
|
14
|
+
import * as renderDelegates from "./editor-methods/render.ts";
|
|
15
|
+
import * as textInsertionDelegates from "./editor-methods/text-insertion.ts";
|
|
16
|
+
import * as textLayoutDelegates from "./editor-methods/text-layout.ts";
|
|
17
|
+
import * as verticalMovementDelegates from "./editor-methods/vertical-movement.ts";
|
|
18
|
+
import * as wordOperationsDelegates from "./editor-methods/word-operations.ts";
|
|
19
|
+
import * as yankUndoDelegates from "./editor-methods/yank-undo.ts";
|
|
20
|
+
import type { EditorOptions, EditorState, EditorTheme } from "./types.ts";
|
|
21
|
+
export declare class Editor implements Component, Focusable {
|
|
22
|
+
state: EditorState;
|
|
23
|
+
focused: boolean;
|
|
24
|
+
tui: TUI;
|
|
25
|
+
theme: EditorTheme;
|
|
26
|
+
paddingX: number;
|
|
27
|
+
lastWidth: number;
|
|
28
|
+
scrollOffset: number;
|
|
29
|
+
borderColor: (str: string) => string;
|
|
30
|
+
autocompleteProvider?: AutocompleteProvider;
|
|
31
|
+
autocompleteTriggerCharacters: string[];
|
|
32
|
+
autocompleteTriggerPattern: RegExp;
|
|
33
|
+
autocompleteDebouncePattern: RegExp;
|
|
34
|
+
autocompleteList?: SelectList;
|
|
35
|
+
autocompleteState: "regular" | "force" | null;
|
|
36
|
+
autocompletePrefix: string;
|
|
37
|
+
autocompleteMaxVisible: number;
|
|
38
|
+
autocompleteAbort?: AbortController;
|
|
39
|
+
autocompleteDebounceTimer?: ReturnType<typeof setTimeout>;
|
|
40
|
+
autocompleteRequestTask: Promise<void>;
|
|
41
|
+
autocompleteStartToken: number;
|
|
42
|
+
autocompleteRequestId: number;
|
|
43
|
+
pastes: Map<number, string>;
|
|
44
|
+
pasteCounter: number;
|
|
45
|
+
pasteBuffer: string;
|
|
46
|
+
isInPaste: boolean;
|
|
47
|
+
history: string[];
|
|
48
|
+
historyIndex: number;
|
|
49
|
+
historyDraft: EditorState | null;
|
|
50
|
+
killRing: KillRing;
|
|
51
|
+
lastAction: "kill" | "yank" | "type-word" | null;
|
|
52
|
+
jumpMode: "forward" | "backward" | null;
|
|
53
|
+
preferredVisualCol: number | null;
|
|
54
|
+
snappedFromCursorCol: number | null;
|
|
55
|
+
undoStack: UndoStack<EditorState>;
|
|
56
|
+
onSubmit?: (text: string) => void;
|
|
57
|
+
onChange?: (text: string) => void;
|
|
58
|
+
disableSubmit: boolean;
|
|
59
|
+
constructor(tui: TUI, theme: EditorTheme, options?: EditorOptions);
|
|
60
|
+
render(width: number): string[];
|
|
61
|
+
handleInput(data: string): void;
|
|
62
|
+
}
|
|
63
|
+
type EditorMethods = Omit<DelegatedMethods<Editor, typeof autocompleteMatchingDelegates & typeof autocompleteRequestDelegates & typeof backspaceCursorDelegates & typeof configurationDelegates & typeof cursorMovementDelegates & typeof inputHandlingDelegates & typeof pasteSubmitDelegates & typeof renderDelegates & typeof textInsertionDelegates & typeof textLayoutDelegates & typeof verticalMovementDelegates & typeof wordOperationsDelegates & typeof yankUndoDelegates>, "handleInput" | "render">;
|
|
64
|
+
export interface Editor extends EditorMethods {
|
|
65
|
+
}
|
|
66
|
+
export {};
|
|
67
|
+
//# sourceMappingURL=editor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"editor.d.ts","sourceRoot":"","sources":["../../../src/components/editor/editor.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AutocompleteProvider } from \"../../autocomplete.ts\";\nimport { KillRing } from \"../../kill-ring.ts\";\nimport type { Component, Focusable, TUI } from \"../../tui.ts\";\nimport { UndoStack } from \"../../undo-stack.ts\";\nimport { type DelegatedMethods, installDelegatedMethods } from \"../../utils/install-delegated-methods.ts\";\nimport type { SelectList } from \"../select-list.ts\";\nimport { DEFAULT_AUTOCOMPLETE_TRIGGER_CHARACTERS } from \"./constants.ts\";\nimport * as autocompleteMatchingDelegates from \"./editor-methods/autocomplete-matching.ts\";\nimport * as autocompleteRequestDelegates from \"./editor-methods/autocomplete-request.ts\";\nimport * as backspaceCursorDelegates from \"./editor-methods/backspace-cursor.ts\";\nimport * as configurationDelegates from \"./editor-methods/configuration.ts\";\nimport * as cursorMovementDelegates from \"./editor-methods/cursor-movement.ts\";\nimport * as inputHandlingDelegates from \"./editor-methods/input-handling.ts\";\nimport * as pasteSubmitDelegates from \"./editor-methods/paste-submit.ts\";\nimport * as renderDelegates from \"./editor-methods/render.ts\";\nimport * as textInsertionDelegates from \"./editor-methods/text-insertion.ts\";\nimport * as textLayoutDelegates from \"./editor-methods/text-layout.ts\";\nimport * as verticalMovementDelegates from \"./editor-methods/vertical-movement.ts\";\nimport * as wordOperationsDelegates from \"./editor-methods/word-operations.ts\";\nimport * as yankUndoDelegates from \"./editor-methods/yank-undo.ts\";\nimport { buildDebouncePattern, buildTriggerPattern } from \"./trigger-patterns.ts\";\nimport type { EditorOptions, EditorState, EditorTheme } from \"./types.ts\";\n\n// biome-ignore lint/suspicious/noUnsafeDeclarationMerging: The installer below synchronously defines every delegated method.\nexport class Editor implements Component, Focusable {\n public state: EditorState = {\n lines: [\"\"],\n cursorLine: 0,\n cursorCol: 0,\n };\n\n focused: boolean = false;\n\n public tui: TUI;\n\n public theme: EditorTheme;\n\n public paddingX: number = 0;\n\n public lastWidth: number = 80;\n\n public scrollOffset: number = 0;\n\n public borderColor: (str: string) => string;\n\n public autocompleteProvider?: AutocompleteProvider;\n\n public autocompleteTriggerCharacters = [...DEFAULT_AUTOCOMPLETE_TRIGGER_CHARACTERS];\n\n public autocompleteTriggerPattern = buildTriggerPattern(this.autocompleteTriggerCharacters);\n\n public autocompleteDebouncePattern = buildDebouncePattern(this.autocompleteTriggerCharacters);\n\n public autocompleteList?: SelectList;\n\n public autocompleteState: \"regular\" | \"force\" | null = null;\n\n public autocompletePrefix: string = \"\";\n\n public autocompleteMaxVisible: number = 5;\n\n public autocompleteAbort?: AbortController;\n\n public autocompleteDebounceTimer?: ReturnType<typeof setTimeout>;\n\n public autocompleteRequestTask: Promise<void> = Promise.resolve();\n\n public autocompleteStartToken: number = 0;\n\n public autocompleteRequestId: number = 0;\n\n public pastes: Map<number, string> = new Map();\n\n public pasteCounter: number = 0;\n\n public pasteBuffer: string = \"\";\n\n public isInPaste: boolean = false;\n\n public history: string[] = [];\n\n public historyIndex: number = -1;\n\n public historyDraft: EditorState | null = null;\n\n public killRing = new KillRing();\n\n public lastAction: \"kill\" | \"yank\" | \"type-word\" | null = null;\n\n public jumpMode: \"forward\" | \"backward\" | null = null;\n\n public preferredVisualCol: number | null = null;\n\n public snappedFromCursorCol: number | null = null;\n\n public undoStack = new UndoStack<EditorState>();\n\n public onSubmit?: (text: string) => void;\n\n public onChange?: (text: string) => void;\n\n public disableSubmit: boolean = false;\n\n constructor(tui: TUI, theme: EditorTheme, options: EditorOptions = {}) {\n this.tui = tui;\n this.theme = theme;\n this.borderColor = theme.borderColor;\n const paddingX = options.paddingX ?? 0;\n this.paddingX = Number.isFinite(paddingX) ? Math.max(0, Math.floor(paddingX)) : 0;\n const maxVisible = options.autocompleteMaxVisible ?? 5;\n this.autocompleteMaxVisible = Number.isFinite(maxVisible) ? Math.max(3, Math.min(20, Math.floor(maxVisible))) : 5;\n }\n\n render(width: number): string[] {\n return renderDelegates.do_render(this, width);\n }\n\n handleInput(data: string): void {\n inputHandlingDelegates.do_handleInput(this, data);\n }\n}\n\ntype EditorMethods = Omit<\n DelegatedMethods<\n Editor,\n typeof autocompleteMatchingDelegates &\n typeof autocompleteRequestDelegates &\n typeof backspaceCursorDelegates &\n typeof configurationDelegates &\n typeof cursorMovementDelegates &\n typeof inputHandlingDelegates &\n typeof pasteSubmitDelegates &\n typeof renderDelegates &\n typeof textInsertionDelegates &\n typeof textLayoutDelegates &\n typeof verticalMovementDelegates &\n typeof wordOperationsDelegates &\n typeof yankUndoDelegates\n >,\n \"handleInput\" | \"render\"\n>;\n\nexport interface Editor extends EditorMethods {}\n\ninstallDelegatedMethods(Editor.prototype, [\n autocompleteMatchingDelegates,\n autocompleteRequestDelegates,\n backspaceCursorDelegates,\n configurationDelegates,\n cursorMovementDelegates,\n inputHandlingDelegates,\n pasteSubmitDelegates,\n renderDelegates,\n textInsertionDelegates,\n textLayoutDelegates,\n verticalMovementDelegates,\n wordOperationsDelegates,\n yankUndoDelegates,\n]);\n"]}
|