Command mode: Per command completers.

imgbot
Blaž Hrastnik 3 years ago
parent 87e7a0de3f
commit ff84c8e394

@ -814,6 +814,7 @@ mod cmd {
use std::collections::HashMap; use std::collections::HashMap;
use helix_view::editor::Action; use helix_view::editor::Action;
use ui::completers::{self, Completer};
#[derive(Clone)] #[derive(Clone)]
pub struct Command { pub struct Command {
@ -822,6 +823,7 @@ mod cmd {
pub doc: &'static str, pub doc: &'static str,
// params, flags, helper, completer // params, flags, helper, completer
pub fun: fn(&mut Editor, &[&str], PromptEvent), pub fun: fn(&mut Editor, &[&str], PromptEvent),
pub completer: Option<Completer>,
} }
fn quit(editor: &mut Editor, args: &[&str], event: PromptEvent) { fn quit(editor: &mut Editor, args: &[&str], event: PromptEvent) {
@ -878,30 +880,35 @@ mod cmd {
alias: Some("q"), alias: Some("q"),
doc: "Close the current view.", doc: "Close the current view.",
fun: quit, fun: quit,
completer: None,
}, },
Command { Command {
name: "quit!", name: "quit!",
alias: Some("q!"), alias: Some("q!"),
doc: "Close the current view.", doc: "Close the current view.",
fun: force_quit, fun: force_quit,
completer: None,
}, },
Command { Command {
name: "open", name: "open",
alias: Some("o"), alias: Some("o"),
doc: "Open a file from disk into the current view.", doc: "Open a file from disk into the current view.",
fun: open, fun: open,
completer: Some(completers::filename),
}, },
Command { Command {
name: "write", name: "write",
alias: Some("w"), alias: Some("w"),
doc: "Write changes to disk.", doc: "Write changes to disk.",
fun: write, fun: write,
completer: Some(completers::filename),
}, },
Command { Command {
name: "new", name: "new",
alias: Some("n"), alias: Some("n"),
doc: "Create a new scratch buffer.", doc: "Create a new scratch buffer.",
fun: new_file, fun: new_file,
completer: Some(completers::filename),
}, },
]; ];
@ -920,14 +927,17 @@ mod cmd {
} }
pub fn command_mode(cx: &mut Context) { pub fn command_mode(cx: &mut Context) {
// TODO: completion items should have a info section that would get displayed in
// a popup above the prompt when items are tabbed over
let prompt = Prompt::new( let prompt = Prompt::new(
":".to_owned(), ":".to_owned(),
|input: &str| { |input: &str| {
// we use .this over split_ascii_whitespace() because we care about empty segments // we use .this over split_ascii_whitespace() because we care about empty segments
let parts = input.split(' ').collect::<Vec<&str>>(); let parts = input.split(' ').collect::<Vec<&str>>();
// simple heuristic: if there's no space, complete command. // simple heuristic: if there's no just one part, complete command name.
// if there's a space, file completion kicks in. We should specialize by command later. // if there's a space, per command completion kicks in.
if parts.len() <= 1 { if parts.len() <= 1 {
use std::{borrow::Cow, ops::Range}; use std::{borrow::Cow, ops::Range};
let end = 0..; let end = 0..;
@ -938,7 +948,13 @@ pub fn command_mode(cx: &mut Context) {
.collect() .collect()
} else { } else {
let part = parts.last().unwrap(); let part = parts.last().unwrap();
ui::completers::filename(part)
if let Some(cmd::Command {
completer: Some(completer),
..
}) = cmd::COMMANDS.get(parts[0])
{
completer(part)
.into_iter() .into_iter()
.map(|(range, file)| { .map(|(range, file)| {
// offset ranges to input // offset ranges to input
@ -947,10 +963,9 @@ pub fn command_mode(cx: &mut Context) {
(range, file) (range, file)
}) })
.collect() .collect()
} else {
// TODO Vec::new()
// additionally, completion items could have a info section that would get }
// displayed in a popup above the prompt when items are tabbed over
} }
}, // completion }, // completion
move |editor: &mut Editor, input: &str, event: PromptEvent| { move |editor: &mut Editor, input: &str, event: PromptEvent| {

@ -114,6 +114,9 @@ pub fn file_picker(root: PathBuf) -> Picker<PathBuf> {
pub mod completers { pub mod completers {
use crate::ui::prompt::Completion; use crate::ui::prompt::Completion;
use std::borrow::Cow; use std::borrow::Cow;
pub type Completer = fn(&str) -> Vec<Completion>;
// TODO: we could return an iter/lazy thing so it can fetch as many as it needs. // TODO: we could return an iter/lazy thing so it can fetch as many as it needs.
pub fn filename(input: &str) -> Vec<Completion> { pub fn filename(input: &str) -> Vec<Completion> {
// Rust's filename handling is really annoying. // Rust's filename handling is really annoying.

Loading…
Cancel
Save