diff --git a/ranger_zoxide.py b/ranger_zoxide.py index a19cd13..7523d2c 100644 --- a/ranger_zoxide.py +++ b/ranger_zoxide.py @@ -25,7 +25,7 @@ class z(ranger.api.commands.Command): output = subprocess.check_output(["zoxide", "query"] + self.args[1:]) output = output.decode("utf-8") - query_prefix = "query:" + query_prefix = "query: " if output.startswith(query_prefix): directory = output[len(query_prefix) :].strip() diff --git a/src/main.rs b/src/main.rs index 78a7a00..2d22a54 100644 --- a/src/main.rs +++ b/src/main.rs @@ -23,7 +23,7 @@ pub fn main() -> Result<()> { let opt = Zoxide::from_args(); let env = envy::prefixed("_ZO_") .from_env::() - .with_context(|| "Could not parse environment variables")?; + .with_context(|| "could not parse environment variables")?; match opt { Zoxide::Add(add) => add.run(&env)?, diff --git a/src/subcommand/init.rs b/src/subcommand/init.rs index b73c599..ff237b2 100644 --- a/src/subcommand/init.rs +++ b/src/subcommand/init.rs @@ -108,55 +108,57 @@ struct HookConfig { const BASH_Z: &str = r#" _z_cd() { - cd "${@}" > /dev/null + cd "$@" || return "$?" - if [ "${?}" -eq 0 ]; then if [ -n "$_ZO_ECHO" ]; then - echo "${PWD}" + echo "$PWD" fi - fi } z() { - if [ "${#}" -eq 0 ]; then - _z_cd "${HOME}" - elif [ "${#}" -eq 1 ] && [ "${1}" = '-' ]; then - _z_cd '-' - else - local result=$(zoxide query "${@}") - case "${result}" in - "query: "*) - _z_cd "${result:7}" - ;; - *) - if [ -n "${result}" ]; then - echo "${result}" - fi - ;; - esac - fi + if [ "$#" -eq 0 ]; then + _z_cd ~ || return "$?" + elif [ "$#" -eq 1 ] && [ "$1" = '-' ]; then + _z_cd ~- || return "$?" + else + result="$(zoxide query $@)" || return "$?" + case "$result" in + "query: "*) + _z_cd "${result:7}" || return "$?" + ;; + *) + if [ -n "$result" ]; then + echo "$result" + fi + ;; + esac + fi } "#; const FISH_Z: &str = r#" function _z_cd - cd "$argv" > /dev/null + cd "$argv" + or return "$status" - if [ "$status" -eq 0 ] - commandline -f repaint - if [ -n "$_ZO_ECHO" ] - echo "$PWD" - end + commandline -f repaint + + if [ -n "$_ZO_ECHO" ] + echo "$PWD" end end function z - set -l argc (count "$argv") + set argc (count "$argv") + if [ "$argc" -eq 0 ] _z_cd "$HOME" - else if [ "$argc" -eq 1 ] - and [ "$argv[1]" = '-' ] + or return "$status" + + else if [ "$argc" -eq 1 ]; and [ "$argv[1]" = '-' ] _z_cd '-' + or return "$status" + else # TODO: use string-collect from fish 3.1.0 once it has wider adoption set -l IFS '' @@ -165,6 +167,7 @@ function z switch "$result" case 'query: *' _z_cd (string sub -s 8 "$result") + or return "$status" case '*' if [ -n "$result" ] echo "$result" @@ -194,12 +197,12 @@ const ZSH_ALIAS: &str = BASH_ALIAS; const BASH_HOOK_PROMPT: &str = r#" _zoxide_hook() { - zoxide add + zoxide add } case "$PROMPT_COMMAND" in - *_zoxide_hook*) ;; - *) PROMPT_COMMAND="_zoxide_hook${PROMPT_COMMAND:+;${PROMPT_COMMAND}}" ;; + *_zoxide_hook*) ;; + *) PROMPT_COMMAND="_zoxide_hook${PROMPT_COMMAND:+;${PROMPT_COMMAND}}" ;; esac "#; @@ -211,27 +214,27 @@ end const ZSH_HOOK_PROMPT: &str = r#" _zoxide_hook() { - zoxide add + zoxide add } [[ -n "${precmd_functions[(r)_zoxide_hook]}" ]] || { - precmd_functions+=(_zoxide_hook) + precmd_functions+=(_zoxide_hook) } "#; const BASH_HOOK_PWD: &str = r#" _zoxide_hook() { - if [ -z "${_ZO_PWD}" ]; then - _ZO_PWD="${PWD}" - elif [ "${_ZO_PWD}" != "${PWD}" ]; then - _ZO_PWD="${PWD}" - zoxide add - fi + if [ -z "${_ZO_PWD}" ]; then + _ZO_PWD="${PWD}" + elif [ "${_ZO_PWD}" != "${PWD}" ]; then + _ZO_PWD="${PWD}" + zoxide add + fi } case "$PROMPT_COMMAND" in - *_zoxide_hook*) ;; - *) PROMPT_COMMAND="_zoxide_hook${PROMPT_COMMAND:+;${PROMPT_COMMAND}}" ;; + *_zoxide_hook*) ;; + *) PROMPT_COMMAND="_zoxide_hook${PROMPT_COMMAND:+;${PROMPT_COMMAND}}" ;; esac "#; @@ -243,7 +246,7 @@ end const ZSH_HOOK_PWD: &str = r#" _zoxide_hook() { - zoxide add + zoxide add } chpwd_functions=(${chpwd_functions[@]} "_zoxide_hook") diff --git a/src/subcommand/query.rs b/src/subcommand/query.rs index f580677..e5cc4f9 100644 --- a/src/subcommand/query.rs +++ b/src/subcommand/query.rs @@ -1,6 +1,6 @@ use crate::env::Env; use crate::util; -use anyhow::Result; +use anyhow::{bail, Result}; use std::path::Path; use structopt::StructOpt; @@ -15,14 +15,15 @@ pub struct Query { impl Query { pub fn run(mut self, env: &Env) -> Result<()> { let path_opt = if self.interactive { - self.query_interactive(env) + self.query_interactive(env)? } else { - self.query(env) - }?; + self.query(env)? + }; - if let Some(path) = path_opt { - println!("query: {}", path.trim()); - } + match path_opt { + Some(path) => println!("query: {}", path.trim()), + None => bail!("no match found"), + }; Ok(()) } @@ -41,10 +42,10 @@ impl Query { let now = util::get_current_time()?; if let Some(dir) = util::get_db(env)?.query(&self.keywords, now) { - return Ok(Some(dir.path)); + Ok(Some(dir.path)) + } else { + Ok(None) } - - Ok(None) } fn query_interactive(&mut self, env: &Env) -> Result> { diff --git a/src/util.rs b/src/util.rs index 569acea..c223a96 100644 --- a/src/util.rs +++ b/src/util.rs @@ -2,7 +2,7 @@ use crate::db::DB; use crate::dir::Dir; use crate::env::Env; use crate::types::Epoch; -use anyhow::{anyhow, Context, Result}; +use anyhow::{anyhow, bail, Context, Result}; use std::io::{Read, Write}; use std::process::{Command, Stdio}; use std::time::SystemTime; @@ -25,15 +25,16 @@ pub fn get_current_time() -> Result { } pub fn fzf_helper(now: Epoch, mut dirs: Vec) -> Result> { - let fzf = Command::new("fzf") + let mut fzf = Command::new("fzf") .arg("-n2..") .stdin(Stdio::piped()) .stdout(Stdio::piped()) .spawn() .with_context(|| anyhow!("could not launch fzf"))?; - let mut fzf_stdin = fzf + let fzf_stdin = fzf .stdin + .as_mut() .ok_or_else(|| anyhow!("could not connect to fzf stdin"))?; for dir in dirs.iter_mut() { @@ -56,8 +57,9 @@ pub fn fzf_helper(now: Epoch, mut dirs: Vec) -> Result> { .with_context(|| anyhow!("could not write into fzf stdin"))?; } - let mut fzf_stdout = fzf + let fzf_stdout = fzf .stdout + .as_mut() .ok_or_else(|| anyhow!("could not connect to fzf stdout"))?; let mut output = String::new(); @@ -65,5 +67,25 @@ pub fn fzf_helper(now: Epoch, mut dirs: Vec) -> Result> { .read_to_string(&mut output) .with_context(|| anyhow!("could not read from fzf stdout"))?; - Ok(output.get(12..).map(str::to_string)) + let status = fzf.wait().with_context(|| "could not wait on fzf")?; + + match status.code() { + // normal exit + Some(0) => match output.get(12..) { + Some(path) => Ok(Some(path.to_string())), + None => bail!("fzf returned invalid output"), + }, + + // no match + Some(1) => Ok(None), + + // error + Some(2) => bail!("fzf returned an error"), + + // terminated by a signal + Some(128..=254) | None => bail!("fzf was terminated"), + + // unknown + _ => bail!("fzf returned an unknown error"), + } }