diff --git a/CHANGELOG.md b/CHANGELOG.md index 63c6a88..bdc81b6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,13 +5,15 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## Unreleased +## [0.5.0] - 2020-10-30 ### Added - Inaccessible directories are no longer removed; zoxide can now remember paths on removable devices. - `$_ZO_EXCLUDE_DIRS` now supports globs. - `zoxide init` now defines `__zoxide_z*` functions that can be aliased as needed. +- Support for the [xonsh](https://xon.sh/) shell. +- `zoxide import` can now import from Autojump. ### Changed @@ -19,7 +21,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed -- Clobber conflicting alias definitions in Bash/POSIX/Zsh shells. +- Clobber conflicting alias definitions in bash/fish/zsh/POSIX shells. ### Removed @@ -176,6 +178,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - GitHub Actions pipeline to build and upload releases. - Support for the `zsh` shell. +[0.5.0]: https://github.com/ajeetdsouza/zoxide/compare/v0.4.3...v0.5.0 [0.4.3]: https://github.com/ajeetdsouza/zoxide/compare/v0.4.2...v0.4.3 [0.4.2]: https://github.com/ajeetdsouza/zoxide/compare/v0.4.1...v0.4.2 [0.4.1]: https://github.com/ajeetdsouza/zoxide/compare/v0.4.0...v0.4.1 diff --git a/Cargo.lock b/Cargo.lock index aff44ec..b96a2f6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -585,7 +585,7 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "zoxide" -version = "0.4.3" +version = "0.5.0" dependencies = [ "anyhow", "askama", diff --git a/Cargo.toml b/Cargo.toml index 0b3090e..3bd8f49 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "zoxide" -version = "0.4.3" +version = "0.5.0" authors = ["Ajeet D'Souza <98ajeet@gmail.com>"] description = "A faster way to navigate your filesystem" repository = "https://github.com/ajeetdsouza/zoxide/" diff --git a/README.md b/README.md index 8f8fa00..e82a4bd 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,7 @@ A faster way to navigate your filesystem - [fish](#fish) - [POSIX](#posix-shells) - [PowerShell](#powershell) + - [xonsh](#xonsh) - [zsh](#zsh) - [Configuration](#configuration) - [`init` flags](#init-flags) @@ -168,21 +169,6 @@ Add the following line to your shell's configuration file: eval "$(zoxide init posix --hook prompt)" ``` -The `prompt` hook is recommended for POSIX shells because the default `pwd` -hook creates a temporary file for every session, which are only deleted upon -reboot. If you do want to use `pwd` hooks instead, you may want to set up traps -to perform a cleanup once the shell exits: - -```sh -trap '_zoxide_cleanup' EXIT HUP KILL TERM -trap '_zoxide_cleanup; trap - INT; kill -s INT "$$"' INT -trap '_zoxide_cleanup; trap - QUIT; kill -s QUIT "$$"' QUIT -``` - -NOTE: If you modify your `PS1` at any point, you may need to re-run the above -command. This is due to the fact that the hook is stored in `PS1`, in order to -be evaluated every time the prompt is displayed. - #### PowerShell Add the following line to your profile: @@ -194,6 +180,14 @@ Invoke-Expression (& { }) ``` +#### xonsh + +Add the following line to your profile (usually `~/.xonshrc`): + +```xonsh +execx($(zoxide init xonsh), 'exec', __xonsh__.ctx, filename='zoxide') +``` + #### zsh Add the following line to your `~/.zshrc`: diff --git a/src/cmd/add.rs b/src/cmd/add.rs index 028889f..19fb329 100644 --- a/src/cmd/add.rs +++ b/src/cmd/add.rs @@ -1,4 +1,4 @@ -use crate::cmd::Cmd; +use super::Cmd; use crate::config; use crate::util; diff --git a/src/cmd/import.rs b/src/cmd/import.rs index 1c2da1a..e2cd761 100644 --- a/src/cmd/import.rs +++ b/src/cmd/import.rs @@ -1,4 +1,4 @@ -use crate::cmd::Cmd; +use super::Cmd; use crate::config; use crate::import::{Autojump, Import as _, Z}; use crate::util; diff --git a/src/cmd/init.rs b/src/cmd/init.rs index f24488e..b43a3fc 100644 --- a/src/cmd/init.rs +++ b/src/cmd/init.rs @@ -1,4 +1,4 @@ -use crate::cmd::Cmd; +use super::Cmd; use crate::config; use crate::shell::{self, Hook, Opts}; diff --git a/src/cmd/mod.rs b/src/cmd/mod.rs index 05bc4cf..b8dbaae 100644 --- a/src/cmd/mod.rs +++ b/src/cmd/mod.rs @@ -5,6 +5,7 @@ mod query; mod remove; use anyhow::Result; +use clap::{AppSettings, Clap}; pub use add::Add; pub use import::Import; @@ -15,3 +16,25 @@ pub use remove::Remove; pub trait Cmd { fn run(&self) -> Result<()>; } + +#[derive(Debug, Clap)] +#[clap(about, author, global_setting(AppSettings::GlobalVersion), global_setting(AppSettings::VersionlessSubcommands), version = env!("ZOXIDE_VERSION"))] +pub enum App { + Add(Add), + Import(Import), + Init(Init), + Query(Query), + Remove(Remove), +} + +impl Cmd for App { + fn run(&self) -> Result<()> { + match self { + App::Add(cmd) => cmd.run(), + App::Import(cmd) => cmd.run(), + App::Init(cmd) => cmd.run(), + App::Query(cmd) => cmd.run(), + App::Remove(cmd) => cmd.run(), + } + } +} diff --git a/src/cmd/query.rs b/src/cmd/query.rs index 7e3cf0f..24bafcc 100644 --- a/src/cmd/query.rs +++ b/src/cmd/query.rs @@ -1,4 +1,4 @@ -use crate::cmd::Cmd; +use super::Cmd; use crate::config; use crate::fzf::Fzf; use crate::util; diff --git a/src/cmd/remove.rs b/src/cmd/remove.rs index c2152fb..b629c16 100644 --- a/src/cmd/remove.rs +++ b/src/cmd/remove.rs @@ -1,4 +1,4 @@ -use crate::cmd::Cmd; +use super::Cmd; use crate::config; use crate::fzf::Fzf; use crate::store::Query; @@ -49,7 +49,11 @@ impl Cmd for Remove { }; if !store.remove(path) { - bail!("path not found in store: {}", &path) + let path = util::resolve_path(&path)?; + let path = util::path_to_str(&path)?; + if !store.remove(path) { + bail!("path not found in store: {}", &path) + } } Ok(()) diff --git a/src/import/autojump.rs b/src/import/autojump.rs index 548e839..0e469ea 100644 --- a/src/import/autojump.rs +++ b/src/import/autojump.rs @@ -1,11 +1,9 @@ use super::Import; -use crate::util; use crate::store::{Dir, Epoch, Store}; use anyhow::{Context, Result}; -use std::fs::File; -use std::io::{BufRead, BufReader}; +use std::fs; use std::path::Path; pub struct Autojump { @@ -15,44 +13,50 @@ pub struct Autojump { impl Import for Autojump { fn import>(&self, store: &mut Store, path: P) -> Result<()> { - let file = File::open(path).context("could not open autojump database")?; - let reader = BufReader::new(file); + let path = path.as_ref(); + let buffer = fs::read_to_string(path) + .with_context(|| format!("could not open autojump database: {}", path.display()))?; - for (idx, line) in reader.lines().enumerate() { + let mut entries = Vec::new(); + for (idx, line) in buffer.lines().enumerate() { (|| -> Result<()> { - let line = line?; if line.is_empty() { return Ok(()); } - let split_idx = line - .find('\t') - .with_context(|| format!("invalid entry: {}", line))?; - let (rank, path) = line.split_at(split_idx); + let (rank, path) = (|| { + let mut split = line.splitn(2, '\t'); + let rank = split.next()?; + let path = split.next()?; + Some((rank, path)) + })() + .with_context(|| format!("invalid entry: {}", line))?; let rank = rank - .parse() + .parse::() .with_context(|| format!("invalid rank: {}", rank))?; - let path = if self.resolve_symlinks { - util::canonicalize - } else { - util::resolve_path - }(&path)?; - let path = util::path_to_str(&path)?; - - if store.dirs.iter_mut().find(|dir| dir.path == path).is_none() { - store.dirs.push(Dir { - path: path.into(), - rank, - last_accessed: self.now, - }); - store.modified = true; - } - + entries.push((path, rank)); Ok(()) })() - .with_context(|| format!("line {}: error reading from z database", idx + 1))?; + .with_context(|| format!("line {}: error reading from autojump database", idx + 1))?; + } + + let rank_sum = entries.iter().map(|(_, rank)| rank).sum::(); + for (path, rank) in entries.iter() { + if store + .dirs + .iter_mut() + .find(|dir| &dir.path == path) + .is_none() + { + store.dirs.push(Dir { + path: path.to_string(), + rank: rank / rank_sum, + last_accessed: self.now, + }); + store.modified = true; + } } Ok(()) diff --git a/src/import/z.rs b/src/import/z.rs index 94cdaac..e6d565a 100644 --- a/src/import/z.rs +++ b/src/import/z.rs @@ -1,5 +1,4 @@ use super::Import; -use crate::util; use crate::store::{Dir, Store}; use anyhow::{Context, Result}; @@ -33,13 +32,6 @@ impl Import for Z { })() .with_context(|| format!("invalid entry: {}", line))?; - let path = if self.resolve_symlinks { - util::canonicalize - } else { - util::resolve_path - }(&path)?; - let path = util::path_to_str(&path)?; - let rank = rank .parse() .with_context(|| format!("invalid rank: {}", rank))?; @@ -54,7 +46,7 @@ impl Import for Z { dir.last_accessed = dir.last_accessed.max(last_accessed); } None => store.dirs.push(Dir { - path: path.into(), + path: path.to_string(), rank, last_accessed, }), diff --git a/src/main.rs b/src/main.rs index e43ca62..ab640bd 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,43 +7,20 @@ mod shell; mod store; mod util; -use crate::cmd::{Add, Cmd, Import, Init, Query, Remove}; +use crate::cmd::{App, Cmd}; use crate::error::SilentExit; use anyhow::Result; -use clap::{AppSettings, Clap}; +use clap::Clap; use std::process; -#[derive(Debug, Clap)] -#[clap( - about, - author, - global_setting(AppSettings::GlobalVersion), - global_setting(AppSettings::VersionlessSubcommands), - version = env!("ZOXIDE_VERSION"))] -enum Opts { - Add(Add), - Import(Import), - Init(Init), - Query(Query), - Remove(Remove), -} - pub fn main() -> Result<()> { - let opts = Opts::parse(); - - let result: Result<()> = match opts { - Opts::Add(cmd) => cmd.run(), - Opts::Import(cmd) => cmd.run(), - Opts::Init(cmd) => cmd.run(), - Opts::Query(cmd) => cmd.run(), - Opts::Remove(cmd) => cmd.run(), - }; - - result.map_err(|e| match e.downcast::() { - Ok(SilentExit { code }) => process::exit(code), - // TODO: change the error prefix to `zoxide:` - Err(e) => e, - }) + App::parse() + .run() + .map_err(|e| match e.downcast::() { + Ok(SilentExit { code }) => process::exit(code), + // TODO: change the error prefix to `zoxide:` + Err(e) => e, + }) }