Repository: nushell/nushell
File: crates/nu-cli/tests/completions/mod.rs (Rust)

Code before:
        def comp [] {
            {
                completions: [
                    { value: first, display_override: "\u{1b}[2mansi\u{1b}[3mrocks" },
                    { value: second, display_override: "sir\u{1b}[1mlancelot" },
                    { value: nonmatching, display_override: "asdf" },
                ],
                options: { completion_algorithm: "substring" }
            }
        }
        def my-command [arg: string@comp] {}"#;
    assert!(support::merge_input(command.as_bytes(), &mut engine, &mut stack).is_ok());

    let mut completer = NuCompleter::new(Arc::new(engine), Arc::new(stack));
    let completion_str = "my-command sir";
    let suggestions = completer.complete(completion_str, completion_str.len());
    match_suggestions(&vec!["first", "second"], &suggestions);
}

#[test]
fn custom_completions_strip_ansi_from_values() {
    let (_, _, mut engine, mut stack) = new_engine();
    // Completions with embedded ANSI escape codes should have them stripped
    let command = r#"
        def comp [] {
            [$"\u{1b}[35mfoo", $"\u{1b}[31mbar", $"\u{1b}[34mbaz"]
        }
        def my-command [arg: string@comp] {}"#;
    assert!(support::merge_input(command.as_bytes(), &mut engine, &mut stack).is_ok());

    let mut completer = NuCompleter::new(Arc::new(engine), Arc::new(stack));
    let completion_str = "my-command ";
    let suggestions = completer.complete(completion_str, completion_str.len());
    match_suggestions(&vec!["bar", "baz", "foo"], &suggestions);
}

#[test]
fn custom_completions_strip_ansi_from_record_values() {
    let (_, _, mut engine, mut stack) = new_engine();
    // Record-style completions with ANSI codes in the value field should be stripped
    let command = r#"
        def comp [] {
            {
                completions: [
                    { value: $"\u{1b}[35mmagenta_dir", description: "a zoxide dir" },
                    { value: "plain_dir", description: "a normal dir" },
                ],
                options: { sort: false }
            }
        }
        def my-command [arg: string@comp] {}"#;

Review comment (security):
Would be good to make one of these a hyperlink instead of all of them being for colors (hyperlinks are in the form `ESC ]8;;link ST` according to [Wikipedia](https://en.wikipedia.org/wiki/ANSI_escape_code#Operating_System_Command_sequences))

Code after:
        def comp [] {
            {
                completions: [
                    { value: first, display_override: "\u{1b}[2mansi\u{1b}[3mrocks" },
                    { value: second, display_override: "sir\u{1b}[1mlancelot" },
                    { value: nonmatching, display_override: "asdf" },
                ],
                options: { completion_algorithm: "substring" }
            }
        }
        def my-command [arg: string@comp] {}"#;
    assert!(support::merge_input(command.as_bytes(), &mut engine, &mut stack).is_ok());

    let mut completer = NuCompleter::new(Arc::new(engine), Arc::new(stack));
    let completion_str = "my-command sir";
    let suggestions = completer.complete(completion_str, completion_str.len());
    match_suggestions(&vec!["first", "second"], &suggestions);
}

#[test]
fn custom_completions_strip_ansi_from_values() {
    let (_, _, mut engine, mut stack) = new_engine();
    let command = r#"
        def comp [] {
            [$"\u{1b}[35mfoo", $"\u{1b}[31mbar", $"\u{1b}]8;;http://example.com\u{7}baz\u{1b}]8;;\u{7}"]
        }
        def my-command [arg: string@comp] {}"#;
    assert!(support::merge_input(command.as_bytes(), &mut engine, &mut stack).is_ok());

    let mut completer = NuCompleter::new(Arc::new(engine), Arc::new(stack));
    let completion_str = "my-command ";
    let suggestions = completer.complete(completion_str, completion_str.len());
    match_suggestions(&vec!["bar", "baz", "foo"], &suggestions);
}

#[test]
fn custom_completions_strip_ansi_from_record_values() {
    let (_, _, mut engine, mut stack) = new_engine();
    let command = r#"
        def comp [] {
            [{ value: $"\u{1b}[35mmagenta_dir" }, { value: "plain_dir" }]
        }
        def my-command [arg: string@comp] {}"#;
    assert!(support::merge_input(command.as_bytes(), &mut engine, &mut stack).is_ok());

    let mut completer = NuCompleter::new(Arc::new(engine), Arc::new(stack));
    let completion_str = "my-command ";
    let suggestions = completer.complete(completion_str, completion_str.len());
    match_suggestions(&vec!["magenta_dir", "plain_dir"], &suggestions);
}