2020-10-26 17:55:04 +00:00
|
|
|
use clap::ArgEnum;
|
|
|
|
|
2020-11-10 19:11:26 +00:00
|
|
|
#[derive(Debug, Eq, PartialEq)]
|
2020-10-26 17:55:04 +00:00
|
|
|
pub struct Opts<'a> {
|
|
|
|
pub cmd: Option<&'a str>,
|
|
|
|
pub hook: Hook,
|
|
|
|
pub echo: bool,
|
|
|
|
pub resolve_symlinks: bool,
|
|
|
|
}
|
|
|
|
|
|
|
|
macro_rules! make_template {
|
|
|
|
($name:ident, $path:expr) => {
|
|
|
|
#[derive(::std::fmt::Debug, ::askama::Template)]
|
|
|
|
#[template(path = $path)]
|
|
|
|
pub struct $name<'a>(pub &'a self::Opts<'a>);
|
|
|
|
|
|
|
|
impl<'a> ::std::ops::Deref for $name<'a> {
|
|
|
|
type Target = self::Opts<'a>;
|
|
|
|
fn deref(&self) -> &Self::Target {
|
|
|
|
self.0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
make_template!(Bash, "bash.txt");
|
|
|
|
make_template!(Fish, "fish.txt");
|
|
|
|
make_template!(Posix, "posix.txt");
|
|
|
|
make_template!(PowerShell, "powershell.txt");
|
|
|
|
make_template!(Xonsh, "xonsh.txt");
|
|
|
|
make_template!(Zsh, "zsh.txt");
|
|
|
|
|
2020-11-10 19:11:26 +00:00
|
|
|
#[derive(ArgEnum, Clone, Copy, Debug, Eq, PartialEq)]
|
2020-10-26 17:55:04 +00:00
|
|
|
pub enum Hook {
|
|
|
|
None,
|
|
|
|
Prompt,
|
|
|
|
Pwd,
|
|
|
|
}
|
|
|
|
|
2021-03-29 15:44:30 +00:00
|
|
|
#[cfg(feature = "shell_tests")]
|
2020-10-26 17:55:04 +00:00
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
use askama::Template;
|
|
|
|
use assert_cmd::Command;
|
|
|
|
use once_cell::sync::OnceCell;
|
2020-11-10 19:11:26 +00:00
|
|
|
use seq_macro::seq;
|
|
|
|
|
|
|
|
macro_rules! with_opts_size {
|
|
|
|
($macro:ident) => {
|
|
|
|
$macro!(24);
|
|
|
|
};
|
|
|
|
}
|
2020-10-26 17:55:04 +00:00
|
|
|
|
|
|
|
fn opts() -> &'static [Opts<'static>] {
|
|
|
|
static OPTS: OnceCell<Vec<Opts>> = OnceCell::new();
|
2020-11-10 19:11:26 +00:00
|
|
|
const BOOLS: &[bool] = &[false, true];
|
|
|
|
const HOOKS: &[Hook] = &[Hook::None, Hook::Prompt, Hook::Pwd];
|
|
|
|
const CMDS: &[Option<&str>] = &[None, Some("z")];
|
2020-10-26 17:55:04 +00:00
|
|
|
|
2020-11-10 19:11:26 +00:00
|
|
|
OPTS.get_or_init(|| {
|
2020-10-26 17:55:04 +00:00
|
|
|
let mut opts = Vec::new();
|
|
|
|
for &echo in BOOLS {
|
|
|
|
for &resolve_symlinks in BOOLS {
|
|
|
|
for &hook in HOOKS {
|
|
|
|
for &cmd in CMDS {
|
|
|
|
let opt = Opts {
|
2021-03-01 06:10:10 +00:00
|
|
|
cmd,
|
|
|
|
hook,
|
2020-10-26 17:55:04 +00:00
|
|
|
echo,
|
|
|
|
resolve_symlinks,
|
|
|
|
};
|
|
|
|
opts.push(opt);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-10 19:11:26 +00:00
|
|
|
// 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));
|
|
|
|
|
2020-10-26 17:55:04 +00:00
|
|
|
opts
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2020-11-10 19:11:26 +00:00
|
|
|
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")
|
2020-12-09 22:07:40 +00:00
|
|
|
.args(&["-c", &source, "--noediting", "--noprofile", "--norc"])
|
2020-11-10 19:11:26 +00:00
|
|
|
.assert()
|
|
|
|
.success()
|
|
|
|
.stdout("")
|
|
|
|
.stderr("");
|
|
|
|
}
|
2020-10-26 17:55:04 +00:00
|
|
|
|
2020-11-10 19:11:26 +00:00
|
|
|
#[test]
|
|
|
|
fn bash_shellcheck_#i() {
|
|
|
|
let opts = dbg!(&opts()[i]);
|
|
|
|
let source = Bash(opts).render().unwrap();
|
|
|
|
Command::new("shellcheck")
|
2020-11-11 12:53:37 +00:00
|
|
|
.args(&["--enable", "all", "--shell", "bash", "-"])
|
2020-11-10 19:11:26 +00:00
|
|
|
.write_stdin(source)
|
|
|
|
.assert()
|
|
|
|
.success()
|
|
|
|
.stdout("")
|
|
|
|
.stderr("");
|
|
|
|
}
|
2020-10-26 17:55:04 +00:00
|
|
|
|
2020-11-10 19:11:26 +00:00
|
|
|
#[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("");
|
|
|
|
}
|
2020-10-26 17:55:04 +00:00
|
|
|
|
2020-11-10 19:11:26 +00:00
|
|
|
#[test]
|
|
|
|
fn fish_fish_#i() {
|
|
|
|
let opts = dbg!(&opts()[i]);
|
|
|
|
let source = Fish(opts).render().unwrap();
|
2020-12-13 05:26:51 +00:00
|
|
|
|
|
|
|
let tempdir = tempfile::tempdir().unwrap();
|
|
|
|
let tempdir = tempdir.path().to_str().unwrap();
|
|
|
|
|
2020-11-10 19:11:26 +00:00
|
|
|
Command::new("fish")
|
2020-12-13 05:26:51 +00:00
|
|
|
.env("HOME", tempdir) // fish needs a writeable $HOME directory
|
2020-12-09 22:07:40 +00:00
|
|
|
.args(&["--command", &source, "--private"])
|
2020-11-10 19:11:26 +00:00
|
|
|
.assert()
|
|
|
|
.success()
|
|
|
|
.stdout("")
|
|
|
|
.stderr("");
|
|
|
|
}
|
2020-10-26 17:55:04 +00:00
|
|
|
|
2020-11-10 19:11:26 +00:00
|
|
|
// TODO: fishindent
|
2020-10-26 17:55:04 +00:00
|
|
|
|
2020-11-10 19:11:26 +00:00
|
|
|
#[test]
|
|
|
|
fn posix_bashposix_#i() {
|
|
|
|
let opts = dbg!(&opts()[i]);
|
|
|
|
let source = Posix(opts).render().unwrap();
|
|
|
|
let assert = Command::new("bash")
|
2020-12-09 22:07:40 +00:00
|
|
|
.args(&["--posix", "-c", &source, "--noediting", "--noprofile", "--norc"])
|
2020-11-10 19:11:26 +00:00
|
|
|
.assert()
|
|
|
|
.success()
|
|
|
|
.stderr("");
|
2020-10-26 17:55:04 +00:00
|
|
|
|
2020-11-10 19:11:26 +00:00
|
|
|
if opts.hook != Hook::Pwd {
|
|
|
|
assert.stdout("");
|
|
|
|
}
|
|
|
|
}
|
2020-10-26 17:55:04 +00:00
|
|
|
|
2020-11-10 19:11:26 +00:00
|
|
|
#[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("");
|
2020-10-26 17:55:04 +00:00
|
|
|
|
2020-11-10 19:11:26 +00:00
|
|
|
if opts.hook != Hook::Pwd {
|
|
|
|
assert.stdout("");
|
|
|
|
}
|
|
|
|
}
|
2020-10-26 17:55:04 +00:00
|
|
|
|
2020-11-10 19:11:26 +00:00
|
|
|
#[test]
|
|
|
|
fn posix_shellcheck_#i() {
|
|
|
|
let opts = dbg!(&opts()[i]);
|
|
|
|
let source = Posix(opts).render().unwrap();
|
|
|
|
Command::new("shellcheck")
|
2020-11-11 12:53:37 +00:00
|
|
|
.args(&["--enable", "all", "--shell", "sh", "-"])
|
2020-11-10 19:11:26 +00:00
|
|
|
.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("");
|
|
|
|
}
|
2020-10-26 17:55:04 +00:00
|
|
|
|
2020-11-10 19:11:26 +00:00
|
|
|
#[test]
|
|
|
|
fn powershell_pwsh_#i() {
|
|
|
|
let opts = dbg!(&opts()[i]);
|
|
|
|
let source = PowerShell(opts).render().unwrap();
|
|
|
|
Command::new("pwsh")
|
2020-12-09 22:07:40 +00:00
|
|
|
.args(&["-Command", &source, "-NoLogo", "-NonInteractive", "-NoProfile"])
|
2020-11-10 19:11:26 +00:00
|
|
|
.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")
|
2020-12-09 22:07:40 +00:00
|
|
|
.args(&["-c", &source, "--no-rc"])
|
2020-11-10 19:11:26 +00:00
|
|
|
.assert()
|
|
|
|
.success()
|
|
|
|
.stdout("")
|
|
|
|
.stderr("");
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn zsh_zsh_#i() {
|
|
|
|
let opts = dbg!(&opts()[i]);
|
|
|
|
let source = Zsh(opts).render().unwrap();
|
|
|
|
Command::new("zsh")
|
2020-12-09 22:07:40 +00:00
|
|
|
.args(&["-c", &source, "--no-rcs"])
|
2020-11-10 19:11:26 +00:00
|
|
|
.assert()
|
|
|
|
.success()
|
|
|
|
.stdout("")
|
|
|
|
.stderr("");
|
|
|
|
}
|
|
|
|
});
|
2020-10-26 17:55:04 +00:00
|
|
|
}
|
|
|
|
}
|
2020-11-10 19:11:26 +00:00
|
|
|
|
|
|
|
with_opts_size!(generate_tests);
|
2020-10-26 17:55:04 +00:00
|
|
|
}
|