1#![doc = include_str!("../readme.md")]
2
3pub mod base;
5
6pub mod help;
8
9pub mod traits;
11
12pub mod traits_impls;
14
15pub use aargvark_proc_macros::Aargvark;
16use {
17 base::{
18 Error,
19 R,
20 VarkFailure,
21 VarkState,
22 },
23 help::VarkRetHelp,
24 traits::AargvarkTrait,
25};
26
27#[derive(PartialEq, Eq)]
28pub enum CompleteCursorPosition {
29 Empty,
31 Partial,
33}
34
35pub fn vark<T: AargvarkTrait>() -> T {
39 let mut args = std::env::args();
40 let command = args.next();
41 let mut args = args.collect::<Vec<String>>();
42 if let Some(complete) = std::env::var_os("AARGVARK_COMPLETE") {
43 let cursor = match complete.as_encoded_bytes() {
44 b"empty" => CompleteCursorPosition::Empty,
45 b"partial" => CompleteCursorPosition::Partial,
46 _ => {
47 eprintln!("Invalid value for AARGVARK_COMPLETE");
48 std::process::exit(1);
49 },
50 };
51
52 args.remove(0);
54 let res = vark_complete::<T>(cursor, command, args);
55 println!(
56 "{}",
57 res
58 .into_iter()
59 .map(
60 |args| args
61 .iter()
62 .map(|a| shell_escape::escape(std::borrow::Cow::Borrowed(&a)))
63 .collect::<Vec<_>>()
64 .join(" "),
65 )
66 .collect::<Vec<_>>()
67 .join("\n")
68 );
69 std::process::exit(0);
70 } else {
71 match vark_explicit::<T>(command, args) {
72 Ok(v) => match v {
73 VarkRet::Ok(v) => return v,
74 VarkRet::Help(h) => {
75 println!("{}", h.render());
76 std::process::exit(0);
77 },
78 },
79 Err(e) => {
80 eprintln!("{:?}", e);
81 std::process::exit(1);
82 },
83 }
84 }
85}
86
87pub fn vark_complete<
93 T: AargvarkTrait,
94>(cursor: CompleteCursorPosition, command: Option<String>, args: Vec<String>) -> Vec<Vec<String>> {
95 let mut args = args;
96 if args.is_empty() || cursor == CompleteCursorPosition::Empty {
97 args.push("".to_string());
98 }
99 let mut state = VarkState::new(true, command, args);
100 T::vark(&mut state);
101 return (state.last_completer.take().unwrap())();
102}
103
104pub fn vark_explicit<T: AargvarkTrait>(command: Option<String>, args: Vec<String>) -> Result<VarkRet<T>, Error> {
108 let mut state = VarkState::new(false, command, args);
109 match T::vark(&mut state) {
110 R::Err => {
111 return Err(Error {
112 command: state.command,
113 args: state.args,
114 detail: state.errors,
115 });
116 },
117 R::Help(builder) => {
118 return Ok(VarkRet::Help(VarkRetHelp {
119 command: state.command,
120 args: state.args,
121 consumed_args: state.i,
122 builder: builder,
123 }));
124 },
125 R::Ok(v) => {
126 if state.i != state.args.len() {
127 return Err(Error {
128 command: state.command,
129 detail: vec![VarkFailure {
130 arg_offset: state.i,
131 error: format!(
132 "Error parsing command line arguments: final arguments are unrecognized\n{:?}",
133 &state.args[state.i..]
134 ),
135 }],
136 args: state.args,
137 });
138 }
139 return Ok(VarkRet::Ok(v));
140 },
141 }
142}
143
144pub enum VarkRet<T> {
147 Help(VarkRetHelp),
148 Ok(T),
149}