diff options
| author | Jonas Maier <> | 2026-03-17 15:32:30 +0100 |
|---|---|---|
| committer | Jonas Maier <> | 2026-03-17 15:32:30 +0100 |
| commit | 89e027f61eda0d918ee2c2622f6ad370a76c5754 (patch) | |
| tree | bca51022f83e6bf477312fdb03976da8b9c86cd0 /src | |
| parent | 965196972fa27237b6cb97209c915381a95a5bef (diff) | |
| download | pish-89e027f61eda0d918ee2c2622f6ad370a76c5754.tar.gz | |
completion when using path in place of command
Diffstat (limited to 'src')
| -rw-r--r-- | src/completion.rs | 22 | ||||
| -rw-r--r-- | src/parse/mod.rs | 10 |
2 files changed, 27 insertions, 5 deletions
diff --git a/src/completion.rs b/src/completion.rs index c7a183f..d3e4704 100644 --- a/src/completion.rs +++ b/src/completion.rs @@ -2,6 +2,7 @@ use crate::parse::{self, CompletionContext}; use crate::{BString, Session}; use std::collections::HashMap; use std::ffi::OsStr; +use std::fs::DirEntry; use std::os::unix::ffi::OsStrExt; use std::path::{Path, PathBuf}; use std::sync::{Arc, Mutex}; @@ -12,7 +13,10 @@ pub struct Suggestion { pub delta: BString, } -fn _path_completion(mut prefix: BString) -> std::io::Result<Vec<Suggestion>> { +fn _path_completion( + mut prefix: BString, + filter: &dyn Fn(&DirEntry) -> bool, +) -> std::io::Result<Vec<Suggestion>> { let mut partial_entry = BString::new(); while let Some(c) = prefix.last().cloned() { if c == b'/' { @@ -31,6 +35,9 @@ fn _path_completion(mut prefix: BString) -> std::io::Result<Vec<Suggestion>> { for entry in fs::read_dir(OsStr::from_bytes(&prefix))? { let entry = entry?; + if !filter(&entry) { + continue; + } let name = entry.file_name().as_bytes().to_vec(); if name.starts_with(&partial_entry) { let mut delta = name[partial_entry.len()..].to_vec(); @@ -53,7 +60,17 @@ fn _path_completion(mut prefix: BString) -> std::io::Result<Vec<Suggestion>> { } pub fn path_completion(prefix: BString) -> Vec<Suggestion> { - match _path_completion(prefix) { + match _path_completion(prefix, &|_| true) { + Ok(suggestions) => suggestions, + Err(err) => { + println!("path completion failed: {err:?}\r"); + Vec::new() + } + } +} + +pub fn path_exe_completion(prefix: BString) -> Vec<Suggestion> { + match _path_completion(prefix, &|d| is_executable(&d.path())) { Ok(suggestions) => suggestions, Err(err) => { println!("path completion failed: {err:?}\r"); @@ -165,6 +182,7 @@ pub fn completion(session: Arc<Mutex<Session>>, cmd: &[u8]) -> CompletionResult let mut suggestions = match comp.kind { parse::CompletionKind::Command => command_completion(session.clone(), comp.partial), + parse::CompletionKind::PathCommand => path_exe_completion(comp.partial), parse::CompletionKind::Argument => path_completion(comp.partial), parse::CompletionKind::Variable => variable_completion(session.clone(), comp.partial), parse::CompletionKind::None => return CompletionResult::empty(), diff --git a/src/parse/mod.rs b/src/parse/mod.rs index e085f34..006fce2 100644 --- a/src/parse/mod.rs +++ b/src/parse/mod.rs @@ -1,4 +1,4 @@ -use crate::BString; +use crate::{BString, run::CommandKind}; #[cfg(test)] mod test; @@ -797,9 +797,10 @@ pub fn do_parse(x: &[u8]) -> Res<Ast<PreExpansion>, (ParseError, &[u8])> { } } -#[derive(Debug)] +#[derive(Debug, PartialEq)] pub enum CompletionKind { Command, + PathCommand, Argument, Variable, None, @@ -840,7 +841,7 @@ impl Ast<PreExpansion> { } impl ExpString { - fn completion<E: Expander>(&self, e: &mut E, kind: CompletionKind) -> CompletionContext { + fn completion<E: Expander>(&self, e: &mut E, mut kind: CompletionKind) -> CompletionContext { if let Some(StringPart::Var(var)) = self.parts.last() && !var.already_complete { @@ -853,6 +854,9 @@ impl ExpString { { cmd.cmd.completion(e) } else if let Ok(s) = self.clone().expand(e) { + if s.contains(&b'/') && kind == CompletionKind::Command { + kind = CompletionKind::PathCommand; + } CompletionContext { kind, partial: s } } else { CompletionContext::none() |
