Skip to content

Commit a0e5470

Browse files
committed
Polish.
1 parent 823b47c commit a0e5470

File tree

5 files changed

+101
-31
lines changed

5 files changed

+101
-31
lines changed

crates/shell/src/joiner.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ where
3838
}
3939

4040
#[derive(PartialEq)]
41-
pub enum ArgSyntax {
41+
enum ArgSyntax {
4242
Option,
4343
Operator,
4444
Pipe,
@@ -61,7 +61,7 @@ impl ArgSyntax {
6161
if quotable_equals(
6262
value,
6363
[
64-
">", "^>", "&>", "&>>", ">&", "<&", ">>", "<", "<<", "<<<", "2>", "2>>", "2>&1",
64+
">", ">>", "^>", "&>", "&>>", ">&", "<&", "<", "<<", "<<<", "2>", "2>>", "2>&1",
6565
"<>",
6666
],
6767
) {

crates/shell/src/quoter.rs

Lines changed: 88 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,9 @@
1-
use crate::helpers::{get_var_regex, get_var_regex_bytes, quotable_contains, quotable_into_string};
1+
use crate::helpers::{get_var_regex, get_var_regex_bytes, quotable_into_string};
22
use shell_quote::{Bash, QuoteRefExt};
33
use std::sync::Arc;
44

55
pub use shell_quote::Quotable;
66

7-
fn string_vec<T: AsRef<str>>(items: &[T]) -> Vec<String> {
8-
items
9-
.iter()
10-
.map(|item| item.as_ref().to_string())
11-
.collect::<Vec<_>>()
12-
}
13-
147
fn quote(data: Quotable<'_>) -> String {
158
data.quoted(Bash)
169
}
@@ -31,16 +24,22 @@ fn quote_expansion(data: Quotable<'_>) -> String {
3124
output
3225
}
3326

27+
/// Types of syntax to check for to determine quoting.
28+
pub enum Syntax {
29+
Symbol(String),
30+
Pair(String, String),
31+
}
32+
3433
/// Options for [`Quoter`].
3534
pub struct QuoterOptions {
3635
/// List of start and end quotes for strings.
3736
pub quote_pairs: Vec<(String, String)>,
3837

3938
/// List of syntax and characters that must be quoted for expansion.
40-
pub quoted_syntax: Vec<String>,
39+
pub quoted_syntax: Vec<Syntax>,
4140

4241
/// List of syntax and characters that must not be quoted.
43-
pub unquoted_syntax: Vec<String>,
42+
pub unquoted_syntax: Vec<Syntax>,
4443

4544
/// Handler to apply quoting.
4645
pub on_quote: Arc<dyn Fn(Quotable<'_>) -> String>,
@@ -54,15 +53,31 @@ impl Default for QuoterOptions {
5453
Self {
5554
quote_pairs: vec![("'".into(), "'".into()), ("\"".into(), "\"".into())],
5655
// https://www.gnu.org/software/bash/manual/bash.html#Shell-Expansions
57-
quoted_syntax: string_vec(&[
58-
"${", // param
59-
"$(", // command
60-
]),
61-
unquoted_syntax: string_vec(&[
62-
"{", "}", // brace
63-
"<(", ">(", // process
64-
"**", "*", "?", "?(", "*(", "+(", "@(", "!(", // file, glob
65-
]),
56+
quoted_syntax: vec![
57+
// param
58+
Syntax::Pair("${".into(), "}".into()),
59+
// command
60+
Syntax::Pair("$(".into(), ")".into()),
61+
// arithmetic
62+
Syntax::Pair("$((".into(), "))".into()),
63+
],
64+
unquoted_syntax: vec![
65+
// brace
66+
Syntax::Pair("{".into(), "}".into()),
67+
// process
68+
Syntax::Pair("<(".into(), ")".into()),
69+
Syntax::Pair(">(".into(), ")".into()),
70+
// file, glob
71+
Syntax::Symbol("**".into()),
72+
Syntax::Symbol("*".into()),
73+
Syntax::Symbol("?".into()),
74+
Syntax::Pair("[".into(), "]".into()),
75+
Syntax::Pair("?(".into(), ")".into()),
76+
Syntax::Pair("*(".into(), ")".into()),
77+
Syntax::Pair("+(".into(), ")".into()),
78+
Syntax::Pair("@(".into(), ")".into()),
79+
Syntax::Pair("!(".into(), ")".into()),
80+
],
6681
on_quote: Arc::new(quote),
6782
on_quote_expansion: Arc::new(quote_expansion),
6883
}
@@ -151,7 +166,7 @@ impl<'a> Quoter<'a> {
151166

152167
/// Return true if the provided string requires expansion.
153168
pub fn requires_expansion(&self) -> bool {
154-
if quotable_contains(&self.data, &self.options.quoted_syntax) {
169+
if quotable_contains_syntax(&self.data, &self.options.quoted_syntax) {
155170
return true;
156171
}
157172

@@ -163,6 +178,58 @@ impl<'a> Quoter<'a> {
163178

164179
/// Return true if the provided string must be unquoted.
165180
pub fn requires_unquoted(&self) -> bool {
166-
quotable_contains(&self.data, &self.options.unquoted_syntax)
181+
quotable_contains_syntax(&self.data, &self.options.unquoted_syntax)
182+
}
183+
}
184+
185+
fn quotable_contains_syntax(data: &Quotable<'_>, syntaxes: &[Syntax]) -> bool {
186+
for syntax in syntaxes {
187+
match data {
188+
Quotable::Bytes(bytes) => {
189+
match syntax {
190+
Syntax::Symbol(symbol) => {
191+
let sbytes = symbol.as_bytes();
192+
193+
if bytes.windows(sbytes.len()).any(|chunk| chunk == sbytes) {
194+
return true;
195+
}
196+
}
197+
Syntax::Pair(open, close) => {
198+
let obytes = open.as_bytes();
199+
let cbytes = close.as_bytes();
200+
201+
if let Some(o) = bytes
202+
.windows(obytes.len())
203+
.position(|chunk| chunk == obytes)
204+
{
205+
if bytes[o..]
206+
.windows(cbytes.len())
207+
.any(|chunk| chunk == cbytes)
208+
{
209+
return true;
210+
}
211+
}
212+
}
213+
};
214+
}
215+
Quotable::Text(text) => {
216+
match syntax {
217+
Syntax::Symbol(symbol) => {
218+
if text.contains(symbol) {
219+
return true;
220+
}
221+
}
222+
Syntax::Pair(open, close) => {
223+
if let Some(o) = text.find(open) {
224+
if text[o..].contains(close) {
225+
return true;
226+
}
227+
}
228+
}
229+
};
230+
}
231+
};
167232
}
233+
234+
false
168235
}

crates/shell/src/shells/elvish.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ impl Shell for Elvish {
7676
Quoter::new(
7777
data,
7878
QuoterOptions {
79-
unquoted_syntax: vec!["{~}".into()],
79+
unquoted_syntax: vec![Syntax::Symbol("{~}".into())],
8080
on_quote: Arc::new(|data| Elvish::do_quote(quotable_into_string(data))),
8181
..Default::default()
8282
},

crates/shell/src/shells/ion.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,12 @@ impl Shell for Ion {
4444
QuoterOptions {
4545
// https://doc.redox-os.org/ion-manual/expansions/00-expansions.html
4646
quoted_syntax: vec![
47-
"$".into(),
48-
"${".into(),
49-
"$(".into(),
50-
"@".into(),
51-
"@{".into(),
52-
"@(".into(),
47+
Syntax::Symbol("$".into()),
48+
Syntax::Pair("${".into(), "}".into()),
49+
Syntax::Pair("$(".into(), ")".into()),
50+
Syntax::Symbol("@".into()),
51+
Syntax::Pair("@{".into(), "}".into()),
52+
Syntax::Pair("@(".into(), ")".into()),
5353
],
5454
on_quote: Arc::new(|data| Ion::do_quote(quotable_into_string(data))),
5555
..Default::default()

crates/shell/src/shells/powershell.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,10 @@ impl Shell for PowerShell {
8888
Quoter::new(
8989
data,
9090
QuoterOptions {
91-
quoted_syntax: vec!["$(".into(), "${".into()],
91+
quoted_syntax: vec![
92+
Syntax::Pair("$(".into(), ")".into()),
93+
Syntax::Pair("${".into(), "}".into()),
94+
],
9295
on_quote: Arc::new(|data| PowerShell::do_quote(quotable_into_string(data))),
9396
on_quote_expansion: Arc::new(|data| {
9497
PowerShell::do_quote_expansion(quotable_into_string(data))

0 commit comments

Comments
 (0)