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  }