mirror of
https://github.com/nushell/reedline.git
synced 2024-09-11 15:55:50 +03:00
* get correct cursor pos when menu indicator contains newline * add tests * fix cursor pos in multiline prompt * make description mode enum public * add doc comment * respect windows newline in update_values * Revert "respect windows newline in update_values" This reverts commit070d600545
. * add complete_with_base_ranges to Completer * add builder for correct_cursor_pos * add config options to completion examples * add style to ide menu * run fmt * start menu refactor * Revert "start menu refactor" This reverts commit62726f29be
. * start menu refactor * fix ci * use MenuSettings struct * add test case for unix newline * more tests * fix newline replace * add explicit panic to stay backwards compatible * fix ci * Update columnar_menu.rs Co-authored-by: Yash Thakur <45539777+ysthakur@users.noreply.github.com> --------- Co-authored-by: Yash Thakur <45539777+ysthakur@users.noreply.github.com>
132 lines
4.5 KiB
Rust
132 lines
4.5 KiB
Rust
// Create a reedline object with tab completions support
|
|
// cargo run --example completions
|
|
//
|
|
// "t" [Tab] will allow you to select the completions "test" and "this is the reedline crate"
|
|
// [Enter] to select the chosen alternative
|
|
|
|
use reedline::{
|
|
default_emacs_keybindings, DefaultCompleter, DefaultPrompt, DescriptionMode, EditCommand,
|
|
Emacs, IdeMenu, KeyCode, KeyModifiers, Keybindings, MenuBuilder, Reedline, ReedlineEvent,
|
|
ReedlineMenu, Signal,
|
|
};
|
|
use std::io;
|
|
|
|
fn add_menu_keybindings(keybindings: &mut Keybindings) {
|
|
keybindings.add_binding(
|
|
KeyModifiers::NONE,
|
|
KeyCode::Tab,
|
|
ReedlineEvent::UntilFound(vec![
|
|
ReedlineEvent::Menu("completion_menu".to_string()),
|
|
ReedlineEvent::MenuNext,
|
|
]),
|
|
);
|
|
keybindings.add_binding(
|
|
KeyModifiers::ALT,
|
|
KeyCode::Enter,
|
|
ReedlineEvent::Edit(vec![EditCommand::InsertNewline]),
|
|
);
|
|
}
|
|
|
|
fn main() -> io::Result<()> {
|
|
// Min width of the completion box, including the border
|
|
let min_completion_width: u16 = 0;
|
|
// Max width of the completion box, including the border
|
|
let max_completion_width: u16 = 50;
|
|
// Max height of the completion box, including the border
|
|
let max_completion_height = u16::MAX;
|
|
// Padding inside of the completion box (on the left and right side)
|
|
let padding: u16 = 0;
|
|
// Whether to draw the default border around the completion box
|
|
let border: bool = false;
|
|
// Offset of the cursor from the top left corner of the completion box
|
|
// By default the top left corner is below the cursor
|
|
let cursor_offset: i16 = 0;
|
|
// How the description should be aligned
|
|
let description_mode: DescriptionMode = DescriptionMode::PreferRight;
|
|
// Min width of the description box, including the border
|
|
let min_description_width: u16 = 0;
|
|
// Max width of the description box, including the border
|
|
let max_description_width: u16 = 50;
|
|
// Distance between the completion and the description box
|
|
let description_offset: u16 = 1;
|
|
// If true, the cursor pos will be corrected, so the suggestions match up with the typed text
|
|
// ```text
|
|
// C:\> str
|
|
// str join
|
|
// str trim
|
|
// str split
|
|
// ```
|
|
// If a border is being used
|
|
let correct_cursor_pos: bool = false;
|
|
|
|
let commands = vec![
|
|
"test".into(),
|
|
"clear".into(),
|
|
"exit".into(),
|
|
"history 1".into(),
|
|
"history 2".into(),
|
|
"logout".into(),
|
|
"login".into(),
|
|
"hello world".into(),
|
|
"hello world reedline".into(),
|
|
"hello world something".into(),
|
|
"hello world another".into(),
|
|
"hello world 1".into(),
|
|
"hello world 2".into(),
|
|
"hello another very large option for hello word that will force one column".into(),
|
|
"this is the reedline crate".into(),
|
|
"abaaabas".into(),
|
|
"abaaacas".into(),
|
|
"ababac".into(),
|
|
"abacaxyc".into(),
|
|
"abadarabc".into(),
|
|
];
|
|
|
|
let completer = Box::new(DefaultCompleter::new_with_wordlen(commands, 2));
|
|
|
|
// Use the interactive menu to select options from the completer
|
|
let mut ide_menu = IdeMenu::default()
|
|
.with_name("completion_menu")
|
|
.with_min_completion_width(min_completion_width)
|
|
.with_max_completion_width(max_completion_width)
|
|
.with_max_completion_height(max_completion_height)
|
|
.with_padding(padding)
|
|
.with_cursor_offset(cursor_offset)
|
|
.with_description_mode(description_mode)
|
|
.with_min_description_width(min_description_width)
|
|
.with_max_description_width(max_description_width)
|
|
.with_description_offset(description_offset)
|
|
.with_correct_cursor_pos(correct_cursor_pos);
|
|
|
|
if border {
|
|
ide_menu = ide_menu.with_default_border();
|
|
}
|
|
|
|
let completion_menu = Box::new(ide_menu);
|
|
|
|
let mut keybindings = default_emacs_keybindings();
|
|
add_menu_keybindings(&mut keybindings);
|
|
|
|
let edit_mode = Box::new(Emacs::new(keybindings));
|
|
|
|
let mut line_editor = Reedline::create()
|
|
.with_completer(completer)
|
|
.with_menu(ReedlineMenu::EngineCompleter(completion_menu))
|
|
.with_edit_mode(edit_mode);
|
|
|
|
let prompt = DefaultPrompt::default();
|
|
|
|
loop {
|
|
let sig = line_editor.read_line(&prompt)?;
|
|
match sig {
|
|
Signal::Success(buffer) => {
|
|
println!("We processed: {buffer}");
|
|
}
|
|
Signal::CtrlD | Signal::CtrlC => {
|
|
println!("\nAborted!");
|
|
break Ok(());
|
|
}
|
|
}
|
|
}
|
|
}
|