Skip to content

Commit

Permalink
Merge pull request #840 from zjp-CN/win
Browse files Browse the repository at this point in the history
Fix multiple paths: define the platform-specific join separator
  • Loading branch information
denisidoro committed Dec 10, 2023
2 parents 20c658a + ea95dfe commit b560ba5
Show file tree
Hide file tree
Showing 18 changed files with 121 additions and 38 deletions.
1 change: 1 addition & 0 deletions .gitignore
@@ -1,2 +1,3 @@
/target
**/*.rs.bk
navi.log
11 changes: 9 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions Cargo.toml
Expand Up @@ -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"
Expand Down
6 changes: 6 additions & 0 deletions docs/config_file.md
Expand Up @@ -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`.
11 changes: 7 additions & 4 deletions docs/config_file_example.yaml
Expand Up @@ -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
36 changes: 33 additions & 3 deletions 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)]
Expand All @@ -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(())
}
14 changes: 8 additions & 6 deletions src/commands/core/actor.rs
Expand Up @@ -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))?;

Expand Down Expand Up @@ -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")?;
Expand Down
6 changes: 5 additions & 1 deletion src/commands/core/mod.rs
Expand Up @@ -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
Expand All @@ -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() {
Expand All @@ -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));
Expand Down
1 change: 1 addition & 0 deletions src/commands/mod.rs
Expand Up @@ -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(),

Expand Down
9 changes: 4 additions & 5 deletions src/commands/preview/var_stdin.rs
Expand Up @@ -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()?;
}
}

Expand Down
5 changes: 5 additions & 0 deletions src/common/fs.rs
Expand Up @@ -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)
}

Expand Down
1 change: 1 addition & 0 deletions src/config/cli.rs
Expand Up @@ -117,6 +117,7 @@ pub enum Command {
Info(commands::info::Input),
}

#[derive(Debug)]
pub enum Source {
Filesystem(Option<String>),
Tldr(String),
Expand Down
1 change: 1 addition & 0 deletions src/config/env.rs
Expand Up @@ -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>,
Expand Down
3 changes: 2 additions & 1 deletion src/config/mod.rs
Expand Up @@ -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,
Expand Down Expand Up @@ -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())
Expand Down
16 changes: 8 additions & 8 deletions src/config/yaml.rs
Expand Up @@ -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 {
Expand All @@ -24,23 +24,23 @@ 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,
pub width_percentage: u16,
pub min_width: u16,
}

#[derive(Deserialize)]
#[derive(Deserialize, Debug)]
#[serde(default)]
pub struct Style {
pub tag: ColorWidth,
pub comment: ColorWidth,
pub snippet: ColorWidth,
}

#[derive(Deserialize)]
#[derive(Deserialize, Debug)]
#[serde(default)]
pub struct Finder {
#[serde(deserialize_with = "finder_deserialize")]
Expand All @@ -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,
Expand Down
23 changes: 21 additions & 2 deletions src/filesystem.rs
Expand Up @@ -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)
Expand All @@ -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> {
Expand Down Expand Up @@ -125,6 +132,7 @@ fn interpolate_paths(paths: String) -> String {
newtext
}

#[derive(Debug)]
pub struct Fetcher {
path: Option<String>,
files: RefCell<Vec<String>>,
Expand Down Expand Up @@ -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 = {
Expand All @@ -180,6 +190,7 @@ impl fetcher::Fetcher for Fetcher {
}
}

debug!("FilesystemFetcher = {self:#?}");
Ok(found_something)
}

Expand Down Expand Up @@ -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]);
}
}
8 changes: 5 additions & 3 deletions src/finder/mod.rs
Expand Up @@ -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,
Expand Down

0 comments on commit b560ba5

Please sign in to comment.