Skip to content

Common prefix inserted when selecting an item in columnar menu #912

Open
@jabdinghoff

Description

@jabdinghoff

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-CompletionsArea: Tab completion and inline hint completionsbugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions