diff options
-rw-r--r-- | Cargo.lock | 7 | ||||
-rw-r--r-- | Cargo.toml | 1 | ||||
-rw-r--r-- | README.md | 8 | ||||
-rw-r--r-- | src/bat_utils/output.rs | 6 | ||||
-rw-r--r-- | src/features/navigate.rs | 86 |
5 files changed, 98 insertions, 10 deletions
@@ -279,6 +279,7 @@ dependencies = [ "unicode-segmentation", "unicode-width", "vte", + "xdg", ] [[package]] @@ -900,6 +901,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] +name = "xdg" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d089681aa106a86fade1b0128fb5daf07d5867a509ab036d99988dec80429a57" + +[[package]] name = "xml-rs" version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -31,6 +31,7 @@ structopt = "0.3.21" unicode-segmentation = "1.7.1" unicode-width = "0.1.8" vte = "0.10.0" +xdg = "2.2.0" [dependencies.git2] version = "0.13.17" @@ -448,14 +448,6 @@ In order to support this feature, Delta has to look at the raw colors it receive Use the `navigate` feature to activate navigation keybindings. In this mode, pressing `n` will jump forward to the next file in the diff, and `N` will jump backwards. If you are viewing multiple commits (e.g. via `git log -p`) then navigation will also visit commit boundaries. -The recommended way to use `navigate` is to activate it only when needed, for example - -```bash -git -c delta.navigate=true log -p -``` - -The reason that `navigate` should not be used all the time is that Delta uses `less` as its pager, and the `navigate` feature works by doing `less --pattern <regex-matching-file-and-commit-lines>`. When the git output does not contain file/commit diff lines, `less --pattern` behaves unhelpfully (see [#234](https://github.com/dandavison/delta/issues/234), [#237](https://github.com/dandavison/delta/issues/237)). - ### 24 bit color (truecolor) diff --git a/src/bat_utils/output.rs b/src/bat_utils/output.rs index 79b33bd4..8e959eb7 100644 --- a/src/bat_utils/output.rs +++ b/src/bat_utils/output.rs @@ -133,7 +133,11 @@ delta is not an appropriate value for $PAGER \ p }; if config.navigate { - process.args(&["--pattern", &navigate::make_navigate_regexp(&config)]); + if let Ok(hist_file) = + navigate::copy_less_hist_file_and_append_navigate_regexp(config) + { + process.env("LESSHISTFILE", hist_file); + } } Ok(process .env("LESSANSIENDCHARS", "mK") diff --git a/src/features/navigate.rs b/src/features/navigate.rs index 35549f24..81bab383 100644 --- a/src/features/navigate.rs +++ b/src/features/navigate.rs @@ -1,3 +1,8 @@ +use std::io::Write; +#[cfg(target_os = "windows")] +use std::io::{Error, ErrorKind}; +use std::path::PathBuf; + use crate::config::Config; use crate::features::OptionValueFunction; @@ -18,7 +23,7 @@ pub fn make_feature() -> Vec<(String, OptionValueFunction)> { ]) } -pub fn make_navigate_regexp(config: &Config) -> String { +fn make_navigate_regexp(config: &Config) -> String { format!( "^(commit|{}|{}|{}|{})", config.file_modified_label, @@ -28,6 +33,85 @@ pub fn make_navigate_regexp(config: &Config) -> String { ) } +// Create a less history file to be used by delta's child less process. This file is initialized +// with the contents of user's real less hist file, to which the navigate regexp is appended. This +// has the effect that 'n' or 'N' in delta's less process will search for the navigate regexp, +// without the undesirable aspects of using --pattern, yet without polluting the user's less search +// history with delta's navigate regexp. See +// https://github.com/dandavison/delta/issues/237#issuecomment-780654036. Note that with the +// current implementation, no writes to the delta less history file are propagated back to the real +// history file so, for example, a (non-navigate) search performed in the delta less process will +// not be stored in history. +pub fn copy_less_hist_file_and_append_navigate_regexp(config: &Config) -> std::io::Result<PathBuf> { + let delta_less_hist_file = get_delta_less_hist_file()?; + let initial_contents = "\ +.less-history-file: +.search +" + .to_string(); + let contents = if let Some(hist_file) = get_less_hist_file() { + std::fs::read_to_string(hist_file).unwrap_or(initial_contents) + } else { + initial_contents + }; + writeln!( + std::fs::File::create(&delta_less_hist_file)?, + "{}\"{}", + contents, + make_navigate_regexp(config) + )?; + Ok(delta_less_hist_file) +} + +#[cfg(target_os = "windows")] +fn get_delta_less_hist_file() -> std::io::Result<PathBuf> { + let mut path = dirs_next::home_dir() + .ok_or_else(|| Error::new(ErrorKind::NotFound, "Can't determine home dir"))?; + path.push(".delta.lesshst"); + Ok(path) +} + +#[cfg(not(target_os = "windows"))] +fn get_delta_less_hist_file() -> std::io::Result<PathBuf> { + let dir = xdg::BaseDirectories::with_prefix("delta")?; + dir.place_data_file("lesshst") +} + +// LESSHISTFILE +// Name of the history file used to remember search commands +// and shell commands between invocations of less. If set to +// "-" or "/dev/null", a history file is not used. The +// default is "$HOME/.lesshst" on Unix systems, +// "$HOME/_lesshst" on DOS and Windows systems, or +// "$HOME/lesshst.ini" or "$INIT/lesshst.ini" on OS/2 +// systems. +fn get_less_hist_file() -> Option<PathBuf> { + if let Some(home_dir) = dirs_next::home_dir() { + match std::env::var("LESSHISTFILE").as_deref() { + Ok("-") | Ok("/dev/null") => { + // The user has explicitly disabled less history. + None + } + Ok(path) => { + // The user has specified a custom histfile + Some(PathBuf::from(path)) + } + Err(_) => { + // The user is using the default less histfile location. + let mut hist_file = home_dir.clone(); + hist_file.push(if cfg!(windows) { + "_lesshst" + } else { + ".lesshst" + }); + Some(hist_file) + } + } + } else { + None + } +} + #[cfg(test)] mod tests { use std::fs::remove_file; |