Open
Description
Platform: Windows 11 (24H2)
Terminal software : Windows Terminal (1.22.11141.0)
Nushell: 0.104.1
When I select an item in nushell from a columnar menu the common prefix is added as well.
This came up here nushell/nu_scripts#1126 (comment)
Steps to reproduce
A menu like
def __test_menu [] {
{
name: test_menu
only_buffer_difference: true
marker: "| "
type: {
layout: columnar
page_size: 3
}
style: {
text: blue
selected_text: blue_reverse
description_text: yellow
}
source: { |buffer, position|
[{description: 0, value: "AAAA"}, {description: 1, value: "AAAB"}, {description: 3, value:"AAAC"}]
}
}
}
def __test_keybinding [] {
{
name: test_menu
modifier: control
keycode: char_t
mode: [emacs, vi_normal, vi_insert]
event: [
{ send: menu name: test_menu }
]
}
}
export-env {
$env.config = ($env.config
| upsert menus ($env.config.menus | append (__test_menu))
| upsert keybindings ($env.config.keybindings | append [(__test_keybinding)])
)
}
Selecting AAAC
results in AAAAAAC
Screenshots/Screencaptures
WindowsTerminal_2aXQixvCET.mp4
Edit:
Maybe this isn't an issue with reedline itself? I tried to replicate this directly with reedline and it seems fine here:
//completer.rs
use reedline::{Completer, Span, Suggestion};
#[derive(Clone)]
pub struct Item {
pub value: String,
pub description: String,
}
pub struct TestMenuCompleter {
items: Vec<Item>,
}
impl TestMenuCompleter {
pub fn new() -> Self {
let items = vec![
Item {
value: "AAAA".to_string(),
description: "0".to_string(),
},
Item {
value: "AAAB".to_string(),
description: "1".to_string(),
},
Item {
value: "AAAC".to_string(),
description: "3".to_string(),
},
];
Self { items }
}
}
impl Completer for TestMenuCompleter {
fn complete(&mut self, _line: &str, pos: usize) -> Vec<Suggestion> {
self.items
.iter()
.map(|item| Suggestion {
value: item.value.clone(),
description: Some(item.description.clone()),
style: None,
extra: None,
span: Span::new(pos, pos),
append_whitespace: false,
})
.collect()
}
}
//main.rs
use nu_ansi_term::{Color, Style};
use reedline::{
ColumnarMenu, DefaultPrompt, Emacs, KeyCode, KeyModifiers, MenuBuilder, Reedline,
ReedlineEvent, ReedlineMenu, Signal,
};
mod completer;
use completer::TestMenuCompleter;
fn main() {
let completer = Box::new(TestMenuCompleter::new());
let mut columnar = ColumnarMenu::default().with_name("test_menu");
columnar = columnar.with_only_buffer_difference(true);
columnar = columnar.with_marker("| ");
columnar = columnar
.with_text_style(Style::new().fg(Color::Blue))
.with_selected_text_style(Style::new().fg(Color::Blue).reverse())
.with_description_text_style(Style::new().fg(Color::Yellow));
let mut keybindings = keybindings_default();
keybindings.add_binding(
KeyModifiers::NONE,
KeyCode::Tab,
ReedlineEvent::UntilFound(vec![
ReedlineEvent::Menu("test_menu".into()),
ReedlineEvent::MenuNext,
]),
);
let edit_mode = Box::new(Emacs::new(keybindings));
let mut line_editor = Reedline::create()
.with_completer(completer)
.with_menu(ReedlineMenu::EngineCompleter(Box::new(columnar)))
.with_edit_mode(edit_mode);
let prompt = DefaultPrompt::default();
loop {
match line_editor.read_line(&prompt) {
Ok(Signal::Success(buffer)) => {
println!("You entered: {}", buffer);
}
Ok(Signal::CtrlD) | Ok(Signal::CtrlC) => {
println!("\nExiting.");
break;
}
other => {
eprintln!("Unhandled event: {:?}", other);
break;
}
}
}
}
fn keybindings_default() -> reedline::Keybindings {
reedline::default_emacs_keybindings()
}
This outputs You entered: AAAC