* 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
()
| 935 | * Only triggers when cursor is at end of token (followed by whitespace or EOL). |
| 936 | */ |
| 937 | deleteTokenBefore(): Cursor | null { |
| 938 | // Cursor at chip.start is the "selected" state — backspace deletes the |
| 939 | // chip forward, not the char before it. |
| 940 | const chipAfter = this.imageRefStartingAt(this.offset) |
| 941 | if (chipAfter) { |
| 942 | const end = |
| 943 | this.text[chipAfter.end] === ' ' ? chipAfter.end + 1 : chipAfter.end |
| 944 | return this.modifyText(new Cursor(this.measuredText, end)) |
| 945 | } |
| 946 | |
| 947 | if (this.isAtStart()) { |
| 948 | return null |
| 949 | } |
| 950 | |
| 951 | // Only trigger if cursor is at a word boundary (whitespace or end of string after cursor) |
| 952 | const charAfter = this.text[this.offset] |
| 953 | if (charAfter !== undefined && !/\s/.test(charAfter)) { |
| 954 | return null |
| 955 | } |
| 956 | |
| 957 | const textBefore = this.text.slice(0, this.offset) |
| 958 | |
| 959 | // Check for pasted/truncated text refs: [Pasted text #1] or [...Truncated text #1 +50 lines...] |
| 960 | const pasteMatch = textBefore.match( |
| 961 | /(^|\s)\[(Pasted text #\d+(?: \+\d+ lines)?|Image #\d+|\.\.\.Truncated text #\d+ \+\d+ lines\.\.\.)\]$/, |
| 962 | ) |
| 963 | if (pasteMatch) { |
| 964 | const matchStart = pasteMatch.index! + pasteMatch[1]!.length |
| 965 | return new Cursor(this.measuredText, matchStart).modifyText(this) |
| 966 | } |
| 967 | |
| 968 | return null |
| 969 | } |
| 970 | |
| 971 | deleteWordAfter(): Cursor { |
| 972 | if (this.isAtEnd()) { |
no test coverage detected