A vim-like listbox in rbcurse (ruby ncurses)
Lots of terminal application users like applications to use vim-like keys. So I’ve played around with the Listbox of rbcurse, and added some mappings to give it a very vim (and emacsy) feel. The result is on github (master19 branch) as examples/testlistbox.rb.
What did i do:
This adds a whole lots of vim like bindings to lists. Since, this file is shared by textareas and lists, I’ve put in some separate mappings for listboxes in there. This allows us to use “gg” “G”, “dd”, o, O, j,k and plenty of other keys.
Note than normally entering into a cell of a listbox makes it editable in-place. Exiting saves the value. But being terminal freaks, we don’t like that behavior ! We want keys to be used for navigation and search etc. So for changing contents I can press a “C”. And edit box at the bottom of the screen (ugh! reminds you of alpine, doesn’t it). Similarly, to add a row above or below the present you can press “o” or “O”.
Please note, to keep the library and my life simple, delete is “dd”, So to delete 5 rows its “5dd” not “5d”, To yank 5 rows it is “5yy” not “5y”. Maybe in the future, I’ll look into this.
$catch_alt_digits = true; # emacs like alt-1..9 numeric arguments
For the emacs crowd. You like to use
C-u for numeric arguments. In a rbcurse app, C-u no longer does an undo, its always used for numeric arguments, each successive press of C-u uses a range: 4, 16, 64 etc (I’ve detailed this in a previous post)
catch_alt_digits allows us to use numeric arguments like Alt-9 9 for 99. To go down 99 rows, an emacs guy can do Alt-99 j. Of course, vim guys can just do “99j”.
The advantage of
catch_alt_digits is that it can be used in editable boxes too, such as textareas.
In order that keys can be mapped to functions or blocks, I’ve disabled cell_editing. If I did not, then j or k would insert a j or k in the box.
listb.one_key_selection = false # this allows us to map keys to methods
By default, if cell_editing is false, typing a key takes us to the first item that starts with that key. That’s pretty friendly behavior, but it does not allow us to map keys. So setting this as false, means we can map keys. Now use “f” to go to the first row, as “fn” or “f <char>”.
5. The mappings. Rather than put the mappings in the sample file, I’ve added them to the vieditable.rb file, so they may be reused. So lets call that method.
6. We want to have infinite linear undo and redo. So let’s instantiate our undo manager and give it our list.
undom = SimpleUndo.new listb
Now we can use “u” and “C-r” for undo and redo. The emacs key “C-_” can also be used. You can do single or multi-row deletes and undo. “12dd”, “u”. For this don’t forget to require the undo manager at the top.
That’s about it. However, there’s more in the mappings. I’ve adopted emacs’s kill-ring concept. So “yy” does a
kill-ring-save. “p” and “P” of course do a paste (emacs calls it a yank, for vimmers a yank is a copy). For emacsers, M-w does a
kill-ring-save, C-y does a
yank (paste), and M-y does a
yank-pop. Again, this is explained in a previous post, but it helps to save multiple rows into a ring, and select which one one wishes to paste. We first have to type C-y to paste the last copy, and then M-y to cycle through previous copies. I think this gives the best of both worlds without a vimmer having to change his habit of yy and p/P.
This sample is not included in the rbcurse gem 1.1.3. Fetch it from github, it will be included in 1.1.4 when i release it shortly.