summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Davison <dandavison7@gmail.com>2021-03-05 23:38:54 -0500
committerGitHub <noreply@github.com>2021-03-05 23:38:54 -0500
commit2619d07fa4ee701a19a08351ac4d3e7622e42877 (patch)
tree757e8b066611963ecb8183fe8379a1da06500de6
parent4fb55fa820aac3e4e534000bf65dc5050ec0630b (diff)
237 navigate improvement (#526)
* Change less invocation under navigate Thanks @cben * Don't pass regexp to less * Append navigate regexp to transient copy of less history file * Rustfmt * Store delta less hist file in XDG data directory * Don't use xdg on Windows * Fix conditional compilation for Windows * Get rid of advice not to use keep navigate feature activated
-rw-r--r--Cargo.lock7
-rw-r--r--Cargo.toml1
-rw-r--r--README.md8
-rw-r--r--src/bat_utils/output.rs6
-rw-r--r--src/features/navigate.rs86
5 files changed, 98 insertions, 10 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 3202a38d..26fa783a 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -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"
diff --git a/Cargo.toml b/Cargo.toml
index 78e8917b..9ec2e10a 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -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"
diff --git a/README.md b/README.md
index d94b23f3..a93a2788 100644
--- a/README.md
+++ b/README.md
@@ -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;