summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDenis Isidoro <denisidoro@users.noreply.github.com>2023-12-10 06:20:08 -0300
committerGitHub <noreply@github.com>2023-12-10 06:20:08 -0300
commitb560ba572e43d64a58266614a36a9f17f60c2bfd (patch)
tree5fdb8aeea32f6177fce9136d0b489dad7bc1fb49
parent20c658a50334c56defe15978e5e8f9a05efe4de2 (diff)
parentea95dfec483d4d5f1ff5e474198eae62e7488b4d (diff)
Merge pull request #840 from zjp-CN/win
Fix multiple paths: define the platform-specific join separator
-rw-r--r--.gitignore1
-rw-r--r--Cargo.lock11
-rw-r--r--Cargo.toml3
-rw-r--r--docs/config_file.md6
-rw-r--r--docs/config_file_example.yaml11
-rw-r--r--src/bin/main.rs36
-rw-r--r--src/commands/core/actor.rs14
-rw-r--r--src/commands/core/mod.rs6
-rw-r--r--src/commands/mod.rs1
-rwxr-xr-xsrc/commands/preview/var_stdin.rs9
-rw-r--r--src/common/fs.rs5
-rw-r--r--src/config/cli.rs1
-rw-r--r--src/config/env.rs1
-rw-r--r--src/config/mod.rs3
-rw-r--r--src/config/yaml.rs16
-rw-r--r--src/filesystem.rs23
-rw-r--r--src/finder/mod.rs8
-rw-r--r--src/lib.rs4
18 files changed, 121 insertions, 38 deletions
diff --git a/.gitignore b/.gitignore
index 53eaa21..3f2d71b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
/target
**/*.rs.bk
+navi.log
diff --git a/Cargo.lock b/Cargo.lock
index bbdffee..a379f1b 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -245,6 +245,12 @@ dependencies = [
]
[[package]]
+name = "dunce"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b"
+
+[[package]]
name = "edit"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -412,9 +418,9 @@ dependencies = [
[[package]]
name = "log"
-version = "0.4.14"
+version = "0.4.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
+checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
dependencies = [
"cfg-if",
]
@@ -455,6 +461,7 @@ dependencies = [
"crossterm",
"dns_common",
"dns_common_derive",
+ "dunce",
"edit",
"etcetera",
"lazy_static",
diff --git a/Cargo.toml b/Cargo.toml
index a9dc3d1..fa054cc 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -37,6 +37,9 @@ dns_common_derive = { version = "0.2.1" }
dns_common = { version = "0.2.1", default-features = false, features = ["yaml", "json"] }
unicode-width = "0.1.10"
+[target.'cfg(windows)'.dependencies]
+dunce = "1"
+
[lib]
name = "navi"
path = "src/lib.rs"
diff --git a/docs/config_file.md b/docs/config_file.md
index d7db573..25498c0 100644
--- a/docs/config_file.md
+++ b/docs/config_file.md
@@ -29,3 +29,9 @@ Run the following command to generate a config file with the default parameters:
```sh
navi info config-example > "$(navi info config-path)"
```
+
+### Logging
+
+The log file will be created under the same directory where the config locates.
+
+And you can use the `RUST_LOG` env to set the log level, e.g. `RUST_LOG=debug navi`.
diff --git a/docs/config_file_example.yaml b/docs/config_file_example.yaml
index 2344dec..1eb7ab7 100644
--- a/docs/config_file_example.yaml
+++ b/docs/config_file_example.yaml
@@ -19,14 +19,17 @@ finder:
# overrides_var: --tac # equivalent to the --fzf-overrides-var option
# cheats:
-# paths:
-# - /path/to/some/dir
-# - /path/to/another/dir
+# paths:
+# - /path/to/some/dir # on unix-like os
+# - F:\\path\\to\\dir # on Windows
# path: /path/to/some/dir # (DEPRECATED) equivalent to the --path option
# search:
# tags: git,!checkout # equivalent to the --tag-rules option
shell:
- command: bash # shell used for shell out. possible values: bash, zsh, dash, ...
+ # Shell used for shell out. Possible values: bash, zsh, dash, ...
+ # For Windows, use `cmd.exe` instead.
+ command: bash
+
# finder_command: bash # similar, but for fzf's internals
diff --git a/src/bin/main.rs b/src/bin/main.rs
index ad67e71..8c4856a 100644
--- a/src/bin/main.rs
+++ b/src/bin/main.rs
@@ -1,6 +1,6 @@
extern crate navi;
-use std::fmt::Debug;
+use dns_common::prelude::*;
use thiserror::Error;
#[derive(Error, Debug)]
@@ -24,6 +24,36 @@ impl FileAnIssue {
}
}
-fn main() -> Result<(), anyhow::Error> {
- navi::handle().map_err(|e| FileAnIssue::new(e).into())
+fn main() -> anyhow::Result<()> {
+ if let Err(err) = init_logger() {
+ // may need redir stderr to a file to show this log initialization error
+ eprintln!("failed to initialize logging: {err:?}");
+ }
+ navi::handle().map_err(|e| {
+ error!("{e:?}");
+ FileAnIssue::new(e).into()
+ })
+}
+
+fn init_logger() -> anyhow::Result<()> {
+ const FILE_NAME: &str = "navi.log";
+ let mut file = navi::default_config_pathbuf()?;
+ file.set_file_name(FILE_NAME);
+
+ // If config path doesn't exist, navi won't log.
+ if file.parent().map(|p| !p.exists()).unwrap_or(true) {
+ return Ok(());
+ }
+
+ let writer = std::fs::File::create(&file).with_context(|| format!("{file:?} is not created"))?;
+ tracing::subscriber::set_global_default(
+ tracing_subscriber::fmt()
+ .with_ansi(false)
+ .with_writer(writer)
+ .with_env_filter(tracing_subscriber::EnvFilter::from_default_env())
+ .finish(),
+ )?;
+ debug!("tracing initialized");
+
+ Ok(())
}
diff --git a/src/commands/core/actor.rs b/src/commands/core/actor.rs
index 9d49717..91a1846 100644
--- a/src/commands/core/actor.rs
+++ b/src/commands/core/actor.rs
@@ -41,9 +41,10 @@ fn prompt_finder(
}
}
- let child = shell::out()
- .stdout(Stdio::piped())
- .arg(suggestion_command)
+ let mut cmd = shell::out();
+ cmd.stdout(Stdio::piped()).arg(suggestion_command);
+ debug!(cmd = ?cmd);
+ let child = cmd
.spawn()
.map_err(|e| ShellSpawnError::new(suggestion_command, e))?;
@@ -236,9 +237,10 @@ pub fn act(
clipboard::copy(interpolated_snippet)?;
}
_ => {
- shell::out()
- .arg(&interpolated_snippet[..])
- .spawn()
+ let mut cmd = shell::out();
+ cmd.arg(&interpolated_snippet[..]);
+ debug!(cmd = ?cmd);
+ cmd.spawn()
.map_err(|e| ShellSpawnError::new(&interpolated_snippet[..], e))?
.wait()
.context("bash was not running")?;
diff --git a/src/commands/core/mod.rs b/src/commands/core/mod.rs
index ded24f1..00e3a35 100644
--- a/src/commands/core/mod.rs
+++ b/src/commands/core/mod.rs
@@ -13,6 +13,7 @@ use crate::welcome;
pub fn init(fetcher: Box<dyn Fetcher>) -> Result<()> {
let config = &CONFIG;
let opts = FinderOpts::snippet_default();
+ debug!("opts = {opts:#?}");
// let fetcher = config.fetcher();
let (raw_selection, (variables, files)) = config
@@ -32,6 +33,7 @@ pub fn init(fetcher: Box<dyn Fetcher>) -> Result<()> {
})
.context("Failed getting selection and variables from finder")?;
+ debug!(raw_selection = ?raw_selection);
let extractions = deser::terminal::read(&raw_selection, config.best_match());
if extractions.is_err() {
@@ -44,7 +46,9 @@ pub fn init(fetcher: Box<dyn Fetcher>) -> Result<()> {
}
pub fn get_fetcher() -> Result<Box<dyn Fetcher>> {
- match CONFIG.source() {
+ let source = CONFIG.source();
+ debug!(source = ?source);
+ match source {
Source::Cheats(query) => {
let lines = cheatsh::call(&query)?;
let fetcher = Box::new(StaticFetcher::new(lines));
diff --git a/src/commands/mod.rs b/src/commands/mod.rs
index 783cbad..4537177 100644
--- a/src/commands/mod.rs
+++ b/src/commands/mod.rs
@@ -12,6 +12,7 @@ use crate::prelude::*;
pub fn handle() -> Result<()> {
use crate::config::Command::*;
+ debug!("CONFIG = {:#?}", &*CONFIG);
match CONFIG.cmd() {
None => commands::core::main(),
diff --git a/src/commands/preview/var_stdin.rs b/src/commands/preview/var_stdin.rs
index 4b8ddfb..78cc8ef 100755
--- a/src/commands/preview/var_stdin.rs
+++ b/src/commands/preview/var_stdin.rs
@@ -30,11 +30,10 @@ impl Runnable for Input {
if !extra.is_empty() {
print!("");
- shell::out()
- .arg(extra)
- .spawn()
- .map_err(|e| ShellSpawnError::new(extra, e))?
- .wait()?;
+ let mut cmd = shell::out();
+ cmd.arg(extra);
+ debug!(?cmd);
+ cmd.spawn().map_err(|e| ShellSpawnError::new(extra, e))?.wait()?;
}
}
diff --git a/src/common/fs.rs b/src/common/fs.rs
index 32c8b1e..cf8a737 100644
--- a/src/common/fs.rs
+++ b/src/common/fs.rs
@@ -78,6 +78,11 @@ fn follow_symlink(pathbuf: PathBuf) -> Result<PathBuf> {
fn exe_pathbuf() -> Result<PathBuf> {
let pathbuf = std::env::current_exe().context("Unable to acquire executable's path")?;
+
+ #[cfg(target_family = "windows")]
+ let pathbuf = dunce::canonicalize(pathbuf)?;
+
+ debug!(current_exe = ?pathbuf);
follow_symlink(pathbuf)
}
diff --git a/src/config/cli.rs b/src/config/cli.rs
index 7e2ec20..c6f86f9 100644
--- a/src/config/cli.rs
+++ b/src/config/cli.rs
@@ -117,6 +117,7 @@ pub enum Command {
Info(commands::info::Input),
}
+#[derive(Debug)]
pub enum Source {
Filesystem(Option<String>),
Tldr(String),
diff --git a/src/config/env.rs b/src/config/env.rs
index 7afd27e..ba428fc 100644
--- a/src/config/env.rs
+++ b/src/config/env.rs
@@ -2,6 +2,7 @@ use crate::env_var;
use crate::finder::FinderChoice;
use crate::prelude::*;
+#[derive(Debug)]
pub struct EnvConfig {
pub config_yaml: Option<String>,
pub config_path: Option<String>,
diff --git a/src/config/mod.rs b/src/config/mod.rs
index 774f930..b652608 100644
--- a/src/config/mod.rs
+++ b/src/config/mod.rs
@@ -12,6 +12,7 @@ use yaml::YamlConfig;
lazy_static! {
pub static ref CONFIG: Config = Config::new();
}
+#[derive(Debug)]
pub struct Config {
yaml: YamlConfig,
clap: ClapConfig,
@@ -69,7 +70,7 @@ impl Config {
if p.is_empty() {
None
} else {
- Some(p.join(":"))
+ Some(p.join(crate::filesystem::JOIN_SEPARATOR))
}
})
.or_else(|| self.yaml.cheats.path.clone())
diff --git a/src/config/yaml.rs b/src/config/yaml.rs
index 8c4a693..70a5a17 100644
--- a/src/config/yaml.rs
+++ b/src/config/yaml.rs
@@ -6,7 +6,7 @@ use crate::prelude::*;
use crossterm::style::Color as TerminalColor;
use serde::de;
-#[derive(Deserialize)]
+#[derive(Deserialize, Debug)]
pub struct Color(#[serde(deserialize_with = "color_deserialize")] TerminalColor);
impl Color {
@@ -24,7 +24,7 @@ where
.map_err(|_| de::Error::custom(format!("Failed to deserialize color: {s}")))
}
-#[derive(Deserialize)]
+#[derive(Deserialize, Debug)]
#[serde(default)]
pub struct ColorWidth {
pub color: Color,
@@ -32,7 +32,7 @@ pub struct ColorWidth {
pub min_width: u16,
}
-#[derive(Deserialize)]
+#[derive(Deserialize, Debug)]
#[serde(default)]
pub struct Style {
pub tag: ColorWidth,
@@ -40,7 +40,7 @@ pub struct Style {
pub snippet: ColorWidth,
}
-#[derive(Deserialize)]
+#[derive(Deserialize, Debug)]
#[serde(default)]
pub struct Finder {
#[serde(deserialize_with = "finder_deserialize")]
@@ -58,27 +58,27 @@ where
.map_err(|_| de::Error::custom(format!("Failed to deserialize finder: {s}")))
}
-#[derive(Deserialize, Default)]
+#[derive(Deserialize, Default, Debug)]
#[serde(default)]
pub struct Cheats {
pub path: Option<String>,
pub paths: Vec<String>,
}
-#[derive(Deserialize, Default)]
+#[derive(Deserialize, Default, Debug)]
#[serde(default)]
pub struct Search {
pub tags: Option<String>,
}
-#[derive(Deserialize)]
+#[derive(Deserialize, Debug)]
#[serde(default)]
pub struct Shell {
pub command: String,
pub finder_command: Option<String>,
}
-#[derive(Deserialize, Default)]
+#[derive(Deserialize, Default, Debug)]
#[serde(default)]
pub struct YamlConfig {
pub style: Style,
diff --git a/src/filesystem.rs b/src/filesystem.rs
index 6340f82..b8c4a03 100644
--- a/src/filesystem.rs
+++ b/src/filesystem.rs
@@ -12,6 +12,13 @@ use std::path::MAIN_SEPARATOR;
use walkdir::WalkDir;
+/// Multiple paths are joint by a platform-specific separator.
+/// FIXME: it's actually incorrect to assume a path doesn't containing this separator
+#[cfg(target_family = "windows")]
+pub const JOIN_SEPARATOR: &str = ";";
+#[cfg(not(target_family = "windows"))]
+pub const JOIN_SEPARATOR: &str = ":";
+
pub fn all_cheat_files(path: &Path) -> Vec<String> {
WalkDir::new(path)
.follow_links(true)
@@ -23,7 +30,7 @@ pub fn all_cheat_files(path: &Path) -> Vec<String> {
}
fn paths_from_path_param(env_var: &str) -> impl Iterator<Item = &str> {
- env_var.split(':').filter(|folder| folder != &"")
+ env_var.split(JOIN_SEPARATOR).filter(|folder| folder != &"")
}
fn compiled_default_path(path: Option<&str>) -> Option<PathBuf> {
@@ -125,6 +132,7 @@ fn interpolate_paths(paths: String) -> String {
newtext
}
+#[derive(Debug)]
pub struct Fetcher {
path: Option<String>,
files: RefCell<Vec<String>>,
@@ -165,7 +173,9 @@ impl fetcher::Fetcher for Fetcher {
None => folder.to_string(),
};
let folder_pathbuf = PathBuf::from(interpolated_folder);
- for file in all_cheat_files(&folder_pathbuf) {
+ let cheat_files = all_cheat_files(&folder_pathbuf);
+ debug!("read cheat files in `{folder_pathbuf:?}`: {cheat_files:#?}");
+ for file in cheat_files {
self.files.borrow_mut().push(file.clone());
let index = self.files.borrow().len() - 1;
let read_file_result = {
@@ -180,6 +190,7 @@ impl fetcher::Fetcher for Fetcher {
}
}
+ debug!("FilesystemFetcher = {self:#?}");
Ok(found_something)
}
@@ -280,4 +291,12 @@ mod tests {
assert_eq!(expected, cheats.to_string_lossy().to_string())
}
+
+ #[test]
+ #[cfg(target_family = "windows")]
+ fn multiple_paths() {
+ let p = r#"C:\Users\Administrator\AppData\Roaming\navi\config.yaml"#;
+ let paths = &[p; 2].join(JOIN_SEPARATOR);
+ assert_eq!(paths_from_path_param(paths).collect::<Vec<_>>(), [p; 2]);
+ }
}
diff --git a/src/finder/mod.rs b/src/finder/mod.rs
index b18888f..9b4ccfd 100644
--- a/src/finder/mod.rs
+++ b/src/finder/mod.rs
@@ -152,11 +152,13 @@ impl FinderChoice {
});
}
- let child = command
+ command
.env("SHELL", CONFIG.finder_shell())
.stdin(Stdio::piped())
- .stdout(Stdio::piped())
- .spawn();
+ .stdout(Stdio::piped());
+ debug!(cmd = ?command);
+
+ let child = command.spawn();
let mut child = match child {
Ok(x) => x,
diff --git a/src/lib.rs b/src/lib.rs
index cbae52d..bc2bdf6 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,7 +1,5 @@
#[macro_use]
extern crate lazy_static;
-// #[macro_use]
-// extern crate anyhow;
mod clients;
mod commands;
@@ -16,4 +14,4 @@ mod prelude;
mod structures;
mod welcome;
-pub use commands::handle;
+pub use {commands::handle, filesystem::default_config_pathbuf};