diff --git a/src/bin/proxmox-backup-client.rs b/src/bin/proxmox-backup-client.rs index f2773370..f313344d 100644 --- a/src/bin/proxmox-backup-client.rs +++ b/src/bin/proxmox-backup-client.rs @@ -111,6 +111,58 @@ fn create_backup(param: Value, _info: &ApiMethod) -> Result { } +pub fn complete_file_name(arg: &str) -> Vec { + + let mut result = vec![]; + + use nix::fcntl::OFlag; + use nix::sys::stat::Mode; + use nix::fcntl::AtFlags; + + let mut dirname = std::path::PathBuf::from(arg); + + if let Ok(stat) = nix::sys::stat::fstatat(libc::AT_FDCWD, &dirname, AtFlags::empty()) { + + } else { + if let Some(parent) = dirname.parent() { + dirname = parent.to_owned(); + } + } + + let mut dir = match nix::dir::Dir::openat(libc::AT_FDCWD, &dirname, OFlag::O_DIRECTORY, Mode::empty()) { + Ok(d) => d, + Err(err) => { + return result; + } + }; + + for item in dir.iter() { + if let Ok(entry) = item { + if let Ok(name) = entry.file_name().to_str() { + if name == "." || name == ".." { continue; } + let mut newpath = dirname.clone(); + newpath.push(name); + + if let Ok(stat) = nix::sys::stat::fstatat(libc::AT_FDCWD, &newpath, AtFlags::empty()) { + if (stat.st_mode & libc::S_IFMT) == libc::S_IFDIR { + newpath.push(""); + if let Some(newpath) = newpath.to_str() { + result.push(newpath.to_owned()); + } + continue; + } + } + if let Some(newpath) = newpath.to_str() { + result.push(newpath.to_owned()); + } + + } + } + } + + result +} + fn main() { let cmd_def = CliCommand::new( @@ -129,6 +181,7 @@ fn main() { ) )) .arg_param(vec!["filename", "target"]) + .completion_cb("filename", complete_file_name) .completion_cb("store", proxmox_backup::config::datastore::complete_datastore_name); diff --git a/src/cli/command.rs b/src/cli/command.rs index e76ee0cf..87143d82 100644 --- a/src/cli/command.rs +++ b/src/cli/command.rs @@ -93,7 +93,7 @@ fn print_property_completion( arg: &str) { if let Some(callback) = completion_functions.get(name) { - let list = (callback)(); + let list = (callback)(arg); for value in list { if value.starts_with(arg) { println!("{}", value); @@ -271,7 +271,7 @@ pub fn run_cli_command(def: &CommandLineInterface) -> Result<(), Error> { Ok(()) } -pub type CompletionFunction = fn() -> Vec; +pub type CompletionFunction = fn(&str) -> Vec; pub struct CliCommand { pub info: ApiMethod, diff --git a/src/config/datastore.rs b/src/config/datastore.rs index 86a5f325..14540ea2 100644 --- a/src/config/datastore.rs +++ b/src/config/datastore.rs @@ -78,7 +78,7 @@ pub fn save_config(config: &SectionConfigData) -> Result<(), Error> { } // shell completion helper -pub fn complete_datastore_name() -> Vec { +pub fn complete_datastore_name(arg: &str) -> Vec { match config() { Ok(data) => data.sections.iter().map(|(id,_)| id.to_string()).collect(), Err(_) => return vec![],