The text buffer and editor keys¶
rich_interact::edit::Buffer is the editing under every text editor in the
project: rs-rich-interact's own TextArea, and intuiTUIve's text_area and
input. A fix to how the caret moves or how text is killed lands in all of
them. rich_interact::edit_keys names what an editor's keys do, and
rich_interact::vim (the vim feature) is a Vim preset over the buffer.
For the intuiTUIve options built on them, see
Editing text.
The buffer¶
use rich_interact::edit::{Buffer, Search};
let mut buffer = Buffer::new("one fish\ntwo fish");
buffer.kill_to_end(); // "one fish" onto the kill ring
buffer.yank(); // and back
buffer.set_search(Some(Search::plain("fish")));
buffer.select_match(true); // the first "fish", selected
assert_eq!(buffer.match_count(), 2);
- Editing:
insert,backspace,delete,delete_word,delete_next_word,delete_to_start,delete_to_end,indent,outdent,indent_lines,outdent_linesandreplace, each one undo step (a typed run is one);undoandredo. - Moves, each with a flag to select:
left,right,word_left,word_right,vertical,home,end,top,bottom,paragraph_upandparagraph_down(to the blank line before or after the paragraph).set_markmakes every move select until an edit orclear_mark, as Emacs's mark does. - The kill ring:
kill_to_end(at a line's end, the line break),kill_to_start,kill_word(the selection, else back to a space),kill_next_word,kill_previous_wordandkill(start, end, forward)delete and keep what they took; kills straight after each other join.yankputs the newest back, andyank_popright after it swaps in the one before, round the ring (sixteen kills).push_killputs text on it. - Search:
Search::plain(text),Search::regex(pattern)(fancy-regex, anErrwith the reason when it does not compile) and.ignore_case(true). Set one withset_search;matches(lines)gives the matches on some lines (what a view highlights),match_countandmatch_indexwhere the selection is among them,search_forwardandsearch_backmove the caret to the next or previous match andselect_matchselects it, round past the ends. - Settings:
set_limit(characters, grapheme clusters),set_history_limit(1000 undo steps by default;Nonekeeps them all),set_tab_width(4 cells by default, and the indent's width) andset_hard_tabs(indent with a tab).set_textkeeps them, the ring and the search. - Wrapping:
wrap_line(line, room, tab, mode)gives the rows a line takes, as byte ranges:WrapMode::Graphemebreaks at a character,WrapMode::Wordafter a space,WrapMode::Nonenot at all.
Editor keys¶
use rich_interact::edit::Buffer;
use rich_interact::edit_keys::{emacs_keymap, perform, resolve, Act};
use rich_interact::Key;
let keymap = emacs_keymap();
let mut buffer = Buffer::new("hello world");
if let Some((action, select)) = resolve(&keymap, Key::parse("alt+d").unwrap()) {
perform(&mut buffer, &action, Act { select, ..Act::default() });
}
editor_keymap()is the default (the arrows, Ctrl+A select all, Ctrl+Z/Ctrl+Y undo and redo, Ctrl+W/U/K delete), andemacs_keymap()the Emacs preset (Ctrl+F/B/N/P, Alt+F/B, Ctrl+A/E, kills and yanks, the mark). Both declare every action, in contexttext_area, so either can be rebound one action at a time and listed in a help.resolve(keymap, key)says which action a key does, and whether it selects: a key bound to nothing as it is tries itself without Shift (which then selects), without Alt, then without Ctrl.perform(buffer, action, act)does it:Outcome::Used,Outcome::Unused(an edit on read-only text, a vertical move in one line, Esc with nothing selected: the key goes on), orOutcome::Unknown(copyandcut, which need the app's clipboard).KeyModeis the hook for a modal preset: it sees each key first with the buffer (ModeCx), and saysUsed,Pass(edit as usual),Unused(to the app) orCopy(text); it can name a caret shape and a mode label.
caret::CaretShape (block, bar, underline) gives the DECSCUSR sequences
that set the terminal's cursor shape, and caret::RESET puts back the
user's.
The Vim preset (the vim feature)¶
vim::Vim is a KeyMode with Vim's normal, insert, visual and visual line
modes, its motions (hjkl wbe 0^$ gg G {} f t F T n N), the operators
d c y > < with motions or doubled, x X D C s S J r p P u and Ctrl+R,
counts, and .. intuiTUIve's .vim() puts it on a text area.
TextArea¶
The interact TextArea (rich write) runs on the same buffer, so the
kill ring, undo, paragraph moves and the rest are its actions too, bound to
no key by default: TextArea::rebind("yank", keys("ctrl+y")) binds one.
.emacs_keys() binds Emacs's: Ctrl+F/B/N/P and Alt+F/B move, Ctrl+K,
Ctrl+U, Ctrl+W, Alt+D and Alt+Backspace kill, Ctrl+Y and Alt+Y yank, and
Alt+{ and Alt+} move by paragraph.