use crate::compsys::ported::_arguments::_arguments;
use crate::ported::zle::compcore::{get_compstate_str, set_compstate_str};
const XARGS: [&str; 22] = [
"-+rv",
"-+synchronous",
"-reverse",
"-iconic",
"-background:background color:_x_color",
"-bd:border color:_x_color",
"-bg:background color:_x_color",
"-bordercolor:border color:_x_color",
"-borderwidth:border width:_x_borderwidth",
"-bw:border width:_x_borderwidth",
"-display:display:_x_display",
"-fg:foreground color:_x_color",
"-font:font:_x_font",
"-fn:font:_x_font",
"-foreground:foreground color:_x_color",
"-geometry:geometry:_x_geometry",
"-name:name:_x_name",
"-selectionTimeout:selection timeout (milliseconds):_x_selection_timeout",
"-title:title:_x_title",
"-xnllanguage:locale:_x_locale",
"*-xrm:resource:_x_resource",
"-xtsessionID:session ID:_xt_session_id",
];
fn splice_xargs(argv: &[String], xargs: &[String]) -> Vec<String> {
match argv.iter().rposition(|a| a == "--") {
Some(idx) => {
let mut out = Vec::with_capacity(argv.len() + xargs.len());
out.extend_from_slice(&argv[..idx]);
out.extend_from_slice(xargs);
out.push("--".to_string());
out.extend_from_slice(&argv[idx + 1..]);
out
}
None => {
let mut out = argv.to_vec();
out.extend_from_slice(xargs);
out
}
}
}
fn matches_leading_opt(w: &str) -> bool {
let b = w.as_bytes();
if b.len() < 2 || b[0] != b'-' {
return false;
}
match b[1] {
b'O' => true,
b'C' | b'R' | b'W' | b's' | b'w' => b.len() == 2,
_ => false,
}
}
fn parse_leading(argv: &[String]) -> (Vec<String>, Vec<String>, bool) {
let mut opts: Vec<String> = Vec::new();
let mut rawret = false;
let mut p = 0usize;
while p < argv.len() {
let w = &argv[p];
if !matches_leading_opt(w) {
break;
}
opts.push(w.clone()); if w == "-R" {
rawret = true; }
p += 1; }
(opts, argv[p..].to_vec(), rawret)
}
fn nmatches() -> i64 {
get_compstate_str("nmatches")
.and_then(|s| s.trim().parse::<i64>().ok())
.unwrap_or(0)
}
pub fn _xt_arguments(args: &[String]) -> i32 {
let nm = nmatches();
let xargs: Vec<String> = XARGS.iter().map(|s| s.to_string()).collect();
let argv = splice_xargs(args, &xargs);
let (opts, remaining, rawret) = parse_leading(&argv);
let mut call: Vec<String> = Vec::with_capacity(1 + opts.len() + remaining.len());
call.push("-R".to_string());
call.extend(opts);
call.extend(remaining);
let mut ret = _arguments(&call);
if ret == 300 {
set_compstate_str("restore", ""); if !rawret {
ret = if nm == nmatches() { 1 } else { 0 };
}
}
ret }
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn leading_opt_guard_matches_spec() {
for ok in ["-C", "-R", "-W", "-s", "-w", "-O", "-Oxx"] {
assert!(matches_leading_opt(ok), "{ok} should match");
}
for no in [
"-F", "-Fgrp", "-Wx", "-Cx", "-d", "-r", "--", "-", "", "-xrm", "spec",
] {
assert!(!matches_leading_opt(no), "{no} should not match");
}
}
#[test]
fn splice_inserts_before_last_dashdash_else_appends() {
let xargs = vec!["A".to_string(), "B".to_string()];
let out = splice_xargs(&["x".to_string(), "y".to_string()], &xargs);
assert_eq!(out, vec!["x", "y", "A", "B"]);
let argv = vec![
"-C".to_string(),
"--".to_string(),
"tail".to_string(),
"--".to_string(),
"z".to_string(),
];
let out = splice_xargs(&argv, &xargs);
assert_eq!(out, vec!["-C", "--", "tail", "A", "B", "--", "z"]);
}
#[test]
fn parse_leading_collects_opts_and_rawret() {
let (opts, remaining, rawret) = parse_leading(&[
"-C".to_string(),
"-R".to_string(),
"-xrm:resource:_x_resource".to_string(),
]);
assert_eq!(opts, vec!["-C", "-R"]);
assert!(rawret);
assert_eq!(remaining, vec!["-xrm:resource:_x_resource".to_string()]);
}
#[test]
fn parse_leading_no_rawret_without_dash_r() {
let (opts, remaining, rawret) =
parse_leading(&["-Ostuff".to_string(), "spec".to_string()]);
assert_eq!(opts, vec!["-Ostuff"]);
assert!(!rawret);
assert_eq!(remaining, vec!["spec".to_string()]);
}
#[test]
fn xargs_contains_flattened_brace_words() {
let x: Vec<String> = XARGS.iter().map(|s| s.to_string()).collect();
for w in ["-+rv", "-+synchronous", "-reverse", "-iconic"] {
assert!(x.contains(&w.to_string()), "{w} missing from XARGS");
}
assert!(x.contains(&"*-xrm:resource:_x_resource".to_string()));
}
}