diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-30 18:31:44 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-30 18:31:44 +0000 |
commit | c23a457e72abe608715ac76f076f47dc42af07a5 (patch) | |
tree | 2772049aaf84b5c9d0ed12ec8d86812f7a7904b6 /vendor/comma | |
parent | Releasing progress-linux version 1.73.0+dfsg1-1~progress7.99u1. (diff) | |
download | rustc-c23a457e72abe608715ac76f076f47dc42af07a5.tar.xz rustc-c23a457e72abe608715ac76f076f47dc42af07a5.zip |
Merging upstream version 1.74.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/comma')
-rw-r--r-- | vendor/comma/.cargo-checksum.json | 1 | ||||
-rw-r--r-- | vendor/comma/Cargo.toml | 26 | ||||
-rw-r--r-- | vendor/comma/README.md | 26 | ||||
-rw-r--r-- | vendor/comma/src/lib.rs | 90 |
4 files changed, 143 insertions, 0 deletions
diff --git a/vendor/comma/.cargo-checksum.json b/vendor/comma/.cargo-checksum.json new file mode 100644 index 000000000..5ab64dc2e --- /dev/null +++ b/vendor/comma/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"Cargo.toml":"1948b6f99c75b25f6b70dab12155ba2854cdcebd18d823a3b84f3ea7a57e382c","README.md":"04da7267815159c07eae7f9802697cde66c49c8f2cca190c7f657841eb1dc0a8","src/lib.rs":"4beb857981727fbdd3142301bb2f945e88437320296da6d39b266aeaddbfdb22"},"package":"55b672471b4e9f9e95499ea597ff64941a309b2cdbffcc46f2cc5e2d971fd335"}
\ No newline at end of file diff --git a/vendor/comma/Cargo.toml b/vendor/comma/Cargo.toml new file mode 100644 index 000000000..2d0a24a09 --- /dev/null +++ b/vendor/comma/Cargo.toml @@ -0,0 +1,26 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies +# +# If you believe there's an error in this file please file an +# issue against the rust-lang/cargo repository. If you're +# editing this file be aware that the upstream Cargo.toml +# will likely look very different (and much more reasonable) + +[package] +edition = "2018" +name = "comma" +version = "1.0.0" +authors = ["Ethan McTague <ethan@tague.me>"] +exclude = ["target", ".idea/*", ".gitignore"] +description = "Shell-style command parser with support for escaping and quotations." +readme = "README.md" +keywords = ["string", "parse", "parsing", "command", "shell"] +categories = ["command-line-interface", "parsing", "parser-implementations"] +license = "MIT" +repository = "https://github.com/emctague/comma" + +[dependencies] diff --git a/vendor/comma/README.md b/vendor/comma/README.md new file mode 100644 index 000000000..a6d9f5f60 --- /dev/null +++ b/vendor/comma/README.md @@ -0,0 +1,26 @@ +# comma + +[![Crates.io](https://img.shields.io/crates/v/comma?style=flat-square)](https://crates.io/crates/comma) +[![docs.rs](https://docs.rs/comma/badge.svg)](https://docs.rs/comma) +[![Build Status](https://travis-ci.org/emctague/comma.svg?branch=master)](https://travis-ci.org/emctague/comma) + +`comma` splits shell-style commands, e.g. `sendmsg joe "I say \"hi\" to you!"`, into a list of individual tokens. +It correctly handles unicode characters, escape sequences, and single- or double-quoted strings. + +## Cargo + +```toml +[dependencies] +comma = "1.0.0" +``` + +## Usage + +```rust +use comma::parse_command; + +fn main () { + let parsed = parse_command("sendmsg joe \"I say \\\"hi\\\" to you!\" 'but only\\ntoday'").unwrap(); + println!("Result: {:#?}", parsed); // Result: [ "sendmsg", "joe", "I say \"hi\" to you!", "but only\ntoday" ] +} +```
\ No newline at end of file diff --git a/vendor/comma/src/lib.rs b/vendor/comma/src/lib.rs new file mode 100644 index 000000000..d82154e48 --- /dev/null +++ b/vendor/comma/src/lib.rs @@ -0,0 +1,90 @@ +//! `comma` parses command-line-style strings. See [`parse_command`] for details. + +use std::iter::{Peekable}; +use std::str::{Chars}; + +fn parse_escape(chars: &mut Peekable<Chars>) -> Option<char> { + return Some(match chars.next()? { + 'n' => '\n', + 'r' => '\r', + 't' => '\t', + literal => literal + }) +} + +fn parse_string(chars: &mut Peekable<Chars>, delim: char) -> Option<String> { + let mut output = String::new(); + + while let Some(ch) = chars.next() { + if ch == delim { + return Some(output) + } else if ch == '\\' { + output.push(parse_escape(chars)?); + } else { + output.push(ch); + } + } + + return None +} + +/// Parses a command into a list of individual tokens. +/// Each token is separated by one or more characters of whitespace. +/// Pairs of single- or double-quotes can be used to ignore whitespace. Within pairs of quotation +/// marks, a backslash (\) can be used to escape any character. The special escape sequences +/// '\n', '\r', and '\t' are also handled as Newlines, Carriage Returns, and Tabs, respectively. +/// Should a quotation mark be mismatched (no counterpart terminating mark exists), this function +/// will return None. Otherwise, it returns a list of tokens in the input string. +pub fn parse_command(input: &str) -> Option<Vec<String>> { + let mut next_push = true; + let mut chars = input.chars().peekable(); + let mut output : Vec<String> = Vec::new(); + + while let Some(ch) = chars.next() { + if ch.is_whitespace() { + next_push = true; + } else{ + if next_push { output.push(String::new()); next_push = false; } + + if ch == '\\' { + output.last_mut()?.push(parse_escape(&mut chars)?); + } else if ch == '"' || ch == '\'' { + output.last_mut()?.push_str(parse_string(&mut chars, ch)?.as_str()); + } else { + output.last_mut()?.push(ch); + } + } + } + + return Some(output) +} + + +#[cfg(test)] +mod tests { + use crate::{parse_command}; + + #[test] + fn parsing_works() { + let result = parse_command("hello world \\'this is\\' a \"quoted \\\"string\\\"\"").unwrap(); + assert_eq!(result, + vec![String::from("hello"), String::from("world"), + String::from("'this"), String::from("is'"), String::from("a"), + String::from("quoted \"string\"")]); + } + + #[test] + fn fail_mismatch() { + assert_eq!(parse_command("Hello 'world "), None); + } + + #[test] + fn unicode() { + // This contains a CJK IDEOGRAPH EXTENSION G character, which is invisible. + let result = parse_command("ß 𱁬").unwrap(); + assert_eq!( + result, + vec![String::from("ß"), String::from("𱁬")] + ); + } +} |