diff --git a/.github/workflows/cargo-test.yml b/.github/workflows/cargo-test.yml index e1798be..1ef9100 100644 --- a/.github/workflows/cargo-test.yml +++ b/.github/workflows/cargo-test.yml @@ -14,8 +14,10 @@ jobs: - run: sudo dpkg -i packages-microsoft-prod.deb - run: sudo apt update - run: sudo add-apt-repository universe - - run: sudo apt install bash dash fish powershell shellcheck xonsh zsh + - run: sudo apt install bash dash fish powershell python3 python3-pip shellcheck xonsh zsh - run: sudo snap install shfmt + - run: sudo pip3 install --upgrade pip setuptools + - run: sudo pip3 install --upgrade black mypy pylint - uses: actions/checkout@v2 - uses: actions-rs/toolchain@v1 with: diff --git a/Cargo.lock b/Cargo.lock index b96a2f6..9cf9598 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,9 +2,9 @@ # It is not intended for manual editing. [[package]] name = "anyhow" -version = "1.0.33" +version = "1.0.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1fd36ffbb1fb7c834eac128ea8d0e310c5aeb635548f9d58861e1308d46e71c" +checksum = "bf8dcb5b4bbaa28653b647d8c77bd4ed40183b48882e130c1f1ffb73de069fd7" [[package]] name = "askama" @@ -152,9 +152,9 @@ checksum = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" [[package]] name = "dirs-next" -version = "1.0.2" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf36e65a80337bea855cd4ef9b8401ffce06a7baedf2e85ec467b1ac3f6e82b6" +checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" dependencies = [ "cfg-if 1.0.0", "dirs-sys-next", @@ -248,9 +248,9 @@ checksum = "4d58d1b70b004888f764dfbf6a26a3b0342a1632d33968e4a179d8011c760614" [[package]] name = "memchr" -version = "2.3.3" +version = "2.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400" +checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525" [[package]] name = "nom" @@ -264,9 +264,9 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.12" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac267bcc07f48ee5f8935ab0d24f316fb722d7a1292e2913f0cc196b29ffd611" +checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" dependencies = [ "autocfg", ] @@ -288,15 +288,15 @@ dependencies = [ [[package]] name = "os_str_bytes" -version = "2.3.2" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ac6fe3538f701e339953a3ebbe4f39941aababa8a3f6964635b24ab526daeac" +checksum = "afb2e1c3ee07430c2cf76151675e583e0f19985fa6efae47d6848a3e2c824f85" [[package]] name = "ppv-lite86" -version = "0.2.9" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c36fa947111f5c62a733b652544dd0016a43ce89619538a8ef92724a6f501a20" +checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" [[package]] name = "predicates" @@ -432,6 +432,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "seq-macro" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5b3bd665f328d73d7079123bfbd14a6edd74187667b5c6f340adfc65ea9d25a" + [[package]] name = "serde" version = "1.0.117" @@ -598,6 +604,7 @@ dependencies = [ "once_cell", "ordered-float", "rand", + "seq-macro", "serde", "tempfile", ] diff --git a/Cargo.toml b/Cargo.toml index 3bd8f49..7604b9d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,7 +14,7 @@ anyhow = "1.0.32" askama = { version = "0.10.3", default-features = false } bincode = "1.3.1" clap = "3.0.0-beta.2" -dirs-next = "1.0.2" +dirs-next = "2.0.0" dunce = "1.0.1" glob = "0.3.0" once_cell = "1.4.1" @@ -27,6 +27,7 @@ rand = "0.7.3" [target.'cfg(unix)'.dev-dependencies] assert_cmd = "1.0.1" +seq-macro = "0.2.1" [profile.release] codegen-units = 1 diff --git a/src/shell.rs b/src/shell.rs index 481081e..eea653f 100644 --- a/src/shell.rs +++ b/src/shell.rs @@ -1,6 +1,6 @@ use clap::ArgEnum; -#[derive(Debug)] +#[derive(Debug, Eq, PartialEq)] pub struct Opts<'a> { pub cmd: Option<&'a str>, pub hook: Hook, @@ -34,7 +34,7 @@ make_template!(PowerShell, "powershell.txt"); make_template!(Xonsh, "xonsh.txt"); make_template!(Zsh, "zsh.txt"); -#[derive(ArgEnum, Clone, Copy, Debug, PartialEq)] +#[derive(ArgEnum, Clone, Copy, Debug, Eq, PartialEq)] pub enum Hook { None, Prompt, @@ -49,14 +49,21 @@ mod tests { use askama::Template; use assert_cmd::Command; use once_cell::sync::OnceCell; + use seq_macro::seq; + + macro_rules! with_opts_size { + ($macro:ident) => { + $macro!(24); + }; + } fn opts() -> &'static [Opts<'static>] { static OPTS: OnceCell> = OnceCell::new(); - OPTS.get_or_init(|| { - const BOOLS: &[bool] = &[false, true]; - const HOOKS: &[Hook] = &[Hook::None, Hook::Prompt, Hook::Pwd]; - const CMDS: &[Option<&str>] = &[None, Some("z")]; + const BOOLS: &[bool] = &[false, true]; + const HOOKS: &[Hook] = &[Hook::None, Hook::Prompt, Hook::Pwd]; + const CMDS: &[Option<&str>] = &[None, Some("z")]; + OPTS.get_or_init(|| { let mut opts = Vec::new(); for &echo in BOOLS { for &resolve_symlinks in BOOLS { @@ -74,162 +81,212 @@ mod tests { } } + // Verify that the value hardcoded into `with_opts_size` is correct. + macro_rules! id { + ($x:literal) => { + $x + }; + } + assert_eq!(opts.len(), with_opts_size!(id)); + opts }) } - #[test] - fn test_bash() { - for opts in opts() { - let source = Bash(opts).render().unwrap(); - Command::new("bash") - .args(&["-c", &source]) - .assert() - .success() - .stdout("") - .stderr(""); + macro_rules! generate_tests { + ($N:literal) => { + seq!(i in 0..$N { + #[test] + fn bash_bash_#i() { + let opts = dbg!(&opts()[i]); + let source = Bash(opts).render().unwrap(); + Command::new("bash") + .args(&["-c", &source]) + .assert() + .success() + .stdout("") + .stderr(""); + } + + #[test] + fn bash_shellcheck_#i() { + let opts = dbg!(&opts()[i]); + let source = Bash(opts).render().unwrap(); + Command::new("shellcheck") + .args(&["--shell", "bash", "-"]) + .write_stdin(source) + .assert() + .success() + .stdout("") + .stderr(""); + } + + #[test] + fn bash_shfmt_#i() { + let opts = dbg!(&opts()[i]); + let mut source = Bash(opts).render().unwrap(); + source.push('\n'); + // FIXME: caused by + let source = source.as_str().trim_start(); + Command::new("shfmt") + .args(&["-d", "-s", "-ln", "bash", "-i", "4", "-ci", "-"]) + .write_stdin(source) + .assert() + .success() + .stdout("") + .stderr(""); + } + + #[test] + fn fish_fish_#i() { + let opts = dbg!(&opts()[i]); + let source = Fish(opts).render().unwrap(); + Command::new("fish") + .args(&["-c", &source]) + .assert() + .success() + .stdout("") + .stderr(""); + } + + // TODO: fishindent + + #[test] + fn posix_bashposix_#i() { + let opts = dbg!(&opts()[i]); + let source = Posix(opts).render().unwrap(); + let assert = Command::new("bash") + .args(&["--posix", "-c", &source]) + .assert() + .success() + .stderr(""); + + if opts.hook != Hook::Pwd { + assert.stdout(""); + } + } + + #[test] + fn posix_dash_#i() { + let opts = dbg!(&opts()[i]); + let source = Posix(opts).render().unwrap(); + let assert = Command::new("dash") + .args(&["-c", &source]) + .assert() + .success() + .stderr(""); + + if opts.hook != Hook::Pwd { + assert.stdout(""); + } + } + + #[test] + fn posix_shellcheck_#i() { + let opts = dbg!(&opts()[i]); + let source = Posix(opts).render().unwrap(); + Command::new("shellcheck") + .args(&["--shell", "sh", "-"]) + .write_stdin(source) + .assert() + .success() + .stdout("") + .stderr(""); + } + + #[test] + fn posix_shfmt_#i() { + let opts = dbg!(&opts()[i]); + let mut source = Posix(opts).render().unwrap(); + source.push('\n'); + // FIXME: caused by + let source = source.as_str().trim_start(); + Command::new("shfmt") + .args(&["-d", "-s", "-ln", "posix", "-i", "4", "-ci", "-"]) + .write_stdin(source) + .assert() + .success() + .stdout("") + .stderr(""); + } + + #[test] + fn powershell_pwsh_#i() { + let opts = dbg!(&opts()[i]); + let source = PowerShell(opts).render().unwrap(); + Command::new("pwsh") + .args(&["-c", &source]) + .assert() + .success() + .stdout("") + .stderr(""); + } + + #[test] + fn xonsh_black_#i() { + let opts = dbg!(&opts()[i]); + let mut source = Xonsh(opts).render().unwrap(); + source.push('\n'); + Command::new("black") + .args(&["--check", "--diff", "-"]) + .write_stdin(source) + .assert() + .success() + .stdout(""); + } + + #[test] + fn xonsh_mypy_#i() { + let opts = dbg!(&opts()[i]); + let source = Xonsh(opts).render().unwrap(); + Command::new("mypy") + .args(&["--command", &source]) + .assert() + .success() + .stderr(""); + } + + #[test] + fn xonsh_pylint_#i() { + let opts = dbg!(&opts()[i]); + let mut source = Xonsh(opts).render().unwrap(); + source.push('\n'); + Command::new("pylint") + .args(&["--from-stdin", "zoxide"]) + .write_stdin(source) + .assert() + .success() + .stderr(""); + } + + #[test] + // FIXME: caused by + #[ignore] + fn xonsh_xonsh_#i() { + let opts = dbg!(&opts()[i]); + let source = Xonsh(opts).render().unwrap(); + Command::new("xonsh") + .args(&["-c", &source]) + .assert() + .success() + .stdout("") + .stderr(""); + } + + #[test] + fn zsh_zsh_#i() { + let opts = dbg!(&opts()[i]); + let source = Zsh(opts).render().unwrap(); + Command::new("zsh") + .args(&["-c", &source]) + .assert() + .success() + .stdout("") + .stderr(""); + } + }); } } - #[test] - fn test_bash_posix() { - for opts in opts() { - let source = Posix(opts).render().unwrap(); - let assert = Command::new("bash") - .args(&["--posix", "-c", &source]) - .assert() - .success() - .stderr(""); - - if opts.hook != Hook::Pwd { - assert.stdout(""); - } - } - } - - #[test] - fn test_dash() { - for opts in opts() { - let source = Posix(opts).render().unwrap(); - let assert = Command::new("bash") - .args(&["--posix", "-c", &source]) - .assert() - .success() - .stderr(""); - - if opts.hook != Hook::Pwd { - assert.stdout(""); - } - } - } - - #[test] - fn test_fish() { - for opts in opts() { - let source = Fish(opts).render().unwrap(); - Command::new("fish") - .args(&["-c", &source]) - .assert() - .success() - .stdout("") - .stderr(""); - } - } - - #[test] - fn test_pwsh() { - for opts in opts() { - let source = PowerShell(opts).render().unwrap(); - Command::new("pwsh") - .args(&["-c", &source]) - .assert() - .success() - .stdout("") - .stderr(""); - } - } - - #[test] - fn test_shellcheck_bash() { - for opts in opts() { - let source = Bash(opts).render().unwrap(); - Command::new("shellcheck") - .args(&["--shell", "bash", "-"]) - .write_stdin(source.as_bytes()) - .assert() - .success() - .stdout("") - .stderr(""); - } - } - - #[test] - fn test_shellcheck_sh() { - for opts in opts() { - let source = Posix(opts).render().unwrap(); - Command::new("shellcheck") - .args(&["--shell", "sh", "-"]) - .write_stdin(source.as_bytes()) - .assert() - .success() - .stdout("") - .stderr(""); - } - } - - #[test] - fn test_shfmt_bash() { - for opts in opts() { - let source = Bash(opts).render().unwrap(); - Command::new("shfmt") - .args(&["-d", "-s", "-ln", "bash", "-i", "4", "-ci", "-"]) - .write_stdin(source.as_bytes()) - .write_stdin(b"\n".as_ref()) - .assert() - .success() - .stdout("") - .stderr(""); - } - } - - #[test] - fn test_shfmt_posix() { - for opts in opts() { - let source = Posix(opts).render().unwrap(); - Command::new("shfmt") - .args(&["-d", "-s", "-ln", "posix", "-i", "4", "-ci", "-"]) - .write_stdin(source.as_bytes()) - .write_stdin(b"\n".as_ref()) - .assert() - .success() - .stdout("") - .stderr(""); - } - } - - #[test] - fn test_xonsh() { - for opts in opts() { - let source = Xonsh(opts).render().unwrap(); - Command::new("xonsh") - .args(&["-c", &source]) - .assert() - .success() - .stdout("") - .stderr(""); - } - } - - #[test] - fn test_zsh() { - for opts in opts() { - let source = Zsh(opts).render().unwrap(); - Command::new("zsh") - .args(&["-c", &source]) - .assert() - .success() - .stdout("") - .stderr(""); - } - } + with_opts_size!(generate_tests); } diff --git a/src/store/mod.rs b/src/store/mod.rs index 3878d2e..c71ef37 100644 --- a/src/store/mod.rs +++ b/src/store/mod.rs @@ -245,7 +245,7 @@ mod tests { use super::*; #[test] - fn test_add() { + fn add() { let path = if cfg!(windows) { r"C:\foo\bar" } else { @@ -270,7 +270,7 @@ mod tests { } #[test] - fn test_remove() { + fn remove() { let path = if cfg!(windows) { r"C:\foo\bar" } else { diff --git a/src/store/query.rs b/src/store/query.rs index abca62c..f145085 100644 --- a/src/store/query.rs +++ b/src/store/query.rs @@ -54,47 +54,47 @@ mod tests { use super::Query; #[test] - fn test_query_normalization() { + fn query_normalization() { assert!(Query::new(&["fOo", "bAr"]).matches("/foo/bar")); } #[test] - fn test_query_filename() { + fn query_filename() { assert!(Query::new(&["ba"]).matches("/foo/bar")); } #[test] - fn test_query_not_filename() { + fn query_not_filename() { assert!(!Query::new(&["fo"]).matches("/foo/bar")); } #[test] - fn test_query_not_filename_slash() { + fn query_not_filename_slash() { assert!(!Query::new(&["foo/"]).matches("/foo/bar")); } #[test] - fn test_query_path_separator() { + fn query_path_separator() { assert!(Query::new(&["/", "fo", "/", "ar"]).matches("/foo/bar")); } #[test] - fn test_query_path_separator_between() { + fn query_path_separator_between() { assert!(Query::new(&["oo/ba"]).matches("/foo/bar")); } #[test] - fn test_query_overlap_text() { + fn query_overlap_text() { assert!(!Query::new(&["foo", "o", "bar"]).matches("/foo/bar")); } #[test] - fn test_query_overlap_slash() { + fn query_overlap_slash() { assert!(!Query::new(&["/foo/", "/bar"]).matches("/foo/bar")); } #[test] - fn test_query_consecutive_slash() { + fn query_consecutive_slash() { assert!(Query::new(&["/foo/", "/baz"]).matches("/foo/bar/baz")); } } diff --git a/templates/bash.txt b/templates/bash.txt index b5e17d2..c269fcc 100644 --- a/templates/bash.txt +++ b/templates/bash.txt @@ -74,7 +74,7 @@ function __zoxide_z() { echo "zoxide: \\$OLDPWD is not set" return 1 fi - elif [ "$#" -eq 1 ] && [ -d "$1" ]; then + elif [ "$#" -eq 1 ] && [ -d "$1" ]; then __zoxide_cd "$1" else local __zoxide_result diff --git a/templates/posix.txt b/templates/posix.txt index 4603cc7..a2d0893 100644 --- a/templates/posix.txt +++ b/templates/posix.txt @@ -1,11 +1,12 @@ {%- let SECTION = "# =============================================================================\n#" -%} {%- let NOT_CONFIGURED = "# -- not configured --" -%} -{% if hook == Hook::Pwd -%} +{%- if hook == Hook::Pwd -%} echo "\ zoxide: PWD hooks are not supported on POSIX shells. Use '--hook prompt' when initializing zoxide." -{%- endif %} + +{% endif -%} {{ SECTION }} # Utility functions for zoxide. @@ -77,7 +78,7 @@ __zoxide_z() { echo "zoxide: \\$OLDPWD is not set" return 1 fi - elif [ "$#" -eq 1 ] && [ -d "$1" ]; then + elif [ "$#" -eq 1 ] && [ -d "$1" ]; then __zoxide_cd "$1" else __zoxide_result="$(zoxide query -- "$@")" && __zoxide_cd "$__zoxide_result" diff --git a/templates/xonsh.txt b/templates/xonsh.txt index 96db21e..c8c9a36 100644 --- a/templates/xonsh.txt +++ b/templates/xonsh.txt @@ -1,30 +1,75 @@ {%- let SECTION = "# =============================================================================\n#" -%} {%- let NOT_CONFIGURED = "# -- not configured --" -%} -{%- if resolve_symlinks -%} +"""Initialize zoxide on Xonsh.""" + import os -{%- endif %} import os.path import subprocess import sys - +{%- if cmd.is_some() %} +from builtins import aliases # type: ignore # pylint: disable=no-name-in-module +{%- endif %} +{%- if hook != Hook::None %} +from builtins import events # type: ignore # pylint: disable=no-name-in-module +{%- endif %} from subprocess import CalledProcessError +from typing import AnyStr, List, Optional + +import xonsh.dirstack # type: ignore {{ SECTION }} # Utility functions for zoxide. # -# pwd based on the value of _ZO_RESOLVE_SYMLINKS. + def __zoxide_pwd() -> str: + """pwd based on the value of _ZO_RESOLVE_SYMLINKS.""" {%- if resolve_symlinks %} - return os.getcwd() + pwd = os.getcwd() {%- else %} - return $PWD + pwd = os.getenv("PWD") + if pwd is None: + raise Exception("$PWD not found in env") +{%- endif %} + return pwd + + +def __zoxide_cd(path: Optional[AnyStr] = None): + """cd + custom logic based on the value of _ZO_ECHO.""" + if path is None: + args = [] + elif isinstance(path, bytes): + args = [path.decode("utf-8")] + elif isinstance(path, str): + args = [path] + _, exc, _ = xonsh.dirstack.cd(args) + if exc is not None: + raise Exception(exc) +{%- if echo %} + print(__zoxide_pwd()) {%- endif %} -# cd + custom logic based on the value of _ZO_ECHO. -def __zoxide_cd(path: str): - cd @(path) {%- if echo %} and print(__zoxide_pwd()) {%- endif %} + +class ZoxideSilentException(Exception): + """Exit without complaining.""" + + +def __zoxide_errhandler(func): + """Print exception and exit with error code 1.""" + + def wrapper(args: List[str]): + try: + func(args) + return 0 + except ZoxideSilentException: + return 1 + except Exception as exc: # pylint: disable=broad-except + print(f"zoxide: {exc}", file=sys.stderr) + return 1 + + return wrapper + {{ SECTION }} # Hook configuration for zoxide. @@ -36,77 +81,97 @@ def __zoxide_cd(path: str): {{ NOT_CONFIGURED }} {%- when Hook::Prompt %} -@events.on_post_prompt +@events.on_post_prompt # type: ignore # pylint:disable=undefined-variable {%- when Hook::Pwd %} -@events.on_chdir +@events.on_chdir # type: ignore # pylint:disable=undefined-variable {%- endmatch %} -def __zoxide_hook(**kwargs): - zoxide add @(__zoxide_pwd()) +def __zoxide_hook(**_kwargs): + """Hook to add new entries to the database.""" + pwd = __zoxide_pwd() + subprocess.run(["zoxide", "add", pwd], check=False) + {{ SECTION }} # When using zoxide with --no-aliases, alias these internal functions as # desired. # -# Jump to a directory using only keywords. -def __zoxide_z(keywords: [str]): - if keywords == []: - __zoxide_cd($HOME) - elif keywords == ['-']: - __zoxide_cd('-') - elif len(keywords) == 1 and os.path.isdir(keywords[0]): - __zoxide_cd(keywords[0]) + +@__zoxide_errhandler +def __zoxide_z(args: List[str]): + """Jump to a directory using only keywords.""" + if args == []: + __zoxide_cd() + elif args == ["-"]: + __zoxide_cd("-") + elif len(args) == 1 and os.path.isdir(args[0]): + __zoxide_cd(args[0]) else: try: - __zoxide_cmd = subprocess.run(["zoxide", "query", "--"] + keywords, check=True, stdout=subprocess.PIPE) - except CalledProcessError as e: - return e.returncode - - try: - __zoxide_result = __zoxide_cmd.stdout[:-1].decode("utf-8") - except UnicodeDecodeError: - print(f"zoxide: invalid unicode in result: {__zoxide_result}", file=sys.stderr) - return 1 + __zoxide_cmd = subprocess.run( + ["zoxide", "query", "--"] + args, check=True, stdout=subprocess.PIPE + ) + except CalledProcessError as exc: + raise ZoxideSilentException() from exc + __zoxide_result = __zoxide_cmd.stdout[:-1] __zoxide_cd(__zoxide_result) -# Jump to a directory using interactive search. -def __zoxide_zi(keywords: [str]): - try: - __zoxide_cmd = subprocess.run(["zoxide", "query", "-i", "--"] + keywords, check=True, stdout=subprocess.PIPE) - except CalledProcessError as e: - return e.returncode +def __zoxide_zi(args: List[str]): + """Jump to a directory using interactive search.""" try: - __zoxide_result = __zoxide_cmd.stdout[:-1].decode("utf-8") - except UnicodeDecodeError: - print(f"zoxide: invalid unicode in result: {__zoxide_result}", file=sys.stderr) - return 1 + __zoxide_cmd = subprocess.run( + ["zoxide", "query", "-i", "--"] + args, check=True, stdout=subprocess.PIPE + ) + except CalledProcessError as exc: + raise ZoxideSilentException() from exc + __zoxide_result = __zoxide_cmd.stdout[:-1] __zoxide_cd(__zoxide_result) -# Add a new entry to the database. -def __zoxide_za(args: [str]): - zoxide add @(args) +def __zoxide_za(args: List[str]): + """Add a new entry to the database.""" + try: + subprocess.run(["zoxide", "add"] + args, check=True) + except CalledProcessError as exc: + raise ZoxideSilentException from exc -# Query an entry from the database using only keywords. -def __zoxide_zq(args: [str]): - zoxide query @(args) -# Query an entry from the database using interactive selection. -def __zoxide_zqi(args: [str]): - zoxide query -i @(args) +def __zoxide_zq(args: List[str]): + """Query an entry from the database using only keywords.""" + try: + subprocess.run(["zoxide", "query"] + args, check=True) + except CalledProcessError as exc: + raise ZoxideSilentException from exc -# Remove an entry from the database using the exact path. -def __zoxide_zr(args: [str]): - zoxide remove @(args) -# Remove an entry from the database using interactive selection. -def __zoxide_zri(args: [str]): - zoxide remove -i @(args) +def __zoxide_zqi(args: List[str]): + """Query an entry from the database using interactive selection.""" + try: + subprocess.run(["zoxide", "query", "-i"] + args, check=True) + except CalledProcessError as exc: + raise ZoxideSilentException from exc + + +def __zoxide_zr(args: List[str]): + """Remove an entry from the database using the exact path.""" + try: + subprocess.run(["zoxide", "remove"] + args, check=True) + except CalledProcessError as exc: + raise ZoxideSilentException from exc + + +def __zoxide_zri(args: List[str]): + """Remove an entry from the database using interactive selection.""" + try: + subprocess.run(["zoxide", "remove", "-i"] + args, check=True) + except CalledProcessError as exc: + raise ZoxideSilentException from exc + {{ SECTION }} # Convenient aliases for zoxide. Disable these using --no-aliases. @@ -115,13 +180,13 @@ def __zoxide_zri(args: [str]): {%- match cmd %} {%- when Some with (cmd) %} -aliases['{{cmd}}'] = __zoxide_z -aliases['{{cmd}}i'] = __zoxide_zi -aliases['{{cmd}}a'] = __zoxide_za -aliases['{{cmd}}q'] = __zoxide_zq -aliases['{{cmd}}qi'] = __zoxide_zqi -aliases['{{cmd}}r'] = __zoxide_zr -aliases['{{cmd}}ri'] = __zoxide_zri +aliases["{{cmd}}"] = __zoxide_z +aliases["{{cmd}}i"] = __zoxide_zi +aliases["{{cmd}}a"] = __zoxide_za +aliases["{{cmd}}q"] = __zoxide_zq +aliases["{{cmd}}qi"] = __zoxide_zqi +aliases["{{cmd}}r"] = __zoxide_zr +aliases["{{cmd}}ri"] = __zoxide_zri {%- when None %} {{ NOT_CONFIGURED }}