Keys while in char-wise visual mode: motions extend the selection; d/x * delete it, c/s change it, y yanks it, Esc cancels.
(cell: HTMLElement, key: string, text: string)
| 1101 | /** Keys while in char-wise visual mode: motions extend the selection; d/x |
| 1102 | * delete it, c/s change it, y yanks it, Esc cancels. */ |
| 1103 | private handleVisualKey(cell: HTMLElement, key: string, text: string): void { |
| 1104 | const selFrom = (): number => Math.max(0, Math.min(this.visualAnchor, this.cursorOffset)) |
| 1105 | const selTo = (): number => |
| 1106 | Math.min(text.length, Math.max(this.visualAnchor, this.cursorOffset) + 1) |
| 1107 | if (this.visualScope) { |
| 1108 | // `vi{obj}` / `va{obj}`: select the text object. |
| 1109 | const scope = this.visualScope |
| 1110 | this.visualScope = null |
| 1111 | const r = textObjectRange(text, this.cursorOffset, scope, key) |
| 1112 | if (r) { |
| 1113 | this.visualAnchor = r.from |
| 1114 | this.cursorOffset = Math.max(r.from, r.to - 1) |
| 1115 | this.renderCellSelection(cell) |
| 1116 | } |
| 1117 | return |
| 1118 | } |
| 1119 | if (key === 'i' || key === 'a') { |
| 1120 | this.visualScope = key |
| 1121 | return |
| 1122 | } |
| 1123 | switch (key) { |
| 1124 | case 'h': |
| 1125 | this.cursorOffset = Math.max(0, this.cursorOffset - 1) |
| 1126 | this.renderCellSelection(cell) |
| 1127 | return |
| 1128 | case 'l': |
| 1129 | this.cursorOffset = Math.min(Math.max(0, text.length - 1), this.cursorOffset + 1) |
| 1130 | this.renderCellSelection(cell) |
| 1131 | return |
| 1132 | case 'w': |
| 1133 | this.cursorOffset = nextWordStart(text, this.cursorOffset) |
| 1134 | this.renderCellSelection(cell) |
| 1135 | return |
| 1136 | case 'e': |
| 1137 | this.cursorOffset = nextWordEnd(text, this.cursorOffset) |
| 1138 | this.renderCellSelection(cell) |
| 1139 | return |
| 1140 | case 'b': |
| 1141 | this.cursorOffset = prevWordStart(text, this.cursorOffset) |
| 1142 | this.renderCellSelection(cell) |
| 1143 | return |
| 1144 | case '0': |
| 1145 | this.cursorOffset = 0 |
| 1146 | this.renderCellSelection(cell) |
| 1147 | return |
| 1148 | case '$': |
| 1149 | this.cursorOffset = Math.max(0, text.length - 1) |
| 1150 | this.renderCellSelection(cell) |
| 1151 | return |
| 1152 | case 'd': |
| 1153 | case 'x': { |
| 1154 | const from = selFrom() |
| 1155 | const to = selTo() |
| 1156 | this.exitVisual() |
| 1157 | this.deleteRange(cell, from, to) |
| 1158 | return |
| 1159 | } |
| 1160 | case 'c': |
no test coverage detected