github.com/aretext/aretext@v1.3.0/input/interpreter_test.go (about) 1 package input 2 3 import ( 4 "io" 5 "log" 6 "os" 7 "testing" 8 "unicode/utf8" 9 10 "github.com/gdamore/tcell/v2" 11 "github.com/stretchr/testify/assert" 12 "github.com/stretchr/testify/require" 13 14 "github.com/aretext/aretext/input/engine" 15 "github.com/aretext/aretext/state" 16 ) 17 18 func init() { 19 // Suppress noisy log output from these tests. 20 log.SetOutput(io.Discard) 21 } 22 23 func TestInterpreterStateIntegration(t *testing.T) { 24 testCases := []struct { 25 name string 26 initialText string 27 events []tcell.Event 28 expectedCursorPos uint64 29 expectedText string 30 }{ 31 { 32 name: "cursor home row keys", 33 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 34 events: []tcell.Event{ 35 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 36 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 37 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 38 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 39 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 40 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 41 tcell.NewEventKey(tcell.KeyRune, 'j', tcell.ModNone), 42 tcell.NewEventKey(tcell.KeyRune, 'j', tcell.ModNone), 43 tcell.NewEventKey(tcell.KeyRune, 'h', tcell.ModNone), 44 tcell.NewEventKey(tcell.KeyRune, 'h', tcell.ModNone), 45 tcell.NewEventKey(tcell.KeyRune, 'k', tcell.ModNone), 46 }, 47 expectedCursorPos: 22, 48 expectedText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 49 }, 50 { 51 name: "cursor arrow keys", 52 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 53 events: []tcell.Event{ 54 tcell.NewEventKey(tcell.KeyRight, '\x00', tcell.ModNone), 55 tcell.NewEventKey(tcell.KeyRight, '\x00', tcell.ModNone), 56 tcell.NewEventKey(tcell.KeyRight, '\x00', tcell.ModNone), 57 tcell.NewEventKey(tcell.KeyRight, '\x00', tcell.ModNone), 58 tcell.NewEventKey(tcell.KeyRight, '\x00', tcell.ModNone), 59 tcell.NewEventKey(tcell.KeyRight, '\x00', tcell.ModNone), 60 tcell.NewEventKey(tcell.KeyDown, '\x00', tcell.ModNone), 61 tcell.NewEventKey(tcell.KeyDown, '\x00', tcell.ModNone), 62 tcell.NewEventKey(tcell.KeyLeft, '\x00', tcell.ModNone), 63 tcell.NewEventKey(tcell.KeyLeft, '\x00', tcell.ModNone), 64 tcell.NewEventKey(tcell.KeyUp, '\x00', tcell.ModNone), 65 }, 66 expectedCursorPos: 22, 67 expectedText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 68 }, 69 { 70 name: "cursor back", 71 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 72 events: []tcell.Event{ 73 tcell.NewEventKey(tcell.KeyRune, 'e', tcell.ModNone), 74 tcell.NewEventKey(tcell.KeyRune, 'e', tcell.ModNone), 75 tcell.NewEventKey(tcell.KeyBackspace2, '\u007f', tcell.ModNone), 76 tcell.NewEventKey(tcell.KeyBackspace2, '\u007f', tcell.ModNone), 77 }, 78 expectedCursorPos: 8, 79 expectedText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 80 }, 81 { 82 name: "cursor forward", 83 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 84 events: []tcell.Event{ 85 tcell.NewEventKey(tcell.KeyRune, ' ', tcell.ModNone), 86 }, 87 expectedCursorPos: 1, 88 expectedText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 89 }, 90 { 91 name: "cursor left with count", 92 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 93 events: []tcell.Event{ 94 tcell.NewEventKey(tcell.KeyRune, '$', tcell.ModNone), 95 tcell.NewEventKey(tcell.KeyRune, '5', tcell.ModNone), 96 tcell.NewEventKey(tcell.KeyRune, 'h', tcell.ModNone), 97 }, 98 expectedCursorPos: 11, 99 expectedText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 100 }, 101 { 102 name: "cursor right with count", 103 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 104 events: []tcell.Event{ 105 tcell.NewEventKey(tcell.KeyRune, '5', tcell.ModNone), 106 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 107 }, 108 expectedCursorPos: 5, 109 expectedText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 110 }, 111 { 112 name: "cursor down with count", 113 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 114 events: []tcell.Event{ 115 tcell.NewEventKey(tcell.KeyRune, '2', tcell.ModNone), 116 tcell.NewEventKey(tcell.KeyRune, 'j', tcell.ModNone), 117 }, 118 expectedCursorPos: 39, 119 expectedText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 120 }, 121 { 122 name: "cursor up with count", 123 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 124 events: []tcell.Event{ 125 tcell.NewEventKey(tcell.KeyRune, 'G', tcell.ModNone), 126 tcell.NewEventKey(tcell.KeyRune, '2', tcell.ModNone), 127 tcell.NewEventKey(tcell.KeyRune, 'k', tcell.ModNone), 128 }, 129 expectedCursorPos: 0, 130 expectedText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 131 }, 132 { 133 name: "cursor start of next line", 134 initialText: "Lorem ipsum dolor\n sit amet consectetur\nadipiscing elit", 135 events: []tcell.Event{ 136 tcell.NewEventKey(tcell.KeyEnter, '\x00', tcell.ModNone), 137 }, 138 expectedCursorPos: 20, 139 expectedText: "Lorem ipsum dolor\n sit amet consectetur\nadipiscing elit", 140 }, 141 { 142 name: "cursor to next matching in line", 143 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 144 events: []tcell.Event{ 145 tcell.NewEventKey(tcell.KeyRune, 'f', tcell.ModNone), 146 tcell.NewEventKey(tcell.KeyRune, 'p', tcell.ModNone), 147 }, 148 expectedCursorPos: 7, 149 expectedText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 150 }, 151 { 152 name: "cursor to prev matching in line", 153 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 154 events: []tcell.Event{ 155 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 156 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 157 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 158 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 159 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 160 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 161 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 162 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 163 tcell.NewEventKey(tcell.KeyRune, 'j', tcell.ModNone), 164 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 165 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 166 tcell.NewEventKey(tcell.KeyRune, 'F', tcell.ModNone), 167 tcell.NewEventKey(tcell.KeyRune, 'a', tcell.ModNone), 168 }, 169 expectedCursorPos: 22, 170 expectedText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 171 }, 172 { 173 name: "cursor till next matching in line", 174 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 175 events: []tcell.Event{ 176 tcell.NewEventKey(tcell.KeyRune, 't', tcell.ModNone), 177 tcell.NewEventKey(tcell.KeyRune, 'd', tcell.ModNone), 178 }, 179 expectedCursorPos: 11, 180 expectedText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 181 }, 182 { 183 name: "cursor till prev matching in line", 184 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 185 events: []tcell.Event{ 186 tcell.NewEventKey(tcell.KeyRune, 'j', tcell.ModNone), 187 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 188 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 189 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 190 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 191 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 192 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 193 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 194 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 195 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 196 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 197 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 198 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 199 tcell.NewEventKey(tcell.KeyRune, 'T', tcell.ModNone), 200 tcell.NewEventKey(tcell.KeyRune, 't', tcell.ModNone), 201 }, 202 expectedCursorPos: 26, 203 expectedText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 204 }, 205 { 206 name: "cursor next word start", 207 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 208 events: []tcell.Event{ 209 tcell.NewEventKey(tcell.KeyRune, 'w', tcell.ModNone), 210 tcell.NewEventKey(tcell.KeyRune, 'w', tcell.ModNone), 211 tcell.NewEventKey(tcell.KeyRune, 'w', tcell.ModNone), 212 tcell.NewEventKey(tcell.KeyRune, 'w', tcell.ModNone), 213 }, 214 expectedCursorPos: 22, 215 expectedText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 216 }, 217 { 218 name: "cursor next word start with count", 219 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 220 events: []tcell.Event{ 221 tcell.NewEventKey(tcell.KeyRune, '5', tcell.ModNone), 222 tcell.NewEventKey(tcell.KeyRune, 'w', tcell.ModNone), 223 }, 224 expectedCursorPos: 27, 225 expectedText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 226 }, 227 { 228 name: "cursor next word start including punctuation", 229 initialText: "Lorem ipsum,dolor;sit amet consectetur", 230 events: []tcell.Event{ 231 tcell.NewEventKey(tcell.KeyRune, 'W', tcell.ModNone), 232 tcell.NewEventKey(tcell.KeyRune, 'W', tcell.ModNone), 233 }, 234 expectedCursorPos: 22, 235 expectedText: "Lorem ipsum,dolor;sit amet consectetur", 236 }, 237 { 238 name: "cursor prev word start", 239 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 240 events: []tcell.Event{ 241 tcell.NewEventKey(tcell.KeyRune, 'j', tcell.ModNone), 242 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 243 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 244 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 245 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 246 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 247 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 248 tcell.NewEventKey(tcell.KeyRune, 'b', tcell.ModNone), 249 tcell.NewEventKey(tcell.KeyRune, 'b', tcell.ModNone), 250 tcell.NewEventKey(tcell.KeyRune, 'b', tcell.ModNone), 251 }, 252 expectedCursorPos: 12, 253 expectedText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 254 }, 255 { 256 name: "cursor prev word start including punctuation", 257 initialText: "Lorem ipsum,dolor;sit amet consectetur", 258 events: []tcell.Event{ 259 tcell.NewEventKey(tcell.KeyRune, '$', tcell.ModNone), 260 tcell.NewEventKey(tcell.KeyRune, 'B', tcell.ModNone), 261 tcell.NewEventKey(tcell.KeyRune, 'B', tcell.ModNone), 262 tcell.NewEventKey(tcell.KeyRune, 'B', tcell.ModNone), 263 }, 264 expectedCursorPos: 6, 265 expectedText: "Lorem ipsum,dolor;sit amet consectetur", 266 }, 267 { 268 name: "cursor prev word start with count", 269 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 270 events: []tcell.Event{ 271 tcell.NewEventKey(tcell.KeyRune, 'j', tcell.ModNone), 272 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 273 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 274 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 275 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 276 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 277 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 278 tcell.NewEventKey(tcell.KeyRune, '3', tcell.ModNone), 279 tcell.NewEventKey(tcell.KeyRune, 'b', tcell.ModNone), 280 }, 281 expectedCursorPos: 12, 282 expectedText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 283 }, 284 { 285 name: "cursor next word end", 286 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 287 events: []tcell.Event{ 288 tcell.NewEventKey(tcell.KeyRune, 'e', tcell.ModNone), 289 tcell.NewEventKey(tcell.KeyRune, 'e', tcell.ModNone), 290 }, 291 expectedCursorPos: 10, 292 expectedText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 293 }, 294 { 295 name: "cursor next word end including punctuation", 296 initialText: "Lorem ipsum,dolor;sit amet consectetur", 297 events: []tcell.Event{ 298 tcell.NewEventKey(tcell.KeyRune, 'E', tcell.ModNone), 299 tcell.NewEventKey(tcell.KeyRune, 'E', tcell.ModNone), 300 }, 301 expectedCursorPos: 20, 302 expectedText: "Lorem ipsum,dolor;sit amet consectetur", 303 }, 304 { 305 name: "cursor next word end with count", 306 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 307 events: []tcell.Event{ 308 tcell.NewEventKey(tcell.KeyRune, '5', tcell.ModNone), 309 tcell.NewEventKey(tcell.KeyRune, 'e', tcell.ModNone), 310 }, 311 expectedCursorPos: 25, 312 expectedText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 313 }, 314 { 315 name: "cursor prev paragraph", 316 initialText: "Lorem ipsum dolor\n\nsit amet consectetur\nadipiscing\n\nelit\n\n", 317 events: []tcell.Event{ 318 tcell.NewEventKey(tcell.KeyRune, 'j', tcell.ModNone), 319 tcell.NewEventKey(tcell.KeyRune, 'j', tcell.ModNone), 320 tcell.NewEventKey(tcell.KeyRune, 'j', tcell.ModNone), 321 tcell.NewEventKey(tcell.KeyRune, 'j', tcell.ModNone), 322 tcell.NewEventKey(tcell.KeyRune, 'j', tcell.ModNone), 323 tcell.NewEventKey(tcell.KeyRune, '{', tcell.ModNone), 324 }, 325 expectedCursorPos: 18, 326 expectedText: "Lorem ipsum dolor\n\nsit amet consectetur\nadipiscing\n\nelit\n\n", 327 }, 328 { 329 name: "cursor next paragraph", 330 initialText: "Lorem ipsum dolor\n\nsit amet consectetur\nadipiscing\n\nelit\n\n", 331 events: []tcell.Event{ 332 tcell.NewEventKey(tcell.KeyRune, '}', tcell.ModNone), 333 tcell.NewEventKey(tcell.KeyRune, '}', tcell.ModNone), 334 }, 335 expectedCursorPos: 51, 336 expectedText: "Lorem ipsum dolor\n\nsit amet consectetur\nadipiscing\n\nelit\n\n", 337 }, 338 { 339 name: "cursor line start", 340 initialText: "Lorem ipsum dolor\n\tsit amet consectetur\n\t\tadipiscing\nelit\n\n", 341 events: []tcell.Event{ 342 tcell.NewEventKey(tcell.KeyRune, 'j', tcell.ModNone), 343 tcell.NewEventKey(tcell.KeyRune, 'w', tcell.ModNone), 344 tcell.NewEventKey(tcell.KeyRune, 'w', tcell.ModNone), 345 tcell.NewEventKey(tcell.KeyRune, 'w', tcell.ModNone), 346 tcell.NewEventKey(tcell.KeyRune, '0', tcell.ModNone), 347 }, 348 expectedCursorPos: 18, 349 expectedText: "Lorem ipsum dolor\n\tsit amet consectetur\n\t\tadipiscing\nelit\n\n", 350 }, 351 { 352 name: "cursor line start after indentation", 353 initialText: "Lorem ipsum dolor\n\tsit amet consectetur\n\t\tadipiscing\nelit\n\n", 354 events: []tcell.Event{ 355 tcell.NewEventKey(tcell.KeyRune, 'j', tcell.ModNone), 356 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 357 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 358 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 359 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 360 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 361 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 362 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 363 tcell.NewEventKey(tcell.KeyRune, '^', tcell.ModNone), 364 }, 365 expectedCursorPos: 19, 366 expectedText: "Lorem ipsum dolor\n\tsit amet consectetur\n\t\tadipiscing\nelit\n\n", 367 }, 368 { 369 name: "cursor line end", 370 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 371 events: []tcell.Event{ 372 tcell.NewEventKey(tcell.KeyRune, '$', tcell.ModNone), 373 }, 374 expectedCursorPos: 16, 375 expectedText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 376 }, 377 { 378 name: "cursor start of first line", 379 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 380 events: []tcell.Event{ 381 tcell.NewEventKey(tcell.KeyRune, 'j', tcell.ModNone), 382 tcell.NewEventKey(tcell.KeyRune, 'j', tcell.ModNone), 383 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 384 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 385 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 386 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 387 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 388 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 389 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 390 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 391 tcell.NewEventKey(tcell.KeyRune, 'g', tcell.ModNone), 392 tcell.NewEventKey(tcell.KeyRune, 'g', tcell.ModNone), 393 }, 394 expectedCursorPos: 0, 395 expectedText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 396 }, 397 { 398 name: "cursor start of line number", 399 initialText: "Lorem ipsum dolor\n\nsit amet consectetur\nadipiscing\n\nelit\n\n", 400 events: []tcell.Event{ 401 tcell.NewEventKey(tcell.KeyRune, '4', tcell.ModNone), 402 tcell.NewEventKey(tcell.KeyRune, 'g', tcell.ModNone), 403 tcell.NewEventKey(tcell.KeyRune, 'g', tcell.ModNone), 404 }, 405 expectedCursorPos: 40, 406 expectedText: "Lorem ipsum dolor\n\nsit amet consectetur\nadipiscing\n\nelit\n\n", 407 }, 408 { 409 name: "cursor start of last line", 410 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 411 events: []tcell.Event{ 412 tcell.NewEventKey(tcell.KeyRune, 'G', tcell.ModNone), 413 }, 414 expectedCursorPos: 39, 415 expectedText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 416 }, 417 { 418 name: "cursor matching code block delimiter", 419 initialText: `func foo() { fmt.Printf("foo {} bar!") }`, 420 events: []tcell.Event{ 421 tcell.NewEventKey(tcell.KeyRune, '3', tcell.ModNone), 422 tcell.NewEventKey(tcell.KeyRune, 'w', tcell.ModNone), 423 tcell.NewEventKey(tcell.KeyRune, '%', tcell.ModNone), 424 }, 425 expectedCursorPos: 39, 426 expectedText: `func foo() { fmt.Printf("foo {} bar!") }`, 427 }, 428 { 429 name: "cursor prev unmatched open brace", 430 initialText: `{ { a { b } c } }`, 431 events: []tcell.Event{ 432 tcell.NewEventKey(tcell.KeyRune, '6', tcell.ModNone), 433 tcell.NewEventKey(tcell.KeyRune, 'w', tcell.ModNone), 434 tcell.NewEventKey(tcell.KeyRune, '[', tcell.ModNone), 435 tcell.NewEventKey(tcell.KeyRune, '{', tcell.ModNone), 436 }, 437 expectedCursorPos: 2, 438 expectedText: `{ { a { b } c } }`, 439 }, 440 { 441 name: "cursor next unmatched close brace", 442 initialText: `{ { a { b } c } }`, 443 events: []tcell.Event{ 444 tcell.NewEventKey(tcell.KeyRune, '2', tcell.ModNone), 445 tcell.NewEventKey(tcell.KeyRune, 'w', tcell.ModNone), 446 tcell.NewEventKey(tcell.KeyRune, ']', tcell.ModNone), 447 tcell.NewEventKey(tcell.KeyRune, '}', tcell.ModNone), 448 }, 449 expectedCursorPos: 14, 450 expectedText: `{ { a { b } c } }`, 451 }, 452 { 453 name: "cursor prev unmatched open paren", 454 initialText: `( ( a ( b ) c ) )`, 455 events: []tcell.Event{ 456 tcell.NewEventKey(tcell.KeyRune, '6', tcell.ModNone), 457 tcell.NewEventKey(tcell.KeyRune, 'w', tcell.ModNone), 458 tcell.NewEventKey(tcell.KeyRune, '[', tcell.ModNone), 459 tcell.NewEventKey(tcell.KeyRune, '(', tcell.ModNone), 460 }, 461 expectedCursorPos: 2, 462 expectedText: `( ( a ( b ) c ) )`, 463 }, 464 { 465 name: "cursor next unmatched close paren", 466 initialText: `( ( a ( b ) c ) )`, 467 events: []tcell.Event{ 468 tcell.NewEventKey(tcell.KeyRune, '2', tcell.ModNone), 469 tcell.NewEventKey(tcell.KeyRune, 'w', tcell.ModNone), 470 tcell.NewEventKey(tcell.KeyRune, ']', tcell.ModNone), 471 tcell.NewEventKey(tcell.KeyRune, ')', tcell.ModNone), 472 }, 473 expectedCursorPos: 14, 474 expectedText: `( ( a ( b ) c ) )`, 475 }, 476 { 477 name: "insert", 478 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 479 events: []tcell.Event{ 480 tcell.NewEventKey(tcell.KeyRune, 'w', tcell.ModNone), 481 tcell.NewEventKey(tcell.KeyRune, 'i', tcell.ModNone), 482 tcell.NewEventKey(tcell.KeyRune, 't', tcell.ModNone), 483 tcell.NewEventKey(tcell.KeyRune, 'e', tcell.ModNone), 484 tcell.NewEventKey(tcell.KeyRune, 's', tcell.ModNone), 485 tcell.NewEventKey(tcell.KeyRune, 't', tcell.ModNone), 486 tcell.NewEventKey(tcell.KeyRune, ' ', tcell.ModNone), 487 tcell.NewEventKey(tcell.KeyEsc, '\x00', tcell.ModNone), 488 }, 489 expectedCursorPos: 10, 490 expectedText: "Lorem test ipsum dolor\nsit amet consectetur\nadipiscing elit", 491 }, 492 { 493 name: "insert then delete with backspace", 494 initialText: "", 495 events: []tcell.Event{ 496 tcell.NewEventKey(tcell.KeyRune, 'i', tcell.ModNone), 497 tcell.NewEventKey(tcell.KeyRune, 'f', tcell.ModNone), 498 tcell.NewEventKey(tcell.KeyRune, 'o', tcell.ModNone), 499 tcell.NewEventKey(tcell.KeyRune, 'o', tcell.ModNone), 500 tcell.NewEventKey(tcell.KeyRune, 'b', tcell.ModNone), 501 tcell.NewEventKey(tcell.KeyRune, 'a', tcell.ModNone), 502 tcell.NewEventKey(tcell.KeyRune, 'r', tcell.ModNone), 503 tcell.NewEventKey(tcell.KeyBackspace2, '\u007f', tcell.ModNone), 504 tcell.NewEventKey(tcell.KeyBackspace2, '\u007f', tcell.ModNone), 505 tcell.NewEventKey(tcell.KeyBackspace2, '\u007f', tcell.ModNone), 506 tcell.NewEventKey(tcell.KeyEsc, '\x00', tcell.ModNone), 507 }, 508 expectedCursorPos: 2, 509 expectedText: "foo", 510 }, 511 { 512 name: "insert max rune", 513 initialText: "", 514 events: []tcell.Event{ 515 tcell.NewEventKey(tcell.KeyRune, 'i', tcell.ModNone), 516 tcell.NewEventKey(tcell.KeyRune, utf8.MaxRune, tcell.ModNone), 517 }, 518 expectedCursorPos: 1, 519 expectedText: "\U0010FFFF", 520 }, 521 { 522 name: "delete with delete key", 523 initialText: "foobar baz", 524 events: []tcell.Event{ 525 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 526 tcell.NewEventKey(tcell.KeyRune, 'i', tcell.ModNone), 527 tcell.NewEventKey(tcell.KeyDelete, '\x00', tcell.ModNone), 528 tcell.NewEventKey(tcell.KeyDelete, '\x00', tcell.ModNone), 529 tcell.NewEventKey(tcell.KeyDelete, '\x00', tcell.ModNone), 530 tcell.NewEventKey(tcell.KeyEsc, '\x00', tcell.ModNone), 531 }, 532 expectedCursorPos: 0, 533 expectedText: "far baz", 534 }, 535 { 536 name: "insert at start of line", 537 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 538 events: []tcell.Event{ 539 tcell.NewEventKey(tcell.KeyRune, 'j', tcell.ModNone), 540 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 541 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 542 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 543 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 544 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 545 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 546 tcell.NewEventKey(tcell.KeyRune, 'I', tcell.ModNone), 547 tcell.NewEventKey(tcell.KeyRune, 't', tcell.ModNone), 548 tcell.NewEventKey(tcell.KeyRune, 'e', tcell.ModNone), 549 tcell.NewEventKey(tcell.KeyRune, 's', tcell.ModNone), 550 tcell.NewEventKey(tcell.KeyRune, 't', tcell.ModNone), 551 tcell.NewEventKey(tcell.KeyRune, ' ', tcell.ModNone), 552 tcell.NewEventKey(tcell.KeyEsc, '\x00', tcell.ModNone), 553 }, 554 expectedCursorPos: 22, 555 expectedText: "Lorem ipsum dolor\ntest sit amet consectetur\nadipiscing elit", 556 }, 557 { 558 name: "insert move cursor right at end of line", 559 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 560 events: []tcell.Event{ 561 tcell.NewEventKey(tcell.KeyRune, '$', tcell.ModNone), 562 tcell.NewEventKey(tcell.KeyRune, 'i', tcell.ModNone), 563 tcell.NewEventKey(tcell.KeyRight, '\x00', tcell.ModNone), 564 tcell.NewEventKey(tcell.KeyBackspace, '\x00', tcell.ModNone), 565 }, 566 expectedCursorPos: 16, 567 expectedText: "Lorem ipsum dolo\nsit amet consectetur\nadipiscing elit", 568 }, 569 { 570 name: "append", 571 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 572 events: []tcell.Event{ 573 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 574 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 575 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 576 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 577 tcell.NewEventKey(tcell.KeyRune, 'a', tcell.ModNone), 578 tcell.NewEventKey(tcell.KeyRune, ' ', tcell.ModNone), 579 tcell.NewEventKey(tcell.KeyRune, 't', tcell.ModNone), 580 tcell.NewEventKey(tcell.KeyRune, 'e', tcell.ModNone), 581 tcell.NewEventKey(tcell.KeyRune, 's', tcell.ModNone), 582 tcell.NewEventKey(tcell.KeyRune, 't', tcell.ModNone), 583 tcell.NewEventKey(tcell.KeyEsc, '\x00', tcell.ModNone), 584 }, 585 expectedCursorPos: 9, 586 expectedText: "Lorem test ipsum dolor\nsit amet consectetur\nadipiscing elit", 587 }, 588 { 589 name: "append at end of line", 590 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 591 events: []tcell.Event{ 592 tcell.NewEventKey(tcell.KeyRune, 'j', tcell.ModNone), 593 tcell.NewEventKey(tcell.KeyRune, 'A', tcell.ModNone), 594 tcell.NewEventKey(tcell.KeyRune, ' ', tcell.ModNone), 595 tcell.NewEventKey(tcell.KeyRune, 't', tcell.ModNone), 596 tcell.NewEventKey(tcell.KeyRune, 'e', tcell.ModNone), 597 tcell.NewEventKey(tcell.KeyRune, 's', tcell.ModNone), 598 tcell.NewEventKey(tcell.KeyRune, 't', tcell.ModNone), 599 tcell.NewEventKey(tcell.KeyEsc, '\x00', tcell.ModNone), 600 }, 601 expectedCursorPos: 42, 602 expectedText: "Lorem ipsum dolor\nsit amet consectetur test\nadipiscing elit", 603 }, 604 { 605 name: "new line below", 606 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 607 events: []tcell.Event{ 608 tcell.NewEventKey(tcell.KeyRune, 'o', tcell.ModNone), 609 tcell.NewEventKey(tcell.KeyRune, 't', tcell.ModNone), 610 tcell.NewEventKey(tcell.KeyRune, 'e', tcell.ModNone), 611 tcell.NewEventKey(tcell.KeyRune, 's', tcell.ModNone), 612 tcell.NewEventKey(tcell.KeyRune, 't', tcell.ModNone), 613 tcell.NewEventKey(tcell.KeyEsc, '\x00', tcell.ModNone), 614 }, 615 expectedCursorPos: 21, 616 expectedText: "Lorem ipsum dolor\ntest\nsit amet consectetur\nadipiscing elit", 617 }, 618 { 619 name: "new line above", 620 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 621 events: []tcell.Event{ 622 tcell.NewEventKey(tcell.KeyRune, 'j', tcell.ModNone), 623 tcell.NewEventKey(tcell.KeyRune, 'O', tcell.ModNone), 624 tcell.NewEventKey(tcell.KeyRune, 't', tcell.ModNone), 625 tcell.NewEventKey(tcell.KeyRune, 'e', tcell.ModNone), 626 tcell.NewEventKey(tcell.KeyRune, 's', tcell.ModNone), 627 tcell.NewEventKey(tcell.KeyRune, 't', tcell.ModNone), 628 tcell.NewEventKey(tcell.KeyEsc, '\x00', tcell.ModNone), 629 }, 630 expectedCursorPos: 21, 631 expectedText: "Lorem ipsum dolor\ntest\nsit amet consectetur\nadipiscing elit", 632 }, 633 { 634 name: "join lines", 635 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 636 events: []tcell.Event{ 637 tcell.NewEventKey(tcell.KeyRune, 'J', tcell.ModNone), 638 }, 639 expectedCursorPos: 17, 640 expectedText: "Lorem ipsum dolor sit amet consectetur\nadipiscing elit", 641 }, 642 { 643 name: "delete next character in line", 644 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 645 events: []tcell.Event{ 646 tcell.NewEventKey(tcell.KeyRune, 'x', tcell.ModNone), 647 tcell.NewEventKey(tcell.KeyRune, 'x', tcell.ModNone), 648 tcell.NewEventKey(tcell.KeyRune, 'x', tcell.ModNone), 649 tcell.NewEventKey(tcell.KeyRune, 'x', tcell.ModNone), 650 tcell.NewEventKey(tcell.KeyRune, 'x', tcell.ModNone), 651 tcell.NewEventKey(tcell.KeyRune, 'x', tcell.ModNone), 652 }, 653 expectedCursorPos: 0, 654 expectedText: "ipsum dolor\nsit amet consectetur\nadipiscing elit", 655 }, 656 { 657 name: "delete next character in line with count", 658 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 659 events: []tcell.Event{ 660 tcell.NewEventKey(tcell.KeyRune, '5', tcell.ModNone), 661 tcell.NewEventKey(tcell.KeyRune, 'x', tcell.ModNone), 662 }, 663 expectedCursorPos: 0, 664 expectedText: " ipsum dolor\nsit amet consectetur\nadipiscing elit", 665 }, 666 { 667 name: "delete next character in line using delete key", 668 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 669 events: []tcell.Event{ 670 tcell.NewEventKey(tcell.KeyDelete, '\x00', tcell.ModNone), 671 }, 672 expectedCursorPos: 0, 673 expectedText: "orem ipsum dolor\nsit amet consectetur\nadipiscing elit", 674 }, 675 { 676 name: "delete next character in line using delete key then paste from default clipboard", 677 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 678 events: []tcell.Event{ 679 tcell.NewEventKey(tcell.KeyDelete, '\x00', tcell.ModNone), 680 tcell.NewEventKey(tcell.KeyDelete, '\x00', tcell.ModNone), 681 tcell.NewEventKey(tcell.KeyRune, '$', tcell.ModNone), 682 tcell.NewEventKey(tcell.KeyRune, 'p', tcell.ModNone), 683 }, 684 expectedCursorPos: 15, 685 expectedText: "rem ipsum doloro\nsit amet consectetur\nadipiscing elit", 686 }, 687 { 688 name: "delete line", 689 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 690 events: []tcell.Event{ 691 tcell.NewEventKey(tcell.KeyRune, 'j', tcell.ModNone), 692 tcell.NewEventKey(tcell.KeyRune, 'd', tcell.ModNone), 693 tcell.NewEventKey(tcell.KeyRune, 'd', tcell.ModNone), 694 }, 695 expectedCursorPos: 18, 696 expectedText: "Lorem ipsum dolor\nadipiscing elit", 697 }, 698 { 699 name: "delete count lines", 700 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 701 events: []tcell.Event{ 702 tcell.NewEventKey(tcell.KeyRune, '2', tcell.ModNone), 703 tcell.NewEventKey(tcell.KeyRune, 'd', tcell.ModNone), 704 tcell.NewEventKey(tcell.KeyRune, 'd', tcell.ModNone), 705 }, 706 expectedCursorPos: 0, 707 expectedText: "adipiscing elit", 708 }, 709 { 710 name: "delete previous char in line", 711 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 712 events: []tcell.Event{ 713 tcell.NewEventKey(tcell.KeyRune, 'j', tcell.ModNone), 714 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 715 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 716 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 717 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 718 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 719 tcell.NewEventKey(tcell.KeyRune, 'd', tcell.ModNone), 720 tcell.NewEventKey(tcell.KeyRune, 'h', tcell.ModNone), 721 }, 722 expectedCursorPos: 22, 723 expectedText: "Lorem ipsum dolor\nsit met consectetur\nadipiscing elit", 724 }, 725 { 726 name: "delete lines below", 727 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 728 events: []tcell.Event{ 729 tcell.NewEventKey(tcell.KeyRune, 'd', tcell.ModNone), 730 tcell.NewEventKey(tcell.KeyRune, 'j', tcell.ModNone), 731 }, 732 expectedCursorPos: 0, 733 expectedText: "adipiscing elit", 734 }, 735 { 736 name: "delete lines above", 737 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 738 events: []tcell.Event{ 739 tcell.NewEventKey(tcell.KeyRune, 'j', tcell.ModNone), 740 tcell.NewEventKey(tcell.KeyRune, 'j', tcell.ModNone), 741 tcell.NewEventKey(tcell.KeyRune, 'd', tcell.ModNone), 742 tcell.NewEventKey(tcell.KeyRune, 'k', tcell.ModNone), 743 }, 744 expectedCursorPos: 0, 745 expectedText: "Lorem ipsum dolor", 746 }, 747 { 748 name: "delete next character in line", 749 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 750 events: []tcell.Event{ 751 tcell.NewEventKey(tcell.KeyRune, 'd', tcell.ModNone), 752 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 753 }, 754 expectedCursorPos: 0, 755 expectedText: "orem ipsum dolor\nsit amet consectetur\nadipiscing elit", 756 }, 757 { 758 name: "delete to end of line", 759 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 760 events: []tcell.Event{ 761 tcell.NewEventKey(tcell.KeyRune, 'd', tcell.ModNone), 762 tcell.NewEventKey(tcell.KeyRune, '$', tcell.ModNone), 763 }, 764 expectedCursorPos: 0, 765 expectedText: "\nsit amet consectetur\nadipiscing elit", 766 }, 767 { 768 name: "delete to end of line shortcut", 769 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 770 events: []tcell.Event{ 771 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 772 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 773 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 774 tcell.NewEventKey(tcell.KeyRune, 'D', tcell.ModNone), 775 }, 776 expectedCursorPos: 2, 777 expectedText: "Lor\nsit amet consectetur\nadipiscing elit", 778 }, 779 { 780 name: "delete to start of line", 781 initialText: "Lorem ipsum dolor\n\tsit amet consectetur\n\t\tadipiscing\nelit\n\n", 782 events: []tcell.Event{ 783 tcell.NewEventKey(tcell.KeyRune, 'j', tcell.ModNone), 784 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 785 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 786 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 787 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 788 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 789 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 790 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 791 tcell.NewEventKey(tcell.KeyRune, 'd', tcell.ModNone), 792 tcell.NewEventKey(tcell.KeyRune, '0', tcell.ModNone), 793 }, 794 expectedCursorPos: 18, 795 expectedText: "Lorem ipsum dolor\net consectetur\n\t\tadipiscing\nelit\n\n", 796 }, 797 { 798 name: "delete to start of line after indentation", 799 initialText: "Lorem ipsum dolor\n\tsit amet consectetur\n\t\tadipiscing\nelit\n\n", 800 events: []tcell.Event{ 801 tcell.NewEventKey(tcell.KeyRune, 'j', tcell.ModNone), 802 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 803 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 804 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 805 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 806 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 807 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 808 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 809 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 810 tcell.NewEventKey(tcell.KeyRune, 'd', tcell.ModNone), 811 tcell.NewEventKey(tcell.KeyRune, '^', tcell.ModNone), 812 }, 813 expectedCursorPos: 19, 814 expectedText: "Lorem ipsum dolor\n\tt consectetur\n\t\tadipiscing\nelit\n\n", 815 }, 816 { 817 name: "delete to start of next word", 818 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 819 events: []tcell.Event{ 820 tcell.NewEventKey(tcell.KeyRune, 'd', tcell.ModNone), 821 tcell.NewEventKey(tcell.KeyRune, 'w', tcell.ModNone), 822 }, 823 expectedCursorPos: 0, 824 expectedText: "ipsum dolor\nsit amet consectetur\nadipiscing elit", 825 }, 826 { 827 name: "delete to start of next word on an empty line with next line indented", 828 initialText: "a\n\n bcd", 829 events: []tcell.Event{ 830 tcell.NewEventKey(tcell.KeyRune, 'j', tcell.ModNone), 831 tcell.NewEventKey(tcell.KeyRune, 'd', tcell.ModNone), 832 tcell.NewEventKey(tcell.KeyRune, 'w', tcell.ModNone), 833 }, 834 expectedCursorPos: 6, 835 expectedText: "a\n bcd", 836 }, 837 { 838 name: "delete to start of next word at end of line with whitespace", 839 initialText: "a\n \nbcd", 840 events: []tcell.Event{ 841 tcell.NewEventKey(tcell.KeyRune, 'j', tcell.ModNone), 842 tcell.NewEventKey(tcell.KeyRune, '$', tcell.ModNone), 843 tcell.NewEventKey(tcell.KeyRune, 'd', tcell.ModNone), 844 tcell.NewEventKey(tcell.KeyRune, 'w', tcell.ModNone), 845 }, 846 expectedCursorPos: 3, 847 expectedText: "a\n \nbcd", 848 }, 849 { 850 name: "delete to start of next word end of document", 851 initialText: "abcdef", 852 events: []tcell.Event{ 853 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 854 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 855 tcell.NewEventKey(tcell.KeyRune, 'd', tcell.ModNone), 856 tcell.NewEventKey(tcell.KeyRune, 'w', tcell.ModNone), 857 }, 858 expectedCursorPos: 1, 859 expectedText: "ab", 860 }, 861 { 862 name: "delete to start of next word with count", 863 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 864 events: []tcell.Event{ 865 tcell.NewEventKey(tcell.KeyRune, '4', tcell.ModNone), 866 tcell.NewEventKey(tcell.KeyRune, 'd', tcell.ModNone), 867 tcell.NewEventKey(tcell.KeyRune, 'w', tcell.ModNone), 868 }, 869 expectedCursorPos: 0, 870 expectedText: "amet consectetur\nadipiscing elit", 871 }, 872 { 873 name: "delete to start of next word with verb and object count", 874 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 875 events: []tcell.Event{ 876 tcell.NewEventKey(tcell.KeyRune, '2', tcell.ModNone), 877 tcell.NewEventKey(tcell.KeyRune, 'd', tcell.ModNone), 878 tcell.NewEventKey(tcell.KeyRune, '3', tcell.ModNone), 879 tcell.NewEventKey(tcell.KeyRune, 'w', tcell.ModNone), 880 }, 881 expectedCursorPos: 0, 882 expectedText: "\nadipiscing elit", 883 }, 884 { 885 name: "delete to start of next word including punctuation", 886 initialText: "Lorem.ipsum,dolor;sit amet consectetur\nadipiscing elit", 887 events: []tcell.Event{ 888 tcell.NewEventKey(tcell.KeyRune, 'd', tcell.ModNone), 889 tcell.NewEventKey(tcell.KeyRune, 'W', tcell.ModNone), 890 }, 891 expectedCursorPos: 0, 892 expectedText: "amet consectetur\nadipiscing elit", 893 }, 894 { 895 name: "delete a word", 896 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 897 events: []tcell.Event{ 898 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 899 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 900 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 901 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 902 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 903 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 904 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 905 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 906 tcell.NewEventKey(tcell.KeyRune, 'd', tcell.ModNone), 907 tcell.NewEventKey(tcell.KeyRune, 'a', tcell.ModNone), 908 tcell.NewEventKey(tcell.KeyRune, 'w', tcell.ModNone), 909 }, 910 expectedCursorPos: 6, 911 expectedText: "Lorem dolor\nsit amet consectetur\nadipiscing elit", 912 }, 913 // NOTE: vim removes the trailing empty line, but aretext keeps it. 914 { 915 name: "delete a word on an empty line with next line indented", 916 initialText: "a\n\n bcd", 917 events: []tcell.Event{ 918 tcell.NewEventKey(tcell.KeyRune, 'j', tcell.ModNone), 919 tcell.NewEventKey(tcell.KeyRune, 'd', tcell.ModNone), 920 tcell.NewEventKey(tcell.KeyRune, 'a', tcell.ModNone), 921 tcell.NewEventKey(tcell.KeyRune, 'w', tcell.ModNone), 922 }, 923 expectedCursorPos: 2, 924 expectedText: "a\n", 925 }, 926 { 927 name: "delete a word in whitespace before word", 928 initialText: "ab cd ef", 929 events: []tcell.Event{ 930 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 931 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 932 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 933 tcell.NewEventKey(tcell.KeyRune, 'd', tcell.ModNone), 934 tcell.NewEventKey(tcell.KeyRune, 'a', tcell.ModNone), 935 tcell.NewEventKey(tcell.KeyRune, 'w', tcell.ModNone), 936 }, 937 expectedCursorPos: 2, 938 expectedText: "ab ef", 939 }, 940 // NOTE: aretext deletes the word, but vim deletes the leading whitespace as well. 941 { 942 name: "delete a word on word at end of line with leading whitespace", 943 initialText: "ab cd ef", 944 events: []tcell.Event{ 945 tcell.NewEventKey(tcell.KeyRune, '$', tcell.ModNone), 946 tcell.NewEventKey(tcell.KeyRune, 'd', tcell.ModNone), 947 tcell.NewEventKey(tcell.KeyRune, 'a', tcell.ModNone), 948 tcell.NewEventKey(tcell.KeyRune, 'w', tcell.ModNone), 949 }, 950 expectedCursorPos: 9, 951 expectedText: "ab cd ", 952 }, 953 { 954 name: "delete a word with count", 955 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 956 events: []tcell.Event{ 957 tcell.NewEventKey(tcell.KeyRune, '5', tcell.ModNone), 958 tcell.NewEventKey(tcell.KeyRune, 'd', tcell.ModNone), 959 tcell.NewEventKey(tcell.KeyRune, 'a', tcell.ModNone), 960 tcell.NewEventKey(tcell.KeyRune, 'w', tcell.ModNone), 961 }, 962 expectedCursorPos: 0, 963 expectedText: "consectetur\nadipiscing elit", 964 }, 965 { 966 name: "delete inner word", 967 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 968 events: []tcell.Event{ 969 tcell.NewEventKey(tcell.KeyRune, 'j', tcell.ModNone), 970 tcell.NewEventKey(tcell.KeyRune, 'd', tcell.ModNone), 971 tcell.NewEventKey(tcell.KeyRune, 'i', tcell.ModNone), 972 tcell.NewEventKey(tcell.KeyRune, 'w', tcell.ModNone), 973 tcell.NewEventKey(tcell.KeyEsc, '\x00', tcell.ModNone), 974 }, 975 expectedCursorPos: 18, 976 expectedText: "Lorem ipsum dolor\n amet consectetur\nadipiscing elit", 977 }, 978 { 979 name: "delete inner word at end of line", 980 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 981 events: []tcell.Event{ 982 tcell.NewEventKey(tcell.KeyRune, 'w', tcell.ModNone), 983 tcell.NewEventKey(tcell.KeyRune, 'w', tcell.ModNone), 984 tcell.NewEventKey(tcell.KeyRune, 'd', tcell.ModNone), 985 tcell.NewEventKey(tcell.KeyRune, 'i', tcell.ModNone), 986 tcell.NewEventKey(tcell.KeyRune, 'w', tcell.ModNone), 987 tcell.NewEventKey(tcell.KeyEsc, '\x00', tcell.ModNone), 988 }, 989 expectedCursorPos: 11, 990 expectedText: "Lorem ipsum \nsit amet consectetur\nadipiscing elit", 991 }, 992 { 993 name: "delete inner word with count", 994 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 995 events: []tcell.Event{ 996 tcell.NewEventKey(tcell.KeyRune, '7', tcell.ModNone), 997 tcell.NewEventKey(tcell.KeyRune, 'd', tcell.ModNone), 998 tcell.NewEventKey(tcell.KeyRune, 'i', tcell.ModNone), 999 tcell.NewEventKey(tcell.KeyRune, 'w', tcell.ModNone), 1000 }, 1001 expectedCursorPos: 0, 1002 expectedText: "amet consectetur\nadipiscing elit", 1003 }, 1004 { 1005 name: "delete inner string object with double-quote", 1006 initialText: `"ab c" x`, 1007 events: []tcell.Event{ 1008 tcell.NewEventKey(tcell.KeyRune, 'd', tcell.ModNone), 1009 tcell.NewEventKey(tcell.KeyRune, 'i', tcell.ModNone), 1010 tcell.NewEventKey(tcell.KeyRune, '"', tcell.ModNone), 1011 }, 1012 expectedCursorPos: 1, 1013 expectedText: `"" x`, 1014 }, 1015 { 1016 name: "delete a string object with double-quote", 1017 initialText: `"ab c" x`, 1018 events: []tcell.Event{ 1019 tcell.NewEventKey(tcell.KeyRune, 'd', tcell.ModNone), 1020 tcell.NewEventKey(tcell.KeyRune, 'a', tcell.ModNone), 1021 tcell.NewEventKey(tcell.KeyRune, '"', tcell.ModNone), 1022 }, 1023 expectedCursorPos: 0, 1024 expectedText: ` x`, 1025 }, 1026 { 1027 name: "delete inner string object with single-quote", 1028 initialText: `'ab c' x`, 1029 events: []tcell.Event{ 1030 tcell.NewEventKey(tcell.KeyRune, 'd', tcell.ModNone), 1031 tcell.NewEventKey(tcell.KeyRune, 'i', tcell.ModNone), 1032 tcell.NewEventKey(tcell.KeyRune, '\'', tcell.ModNone), 1033 }, 1034 expectedCursorPos: 1, 1035 expectedText: `'' x`, 1036 }, 1037 { 1038 name: "delete a string object with single-quote", 1039 initialText: `'ab c' x`, 1040 events: []tcell.Event{ 1041 tcell.NewEventKey(tcell.KeyRune, 'd', tcell.ModNone), 1042 tcell.NewEventKey(tcell.KeyRune, 'a', tcell.ModNone), 1043 tcell.NewEventKey(tcell.KeyRune, '\'', tcell.ModNone), 1044 }, 1045 expectedCursorPos: 0, 1046 expectedText: ` x`, 1047 }, 1048 { 1049 name: "delete inner string object with backtick-quote", 1050 initialText: "`ab c` x", 1051 events: []tcell.Event{ 1052 tcell.NewEventKey(tcell.KeyRune, 'd', tcell.ModNone), 1053 tcell.NewEventKey(tcell.KeyRune, 'i', tcell.ModNone), 1054 tcell.NewEventKey(tcell.KeyRune, '`', tcell.ModNone), 1055 }, 1056 expectedCursorPos: 1, 1057 expectedText: "`` x", 1058 }, 1059 { 1060 name: "delete a string object with backtick-quote", 1061 initialText: "`ab c` x", 1062 events: []tcell.Event{ 1063 tcell.NewEventKey(tcell.KeyRune, 'd', tcell.ModNone), 1064 tcell.NewEventKey(tcell.KeyRune, 'a', tcell.ModNone), 1065 tcell.NewEventKey(tcell.KeyRune, '`', tcell.ModNone), 1066 }, 1067 expectedCursorPos: 0, 1068 expectedText: " x", 1069 }, 1070 { 1071 name: "delete to next matching character in line", 1072 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 1073 events: []tcell.Event{ 1074 tcell.NewEventKey(tcell.KeyRune, 'd', tcell.ModNone), 1075 tcell.NewEventKey(tcell.KeyRune, 'f', tcell.ModNone), 1076 tcell.NewEventKey(tcell.KeyRune, 'm', tcell.ModNone), 1077 }, 1078 expectedCursorPos: 0, 1079 expectedText: " ipsum dolor\nsit amet consectetur\nadipiscing elit", 1080 }, 1081 { 1082 name: "delete to prev matching char in line", 1083 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 1084 events: []tcell.Event{ 1085 tcell.NewEventKey(tcell.KeyRune, 'j', tcell.ModNone), 1086 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1087 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1088 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1089 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1090 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1091 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1092 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1093 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1094 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1095 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1096 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1097 tcell.NewEventKey(tcell.KeyRune, 'd', tcell.ModNone), 1098 tcell.NewEventKey(tcell.KeyRune, 'F', tcell.ModNone), 1099 tcell.NewEventKey(tcell.KeyRune, 't', tcell.ModNone), 1100 }, 1101 expectedCursorPos: 25, 1102 expectedText: "Lorem ipsum dolor\nsit amensectetur\nadipiscing elit", 1103 }, 1104 { 1105 name: "delete till next matching char in line", 1106 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 1107 events: []tcell.Event{ 1108 tcell.NewEventKey(tcell.KeyRune, 'd', tcell.ModNone), 1109 tcell.NewEventKey(tcell.KeyRune, 't', tcell.ModNone), 1110 tcell.NewEventKey(tcell.KeyRune, 'd', tcell.ModNone), 1111 }, 1112 expectedCursorPos: 0, 1113 expectedText: "dolor\nsit amet consectetur\nadipiscing elit", 1114 }, 1115 { 1116 name: "delete till prev matching char in line", 1117 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 1118 events: []tcell.Event{ 1119 tcell.NewEventKey(tcell.KeyRune, 'j', tcell.ModNone), 1120 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1121 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1122 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1123 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1124 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1125 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1126 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1127 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1128 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1129 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1130 tcell.NewEventKey(tcell.KeyRune, 'd', tcell.ModNone), 1131 tcell.NewEventKey(tcell.KeyRune, 'T', tcell.ModNone), 1132 tcell.NewEventKey(tcell.KeyRune, 's', tcell.ModNone), 1133 }, 1134 expectedCursorPos: 19, 1135 expectedText: "Lorem ipsum dolor\nsonsectetur\nadipiscing elit", 1136 }, 1137 { 1138 name: "delete a word, then put from default clipboard", 1139 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 1140 events: []tcell.Event{ 1141 tcell.NewEventKey(tcell.KeyRune, 'd', tcell.ModNone), 1142 tcell.NewEventKey(tcell.KeyRune, 'a', tcell.ModNone), 1143 tcell.NewEventKey(tcell.KeyRune, 'w', tcell.ModNone), 1144 tcell.NewEventKey(tcell.KeyRune, 'o', tcell.ModNone), 1145 tcell.NewEventKey(tcell.KeyEsc, '\x00', tcell.ModNone), 1146 tcell.NewEventKey(tcell.KeyRune, 'p', tcell.ModNone), 1147 }, 1148 expectedCursorPos: 17, 1149 expectedText: "ipsum dolor\nLorem \nsit amet consectetur\nadipiscing elit", 1150 }, 1151 { 1152 name: "change word from start of word", 1153 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 1154 events: []tcell.Event{ 1155 tcell.NewEventKey(tcell.KeyRune, 'c', tcell.ModNone), 1156 tcell.NewEventKey(tcell.KeyRune, 'w', tcell.ModNone), 1157 tcell.NewEventKey(tcell.KeyRune, 'f', tcell.ModNone), 1158 tcell.NewEventKey(tcell.KeyRune, 'o', tcell.ModNone), 1159 tcell.NewEventKey(tcell.KeyRune, 'o', tcell.ModNone), 1160 tcell.NewEventKey(tcell.KeyEsc, '\x00', tcell.ModNone), 1161 }, 1162 expectedCursorPos: 2, 1163 expectedText: "foo ipsum dolor\nsit amet consectetur\nadipiscing elit", 1164 }, 1165 { 1166 name: "change word from middle of word", 1167 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 1168 events: []tcell.Event{ 1169 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1170 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1171 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1172 tcell.NewEventKey(tcell.KeyRune, 'c', tcell.ModNone), 1173 tcell.NewEventKey(tcell.KeyRune, 'w', tcell.ModNone), 1174 tcell.NewEventKey(tcell.KeyRune, 'f', tcell.ModNone), 1175 tcell.NewEventKey(tcell.KeyRune, 'o', tcell.ModNone), 1176 tcell.NewEventKey(tcell.KeyRune, 'o', tcell.ModNone), 1177 tcell.NewEventKey(tcell.KeyEsc, '\x00', tcell.ModNone), 1178 }, 1179 expectedCursorPos: 5, 1180 expectedText: "Lorfoo ipsum dolor\nsit amet consectetur\nadipiscing elit", 1181 }, 1182 { 1183 name: "change word from end of word", 1184 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 1185 events: []tcell.Event{ 1186 tcell.NewEventKey(tcell.KeyRune, 'e', tcell.ModNone), 1187 tcell.NewEventKey(tcell.KeyRune, 'c', tcell.ModNone), 1188 tcell.NewEventKey(tcell.KeyRune, 'w', tcell.ModNone), 1189 tcell.NewEventKey(tcell.KeyRune, 'f', tcell.ModNone), 1190 tcell.NewEventKey(tcell.KeyRune, 'o', tcell.ModNone), 1191 tcell.NewEventKey(tcell.KeyRune, 'o', tcell.ModNone), 1192 tcell.NewEventKey(tcell.KeyEsc, '\x00', tcell.ModNone), 1193 }, 1194 expectedCursorPos: 6, 1195 expectedText: "Lorefoo ipsum dolor\nsit amet consectetur\nadipiscing elit", 1196 }, 1197 { 1198 name: "change word in leading whitespace", 1199 initialText: "abcd efghi jklm", 1200 events: []tcell.Event{ 1201 tcell.NewEventKey(tcell.KeyRune, 'e', tcell.ModNone), 1202 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1203 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1204 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1205 tcell.NewEventKey(tcell.KeyRune, 'c', tcell.ModNone), 1206 tcell.NewEventKey(tcell.KeyRune, 'w', tcell.ModNone), 1207 tcell.NewEventKey(tcell.KeyRune, 'f', tcell.ModNone), 1208 tcell.NewEventKey(tcell.KeyRune, 'o', tcell.ModNone), 1209 tcell.NewEventKey(tcell.KeyRune, 'o', tcell.ModNone), 1210 tcell.NewEventKey(tcell.KeyEsc, '\x00', tcell.ModNone), 1211 }, 1212 expectedCursorPos: 8, 1213 expectedText: "abcd fooefghi jklm", 1214 }, 1215 { 1216 name: "change word with count", 1217 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 1218 events: []tcell.Event{ 1219 tcell.NewEventKey(tcell.KeyRune, '3', tcell.ModNone), 1220 tcell.NewEventKey(tcell.KeyRune, 'c', tcell.ModNone), 1221 tcell.NewEventKey(tcell.KeyRune, 'w', tcell.ModNone), 1222 tcell.NewEventKey(tcell.KeyRune, 'f', tcell.ModNone), 1223 tcell.NewEventKey(tcell.KeyRune, 'o', tcell.ModNone), 1224 tcell.NewEventKey(tcell.KeyRune, 'o', tcell.ModNone), 1225 tcell.NewEventKey(tcell.KeyEsc, '\x00', tcell.ModNone), 1226 }, 1227 expectedCursorPos: 2, 1228 expectedText: "foo dolor\nsit amet consectetur\nadipiscing elit", 1229 }, 1230 { 1231 name: "change a word", 1232 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 1233 events: []tcell.Event{ 1234 tcell.NewEventKey(tcell.KeyRune, 'j', tcell.ModNone), 1235 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1236 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1237 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1238 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1239 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1240 tcell.NewEventKey(tcell.KeyRune, 'c', tcell.ModNone), 1241 tcell.NewEventKey(tcell.KeyRune, 'a', tcell.ModNone), 1242 tcell.NewEventKey(tcell.KeyRune, 'w', tcell.ModNone), 1243 tcell.NewEventKey(tcell.KeyRune, 'f', tcell.ModNone), 1244 tcell.NewEventKey(tcell.KeyRune, 'o', tcell.ModNone), 1245 tcell.NewEventKey(tcell.KeyRune, 'o', tcell.ModNone), 1246 tcell.NewEventKey(tcell.KeyRune, 'b', tcell.ModNone), 1247 tcell.NewEventKey(tcell.KeyRune, 'a', tcell.ModNone), 1248 tcell.NewEventKey(tcell.KeyRune, 'r', tcell.ModNone), 1249 tcell.NewEventKey(tcell.KeyRune, ' ', tcell.ModNone), 1250 tcell.NewEventKey(tcell.KeyEsc, '\x00', tcell.ModNone), 1251 }, 1252 expectedCursorPos: 28, 1253 expectedText: "Lorem ipsum dolor\nsit foobar consectetur\nadipiscing elit", 1254 }, 1255 { 1256 name: "change a word at end of line", 1257 initialText: "foo=bar\nbaz", 1258 events: []tcell.Event{ 1259 tcell.NewEventKey(tcell.KeyRune, '$', tcell.ModNone), 1260 tcell.NewEventKey(tcell.KeyRune, 'c', tcell.ModNone), 1261 tcell.NewEventKey(tcell.KeyRune, 'a', tcell.ModNone), 1262 tcell.NewEventKey(tcell.KeyRune, 'w', tcell.ModNone), 1263 tcell.NewEventKey(tcell.KeyRune, 'x', tcell.ModNone), 1264 tcell.NewEventKey(tcell.KeyRune, 'x', tcell.ModNone), 1265 tcell.NewEventKey(tcell.KeyRune, 'x', tcell.ModNone), 1266 tcell.NewEventKey(tcell.KeyEsc, '\x00', tcell.ModNone), 1267 }, 1268 expectedCursorPos: 6, 1269 expectedText: "foo=xxx\nbaz", 1270 }, 1271 { 1272 name: "change a word with count", 1273 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 1274 events: []tcell.Event{ 1275 tcell.NewEventKey(tcell.KeyRune, '5', tcell.ModNone), 1276 tcell.NewEventKey(tcell.KeyRune, 'c', tcell.ModNone), 1277 tcell.NewEventKey(tcell.KeyRune, 'a', tcell.ModNone), 1278 tcell.NewEventKey(tcell.KeyRune, 'w', tcell.ModNone), 1279 tcell.NewEventKey(tcell.KeyRune, 'f', tcell.ModNone), 1280 tcell.NewEventKey(tcell.KeyRune, 'o', tcell.ModNone), 1281 tcell.NewEventKey(tcell.KeyRune, 'o', tcell.ModNone), 1282 tcell.NewEventKey(tcell.KeyRune, 'b', tcell.ModNone), 1283 tcell.NewEventKey(tcell.KeyRune, 'a', tcell.ModNone), 1284 tcell.NewEventKey(tcell.KeyRune, 'r', tcell.ModNone), 1285 tcell.NewEventKey(tcell.KeyEsc, '\x00', tcell.ModNone), 1286 }, 1287 expectedCursorPos: 5, 1288 expectedText: "foobarconsectetur\nadipiscing elit", 1289 }, 1290 { 1291 name: "change inner word", 1292 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 1293 events: []tcell.Event{ 1294 tcell.NewEventKey(tcell.KeyRune, 'j', tcell.ModNone), 1295 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1296 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1297 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1298 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1299 tcell.NewEventKey(tcell.KeyRune, 'c', tcell.ModNone), 1300 tcell.NewEventKey(tcell.KeyRune, 'i', tcell.ModNone), 1301 tcell.NewEventKey(tcell.KeyRune, 'w', tcell.ModNone), 1302 tcell.NewEventKey(tcell.KeyRune, 'f', tcell.ModNone), 1303 tcell.NewEventKey(tcell.KeyRune, 'o', tcell.ModNone), 1304 tcell.NewEventKey(tcell.KeyRune, 'o', tcell.ModNone), 1305 tcell.NewEventKey(tcell.KeyRune, 'b', tcell.ModNone), 1306 tcell.NewEventKey(tcell.KeyRune, 'a', tcell.ModNone), 1307 tcell.NewEventKey(tcell.KeyRune, 'r', tcell.ModNone), 1308 tcell.NewEventKey(tcell.KeyEsc, '\x00', tcell.ModNone), 1309 }, 1310 expectedCursorPos: 27, 1311 expectedText: "Lorem ipsum dolor\nsit foobar consectetur\nadipiscing elit", 1312 }, 1313 { 1314 name: "change inner word at end of line", 1315 initialText: "foo=bar\nbaz", 1316 events: []tcell.Event{ 1317 tcell.NewEventKey(tcell.KeyRune, '$', tcell.ModNone), 1318 tcell.NewEventKey(tcell.KeyRune, 'c', tcell.ModNone), 1319 tcell.NewEventKey(tcell.KeyRune, 'i', tcell.ModNone), 1320 tcell.NewEventKey(tcell.KeyRune, 'w', tcell.ModNone), 1321 tcell.NewEventKey(tcell.KeyRune, 'x', tcell.ModNone), 1322 tcell.NewEventKey(tcell.KeyRune, 'x', tcell.ModNone), 1323 tcell.NewEventKey(tcell.KeyRune, 'x', tcell.ModNone), 1324 tcell.NewEventKey(tcell.KeyEsc, '\x00', tcell.ModNone), 1325 }, 1326 expectedCursorPos: 6, 1327 expectedText: "foo=xxx\nbaz", 1328 }, 1329 { 1330 name: "change inner word with count", 1331 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 1332 events: []tcell.Event{ 1333 tcell.NewEventKey(tcell.KeyRune, '8', tcell.ModNone), 1334 tcell.NewEventKey(tcell.KeyRune, 'c', tcell.ModNone), 1335 tcell.NewEventKey(tcell.KeyRune, 'i', tcell.ModNone), 1336 tcell.NewEventKey(tcell.KeyRune, 'w', tcell.ModNone), 1337 tcell.NewEventKey(tcell.KeyRune, 'f', tcell.ModNone), 1338 tcell.NewEventKey(tcell.KeyRune, 'o', tcell.ModNone), 1339 tcell.NewEventKey(tcell.KeyRune, 'o', tcell.ModNone), 1340 tcell.NewEventKey(tcell.KeyRune, 'b', tcell.ModNone), 1341 tcell.NewEventKey(tcell.KeyRune, 'a', tcell.ModNone), 1342 tcell.NewEventKey(tcell.KeyRune, 'r', tcell.ModNone), 1343 tcell.NewEventKey(tcell.KeyEsc, '\x00', tcell.ModNone), 1344 }, 1345 expectedCursorPos: 5, 1346 expectedText: "foobar consectetur\nadipiscing elit", 1347 }, 1348 { 1349 name: "change inner string object with double-quote", 1350 initialText: `"abc" x`, 1351 events: []tcell.Event{ 1352 tcell.NewEventKey(tcell.KeyRune, 'c', tcell.ModNone), 1353 tcell.NewEventKey(tcell.KeyRune, 'i', tcell.ModNone), 1354 tcell.NewEventKey(tcell.KeyRune, '"', tcell.ModNone), 1355 tcell.NewEventKey(tcell.KeyRune, 'f', tcell.ModNone), 1356 }, 1357 expectedCursorPos: 2, 1358 expectedText: `"f" x`, 1359 }, 1360 { 1361 name: "change a string object with double-quote", 1362 initialText: `"abc" x`, 1363 events: []tcell.Event{ 1364 tcell.NewEventKey(tcell.KeyRune, 'c', tcell.ModNone), 1365 tcell.NewEventKey(tcell.KeyRune, 'a', tcell.ModNone), 1366 tcell.NewEventKey(tcell.KeyRune, '"', tcell.ModNone), 1367 tcell.NewEventKey(tcell.KeyRune, 'f', tcell.ModNone), 1368 }, 1369 expectedCursorPos: 1, 1370 expectedText: `f x`, 1371 }, 1372 { 1373 name: "change inner string object with single-quote", 1374 initialText: `'abc' x`, 1375 events: []tcell.Event{ 1376 tcell.NewEventKey(tcell.KeyRune, 'c', tcell.ModNone), 1377 tcell.NewEventKey(tcell.KeyRune, 'i', tcell.ModNone), 1378 tcell.NewEventKey(tcell.KeyRune, '\'', tcell.ModNone), 1379 tcell.NewEventKey(tcell.KeyRune, 'f', tcell.ModNone), 1380 }, 1381 expectedCursorPos: 2, 1382 expectedText: `'f' x`, 1383 }, 1384 { 1385 name: "change a string object with single-quote", 1386 initialText: `'abc' x`, 1387 events: []tcell.Event{ 1388 tcell.NewEventKey(tcell.KeyRune, 'c', tcell.ModNone), 1389 tcell.NewEventKey(tcell.KeyRune, 'a', tcell.ModNone), 1390 tcell.NewEventKey(tcell.KeyRune, '\'', tcell.ModNone), 1391 tcell.NewEventKey(tcell.KeyRune, 'f', tcell.ModNone), 1392 }, 1393 expectedCursorPos: 1, 1394 expectedText: `f x`, 1395 }, 1396 { 1397 name: "change inner string object with backtick-quote", 1398 initialText: "`abc` x", 1399 events: []tcell.Event{ 1400 tcell.NewEventKey(tcell.KeyRune, 'c', tcell.ModNone), 1401 tcell.NewEventKey(tcell.KeyRune, 'i', tcell.ModNone), 1402 tcell.NewEventKey(tcell.KeyRune, '`', tcell.ModNone), 1403 tcell.NewEventKey(tcell.KeyRune, 'f', tcell.ModNone), 1404 }, 1405 expectedCursorPos: 2, 1406 expectedText: "`f` x", 1407 }, 1408 { 1409 name: "change a string object with backtick-quote", 1410 initialText: "`abc` x", 1411 events: []tcell.Event{ 1412 tcell.NewEventKey(tcell.KeyRune, 'c', tcell.ModNone), 1413 tcell.NewEventKey(tcell.KeyRune, 'a', tcell.ModNone), 1414 tcell.NewEventKey(tcell.KeyRune, '`', tcell.ModNone), 1415 tcell.NewEventKey(tcell.KeyRune, 'f', tcell.ModNone), 1416 }, 1417 expectedCursorPos: 1, 1418 expectedText: "f x", 1419 }, 1420 { 1421 name: "change to next matching char in line", 1422 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 1423 events: []tcell.Event{ 1424 tcell.NewEventKey(tcell.KeyRune, 'c', tcell.ModNone), 1425 tcell.NewEventKey(tcell.KeyRune, 't', tcell.ModNone), 1426 tcell.NewEventKey(tcell.KeyRune, 's', tcell.ModNone), 1427 tcell.NewEventKey(tcell.KeyRune, 't', tcell.ModNone), 1428 tcell.NewEventKey(tcell.KeyRune, 'e', tcell.ModNone), 1429 tcell.NewEventKey(tcell.KeyRune, 's', tcell.ModNone), 1430 tcell.NewEventKey(tcell.KeyRune, 't', tcell.ModNone), 1431 tcell.NewEventKey(tcell.KeyEsc, '\x00', tcell.ModNone), 1432 }, 1433 expectedCursorPos: 3, 1434 expectedText: "testsum dolor\nsit amet consectetur\nadipiscing elit", 1435 }, 1436 { 1437 name: "change to next matching char in line at end of line", 1438 1439 initialText: "foobar123\nbaz", 1440 events: []tcell.Event{ 1441 tcell.NewEventKey(tcell.KeyRune, 'c', tcell.ModNone), 1442 tcell.NewEventKey(tcell.KeyRune, 't', tcell.ModNone), 1443 tcell.NewEventKey(tcell.KeyRune, '3', tcell.ModNone), 1444 tcell.NewEventKey(tcell.KeyRune, 't', tcell.ModNone), 1445 tcell.NewEventKey(tcell.KeyRune, 'e', tcell.ModNone), 1446 tcell.NewEventKey(tcell.KeyRune, 's', tcell.ModNone), 1447 tcell.NewEventKey(tcell.KeyRune, 't', tcell.ModNone), 1448 tcell.NewEventKey(tcell.KeyEsc, '\x00', tcell.ModNone), 1449 }, 1450 expectedCursorPos: 3, 1451 expectedText: "test3\nbaz", 1452 }, 1453 { 1454 name: "change to prev matching character in line ", 1455 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 1456 events: []tcell.Event{ 1457 tcell.NewEventKey(tcell.KeyRune, 'j', tcell.ModNone), 1458 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1459 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1460 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1461 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1462 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1463 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1464 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1465 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1466 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1467 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1468 tcell.NewEventKey(tcell.KeyRune, 'c', tcell.ModNone), 1469 tcell.NewEventKey(tcell.KeyRune, 'F', tcell.ModNone), 1470 tcell.NewEventKey(tcell.KeyRune, 's', tcell.ModNone), 1471 tcell.NewEventKey(tcell.KeyRune, 'f', tcell.ModNone), 1472 tcell.NewEventKey(tcell.KeyRune, 'o', tcell.ModNone), 1473 tcell.NewEventKey(tcell.KeyRune, 'o', tcell.ModNone), 1474 tcell.NewEventKey(tcell.KeyRune, 'b', tcell.ModNone), 1475 tcell.NewEventKey(tcell.KeyRune, 'a', tcell.ModNone), 1476 tcell.NewEventKey(tcell.KeyRune, 'r', tcell.ModNone), 1477 tcell.NewEventKey(tcell.KeyEsc, '\x00', tcell.ModNone), 1478 }, 1479 expectedCursorPos: 23, 1480 expectedText: "Lorem ipsum dolor\nfoobaronsectetur\nadipiscing elit", 1481 }, 1482 { 1483 name: "change till next matching char in line", 1484 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 1485 events: []tcell.Event{ 1486 tcell.NewEventKey(tcell.KeyRune, 'c', tcell.ModNone), 1487 tcell.NewEventKey(tcell.KeyRune, 'f', tcell.ModNone), 1488 tcell.NewEventKey(tcell.KeyRune, 'm', tcell.ModNone), 1489 tcell.NewEventKey(tcell.KeyRune, 't', tcell.ModNone), 1490 tcell.NewEventKey(tcell.KeyRune, 'e', tcell.ModNone), 1491 tcell.NewEventKey(tcell.KeyRune, 's', tcell.ModNone), 1492 tcell.NewEventKey(tcell.KeyRune, 't', tcell.ModNone), 1493 tcell.NewEventKey(tcell.KeyEsc, '\x00', tcell.ModNone), 1494 }, 1495 expectedCursorPos: 3, 1496 expectedText: "test ipsum dolor\nsit amet consectetur\nadipiscing elit", 1497 }, 1498 { 1499 name: "change till next matching char in line at end of line", 1500 initialText: "foobar123\nbaz", 1501 events: []tcell.Event{ 1502 tcell.NewEventKey(tcell.KeyRune, 'c', tcell.ModNone), 1503 tcell.NewEventKey(tcell.KeyRune, 'f', tcell.ModNone), 1504 tcell.NewEventKey(tcell.KeyRune, '3', tcell.ModNone), 1505 tcell.NewEventKey(tcell.KeyRune, 't', tcell.ModNone), 1506 tcell.NewEventKey(tcell.KeyRune, 'e', tcell.ModNone), 1507 tcell.NewEventKey(tcell.KeyRune, 's', tcell.ModNone), 1508 tcell.NewEventKey(tcell.KeyRune, 't', tcell.ModNone), 1509 tcell.NewEventKey(tcell.KeyEsc, '\x00', tcell.ModNone), 1510 }, 1511 expectedCursorPos: 3, 1512 expectedText: "test\nbaz", 1513 }, 1514 { 1515 name: "change till prev matching char in line", 1516 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 1517 events: []tcell.Event{ 1518 tcell.NewEventKey(tcell.KeyRune, 'j', tcell.ModNone), 1519 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1520 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1521 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1522 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1523 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1524 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1525 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1526 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1527 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1528 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1529 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1530 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1531 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1532 tcell.NewEventKey(tcell.KeyRune, 'c', tcell.ModNone), 1533 tcell.NewEventKey(tcell.KeyRune, 'T', tcell.ModNone), 1534 tcell.NewEventKey(tcell.KeyRune, 't', tcell.ModNone), 1535 tcell.NewEventKey(tcell.KeyRune, 'f', tcell.ModNone), 1536 tcell.NewEventKey(tcell.KeyRune, 'o', tcell.ModNone), 1537 tcell.NewEventKey(tcell.KeyRune, 'o', tcell.ModNone), 1538 tcell.NewEventKey(tcell.KeyRune, 'b', tcell.ModNone), 1539 tcell.NewEventKey(tcell.KeyRune, 'a', tcell.ModNone), 1540 tcell.NewEventKey(tcell.KeyRune, 'r', tcell.ModNone), 1541 tcell.NewEventKey(tcell.KeyEsc, '\x00', tcell.ModNone), 1542 }, 1543 expectedCursorPos: 31, 1544 expectedText: "Lorem ipsum dolor\nsit ametfoobarectetur\nadipiscing elit", 1545 }, 1546 { 1547 name: "delete inner paren block (dib)", 1548 initialText: "abc (def) ghi", 1549 events: []tcell.Event{ 1550 tcell.NewEventKey(tcell.KeyRune, '5', tcell.ModNone), 1551 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1552 tcell.NewEventKey(tcell.KeyRune, 'd', tcell.ModNone), 1553 tcell.NewEventKey(tcell.KeyRune, 'i', tcell.ModNone), 1554 tcell.NewEventKey(tcell.KeyRune, 'b', tcell.ModNone), 1555 }, 1556 expectedCursorPos: 5, 1557 expectedText: "abc () ghi", 1558 }, 1559 { 1560 name: "delete inner paren block (di+openparen)", 1561 initialText: "abc (def) ghi", 1562 events: []tcell.Event{ 1563 tcell.NewEventKey(tcell.KeyRune, '5', tcell.ModNone), 1564 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1565 tcell.NewEventKey(tcell.KeyRune, 'd', tcell.ModNone), 1566 tcell.NewEventKey(tcell.KeyRune, 'i', tcell.ModNone), 1567 tcell.NewEventKey(tcell.KeyRune, '(', tcell.ModNone), 1568 }, 1569 expectedCursorPos: 5, 1570 expectedText: "abc () ghi", 1571 }, 1572 { 1573 name: "delete inner paren block (di+closeparen)", 1574 initialText: "abc (def) ghi", 1575 events: []tcell.Event{ 1576 tcell.NewEventKey(tcell.KeyRune, '5', tcell.ModNone), 1577 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1578 tcell.NewEventKey(tcell.KeyRune, 'd', tcell.ModNone), 1579 tcell.NewEventKey(tcell.KeyRune, 'i', tcell.ModNone), 1580 tcell.NewEventKey(tcell.KeyRune, ')', tcell.ModNone), 1581 }, 1582 expectedCursorPos: 5, 1583 expectedText: "abc () ghi", 1584 }, 1585 { 1586 name: "delete a paren block (dib)", 1587 initialText: "abc (def) ghi", 1588 events: []tcell.Event{ 1589 tcell.NewEventKey(tcell.KeyRune, '5', tcell.ModNone), 1590 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1591 tcell.NewEventKey(tcell.KeyRune, 'd', tcell.ModNone), 1592 tcell.NewEventKey(tcell.KeyRune, 'a', tcell.ModNone), 1593 tcell.NewEventKey(tcell.KeyRune, 'b', tcell.ModNone), 1594 }, 1595 expectedCursorPos: 4, 1596 expectedText: "abc ghi", 1597 }, 1598 { 1599 name: "delete inner brace block (diB)", 1600 initialText: `func() { fmt.Printf("abc") }`, 1601 events: []tcell.Event{ 1602 tcell.NewEventKey(tcell.KeyRune, '9', tcell.ModNone), 1603 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1604 tcell.NewEventKey(tcell.KeyRune, 'd', tcell.ModNone), 1605 tcell.NewEventKey(tcell.KeyRune, 'i', tcell.ModNone), 1606 tcell.NewEventKey(tcell.KeyRune, 'B', tcell.ModNone), 1607 }, 1608 expectedCursorPos: 8, 1609 expectedText: "func() {}", 1610 }, 1611 { 1612 name: "delete a brace block (daB)", 1613 initialText: `func() { fmt.Printf("abc") }`, 1614 events: []tcell.Event{ 1615 tcell.NewEventKey(tcell.KeyRune, '9', tcell.ModNone), 1616 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1617 tcell.NewEventKey(tcell.KeyRune, 'd', tcell.ModNone), 1618 tcell.NewEventKey(tcell.KeyRune, 'a', tcell.ModNone), 1619 tcell.NewEventKey(tcell.KeyRune, 'B', tcell.ModNone), 1620 }, 1621 expectedCursorPos: 7, 1622 expectedText: "func() ", 1623 }, 1624 { 1625 name: "delete inner angle block (di<)", 1626 initialText: `<html><body /></html>`, 1627 events: []tcell.Event{ 1628 tcell.NewEventKey(tcell.KeyRune, '9', tcell.ModNone), 1629 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1630 tcell.NewEventKey(tcell.KeyRune, 'd', tcell.ModNone), 1631 tcell.NewEventKey(tcell.KeyRune, 'i', tcell.ModNone), 1632 tcell.NewEventKey(tcell.KeyRune, '<', tcell.ModNone), 1633 }, 1634 expectedCursorPos: 7, 1635 expectedText: "<html><></html>", 1636 }, 1637 { 1638 name: "delete an angle block (da<)", 1639 initialText: `<html><body /></html>`, 1640 events: []tcell.Event{ 1641 tcell.NewEventKey(tcell.KeyRune, '9', tcell.ModNone), 1642 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1643 tcell.NewEventKey(tcell.KeyRune, 'd', tcell.ModNone), 1644 tcell.NewEventKey(tcell.KeyRune, 'a', tcell.ModNone), 1645 tcell.NewEventKey(tcell.KeyRune, '<', tcell.ModNone), 1646 }, 1647 expectedCursorPos: 6, 1648 expectedText: "<html></html>", 1649 }, 1650 { 1651 name: "change inner paren block (cib)", 1652 initialText: "abc (def) ghi", 1653 events: []tcell.Event{ 1654 tcell.NewEventKey(tcell.KeyRune, '5', tcell.ModNone), 1655 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1656 tcell.NewEventKey(tcell.KeyRune, 'c', tcell.ModNone), 1657 tcell.NewEventKey(tcell.KeyRune, 'i', tcell.ModNone), 1658 tcell.NewEventKey(tcell.KeyRune, 'b', tcell.ModNone), 1659 tcell.NewEventKey(tcell.KeyRune, 'x', tcell.ModNone), 1660 }, 1661 expectedCursorPos: 6, 1662 expectedText: "abc (x) ghi", 1663 }, 1664 { 1665 name: "change inner paren block (ci+openparen)", 1666 initialText: "abc (def) ghi", 1667 events: []tcell.Event{ 1668 tcell.NewEventKey(tcell.KeyRune, '5', tcell.ModNone), 1669 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1670 tcell.NewEventKey(tcell.KeyRune, 'c', tcell.ModNone), 1671 tcell.NewEventKey(tcell.KeyRune, 'i', tcell.ModNone), 1672 tcell.NewEventKey(tcell.KeyRune, '(', tcell.ModNone), 1673 tcell.NewEventKey(tcell.KeyRune, 'x', tcell.ModNone), 1674 }, 1675 expectedCursorPos: 6, 1676 expectedText: "abc (x) ghi", 1677 }, 1678 { 1679 name: "change inner paren block (ci+closeparen)", 1680 initialText: "abc (def) ghi", 1681 events: []tcell.Event{ 1682 tcell.NewEventKey(tcell.KeyRune, '5', tcell.ModNone), 1683 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1684 tcell.NewEventKey(tcell.KeyRune, 'c', tcell.ModNone), 1685 tcell.NewEventKey(tcell.KeyRune, 'i', tcell.ModNone), 1686 tcell.NewEventKey(tcell.KeyRune, ')', tcell.ModNone), 1687 tcell.NewEventKey(tcell.KeyRune, 'x', tcell.ModNone), 1688 }, 1689 expectedCursorPos: 6, 1690 expectedText: "abc (x) ghi", 1691 }, 1692 { 1693 name: "change inner paren block, outside block", 1694 initialText: "abc (def) ghi", 1695 events: []tcell.Event{ 1696 tcell.NewEventKey(tcell.KeyRune, 'c', tcell.ModNone), 1697 tcell.NewEventKey(tcell.KeyRune, 'i', tcell.ModNone), 1698 tcell.NewEventKey(tcell.KeyRune, 'b', tcell.ModNone), 1699 tcell.NewEventKey(tcell.KeyRune, 'x', tcell.ModNone), // interpret in normal mode, NOT insert mode. 1700 }, 1701 expectedCursorPos: 0, 1702 expectedText: "bc (def) ghi", 1703 }, 1704 { 1705 name: "change inner brace block (ciB), single line", 1706 initialText: `func() { fmt.Printf("abc") }`, 1707 events: []tcell.Event{ 1708 tcell.NewEventKey(tcell.KeyRune, '9', tcell.ModNone), 1709 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1710 tcell.NewEventKey(tcell.KeyRune, 'c', tcell.ModNone), 1711 tcell.NewEventKey(tcell.KeyRune, 'i', tcell.ModNone), 1712 tcell.NewEventKey(tcell.KeyRune, 'B', tcell.ModNone), 1713 tcell.NewEventKey(tcell.KeyRune, 'x', tcell.ModNone), 1714 }, 1715 expectedCursorPos: 9, 1716 expectedText: "func() {x}", 1717 }, 1718 { 1719 name: "change inner brace block (ciB), multiple lines", 1720 initialText: "func() {\n\tfmt.Printf(\"abc\")\n\tfmt.Printf(\"xyz\")\n}", 1721 events: []tcell.Event{ 1722 tcell.NewEventKey(tcell.KeyRune, '9', tcell.ModNone), 1723 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1724 tcell.NewEventKey(tcell.KeyRune, 'c', tcell.ModNone), 1725 tcell.NewEventKey(tcell.KeyRune, 'i', tcell.ModNone), 1726 tcell.NewEventKey(tcell.KeyRune, 'B', tcell.ModNone), 1727 tcell.NewEventKey(tcell.KeyRune, 'x', tcell.ModNone), 1728 }, 1729 expectedCursorPos: 10, 1730 expectedText: "func() {\nx\n}", 1731 }, 1732 { 1733 name: "change a brace block (caB)", 1734 initialText: `func() { fmt.Printf("abc") }`, 1735 events: []tcell.Event{ 1736 tcell.NewEventKey(tcell.KeyRune, '9', tcell.ModNone), 1737 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1738 tcell.NewEventKey(tcell.KeyRune, 'c', tcell.ModNone), 1739 tcell.NewEventKey(tcell.KeyRune, 'a', tcell.ModNone), 1740 tcell.NewEventKey(tcell.KeyRune, 'B', tcell.ModNone), 1741 tcell.NewEventKey(tcell.KeyRune, 'x', tcell.ModNone), 1742 }, 1743 expectedCursorPos: 8, 1744 expectedText: "func() x", 1745 }, 1746 { 1747 name: "change inner angle block (ci<)", 1748 initialText: `<html><body /></html>`, 1749 events: []tcell.Event{ 1750 tcell.NewEventKey(tcell.KeyRune, '9', tcell.ModNone), 1751 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1752 tcell.NewEventKey(tcell.KeyRune, 'c', tcell.ModNone), 1753 tcell.NewEventKey(tcell.KeyRune, 'i', tcell.ModNone), 1754 tcell.NewEventKey(tcell.KeyRune, '<', tcell.ModNone), 1755 tcell.NewEventKey(tcell.KeyRune, 'x', tcell.ModNone), 1756 }, 1757 expectedCursorPos: 8, 1758 expectedText: "<html><x></html>", 1759 }, 1760 { 1761 name: "change an angle block (ca<)", 1762 initialText: `<html><body /></html>`, 1763 events: []tcell.Event{ 1764 tcell.NewEventKey(tcell.KeyRune, '9', tcell.ModNone), 1765 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1766 tcell.NewEventKey(tcell.KeyRune, 'c', tcell.ModNone), 1767 tcell.NewEventKey(tcell.KeyRune, 'a', tcell.ModNone), 1768 tcell.NewEventKey(tcell.KeyRune, '<', tcell.ModNone), 1769 tcell.NewEventKey(tcell.KeyRune, 'x', tcell.ModNone), 1770 }, 1771 expectedCursorPos: 7, 1772 expectedText: "<html>x</html>", 1773 }, 1774 { 1775 name: "replace character", 1776 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 1777 events: []tcell.Event{ 1778 tcell.NewEventKey(tcell.KeyRune, 'r', tcell.ModNone), 1779 tcell.NewEventKey(tcell.KeyRune, 'x', tcell.ModNone), 1780 }, 1781 expectedCursorPos: 0, 1782 expectedText: "xorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 1783 }, 1784 { 1785 name: "replace character with newline", 1786 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 1787 events: []tcell.Event{ 1788 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1789 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1790 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1791 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1792 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1793 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1794 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1795 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1796 tcell.NewEventKey(tcell.KeyRune, 'r', tcell.ModNone), 1797 tcell.NewEventKey(tcell.KeyEnter, '\r', tcell.ModNone), 1798 }, 1799 expectedCursorPos: 9, 1800 expectedText: "Lorem ip\num dolor\nsit amet consectetur\nadipiscing elit", 1801 }, 1802 { 1803 name: "replace character with tab", 1804 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 1805 events: []tcell.Event{ 1806 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1807 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1808 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1809 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1810 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1811 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1812 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1813 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1814 tcell.NewEventKey(tcell.KeyRune, 'r', tcell.ModNone), 1815 tcell.NewEventKey(tcell.KeyTab, '\t', tcell.ModNone), 1816 }, 1817 expectedCursorPos: 8, 1818 expectedText: "Lorem ip\tum dolor\nsit amet consectetur\nadipiscing elit", 1819 }, 1820 { 1821 name: "toggle case", 1822 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 1823 events: []tcell.Event{ 1824 tcell.NewEventKey(tcell.KeyRune, '~', tcell.ModNone), 1825 }, 1826 expectedCursorPos: 1, 1827 expectedText: "lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 1828 }, 1829 { 1830 name: "indent line", 1831 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 1832 events: []tcell.Event{ 1833 tcell.NewEventKey(tcell.KeyRune, '>', tcell.ModNone), 1834 tcell.NewEventKey(tcell.KeyRune, '>', tcell.ModNone), 1835 }, 1836 expectedCursorPos: 1, 1837 expectedText: "\tLorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 1838 }, 1839 { 1840 name: "indent line with count", 1841 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 1842 events: []tcell.Event{ 1843 tcell.NewEventKey(tcell.KeyRune, '2', tcell.ModNone), 1844 tcell.NewEventKey(tcell.KeyRune, '>', tcell.ModNone), 1845 tcell.NewEventKey(tcell.KeyRune, '>', tcell.ModNone), 1846 }, 1847 expectedCursorPos: 1, 1848 expectedText: "\tLorem ipsum dolor\n\tsit amet consectetur\nadipiscing elit", 1849 }, 1850 { 1851 name: "outdent line", 1852 initialText: "Lorem ipsum dolor\n\tsit amet consectetur\n\t\tadipiscing\nelit\n\n", 1853 events: []tcell.Event{ 1854 tcell.NewEventKey(tcell.KeyRune, 'j', tcell.ModNone), 1855 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1856 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1857 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1858 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1859 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1860 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1861 tcell.NewEventKey(tcell.KeyRune, '<', tcell.ModNone), 1862 tcell.NewEventKey(tcell.KeyRune, '<', tcell.ModNone), 1863 }, 1864 expectedCursorPos: 18, 1865 expectedText: "Lorem ipsum dolor\nsit amet consectetur\n\t\tadipiscing\nelit\n\n", 1866 }, 1867 { 1868 name: "outdent line with count", 1869 initialText: "Lorem ipsum dolor\n\tsit amet consectetur\n\t\tadipiscing\nelit\n\n", 1870 events: []tcell.Event{ 1871 tcell.NewEventKey(tcell.KeyRune, 'j', tcell.ModNone), 1872 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1873 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1874 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1875 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1876 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1877 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 1878 tcell.NewEventKey(tcell.KeyRune, '2', tcell.ModNone), 1879 tcell.NewEventKey(tcell.KeyRune, '<', tcell.ModNone), 1880 tcell.NewEventKey(tcell.KeyRune, '<', tcell.ModNone), 1881 }, 1882 expectedCursorPos: 18, 1883 expectedText: "Lorem ipsum dolor\nsit amet consectetur\n\tadipiscing\nelit\n\n", 1884 }, 1885 { 1886 name: "yank to start of next word", 1887 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 1888 events: []tcell.Event{ 1889 tcell.NewEventKey(tcell.KeyRune, 'y', tcell.ModNone), 1890 tcell.NewEventKey(tcell.KeyRune, 'w', tcell.ModNone), 1891 tcell.NewEventKey(tcell.KeyRune, 'o', tcell.ModNone), 1892 tcell.NewEventKey(tcell.KeyEsc, '\x00', tcell.ModNone), 1893 tcell.NewEventKey(tcell.KeyRune, 'p', tcell.ModNone), 1894 }, 1895 expectedCursorPos: 23, 1896 expectedText: "Lorem ipsum dolor\nLorem \nsit amet consectetur\nadipiscing elit", 1897 }, 1898 { 1899 name: "yank to start of next word with count", 1900 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 1901 events: []tcell.Event{ 1902 tcell.NewEventKey(tcell.KeyRune, '4', tcell.ModNone), 1903 tcell.NewEventKey(tcell.KeyRune, 'y', tcell.ModNone), 1904 tcell.NewEventKey(tcell.KeyRune, 'w', tcell.ModNone), 1905 tcell.NewEventKey(tcell.KeyRune, 'o', tcell.ModNone), 1906 tcell.NewEventKey(tcell.KeyEsc, '\x00', tcell.ModNone), 1907 tcell.NewEventKey(tcell.KeyRune, 'p', tcell.ModNone), 1908 }, 1909 expectedCursorPos: 39, 1910 expectedText: "Lorem ipsum dolor\nLorem ipsum dolor\nsit \nsit amet consectetur\nadipiscing elit", 1911 }, 1912 { 1913 name: "yank to start of next word including punctuation", 1914 initialText: "Lorem.ipsum;dolor sit amet consectetur\nadipiscing elit", 1915 events: []tcell.Event{ 1916 tcell.NewEventKey(tcell.KeyRune, 'y', tcell.ModNone), 1917 tcell.NewEventKey(tcell.KeyRune, 'W', tcell.ModNone), 1918 tcell.NewEventKey(tcell.KeyRune, 'o', tcell.ModNone), 1919 tcell.NewEventKey(tcell.KeyEsc, '\x00', tcell.ModNone), 1920 tcell.NewEventKey(tcell.KeyRune, 'p', tcell.ModNone), 1921 }, 1922 expectedCursorPos: 56, 1923 expectedText: "Lorem.ipsum;dolor sit amet consectetur\nLorem.ipsum;dolor \nadipiscing elit", 1924 }, 1925 { 1926 name: "yank a word", 1927 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 1928 events: []tcell.Event{ 1929 tcell.NewEventKey(tcell.KeyRune, 'w', tcell.ModNone), 1930 tcell.NewEventKey(tcell.KeyRune, 'y', tcell.ModNone), 1931 tcell.NewEventKey(tcell.KeyRune, 'a', tcell.ModNone), 1932 tcell.NewEventKey(tcell.KeyRune, 'w', tcell.ModNone), 1933 tcell.NewEventKey(tcell.KeyEsc, '\x00', tcell.ModNone), 1934 tcell.NewEventKey(tcell.KeyRune, 'o', tcell.ModNone), 1935 tcell.NewEventKey(tcell.KeyEsc, '\x00', tcell.ModNone), 1936 tcell.NewEventKey(tcell.KeyRune, 'p', tcell.ModNone), 1937 }, 1938 expectedCursorPos: 23, 1939 expectedText: "Lorem ipsum dolor\nipsum \nsit amet consectetur\nadipiscing elit", 1940 }, 1941 { 1942 name: "yank a word with count", 1943 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 1944 events: []tcell.Event{ 1945 tcell.NewEventKey(tcell.KeyRune, '4', tcell.ModNone), 1946 tcell.NewEventKey(tcell.KeyRune, 'y', tcell.ModNone), 1947 tcell.NewEventKey(tcell.KeyRune, 'a', tcell.ModNone), 1948 tcell.NewEventKey(tcell.KeyRune, 'w', tcell.ModNone), 1949 tcell.NewEventKey(tcell.KeyEsc, '\x00', tcell.ModNone), 1950 tcell.NewEventKey(tcell.KeyRune, 'o', tcell.ModNone), 1951 tcell.NewEventKey(tcell.KeyEsc, '\x00', tcell.ModNone), 1952 tcell.NewEventKey(tcell.KeyRune, 'p', tcell.ModNone), 1953 }, 1954 expectedCursorPos: 39, 1955 expectedText: "Lorem ipsum dolor\nLorem ipsum dolor\nsit \nsit amet consectetur\nadipiscing elit", 1956 }, 1957 { 1958 name: "yank inner word", 1959 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 1960 events: []tcell.Event{ 1961 tcell.NewEventKey(tcell.KeyRune, 'y', tcell.ModNone), 1962 tcell.NewEventKey(tcell.KeyRune, 'i', tcell.ModNone), 1963 tcell.NewEventKey(tcell.KeyRune, 'w', tcell.ModNone), 1964 tcell.NewEventKey(tcell.KeyEsc, '\x00', tcell.ModNone), 1965 tcell.NewEventKey(tcell.KeyRune, 'o', tcell.ModNone), 1966 tcell.NewEventKey(tcell.KeyEsc, '\x00', tcell.ModNone), 1967 tcell.NewEventKey(tcell.KeyRune, 'p', tcell.ModNone), 1968 }, 1969 expectedCursorPos: 22, 1970 expectedText: "Lorem ipsum dolor\nLorem\nsit amet consectetur\nadipiscing elit", 1971 }, 1972 { 1973 name: "yank inner word with count", 1974 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 1975 events: []tcell.Event{ 1976 tcell.NewEventKey(tcell.KeyRune, '3', tcell.ModNone), 1977 tcell.NewEventKey(tcell.KeyRune, 'y', tcell.ModNone), 1978 tcell.NewEventKey(tcell.KeyRune, 'i', tcell.ModNone), 1979 tcell.NewEventKey(tcell.KeyRune, 'w', tcell.ModNone), 1980 tcell.NewEventKey(tcell.KeyEsc, '\x00', tcell.ModNone), 1981 tcell.NewEventKey(tcell.KeyRune, 'o', tcell.ModNone), 1982 tcell.NewEventKey(tcell.KeyEsc, '\x00', tcell.ModNone), 1983 tcell.NewEventKey(tcell.KeyRune, 'p', tcell.ModNone), 1984 }, 1985 expectedCursorPos: 28, 1986 expectedText: "Lorem ipsum dolor\nLorem ipsum\nsit amet consectetur\nadipiscing elit", 1987 }, 1988 { 1989 name: "yank inner string block with double-quote", 1990 initialText: `"abc" x`, 1991 events: []tcell.Event{ 1992 tcell.NewEventKey(tcell.KeyRune, 'y', tcell.ModNone), 1993 tcell.NewEventKey(tcell.KeyRune, 'i', tcell.ModNone), 1994 tcell.NewEventKey(tcell.KeyRune, '"', tcell.ModNone), 1995 tcell.NewEventKey(tcell.KeyRune, 'o', tcell.ModNone), 1996 tcell.NewEventKey(tcell.KeyEsc, '\x00', tcell.ModNone), 1997 tcell.NewEventKey(tcell.KeyRune, 'p', tcell.ModNone), 1998 }, 1999 expectedCursorPos: 10, 2000 expectedText: "\"abc\" x\nabc", 2001 }, 2002 { 2003 name: "yank a string block with double-quote", 2004 initialText: `"abc" x`, 2005 events: []tcell.Event{ 2006 tcell.NewEventKey(tcell.KeyRune, 'y', tcell.ModNone), 2007 tcell.NewEventKey(tcell.KeyRune, 'a', tcell.ModNone), 2008 tcell.NewEventKey(tcell.KeyRune, '"', tcell.ModNone), 2009 tcell.NewEventKey(tcell.KeyRune, 'o', tcell.ModNone), 2010 tcell.NewEventKey(tcell.KeyEsc, '\x00', tcell.ModNone), 2011 tcell.NewEventKey(tcell.KeyRune, 'p', tcell.ModNone), 2012 }, 2013 expectedCursorPos: 12, 2014 expectedText: "\"abc\" x\n\"abc\"", 2015 }, 2016 { 2017 name: "yank inner string block with single-quote", 2018 initialText: `'abc' x`, 2019 events: []tcell.Event{ 2020 tcell.NewEventKey(tcell.KeyRune, 'y', tcell.ModNone), 2021 tcell.NewEventKey(tcell.KeyRune, 'i', tcell.ModNone), 2022 tcell.NewEventKey(tcell.KeyRune, '\'', tcell.ModNone), 2023 tcell.NewEventKey(tcell.KeyRune, 'o', tcell.ModNone), 2024 tcell.NewEventKey(tcell.KeyEsc, '\x00', tcell.ModNone), 2025 tcell.NewEventKey(tcell.KeyRune, 'p', tcell.ModNone), 2026 }, 2027 expectedCursorPos: 10, 2028 expectedText: "'abc' x\nabc", 2029 }, 2030 { 2031 name: "yank a string block with single-quote", 2032 initialText: `'abc' x`, 2033 events: []tcell.Event{ 2034 tcell.NewEventKey(tcell.KeyRune, 'y', tcell.ModNone), 2035 tcell.NewEventKey(tcell.KeyRune, 'a', tcell.ModNone), 2036 tcell.NewEventKey(tcell.KeyRune, '\'', tcell.ModNone), 2037 tcell.NewEventKey(tcell.KeyRune, 'o', tcell.ModNone), 2038 tcell.NewEventKey(tcell.KeyEsc, '\x00', tcell.ModNone), 2039 tcell.NewEventKey(tcell.KeyRune, 'p', tcell.ModNone), 2040 }, 2041 expectedCursorPos: 12, 2042 expectedText: "'abc' x\n'abc'", 2043 }, 2044 { 2045 name: "yank inner string block with backtick-quote", 2046 initialText: "`abc` x", 2047 events: []tcell.Event{ 2048 tcell.NewEventKey(tcell.KeyRune, 'y', tcell.ModNone), 2049 tcell.NewEventKey(tcell.KeyRune, 'i', tcell.ModNone), 2050 tcell.NewEventKey(tcell.KeyRune, '`', tcell.ModNone), 2051 tcell.NewEventKey(tcell.KeyRune, 'o', tcell.ModNone), 2052 tcell.NewEventKey(tcell.KeyEsc, '\x00', tcell.ModNone), 2053 tcell.NewEventKey(tcell.KeyRune, 'p', tcell.ModNone), 2054 }, 2055 expectedCursorPos: 10, 2056 expectedText: "`abc` x\nabc", 2057 }, 2058 { 2059 name: "yank a string block with backtick-quote", 2060 initialText: "`abc` x", 2061 events: []tcell.Event{ 2062 tcell.NewEventKey(tcell.KeyRune, 'y', tcell.ModNone), 2063 tcell.NewEventKey(tcell.KeyRune, 'a', tcell.ModNone), 2064 tcell.NewEventKey(tcell.KeyRune, '`', tcell.ModNone), 2065 tcell.NewEventKey(tcell.KeyRune, 'o', tcell.ModNone), 2066 tcell.NewEventKey(tcell.KeyEsc, '\x00', tcell.ModNone), 2067 tcell.NewEventKey(tcell.KeyRune, 'p', tcell.ModNone), 2068 }, 2069 expectedCursorPos: 12, 2070 expectedText: "`abc` x\n`abc`", 2071 }, 2072 { 2073 name: "yank line", 2074 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 2075 events: []tcell.Event{ 2076 tcell.NewEventKey(tcell.KeyRune, 'y', tcell.ModNone), 2077 tcell.NewEventKey(tcell.KeyRune, 'y', tcell.ModNone), 2078 tcell.NewEventKey(tcell.KeyRune, 'p', tcell.ModNone), 2079 }, 2080 expectedCursorPos: 18, 2081 expectedText: "Lorem ipsum dolor\nLorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 2082 }, 2083 { 2084 name: "yank to next matching character in line", 2085 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 2086 events: []tcell.Event{ 2087 tcell.NewEventKey(tcell.KeyRune, 'y', tcell.ModNone), 2088 tcell.NewEventKey(tcell.KeyRune, 'f', tcell.ModNone), 2089 tcell.NewEventKey(tcell.KeyRune, 'e', tcell.ModNone), 2090 tcell.NewEventKey(tcell.KeyRune, 'o', tcell.ModNone), 2091 tcell.NewEventKey(tcell.KeyEsc, '\x00', tcell.ModNone), 2092 tcell.NewEventKey(tcell.KeyRune, 'p', tcell.ModNone), 2093 }, 2094 expectedCursorPos: 21, 2095 expectedText: "Lorem ipsum dolor\nLore\nsit amet consectetur\nadipiscing elit", 2096 }, 2097 { 2098 name: "yank to prev matching character in line", 2099 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 2100 events: []tcell.Event{ 2101 tcell.NewEventKey(tcell.KeyRune, '$', tcell.ModNone), 2102 tcell.NewEventKey(tcell.KeyRune, 'y', tcell.ModNone), 2103 tcell.NewEventKey(tcell.KeyRune, 'F', tcell.ModNone), 2104 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 2105 tcell.NewEventKey(tcell.KeyRune, 'o', tcell.ModNone), 2106 tcell.NewEventKey(tcell.KeyEsc, '\x00', tcell.ModNone), 2107 tcell.NewEventKey(tcell.KeyRune, 'p', tcell.ModNone), 2108 }, 2109 expectedCursorPos: 19, 2110 expectedText: "Lorem ipsum dolor\nlo\nsit amet consectetur\nadipiscing elit", 2111 }, 2112 { 2113 name: "yank till next matching character in line", 2114 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 2115 events: []tcell.Event{ 2116 tcell.NewEventKey(tcell.KeyRune, 'y', tcell.ModNone), 2117 tcell.NewEventKey(tcell.KeyRune, 't', tcell.ModNone), 2118 tcell.NewEventKey(tcell.KeyRune, 'e', tcell.ModNone), 2119 tcell.NewEventKey(tcell.KeyRune, 'o', tcell.ModNone), 2120 tcell.NewEventKey(tcell.KeyEsc, '\x00', tcell.ModNone), 2121 tcell.NewEventKey(tcell.KeyRune, 'p', tcell.ModNone), 2122 }, 2123 expectedCursorPos: 20, 2124 expectedText: "Lorem ipsum dolor\nLor\nsit amet consectetur\nadipiscing elit", 2125 }, 2126 { 2127 name: "yank till prev matching character in line", 2128 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 2129 events: []tcell.Event{ 2130 tcell.NewEventKey(tcell.KeyRune, '$', tcell.ModNone), 2131 tcell.NewEventKey(tcell.KeyRune, 'y', tcell.ModNone), 2132 tcell.NewEventKey(tcell.KeyRune, 'T', tcell.ModNone), 2133 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 2134 tcell.NewEventKey(tcell.KeyRune, 'o', tcell.ModNone), 2135 tcell.NewEventKey(tcell.KeyEsc, '\x00', tcell.ModNone), 2136 tcell.NewEventKey(tcell.KeyRune, 'p', tcell.ModNone), 2137 }, 2138 expectedCursorPos: 18, 2139 expectedText: "Lorem ipsum dolor\no\nsit amet consectetur\nadipiscing elit", 2140 }, 2141 { 2142 name: "put before cursor", 2143 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 2144 events: []tcell.Event{ 2145 tcell.NewEventKey(tcell.KeyRune, 'y', tcell.ModNone), 2146 tcell.NewEventKey(tcell.KeyRune, 'a', tcell.ModNone), 2147 tcell.NewEventKey(tcell.KeyRune, 'w', tcell.ModNone), 2148 tcell.NewEventKey(tcell.KeyRune, 'P', tcell.ModNone), 2149 }, 2150 expectedCursorPos: 5, 2151 expectedText: "Lorem Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 2152 }, 2153 { 2154 name: "search forward", 2155 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 2156 events: []tcell.Event{ 2157 tcell.NewEventKey(tcell.KeyRune, '/', tcell.ModNone), 2158 tcell.NewEventKey(tcell.KeyRune, 'c', tcell.ModNone), 2159 tcell.NewEventKey(tcell.KeyRune, 'o', tcell.ModNone), 2160 tcell.NewEventKey(tcell.KeyRune, 'n', tcell.ModNone), 2161 tcell.NewEventKey(tcell.KeyEnter, '\r', tcell.ModNone), 2162 }, 2163 expectedCursorPos: 27, 2164 expectedText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 2165 }, 2166 { 2167 name: "search backward", 2168 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 2169 events: []tcell.Event{ 2170 tcell.NewEventKey(tcell.KeyRune, 'j', tcell.ModNone), 2171 tcell.NewEventKey(tcell.KeyRune, 'j', tcell.ModNone), 2172 tcell.NewEventKey(tcell.KeyRune, '?', tcell.ModNone), 2173 tcell.NewEventKey(tcell.KeyRune, 'o', tcell.ModNone), 2174 tcell.NewEventKey(tcell.KeyRune, 'r', tcell.ModNone), 2175 tcell.NewEventKey(tcell.KeyEnter, '\r', tcell.ModNone), 2176 }, 2177 expectedCursorPos: 15, 2178 expectedText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 2179 }, 2180 { 2181 name: "find next match", 2182 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 2183 events: []tcell.Event{ 2184 tcell.NewEventKey(tcell.KeyRune, '/', tcell.ModNone), 2185 tcell.NewEventKey(tcell.KeyRune, 'm', tcell.ModNone), 2186 tcell.NewEventKey(tcell.KeyEnter, '\r', tcell.ModNone), 2187 tcell.NewEventKey(tcell.KeyRune, 'n', tcell.ModNone), 2188 tcell.NewEventKey(tcell.KeyRune, 'n', tcell.ModNone), 2189 }, 2190 expectedCursorPos: 23, 2191 expectedText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 2192 }, 2193 { 2194 name: "find prev match", 2195 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 2196 events: []tcell.Event{ 2197 tcell.NewEventKey(tcell.KeyRune, 'j', tcell.ModNone), 2198 tcell.NewEventKey(tcell.KeyRune, 'j', tcell.ModNone), 2199 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 2200 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 2201 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 2202 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 2203 tcell.NewEventKey(tcell.KeyRune, '/', tcell.ModNone), 2204 tcell.NewEventKey(tcell.KeyRune, 't', tcell.ModNone), 2205 tcell.NewEventKey(tcell.KeyEnter, '\r', tcell.ModNone), 2206 tcell.NewEventKey(tcell.KeyRune, 'N', tcell.ModNone), 2207 tcell.NewEventKey(tcell.KeyRune, 'N', tcell.ModNone), 2208 }, 2209 expectedCursorPos: 33, 2210 expectedText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 2211 }, 2212 { 2213 name: "search forward for word under cursor", 2214 initialText: "Lorem ipsum dolor\nsit amet consectetur\nlorem ipsum dolor", 2215 events: []tcell.Event{ 2216 tcell.NewEventKey(tcell.KeyRune, 'w', tcell.ModNone), 2217 tcell.NewEventKey(tcell.KeyRune, '*', tcell.ModNone), 2218 }, 2219 expectedCursorPos: 45, 2220 expectedText: "Lorem ipsum dolor\nsit amet consectetur\nlorem ipsum dolor", 2221 }, 2222 { 2223 name: "search backward for word under cursor", 2224 initialText: "Lorem ipsum dolor\nsit amet consectetur\nlorem ipsum dolor", 2225 events: []tcell.Event{ 2226 tcell.NewEventKey(tcell.KeyRune, 'j', tcell.ModNone), 2227 tcell.NewEventKey(tcell.KeyRune, 'j', tcell.ModNone), 2228 tcell.NewEventKey(tcell.KeyRune, 'w', tcell.ModNone), 2229 tcell.NewEventKey(tcell.KeyRune, '#', tcell.ModNone), 2230 }, 2231 expectedCursorPos: 6, 2232 expectedText: "Lorem ipsum dolor\nsit amet consectetur\nlorem ipsum dolor", 2233 }, 2234 { 2235 name: "search forward and delete", 2236 initialText: "Lorem ipsum dolor\nsit amet consectetur\nlorem ipsum dolor", 2237 events: []tcell.Event{ 2238 tcell.NewEventKey(tcell.KeyRune, 'd', tcell.ModNone), 2239 tcell.NewEventKey(tcell.KeyRune, '/', tcell.ModNone), 2240 tcell.NewEventKey(tcell.KeyRune, 'd', tcell.ModNone), 2241 tcell.NewEventKey(tcell.KeyRune, 'o', tcell.ModNone), 2242 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 2243 tcell.NewEventKey(tcell.KeyEnter, '\x00', tcell.ModNone), 2244 }, 2245 expectedCursorPos: 0, 2246 expectedText: "dolor\nsit amet consectetur\nlorem ipsum dolor", 2247 }, 2248 { 2249 name: "search backward and delete", 2250 initialText: "Lorem ipsum dolor\nsit amet consectetur\nlorem ipsum dolor", 2251 events: []tcell.Event{ 2252 tcell.NewEventKey(tcell.KeyRune, 'j', tcell.ModNone), 2253 tcell.NewEventKey(tcell.KeyRune, '$', tcell.ModNone), 2254 tcell.NewEventKey(tcell.KeyRune, 'd', tcell.ModNone), 2255 tcell.NewEventKey(tcell.KeyRune, '?', tcell.ModNone), 2256 tcell.NewEventKey(tcell.KeyRune, 'd', tcell.ModNone), 2257 tcell.NewEventKey(tcell.KeyRune, 'o', tcell.ModNone), 2258 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 2259 tcell.NewEventKey(tcell.KeyEnter, '\x00', tcell.ModNone), 2260 }, 2261 expectedCursorPos: 15, 2262 expectedText: "Lorem ipsum dolr\nlorem ipsum dolor", 2263 }, 2264 { 2265 name: "search and delete to clipboard then paste", 2266 initialText: "Lorem ipsum dolor\nsit amet consectetur\nlorem ipsum dolor", 2267 events: []tcell.Event{ 2268 tcell.NewEventKey(tcell.KeyRune, '"', tcell.ModNone), 2269 tcell.NewEventKey(tcell.KeyRune, 'a', tcell.ModNone), 2270 tcell.NewEventKey(tcell.KeyRune, 'd', tcell.ModNone), 2271 tcell.NewEventKey(tcell.KeyRune, '/', tcell.ModNone), 2272 tcell.NewEventKey(tcell.KeyRune, 'd', tcell.ModNone), 2273 tcell.NewEventKey(tcell.KeyRune, 'o', tcell.ModNone), 2274 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 2275 tcell.NewEventKey(tcell.KeyEnter, '\x00', tcell.ModNone), 2276 tcell.NewEventKey(tcell.KeyRune, 'G', tcell.ModNone), 2277 tcell.NewEventKey(tcell.KeyRune, '"', tcell.ModNone), 2278 tcell.NewEventKey(tcell.KeyRune, 'a', tcell.ModNone), 2279 tcell.NewEventKey(tcell.KeyRune, 'P', tcell.ModNone), 2280 }, 2281 expectedCursorPos: 38, 2282 expectedText: "dolor\nsit amet consectetur\nLorem ipsum lorem ipsum dolor", 2283 }, 2284 { 2285 name: "search and delete then undo", 2286 initialText: "Lorem ipsum dolor\nsit amet consectetur\nlorem ipsum dolor", 2287 events: []tcell.Event{ 2288 tcell.NewEventKey(tcell.KeyRune, 'D', tcell.ModNone), 2289 tcell.NewEventKey(tcell.KeyRune, 'd', tcell.ModNone), 2290 tcell.NewEventKey(tcell.KeyRune, '/', tcell.ModNone), 2291 tcell.NewEventKey(tcell.KeyRune, 'c', tcell.ModNone), 2292 tcell.NewEventKey(tcell.KeyRune, 'o', tcell.ModNone), 2293 tcell.NewEventKey(tcell.KeyRune, 'n', tcell.ModNone), 2294 tcell.NewEventKey(tcell.KeyEnter, '\x00', tcell.ModNone), 2295 tcell.NewEventKey(tcell.KeyRune, 'u', tcell.ModNone), 2296 }, 2297 expectedCursorPos: 0, 2298 expectedText: "\nsit amet consectetur\nlorem ipsum dolor", 2299 }, 2300 { 2301 name: "search and delete then replay last action", 2302 initialText: "abc xyz\nabc xyz 123\nabc xyz 456", 2303 events: []tcell.Event{ 2304 tcell.NewEventKey(tcell.KeyRune, 'd', tcell.ModNone), 2305 tcell.NewEventKey(tcell.KeyRune, '/', tcell.ModNone), 2306 tcell.NewEventKey(tcell.KeyRune, 'x', tcell.ModNone), 2307 tcell.NewEventKey(tcell.KeyRune, 'y', tcell.ModNone), 2308 tcell.NewEventKey(tcell.KeyEnter, '\x00', tcell.ModNone), 2309 tcell.NewEventKey(tcell.KeyRune, 'j', tcell.ModNone), 2310 tcell.NewEventKey(tcell.KeyRune, '.', tcell.ModNone), 2311 tcell.NewEventKey(tcell.KeyRune, '/', tcell.ModNone), 2312 tcell.NewEventKey(tcell.KeyRune, 'a', tcell.ModNone), 2313 tcell.NewEventKey(tcell.KeyEnter, '\x00', tcell.ModNone), 2314 tcell.NewEventKey(tcell.KeyRune, 'j', tcell.ModNone), 2315 tcell.NewEventKey(tcell.KeyRune, '.', tcell.ModNone), 2316 }, 2317 expectedCursorPos: 12, 2318 expectedText: "xyz\nxyz 123\nxyz 456", 2319 }, 2320 { 2321 name: "search and delete in user macro then replay", 2322 initialText: "abc xyz\nabc xyz 123\nabc xyz 456", 2323 events: []tcell.Event{ 2324 tcell.NewEventKey(tcell.KeyRune, ':', tcell.ModNone), 2325 tcell.NewEventKey(tcell.KeyRune, 's', tcell.ModNone), 2326 tcell.NewEventKey(tcell.KeyRune, 't', tcell.ModNone), 2327 tcell.NewEventKey(tcell.KeyRune, 'a', tcell.ModNone), 2328 tcell.NewEventKey(tcell.KeyRune, 'r', tcell.ModNone), 2329 tcell.NewEventKey(tcell.KeyRune, 't', tcell.ModNone), 2330 tcell.NewEventKey(tcell.KeyEnter, '\r', tcell.ModNone), 2331 tcell.NewEventKey(tcell.KeyRune, 'd', tcell.ModNone), 2332 tcell.NewEventKey(tcell.KeyRune, '/', tcell.ModNone), 2333 tcell.NewEventKey(tcell.KeyRune, 'x', tcell.ModNone), 2334 tcell.NewEventKey(tcell.KeyRune, 'y', tcell.ModNone), 2335 tcell.NewEventKey(tcell.KeyEnter, '\r', tcell.ModNone), 2336 tcell.NewEventKey(tcell.KeyRune, ':', tcell.ModNone), 2337 tcell.NewEventKey(tcell.KeyRune, 's', tcell.ModNone), 2338 tcell.NewEventKey(tcell.KeyRune, 't', tcell.ModNone), 2339 tcell.NewEventKey(tcell.KeyRune, 'o', tcell.ModNone), 2340 tcell.NewEventKey(tcell.KeyRune, 'p', tcell.ModNone), 2341 tcell.NewEventKey(tcell.KeyEnter, '\r', tcell.ModNone), 2342 tcell.NewEventKey(tcell.KeyRune, ':', tcell.ModNone), 2343 tcell.NewEventKey(tcell.KeyRune, 'r', tcell.ModNone), 2344 tcell.NewEventKey(tcell.KeyRune, 'e', tcell.ModNone), 2345 tcell.NewEventKey(tcell.KeyRune, 'p', tcell.ModNone), 2346 tcell.NewEventKey(tcell.KeyEnter, '\r', tcell.ModNone), 2347 }, 2348 expectedCursorPos: 0, 2349 expectedText: "xyz 123\nabc xyz 456", 2350 }, 2351 { 2352 name: "search forward and change", 2353 initialText: "abc xyz 123", 2354 events: []tcell.Event{ 2355 tcell.NewEventKey(tcell.KeyRune, 'c', tcell.ModNone), 2356 tcell.NewEventKey(tcell.KeyRune, '/', tcell.ModNone), 2357 tcell.NewEventKey(tcell.KeyRune, 'x', tcell.ModNone), 2358 tcell.NewEventKey(tcell.KeyRune, 'y', tcell.ModNone), 2359 tcell.NewEventKey(tcell.KeyEnter, '\r', tcell.ModNone), 2360 tcell.NewEventKey(tcell.KeyRune, 'f', tcell.ModNone), 2361 tcell.NewEventKey(tcell.KeyRune, 'o', tcell.ModNone), 2362 tcell.NewEventKey(tcell.KeyRune, 'o', tcell.ModNone), 2363 tcell.NewEventKey(tcell.KeyEscape, '\x00', tcell.ModNone), 2364 }, 2365 expectedCursorPos: 2, 2366 expectedText: "fooxyz 123", 2367 }, 2368 { 2369 name: "search backward and change", 2370 initialText: "abc xyz 123", 2371 events: []tcell.Event{ 2372 tcell.NewEventKey(tcell.KeyRune, '$', tcell.ModNone), 2373 tcell.NewEventKey(tcell.KeyRune, 'c', tcell.ModNone), 2374 tcell.NewEventKey(tcell.KeyRune, '?', tcell.ModNone), 2375 tcell.NewEventKey(tcell.KeyRune, 'x', tcell.ModNone), 2376 tcell.NewEventKey(tcell.KeyRune, 'y', tcell.ModNone), 2377 tcell.NewEventKey(tcell.KeyEnter, '\r', tcell.ModNone), 2378 tcell.NewEventKey(tcell.KeyRune, 'f', tcell.ModNone), 2379 tcell.NewEventKey(tcell.KeyRune, 'o', tcell.ModNone), 2380 tcell.NewEventKey(tcell.KeyRune, 'o', tcell.ModNone), 2381 tcell.NewEventKey(tcell.KeyEscape, '\x00', tcell.ModNone), 2382 }, 2383 expectedCursorPos: 8, 2384 expectedText: "abc xyfoo3", 2385 }, 2386 { 2387 name: "search and change then replay last action", 2388 initialText: "abc xyz 123\nabc xyz 123\nabc xyz 123", 2389 events: []tcell.Event{ 2390 tcell.NewEventKey(tcell.KeyRune, 'c', tcell.ModNone), 2391 tcell.NewEventKey(tcell.KeyRune, '/', tcell.ModNone), 2392 tcell.NewEventKey(tcell.KeyRune, 'x', tcell.ModNone), 2393 tcell.NewEventKey(tcell.KeyRune, 'y', tcell.ModNone), 2394 tcell.NewEventKey(tcell.KeyEnter, '\r', tcell.ModNone), 2395 tcell.NewEventKey(tcell.KeyRune, 'f', tcell.ModNone), 2396 tcell.NewEventKey(tcell.KeyRune, 'o', tcell.ModNone), 2397 tcell.NewEventKey(tcell.KeyRune, 'o', tcell.ModNone), 2398 tcell.NewEventKey(tcell.KeyEscape, '\x00', tcell.ModNone), 2399 tcell.NewEventKey(tcell.KeyRune, 'j', tcell.ModNone), 2400 tcell.NewEventKey(tcell.KeyRune, '^', tcell.ModNone), 2401 tcell.NewEventKey(tcell.KeyRune, '.', tcell.ModNone), 2402 tcell.NewEventKey(tcell.KeyRune, 'j', tcell.ModNone), 2403 tcell.NewEventKey(tcell.KeyRune, '^', tcell.ModNone), 2404 tcell.NewEventKey(tcell.KeyRune, '.', tcell.ModNone), 2405 }, 2406 expectedCursorPos: 24, 2407 expectedText: "fooxyz 123\nfooxyz 123\nfooxyz 123", 2408 }, 2409 { 2410 name: "search forward and yank", 2411 initialText: "abc xyz 123", 2412 events: []tcell.Event{ 2413 tcell.NewEventKey(tcell.KeyRune, 'y', tcell.ModNone), 2414 tcell.NewEventKey(tcell.KeyRune, '/', tcell.ModNone), 2415 tcell.NewEventKey(tcell.KeyRune, 'x', tcell.ModNone), 2416 tcell.NewEventKey(tcell.KeyRune, 'y', tcell.ModNone), 2417 tcell.NewEventKey(tcell.KeyEnter, '\r', tcell.ModNone), 2418 tcell.NewEventKey(tcell.KeyRune, 'p', tcell.ModNone), 2419 }, 2420 expectedCursorPos: 4, 2421 expectedText: "aabc bc xyz 123", 2422 }, 2423 { 2424 name: "search forward and yank to clipboard", 2425 initialText: "abc xyz 123", 2426 events: []tcell.Event{ 2427 tcell.NewEventKey(tcell.KeyRune, '"', tcell.ModNone), 2428 tcell.NewEventKey(tcell.KeyRune, 'a', tcell.ModNone), 2429 tcell.NewEventKey(tcell.KeyRune, 'y', tcell.ModNone), 2430 tcell.NewEventKey(tcell.KeyRune, '/', tcell.ModNone), 2431 tcell.NewEventKey(tcell.KeyRune, 'x', tcell.ModNone), 2432 tcell.NewEventKey(tcell.KeyRune, 'y', tcell.ModNone), 2433 tcell.NewEventKey(tcell.KeyEnter, '\r', tcell.ModNone), 2434 tcell.NewEventKey(tcell.KeyRune, '"', tcell.ModNone), 2435 tcell.NewEventKey(tcell.KeyRune, 'a', tcell.ModNone), 2436 tcell.NewEventKey(tcell.KeyRune, 'p', tcell.ModNone), 2437 }, 2438 expectedCursorPos: 4, 2439 expectedText: "aabc bc xyz 123", 2440 }, 2441 { 2442 name: "search backward and yank", 2443 initialText: "abc xyz 123", 2444 events: []tcell.Event{ 2445 tcell.NewEventKey(tcell.KeyRune, '$', tcell.ModNone), 2446 tcell.NewEventKey(tcell.KeyRune, 'y', tcell.ModNone), 2447 tcell.NewEventKey(tcell.KeyRune, '?', tcell.ModNone), 2448 tcell.NewEventKey(tcell.KeyRune, 'x', tcell.ModNone), 2449 tcell.NewEventKey(tcell.KeyRune, 'y', tcell.ModNone), 2450 tcell.NewEventKey(tcell.KeyEnter, '\r', tcell.ModNone), 2451 tcell.NewEventKey(tcell.KeyRune, 'P', tcell.ModNone), 2452 }, 2453 expectedCursorPos: 13, 2454 expectedText: "abc xyz 12z 123", 2455 }, 2456 { 2457 name: "search backward and yank to clipboard", 2458 initialText: "abc xyz 123", 2459 events: []tcell.Event{ 2460 tcell.NewEventKey(tcell.KeyRune, '$', tcell.ModNone), 2461 tcell.NewEventKey(tcell.KeyRune, '"', tcell.ModNone), 2462 tcell.NewEventKey(tcell.KeyRune, 'a', tcell.ModNone), 2463 tcell.NewEventKey(tcell.KeyRune, 'y', tcell.ModNone), 2464 tcell.NewEventKey(tcell.KeyRune, '?', tcell.ModNone), 2465 tcell.NewEventKey(tcell.KeyRune, 'x', tcell.ModNone), 2466 tcell.NewEventKey(tcell.KeyRune, 'y', tcell.ModNone), 2467 tcell.NewEventKey(tcell.KeyEnter, '\r', tcell.ModNone), 2468 tcell.NewEventKey(tcell.KeyRune, '"', tcell.ModNone), 2469 tcell.NewEventKey(tcell.KeyRune, 'a', tcell.ModNone), 2470 tcell.NewEventKey(tcell.KeyRune, 'P', tcell.ModNone), 2471 }, 2472 expectedCursorPos: 13, 2473 expectedText: "abc xyz 12z 123", 2474 }, 2475 { 2476 name: "previous search query in history", 2477 initialText: "Lorem ipsum dolor\nsit amet consectetur\nlorem ipsum dolor", 2478 events: []tcell.Event{ 2479 tcell.NewEventKey(tcell.KeyRune, '/', tcell.ModNone), 2480 tcell.NewEventKey(tcell.KeyRune, 'a', tcell.ModNone), 2481 tcell.NewEventKey(tcell.KeyRune, 'm', tcell.ModNone), 2482 tcell.NewEventKey(tcell.KeyEnter, '\x00', tcell.ModNone), 2483 tcell.NewEventKey(tcell.KeyRune, '/', tcell.ModNone), 2484 tcell.NewEventKey(tcell.KeyRune, 'd', tcell.ModNone), 2485 tcell.NewEventKey(tcell.KeyRune, 'o', tcell.ModNone), 2486 tcell.NewEventKey(tcell.KeyEnter, '\x00', tcell.ModNone), 2487 tcell.NewEventKey(tcell.KeyRune, '/', tcell.ModNone), 2488 tcell.NewEventKey(tcell.KeyUp, '\x00', tcell.ModNone), 2489 tcell.NewEventKey(tcell.KeyUp, '\x00', tcell.ModNone), 2490 tcell.NewEventKey(tcell.KeyEnter, '\x00', tcell.ModNone), 2491 }, 2492 expectedCursorPos: 22, 2493 expectedText: "Lorem ipsum dolor\nsit amet consectetur\nlorem ipsum dolor", 2494 }, 2495 { 2496 name: "next search query in history", 2497 initialText: "Lorem ipsum dolor\nsit amet consectetur\nlorem ipsum dolor", 2498 events: []tcell.Event{ 2499 tcell.NewEventKey(tcell.KeyRune, '/', tcell.ModNone), 2500 tcell.NewEventKey(tcell.KeyRune, 'a', tcell.ModNone), 2501 tcell.NewEventKey(tcell.KeyRune, 'm', tcell.ModNone), 2502 tcell.NewEventKey(tcell.KeyEscape, '\x00', tcell.ModNone), 2503 tcell.NewEventKey(tcell.KeyRune, '/', tcell.ModNone), 2504 tcell.NewEventKey(tcell.KeyRune, 'd', tcell.ModNone), 2505 tcell.NewEventKey(tcell.KeyRune, 'o', tcell.ModNone), 2506 tcell.NewEventKey(tcell.KeyEscape, '\x00', tcell.ModNone), 2507 tcell.NewEventKey(tcell.KeyRune, '/', tcell.ModNone), 2508 tcell.NewEventKey(tcell.KeyRune, 's', tcell.ModNone), 2509 tcell.NewEventKey(tcell.KeyRune, 'i', tcell.ModNone), 2510 tcell.NewEventKey(tcell.KeyEscape, '\x00', tcell.ModNone), 2511 tcell.NewEventKey(tcell.KeyRune, '/', tcell.ModNone), 2512 tcell.NewEventKey(tcell.KeyUp, '\x00', tcell.ModNone), 2513 tcell.NewEventKey(tcell.KeyUp, '\x00', tcell.ModNone), 2514 tcell.NewEventKey(tcell.KeyUp, '\x00', tcell.ModNone), 2515 tcell.NewEventKey(tcell.KeyDown, '\x00', tcell.ModNone), 2516 tcell.NewEventKey(tcell.KeyEnter, '\x00', tcell.ModNone), 2517 }, 2518 expectedCursorPos: 12, 2519 expectedText: "Lorem ipsum dolor\nsit amet consectetur\nlorem ipsum dolor", 2520 }, 2521 { 2522 name: "undo", 2523 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 2524 events: []tcell.Event{ 2525 tcell.NewEventKey(tcell.KeyRune, 'i', tcell.ModNone), 2526 tcell.NewEventKey(tcell.KeyRune, 't', tcell.ModNone), 2527 tcell.NewEventKey(tcell.KeyRune, 'e', tcell.ModNone), 2528 tcell.NewEventKey(tcell.KeyRune, 's', tcell.ModNone), 2529 tcell.NewEventKey(tcell.KeyRune, 't', tcell.ModNone), 2530 tcell.NewEventKey(tcell.KeyRune, ' ', tcell.ModNone), 2531 tcell.NewEventKey(tcell.KeyEsc, '\x00', tcell.ModNone), 2532 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 2533 tcell.NewEventKey(tcell.KeyRune, 'c', tcell.ModNone), 2534 tcell.NewEventKey(tcell.KeyRune, 'i', tcell.ModNone), 2535 tcell.NewEventKey(tcell.KeyRune, 'w', tcell.ModNone), 2536 tcell.NewEventKey(tcell.KeyRune, 'f', tcell.ModNone), 2537 tcell.NewEventKey(tcell.KeyRune, 'o', tcell.ModNone), 2538 tcell.NewEventKey(tcell.KeyRune, 'o', tcell.ModNone), 2539 tcell.NewEventKey(tcell.KeyEsc, '\x00', tcell.ModNone), 2540 tcell.NewEventKey(tcell.KeyRune, 'u', tcell.ModNone), 2541 }, 2542 expectedCursorPos: 5, 2543 expectedText: "test Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 2544 }, 2545 { 2546 name: "redo", 2547 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 2548 events: []tcell.Event{ 2549 tcell.NewEventKey(tcell.KeyRune, 'j', tcell.ModNone), 2550 tcell.NewEventKey(tcell.KeyRune, 'd', tcell.ModNone), 2551 tcell.NewEventKey(tcell.KeyRune, 'd', tcell.ModNone), 2552 tcell.NewEventKey(tcell.KeyRune, 'd', tcell.ModNone), 2553 tcell.NewEventKey(tcell.KeyRune, 'd', tcell.ModNone), 2554 tcell.NewEventKey(tcell.KeyRune, 'u', tcell.ModNone), 2555 tcell.NewEventKey(tcell.KeyCtrlR, '\x12', tcell.ModCtrl), 2556 }, 2557 expectedCursorPos: 0, 2558 expectedText: "Lorem ipsum dolor", 2559 }, 2560 { 2561 name: "repeat last action delete-a-word", 2562 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 2563 events: []tcell.Event{ 2564 tcell.NewEventKey(tcell.KeyRune, 'd', tcell.ModNone), 2565 tcell.NewEventKey(tcell.KeyRune, 'a', tcell.ModNone), 2566 tcell.NewEventKey(tcell.KeyRune, 'w', tcell.ModNone), 2567 tcell.NewEventKey(tcell.KeyRune, '.', tcell.ModNone), 2568 }, 2569 expectedCursorPos: 0, 2570 expectedText: "dolor\nsit amet consectetur\nadipiscing elit", 2571 }, 2572 { 2573 name: "visual linewise delete", 2574 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 2575 events: []tcell.Event{ 2576 tcell.NewEventKey(tcell.KeyRune, 'V', tcell.ModNone), 2577 tcell.NewEventKey(tcell.KeyRune, 'j', tcell.ModNone), 2578 tcell.NewEventKey(tcell.KeyRune, 'd', tcell.ModNone), 2579 }, 2580 expectedCursorPos: 0, 2581 expectedText: "adipiscing elit", 2582 }, 2583 { 2584 name: "visual linewise delete all lines", 2585 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 2586 events: []tcell.Event{ 2587 tcell.NewEventKey(tcell.KeyRune, 'V', tcell.ModNone), 2588 tcell.NewEventKey(tcell.KeyRune, 'G', tcell.ModNone), 2589 tcell.NewEventKey(tcell.KeyRune, 'd', tcell.ModNone), 2590 }, 2591 expectedCursorPos: 0, 2592 expectedText: "", 2593 }, 2594 { 2595 name: "visual charwise delete", 2596 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 2597 events: []tcell.Event{ 2598 tcell.NewEventKey(tcell.KeyRune, 'j', tcell.ModNone), 2599 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 2600 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 2601 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 2602 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 2603 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 2604 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 2605 tcell.NewEventKey(tcell.KeyRune, 'v', tcell.ModNone), 2606 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 2607 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 2608 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 2609 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 2610 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 2611 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 2612 tcell.NewEventKey(tcell.KeyRune, 'x', tcell.ModNone), 2613 }, 2614 expectedCursorPos: 24, 2615 expectedText: "Lorem ipsum dolor\nsit amectetur\nadipiscing elit", 2616 }, 2617 { 2618 name: "visual change selection", 2619 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 2620 events: []tcell.Event{ 2621 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 2622 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 2623 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 2624 tcell.NewEventKey(tcell.KeyRune, 'v', tcell.ModNone), 2625 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 2626 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 2627 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 2628 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 2629 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 2630 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 2631 tcell.NewEventKey(tcell.KeyRune, 'c', tcell.ModNone), 2632 tcell.NewEventKey(tcell.KeyRune, 'f', tcell.ModNone), 2633 tcell.NewEventKey(tcell.KeyRune, 'o', tcell.ModNone), 2634 tcell.NewEventKey(tcell.KeyRune, 'o', tcell.ModNone), 2635 tcell.NewEventKey(tcell.KeyRune, 'b', tcell.ModNone), 2636 tcell.NewEventKey(tcell.KeyRune, 'a', tcell.ModNone), 2637 tcell.NewEventKey(tcell.KeyRune, 'r', tcell.ModNone), 2638 tcell.NewEventKey(tcell.KeyEsc, '\x00', tcell.ModNone), 2639 }, 2640 expectedCursorPos: 8, 2641 expectedText: "Lorfoobarm dolor\nsit amet consectetur\nadipiscing elit", 2642 }, 2643 { 2644 name: "visual mode change case", 2645 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 2646 events: []tcell.Event{ 2647 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 2648 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 2649 tcell.NewEventKey(tcell.KeyRune, 'v', tcell.ModNone), 2650 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 2651 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 2652 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 2653 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 2654 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 2655 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 2656 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 2657 tcell.NewEventKey(tcell.KeyRune, '~', tcell.ModNone), 2658 }, 2659 expectedCursorPos: 2, 2660 expectedText: "LoREM IPSUm dolor\nsit amet consectetur\nadipiscing elit", 2661 }, 2662 { 2663 name: "visual mode indent with count", 2664 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 2665 events: []tcell.Event{ 2666 tcell.NewEventKey(tcell.KeyRune, 'j', tcell.ModNone), 2667 tcell.NewEventKey(tcell.KeyRune, 'V', tcell.ModNone), 2668 tcell.NewEventKey(tcell.KeyRune, 'j', tcell.ModNone), 2669 tcell.NewEventKey(tcell.KeyRune, '4', tcell.ModNone), 2670 tcell.NewEventKey(tcell.KeyRune, '>', tcell.ModNone), 2671 }, 2672 expectedCursorPos: 22, 2673 expectedText: "Lorem ipsum dolor\n\t\t\t\tsit amet consectetur\n\t\t\t\tadipiscing elit", 2674 }, 2675 { 2676 name: "visual mode indent, then repeat last action", 2677 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 2678 events: []tcell.Event{ 2679 tcell.NewEventKey(tcell.KeyRune, 'j', tcell.ModNone), 2680 tcell.NewEventKey(tcell.KeyRune, 'V', tcell.ModNone), 2681 tcell.NewEventKey(tcell.KeyRune, 'j', tcell.ModNone), 2682 tcell.NewEventKey(tcell.KeyRune, '>', tcell.ModNone), 2683 tcell.NewEventKey(tcell.KeyRune, '.', tcell.ModNone), 2684 }, 2685 expectedCursorPos: 20, 2686 expectedText: "Lorem ipsum dolor\n\t\tsit amet consectetur\n\t\tadipiscing elit", 2687 }, 2688 { 2689 name: "visual mode outdent", 2690 initialText: "Lorem ipsum dolor\n\tsit amet consectetur\n\t\tadipiscing\nelit\n\n", 2691 events: []tcell.Event{ 2692 tcell.NewEventKey(tcell.KeyRune, 'j', tcell.ModNone), 2693 tcell.NewEventKey(tcell.KeyRune, 'V', tcell.ModNone), 2694 tcell.NewEventKey(tcell.KeyRune, 'j', tcell.ModNone), 2695 tcell.NewEventKey(tcell.KeyRune, '<', tcell.ModNone), 2696 }, 2697 expectedCursorPos: 18, 2698 expectedText: "Lorem ipsum dolor\nsit amet consectetur\n\tadipiscing\nelit\n\n", 2699 }, 2700 { 2701 name: "visual mode outdent with count", 2702 initialText: "Lorem ipsum dolor\n\t\tsit amet consectetur\n\t\t\tadipiscing\nelit\n\n", 2703 events: []tcell.Event{ 2704 tcell.NewEventKey(tcell.KeyRune, 'j', tcell.ModNone), 2705 tcell.NewEventKey(tcell.KeyRune, 'V', tcell.ModNone), 2706 tcell.NewEventKey(tcell.KeyRune, 'j', tcell.ModNone), 2707 tcell.NewEventKey(tcell.KeyRune, '2', tcell.ModNone), 2708 tcell.NewEventKey(tcell.KeyRune, '<', tcell.ModNone), 2709 }, 2710 expectedCursorPos: 18, 2711 expectedText: "Lorem ipsum dolor\nsit amet consectetur\n\tadipiscing\nelit\n\n", 2712 }, 2713 { 2714 name: "visual mode yank", 2715 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 2716 events: []tcell.Event{ 2717 tcell.NewEventKey(tcell.KeyRune, 'V', tcell.ModNone), 2718 tcell.NewEventKey(tcell.KeyRune, 'j', tcell.ModNone), 2719 tcell.NewEventKey(tcell.KeyRune, 'y', tcell.ModNone), 2720 tcell.NewEventKey(tcell.KeyRune, 'j', tcell.ModNone), 2721 tcell.NewEventKey(tcell.KeyRune, 'j', tcell.ModNone), 2722 tcell.NewEventKey(tcell.KeyRune, 'p', tcell.ModNone), 2723 }, 2724 expectedCursorPos: 55, 2725 expectedText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit\nLorem ipsum dolor\nsit amet consectetur", 2726 }, 2727 { 2728 name: "visual mode yank to clipboard", 2729 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 2730 events: []tcell.Event{ 2731 tcell.NewEventKey(tcell.KeyRune, 'V', tcell.ModNone), 2732 tcell.NewEventKey(tcell.KeyRune, 'j', tcell.ModNone), 2733 tcell.NewEventKey(tcell.KeyRune, '"', tcell.ModNone), 2734 tcell.NewEventKey(tcell.KeyRune, 'a', tcell.ModNone), 2735 tcell.NewEventKey(tcell.KeyRune, 'y', tcell.ModNone), 2736 tcell.NewEventKey(tcell.KeyRune, 'j', tcell.ModNone), 2737 tcell.NewEventKey(tcell.KeyRune, 'V', tcell.ModNone), 2738 tcell.NewEventKey(tcell.KeyRune, 'y', tcell.ModNone), 2739 tcell.NewEventKey(tcell.KeyRune, 'j', tcell.ModNone), 2740 tcell.NewEventKey(tcell.KeyRune, 'p', tcell.ModNone), 2741 tcell.NewEventKey(tcell.KeyEsc, '\x00', tcell.ModNone), 2742 tcell.NewEventKey(tcell.KeyRune, '"', tcell.ModNone), 2743 tcell.NewEventKey(tcell.KeyRune, 'a', tcell.ModNone), 2744 tcell.NewEventKey(tcell.KeyRune, 'p', tcell.ModNone), 2745 }, 2746 expectedCursorPos: 76, 2747 expectedText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit\nsit amet consectetur\nLorem ipsum dolor\nsit amet consectetur", 2748 }, 2749 { 2750 name: "visual charwise to linewise, then toggle case", 2751 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 2752 events: []tcell.Event{ 2753 tcell.NewEventKey(tcell.KeyRune, 'v', tcell.ModNone), 2754 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 2755 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 2756 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 2757 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 2758 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 2759 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 2760 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 2761 tcell.NewEventKey(tcell.KeyRune, 'V', tcell.ModNone), 2762 tcell.NewEventKey(tcell.KeyRune, '~', tcell.ModNone), 2763 }, 2764 expectedCursorPos: 0, 2765 expectedText: "lOREM IPSUM DOLOR\nsit amet consectetur\nadipiscing elit", 2766 }, 2767 { 2768 name: "visual charwise to linewise, then toggle case", 2769 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 2770 events: []tcell.Event{ 2771 tcell.NewEventKey(tcell.KeyRune, 'V', tcell.ModNone), 2772 tcell.NewEventKey(tcell.KeyRune, 'v', tcell.ModNone), 2773 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 2774 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 2775 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 2776 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 2777 tcell.NewEventKey(tcell.KeyRune, '~', tcell.ModNone), 2778 }, 2779 expectedCursorPos: 0, 2780 expectedText: "lOREM ipsum dolor\nsit amet consectetur\nadipiscing elit", 2781 }, 2782 { 2783 name: "visual mode, then replay last action", 2784 initialText: "", 2785 events: []tcell.Event{ 2786 tcell.NewEventKey(tcell.KeyRune, 'i', tcell.ModNone), 2787 tcell.NewEventKey(tcell.KeyRune, 'a', tcell.ModNone), 2788 tcell.NewEventKey(tcell.KeyEnter, '\r', tcell.ModNone), 2789 tcell.NewEventKey(tcell.KeyTab, '\t', tcell.ModNone), 2790 tcell.NewEventKey(tcell.KeyRune, 'b', tcell.ModNone), 2791 tcell.NewEventKey(tcell.KeyEnter, '\r', tcell.ModNone), 2792 tcell.NewEventKey(tcell.KeyTab, '\t', tcell.ModNone), 2793 tcell.NewEventKey(tcell.KeyTab, '\t', tcell.ModNone), 2794 tcell.NewEventKey(tcell.KeyRune, 'c', tcell.ModNone), 2795 tcell.NewEventKey(tcell.KeyEnter, '\r', tcell.ModNone), 2796 tcell.NewEventKey(tcell.KeyTab, '\t', tcell.ModNone), 2797 tcell.NewEventKey(tcell.KeyTab, '\t', tcell.ModNone), 2798 tcell.NewEventKey(tcell.KeyTab, '\t', tcell.ModNone), 2799 tcell.NewEventKey(tcell.KeyRune, 'd', tcell.ModNone), 2800 tcell.NewEventKey(tcell.KeyEsc, '\x00', tcell.ModNone), 2801 tcell.NewEventKey(tcell.KeyRune, 'k', tcell.ModNone), 2802 tcell.NewEventKey(tcell.KeyRune, 'k', tcell.ModNone), 2803 tcell.NewEventKey(tcell.KeyRune, 'V', tcell.ModNone), 2804 tcell.NewEventKey(tcell.KeyRune, 'j', tcell.ModNone), 2805 tcell.NewEventKey(tcell.KeyRune, 'j', tcell.ModNone), 2806 tcell.NewEventKey(tcell.KeyRune, '<', tcell.ModNone), 2807 tcell.NewEventKey(tcell.KeyRune, '.', tcell.ModNone), 2808 tcell.NewEventKey(tcell.KeyRune, '.', tcell.ModNone), 2809 }, 2810 expectedCursorPos: 2, 2811 expectedText: "a\nb\nc\nd", 2812 }, 2813 { 2814 name: "edit text, enter and exit visual mode, then replay last action", 2815 initialText: "abc", 2816 events: []tcell.Event{ 2817 tcell.NewEventKey(tcell.KeyRune, 'i', tcell.ModNone), 2818 tcell.NewEventKey(tcell.KeyRune, 'x', tcell.ModNone), 2819 tcell.NewEventKey(tcell.KeyEsc, '\x00', tcell.ModNone), 2820 tcell.NewEventKey(tcell.KeyRune, 'v', tcell.ModNone), 2821 tcell.NewEventKey(tcell.KeyEsc, '\x00', tcell.ModNone), 2822 tcell.NewEventKey(tcell.KeyRune, '.', tcell.ModNone), 2823 }, 2824 expectedCursorPos: 0, 2825 expectedText: "xxabc", 2826 }, 2827 { 2828 name: "visual mode escape to normal mode", 2829 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 2830 events: []tcell.Event{ 2831 tcell.NewEventKey(tcell.KeyRune, 'V', tcell.ModNone), 2832 tcell.NewEventKey(tcell.KeyEsc, '\x00', tcell.ModNone), 2833 tcell.NewEventKey(tcell.KeyRune, 'o', tcell.ModNone), 2834 tcell.NewEventKey(tcell.KeyRune, 't', tcell.ModNone), 2835 tcell.NewEventKey(tcell.KeyRune, 'e', tcell.ModNone), 2836 tcell.NewEventKey(tcell.KeyRune, 's', tcell.ModNone), 2837 tcell.NewEventKey(tcell.KeyRune, 't', tcell.ModNone), 2838 tcell.NewEventKey(tcell.KeyEsc, '\x00', tcell.ModNone), 2839 }, 2840 expectedCursorPos: 21, 2841 expectedText: "Lorem ipsum dolor\ntest\nsit amet consectetur\nadipiscing elit", 2842 }, 2843 { 2844 name: "visual mode select inner word", 2845 initialText: "abc def ghi", 2846 events: []tcell.Event{ 2847 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 2848 tcell.NewEventKey(tcell.KeyRune, 'v', tcell.ModNone), 2849 tcell.NewEventKey(tcell.KeyRune, 'i', tcell.ModNone), 2850 tcell.NewEventKey(tcell.KeyRune, 'w', tcell.ModNone), 2851 tcell.NewEventKey(tcell.KeyRune, '~', tcell.ModNone), 2852 }, 2853 expectedCursorPos: 0, 2854 expectedText: "ABC def ghi", 2855 }, 2856 { 2857 name: "visual mode select a word", 2858 initialText: "abc def ghi", 2859 events: []tcell.Event{ 2860 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 2861 tcell.NewEventKey(tcell.KeyRune, 'v', tcell.ModNone), 2862 tcell.NewEventKey(tcell.KeyRune, '2', tcell.ModNone), 2863 tcell.NewEventKey(tcell.KeyRune, 'a', tcell.ModNone), 2864 tcell.NewEventKey(tcell.KeyRune, 'w', tcell.ModNone), 2865 tcell.NewEventKey(tcell.KeyRune, 'x', tcell.ModNone), 2866 }, 2867 expectedCursorPos: 0, 2868 expectedText: "ghi", 2869 }, 2870 { 2871 name: "visual mode select inner string block with double-quotes", 2872 initialText: `"abc" x`, 2873 events: []tcell.Event{ 2874 tcell.NewEventKey(tcell.KeyRune, 'v', tcell.ModNone), 2875 tcell.NewEventKey(tcell.KeyRune, 'i', tcell.ModNone), 2876 tcell.NewEventKey(tcell.KeyRune, '"', tcell.ModNone), 2877 tcell.NewEventKey(tcell.KeyRune, 'x', tcell.ModNone), 2878 }, 2879 expectedCursorPos: 1, 2880 expectedText: `"" x`, 2881 }, 2882 { 2883 name: "visual mode select a string block with double-quotes", 2884 initialText: `"abc" x`, 2885 events: []tcell.Event{ 2886 tcell.NewEventKey(tcell.KeyRune, 'v', tcell.ModNone), 2887 tcell.NewEventKey(tcell.KeyRune, 'a', tcell.ModNone), 2888 tcell.NewEventKey(tcell.KeyRune, '"', tcell.ModNone), 2889 tcell.NewEventKey(tcell.KeyRune, 'x', tcell.ModNone), 2890 }, 2891 expectedCursorPos: 0, 2892 expectedText: ` x`, 2893 }, 2894 { 2895 name: "visual mode select inner string block with single-quotes", 2896 initialText: `'abc' x`, 2897 events: []tcell.Event{ 2898 tcell.NewEventKey(tcell.KeyRune, 'v', tcell.ModNone), 2899 tcell.NewEventKey(tcell.KeyRune, 'i', tcell.ModNone), 2900 tcell.NewEventKey(tcell.KeyRune, '\'', tcell.ModNone), 2901 tcell.NewEventKey(tcell.KeyRune, 'x', tcell.ModNone), 2902 }, 2903 expectedCursorPos: 1, 2904 expectedText: `'' x`, 2905 }, 2906 { 2907 name: "visual mode select a string block with single-quotes", 2908 initialText: `'abc' x`, 2909 events: []tcell.Event{ 2910 tcell.NewEventKey(tcell.KeyRune, 'v', tcell.ModNone), 2911 tcell.NewEventKey(tcell.KeyRune, 'a', tcell.ModNone), 2912 tcell.NewEventKey(tcell.KeyRune, '\'', tcell.ModNone), 2913 tcell.NewEventKey(tcell.KeyRune, 'x', tcell.ModNone), 2914 }, 2915 expectedCursorPos: 0, 2916 expectedText: ` x`, 2917 }, 2918 { 2919 name: "visual mode select inner string block with backtick-quotes", 2920 initialText: "`abc` x", 2921 events: []tcell.Event{ 2922 tcell.NewEventKey(tcell.KeyRune, 'v', tcell.ModNone), 2923 tcell.NewEventKey(tcell.KeyRune, 'i', tcell.ModNone), 2924 tcell.NewEventKey(tcell.KeyRune, '`', tcell.ModNone), 2925 tcell.NewEventKey(tcell.KeyRune, 'x', tcell.ModNone), 2926 }, 2927 expectedCursorPos: 1, 2928 expectedText: "`` x", 2929 }, 2930 { 2931 name: "visual mode select a string block with backtick-quotes", 2932 initialText: "`abc` x", 2933 events: []tcell.Event{ 2934 tcell.NewEventKey(tcell.KeyRune, 'v', tcell.ModNone), 2935 tcell.NewEventKey(tcell.KeyRune, 'a', tcell.ModNone), 2936 tcell.NewEventKey(tcell.KeyRune, '`', tcell.ModNone), 2937 tcell.NewEventKey(tcell.KeyRune, 'x', tcell.ModNone), 2938 }, 2939 expectedCursorPos: 0, 2940 expectedText: ` x`, 2941 }, 2942 { 2943 name: "visual mode select inner paren block", 2944 initialText: "(abc)", 2945 events: []tcell.Event{ 2946 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 2947 tcell.NewEventKey(tcell.KeyRune, 'v', tcell.ModNone), 2948 tcell.NewEventKey(tcell.KeyRune, 'i', tcell.ModNone), 2949 tcell.NewEventKey(tcell.KeyRune, 'b', tcell.ModNone), 2950 tcell.NewEventKey(tcell.KeyRune, 'x', tcell.ModNone), 2951 }, 2952 expectedCursorPos: 1, 2953 expectedText: "()", 2954 }, 2955 { 2956 name: "visual mode select a paren block", 2957 initialText: "x (abc) yz", 2958 events: []tcell.Event{ 2959 tcell.NewEventKey(tcell.KeyRune, 'w', tcell.ModNone), 2960 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 2961 tcell.NewEventKey(tcell.KeyRune, 'v', tcell.ModNone), 2962 tcell.NewEventKey(tcell.KeyRune, 'a', tcell.ModNone), 2963 tcell.NewEventKey(tcell.KeyRune, 'b', tcell.ModNone), 2964 tcell.NewEventKey(tcell.KeyRune, 'x', tcell.ModNone), 2965 }, 2966 expectedCursorPos: 2, 2967 expectedText: "x yz", 2968 }, 2969 { 2970 name: "visual mode select inner brace block", 2971 initialText: "{abc}", 2972 events: []tcell.Event{ 2973 tcell.NewEventKey(tcell.KeyRune, 'v', tcell.ModNone), 2974 tcell.NewEventKey(tcell.KeyRune, 'i', tcell.ModNone), 2975 tcell.NewEventKey(tcell.KeyRune, 'B', tcell.ModNone), 2976 tcell.NewEventKey(tcell.KeyRune, 'x', tcell.ModNone), 2977 }, 2978 expectedCursorPos: 1, 2979 expectedText: "{}", 2980 }, 2981 { 2982 name: "visual mode select a brace block", 2983 initialText: "x {abc} y", 2984 events: []tcell.Event{ 2985 tcell.NewEventKey(tcell.KeyRune, '4', tcell.ModNone), 2986 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 2987 tcell.NewEventKey(tcell.KeyRune, 'v', tcell.ModNone), 2988 tcell.NewEventKey(tcell.KeyRune, 'a', tcell.ModNone), 2989 tcell.NewEventKey(tcell.KeyRune, 'B', tcell.ModNone), 2990 tcell.NewEventKey(tcell.KeyRune, 'x', tcell.ModNone), 2991 }, 2992 expectedCursorPos: 2, 2993 expectedText: "x y", 2994 }, 2995 { 2996 name: "visual mode select inner angle block", 2997 initialText: `<html><body /></html>`, 2998 events: []tcell.Event{ 2999 tcell.NewEventKey(tcell.KeyRune, '9', tcell.ModNone), 3000 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 3001 tcell.NewEventKey(tcell.KeyRune, 'v', tcell.ModNone), 3002 tcell.NewEventKey(tcell.KeyRune, 'i', tcell.ModNone), 3003 tcell.NewEventKey(tcell.KeyRune, '>', tcell.ModNone), 3004 tcell.NewEventKey(tcell.KeyRune, 'x', tcell.ModNone), 3005 }, 3006 expectedCursorPos: 7, 3007 expectedText: "<html><></html>", 3008 }, 3009 { 3010 name: "visual mode select then delete with delete key", 3011 initialText: `Lorem ipsum`, 3012 events: []tcell.Event{ 3013 tcell.NewEventKey(tcell.KeyRune, 'v', tcell.ModNone), 3014 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 3015 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 3016 tcell.NewEventKey(tcell.KeyDelete, '\x00', tcell.ModNone), 3017 }, 3018 expectedCursorPos: 0, 3019 expectedText: "em ipsum", 3020 }, 3021 { 3022 name: "visual mode select an angle block", 3023 initialText: `<html><body /></html>`, 3024 events: []tcell.Event{ 3025 tcell.NewEventKey(tcell.KeyRune, '9', tcell.ModNone), 3026 tcell.NewEventKey(tcell.KeyRune, 'l', tcell.ModNone), 3027 tcell.NewEventKey(tcell.KeyRune, 'v', tcell.ModNone), 3028 tcell.NewEventKey(tcell.KeyRune, 'a', tcell.ModNone), 3029 tcell.NewEventKey(tcell.KeyRune, '<', tcell.ModNone), 3030 tcell.NewEventKey(tcell.KeyRune, 'x', tcell.ModNone), 3031 }, 3032 expectedCursorPos: 6, 3033 expectedText: "<html></html>", 3034 }, 3035 { 3036 name: "record and replay user macro", 3037 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 3038 events: []tcell.Event{ 3039 tcell.NewEventKey(tcell.KeyRune, ':', tcell.ModNone), 3040 tcell.NewEventKey(tcell.KeyRune, 's', tcell.ModNone), 3041 tcell.NewEventKey(tcell.KeyRune, 't', tcell.ModNone), 3042 tcell.NewEventKey(tcell.KeyRune, 'a', tcell.ModNone), 3043 tcell.NewEventKey(tcell.KeyRune, 'r', tcell.ModNone), 3044 tcell.NewEventKey(tcell.KeyRune, 't', tcell.ModNone), 3045 tcell.NewEventKey(tcell.KeyEnter, '\r', tcell.ModNone), 3046 tcell.NewEventKey(tcell.KeyRune, 'i', tcell.ModNone), 3047 tcell.NewEventKey(tcell.KeyRune, '{', tcell.ModNone), 3048 tcell.NewEventKey(tcell.KeyEsc, '\x00', tcell.ModNone), 3049 tcell.NewEventKey(tcell.KeyRune, 'A', tcell.ModNone), 3050 tcell.NewEventKey(tcell.KeyRune, '}', tcell.ModNone), 3051 tcell.NewEventKey(tcell.KeyRune, ',', tcell.ModNone), 3052 tcell.NewEventKey(tcell.KeyEsc, '\x00', tcell.ModNone), 3053 tcell.NewEventKey(tcell.KeyRune, 'j', tcell.ModNone), 3054 tcell.NewEventKey(tcell.KeyRune, '^', tcell.ModNone), 3055 tcell.NewEventKey(tcell.KeyRune, ':', tcell.ModNone), 3056 tcell.NewEventKey(tcell.KeyRune, 's', tcell.ModNone), 3057 tcell.NewEventKey(tcell.KeyRune, 't', tcell.ModNone), 3058 tcell.NewEventKey(tcell.KeyRune, 'o', tcell.ModNone), 3059 tcell.NewEventKey(tcell.KeyRune, 'p', tcell.ModNone), 3060 tcell.NewEventKey(tcell.KeyEnter, '\r', tcell.ModNone), 3061 tcell.NewEventKey(tcell.KeyRune, ':', tcell.ModNone), 3062 tcell.NewEventKey(tcell.KeyRune, 'r', tcell.ModNone), 3063 tcell.NewEventKey(tcell.KeyRune, 'e', tcell.ModNone), 3064 tcell.NewEventKey(tcell.KeyRune, 'p', tcell.ModNone), 3065 tcell.NewEventKey(tcell.KeyEnter, '\r', tcell.ModNone), 3066 tcell.NewEventKey(tcell.KeyRune, '.', tcell.ModNone), 3067 }, 3068 expectedCursorPos: 45, 3069 expectedText: "{Lorem ipsum dolor},\n{sit amet consectetur},\n{adipiscing elit},", 3070 }, 3071 { 3072 name: "record and replay user macro with text search", 3073 initialText: "foo bar baz bat", 3074 events: []tcell.Event{ 3075 tcell.NewEventKey(tcell.KeyRune, ':', tcell.ModNone), 3076 tcell.NewEventKey(tcell.KeyRune, 's', tcell.ModNone), 3077 tcell.NewEventKey(tcell.KeyRune, 't', tcell.ModNone), 3078 tcell.NewEventKey(tcell.KeyRune, 'a', tcell.ModNone), 3079 tcell.NewEventKey(tcell.KeyRune, 'r', tcell.ModNone), 3080 tcell.NewEventKey(tcell.KeyRune, 't', tcell.ModNone), 3081 tcell.NewEventKey(tcell.KeyEnter, '\r', tcell.ModNone), 3082 tcell.NewEventKey(tcell.KeyRune, '/', tcell.ModNone), 3083 tcell.NewEventKey(tcell.KeyRune, 'b', tcell.ModNone), 3084 tcell.NewEventKey(tcell.KeyRune, 'a', tcell.ModNone), 3085 tcell.NewEventKey(tcell.KeyEnter, '\r', tcell.ModNone), 3086 tcell.NewEventKey(tcell.KeyRune, 'x', tcell.ModNone), 3087 tcell.NewEventKey(tcell.KeyRune, ':', tcell.ModNone), 3088 tcell.NewEventKey(tcell.KeyRune, 's', tcell.ModNone), 3089 tcell.NewEventKey(tcell.KeyRune, 't', tcell.ModNone), 3090 tcell.NewEventKey(tcell.KeyRune, 'o', tcell.ModNone), 3091 tcell.NewEventKey(tcell.KeyRune, 'p', tcell.ModNone), 3092 tcell.NewEventKey(tcell.KeyEnter, '\r', tcell.ModNone), 3093 tcell.NewEventKey(tcell.KeyRune, ':', tcell.ModNone), 3094 tcell.NewEventKey(tcell.KeyRune, 'r', tcell.ModNone), 3095 tcell.NewEventKey(tcell.KeyRune, 'e', tcell.ModNone), 3096 tcell.NewEventKey(tcell.KeyRune, 'p', tcell.ModNone), 3097 tcell.NewEventKey(tcell.KeyEnter, '\r', tcell.ModNone), 3098 }, 3099 expectedCursorPos: 7, 3100 expectedText: "foo ar az bat", 3101 }, 3102 { 3103 name: "bracketed paste in insert mode", 3104 initialText: "abc", 3105 events: []tcell.Event{ 3106 tcell.NewEventKey(tcell.KeyRune, 'A', tcell.ModNone), 3107 tcell.NewEventPaste(true), 3108 tcell.NewEventKey(tcell.KeyRune, 'x', tcell.ModNone), 3109 tcell.NewEventKey(tcell.KeyRune, 'y', tcell.ModNone), 3110 tcell.NewEventKey(tcell.KeyRune, 'z', tcell.ModNone), 3111 tcell.NewEventKey(tcell.KeyEnter, '\r', tcell.ModNone), 3112 tcell.NewEventKey(tcell.KeyTab, '\t', tcell.ModNone), 3113 tcell.NewEventKey(tcell.KeyRune, '1', tcell.ModNone), 3114 tcell.NewEventKey(tcell.KeyRune, '2', tcell.ModNone), 3115 tcell.NewEventKey(tcell.KeyRune, '3', tcell.ModNone), 3116 tcell.NewEventPaste(false), 3117 }, 3118 expectedCursorPos: 11, 3119 expectedText: "abcxyz\n\t123", 3120 }, 3121 { 3122 name: "bracketed paste in search mode", 3123 initialText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 3124 events: []tcell.Event{ 3125 tcell.NewEventKey(tcell.KeyRune, '/', tcell.ModNone), 3126 tcell.NewEventPaste(true), 3127 tcell.NewEventKey(tcell.KeyRune, 'c', tcell.ModNone), 3128 tcell.NewEventKey(tcell.KeyRune, 'o', tcell.ModNone), 3129 tcell.NewEventKey(tcell.KeyRune, 'n', tcell.ModNone), 3130 tcell.NewEventPaste(false), 3131 tcell.NewEventKey(tcell.KeyEnter, '\r', tcell.ModNone), 3132 }, 3133 expectedCursorPos: 27, 3134 expectedText: "Lorem ipsum dolor\nsit amet consectetur\nadipiscing elit", 3135 }, 3136 } 3137 3138 for _, tc := range testCases { 3139 t.Run(tc.name, func(t *testing.T) { 3140 interpreter := NewInterpreter() 3141 editorState := state.NewEditorState(100, 100, nil, nil) 3142 3143 // Write the initial text to a temp file, which we will load into the editor. 3144 // Append a final "\n" to the contents as the POSIX end-of-file indicator. 3145 tmpFile, err := os.CreateTemp(t.TempDir(), "") 3146 require.NoError(t, err) 3147 path := tmpFile.Name() 3148 defer os.Remove(path) 3149 3150 err = os.WriteFile(path, []byte(tc.initialText+"\n"), 0644) 3151 require.NoError(t, err) 3152 3153 // Load the initial text tempfile. 3154 state.LoadDocument( 3155 editorState, 3156 path, 3157 false, 3158 func(state.LocatorParams) uint64 { return 0 }, 3159 ) 3160 3161 // Replay the input events. 3162 for _, event := range tc.events { 3163 inputCtx := ContextFromEditorState(editorState) 3164 action := interpreter.ProcessEvent(event, inputCtx) 3165 action(editorState) 3166 } 3167 3168 // Verify that the cursor position and text match what we expect. 3169 buffer := editorState.DocumentBuffer() 3170 reader := buffer.TextTree().ReaderAtPosition(0) 3171 data, err := io.ReadAll(&reader) 3172 require.NoError(t, err) 3173 text := string(data) 3174 assert.Equal(t, tc.expectedCursorPos, buffer.CursorPosition()) 3175 assert.Equal(t, tc.expectedText, text) 3176 }) 3177 } 3178 } 3179 3180 func TestEnterAndExitVisualModeThenReplayLastAction(t *testing.T) { 3181 testCases := []struct { 3182 name string 3183 enterVisualModeKey rune 3184 }{ 3185 { 3186 name: "charwise (v)", 3187 enterVisualModeKey: 'v', 3188 }, 3189 { 3190 name: "linewise (V)", 3191 enterVisualModeKey: 'V', 3192 }, 3193 } 3194 3195 for _, tc := range testCases { 3196 t.Run(tc.name, func(t *testing.T) { 3197 inputEvents := []tcell.Event{ 3198 tcell.NewEventKey(tcell.KeyRune, tc.enterVisualModeKey, tcell.ModNone), // enter visual mode 3199 tcell.NewEventKey(tcell.KeyEsc, '\x00', tcell.ModNone), // exit visual mode 3200 tcell.NewEventKey(tcell.KeyRune, '.', tcell.ModNone), // replay last action 3201 } 3202 3203 editorState := state.NewEditorState(100, 100, nil, nil) 3204 interpreter := NewInterpreter() 3205 for _, event := range inputEvents { 3206 inputCtx := ContextFromEditorState(editorState) 3207 action := interpreter.ProcessEvent(event, inputCtx) 3208 action(editorState) 3209 } 3210 3211 assert.Equal(t, state.InputModeNormal, editorState.InputMode()) 3212 }) 3213 } 3214 } 3215 3216 func inputEventsForBracketedPaste(s string) []tcell.Event { 3217 inputEvents := make([]tcell.Event, 0, len(s)+2) 3218 inputEvents = append(inputEvents, tcell.NewEventPaste(true)) 3219 for _, r := range s { 3220 if r == '\n' { 3221 inputEvents = append(inputEvents, tcell.NewEventKey(tcell.KeyEnter, '\r', tcell.ModNone)) 3222 } else if r == '\t' { 3223 inputEvents = append(inputEvents, tcell.NewEventKey(tcell.KeyTab, '\t', tcell.ModNone)) 3224 } else { 3225 inputEvents = append(inputEvents, tcell.NewEventKey(tcell.KeyRune, r, tcell.ModNone)) 3226 } 3227 } 3228 inputEvents = append(inputEvents, tcell.NewEventPaste(false)) 3229 return inputEvents 3230 } 3231 3232 func TestBracketedPasteInSearchMode(t *testing.T) { 3233 testCases := []struct { 3234 name string 3235 pasteString string 3236 expectedQuery string 3237 }{ 3238 { 3239 name: "short input", 3240 pasteString: "abc", 3241 expectedQuery: "abc", 3242 }, 3243 { 3244 name: "long input, truncated", 3245 pasteString: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 3246 expectedQuery: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 3247 }, 3248 { 3249 name: "input with newline", 3250 pasteString: "abc\nxyz\n123", 3251 expectedQuery: "abc", 3252 }, 3253 { 3254 name: "input with tab", 3255 pasteString: "abc\txyz", 3256 expectedQuery: "abc\txyz", 3257 }, 3258 } 3259 3260 for _, tc := range testCases { 3261 t.Run(tc.name, func(t *testing.T) { 3262 inputEvents := []tcell.Event{tcell.NewEventKey(tcell.KeyRune, '/', tcell.ModNone)} 3263 inputEvents = append(inputEvents, inputEventsForBracketedPaste(tc.pasteString)...) 3264 editorState := state.NewEditorState(100, 100, nil, nil) 3265 interpreter := NewInterpreter() 3266 for _, event := range inputEvents { 3267 inputCtx := ContextFromEditorState(editorState) 3268 action := interpreter.ProcessEvent(event, inputCtx) 3269 action(editorState) 3270 } 3271 3272 assert.Equal(t, state.InputModeSearch, editorState.InputMode()) 3273 searchQuery, _ := editorState.DocumentBuffer().SearchQueryAndDirection() 3274 assert.Equal(t, tc.expectedQuery, searchQuery) 3275 }) 3276 } 3277 } 3278 3279 func TestBracketedPasteInMenuMode(t *testing.T) { 3280 testCases := []struct { 3281 name string 3282 pasteString string 3283 expectedQuery string 3284 }{ 3285 { 3286 name: "short input", 3287 pasteString: "abc", 3288 expectedQuery: "abc", 3289 }, 3290 { 3291 name: "long input, truncated", 3292 pasteString: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 3293 expectedQuery: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 3294 }, 3295 { 3296 name: "input with newline", 3297 pasteString: "abc\nxyz\n123", 3298 expectedQuery: "abc", 3299 }, 3300 { 3301 name: "input with tab", 3302 pasteString: "abc\txyz", 3303 expectedQuery: "abc\txyz", 3304 }, 3305 } 3306 3307 for _, tc := range testCases { 3308 t.Run(tc.name, func(t *testing.T) { 3309 inputEvents := []tcell.Event{tcell.NewEventKey(tcell.KeyRune, ':', tcell.ModNone)} 3310 inputEvents = append(inputEvents, inputEventsForBracketedPaste(tc.pasteString)...) 3311 editorState := state.NewEditorState(100, 100, nil, nil) 3312 interpreter := NewInterpreter() 3313 for _, event := range inputEvents { 3314 inputCtx := ContextFromEditorState(editorState) 3315 action := interpreter.ProcessEvent(event, inputCtx) 3316 action(editorState) 3317 } 3318 3319 assert.Equal(t, state.InputModeMenu, editorState.InputMode()) 3320 assert.Equal(t, tc.expectedQuery, editorState.Menu().SearchQuery()) 3321 }) 3322 } 3323 } 3324 3325 func TestBracketedPasteInNormalAndVisualMode(t *testing.T) { 3326 testCases := []struct { 3327 name string 3328 mode state.InputMode 3329 }{ 3330 {name: "normal mode", mode: state.InputModeNormal}, 3331 {name: "visual mode", mode: state.InputModeVisual}, 3332 } 3333 3334 for _, tc := range testCases { 3335 t.Run(tc.name, func(t *testing.T) { 3336 var inputEvents []tcell.Event 3337 if tc.mode == state.InputModeVisual { 3338 inputEvents = append(inputEvents, tcell.NewEventKey(tcell.KeyRune, 'v', tcell.ModNone)) 3339 } 3340 inputEvents = append(inputEvents, inputEventsForBracketedPaste("abc")...) 3341 3342 editorState := state.NewEditorState(100, 100, nil, nil) 3343 interpreter := NewInterpreter() 3344 for _, event := range inputEvents { 3345 inputCtx := ContextFromEditorState(editorState) 3346 action := interpreter.ProcessEvent(event, inputCtx) 3347 action(editorState) 3348 } 3349 3350 assert.Equal(t, tc.mode, editorState.InputMode()) 3351 assert.Equal(t, state.StatusMsgStyleError, editorState.StatusMsg().Style) 3352 assert.Equal(t, "Cannot paste in this mode. Press 'i' to enter insert mode", editorState.StatusMsg().Text) 3353 }) 3354 } 3355 } 3356 3357 func TestBracketedPasteInUserMacro(t *testing.T) { 3358 var inputEvents []tcell.Event 3359 3360 // Begin recording a user macro. 3361 inputEvents = append(inputEvents, 3362 tcell.NewEventKey(tcell.KeyRune, ':', tcell.ModNone), 3363 tcell.NewEventKey(tcell.KeyRune, 's', tcell.ModNone), 3364 tcell.NewEventKey(tcell.KeyRune, 't', tcell.ModNone), 3365 tcell.NewEventKey(tcell.KeyRune, 'a', tcell.ModNone), 3366 tcell.NewEventKey(tcell.KeyRune, 'r', tcell.ModNone), 3367 tcell.NewEventKey(tcell.KeyRune, 't', tcell.ModNone), 3368 tcell.NewEventKey(tcell.KeyEnter, '\r', tcell.ModNone)) 3369 3370 // Bracketed paste in insert mode. 3371 inputEvents = append(inputEvents, tcell.NewEventKey(tcell.KeyRune, 'i', tcell.ModNone)) 3372 inputEvents = append(inputEvents, inputEventsForBracketedPaste("abc\n")...) 3373 inputEvents = append(inputEvents, tcell.NewEventKey(tcell.KeyEscape, '\x00', tcell.ModNone)) 3374 3375 // End macro. 3376 inputEvents = append(inputEvents, 3377 tcell.NewEventKey(tcell.KeyRune, ':', tcell.ModNone), 3378 tcell.NewEventKey(tcell.KeyRune, 's', tcell.ModNone), 3379 tcell.NewEventKey(tcell.KeyRune, 't', tcell.ModNone), 3380 tcell.NewEventKey(tcell.KeyRune, 'o', tcell.ModNone), 3381 tcell.NewEventKey(tcell.KeyRune, 'p', tcell.ModNone), 3382 tcell.NewEventKey(tcell.KeyEnter, '\r', tcell.ModNone)) 3383 3384 // Replay macro. 3385 inputEvents = append(inputEvents, 3386 tcell.NewEventKey(tcell.KeyRune, ':', tcell.ModNone), 3387 tcell.NewEventKey(tcell.KeyRune, 'r', tcell.ModNone), 3388 tcell.NewEventKey(tcell.KeyRune, 'e', tcell.ModNone), 3389 tcell.NewEventKey(tcell.KeyRune, 'p', tcell.ModNone), 3390 tcell.NewEventKey(tcell.KeyEnter, '\r', tcell.ModNone)) 3391 3392 editorState := state.NewEditorState(100, 100, nil, nil) 3393 interpreter := NewInterpreter() 3394 for _, event := range inputEvents { 3395 inputCtx := ContextFromEditorState(editorState) 3396 action := interpreter.ProcessEvent(event, inputCtx) 3397 action(editorState) 3398 } 3399 3400 // Expect that the pasted text is inserted twice (once from original paste, once from macro replay). 3401 buffer := editorState.DocumentBuffer() 3402 reader := buffer.TextTree().ReaderAtPosition(0) 3403 data, err := io.ReadAll(&reader) 3404 require.NoError(t, err) 3405 text := string(data) 3406 assert.Equal(t, state.InputModeNormal, editorState.InputMode()) 3407 assert.Equal(t, uint64(8), buffer.CursorPosition()) 3408 assert.Equal(t, "abc\nabc\n", text) 3409 } 3410 3411 func TestLoadGeneratedStateMachines(t *testing.T) { 3412 testCases := []struct { 3413 name string 3414 path string 3415 }{ 3416 {name: "normal mode", path: NormalModePath}, 3417 {name: "insert mode", path: InsertModePath}, 3418 {name: "visual mode", path: VisualModePath}, 3419 {name: "menu mode", path: MenuModePath}, 3420 {name: "search mode", path: SearchModePath}, 3421 {name: "task mode", path: TaskModePath}, 3422 {name: "textfield mode", path: TextFieldModePath}, 3423 } 3424 3425 for _, tc := range testCases { 3426 t.Run(tc.name, func(t *testing.T) { 3427 data, err := generatedFiles.ReadFile(tc.path) 3428 require.NoError(t, err) 3429 require.NotPanics(t, func() { 3430 engine.Deserialize(data) 3431 }) 3432 }) 3433 } 3434 } 3435 3436 func TestCountLimits(t *testing.T) { 3437 testCases := []string{ 3438 "1025fx", 3439 "1025Fx", 3440 "1025tx", 3441 "1025Tx", 3442 "1025dd", 3443 "1025dl", 3444 "1025x", 3445 "1025dfx", 3446 "1025dFx", 3447 "1025dtx", 3448 "1025dTx", 3449 "1025cfx", 3450 "1025cFx", 3451 "1025ctx", 3452 "1025cTx", 3453 "1025.", 3454 "1025>>", 3455 "1025<<", 3456 "v33>", 3457 "v33<", 3458 } 3459 3460 for _, tc := range testCases { 3461 t.Run(tc, func(t *testing.T) { 3462 interpreter := NewInterpreter() 3463 editorState := state.NewEditorState(100, 100, nil, nil) 3464 3465 for _, r := range tc { 3466 event := tcell.NewEventKey(tcell.KeyRune, r, tcell.ModNone) 3467 inputCtx := ContextFromEditorState(editorState) 3468 action := interpreter.ProcessEvent(event, inputCtx) 3469 action(editorState) 3470 } 3471 3472 msg := editorState.StatusMsg() 3473 assert.Equal(t, state.StatusMsgStyleError, msg.Style) 3474 assert.Contains(t, msg.Text, "count") 3475 }) 3476 } 3477 } 3478 3479 func TestTextFieldMode(t *testing.T) { 3480 interpreter := NewInterpreter() 3481 editorState := state.NewEditorState(100, 100, nil, nil) 3482 3483 inputEvent := func(event tcell.Event) { 3484 inputCtx := ContextFromEditorState(editorState) 3485 action := interpreter.ProcessEvent(event, inputCtx) 3486 action(editorState) 3487 } 3488 3489 // Enter menu mode, select "new document" 3490 inputEvent(tcell.NewEventKey(tcell.KeyRune, ':', tcell.ModNone)) 3491 inputEvent(tcell.NewEventKey(tcell.KeyRune, 'n', tcell.ModNone)) 3492 inputEvent(tcell.NewEventKey(tcell.KeyRune, 'e', tcell.ModNone)) 3493 inputEvent(tcell.NewEventKey(tcell.KeyRune, 'w', tcell.ModNone)) 3494 inputEvent(tcell.NewEventKey(tcell.KeyEnter, '\x00', tcell.ModNone)) 3495 3496 // Expect that we're in text field mode with a prompt. 3497 assert.Equal(t, state.InputModeTextField, editorState.InputMode()) 3498 assert.Equal(t, "New document file path:", editorState.TextField().PromptText()) 3499 assert.Equal(t, "", editorState.TextField().InputText()) 3500 3501 // Enter some text. 3502 inputEvent(tcell.NewEventKey(tcell.KeyRune, 't', tcell.ModNone)) 3503 inputEvent(tcell.NewEventKey(tcell.KeyRune, 'e', tcell.ModNone)) 3504 inputEvent(tcell.NewEventKey(tcell.KeyRune, 's', tcell.ModNone)) 3505 inputEvent(tcell.NewEventKey(tcell.KeyRune, 't', tcell.ModNone)) 3506 inputEvent(tcell.NewEventKey(tcell.KeyRune, '.', tcell.ModNone)) 3507 inputEvent(tcell.NewEventKey(tcell.KeyRune, 't', tcell.ModNone)) 3508 inputEvent(tcell.NewEventKey(tcell.KeyRune, 'x', tcell.ModNone)) 3509 inputEvent(tcell.NewEventKey(tcell.KeyRune, 't', tcell.ModNone)) 3510 3511 // Expect that we're stil in text field mode, and input text is stored. 3512 assert.Equal(t, state.InputModeTextField, editorState.InputMode()) 3513 assert.Equal(t, "test.txt", editorState.TextField().InputText()) 3514 3515 // Delete some text, then add a new extension. 3516 inputEvent(tcell.NewEventKey(tcell.KeyBackspace, '\x00', tcell.ModNone)) 3517 inputEvent(tcell.NewEventKey(tcell.KeyBackspace, '\x00', tcell.ModNone)) 3518 inputEvent(tcell.NewEventKey(tcell.KeyBackspace, '\x00', tcell.ModNone)) 3519 inputEvent(tcell.NewEventKey(tcell.KeyRune, 'g', tcell.ModNone)) 3520 inputEvent(tcell.NewEventKey(tcell.KeyRune, 'o', tcell.ModNone)) 3521 3522 // Expect updated input text. 3523 assert.Equal(t, state.InputModeTextField, editorState.InputMode()) 3524 assert.Equal(t, "test.go", editorState.TextField().InputText()) 3525 3526 // Execute the action (load new file). 3527 inputEvent(tcell.NewEventKey(tcell.KeyEnter, '\x00', tcell.ModNone)) 3528 3529 // Expect back to normal mode, with the new file path loaded. 3530 assert.Equal(t, state.InputModeNormal, editorState.InputMode()) 3531 assert.Equal(t, "test.go", editorState.FileWatcher().Path()) 3532 } 3533 3534 func BenchmarkNewInterpreter(b *testing.B) { 3535 for n := 0; n < b.N; n++ { 3536 NewInterpreter() 3537 } 3538 } 3539 3540 func BenchmarkProcessEvent(b *testing.B) { 3541 benchmarks := []struct { 3542 name string 3543 mode state.InputMode 3544 events []tcell.Event 3545 }{ 3546 { 3547 name: "i", 3548 mode: state.InputModeNormal, 3549 events: []tcell.Event{ 3550 tcell.NewEventKey(tcell.KeyRune, 'i', tcell.ModNone), 3551 }, 3552 }, 3553 { 3554 name: "1234gg", 3555 mode: state.InputModeNormal, 3556 events: []tcell.Event{ 3557 tcell.NewEventKey(tcell.KeyRune, '1', tcell.ModNone), 3558 tcell.NewEventKey(tcell.KeyRune, '2', tcell.ModNone), 3559 tcell.NewEventKey(tcell.KeyRune, '3', tcell.ModNone), 3560 tcell.NewEventKey(tcell.KeyRune, '4', tcell.ModNone), 3561 tcell.NewEventKey(tcell.KeyRune, 'g', tcell.ModNone), 3562 tcell.NewEventKey(tcell.KeyRune, 'g', tcell.ModNone), 3563 }, 3564 }, 3565 } 3566 3567 for _, bm := range benchmarks { 3568 b.Run(bm.name, func(b *testing.B) { 3569 logWriter := log.Writer() 3570 defer func() { 3571 log.SetOutput(logWriter) 3572 }() 3573 log.SetOutput(io.Discard) 3574 3575 interpreter := NewInterpreter() 3576 inputCtx := Context{InputMode: bm.mode} 3577 b.ResetTimer() 3578 for _, event := range bm.events { 3579 interpreter.ProcessEvent(event, inputCtx) 3580 } 3581 }) 3582 } 3583 }