This commit is contained in:
/dev/mataha 2026-03-25 23:01:27 -04:00 committed by GitHub
commit 8fe5f48726
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
21 changed files with 186 additions and 40 deletions

View File

@ -1,6 +1,3 @@
[alias]
xtask = "run --package xtask --"
# On Windows MSVC, statically link the C runtime so that the resulting EXE does # On Windows MSVC, statically link the C runtime so that the resulting EXE does
# not depend on the vcruntime DLL. # not depend on the vcruntime DLL.
[target.'cfg(all(windows, target_env = "msvc"))'] [target.'cfg(all(windows, target_env = "msvc"))']

16
.editorconfig Normal file
View File

@ -0,0 +1,16 @@
root = true
[*]
charset = utf-8
end_of_line = lf
indent_size = 4
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true
[*.{md,rst,txt}]
indent_size = unset
trim_trailing_whitespace = false
[*.{nix,ts,yml}]
indent_size = 2

9
.gitattributes vendored
View File

@ -1,5 +1,4 @@
/contrib/completions/* eol=lf linguist-generated=true text * text=auto eol=lf
/contrib/completions/README.md -eol -linguist-generated -text
/init.fish eol=lf text /contrib/completions/** linguist-generated
/templates/*.txt eol=lf text /contrib/completions/README.md -linguist-generated
/zoxide.plugin.zsh eol=lf text

View File

@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added ### Added
- POSIX: support for non-Cygwin Windows environments (e.g. Busybox). - POSIX: support for non-Cygwin Windows environments (e.g. Busybox).
- Support for `cmd.exe` (experimental).
### Fixed ### Fixed

View File

@ -25,7 +25,7 @@ bincode = "1.3.1"
clap = { version = "4.3.0", features = ["derive"] } clap = { version = "4.3.0", features = ["derive"] }
color-print = "0.3.4" color-print = "0.3.4"
dirs = "6.0.0" dirs = "6.0.0"
dunce = "1.0.1" dunce = "1.0.4"
fastrand = "2.0.0" fastrand = "2.0.0"
glob = "0.3.0" glob = "0.3.0"
ouroboros = "0.18.3" ouroboros = "0.18.3"

View File

@ -148,9 +148,6 @@ zoxide can be installed in 4 easy steps:
<details> <details>
<summary>Windows</summary> <summary>Windows</summary>
> zoxide works with PowerShell, as well as shells running in Cygwin, Git
> Bash, and MSYS2.
>
> The recommended way to install zoxide is via `winget`: > The recommended way to install zoxide is via `winget`:
> >
> ```sh > ```sh
@ -226,6 +223,18 @@ zoxide can be installed in 4 easy steps:
</details> </details>
<details>
<summary><code>cmd.exe</code></summary>
> Add this to the <ins>**end**</ins> of your config file or AutoRun command
> (usually `HKEY_CURRENT_USER\Software\Microsoft\Command Processor\AutoRun`):
>
> ```batchfile
> zoxide init cmd | cmd /d/q/k echo off
> ```
</details>
<details> <details>
<summary>Elvish</summary> <summary>Elvish</summary>
@ -415,7 +424,7 @@ When calling `zoxide init`, the following flags are available:
- `--cmd` - `--cmd`
- Changes the prefix of the `z` and `zi` commands. - Changes the prefix of the `z` and `zi` commands.
- `--cmd j` would change the commands to (`j`, `ji`). - `--cmd j` would change the commands to (`j`, `ji`).
- `--cmd cd` would replace the `cd` command. - `--cmd cd` would replace the `cd` command (highly recommended on `cmd.exe`).
- `--hook <HOOK>` - `--hook <HOOK>`
- Changes how often zoxide increments a directory's score: - Changes how often zoxide increments a directory's score:
@ -427,8 +436,8 @@ When calling `zoxide init`, the following flags are available:
- `--no-cmd` - `--no-cmd`
- Prevents zoxide from defining the `z` and `zi` commands. - Prevents zoxide from defining the `z` and `zi` commands.
- These functions will still be available in your shell as `__zoxide_z` and - These functions will still be available in your shell (not on `cmd.exe`)
`__zoxide_zi`, should you choose to redefine them. as `__zoxide_z` and `__zoxide_zi`, should you choose to redefine them.
### Environment variables ### Environment variables
@ -446,17 +455,16 @@ Environment variables[^2] can be used for configuration. They must be set before
| Windows | `%LOCALAPPDATA%` | `C:\Users\Alice\AppData\Local` | | Windows | `%LOCALAPPDATA%` | `C:\Users\Alice\AppData\Local` |
- `_ZO_ECHO` - `_ZO_ECHO`
- When set to 1, `z` will print the matched directory before navigating to - When set to 1, `z` will print the matched directory after navigating to it.
it.
- `_ZO_EXCLUDE_DIRS` - `_ZO_EXCLUDE_DIRS`
- Excludes the specified directories from the database. - Excludes the specified directories from the database.
- This is provided as a list of [globs][glob], separated by OS-specific - This is provided as a list of [globs][glob], separated by OS-specific
characters: characters:
| OS | Separator | Example | | OS | Separator | Example |
| ------------------- | --------- | ----------------------- | | ------------------- | --------- | ------------------------- |
| Linux / macOS / BSD | `:` | `$HOME:$HOME/private/*` | | Linux / macOS / BSD | `:` | `$HOME:$HOME/private/*` |
| Windows | `;` | `$HOME;$HOME/private/*` | | Windows | `;` | `%HOME%;%HOME%/private/*` |
- By default, this is set to `"$HOME"`. - By default, this is set to `"$HOME"`.
- `_ZO_FZF_OPTS` - `_ZO_FZF_OPTS`

View File

@ -114,7 +114,7 @@ _arguments "${_arguments_options[@]}" : \
'--help[Print help]' \ '--help[Print help]' \
'-V[Print version]' \ '-V[Print version]' \
'--version[Print version]' \ '--version[Print version]' \
':shell:(bash elvish fish nushell posix powershell tcsh xonsh zsh)' \ ':shell:(bash cmd elvish fish nushell posix powershell tcsh xonsh zsh)' \
&& ret=0 && ret=0
;; ;;
(query) (query)

View File

@ -177,7 +177,7 @@ _zoxide() {
return 0 return 0
;; ;;
zoxide__init) zoxide__init)
opts="-h -V --no-cmd --cmd --hook --help --version bash elvish fish nushell posix powershell tcsh xonsh zsh" opts="-h -V --no-cmd --cmd --hook --help --version bash cmd elvish fish nushell posix powershell tcsh xonsh zsh"
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0 return 0

View File

@ -57,7 +57,7 @@ module completions {
] ]
def "nu-complete zoxide init shell" [] { def "nu-complete zoxide init shell" [] {
[ "bash" "elvish" "fish" "nushell" "posix" "powershell" "tcsh" "xonsh" "zsh" ] [ "bash" "cmd" "elvish" "fish" "nushell" "posix" "powershell" "tcsh" "xonsh" "zsh" ]
} }
def "nu-complete zoxide init hook" [] { def "nu-complete zoxide init hook" [] {

View File

@ -189,6 +189,7 @@ const completion: Fig.Spec = {
name: "shell", name: "shell",
suggestions: [ suggestions: [
"bash", "bash",
"cmd",
"elvish", "elvish",
"fish", "fish",
"nushell", "nushell",

View File

@ -13,6 +13,14 @@ Add this to the \fBend\fR of your config file (usually \fB~/.bashrc\fR):
\fBeval "$(zoxide init bash)"\fR \fBeval "$(zoxide init bash)"\fR
.fi .fi
.TP .TP
.B cmd.exe
Add this to the \fBend\fR of your config file or AutoRun command (usually
\fBHKEY_CURRENT_USER\\Software\\Microsoft\\Command Processor\\AutoRun\fR):
.sp
.nf
\fBzoxide init cmd | cmd /d/q/k echo off\fR
.fi
.TP
.B elvish .B elvish
Add this to the \fBend\fR of your config file (usually \fB~/.elvish/rc.elv\fR): Add this to the \fBend\fR of your config file (usually \fB~/.elvish/rc.elv\fR):
.sp .sp
@ -91,8 +99,8 @@ Changes the prefix of the \fBz\fR and \fBzi\fR commands.
.br .br
\fB--cmd j\fR would change the commands to (\fBj\fR, \fBji\fR). \fB--cmd j\fR would change the commands to (\fBj\fR, \fBji\fR).
.br .br
\fB--cmd cd\fR would replace the \fBcd\fR command (doesn't work on Nushell / \fB--cmd cd\fR would replace the \fBcd\fR command (highly recommended on
POSIX shells). \fBcmd.exe\fR).
.TP .TP
.B -h, --help .B -h, --help
Print help information. Print help information.
@ -109,8 +117,8 @@ l l.
.TP .TP
.B --no-cmd .B --no-cmd
Prevents zoxide from defining the \fBz\fR and \fBzi\fR commands. These functions Prevents zoxide from defining the \fBz\fR and \fBzi\fR commands. These functions
will still be available in your shell as \fB__zoxide_z\fR and \fB__zoxide_zi\fR, will still be available in your shell (not on \fBcmd.exe\fR) as \fB__zoxide_z\fR
should you choose to redefine them. and \fB__zoxide_zi\fR, should you choose to redefine them.
.SH REPORTING BUGS .SH REPORTING BUGS
For any issues, feature requests, or questions, please visit: For any issues, feature requests, or questions, please visit:
.sp .sp

View File

@ -70,7 +70,7 @@ T}
.TE .TE
.TP .TP
.B _ZO_ECHO .B _ZO_ECHO
When set to 1, \fBz\fR will print the matched directory before navigating to it. When set to 1, \fBz\fR will print the matched directory after navigating to it.
.TP .TP
.B _ZO_EXCLUDE_DIRS .B _ZO_EXCLUDE_DIRS
Prevents the specified directories from being added to the database. This is Prevents the specified directories from being added to the database. This is
@ -82,7 +82,7 @@ l l.
\fBLinux/macOS/BSD\fR|T{ \fBLinux/macOS/BSD\fR|T{
\fB:\fR, eg. \fB$HOME:$HOME/private/*\fR \fB:\fR, eg. \fB$HOME:$HOME/private/*\fR
T} T}
\fBWindows\fR|\fB;\fR, eg. \fB$HOME;$HOME/private/*\fR \fBWindows\fR|\fB;\fR, eg. \fB%HOME%;%HOME%/private/*\fR
.TE .TE
.sp .sp
By default, this is set to \fB$HOME\fR. After setting this up, you might need By default, this is set to \fB$HOME\fR. After setting this up, you might need

View File

@ -1,6 +1,6 @@
group_imports = "StdExternalCrate" group_imports = "StdExternalCrate"
imports_granularity = "Module" imports_granularity = "Module"
newline_style = "Native" newline_style = "Unix"
use_field_init_shorthand = true use_field_init_shorthand = true
use_small_heuristics = "Max" use_small_heuristics = "Max"
use_try_shorthand = true use_try_shorthand = true

View File

@ -147,6 +147,7 @@ pub enum InitHook {
#[derive(ValueEnum, Clone, Debug)] #[derive(ValueEnum, Clone, Debug)]
pub enum InitShell { pub enum InitShell {
Bash, Bash,
Cmd,
Elvish, Elvish,
Fish, Fish,
Nushell, Nushell,

View File

@ -6,7 +6,7 @@ use askama::Template;
use crate::cmd::{Init, InitShell, Run}; use crate::cmd::{Init, InitShell, Run};
use crate::config; use crate::config;
use crate::error::BrokenPipeHandler; use crate::error::BrokenPipeHandler;
use crate::shell::{Bash, Elvish, Fish, Nushell, Opts, Posix, Powershell, Tcsh, Xonsh, Zsh}; use crate::shell::{Bash, Cmd, Elvish, Fish, Nushell, Opts, Posix, Powershell, Tcsh, Xonsh, Zsh};
impl Run for Init { impl Run for Init {
fn run(&self) -> Result<()> { fn run(&self) -> Result<()> {
@ -17,6 +17,7 @@ impl Run for Init {
let source = match self.shell { let source = match self.shell {
InitShell::Bash => Bash(opts).render(), InitShell::Bash => Bash(opts).render(),
InitShell::Cmd => Cmd(opts).render(),
InitShell::Elvish => Elvish(opts).render(), InitShell::Elvish => Elvish(opts).render(),
InitShell::Fish => Fish(opts).render(), InitShell::Fish => Fish(opts).render(),
InitShell::Nushell => Nushell(opts).render(), InitShell::Nushell => Nushell(opts).render(),

View File

@ -1,5 +1,3 @@
#![allow(clippy::single_component_path_imports)]
mod cmd; mod cmd;
mod config; mod config;
mod db; mod db;

View File

@ -11,7 +11,7 @@ pub struct Opts<'a> {
macro_rules! make_template { macro_rules! make_template {
($name:ident, $path:expr) => { ($name:ident, $path:expr) => {
#[derive(::std::fmt::Debug, ::askama::Template)] #[derive(::std::fmt::Debug, ::askama::Template)]
#[template(path = $path)] #[template(path = $path, escape = "none")]
pub struct $name<'a>(pub &'a self::Opts<'a>); pub struct $name<'a>(pub &'a self::Opts<'a>);
impl<'a> ::std::ops::Deref for $name<'a> { impl<'a> ::std::ops::Deref for $name<'a> {
@ -24,6 +24,7 @@ macro_rules! make_template {
} }
make_template!(Bash, "bash.txt"); make_template!(Bash, "bash.txt");
make_template!(Cmd, "cmd.txt");
make_template!(Elvish, "elvish.txt"); make_template!(Elvish, "elvish.txt");
make_template!(Fish, "fish.txt"); make_template!(Fish, "fish.txt");
make_template!(Nushell, "nushell.txt"); make_template!(Nushell, "nushell.txt");
@ -54,6 +55,7 @@ mod tests {
} }
#[apply(opts)] #[apply(opts)]
#[cfg(unix)]
fn bash_bash(cmd: Option<&str>, hook: InitHook, echo: bool, resolve_symlinks: bool) { fn bash_bash(cmd: Option<&str>, hook: InitHook, echo: bool, resolve_symlinks: bool) {
let opts = Opts { cmd, hook, echo, resolve_symlinks }; let opts = Opts { cmd, hook, echo, resolve_symlinks };
let source = Bash(&opts).render().unwrap(); let source = Bash(&opts).render().unwrap();
@ -66,6 +68,7 @@ mod tests {
} }
#[apply(opts)] #[apply(opts)]
#[cfg(unix)]
fn bash_shellcheck(cmd: Option<&str>, hook: InitHook, echo: bool, resolve_symlinks: bool) { fn bash_shellcheck(cmd: Option<&str>, hook: InitHook, echo: bool, resolve_symlinks: bool) {
let opts = Opts { cmd, hook, echo, resolve_symlinks }; let opts = Opts { cmd, hook, echo, resolve_symlinks };
let source = Bash(&opts).render().unwrap(); let source = Bash(&opts).render().unwrap();
@ -80,6 +83,7 @@ mod tests {
} }
#[apply(opts)] #[apply(opts)]
#[cfg(unix)]
fn bash_shfmt(cmd: Option<&str>, hook: InitHook, echo: bool, resolve_symlinks: bool) { fn bash_shfmt(cmd: Option<&str>, hook: InitHook, echo: bool, resolve_symlinks: bool) {
let opts = Opts { cmd, hook, echo, resolve_symlinks }; let opts = Opts { cmd, hook, echo, resolve_symlinks };
let mut source = Bash(&opts).render().unwrap(); let mut source = Bash(&opts).render().unwrap();
@ -95,6 +99,45 @@ mod tests {
} }
#[apply(opts)] #[apply(opts)]
#[cfg(windows)]
fn cmd_cmd(cmd: Option<&str>, hook: InitHook, echo: bool, resolve_symlinks: bool) {
let opts = Opts { cmd, hook, echo, resolve_symlinks };
let source = Cmd(&opts).render().unwrap();
let assert = Command::new(which::which("cmd.exe").unwrap())
.args(["/x", "/d", "/q", "/k", "echo off"])
.env("PROMPT", "")
.write_stdin(source)
.assert()
.success()
.stderr("");
if opts.hook == InitHook::None {
assert.stdout("");
}
}
#[apply(opts)]
#[cfg(windows)]
fn cmd_dos(cmd: Option<&str>, hook: InitHook, echo: bool, resolve_symlinks: bool) {
let opts = Opts { cmd, hook, echo, resolve_symlinks };
let source = Cmd(&opts).render().unwrap();
let assert = Command::new(which::which("cmd.exe").unwrap())
.args(["/y", "/d", "/q", "/k", "echo off"])
.env("PROMPT", "")
.write_stdin(source)
.assert()
.success()
.stderr("");
if opts.hook == InitHook::None {
assert.stdout("");
}
}
#[apply(opts)]
#[cfg(unix)]
fn elvish_elvish(cmd: Option<&str>, hook: InitHook, echo: bool, resolve_symlinks: bool) { fn elvish_elvish(cmd: Option<&str>, hook: InitHook, echo: bool, resolve_symlinks: bool) {
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();
@ -115,6 +158,7 @@ mod tests {
} }
#[apply(opts)] #[apply(opts)]
#[cfg(unix)]
fn fish_no_builtin_abbr(cmd: Option<&str>, hook: InitHook, echo: bool, resolve_symlinks: bool) { fn fish_no_builtin_abbr(cmd: Option<&str>, hook: InitHook, echo: bool, resolve_symlinks: bool) {
let opts = Opts { cmd, hook, echo, resolve_symlinks }; let opts = Opts { cmd, hook, echo, resolve_symlinks };
let source = Fish(&opts).render().unwrap(); let source = Fish(&opts).render().unwrap();
@ -125,6 +169,7 @@ mod tests {
} }
#[apply(opts)] #[apply(opts)]
#[cfg(unix)]
fn fish_fish(cmd: Option<&str>, hook: InitHook, echo: bool, resolve_symlinks: bool) { fn fish_fish(cmd: Option<&str>, hook: InitHook, echo: bool, resolve_symlinks: bool) {
let opts = Opts { cmd, hook, echo, resolve_symlinks }; let opts = Opts { cmd, hook, echo, resolve_symlinks };
let source = Fish(&opts).render().unwrap(); let source = Fish(&opts).render().unwrap();
@ -142,6 +187,7 @@ mod tests {
} }
#[apply(opts)] #[apply(opts)]
#[cfg(unix)]
fn fish_fishindent(cmd: Option<&str>, hook: InitHook, echo: bool, resolve_symlinks: bool) { fn fish_fishindent(cmd: Option<&str>, hook: InitHook, echo: bool, resolve_symlinks: bool) {
let opts = Opts { cmd, hook, echo, resolve_symlinks }; let opts = Opts { cmd, hook, echo, resolve_symlinks };
let mut source = Fish(&opts).render().unwrap(); let mut source = Fish(&opts).render().unwrap();
@ -160,6 +206,7 @@ mod tests {
} }
#[apply(opts)] #[apply(opts)]
#[cfg(unix)]
fn nushell_nushell(cmd: Option<&str>, hook: InitHook, echo: bool, resolve_symlinks: bool) { fn nushell_nushell(cmd: Option<&str>, hook: InitHook, echo: bool, resolve_symlinks: bool) {
let opts = Opts { cmd, hook, echo, resolve_symlinks }; let opts = Opts { cmd, hook, echo, resolve_symlinks };
let source = Nushell(&opts).render().unwrap(); let source = Nushell(&opts).render().unwrap();
@ -180,6 +227,7 @@ mod tests {
} }
#[apply(opts)] #[apply(opts)]
#[cfg(unix)]
fn posix_bash(cmd: Option<&str>, hook: InitHook, echo: bool, resolve_symlinks: bool) { fn posix_bash(cmd: Option<&str>, hook: InitHook, echo: bool, resolve_symlinks: bool) {
let opts = Opts { cmd, hook, echo, resolve_symlinks }; let opts = Opts { cmd, hook, echo, resolve_symlinks };
let source = Posix(&opts).render().unwrap(); let source = Posix(&opts).render().unwrap();
@ -195,6 +243,7 @@ mod tests {
} }
#[apply(opts)] #[apply(opts)]
#[cfg(unix)]
fn posix_dash(cmd: Option<&str>, hook: InitHook, echo: bool, resolve_symlinks: bool) { fn posix_dash(cmd: Option<&str>, hook: InitHook, echo: bool, resolve_symlinks: bool) {
let opts = Opts { cmd, hook, echo, resolve_symlinks }; let opts = Opts { cmd, hook, echo, resolve_symlinks };
let source = Posix(&opts).render().unwrap(); let source = Posix(&opts).render().unwrap();
@ -207,6 +256,7 @@ mod tests {
} }
#[apply(opts)] #[apply(opts)]
#[cfg(unix)]
fn posix_shellcheck(cmd: Option<&str>, hook: InitHook, echo: bool, resolve_symlinks: bool) { fn posix_shellcheck(cmd: Option<&str>, hook: InitHook, echo: bool, resolve_symlinks: bool) {
let opts = Opts { cmd, hook, echo, resolve_symlinks }; let opts = Opts { cmd, hook, echo, resolve_symlinks };
let source = Posix(&opts).render().unwrap(); let source = Posix(&opts).render().unwrap();
@ -221,6 +271,7 @@ mod tests {
} }
#[apply(opts)] #[apply(opts)]
#[cfg(unix)]
fn posix_shfmt(cmd: Option<&str>, hook: InitHook, echo: bool, resolve_symlinks: bool) { fn posix_shfmt(cmd: Option<&str>, hook: InitHook, echo: bool, resolve_symlinks: bool) {
let opts = Opts { cmd, hook, echo, resolve_symlinks }; let opts = Opts { cmd, hook, echo, resolve_symlinks };
let mut source = Posix(&opts).render().unwrap(); let mut source = Posix(&opts).render().unwrap();
@ -236,6 +287,7 @@ mod tests {
} }
#[apply(opts)] #[apply(opts)]
#[cfg(unix)]
fn powershell_pwsh(cmd: Option<&str>, hook: InitHook, echo: bool, resolve_symlinks: bool) { fn powershell_pwsh(cmd: Option<&str>, hook: InitHook, echo: bool, resolve_symlinks: bool) {
let opts = Opts { cmd, hook, echo, resolve_symlinks }; let opts = Opts { cmd, hook, echo, resolve_symlinks };
let mut source = "Set-StrictMode -Version latest\n".to_string(); let mut source = "Set-StrictMode -Version latest\n".to_string();
@ -250,6 +302,7 @@ mod tests {
} }
#[apply(opts)] #[apply(opts)]
#[cfg(unix)]
fn tcsh_tcsh(cmd: Option<&str>, hook: InitHook, echo: bool, resolve_symlinks: bool) { fn tcsh_tcsh(cmd: Option<&str>, hook: InitHook, echo: bool, resolve_symlinks: bool) {
let opts = Opts { cmd, hook, echo, resolve_symlinks }; let opts = Opts { cmd, hook, echo, resolve_symlinks };
let source = Tcsh(&opts).render().unwrap(); let source = Tcsh(&opts).render().unwrap();
@ -264,6 +317,7 @@ mod tests {
} }
#[apply(opts)] #[apply(opts)]
#[cfg(unix)]
fn xonsh_black(cmd: Option<&str>, hook: InitHook, echo: bool, resolve_symlinks: bool) { fn xonsh_black(cmd: Option<&str>, hook: InitHook, echo: bool, resolve_symlinks: bool) {
let opts = Opts { cmd, hook, echo, resolve_symlinks }; let opts = Opts { cmd, hook, echo, resolve_symlinks };
let mut source = Xonsh(&opts).render().unwrap(); let mut source = Xonsh(&opts).render().unwrap();
@ -278,6 +332,7 @@ mod tests {
} }
#[apply(opts)] #[apply(opts)]
#[cfg(unix)]
fn xonsh_mypy(cmd: Option<&str>, hook: InitHook, echo: bool, resolve_symlinks: bool) { fn xonsh_mypy(cmd: Option<&str>, hook: InitHook, echo: bool, resolve_symlinks: bool) {
let opts = Opts { cmd, hook, echo, resolve_symlinks }; let opts = Opts { cmd, hook, echo, resolve_symlinks };
let source = Xonsh(&opts).render().unwrap(); let source = Xonsh(&opts).render().unwrap();
@ -286,6 +341,7 @@ mod tests {
} }
#[apply(opts)] #[apply(opts)]
#[cfg(unix)]
fn xonsh_pylint(cmd: Option<&str>, hook: InitHook, echo: bool, resolve_symlinks: bool) { fn xonsh_pylint(cmd: Option<&str>, hook: InitHook, echo: bool, resolve_symlinks: bool) {
let opts = Opts { cmd, hook, echo, resolve_symlinks }; let opts = Opts { cmd, hook, echo, resolve_symlinks };
let mut source = Xonsh(&opts).render().unwrap(); let mut source = Xonsh(&opts).render().unwrap();
@ -300,6 +356,7 @@ mod tests {
} }
#[apply(opts)] #[apply(opts)]
#[cfg(unix)]
fn xonsh_xonsh(cmd: Option<&str>, hook: InitHook, echo: bool, resolve_symlinks: bool) { fn xonsh_xonsh(cmd: Option<&str>, hook: InitHook, echo: bool, resolve_symlinks: bool) {
let opts = Opts { cmd, hook, echo, resolve_symlinks }; let opts = Opts { cmd, hook, echo, resolve_symlinks };
let source = Xonsh(&opts).render().unwrap(); let source = Xonsh(&opts).render().unwrap();
@ -317,6 +374,7 @@ mod tests {
} }
#[apply(opts)] #[apply(opts)]
#[cfg(unix)]
fn zsh_shellcheck(cmd: Option<&str>, hook: InitHook, echo: bool, resolve_symlinks: bool) { fn zsh_shellcheck(cmd: Option<&str>, hook: InitHook, echo: bool, resolve_symlinks: bool) {
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();
@ -332,6 +390,7 @@ mod tests {
} }
#[apply(opts)] #[apply(opts)]
#[cfg(unix)]
fn zsh_zsh(cmd: Option<&str>, hook: InitHook, echo: bool, resolve_symlinks: bool) { fn zsh_zsh(cmd: Option<&str>, hook: InitHook, echo: bool, resolve_symlinks: bool) {
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();

View File

@ -31,7 +31,7 @@ impl Fzf {
// Instead, we resolve the path to the executable and then pass it to // Instead, we resolve the path to the executable and then pass it to
// CreateProcess. // CreateProcess.
#[cfg(windows)] #[cfg(windows)]
let program = which::which("fzf.exe").map_err(|_| anyhow!(Self::ERR_FZF_NOT_FOUND))?; let program = which::which("fzf").map_err(|_| anyhow!(Self::ERR_FZF_NOT_FOUND))?;
#[cfg(not(windows))] #[cfg(not(windows))]
let program = "fzf"; let program = "fzf";

58
templates/cmd.txt Normal file
View File

@ -0,0 +1,58 @@
{%- let section = "::: ===========================================================================\n:::" -%}
{%- let not_configured = "::: -- not configured --" -%}
{%- if hook != InitHook::None -%}
echo zoxide: hooks are not supported on cmd.exe shell.
echo Use '%program% init cmd --hook none' instead.
{% endif -%}
@if "%=^%=" == "%=%=" (set \p=%%<nul) else (set \p=^%<nul)
set program=zoxide
set builtin_cd=chdir /d
set builtin_pwd=(chdir)
::: Get Windows' system directory, like GetSystemDirectoryW.
@if "" == "%SystemRoot%" (set sysdir="%__APPDIR__%") else (set sysdir="%SystemRoot%\system32\")
{{ section }}
::: Utility functions for zoxide.
:::
::: pwd based on the value of _ZO_RESOLVE_SYMLINKS.
set __zoxide_pwd= {%- if resolve_symlinks -%} (for /f "skip=9 tokens=1,2,*" %\p%j in ('^^^^^^^^"%sysdir%fsutil.exe reparsepoint query .^"') do if "%\p%~j" equ "Print" if "%\p%~k" equ "Name:" if "%\p%~l" neq "" (echo(%\p%~l)) ^^^^^^^|^^^^^^^| {%~ endif -%} %builtin_pwd%
::: cd + custom logic based on the value of _ZO_ECHO.
set __zoxide_cd=if /i "%\p%CD%\p%" neq "%\p%~fd" (%builtin_cd% "%\p%~fd" ^^^&^^^& set "OLDPWD=%\p%CD%\p%" ^^^&^^^& (for /f "delims=" %\p%l in ('"%builtin_pwd%"') do if /i "%\p%~fl" neq "%\p%~dpl" (%program% add -- "%\p%~fl") else (%program% add -- "%\p%~dpl\")) {%- if echo ~%} ^^^&^^^& %__zoxide_pwd% {%- endif ~%} ^^^&^^^& if defined CDCMD (call %\p%CDCMD%\p%))
{{ section }}
::: Commands for zoxide. Disable these using --no-cmd.
:::
{%- match cmd %}
{%- when Some with (cmd) %}
::: Jump to a directory using only keywords.
%sysdir%doskey.exe {{ cmd }} = @if not defined _ZO_DOCTOR (echo off) $T for /f "delims=" %\p%s in ('"%sysdir%chcp.com 2>nul"') do for %\p%c in (%\p%~s) do set "_ZO_CODEPAGE=%\p%~nc" $T %sysdir%mode.com con:cp select=65001 ^>nul $T (for %\p%^^^^ in ("") do for /f "delims=" %\p%i in (^^""$*%\p%~^^"^") do if "%\p%~i" equ "" (if "%\p%HOMEDRIVE%\p%%\p%HOMEPATH%\p%" equ "" (for /f "delims=" %\p%d in (^^""%\p%USERPROFILE%\p%"^") do %__zoxide_cd%) else for /f "delims=" %\p%d in (^^""%\p%HOMEDRIVE%\p%%\p%HOMEPATH%\p%"^") do %__zoxide_cd%) else if "%\p%~i" equ "~" (if "%\p%HOMEDRIVE%\p%%\p%HOMEPATH%\p%" equ "" (for /f "delims=" %\p%d in (^^""%\p%USERPROFILE%\p%"^") do %__zoxide_cd%) else for /f "delims=" %\p%d in (^^""%\p%HOMEDRIVE%\p%%\p%HOMEPATH%\p%"^") do %__zoxide_cd%) else if "%\p%~i" equ "-" (if defined OLDPWD (for /f "delims=" %\p%d in (^^""%\p%OLDPWD%\p%"^") do %__zoxide_cd%) else ^>^&2 (echo(%program%: OLDPWD not set) ^& call) else for /f "delims=" %\p%~ in (^^"%\p%~i^") do for /f "tokens=1,* delims=d" %\p%a in ("-%\p%~a~") do if "%\p%b" neq "" (for /f "delims=" %\p%d in (^^""%\p%~f~"^") do %__zoxide_cd%) else if /i "%\p%CD%\p%" neq "%\p%__CD__%\p%" (for /f "delims=" %\p%q in ('^^"%program% query --exclude "%\p%CD%\p%" -- %\p%~i^"') do (for /f "delims=" %\p%d in (^^""%\p%~fq"^") do %__zoxide_cd%)) else (for /f "delims=" %\p%q in ('^^"%program% query --exclude "%\p%__CD__%\p%\" -- %\p%~i^"') do (for /f "delims=" %\p%d in (^^""%\p%~fq"^") do %__zoxide_cd%))) ^&^& (for /f "delims=" %\p%v in ('"set /a _ZO_CODEPAGE"') do %sysdir%mode.com con:cp select=%\p%~v ^>nul) ^|^| (for /f "delims=" %\p%v in ('"set /a _ZO_CODEPAGE"') do %sysdir%mode.com con:cp select=%\p%~v ^>nul ^& call) $T set "_ZO_CODEPAGE=" ^& echo on
::: Jump to a directory using interactive search.
%sysdir%doskey.exe {{ cmd }}i = @if not defined _ZO_DOCTOR (echo off) $T for /f "delims=" %\p%s in ('"%sysdir%chcp.com 2>nul"') do for %\p%c in (%\p%~s) do set "_ZO_CODEPAGE=%\p%~nc" $T %sysdir%mode.com con:cp select=65001 ^>nul $T (for %\p%^^^^ in ("") do for /f "delims=" %\p%i in (^^""$*%\p%~^^"^") do for /f "delims=" %\p%p in ('^^"%program% query --interactive -- %\p%~i^"') do for /f "delims=" %\p%d in (^^""%\p%~fp"^") do %__zoxide_cd%) ^&^& (for /f "delims=" %\p%v in ('"set /a _ZO_CODEPAGE"') do %sysdir%mode.com con:cp select=%\p%~v ^>nul) ^|^| (for /f "delims=" %\p%v in ('"set /a _ZO_CODEPAGE"') do %sysdir%mode.com con:cp select=%\p%~v ^>nul ^& call) $T set "_ZO_CODEPAGE=" ^& echo on
{%- when None %}
{{ not_configured }}
{%- endmatch %}
{{ section }}
::: To initialize zoxide, add this to your configuration or AutoRun command
::: (usually HKEY_CURRENT_USER\Software\Microsoft\Command Processor\AutoRun):
:::
::: zoxide init cmd | cmd /d/q/k echo off
{#~
Content piped to `cmd.exe` needs to end with an empty line to indicate end of
input. Removing this will cause extra "More? " to be written to stdout.
#}

View File

@ -101,8 +101,7 @@ __zoxide_z() {
if [ -n "${OLDPWD}" ]; then if [ -n "${OLDPWD}" ]; then
__zoxide_cd "${OLDPWD}" __zoxide_cd "${OLDPWD}"
else else
# shellcheck disable=SC2016 \command printf 'zoxide: OLDPWD not set'
\command printf 'zoxide: $OLDPWD is not set'
return 1 return 1
fi fi
elif [ "$#" -eq 1 ] && [ -d "$1" ]; then elif [ "$#" -eq 1 ] && [ -d "$1" ]; then

View File

@ -1,5 +1,5 @@
if (( $+commands[zoxide] )); then if (( $+commands[zoxide] )); then
eval "$(zoxide init zsh)" eval "$(zoxide init zsh)"
else else
echo 'zoxide: command not found, please install it from https://github.com/ajeetdsouza/zoxide' echo 'zoxide: command not found, please install it from https://github.com/ajeetdsouza/zoxide'
fi fi