* Deletes a token before the cursor if one exists. * Supports pasted text refs: [Pasted text #1], [Pasted text #1 +10 lines], * [...Truncated text #1 +10 lines...] * * Note: @mentions are NOT tokenized since users may want to correct typos * in file paths. Use Ctrl/Cmd+backspace for w
()
| 910 | * Only triggers when cursor is at end of token (followed by whitespace or EOL). |
| 911 | */ |
| 912 | deleteTokenBefore(): Cursor | null { |
| 913 | // Cursor at chip.start is the "selected" state — backspace deletes the |
| 914 | // chip forward, not the char before it. |
| 915 | const chipAfter = this.imageRefStartingAt(this.offset) |
| 916 | if (chipAfter) { |
| 917 | const end = |
| 918 | this.text[chipAfter.end] === ' ' ? chipAfter.end + 1 : chipAfter.end |
| 919 | return this.modifyText(new Cursor(this.measuredText, end)) |
| 920 | } |
| 921 | |
| 922 | if (this.isAtStart()) { |
| 923 | return null |
| 924 | } |
| 925 | |
| 926 | // Only trigger if cursor is at a word boundary (whitespace or end of string after cursor) |
| 927 | const charAfter = this.text[this.offset] |
| 928 | if (charAfter !== undefined && !/\s/.test(charAfter)) { |
| 929 | return null |
| 930 | } |
| 931 | |
| 932 | const textBefore = this.text.slice(0, this.offset) |
| 933 | |
| 934 | // Check for pasted/truncated text refs: [Pasted text #1] or [...Truncated text #1 +50 lines...] |
| 935 | const pasteMatch = textBefore.match( |
| 936 | /(^|\s)\[(Pasted text #\d+(?: \+\d+ lines)?|Image #\d+|\.\.\.Truncated text #\d+ \+\d+ lines\.\.\.)\]$/, |
| 937 | ) |
| 938 | if (pasteMatch) { |
| 939 | const matchStart = pasteMatch.index! + pasteMatch[1]!.length |
| 940 | return new Cursor(this.measuredText, matchStart).modifyText(this) |
| 941 | } |
| 942 | |
| 943 | return null |
| 944 | } |
| 945 | |
| 946 | deleteWordAfter(): Cursor { |
| 947 | if (this.isAtEnd()) { |
no test coverage detected