-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add 'crates/aargvark/' from commit '3b586b71e8f3f748463cab60f20e7fcc8…
- Loading branch information
Showing
16 changed files
with
2,386 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
|
||
--- | ||
|
||
I agree that when the request is merged I assign the copyright of the request to the repository owner. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
on: | ||
pull_request: | ||
types: [opened, edited, synchronize] | ||
|
||
jobs: | ||
confirm_agreement: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v2 | ||
- env: | ||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
BODY: ${{ github.event.pull_request.body }} | ||
PR_ID: ${{ github.event.pull_request.number }} | ||
run: | | ||
set -xeu | ||
if ! grep -F "$(tail -n 1 .github/pull_request_template.md)" <(echo "$BODY"); then | ||
gh pr close --comment "All changes must include the provided agreement to the copyright assignment." --delete-branch "$PR_ID" | ||
fi |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
/target | ||
/Cargo.lock | ||
/.vscode |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
[workspace] | ||
resolver = "2" | ||
members = ["crates/*"] | ||
|
||
[workspace.package] | ||
edition = "2021" | ||
license = "ISC" | ||
description = "Self-similar argument parsing" | ||
homepage = "https://github.com/andrewbaxter/aargvark" | ||
repository = "https://github.com/andrewbaxter/aargvark" | ||
readme = "readme.md" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
[package] | ||
name = "aargvark" | ||
description = "Self-similar argument parsing" | ||
version = "0.6.5" | ||
edition.workspace = true | ||
license.workspace = true | ||
homepage.workspace = true | ||
repository.workspace = true | ||
readme.workspace = true | ||
|
||
[package.metadata.docs.rs] | ||
all-features = true | ||
|
||
[features] | ||
default = [] | ||
serde_json = ["dep:serde_json", "dep:serde"] | ||
serde_yaml = ["dep:serde_yaml", "dep:serde"] | ||
http_types = ["dep:http"] | ||
|
||
[dependencies] | ||
aargvark_proc_macros = { path = "../aargvark_proc_macros", version = "=3.2.5" } | ||
serde_json = { version = "1", optional = true } | ||
serde_yaml = { version = "0", optional = true } | ||
convert_case = "0.6" | ||
comfy-table = { version = "7", features = ["custom_styling"] } | ||
url = { version = "2", optional = true } | ||
http = { version = "1", optional = true } | ||
serde = { version = "1", optional = true } | ||
console = "0.15" | ||
textwrap = { version = "0.16", features = ["terminal_size"] } | ||
unicode-width = "0.1" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
../../readme.md |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,179 @@ | ||
use { | ||
crate::help::{ | ||
HelpPartialProduction, | ||
HelpState, | ||
}, | ||
unicode_width::UnicodeWidthStr, | ||
}; | ||
|
||
pub struct VarkFailure { | ||
pub arg_offset: usize, | ||
pub error: String, | ||
} | ||
|
||
/// Return type enum (like `Result`) during parsing. | ||
pub enum R<T> { | ||
/// Ran out of arguments before parsing successfully completed. | ||
EOF, | ||
/// Parsing failed due to incorrect arguments. | ||
Err, | ||
/// Encountered `-h` or `--help` and aborted. | ||
Help(Box<dyn FnOnce(&mut HelpState) -> HelpPartialProduction>), | ||
/// Successfully parsed value. | ||
Ok(T), | ||
} | ||
|
||
/// Possible results of peeking the output. | ||
pub enum PeekR<'a> { | ||
/// There's another argument | ||
Ok(&'a str), | ||
/// No more arguments remain | ||
None, | ||
/// The next argument is `-h` or `--help` - caller should return `R::Help`. | ||
Help, | ||
} | ||
|
||
#[doc(hidden)] | ||
pub struct VarkState { | ||
pub(crate) command: Option<String>, | ||
pub(crate) args: Vec<String>, | ||
pub(crate) i: usize, | ||
pub(crate) errors: Vec<VarkFailure>, | ||
} | ||
|
||
impl VarkState { | ||
pub fn new(command: Option<String>, args: Vec<String>) -> Self { | ||
return Self { | ||
command: command, | ||
args: args, | ||
i: 0, | ||
errors: vec![], | ||
}; | ||
} | ||
} | ||
|
||
impl VarkState { | ||
/// Return the next argument without consuming it. | ||
pub fn peek<'a>(&'a self) -> PeekR<'a> { | ||
if self.i >= self.args.len() { | ||
return PeekR::None; | ||
} | ||
let v = &self.args[self.i]; | ||
if v == "-h" || v == "--help" { | ||
return PeekR::Help; | ||
} | ||
return PeekR::Ok(v); | ||
} | ||
|
||
/// The argument the current argument pointer is pointing to. | ||
pub fn position(&self) -> usize { | ||
return self.i; | ||
} | ||
|
||
/// Reset the agument pointer to an earlier argument (i.e. after consuming N | ||
/// arguments but finding the required final argument missing). | ||
pub fn rewind(&mut self, i: usize) { | ||
self.i = i; | ||
} | ||
|
||
/// Move the argument pointer to the next argument (ex: after inspecting it using | ||
/// `peek`). | ||
pub fn consume(&mut self) { | ||
self.i += 1; | ||
} | ||
|
||
/// Produce a "parse successful" return value. | ||
pub fn r_ok<T>(&self, v: T) -> R<T> { | ||
return R::Ok(v); | ||
} | ||
|
||
/// Produce a "parse failed" return value (includes which argument was being | ||
/// inspected when the failure occured). | ||
pub fn r_err<T>(&mut self, text: String) -> R<T> { | ||
self.errors.push(VarkFailure { | ||
arg_offset: self.i, | ||
error: text, | ||
}); | ||
return R::Err; | ||
} | ||
} | ||
|
||
pub enum ErrorDetail { | ||
/// The parser needed more command line arguments. | ||
TooLittle, | ||
/// Fully parsed command but additional unconsumed arguments follow (offset of | ||
/// first unrecognized argument) | ||
TooMuch(usize), | ||
/// Aargvark considers multiple possible parses. This is a list of considered | ||
/// parses, in order of when they were ruled out. | ||
Incorrect(Vec<VarkFailure>), | ||
} | ||
|
||
/// Returned by `vark_explicit`. `command` is whatever is passed as `command` to | ||
/// `vark_explicit`, the first of argv if using `vark`. `args` is the remaining | ||
/// arguments. | ||
pub struct Error { | ||
pub command: Option<String>, | ||
pub args: Vec<String>, | ||
pub detail: ErrorDetail, | ||
} | ||
|
||
impl std::fmt::Display for Error { | ||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||
match &self.detail { | ||
ErrorDetail::TooLittle => { | ||
return "Missing arguments, use --help for more info".fmt(f); | ||
}, | ||
ErrorDetail::TooMuch(first) => { | ||
return format_args!( | ||
"Error parsing command line arguments: final arguments are unrecognized\n{:?}", | ||
&self.args[*first..] | ||
).fmt(f); | ||
}, | ||
ErrorDetail::Incorrect(failures) => { | ||
let mut display_args = vec![]; | ||
let mut offset_offset = 0; | ||
if let Some(c) = &self.command { | ||
display_args.push(c.clone()); | ||
offset_offset = 1; | ||
} | ||
display_args.extend(self.args.iter().map(|a| format!("{:?}", a))); | ||
let mut display_arg_offsets = vec![]; | ||
{ | ||
let mut offset = 0; | ||
for d in &display_args { | ||
display_arg_offsets.push(offset); | ||
offset += d.width() + 1; | ||
} | ||
display_arg_offsets.push(offset); | ||
} | ||
let mut display_args = display_args.join(" "); | ||
display_args.push_str(" <END>"); | ||
let mut text = "Error parsing arguments.\n".to_string(); | ||
for e in failures.iter().rev() { | ||
text.push_str("\n"); | ||
text.push_str(&format!(" * {}\n", e.error)); | ||
text.push_str(" "); | ||
text.push_str(&display_args); | ||
text.push_str("\n"); | ||
text.push_str(" "); | ||
text.push_str( | ||
&" ".repeat( | ||
display_arg_offsets.get(e.arg_offset + offset_offset).cloned().unwrap_or(0usize), | ||
), | ||
); | ||
text.push_str("^\n"); | ||
} | ||
return text.fmt(f); | ||
}, | ||
} | ||
} | ||
} | ||
|
||
impl std::fmt::Debug for Error { | ||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||
return std::fmt::Display::fmt(self, f); | ||
} | ||
} | ||
|
||
impl std::error::Error for Error { } |
Oops, something went wrong.