summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Otto <th1000s@posteo.net>2021-11-10 22:55:07 +0100
committerDan Davison <dandavison7@gmail.com>2021-11-14 14:32:03 -0500
commitb1a7521932d6dea2482ed00cde46b393613dbaec (patch)
tree3c66b4b962eed10fafaef71effc2e4c0e0e19db7
parent88677dc92938fbbfe92ec676891f28b51de15485 (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.lock37
-rw-r--r--Cargo.toml7
-rw-r--r--src/main.rs1
-rw-r--r--src/utils.rs91
4 files changed, 136 insertions, 0 deletions
diff --git a/Cargo.lock b/Cargo.lock
index e1a845d3..65955aeb 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -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"
diff --git a/Cargo.toml b/Cargo.toml
index b58009c0..1f0d7c7d 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -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());
+ }
+}