1
//! Command-line palette completion helpers.
2

            
3
use crate::app::App;
4
use crate::palette;
5
use crate::widgets::Editor;
6
use cli_core::{command_tree, complete};
7

            
8
/// Complete the trailing command-line token using the command tree, leaving
9
/// the cursor at the end of the rebuilt buffer.
10
///
11
/// With one candidate the token is replaced and a trailing space appended.
12
/// With multiple candidates the longest common prefix is applied and all
13
/// candidates are stored in `app.cmdline.completions` for display.
14
6
pub(super) fn apply_command_completion(app: &mut App) {
15
6
    let buffer = app.cmdline.editor.buffer().to_string();
16
6
    let tree = command_tree();
17
6
    let candidates = complete(&tree, &buffer);
18
6
    let lcp = palette::longest_common_prefix(&candidates);
19
6
    let new_buffer = build_completed_buffer(&buffer, &candidates, &lcp);
20
6
    if new_buffer != buffer {
21
1
        app.cmdline.editor = Editor::with_buffer(app.edit_mode, new_buffer);
22
5
    }
23
6
    app.cmdline.completions = candidates;
24
6
}
25

            
26
6
fn build_completed_buffer(buffer: &str, candidates: &[String], lcp: &str) -> String {
27
6
    if lcp.is_empty() {
28
4
        buffer.to_string()
29
2
    } else if candidates.len() == 1 {
30
1
        format!("{} ", replace_last_token(buffer, lcp))
31
    } else {
32
1
        replace_last_token(buffer, lcp)
33
    }
34
6
}
35

            
36
2
fn replace_last_token(buffer: &str, completion: &str) -> String {
37
2
    if buffer.ends_with(' ') {
38
        format!("{buffer}{completion}")
39
    } else {
40
2
        let start = buffer.rfind(' ').map_or(0, |i| i + 1);
41
2
        format!("{}{completion}", &buffer[..start])
42
    }
43
2
}