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

Code before:
#[derive(Clone)]
pub struct CustomCommandWithAnyArgs;

impl Command for CustomCommandWithAnyArgs {
    fn name(&self) -> &str {
        "list"
    }

    fn description(&self) -> &str {
        "Mock def command."
    }

    fn signature(&self) -> Signature {
        Signature::build("list").rest("args", SyntaxShape::Any, "rest of the arguments")
    }

    fn run(
        &self,
        _engine_state: &EngineState,
        _stack: &mut Stack,
        _call: &Call,
        _input: PipelineData,
    ) -> Result<PipelineData, ShellError> {
        todo!()
    }
}

#[test]
fn custom_command_completions() {
    // Create a new engine
    let (dir, dir_str, mut engine, stack) = new_engine();
    let delta = {
        let mut working_set = StateWorkingSet::new(&engine);
        working_set.add_decl(Box::new(CustomCommandWithAnyArgs));
        working_set.render()
    };
    engine.merge_delta(delta).expect("Failed to merge delta");

    // Instantiate a new completer
    let mut completer = NuCompleter::new(Arc::new(engine), Arc::new(stack));

    // Test completions for the current folder
    let target_dir = format!("list {dir_str}{MAIN_SEPARATOR}");
    let suggestions = completer.complete(&target_dir, target_dir.len());

    // Create the expected values
    let expected_paths: Vec<String> = vec![
        folder(dir.join("another")),
        file(dir.join("custom_completion.nu")),
        folder(dir.join("directory_completion")),
        file(dir.join("nushell")),

Review comment (suggestion):
Rather than defining this in Rust, I think you could do the following to make it shorter.
```
let command = r#"def list [ ...args: any ] {}"#;
assert!(support::merge_input(command.as_bytes(), &mut engine, &mut stack).is_ok());
```
There are other places in this file doing that, see https://github.com/nushell/nushell/blob/88d27fd607cabf860843981532921338264c7e30/crates/nu-cli/tests/completions/mod.rs#L46 as an example.

Code after:
    let command = r#"def list [ ...args: any ] {}"#;
    assert!(support::merge_input(command.as_bytes(), &mut engine, &mut stack).is_ok());

    // Instantiate a new completer
    let mut completer = NuCompleter::new(Arc::new(engine), Arc::new(stack));

    // Test completions for the current folder
    let target_dir = format!("list {dir_str}{MAIN_SEPARATOR}");
    let suggestions = completer.complete(&target_dir, target_dir.len());

    // Create the expected values
    let expected_paths: Vec<String> = vec![
        folder(dir.join("another")),
        file(dir.join("custom_completion.nu")),
        folder(dir.join("directory_completion")),
        file(dir.join("nushell")),
        folder(dir.join("test_a")),
        folder(dir.join("test_b")),
        file(dir.join(".hidden_file")),
        folder(dir.join(".hidden_folder")),
    ];

    // Match the results
    match_suggestions(&expected_paths, &suggestions);

    // Test completions for the current folder even with parts before the autocomplet
    let target_dir = format!("list somefile.txt {dir_str}{MAIN_SEPARATOR}");
    let suggestions = completer.complete(&target_dir, target_dir.len());

    // Create the expected values
    let expected_paths: Vec<String> = vec![
        folder(dir.join("another")),
        file(dir.join("custom_completion.nu")),
        folder(dir.join("directory_completion")),
        file(dir.join("nushell")),
        folder(dir.join("test_a")),
        folder(dir.join("test_b")),
        file(dir.join(".hidden_file")),
        folder(dir.join(".hidden_folder")),
    ];

    // Match the results
    match_suggestions(&expected_paths, &suggestions);

    // Test completions for a file
    let target_dir = format!("list {}", folder(dir.join("another")));
    let suggestions = completer.complete(&target_dir, target_dir.len());

    // Create the expected values
    let expected_paths: Vec<String> = vec![file(dir.join("another").join("newfile"))];