use miette::Result;
use winnow::{Parser, combinator::alt};
pub(crate) use debug::DebugWhat;
pub use list::ListItem;
pub(crate) use result::{ResultFormat, ResultSubcommand};
mod copy;
mod debug;
mod describe;
mod edit;
mod expanded;
mod help;
mod include;
mod list;
mod output;
mod quit;
mod redaction;
mod result;
mod snippets;
mod vars;
mod write_mode;
#[derive(Debug, Clone, PartialEq, Eq)]
pub(crate) enum Metacommand {
Quit,
Expanded,
WriteMode {
ots: Option<String>,
},
ToggleRedaction,
Edit,
Copy,
Include {
file_path: String,
vars: Vec<(String, String)>,
},
Output {
file_path: Option<String>,
},
Debug {
what: debug::DebugWhat,
},
Help,
SetVar {
name: String,
value: String,
},
DefaultVar {
name: String,
value: String,
},
UnsetVar {
name: String,
},
LookupVar {
pattern: Option<String>,
},
GetVar {
name: String,
},
SnippetRun {
name: String,
vars: Vec<(String, String)>,
},
SnippetSave {
name: String,
},
SnippetEdit {
name: String,
},
SnippetList,
SnippetRefetch,
List {
item: list::ListItem,
pattern: String,
detail: bool,
sameconn: bool,
},
Describe {
item: String,
detail: bool,
sameconn: bool,
},
Result {
subcommand: result::ResultSubcommand,
},
}
pub(crate) fn parse_metacommand(input: &str) -> Result<Option<Metacommand>> {
let input = input.trim();
if !input.starts_with('\\') {
return Ok(None);
}
let mut input_slice = input;
if let Ok(cmd) = alt((
alt((
quit::parse,
expanded::parse,
write_mode::parse,
redaction::parse,
edit::parse,
copy::parse,
include::parse,
output::parse,
debug::parse,
)),
alt((
help::parse,
snippets::parse,
vars::parse_set,
vars::parse_default,
vars::parse_unset,
vars::parse_lookup,
vars::parse_get,
list::parse,
describe::parse,
)),
result::parse,
))
.parse_next(&mut input_slice)
{
Ok(Some(cmd))
} else {
Ok(None)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_parse_metacommand_not_metacommand() {
let result = parse_metacommand("SELECT * FROM users").unwrap();
assert_eq!(result, None);
}
#[test]
fn test_parse_metacommand_invalid_mushed() {
let result = parse_metacommand(r"\qx").unwrap();
assert_eq!(result, None);
}
#[test]
fn test_parse_metacommand_with_trailing_text() {
let result = parse_metacommand(r"\q extra").unwrap();
assert_eq!(result, None);
}
#[test]
fn test_parse_metacommand_query_modifier() {
let result = parse_metacommand(r"\gx").unwrap();
assert_eq!(result, None);
}
#[test]
fn test_parse_metacommand_unknown() {
let result = parse_metacommand(r"\z").unwrap();
assert_eq!(result, None);
}
#[test]
fn test_parse_metacommand_empty_backslash() {
let result = parse_metacommand(r"\").unwrap();
assert_eq!(result, None);
}
#[test]
fn test_parse_metacommand_mixed_case() {
let result = parse_metacommand(r"\qX").unwrap();
assert_eq!(result, None);
}
#[test]
fn test_parse_metacommand_no_backslash() {
let result = parse_metacommand("q").unwrap();
assert_eq!(result, None);
}
#[test]
fn test_parse_metacommand_empty_string() {
let result = parse_metacommand("").unwrap();
assert_eq!(result, None);
}
}