use std::collections::HashSet;
#[must_use]
pub fn implemented_features() -> HashSet<&'static str> {
let mut f = HashSet::new();
f.insert("simple-command");
f.insert("pipeline");
f.insert("and-or-list");
f.insert("semicolon-list");
f.insert("pipeline-negation");
f.insert("variable-assignment");
f.insert("redirection");
f.insert("here-doc");
f.insert("here-doc-expansion");
f.insert("single-quoting");
f.insert("double-quoting");
f.insert("backslash-escape");
f.insert("parameter-expansion");
f.insert("parameter-default");
f.insert("parameter-assign-default");
f.insert("parameter-alternative");
f.insert("parameter-error");
f.insert("parameter-length");
f.insert("arithmetic-expansion");
f.insert("nested-expansion");
f.insert("comment");
f.insert("if");
f.insert("while");
f.insert("until");
f.insert("for-in");
f.insert("case");
f.insert("subshell");
f.insert("brace-group");
f.insert("function");
f.insert("echo");
f.insert("printf");
f.insert("pwd");
f.insert("cd");
f.insert("export");
f.insert("unset");
f.insert("readonly");
f.insert("test");
f.insert("read");
f.insert("true");
f.insert("false");
f.insert("colon");
f.insert("cat");
f.insert("ls");
f.insert("mkdir");
f.insert("rm");
f.insert("touch");
f.insert("head");
f.insert("tail");
f.insert("wc");
f.insert("grep");
f.insert("sed");
f.insert("sort");
f.insert("uniq");
f.insert("cut");
f.insert("tr");
f.insert("tee");
f.insert("seq");
f.insert("basename");
f.insert("dirname");
f.insert("mv");
f.insert("cp");
f.insert("env");
f.insert("printenv");
f.insert("id");
f.insert("whoami");
f.insert("uname");
f.insert("hostname");
f.insert("sleep");
f.insert("expr");
f.insert("xargs");
f.insert("glob-expansion");
f.insert("brace-expansion");
f.insert("here-string");
f.insert("ansi-c-quoting");
f.insert("stderr-redirection");
f.insert("fd-redirection");
f.insert("tilde-expansion");
f.insert("command-substitution");
f.insert("parameter-substitution");
f.insert("parameter-substring");
f.insert("break");
f.insert("continue");
f.insert("exit");
f.insert("return");
f.insert("local");
f.insert("shift");
f.insert("set");
f.insert("type");
f.insert("command-builtin");
f.insert("times");
f.insert("dirs");
f.insert("pushd");
f.insert("popd");
f.insert("umask");
f.insert("wait");
f.insert("ulimit");
f.insert("exec-builtin");
f.insert("eval");
f.insert("source");
f.insert("getopts");
f.insert("trap");
f.insert("ln");
f.insert("readlink");
f.insert("realpath");
f.insert("stat");
f.insert("find");
f.insert("chmod");
f.insert("date");
f.insert("echo-escape");
f.insert("printf-repeat");
f.insert("errexit");
f.insert("trap-exit");
f.insert("trap-err");
f.insert("trap-debug");
f.insert("trap-return");
f.insert("parameter-strip");
f.insert("double-bracket");
f.insert("bash-rematch");
f.insert("c-style-for");
f.insert("arith-command");
f.insert("pipe-ampersand");
f.insert("case-fallthrough");
f.insert("case-continue-testing");
f.insert("select");
f.insert("locale-quoting");
f.insert("dynamic-fd");
f.insert("move-fd");
f.insert("time-keyword");
f.insert("indexed-array");
f.insert("associative-array");
f.insert("random-variable");
f.insert("lineno-variable");
f.insert("seconds-variable");
f.insert("pipestatus");
f.insert("funcname-variable");
f.insert("bash-source-variable");
f.insert("nameref");
f.insert("case-modification");
f.insert("anchored-substitution");
f.insert("substitution-glob");
f.insert("indirect-expansion");
f.insert("prefix-expansion");
f.insert("transformation-operators");
f.insert("arithmetic-comparison");
f.insert("arithmetic-parentheses");
f.insert("arithmetic-assignment");
f.insert("arithmetic-bases");
f.insert("declare");
f.insert("alias");
f.insert("let");
f.insert("printf-format");
f.insert("read-flags");
f.insert("shopt");
f.insert("mapfile");
f.insert("builtin-keyword");
f.insert("source-path");
f.insert("pipefail");
f.insert("nounset");
f.insert("xtrace");
f.insert("noglob");
f.insert("allexport");
f.insert("extglob");
f.insert("globstar");
f.insert("mktemp");
f.insert("yes");
f.insert("paste");
f.insert("md5sum");
f.insert("sha256sum");
f.insert("base64");
f.insert("rev");
f.insert("column");
f.insert("awk");
f.insert("jq");
f.insert("diff");
f.insert("patch");
f.insert("rg");
f.insert("tree");
f.insert("xxd");
f.insert("dd");
f.insert("strings");
f.insert("split");
f.insert("bc");
f.insert("tar");
f.insert("gzip");
f.insert("gunzip");
f.insert("du");
f.insert("fd");
f.insert("file");
f.insert("comm");
f.insert("yq");
f
}
pub fn missing_features(requires: &[String]) -> Vec<String> {
let implemented = implemented_features();
requires
.iter()
.filter(|r| !implemented.contains(r.as_str()))
.cloned()
.collect()
}