Fix formatting

This commit is contained in:
Ajeet D'Souza 2021-09-13 13:31:58 +05:30
parent 02029aef98
commit a60a305279
21 changed files with 111 additions and 124 deletions

View File

@ -1,6 +1,5 @@
use std::env;
use std::io;
use std::process::Command; use std::process::Command;
use std::{env, io};
fn main() { fn main() {
let pkg_version = env::var("CARGO_PKG_VERSION").unwrap(); let pkg_version = env::var("CARGO_PKG_VERSION").unwrap();
@ -10,8 +9,8 @@ fn main() {
}; };
println!("cargo:rustc-env=ZOXIDE_VERSION={}", version); println!("cargo:rustc-env=ZOXIDE_VERSION={}", version);
// Since we are generating completions in the package directory, we need to // Since we are generating completions in the package directory, we need to set this so that
// set this so that Cargo doesn't rebuild every time. // Cargo doesn't rebuild every time.
println!("cargo:rerun-if-changed=src"); println!("cargo:rerun-if-changed=src");
println!("cargo:rerun-if-changed=templates"); println!("cargo:rerun-if-changed=templates");
println!("cargo:rerun-if-changed=tests"); println!("cargo:rerun-if-changed=tests");

View File

@ -1,3 +1,6 @@
# comment_width = 100
# error_on_line_overflow = true
# error_on_unformatted = true
# group_imports = "StdExternalCrate" # group_imports = "StdExternalCrate"
# imports_granularity = "Module" # imports_granularity = "Module"
max_width = 120 max_width = 120
@ -6,3 +9,4 @@ use_field_init_shorthand = true
use_small_heuristics = "Max" use_small_heuristics = "Max"
use_try_shorthand = true use_try_shorthand = true
# wrap_comments = true # wrap_comments = true
# version = "Two"

View File

@ -1,7 +1,7 @@
use clap::{AppSettings, ArgEnum, Clap, ValueHint};
use std::path::PathBuf; use std::path::PathBuf;
use clap::{AppSettings, ArgEnum, Clap, ValueHint};
const ENV_HELP: &str = "ENVIRONMENT VARIABLES: const ENV_HELP: &str = "ENVIRONMENT VARIABLES:
_ZO_DATA_DIR Path for zoxide data files _ZO_DATA_DIR Path for zoxide data files
_ZO_ECHO Prints the matched directory before navigating to it when set to 1 _ZO_ECHO Prints the matched directory before navigating to it when set to 1

View File

@ -1,16 +1,15 @@
use crate::app::{Add, Run}; use std::path::Path;
use crate::config;
use crate::db::DatabaseFile;
use crate::util;
use anyhow::{bail, Result}; use anyhow::{bail, Result};
use std::path::Path; use crate::app::{Add, Run};
use crate::db::DatabaseFile;
use crate::{config, util};
impl Run for Add { impl Run for Add {
fn run(&self) -> Result<()> { fn run(&self) -> Result<()> {
// These characters can't be printed cleanly to a single line, so they // These characters can't be printed cleanly to a single line, so they can cause confusion
// can cause confusion when writing to fzf / stdout. // when writing to fzf / stdout.
const EXCLUDE_CHARS: &[char] = &['\n', '\r']; const EXCLUDE_CHARS: &[char] = &['\n', '\r'];
let data_dir = config::data_dir()?; let data_dir = config::data_dir()?;
@ -22,11 +21,10 @@ impl Run for Add {
let mut db = db.open()?; let mut db = db.open()?;
for path in &self.paths { for path in &self.paths {
let path = if config::resolve_symlinks() { util::canonicalize(path) } else { util::resolve_path(path) }?; let path = if config::resolve_symlinks() { util::canonicalize } else { util::resolve_path }(path)?;
let path = util::path_to_str(&path)?; let path = util::path_to_str(&path)?;
// Ignore path if it contains unsupported characters, or if it's in // Ignore path if it contains unsupported characters, or if it's in the exclude list.
// the exclude list.
if path.contains(EXCLUDE_CHARS) || exclude_dirs.iter().any(|glob| glob.matches(path)) { if path.contains(EXCLUDE_CHARS) || exclude_dirs.iter().any(|glob| glob.matches(path)) {
continue; continue;
} }

View File

@ -1,10 +1,10 @@
use crate::app::{Import, ImportFrom, Run}; use std::fs;
use crate::config;
use crate::db::{Database, DatabaseFile, Dir};
use anyhow::{bail, Context, Result}; use anyhow::{bail, Context, Result};
use std::fs; use crate::app::{Import, ImportFrom, Run};
use crate::config;
use crate::db::{Database, DatabaseFile, Dir};
impl Run for Import { impl Run for Import {
fn run(&self) -> Result<()> { fn run(&self) -> Result<()> {
@ -37,9 +37,8 @@ fn from_autojump<'a>(db: &mut Database<'a>, buffer: &'a str) -> Result<()> {
let rank = split.next().with_context(|| format!("invalid entry: {}", line))?; let rank = split.next().with_context(|| format!("invalid entry: {}", line))?;
let mut rank = rank.parse::<f64>().with_context(|| format!("invalid rank: {}", rank))?; let mut rank = rank.parse::<f64>().with_context(|| format!("invalid rank: {}", rank))?;
// Normalize the rank using a sigmoid function. Don't import actual // Normalize the rank using a sigmoid function. Don't import actual ranks from autojump,
// ranks from autojump, since its scoring algorithm is very different, // since its scoring algorithm is very different and might take a while to get normalized.
// and might take a while to get normalized.
rank = sigmoid(rank); rank = sigmoid(rank);
let path = split.next().with_context(|| format!("invalid entry: {}", line))?; let path = split.next().with_context(|| format!("invalid entry: {}", line))?;

View File

@ -1,12 +1,12 @@
use crate::app::{Init, InitShell, Run}; use std::io::{self, Write};
use crate::config;
use crate::error::BrokenPipeHandler;
use crate::shell::{self, Opts};
use anyhow::{Context, Result}; use anyhow::{Context, Result};
use askama::Template; use askama::Template;
use std::io::{self, Write}; use crate::app::{Init, InitShell, Run};
use crate::config;
use crate::error::BrokenPipeHandler;
use crate::shell::{self, Opts};
impl Run for Init { impl Run for Init {
fn run(&self) -> Result<()> { fn run(&self) -> Result<()> {

View File

@ -5,10 +5,10 @@ mod init;
mod query; mod query;
mod remove; mod remove;
pub use crate::app::_app::*;
use anyhow::Result; use anyhow::Result;
pub use crate::app::_app::*;
pub trait Run { pub trait Run {
fn run(&self) -> Result<()>; fn run(&self) -> Result<()>;
} }

View File

@ -1,13 +1,12 @@
use crate::app::{Query, Run}; use std::io::{self, Write};
use crate::config;
use crate::db::{Database, DatabaseFile};
use crate::error::BrokenPipeHandler;
use crate::fzf::Fzf;
use crate::util;
use anyhow::{Context, Result}; use anyhow::{Context, Result};
use std::io::{self, Write}; use crate::app::{Query, Run};
use crate::db::{Database, DatabaseFile};
use crate::error::BrokenPipeHandler;
use crate::fzf::Fzf;
use crate::{config, util};
impl Run for Query { impl Run for Query {
fn run(&self) -> Result<()> { fn run(&self) -> Result<()> {

View File

@ -1,13 +1,12 @@
use crate::app::{Remove, Run}; use std::io::Write;
use crate::config;
use crate::db::DatabaseFile;
use crate::error::BrokenPipeHandler;
use crate::fzf::Fzf;
use crate::util;
use anyhow::{bail, Result}; use anyhow::{bail, Result};
use std::io::Write; use crate::app::{Remove, Run};
use crate::db::DatabaseFile;
use crate::error::BrokenPipeHandler;
use crate::fzf::Fzf;
use crate::{config, util};
impl Run for Remove { impl Run for Remove {
fn run(&self) -> Result<()> { fn run(&self) -> Result<()> {

View File

@ -1,12 +1,12 @@
use crate::db::Rank; use std::env;
use std::ffi::OsString;
use std::path::PathBuf;
use anyhow::{bail, Context, Result}; use anyhow::{bail, Context, Result};
use dirs_next as dirs; use dirs_next as dirs;
use glob::Pattern; use glob::Pattern;
use std::env; use crate::db::Rank;
use std::ffi::OsString;
use std::path::PathBuf;
pub fn data_dir() -> Result<PathBuf> { pub fn data_dir() -> Result<PathBuf> {
let path = match env::var_os("_ZO_DATA_DIR") { let path = match env::var_os("_ZO_DATA_DIR") {

View File

@ -1,11 +1,11 @@
use anyhow::{bail, Context, Result};
use bincode::Options as _;
use serde::{Deserialize, Serialize};
use std::borrow::Cow; use std::borrow::Cow;
use std::fmt::{self, Display, Formatter}; use std::fmt::{self, Display, Formatter};
use std::ops::{Deref, DerefMut}; use std::ops::{Deref, DerefMut};
use anyhow::{bail, Context, Result};
use bincode::Options as _;
use serde::{Deserialize, Serialize};
#[derive(Debug, Deserialize, Serialize)] #[derive(Debug, Deserialize, Serialize)]
pub struct DirList<'a>(#[serde(borrow)] pub Vec<Dir<'a>>); pub struct DirList<'a>(#[serde(borrow)] pub Vec<Dir<'a>>);
@ -17,8 +17,8 @@ impl DirList<'_> {
} }
pub fn from_bytes(bytes: &[u8]) -> Result<DirList> { pub fn from_bytes(bytes: &[u8]) -> Result<DirList> {
// Assume a maximum size for the database. This prevents bincode from // Assume a maximum size for the database. This prevents bincode from throwing strange
// throwing strange errors when it encounters invalid data. // errors when it encounters invalid data.
const MAX_SIZE: u64 = 32 << 20; // 32 MiB const MAX_SIZE: u64 = 32 << 20; // 32 MiB
let deserializer = &mut bincode::options().with_fixint_encoding().with_limit(MAX_SIZE); let deserializer = &mut bincode::options().with_fixint_encoding().with_limit(MAX_SIZE);
@ -149,10 +149,10 @@ pub type Epoch = u64;
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::{Dir, DirList};
use std::borrow::Cow; use std::borrow::Cow;
use super::{Dir, DirList};
#[test] #[test]
fn zero_copy() { fn zero_copy() {
let dirs = DirList(vec![Dir { path: "/".into(), rank: 0.0, last_accessed: 0 }]); let dirs = DirList(vec![Dir { path: "/".into(), rank: 0.0, last_accessed: 0 }]);

View File

@ -1,16 +1,15 @@
mod dir; mod dir;
mod stream; mod stream;
pub use dir::{Dir, DirList, Epoch, Rank};
pub use stream::Stream;
use anyhow::{Context, Result};
use tempfile::{NamedTempFile, PersistError};
use std::fs; use std::fs;
use std::io::{self, Write}; use std::io::{self, Write};
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use anyhow::{Context, Result};
pub use dir::{Dir, DirList, Epoch, Rank};
pub use stream::Stream;
use tempfile::{NamedTempFile, PersistError};
#[derive(Debug)] #[derive(Debug)]
pub struct Database<'file> { pub struct Database<'file> {
pub dirs: DirList<'file>, pub dirs: DirList<'file>,
@ -28,9 +27,8 @@ impl<'file> Database<'file> {
let mut file = NamedTempFile::new_in(self.data_dir) let mut file = NamedTempFile::new_in(self.data_dir)
.with_context(|| format!("could not create temporary database in: {}", self.data_dir.display()))?; .with_context(|| format!("could not create temporary database in: {}", self.data_dir.display()))?;
// Preallocate enough space on the file, preventing copying later on. // Preallocate enough space on the file, preventing copying later on. This optimization may
// This optimization may fail on some filesystems, but it is safe to // fail on some filesystems, but it is safe to ignore it and proceed.
// ignore it and proceed.
let _ = file.as_file().set_len(buffer.len() as _); let _ = file.as_file().set_len(buffer.len() as _);
file.write_all(&buffer) file.write_all(&buffer)
.with_context(|| format!("could not write to temporary database: {}", file.path().display()))?; .with_context(|| format!("could not write to temporary database: {}", file.path().display()))?;
@ -89,8 +87,8 @@ impl<'file> Database<'file> {
Stream::new(self, now) Stream::new(self, now)
} }
/// Removes the directory with `path` from the store. /// Removes the directory with `path` from the store. This does not preserve ordering, but is
/// This does not preserve ordering, but is O(1). /// O(1).
pub fn remove<S: AsRef<str>>(&mut self, path: S) -> bool { pub fn remove<S: AsRef<str>>(&mut self, path: S) -> bool {
let path = path.as_ref(); let path = path.as_ref();
@ -124,15 +122,16 @@ impl<'file> Database<'file> {
#[cfg(windows)] #[cfg(windows)]
fn persist<P: AsRef<Path>>(mut file: NamedTempFile, path: P) -> Result<(), PersistError> { fn persist<P: AsRef<Path>>(mut file: NamedTempFile, path: P) -> Result<(), PersistError> {
use rand::distributions::{Distribution, Uniform};
use rand::rngs::SmallRng;
use rand::SeedableRng;
use std::thread; use std::thread;
use std::time::Duration; use std::time::Duration;
// File renames on Windows are not atomic and sometimes fail with `PermissionDenied`. use rand::distributions::{Distribution, Uniform};
// This is extremely unlikely unless it's running in a loop on multiple threads. use rand::rngs::SmallRng;
// Nevertheless, we guard against it by retrying the rename a fixed number of times. use rand::SeedableRng;
// File renames on Windows are not atomic and sometimes fail with `PermissionDenied`. This is
// extremely unlikely unless it's running in a loop on multiple threads. Nevertheless, we guard
// against it by retrying the rename a fixed number of times.
const MAX_TRIES: usize = 10; const MAX_TRIES: usize = 10;
let mut rng = None; let mut rng = None;
@ -170,9 +169,8 @@ impl DatabaseFile {
} }
pub fn open(&mut self) -> Result<Database> { pub fn open(&mut self) -> Result<Database> {
// Read the entire database to memory. For smaller files, this is // Read the entire database to memory. For smaller files, this is faster than
// faster than mmap / streaming, and allows for zero-copy // mmap / streaming, and allows for zero-copy deserialization.
// deserialization.
let path = db_path(&self.data_dir); let path = db_path(&self.data_dir);
match fs::read(&path) { match fs::read(&path) {
Ok(buffer) => { Ok(buffer) => {
@ -182,9 +180,8 @@ impl DatabaseFile {
Ok(Database { dirs, modified: false, data_dir: &self.data_dir }) Ok(Database { dirs, modified: false, data_dir: &self.data_dir })
} }
Err(e) if e.kind() == io::ErrorKind::NotFound => { Err(e) if e.kind() == io::ErrorKind::NotFound => {
// Create data directory, but don't create any file yet. // Create data directory, but don't create any file yet. The file will be created
// The file will be created later by [`Database::save`] // later by [`Database::save`] if any data is modified.
// if any data is modified.
fs::create_dir_all(&self.data_dir) fs::create_dir_all(&self.data_dir)
.with_context(|| format!("unable to create data directory: {}", self.data_dir.display()))?; .with_context(|| format!("unable to create data directory: {}", self.data_dir.display()))?;
Ok(Database { dirs: DirList::new(), modified: false, data_dir: &self.data_dir }) Ok(Database { dirs: DirList::new(), modified: false, data_dir: &self.data_dir })

View File

@ -1,12 +1,11 @@
use super::{Database, Dir, Epoch}; use std::iter::Rev;
use crate::util; use std::ops::Range;
use std::{fs, path};
use ordered_float::OrderedFloat; use ordered_float::OrderedFloat;
use std::fs; use super::{Database, Dir, Epoch};
use std::iter::Rev; use crate::util;
use std::ops::Range;
use std::path;
pub struct Stream<'db, 'file> { pub struct Stream<'db, 'file> {
db: &'db mut Database<'file>, db: &'db mut Database<'file>,
@ -27,8 +26,7 @@ impl<'db, 'file> Stream<'db, 'file> {
db.dirs.sort_unstable_by_key(|dir| OrderedFloat(dir.score(now))); db.dirs.sort_unstable_by_key(|dir| OrderedFloat(dir.score(now)));
let idxs = (0..db.dirs.len()).rev(); let idxs = (0..db.dirs.len()).rev();
// If a directory is deleted and hasn't been used for 90 days, delete // If a directory is deleted and hasn't been used for 90 days, delete it from the database.
// it from the database.
let expire_below = now.saturating_sub(90 * 24 * 60 * 60); let expire_below = now.saturating_sub(90 * 24 * 60 * 60);
Stream { Stream {
@ -124,11 +122,11 @@ impl<'db, 'file> Stream<'db, 'file> {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::Database; use std::path::PathBuf;
use rstest::rstest; use rstest::rstest;
use std::path::PathBuf; use super::Database;
#[rstest] #[rstest]
// Case normalization // Case normalization

View File

@ -1,9 +1,9 @@
use anyhow::{bail, Context, Result};
use std::fmt::{self, Display, Formatter}; use std::fmt::{self, Display, Formatter};
use std::io; use std::io;
// Custom error type for early exit. use anyhow::{bail, Context, Result};
/// Custom error type for early exit.
#[derive(Debug)] #[derive(Debug)]
pub struct SilentExit { pub struct SilentExit {
pub code: i32, pub code: i32,

View File

@ -1,10 +1,10 @@
use crate::config; use std::io;
use crate::error::SilentExit; use std::process::{Child, ChildStdin, Command, Stdio};
use anyhow::{bail, Context, Result}; use anyhow::{bail, Context, Result};
use std::io; use crate::config;
use std::process::{Child, ChildStdin, Command, Stdio}; use crate::error::SilentExit;
pub struct Fzf { pub struct Fzf {
child: Child, child: Child,
@ -33,7 +33,7 @@ impl Fzf {
} }
pub fn stdin(&mut self) -> &mut ChildStdin { pub fn stdin(&mut self) -> &mut ChildStdin {
// unwrap is safe here because command.stdin() has been piped // unwrap is safe here because command.stdin() has been piped.
self.child.stdin.as_mut().unwrap() self.child.stdin.as_mut().unwrap()
} }

View File

@ -6,14 +6,13 @@ mod fzf;
mod shell; mod shell;
mod util; mod util;
use crate::app::{App, Run}; use std::io::{self, Write};
use crate::error::SilentExit; use std::{env, process};
use clap::Clap; use clap::Clap;
use std::env; use crate::app::{App, Run};
use std::io::{self, Write}; use crate::error::SilentExit;
use std::process;
pub fn main() { pub fn main() {
// Forcibly disable backtraces. // Forcibly disable backtraces.

View File

@ -35,12 +35,12 @@ make_template!(Zsh, "zsh.txt");
#[cfg(feature = "shell_tests")] #[cfg(feature = "shell_tests")]
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*;
use askama::Template; use askama::Template;
use assert_cmd::Command; use assert_cmd::Command;
use rstest::rstest; use rstest::rstest;
use super::*;
#[rstest] #[rstest]
fn bash_bash( fn bash_bash(
#[values(None, Some("z"))] cmd: Option<&str>, #[values(None, Some("z"))] cmd: Option<&str>,
@ -102,8 +102,8 @@ mod tests {
let opts = Opts { cmd, hook, echo, resolve_symlinks }; let opts = Opts { cmd, hook, echo, resolve_symlinks };
let mut source = String::new(); let mut source = String::new();
// Filter out lines using edit:*, since those functions // Filter out lines using edit:*, since those functions are only available in the
// are only available in the interactive editor. // interactive editor.
for line in Elvish(&opts).render().unwrap().split('\n').filter(|line| !line.contains("edit:")) { for line in Elvish(&opts).render().unwrap().split('\n').filter(|line| !line.contains("edit:")) {
source.push_str(line); source.push_str(line);
source.push('\n'); source.push('\n');
@ -356,8 +356,7 @@ mod tests {
let opts = Opts { cmd, hook, echo, resolve_symlinks }; let opts = Opts { cmd, hook, echo, resolve_symlinks };
let source = Zsh(&opts).render().unwrap(); let source = Zsh(&opts).render().unwrap();
// ShellCheck doesn't support zsh yet. // ShellCheck doesn't support zsh yet: https://github.com/koalaman/shellcheck/issues/809
// https://github.com/koalaman/shellcheck/issues/809
Command::new("shellcheck") Command::new("shellcheck")
.args(&["--enable", "all", "--shell", "bash", "-"]) .args(&["--enable", "all", "--shell", "bash", "-"])
.write_stdin(source) .write_stdin(source)

View File

@ -1,11 +1,11 @@
use crate::db::Epoch;
use anyhow::{bail, Context, Result};
use std::env; use std::env;
use std::path::{Component, Path, PathBuf}; use std::path::{Component, Path, PathBuf};
use std::time::SystemTime; use std::time::SystemTime;
use anyhow::{bail, Context, Result};
use crate::db::Epoch;
pub fn canonicalize<P: AsRef<Path>>(path: &P) -> Result<PathBuf> { pub fn canonicalize<P: AsRef<Path>>(path: &P) -> Result<PathBuf> {
dunce::canonicalize(path).with_context(|| format!("could not resolve path: {}", path.as_ref().display())) dunce::canonicalize(path).with_context(|| format!("could not resolve path: {}", path.as_ref().display()))
} }
@ -26,11 +26,8 @@ pub fn path_to_str<P: AsRef<Path>>(path: &P) -> Result<&str> {
path.to_str().with_context(|| format!("invalid unicode in path: {}", path.display())) path.to_str().with_context(|| format!("invalid unicode in path: {}", path.display()))
} }
/// Resolves the absolute version of a path. /// Returns the absolute version of a path. Like [`std::path::Path::canonicalize`], but doesn't
/// /// resolve symlinks.
/// If path is already absolute, the path is still processed to be cleaned, as it can contained ".." or "." (or other)
/// character.
/// If path is relative, use the current directory to build the absolute path.
pub fn resolve_path<P: AsRef<Path>>(path: &P) -> Result<PathBuf> { pub fn resolve_path<P: AsRef<Path>>(path: &P) -> Result<PathBuf> {
let path = path.as_ref(); let path = path.as_ref();
let base_path; let base_path;
@ -135,7 +132,7 @@ pub fn resolve_path<P: AsRef<Path>>(path: &P) -> Result<PathBuf> {
Ok(stack.iter().collect()) Ok(stack.iter().collect())
} }
// Convert a string to lowercase, with a fast path for ASCII strings. /// Convert a string to lowercase, with a fast path for ASCII strings.
pub fn to_lowercase<S: AsRef<str>>(s: S) -> String { pub fn to_lowercase<S: AsRef<str>>(s: S) -> String {
let s = s.as_ref(); let s = s.as_ref();
if s.is_ascii() { if s.is_ascii() {

View File

@ -9,10 +9,9 @@ fn completions_bash() {
Command::new("bash").args(&["--noprofile", "--norc", "-c", source]).assert().success().stdout("").stderr(""); Command::new("bash").args(&["--noprofile", "--norc", "-c", source]).assert().success().stdout("").stderr("");
} }
// Elvish: the completions file uses editor commands to add completions to the // Elvish: the completions file uses editor commands to add completions to the shell. However,
// shell. However, Elvish does not support running editor commands from a // Elvish does not support running editor commands from a script, so we can't create a test for
// script, so we can't create a test for this. // this. See: https://github.com/elves/elvish/issues/1299
// <https://github.com/elves/elvish/issues/1299>
#[test] #[test]
fn completions_fish() { fn completions_fish() {

View File

@ -1,7 +1,7 @@
use clap::{ArgEnum, Clap};
use std::process::Command; use std::process::Command;
use clap::{ArgEnum, Clap};
#[derive(Clap, Debug)] #[derive(Clap, Debug)]
struct App { struct App {
#[clap(arg_enum)] #[clap(arg_enum)]