Split tests
This commit is contained in:
parent
21018d5847
commit
58bcbef7aa
|
|
@ -14,8 +14,10 @@ jobs:
|
||||||
- run: sudo dpkg -i packages-microsoft-prod.deb
|
- run: sudo dpkg -i packages-microsoft-prod.deb
|
||||||
- run: sudo apt update
|
- run: sudo apt update
|
||||||
- run: sudo add-apt-repository universe
|
- 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 snap install shfmt
|
||||||
|
- run: sudo pip3 install --upgrade pip setuptools
|
||||||
|
- run: sudo pip3 install --upgrade black mypy pylint
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- uses: actions-rs/toolchain@v1
|
- uses: actions-rs/toolchain@v1
|
||||||
with:
|
with:
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,9 @@
|
||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anyhow"
|
name = "anyhow"
|
||||||
version = "1.0.33"
|
version = "1.0.34"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a1fd36ffbb1fb7c834eac128ea8d0e310c5aeb635548f9d58861e1308d46e71c"
|
checksum = "bf8dcb5b4bbaa28653b647d8c77bd4ed40183b48882e130c1f1ffb73de069fd7"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "askama"
|
name = "askama"
|
||||||
|
|
@ -152,9 +152,9 @@ checksum = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dirs-next"
|
name = "dirs-next"
|
||||||
version = "1.0.2"
|
version = "2.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cf36e65a80337bea855cd4ef9b8401ffce06a7baedf2e85ec467b1ac3f6e82b6"
|
checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if 1.0.0",
|
"cfg-if 1.0.0",
|
||||||
"dirs-sys-next",
|
"dirs-sys-next",
|
||||||
|
|
@ -248,9 +248,9 @@ checksum = "4d58d1b70b004888f764dfbf6a26a3b0342a1632d33968e4a179d8011c760614"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "memchr"
|
name = "memchr"
|
||||||
version = "2.3.3"
|
version = "2.3.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400"
|
checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nom"
|
name = "nom"
|
||||||
|
|
@ -264,9 +264,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-traits"
|
name = "num-traits"
|
||||||
version = "0.2.12"
|
version = "0.2.14"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ac267bcc07f48ee5f8935ab0d24f316fb722d7a1292e2913f0cc196b29ffd611"
|
checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg",
|
"autocfg",
|
||||||
]
|
]
|
||||||
|
|
@ -288,15 +288,15 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "os_str_bytes"
|
name = "os_str_bytes"
|
||||||
version = "2.3.2"
|
version = "2.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2ac6fe3538f701e339953a3ebbe4f39941aababa8a3f6964635b24ab526daeac"
|
checksum = "afb2e1c3ee07430c2cf76151675e583e0f19985fa6efae47d6848a3e2c824f85"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ppv-lite86"
|
name = "ppv-lite86"
|
||||||
version = "0.2.9"
|
version = "0.2.10"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c36fa947111f5c62a733b652544dd0016a43ce89619538a8ef92724a6f501a20"
|
checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "predicates"
|
name = "predicates"
|
||||||
|
|
@ -432,6 +432,12 @@ dependencies = [
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "seq-macro"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d5b3bd665f328d73d7079123bfbd14a6edd74187667b5c6f340adfc65ea9d25a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.117"
|
version = "1.0.117"
|
||||||
|
|
@ -598,6 +604,7 @@ dependencies = [
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"ordered-float",
|
"ordered-float",
|
||||||
"rand",
|
"rand",
|
||||||
|
"seq-macro",
|
||||||
"serde",
|
"serde",
|
||||||
"tempfile",
|
"tempfile",
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ anyhow = "1.0.32"
|
||||||
askama = { version = "0.10.3", default-features = false }
|
askama = { version = "0.10.3", default-features = false }
|
||||||
bincode = "1.3.1"
|
bincode = "1.3.1"
|
||||||
clap = "3.0.0-beta.2"
|
clap = "3.0.0-beta.2"
|
||||||
dirs-next = "1.0.2"
|
dirs-next = "2.0.0"
|
||||||
dunce = "1.0.1"
|
dunce = "1.0.1"
|
||||||
glob = "0.3.0"
|
glob = "0.3.0"
|
||||||
once_cell = "1.4.1"
|
once_cell = "1.4.1"
|
||||||
|
|
@ -27,6 +27,7 @@ rand = "0.7.3"
|
||||||
|
|
||||||
[target.'cfg(unix)'.dev-dependencies]
|
[target.'cfg(unix)'.dev-dependencies]
|
||||||
assert_cmd = "1.0.1"
|
assert_cmd = "1.0.1"
|
||||||
|
seq-macro = "0.2.1"
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
codegen-units = 1
|
codegen-units = 1
|
||||||
|
|
|
||||||
371
src/shell.rs
371
src/shell.rs
|
|
@ -1,6 +1,6 @@
|
||||||
use clap::ArgEnum;
|
use clap::ArgEnum;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Eq, PartialEq)]
|
||||||
pub struct Opts<'a> {
|
pub struct Opts<'a> {
|
||||||
pub cmd: Option<&'a str>,
|
pub cmd: Option<&'a str>,
|
||||||
pub hook: Hook,
|
pub hook: Hook,
|
||||||
|
|
@ -34,7 +34,7 @@ make_template!(PowerShell, "powershell.txt");
|
||||||
make_template!(Xonsh, "xonsh.txt");
|
make_template!(Xonsh, "xonsh.txt");
|
||||||
make_template!(Zsh, "zsh.txt");
|
make_template!(Zsh, "zsh.txt");
|
||||||
|
|
||||||
#[derive(ArgEnum, Clone, Copy, Debug, PartialEq)]
|
#[derive(ArgEnum, Clone, Copy, Debug, Eq, PartialEq)]
|
||||||
pub enum Hook {
|
pub enum Hook {
|
||||||
None,
|
None,
|
||||||
Prompt,
|
Prompt,
|
||||||
|
|
@ -49,14 +49,21 @@ mod tests {
|
||||||
use askama::Template;
|
use askama::Template;
|
||||||
use assert_cmd::Command;
|
use assert_cmd::Command;
|
||||||
use once_cell::sync::OnceCell;
|
use once_cell::sync::OnceCell;
|
||||||
|
use seq_macro::seq;
|
||||||
|
|
||||||
|
macro_rules! with_opts_size {
|
||||||
|
($macro:ident) => {
|
||||||
|
$macro!(24);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
fn opts() -> &'static [Opts<'static>] {
|
fn opts() -> &'static [Opts<'static>] {
|
||||||
static OPTS: OnceCell<Vec<Opts>> = OnceCell::new();
|
static OPTS: OnceCell<Vec<Opts>> = OnceCell::new();
|
||||||
OPTS.get_or_init(|| {
|
const BOOLS: &[bool] = &[false, true];
|
||||||
const BOOLS: &[bool] = &[false, true];
|
const HOOKS: &[Hook] = &[Hook::None, Hook::Prompt, Hook::Pwd];
|
||||||
const HOOKS: &[Hook] = &[Hook::None, Hook::Prompt, Hook::Pwd];
|
const CMDS: &[Option<&str>] = &[None, Some("z")];
|
||||||
const CMDS: &[Option<&str>] = &[None, Some("z")];
|
|
||||||
|
|
||||||
|
OPTS.get_or_init(|| {
|
||||||
let mut opts = Vec::new();
|
let mut opts = Vec::new();
|
||||||
for &echo in BOOLS {
|
for &echo in BOOLS {
|
||||||
for &resolve_symlinks 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
|
opts
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
macro_rules! generate_tests {
|
||||||
fn test_bash() {
|
($N:literal) => {
|
||||||
for opts in opts() {
|
seq!(i in 0..$N {
|
||||||
let source = Bash(opts).render().unwrap();
|
#[test]
|
||||||
Command::new("bash")
|
fn bash_bash_#i() {
|
||||||
.args(&["-c", &source])
|
let opts = dbg!(&opts()[i]);
|
||||||
.assert()
|
let source = Bash(opts).render().unwrap();
|
||||||
.success()
|
Command::new("bash")
|
||||||
.stdout("")
|
.args(&["-c", &source])
|
||||||
.stderr("");
|
.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 <https://github.com/djc/askama/issues/377>
|
||||||
|
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 <https://github.com/djc/askama/issues/377>
|
||||||
|
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 <https://github.com/xonsh/xonsh/issues/3959>
|
||||||
|
#[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]
|
with_opts_size!(generate_tests);
|
||||||
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("");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -245,7 +245,7 @@ mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_add() {
|
fn add() {
|
||||||
let path = if cfg!(windows) {
|
let path = if cfg!(windows) {
|
||||||
r"C:\foo\bar"
|
r"C:\foo\bar"
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -270,7 +270,7 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_remove() {
|
fn remove() {
|
||||||
let path = if cfg!(windows) {
|
let path = if cfg!(windows) {
|
||||||
r"C:\foo\bar"
|
r"C:\foo\bar"
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -54,47 +54,47 @@ mod tests {
|
||||||
use super::Query;
|
use super::Query;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_query_normalization() {
|
fn query_normalization() {
|
||||||
assert!(Query::new(&["fOo", "bAr"]).matches("/foo/bar"));
|
assert!(Query::new(&["fOo", "bAr"]).matches("/foo/bar"));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_query_filename() {
|
fn query_filename() {
|
||||||
assert!(Query::new(&["ba"]).matches("/foo/bar"));
|
assert!(Query::new(&["ba"]).matches("/foo/bar"));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_query_not_filename() {
|
fn query_not_filename() {
|
||||||
assert!(!Query::new(&["fo"]).matches("/foo/bar"));
|
assert!(!Query::new(&["fo"]).matches("/foo/bar"));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_query_not_filename_slash() {
|
fn query_not_filename_slash() {
|
||||||
assert!(!Query::new(&["foo/"]).matches("/foo/bar"));
|
assert!(!Query::new(&["foo/"]).matches("/foo/bar"));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_query_path_separator() {
|
fn query_path_separator() {
|
||||||
assert!(Query::new(&["/", "fo", "/", "ar"]).matches("/foo/bar"));
|
assert!(Query::new(&["/", "fo", "/", "ar"]).matches("/foo/bar"));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_query_path_separator_between() {
|
fn query_path_separator_between() {
|
||||||
assert!(Query::new(&["oo/ba"]).matches("/foo/bar"));
|
assert!(Query::new(&["oo/ba"]).matches("/foo/bar"));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_query_overlap_text() {
|
fn query_overlap_text() {
|
||||||
assert!(!Query::new(&["foo", "o", "bar"]).matches("/foo/bar"));
|
assert!(!Query::new(&["foo", "o", "bar"]).matches("/foo/bar"));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_query_overlap_slash() {
|
fn query_overlap_slash() {
|
||||||
assert!(!Query::new(&["/foo/", "/bar"]).matches("/foo/bar"));
|
assert!(!Query::new(&["/foo/", "/bar"]).matches("/foo/bar"));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_query_consecutive_slash() {
|
fn query_consecutive_slash() {
|
||||||
assert!(Query::new(&["/foo/", "/baz"]).matches("/foo/bar/baz"));
|
assert!(Query::new(&["/foo/", "/baz"]).matches("/foo/bar/baz"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -74,7 +74,7 @@ function __zoxide_z() {
|
||||||
echo "zoxide: \\$OLDPWD is not set"
|
echo "zoxide: \\$OLDPWD is not set"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
elif [ "$#" -eq 1 ] && [ -d "$1" ]; then
|
elif [ "$#" -eq 1 ] && [ -d "$1" ]; then
|
||||||
__zoxide_cd "$1"
|
__zoxide_cd "$1"
|
||||||
else
|
else
|
||||||
local __zoxide_result
|
local __zoxide_result
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,12 @@
|
||||||
{%- let SECTION = "# =============================================================================\n#" -%}
|
{%- let SECTION = "# =============================================================================\n#" -%}
|
||||||
{%- let NOT_CONFIGURED = "# -- not configured --" -%}
|
{%- let NOT_CONFIGURED = "# -- not configured --" -%}
|
||||||
|
|
||||||
{% if hook == Hook::Pwd -%}
|
{%- if hook == Hook::Pwd -%}
|
||||||
echo "\
|
echo "\
|
||||||
zoxide: PWD hooks are not supported on POSIX shells.
|
zoxide: PWD hooks are not supported on POSIX shells.
|
||||||
Use '--hook prompt' when initializing zoxide."
|
Use '--hook prompt' when initializing zoxide."
|
||||||
{%- endif %}
|
|
||||||
|
{% endif -%}
|
||||||
|
|
||||||
{{ SECTION }}
|
{{ SECTION }}
|
||||||
# Utility functions for zoxide.
|
# Utility functions for zoxide.
|
||||||
|
|
@ -77,7 +78,7 @@ __zoxide_z() {
|
||||||
echo "zoxide: \\$OLDPWD is not set"
|
echo "zoxide: \\$OLDPWD is not set"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
elif [ "$#" -eq 1 ] && [ -d "$1" ]; then
|
elif [ "$#" -eq 1 ] && [ -d "$1" ]; then
|
||||||
__zoxide_cd "$1"
|
__zoxide_cd "$1"
|
||||||
else
|
else
|
||||||
__zoxide_result="$(zoxide query -- "$@")" && __zoxide_cd "$__zoxide_result"
|
__zoxide_result="$(zoxide query -- "$@")" && __zoxide_cd "$__zoxide_result"
|
||||||
|
|
|
||||||
|
|
@ -1,30 +1,75 @@
|
||||||
{%- let SECTION = "# =============================================================================\n#" -%}
|
{%- let SECTION = "# =============================================================================\n#" -%}
|
||||||
{%- let NOT_CONFIGURED = "# -- not configured --" -%}
|
{%- let NOT_CONFIGURED = "# -- not configured --" -%}
|
||||||
|
|
||||||
{%- if resolve_symlinks -%}
|
"""Initialize zoxide on Xonsh."""
|
||||||
|
|
||||||
import os
|
import os
|
||||||
{%- endif %}
|
|
||||||
import os.path
|
import os.path
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
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 subprocess import CalledProcessError
|
||||||
|
from typing import AnyStr, List, Optional
|
||||||
|
|
||||||
|
import xonsh.dirstack # type: ignore
|
||||||
|
|
||||||
{{ SECTION }}
|
{{ SECTION }}
|
||||||
# Utility functions for zoxide.
|
# Utility functions for zoxide.
|
||||||
#
|
#
|
||||||
|
|
||||||
# pwd based on the value of _ZO_RESOLVE_SYMLINKS.
|
|
||||||
def __zoxide_pwd() -> str:
|
def __zoxide_pwd() -> str:
|
||||||
|
"""pwd based on the value of _ZO_RESOLVE_SYMLINKS."""
|
||||||
{%- if resolve_symlinks %}
|
{%- if resolve_symlinks %}
|
||||||
return os.getcwd()
|
pwd = os.getcwd()
|
||||||
{%- else %}
|
{%- 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 %}
|
{%- endif %}
|
||||||
|
|
||||||
# cd + custom logic based on the value of _ZO_ECHO.
|
|
||||||
def __zoxide_cd(path: str):
|
class ZoxideSilentException(Exception):
|
||||||
cd @(path) {%- if echo %} and print(__zoxide_pwd()) {%- endif %}
|
"""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 }}
|
{{ SECTION }}
|
||||||
# Hook configuration for zoxide.
|
# Hook configuration for zoxide.
|
||||||
|
|
@ -36,77 +81,97 @@ def __zoxide_cd(path: str):
|
||||||
{{ NOT_CONFIGURED }}
|
{{ NOT_CONFIGURED }}
|
||||||
|
|
||||||
{%- when Hook::Prompt %}
|
{%- when Hook::Prompt %}
|
||||||
@events.on_post_prompt
|
@events.on_post_prompt # type: ignore # pylint:disable=undefined-variable
|
||||||
|
|
||||||
{%- when Hook::Pwd %}
|
{%- when Hook::Pwd %}
|
||||||
@events.on_chdir
|
@events.on_chdir # type: ignore # pylint:disable=undefined-variable
|
||||||
|
|
||||||
{%- endmatch %}
|
{%- endmatch %}
|
||||||
def __zoxide_hook(**kwargs):
|
def __zoxide_hook(**_kwargs):
|
||||||
zoxide add @(__zoxide_pwd())
|
"""Hook to add new entries to the database."""
|
||||||
|
pwd = __zoxide_pwd()
|
||||||
|
subprocess.run(["zoxide", "add", pwd], check=False)
|
||||||
|
|
||||||
|
|
||||||
{{ SECTION }}
|
{{ SECTION }}
|
||||||
# When using zoxide with --no-aliases, alias these internal functions as
|
# When using zoxide with --no-aliases, alias these internal functions as
|
||||||
# desired.
|
# desired.
|
||||||
#
|
#
|
||||||
|
|
||||||
# Jump to a directory using only keywords.
|
|
||||||
def __zoxide_z(keywords: [str]):
|
@__zoxide_errhandler
|
||||||
if keywords == []:
|
def __zoxide_z(args: List[str]):
|
||||||
__zoxide_cd($HOME)
|
"""Jump to a directory using only keywords."""
|
||||||
elif keywords == ['-']:
|
if args == []:
|
||||||
__zoxide_cd('-')
|
__zoxide_cd()
|
||||||
elif len(keywords) == 1 and os.path.isdir(keywords[0]):
|
elif args == ["-"]:
|
||||||
__zoxide_cd(keywords[0])
|
__zoxide_cd("-")
|
||||||
|
elif len(args) == 1 and os.path.isdir(args[0]):
|
||||||
|
__zoxide_cd(args[0])
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
__zoxide_cmd = subprocess.run(["zoxide", "query", "--"] + keywords, check=True, stdout=subprocess.PIPE)
|
__zoxide_cmd = subprocess.run(
|
||||||
except CalledProcessError as e:
|
["zoxide", "query", "--"] + args, check=True, stdout=subprocess.PIPE
|
||||||
return e.returncode
|
)
|
||||||
|
except CalledProcessError as exc:
|
||||||
try:
|
raise ZoxideSilentException() from exc
|
||||||
__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_result = __zoxide_cmd.stdout[:-1]
|
||||||
__zoxide_cd(__zoxide_result)
|
__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:
|
try:
|
||||||
__zoxide_result = __zoxide_cmd.stdout[:-1].decode("utf-8")
|
__zoxide_cmd = subprocess.run(
|
||||||
except UnicodeDecodeError:
|
["zoxide", "query", "-i", "--"] + args, check=True, stdout=subprocess.PIPE
|
||||||
print(f"zoxide: invalid unicode in result: {__zoxide_result}", file=sys.stderr)
|
)
|
||||||
return 1
|
except CalledProcessError as exc:
|
||||||
|
raise ZoxideSilentException() from exc
|
||||||
|
|
||||||
|
__zoxide_result = __zoxide_cmd.stdout[:-1]
|
||||||
__zoxide_cd(__zoxide_result)
|
__zoxide_cd(__zoxide_result)
|
||||||
|
|
||||||
|
|
||||||
# Add a new entry to the database.
|
def __zoxide_za(args: List[str]):
|
||||||
def __zoxide_za(args: [str]):
|
"""Add a new entry to the database."""
|
||||||
zoxide add @(args)
|
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_zq(args: List[str]):
|
||||||
def __zoxide_zqi(args: [str]):
|
"""Query an entry from the database using only keywords."""
|
||||||
zoxide query -i @(args)
|
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_zqi(args: List[str]):
|
||||||
def __zoxide_zri(args: [str]):
|
"""Query an entry from the database using interactive selection."""
|
||||||
zoxide remove -i @(args)
|
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 }}
|
{{ SECTION }}
|
||||||
# Convenient aliases for zoxide. Disable these using --no-aliases.
|
# Convenient aliases for zoxide. Disable these using --no-aliases.
|
||||||
|
|
@ -115,13 +180,13 @@ def __zoxide_zri(args: [str]):
|
||||||
{%- match cmd %}
|
{%- match cmd %}
|
||||||
{%- when Some with (cmd) %}
|
{%- when Some with (cmd) %}
|
||||||
|
|
||||||
aliases['{{cmd}}'] = __zoxide_z
|
aliases["{{cmd}}"] = __zoxide_z
|
||||||
aliases['{{cmd}}i'] = __zoxide_zi
|
aliases["{{cmd}}i"] = __zoxide_zi
|
||||||
aliases['{{cmd}}a'] = __zoxide_za
|
aliases["{{cmd}}a"] = __zoxide_za
|
||||||
aliases['{{cmd}}q'] = __zoxide_zq
|
aliases["{{cmd}}q"] = __zoxide_zq
|
||||||
aliases['{{cmd}}qi'] = __zoxide_zqi
|
aliases["{{cmd}}qi"] = __zoxide_zqi
|
||||||
aliases['{{cmd}}r'] = __zoxide_zr
|
aliases["{{cmd}}r"] = __zoxide_zr
|
||||||
aliases['{{cmd}}ri'] = __zoxide_zri
|
aliases["{{cmd}}ri"] = __zoxide_zri
|
||||||
|
|
||||||
{%- when None %}
|
{%- when None %}
|
||||||
{{ NOT_CONFIGURED }}
|
{{ NOT_CONFIGURED }}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue