Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'helix-term/src/ui/mod.rs')
| -rw-r--r-- | helix-term/src/ui/mod.rs | 61 |
1 files changed, 61 insertions, 0 deletions
diff --git a/helix-term/src/ui/mod.rs b/helix-term/src/ui/mod.rs index a76adbe2..47b046c9 100644 --- a/helix-term/src/ui/mod.rs +++ b/helix-term/src/ui/mod.rs @@ -371,6 +371,7 @@ fn directory_content(path: &Path) -> Result<Vec<(PathBuf, bool)>, std::io::Error pub mod completers { use super::Utf8PathBuf; use crate::ui::prompt::Completion; + use helix_core::command_line::{self, Tokenizer}; use helix_core::fuzzy::fuzzy_match; use helix_core::syntax::LanguageServerFeature; use helix_view::document::SCRATCH_BUFFER_NAME; @@ -378,6 +379,7 @@ pub mod completers { use helix_view::{editor::Config, Editor}; use once_cell::sync::Lazy; use std::borrow::Cow; + use std::collections::BTreeSet; use tui::text::Span; pub type Completer = fn(&Editor, &str) -> Vec<Completion>; @@ -677,4 +679,63 @@ pub mod completers { .map(|(name, _)| ((0..), name.into())) .collect() } + + pub fn program(_editor: &Editor, input: &str) -> Vec<Completion> { + static PROGRAMS_IN_PATH: Lazy<BTreeSet<String>> = Lazy::new(|| { + // Go through the entire PATH and read all files into a set. + let Some(path) = std::env::var_os("PATH") else { + return Default::default(); + }; + + std::env::split_paths(&path) + .filter_map(|path| std::fs::read_dir(path).ok()) + .flatten() + .filter_map(|res| { + let entry = res.ok()?; + if entry.metadata().ok()?.is_file() { + entry.file_name().into_string().ok() + } else { + None + } + }) + .collect() + }); + + fuzzy_match(input, PROGRAMS_IN_PATH.iter(), false) + .into_iter() + .map(|(name, _)| ((0..), name.clone().into())) + .collect() + } + + /// This expects input to be a raw string of arguments, because this is what Signature's raw_after does. + pub fn repeating_filenames(editor: &Editor, input: &str) -> Vec<Completion> { + let token = match Tokenizer::new(input, false).last() { + Some(token) => token.unwrap(), + None => return filename(editor, input), + }; + + let offset = token.content_start; + + let mut completions = filename(editor, &input[offset..]); + for completion in completions.iter_mut() { + completion.0.start += offset; + } + completions + } + + pub fn shell(editor: &Editor, input: &str) -> Vec<Completion> { + let (command, args, complete_command) = command_line::split(input); + + if complete_command { + return program(editor, command); + } + + let mut completions = repeating_filenames(editor, args); + for completion in completions.iter_mut() { + // + 1 for separator between `command` and `args` + completion.0.start += command.len() + 1; + } + + completions + } } |