shlex-0.1.1/Cargo.toml000064400007660000120000000013641254213122500130010ustar0000000000000000# 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] name = "shlex" version = "0.1.1" authors = ["comex "] description = "Split a string into shell words, like Python's shlex.\n" license = "MIT/Apache-2.0" repository = "https://github.com/comex/rust-shlex" shlex-0.1.1/Cargo.toml.orig000064400007660000120000000003541254213122500137360ustar0000000000000000[package] name = "shlex" version = "0.1.1" authors = ["comex "] license = "MIT/Apache-2.0" repository = "https://github.com/comex/rust-shlex" description = """ Split a string into shell words, like Python's shlex. """ shlex-0.1.1/src/lib.rs000064400007660000120000000176011254213213300127540ustar0000000000000000// Copyright 2015 Nicholas Allegra (comex). // Licensed under the Apache License, Version 2.0 or // the MIT license , at your option. This file may not be // copied, modified, or distributed except according to those terms. //! Same idea as (but implementation not directly based on) the Python shlex module. However, this //! implementation does not support any of the Python module's customization because it makes //! parsing slower and is fairly useless. You only get the default settings of shlex.split, which //! mimic the POSIX shell: //! http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html //! //! This implementation also deviates from the Python version in not treating \r specially, which I //! believe is more compliant. //! //! The algorithms in this crate are oblivious to UTF-8 high bytes, so they iterate over the bytes //! directly as a micro-optimization. use std::borrow::Cow; /// An iterator that takes an input string and splits it into the words using the same syntax as /// the POSIX shell. pub struct Shlex<'a> { in_iter: std::str::Bytes<'a>, /// The number of newlines read so far, plus one. pub line_no: usize, /// An input string is erroneous if it ends while inside a quotation or right after an /// unescaped backslash. Since Iterator does not have a mechanism to return an error, if that /// happens, Shlex just throws out the last token, ends the iteration, and sets 'had_error' to /// true; best to check it after you're done iterating. pub had_error: bool, } impl<'a> Shlex<'a> { pub fn new(in_str: &'a str) -> Self { Shlex { in_iter: in_str.bytes(), line_no: 1, had_error: false, } } fn parse_word(&mut self, mut ch: u8) -> Option { let mut result: Vec = Vec::new(); loop { match ch as char { '"' => if let Err(()) = self.parse_double(&mut result) { self.had_error = true; return None; }, '\'' => if let Err(()) = self.parse_single(&mut result) { self.had_error = true; return None; }, '\\' => if let Some(ch2) = self.next_char() { if ch2 != '\n' as u8 { result.push(ch2); } } else { self.had_error = true; return None; }, ' ' | '\t' | '\n' => { break; }, _ => { result.push(ch as u8); }, } if let Some(ch2) = self.next_char() { ch = ch2; } else { break; } } unsafe { Some(String::from_utf8_unchecked(result)) } } fn parse_double(&mut self, result: &mut Vec) -> Result<(), ()> { loop { if let Some(ch2) = self.next_char() { match ch2 as char { '\\' => { if let Some(ch3) = self.next_char() { match ch3 as char { // \$ => $ '$' | '`' | '"' | '\\' => { result.push(ch3); }, // \ => nothing '\n' => {}, // \x => =x _ => { result.push('\\' as u8); result.push(ch3); } } } else { return Err(()); } }, '"' => { return Ok(()); }, _ => { result.push(ch2); }, } } else { return Err(()); } } } fn parse_single(&mut self, result: &mut Vec) -> Result<(), ()> { loop { if let Some(ch2) = self.next_char() { match ch2 as char { '\\' => { if let Some(ch3) = self.next_char() { match ch3 as char { // for single quotes, only these can be escaped '\'' | '\\' => { result.push(ch3); }, _ => { result.push('\\' as u8); result.push(ch3); } } } else { return Err(()); } }, '\'' => { return Ok(()); }, _ => { result.push(ch2); }, } } else { return Err(()); } } } fn next_char(&mut self) -> Option { let res = self.in_iter.next(); if res == Some('\n' as u8) { self.line_no += 1; } res } } impl<'a> Iterator for Shlex<'a> { type Item = String; fn next(&mut self) -> Option { if let Some(mut ch) = self.next_char() { // skip initial whitespace loop { match ch as char { ' ' | '\t' | '\n' => {}, '#' => { while let Some(ch2) = self.next_char() { if ch2 as char == '\n' { break; } } }, _ => { break; } } if let Some(ch2) = self.next_char() { ch = ch2; } else { return None; } } self.parse_word(ch) } else { // no initial character None } } } /// Convenience function that consumes the whole string at once. Returns None if the input was /// erroneous. pub fn split(in_str: &str) -> Option> { let mut shl = Shlex::new(in_str); let res = shl.by_ref().collect(); if shl.had_error { None } else { Some(res) } } /// Given a single word, return a string suitable to encode it as a shell argument. pub fn quote(in_str: &str) -> Cow { if in_str.len() == 0 { "\"\"".into() } else if in_str.bytes().any(|c| match c as char { '|' | '&' | ';' | '<' | '>' | '(' | ')' | '$' | '`' | '\\' | '"' | '\'' | ' ' | '\t' | '\r' | '\n' | '*' | '?' | '[' | '#' | '~' | '=' | '%' => true, _ => false }) { let mut out: Vec = Vec::new(); out.push('"' as u8); for c in in_str.bytes() { match c as char { '$' | '`' | '"' | '\\' => out.push('\\' as u8), _ => () } out.push(c); } out.push('"' as u8); unsafe { String::from_utf8_unchecked(out) }.into() } else { in_str.into() } } #[cfg(test)] static SPLIT_TEST_ITEMS: &'static [(&'static str, Option<&'static [&'static str]>)] = &[ ("foo$baz", Some(&["foo$baz"])), ("foo baz", Some(&["foo", "baz"])), ("foo\"bar\"baz", Some(&["foobarbaz"])), ("foo \"bar\"baz", Some(&["foo", "barbaz"])), (" foo \nbar", Some(&["foo", "bar"])), ("foo\\\nbar", Some(&["foobar"])), ("\"foo\\\nbar\"", Some(&["foobar"])), ("'baz\\$b'", Some(&["baz\\$b"])), ("'baz\\\''", Some(&["baz\'"])), ("\\", None), ("\"\\", None), ("'\\", None), ("\"", None), ("'", None), ("foo #bar\nbaz", Some(&["foo", "baz"])), ("foo #bar", Some(&["foo"])), ("foo#bar", Some(&["foo#bar"])), ("foo\"#bar", None), ]; #[test] fn test_split() { for &(input, output) in SPLIT_TEST_ITEMS { assert_eq!(split(input), output.map(|o| o.iter().map(|&x| x.to_owned()).collect())); } } #[test] fn test_lineno() { let mut sh = Shlex::new("\nfoo\nbar"); while let Some(word) = sh.next() { if word == "bar" { assert_eq!(sh.line_no, 3); } } } #[test] fn test_quote() { assert_eq!(quote("foobar"), "foobar"); assert_eq!(quote("foo bar"), "\"foo bar\""); assert_eq!(quote("\""), "\"\\\"\""); assert_eq!(quote(""), "\"\""); } shlex-0.1.1/.Cargo.toml.swp000064400007660000120000000300001254213127700136630ustar0000000000000000b0VIM 7.4U'jdcomexnicholas-allegras-macbook-pro.local~comex/c/shlex/Cargo.tomlutf-8 3210#"! Utp ad `NRust """Split a string into shell words, like Python's shlex.description = """repository = "https://github.com/comex/rust-shlex"license = "MIT/Apache-2.0"authors = ["comex "]version = "0.1.1"name = "shlex"[package]shlex-0.1.1/src/.lib.rs.swp000064400007660000120000000700001254213215100136320ustar0000000000000000b0VIM 7.4[Umdcomexnicholas-allegras-macbook-pro.local~comex/c/shlex/src/lib.rsutf-8 3210#"! Utp86* P Q/adhd8rj  A = S - ,   f 0  Z ` P +  yjKY. }d6RK|bEVH>8Y-U;" Some('\'') => { return Ok(()); }, }, } return Err(()); } else { } _ => { result.push('\\'); result.push(ch3); } '\'' | '\\' => { result.push(ch3); }, // for single quotes, only these can be escaped match ch3 as char { if let Some(ch3) = self.next_char() { Some('\\') => { match self.next_char() as char { loop { fn parse_single(&mut self, result: &mut Vec) -> Result<(), ()> { } } } None => { return Err(()); } Some(ch2) => { result.push(ch2 as u8); }, Some(34 /* " */) => { return Ok(()); }, }, } else { if ch2 != '\n' as u8 { result.push(ch2 } else { if ch2 != '\n' } else { i } else { if ch2 != '\n' as u8 { result.push(ch2); } } else { if ch2 != '\n' as u8 } else { if ch2 != '\n' as u8 { result.push(ch2); } '\\' => if let Some(ch2) = self.next_char() { }, return None; self.had_error = true; '\'' => if let Err(()) = self.parse_single(&mut result) { }, return None; self.had_error = true; '"' => if let Err(()) = self.parse_double(&mut result) { match ch as char { loop { let mut result: Vec = Vec::new(); fn parse_word(&mut self, mut ch: u8) -> Option { } } had_error: false, line_no: 1, in_iter: in_str.bytes(), Shlex { pub fn new(in_str: &'a str) -> Self {impl<'a> Shlex<'a> {} pub had_error: bool, /// true; best to check it after you're done iterating. /// happens, Shlex just throws out the last token, ends the iteration, and sets 'had_error' to /// unescaped backslash. Since Iterator does not have a mechanism to return an error, if that /// An input string is erroneous if it ends while inside a quotation or right after an pub line_no: usize, /// The number of newlines read so far, plus one. in_iter: std::str::Bytes<'a>,pub struct Shlex<'a> {/// the POSIX shell./// An iterator that takes an input string and splits it into the words using the same syntax asuse std::borrow::Cow;//! directly as a micro-optimization.//! The algorithms in this crate are oblivious to UTF-8 high bytes, so they iterate over the bytes//!//! believe is more compliant.//! This implementation also deviates from the Python version in not treating \r specially, which I//!//! http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html//! mimic the POSIX shell://! parsing slower and is fairly useless. You only get the default settings of shlex.split, which//! implementation does not support any of the Python module's customization because it makes//! Same idea as (but implementation not directly based on) the Python shlex module. However, this// copied, modified, or distributed except according to those terms.// the MIT license , at your option. This file may not be// Licensed under the Apache License, Version 2.0 or// Copyright 2015 Nicholas Allegra (comex).ad>QZ4]B, O < 3  k S E , "  8  _ 8 v e 7  -'%$ ukecbZH} assert_eq!(quote(""), "\"\""); assert_eq!(quote("\""), "\"\\\"\""); assert_eq!(quote("foo bar"), "\"foo bar\""); assert_eq!(quote("foobar"), "foobar");fn test_quote() {#[test]} } } assert_eq!(sh.line_no, 3); if word == "bar" { while let Some(word) = sh.next() { let mut sh = Shlex::new("\nfoo\nbar");fn test_lineno() {#[test]} } assert_eq!(split(input), output.map(|o| o.iter().map(|&x| x.to_owned()).collect())); for &(input, output) in SPLIT_TEST_ITEMS {fn test_split() {#[test]]; ("foo\"#bar", None), ("foo#bar", Some(&["foo#bar"])), ("foo #bar", Some(&["foo"])), ("foo #bar\nbaz", Some(&["foo", "baz"])), ("'", None), ("\"", None), ("'\\", None), ("\"\\", None), ("\\", None), ("'baz\\\''", Some(&["baz\'"])), ("'baz\\$b'", Some(&["baz\\$b"])), ("\"foo\\\nbar\"", Some(&["foobar"])), ("foo\\\nbar", Some(&["foobar"])), (" foo \nbar", Some(&["foo", "bar"])), ("foo \"bar\"baz", Some(&["foo", "barbaz"])), ("foo\"bar\"baz", Some(&["foobarbaz"])), ("foo baz", Some(&["foo", "baz"])), ("foo$baz", Some(&["foo$baz"])),static SPLIT_TEST_ITEMS: &'static [(&'static str, Option<&'static [&'static str]>)] = &[#[cfg(test)]} } in_str.into() } else { unsafe { String::from_utf8_unchecked(out) }.into() out.push('"' as u8); } out.push(c); } _ => () '$' | '`' | '"' | '\\' => out.push('\\' as u8), match c as char { for c in in_str.bytes() { out.push('"' as u8); let mut out: Vec = Vec::new(); }) { _ => false '\r' | '\n' | '*' | '?' | '[' | '#' | '~' | '=' | '%' => true, '|' | '&' | ';' | '<' | '>' | '(' | ')' | '$' | '`' | '\\' | '"' | '\'' | ' ' | '\t' | } else if in_str.bytes().any(|c| match c as char { "\"\"".into() if in_str.len() == 0 {pub fn quote(in_str: &str) -> Cow {/// Given a single word, return a string suitable to encode it as a shell argument.} if shl.had_error { None } else { Some(res) } let res = shl.by_ref().collect(); let mut shl = Shlex::new(in_str);pub fn split(in_str: &str) -> Option> {/// erroneous./// Convenience function that consumes the whole string at once. Returns None if the input was}adawKz`  z V  z p b 6 { ^ D k  t O @ ^&~kJQL$  } } } } } } N } } } } } } } None => { retur } } } } } } } None => { return Err(()); } } } Non } } } } } None => { return Err(()); } } } Non } } } } } None => { return } } None => } } } None => { return Err } } } } None => { return Err(()); } } } } } } } } None => { return E } } } } } } None => { return Err(()); } } } None => { ret } } } } } } None => { return Err(()); } } } } } } } } } } } None => { } } None => { return } } None } } } } None => { return Err(()); } } } } } } } } None => { return E } } } } None => { return Err(()); } } } None => { return Err(()); } } } None => { return Err(()); } } } } } } } } } } } No } } None => { return } } } } } } } } None } else { // no initial character self.parse_word(ch)ad ?  {qkj>c2  J M ? (  } } } } if let Some(ch2) = self.next_char() { ch = ch2; } else { return None; } } _ => { break; } }, } if ch2 as char == '\n' { break; } while let Some(ch2) = self.next_char() { '#' => { ' ' | '\t' | '\n' => {}, match ch as char { loop { // skip initial whitespace if let Some(mut ch) = self.next_char() { fn next(&mut self) -> Option { type Item = String;impl<'a> Iterator for Shlex<'a> {} } res if res == Some('\n' as u8) { self.line_no += 1; } let res = self.in_iter.next(); fn next_char(&mut self) -> Option { } } } return Err(()); } else { } _ => { result.push(ch2); },ad6p?1L=  [ 0 z N u ^ / P A  _  uW6 S '\'' => { return Ok(()); }, '\'' => '\ '\'' => { return Ok(()); }, '\'' => { return Ok(()); }, '\'' '\'' => { return Ok(()); }, }, } return Err(()); } else { } _ => { result.push('\\' as u8); result.push(ch3); } '\'' | '\\' => { result.push(ch3); }, // for single quotes, only these can be escaped match ch3 as char { if let Some(ch3) = self.next_char() { '\\' => { match ch2 as char { if let Some(ch2) = self.next_char() { loop { fn parse_single(&mut self, result: &mut Vec) -> Result<(), ()> { } } } return Err(()); } else { } _ => { result.push(ch2); }, '"' => { return Ok(()); }, }, } return Err(()); } else { } _ => { result.push('\\' as u8); result.push(ch3); } // \x => =x '\n' => {}, // \ => nothing '$' | '`' | '"' | '\\' => { result.push(ch3); }, // \$ => $ match ch3 as char { if let Some(ch3) = self.next_char() { '\\' => { match ch2 as char { if let Some(ch2) = self.next_char() { loop { fn parse_double(&mut self, result: &mut Vec) -> Result<(), ()> { } unsafe { Some(String::from_utf8_unchecked(result)) } } if let Some(ch2) = self.next_char() { ch = ch2; } else { break; } } _ => { result.push(ch as u8); }, ' ' | '\t' | '\n' => { break; }, }, return None; self.had_error = true;