diff options
author | Thomas Otto <th1000s@posteo.net> | 2021-11-10 22:55:07 +0100 |
---|---|---|
committer | Dan Davison <dandavison7@gmail.com> | 2021-11-14 14:32:03 -0500 |
commit | b1a7521932d6dea2482ed00cde46b393613dbaec (patch) | |
tree | 3c66b4b962eed10fafaef71effc2e4c0e0e19db7 | |
parent | 88677dc92938fbbfe92ec676891f28b51de15485 (diff) |
Util: check parent process for filename
Usecase: With delta used as a pager the command `git blame main.rs` calls
delta, but the piped data does not mention the filename. Instead try to
get the filename extension from the parent `git` process.
-rw-r--r-- | Cargo.lock | 37 | ||||
-rw-r--r-- | Cargo.toml | 7 | ||||
-rw-r--r-- | src/main.rs | 1 | ||||
-rw-r--r-- | src/utils.rs | 91 |
4 files changed, 136 insertions, 0 deletions
@@ -180,6 +180,12 @@ dependencies = [ ] [[package]] +name = "core-foundation-sys" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" + +[[package]] name = "crc32fast" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -240,6 +246,12 @@ dependencies = [ ] [[package]] +name = "doc-comment" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" + +[[package]] name = "either" version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -334,6 +346,7 @@ dependencies = [ "smol_str", "structopt", "syntect", + "sysinfo", "unicode-segmentation", "unicode-width", "vte", @@ -566,6 +579,15 @@ dependencies = [ ] [[package]] +name = "ntapi" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44" +dependencies = [ + "winapi", +] + +[[package]] name = "num-integer" version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -869,6 +891,21 @@ dependencies = [ ] [[package]] +name = "sysinfo" +version = "0.19.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e7de153d0438a648bb71e06e300e54fc641685e96af96d49b843f43172d341c" +dependencies = [ + "cfg-if 1.0.0", + "core-foundation-sys", + "doc-comment", + "libc", + "ntapi", + "once_cell", + "winapi", +] + +[[package]] name = "termcolor" version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -47,6 +47,13 @@ version = "4.6.0" default-features = false features = ["parsing", "assets", "yaml-load", "dump-load", "regex-onig"] +[dependencies.sysinfo] +# 0.20.* requires rustc 1.54 +version = "0.19.2" +# no default features to disable the use of threads +default-features = false +features = [] + [dependencies.error-chain] version = "0.12.4" default-features = false diff --git a/src/main.rs b/src/main.rs index 0955f90d..64395de1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -22,6 +22,7 @@ mod options; mod paint; mod parse_style; mod style; +mod utils; mod wrapping; mod subcommands; diff --git a/src/utils.rs b/src/utils.rs new file mode 100644 index 00000000..56bec668 --- /dev/null +++ b/src/utils.rs @@ -0,0 +1,91 @@ +use sysinfo::{Pid, ProcessExt, SystemExt}; + +#[cfg(test)] +const SKIP_ARGS: usize = 1; +#[cfg(not(test))] +const SKIP_ARGS: usize = 2; + +fn guess_filename_extension_from_args(args: &[String]) -> Option<String> { + let mut saw_dash_dash = false; + // skip "git blame" (but during testing only "cargo", not "test" as well) + for x in args.iter().skip(SKIP_ARGS) { + if x == "--" { + saw_dash_dash = true; + continue; + } + if saw_dash_dash || !x.starts_with('-') { + return x.split('.').last().map(str::to_owned); + } + } + + None +} + +pub fn parent_filename_extension() -> Option<String> { + process_parent_cmd_args(guess_filename_extension_from_args) +} + +fn process_parent_cmd_args<F>(f: F) -> Option<String> +where + F: Fn(&[String]) -> Option<String>, +{ + let mut info = sysinfo::System::new(); + + let my_pid = std::process::id() as Pid; + info.refresh_process(my_pid).then(|| ())?; + + let parent_pid = info.process(my_pid)?.parent()?; + info.refresh_process(parent_pid).then(|| ())?; + let parent_process = info.process(parent_pid)?; + + f(parent_process.cmd()) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_guess_filename_extension_from_args() { + fn make_string_vec(args: &[&str]) -> Vec<String> { + args.iter().map(|&x| x.to_owned()).collect::<Vec<String>>() + } + let args = make_string_vec(&["blame", "hello.txt"]); + assert_eq!( + guess_filename_extension_from_args(&args), + Some("txt".into()) + ); + + let args = make_string_vec(&["blame", "-s", "-f", "--", "hello.txt"]); + assert_eq!( + guess_filename_extension_from_args(&args), + Some("txt".into()) + ); + + let args = make_string_vec(&["blame", "--", "--not.an.argument"]); + assert_eq!( + guess_filename_extension_from_args(&args), + Some("argument".into()) + ); + + let args = make_string_vec(&["blame", "--help.txt"]); + assert_eq!(guess_filename_extension_from_args(&args), None); + + let args = make_string_vec(&["blame", "README"]); + assert_eq!( + guess_filename_extension_from_args(&args), + Some("README".into()) + ); + } + + #[test] + fn test_process_parent_cmd_args() { + let _ = parent_filename_extension(); + let parent_arg0 = process_parent_cmd_args(|args| { + // tests that caller is something like "cargo test" + assert!(args.iter().any(|a| a == "test")); + Some(args[0].clone()) + }); + assert!(parent_arg0.is_some()); + } +} |