mirror of https://github.com/helix-editor/helix
Improve auto completion for shell commands
This makes the very first argument of shell commands (like run-shell-command or pipe) auto complete programs instead of files.pull/12883/head
parent
0ee5850016
commit
28349fb8cf
|
@ -6315,7 +6315,7 @@ fn shell_prompt(cx: &mut Context, prompt: Cow<'static, str>, behavior: ShellBeha
|
||||||
cx,
|
cx,
|
||||||
prompt,
|
prompt,
|
||||||
Some('|'),
|
Some('|'),
|
||||||
ui::completers::filename,
|
ui::completers::shell,
|
||||||
move |cx, input: &str, event: PromptEvent| {
|
move |cx, input: &str, event: PromptEvent| {
|
||||||
if event != PromptEvent::Validate {
|
if event != PromptEvent::Validate {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -68,6 +68,13 @@ impl CommandCompleter {
|
||||||
var_args: completer,
|
var_args: completer,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const fn hybrid(completers: &'static [Completer], fallback: Completer) -> Self {
|
||||||
|
Self {
|
||||||
|
positional_args: completers,
|
||||||
|
var_args: fallback,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn quit(cx: &mut compositor::Context, _args: Args, event: PromptEvent) -> anyhow::Result<()> {
|
fn quit(cx: &mut compositor::Context, _args: Args, event: PromptEvent) -> anyhow::Result<()> {
|
||||||
|
|
|
@ -372,6 +372,7 @@ pub mod completers {
|
||||||
use super::Utf8PathBuf;
|
use super::Utf8PathBuf;
|
||||||
use crate::ui::prompt::Completion;
|
use crate::ui::prompt::Completion;
|
||||||
use helix_core::fuzzy::fuzzy_match;
|
use helix_core::fuzzy::fuzzy_match;
|
||||||
|
use helix_core::shellwords::Shellwords;
|
||||||
use helix_core::syntax::LanguageServerFeature;
|
use helix_core::syntax::LanguageServerFeature;
|
||||||
use helix_view::document::SCRATCH_BUFFER_NAME;
|
use helix_view::document::SCRATCH_BUFFER_NAME;
|
||||||
use helix_view::theme;
|
use helix_view::theme;
|
||||||
|
@ -677,4 +678,48 @@ pub mod completers {
|
||||||
.map(|(name, _)| ((0..), name.into()))
|
.map(|(name, _)| ((0..), name.into()))
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn program(_editor: &Editor, input: &str) -> Vec<Completion> {
|
||||||
|
static PROGRAMS_IN_PATH: Lazy<Vec<String>> = Lazy::new(|| {
|
||||||
|
// Go through the entire PATH and read all files into a vec.
|
||||||
|
let mut vec = std::env::var("PATH")
|
||||||
|
.unwrap_or("".to_owned())
|
||||||
|
.split(":")
|
||||||
|
.flat_map(|s| {
|
||||||
|
std::fs::read_dir(s)
|
||||||
|
.map_or_else(|_| vec![], |res| res.into_iter().collect::<Vec<_>>())
|
||||||
|
})
|
||||||
|
.filter_map(|it| it.ok())
|
||||||
|
.map(|f| f.path())
|
||||||
|
.filter(|p| !p.is_dir())
|
||||||
|
.filter_map(|p| p.file_name().and_then(|s| s.to_str().map(|s| s.to_owned())))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
// Paths can share programs like /bin and /usr/bin sometimes contain the same.
|
||||||
|
vec.dedup();
|
||||||
|
|
||||||
|
vec
|
||||||
|
});
|
||||||
|
|
||||||
|
fuzzy_match(input, PROGRAMS_IN_PATH.iter(), false)
|
||||||
|
.into_iter()
|
||||||
|
.map(|(name, _)| ((0..), name.clone().into()))
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn shell(editor: &Editor, input: &str) -> Vec<Completion> {
|
||||||
|
let shellwords = Shellwords::from(input);
|
||||||
|
let words = shellwords.words();
|
||||||
|
|
||||||
|
if words.len() > 1 || shellwords.ends_with_whitespace() {
|
||||||
|
let offset = words[0].len() + 1;
|
||||||
|
// Theoretically one could now parse bash completion scripts, but filename should suffice for now.
|
||||||
|
let mut completions = filename(editor, &input[offset..]);
|
||||||
|
for completion in completions.iter_mut() {
|
||||||
|
completion.0.start += offset;
|
||||||
|
}
|
||||||
|
return completions;
|
||||||
|
}
|
||||||
|
program(editor, input)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue