Archive for October 2010
In rbcurse, we could dialog boxes for entry of text, or getting confirmations (just as in the links editor). However, for those of us who like the vim-ish, bottom of the screen input of text from user, we had an entry routine in io.rb (rbgetstr).
It was certainly not rubyesque. Then i came across the Highline gem and wished our rbgetstr() method was like highline’s ask. I’ve got permission from James Gray to copy his code and fit in ncurses input and output. So now we can almost exactly use highline ask code and get occasional data at the bottom of the screen. Some changes …
- we don’t use readline, since we always are in ncurses character mode,
- if you provide default, then you can edit that value,
- a completion_proc can be passed which is used when pressing TAB
- ANSI color codes can’t be used, thus one can set a color_pair which is used by say
- helptext may be provided. If user presses M-h, this is displayed for 5 seconds (as in alpine. I might pop up a small window at a later stage instead)
- Various keys may be used such as C-a, C-e, C-k (delete till end), C-g (abort) as well as arrow keys, backspace and delete
I’ll be giving it a good trial in an upcoming demo of a gmail client (now that a gmail gem has been released).
At some stage, I could replace the internals with a Label and Field. That would allow users to map keys to procs.
A 1.2.0 release of rbcurse is coming up soon. I am thinking once I have the gmail demo ready, i’ll release 1.2.0. Oh, by the way, I’ve provisionally named the class Bottomline, partly due to Highline, and the fact that the editing line traditionally comes at the bottom of the screen.
Like a Vim screen, rbcurse has controls that permit creation of multiple panes or windows containing lists, tables, and textareas. These may be resized using keys such as "Ctrl-W + – =" etc. However, there are complex cases where its not possible for the widget to know what all to resize and in what direction. The attached image shows the mbox email client demo with 2 Dividers between the panes of a MasterDetail object. Now these dividers could have been made focusable, but that becomes a pain for the user since they will take focus every time user tabs through.
Pressing F3 (can be configured), makes all such widgets focusable (toggle) such that arrow keys can be used for resizing adjacent widgets. However, pressing arrow keys on these widgets fires an event so the user can do custom resizing. Objects such as VimSplit also fire events for maximizing the current component in one keystroke, which can be bound by the app so custom resizing can be done.
In this version of the demo, i’ve moved to a TabularWidget, and allow the user to press Enter on the header row, so that column sorting can be done. I’ve done some crude sorting, whereas in reality the real data will be sorted from source.
In the image, when focus falls on the Divider (horizontal one on right middle), it becomes yellow, and displays up and down arrow keys. Similarly, when focus falls on the vertical one, it will light up and show left and right arrow keys. Pressing F3 will toggle focusability to make traversal easy.
gem install rbcurse --pre
I’ve been working on many new things … new control such as tree, vimsplits, dividers, scrollbars, progressbars, links — lost count of all the things I’ve added. Had to make some tiny changes htat are not backward compatible to make the widgets more usable.
Most importantly is the App class which allows the user to make applications. All the ncurses mumbo-jumbo and even the rbcurse incantations are neatly wrapped in an App.new call and your block contains the app. Also, all widgets are wrapped into methods much like Shoes does, so they are easy to call without having to know what all has to be called.
I’ve introduced stacks and flows (conceot copied from Shoes). Its rough but allows us to stack widgets and the stack does the placement. Similarly, we can horizontally place buttons. It’s rough since it’s not yet a class, so it does not hold information. It places the widgets once and for all on the screen. Stacks and flows don’t persist in any way as objects that can be manipulated later. That shall come later, without changing the API.
Much like vim and other terminal programs, you can now suspend work, show some information outside of ncurses and come back into your ncurses app. Or allow the user to use the shell and return.
I am focusing on user interface patterns such as MasterDetail – see sample appemail.rb (you need to point it to a local mbox). I’ve also used a tree control for directories and a Listbox for directories which allows user to click and go down directories. I intend separating these from their demos so they can be reused. They contain basic functionality and there’s a lot more that can be added to make them complete.
Another pattern is ColumnBrowse