yerba 0.9.2-arm-linux-gnu → 0.10.0-arm-linux-gnu
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +34 -17
- data/exe/arm-linux-gnu/yerba +0 -0
- data/ext/yerba/include/yerba.h +56 -34
- data/ext/yerba/yerba.c +268 -186
- data/lib/yerba/3.2/yerba.so +0 -0
- data/lib/yerba/3.3/yerba.so +0 -0
- data/lib/yerba/3.4/yerba.so +0 -0
- data/lib/yerba/4.0/yerba.so +0 -0
- data/lib/yerba/collection.rb +4 -4
- data/lib/yerba/document.rb +134 -0
- data/lib/yerba/formatting.rb +1 -0
- data/lib/yerba/location.rb +8 -1
- data/lib/yerba/map.rb +16 -6
- data/lib/yerba/node.rb +41 -0
- data/lib/yerba/query_result.rb +33 -10
- data/lib/yerba/scalar.rb +29 -0
- data/lib/yerba/selector.rb +3 -1
- data/lib/yerba/sequence.rb +38 -33
- data/lib/yerba/version.rb +1 -1
- data/rust/Cargo.lock +1 -1
- data/rust/Cargo.toml +1 -1
- data/rust/src/commands/get.rs +12 -12
- data/rust/src/commands/init.rs +8 -8
- data/rust/src/commands/insert.rs +4 -18
- data/rust/src/commands/location.rs +2 -0
- data/rust/src/commands/mod.rs +34 -6
- data/rust/src/commands/move_item.rs +1 -1
- data/rust/src/commands/move_key.rs +8 -8
- data/rust/src/commands/rename.rs +1 -1
- data/rust/src/commands/selectors.rs +1 -1
- data/rust/src/commands/set.rs +14 -6
- data/rust/src/document/condition.rs +25 -25
- data/rust/src/document/delete.rs +57 -43
- data/rust/src/document/get.rs +91 -82
- data/rust/src/document/insert.rs +77 -77
- data/rust/src/document/mod.rs +138 -64
- data/rust/src/document/nodes.rs +162 -0
- data/rust/src/document/schema.rs +8 -8
- data/rust/src/document/set.rs +49 -26
- data/rust/src/document/sort.rs +54 -54
- data/rust/src/document/style.rs +50 -49
- data/rust/src/document/unique.rs +5 -5
- data/rust/src/error.rs +8 -4
- data/rust/src/ffi.rs +218 -106
- data/rust/src/json.rs +62 -2
- data/rust/src/lib.rs +2 -1
- data/rust/src/main.rs +2 -1
- data/rust/src/selector.rs +48 -7
- data/rust/src/syntax.rs +449 -56
- data/rust/src/validation.rs +5 -3
- data/rust/src/yerbafile.rs +124 -76
- metadata +3 -2
data/rust/src/document/set.rs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
use super::*;
|
|
2
2
|
|
|
3
3
|
fn is_plain_writable(value: &str) -> bool {
|
|
4
|
-
crate::syntax::is_plain_safe(value) && !crate::syntax::is_yaml_non_string(value)
|
|
4
|
+
crate::syntax::is_plain_safe(value) && !crate::syntax::is_yaml_non_string(value) && !crate::syntax::resolves_to_non_string_in_psych(value)
|
|
5
5
|
}
|
|
6
6
|
|
|
7
7
|
fn scalar_replacement_text(value: &str, kind: SyntaxKind) -> String {
|
|
@@ -112,23 +112,23 @@ fn replacement_text(span: &ValueSpan, value: &str) -> String {
|
|
|
112
112
|
}
|
|
113
113
|
|
|
114
114
|
impl Document {
|
|
115
|
-
pub fn set(&mut self,
|
|
116
|
-
self.set_with(
|
|
115
|
+
pub fn set(&mut self, selector: &str, value: &str) -> Result<(), YerbaError> {
|
|
116
|
+
self.set_with(selector, value, false)
|
|
117
117
|
}
|
|
118
118
|
|
|
119
|
-
pub fn set_all(&mut self,
|
|
120
|
-
self.set_all_with(
|
|
119
|
+
pub fn set_all(&mut self, selector: &str, value: &str) -> Result<(), YerbaError> {
|
|
120
|
+
self.set_all_with(selector, value, false)
|
|
121
121
|
}
|
|
122
122
|
|
|
123
|
-
pub fn set_all_plain(&mut self,
|
|
124
|
-
self.set_all_with(
|
|
123
|
+
pub fn set_all_plain(&mut self, selector: &str, value: &str) -> Result<(), YerbaError> {
|
|
124
|
+
self.set_all_with(selector, value, true)
|
|
125
125
|
}
|
|
126
126
|
|
|
127
|
-
fn set_all_with(&mut self,
|
|
128
|
-
let nodes = self.navigate_all_compact(
|
|
127
|
+
fn set_all_with(&mut self, selector: &str, value: &str, plain: bool) -> Result<(), YerbaError> {
|
|
128
|
+
let nodes = self.navigate_all_compact(selector);
|
|
129
129
|
|
|
130
130
|
if nodes.is_empty() {
|
|
131
|
-
return Err(YerbaError::SelectorNotFound(
|
|
131
|
+
return Err(YerbaError::SelectorNotFound(selector.to_string()));
|
|
132
132
|
}
|
|
133
133
|
|
|
134
134
|
let source = self.source_text();
|
|
@@ -137,13 +137,21 @@ impl Document {
|
|
|
137
137
|
self.apply_edits(edits)
|
|
138
138
|
}
|
|
139
139
|
|
|
140
|
-
pub fn set_where(
|
|
140
|
+
pub fn set_where(
|
|
141
|
+
&mut self,
|
|
142
|
+
container_selector: &str,
|
|
143
|
+
relative_selector: &str,
|
|
144
|
+
value: &str,
|
|
145
|
+
condition: &str,
|
|
146
|
+
all: bool,
|
|
147
|
+
plain: bool,
|
|
148
|
+
) -> Result<usize, YerbaError> {
|
|
141
149
|
validate_item_condition(condition)?;
|
|
142
150
|
|
|
143
|
-
let items = self.navigate_all_compact(
|
|
151
|
+
let items = self.navigate_all_compact(container_selector);
|
|
144
152
|
|
|
145
153
|
if items.is_empty() {
|
|
146
|
-
return Err(YerbaError::SelectorNotFound(
|
|
154
|
+
return Err(YerbaError::SelectorNotFound(container_selector.to_string()));
|
|
147
155
|
}
|
|
148
156
|
|
|
149
157
|
let source = self.source_text();
|
|
@@ -154,7 +162,7 @@ impl Document {
|
|
|
154
162
|
continue;
|
|
155
163
|
}
|
|
156
164
|
|
|
157
|
-
targets.extend(navigate_from_node(item,
|
|
165
|
+
targets.extend(navigate_from_node(item, relative_selector));
|
|
158
166
|
}
|
|
159
167
|
|
|
160
168
|
if targets.is_empty() {
|
|
@@ -162,10 +170,10 @@ impl Document {
|
|
|
162
170
|
}
|
|
163
171
|
|
|
164
172
|
if !all && targets.len() > 1 {
|
|
165
|
-
let selector = if
|
|
166
|
-
|
|
173
|
+
let selector = if container_selector.is_empty() {
|
|
174
|
+
relative_selector.to_string()
|
|
167
175
|
} else {
|
|
168
|
-
format!("{}.{}",
|
|
176
|
+
format!("{}.{}", container_selector, relative_selector)
|
|
169
177
|
};
|
|
170
178
|
|
|
171
179
|
return Err(YerbaError::AmbiguousSelector(selector, targets.len()));
|
|
@@ -179,9 +187,9 @@ impl Document {
|
|
|
179
187
|
Ok(count)
|
|
180
188
|
}
|
|
181
189
|
|
|
182
|
-
pub fn set_scalar_style(&mut self,
|
|
183
|
-
let current_node = self.navigate(
|
|
184
|
-
let scalar_token = find_scalar_token(¤t_node).ok_or_else(|| YerbaError::SelectorNotFound(
|
|
190
|
+
pub fn set_scalar_style(&mut self, selector: &str, style: &QuoteStyle) -> Result<(), YerbaError> {
|
|
191
|
+
let current_node = self.navigate(selector)?;
|
|
192
|
+
let scalar_token = find_scalar_token(¤t_node).ok_or_else(|| YerbaError::SelectorNotFound(selector.to_string()))?;
|
|
185
193
|
|
|
186
194
|
let current_kind = scalar_token.kind();
|
|
187
195
|
let target_kind = style.to_syntax_kind();
|
|
@@ -200,12 +208,15 @@ impl Document {
|
|
|
200
208
|
self.replace_token(&scalar_token, &new_text)
|
|
201
209
|
}
|
|
202
210
|
|
|
203
|
-
pub fn set_plain(&mut self,
|
|
204
|
-
self.set_with(
|
|
211
|
+
pub fn set_plain(&mut self, selector: &str, value: &str) -> Result<(), YerbaError> {
|
|
212
|
+
self.set_with(selector, value, true)
|
|
205
213
|
}
|
|
206
214
|
|
|
207
|
-
fn set_with(&mut self,
|
|
208
|
-
let current_node = self.navigate(
|
|
215
|
+
fn set_with(&mut self, selector: &str, value: &str, plain: bool) -> Result<(), YerbaError> {
|
|
216
|
+
let current_node = match self.navigate(selector) {
|
|
217
|
+
Ok(node) => node,
|
|
218
|
+
Err(error) => return self.set_valueless_entry(selector, value, plain).unwrap_or(Err(error)),
|
|
219
|
+
};
|
|
209
220
|
|
|
210
221
|
if let Some(block_scalar) = current_node.descendants().find(|node| node.kind() == SyntaxKind::BLOCK_SCALAR) {
|
|
211
222
|
if plain {
|
|
@@ -219,13 +230,13 @@ impl Document {
|
|
|
219
230
|
}
|
|
220
231
|
|
|
221
232
|
if holds_collection(¤t_node) {
|
|
222
|
-
let span = value_span(¤t_node).ok_or_else(|| YerbaError::SelectorNotFound(
|
|
233
|
+
let span = value_span(¤t_node).ok_or_else(|| YerbaError::SelectorNotFound(selector.to_string()))?;
|
|
223
234
|
let replacement = if plain { value.to_string() } else { crate::syntax::quote_scalar(value) };
|
|
224
235
|
|
|
225
236
|
return self.apply_edit(span.range, &replacement_text(&span, &replacement));
|
|
226
237
|
}
|
|
227
238
|
|
|
228
|
-
let scalar_token = find_scalar_token(¤t_node).ok_or_else(|| YerbaError::SelectorNotFound(
|
|
239
|
+
let scalar_token = find_scalar_token(¤t_node).ok_or_else(|| YerbaError::SelectorNotFound(selector.to_string()))?;
|
|
229
240
|
|
|
230
241
|
if plain {
|
|
231
242
|
return self.replace_token(&scalar_token, value);
|
|
@@ -236,6 +247,18 @@ impl Document {
|
|
|
236
247
|
self.replace_token(&scalar_token, &new_text)
|
|
237
248
|
}
|
|
238
249
|
|
|
250
|
+
fn set_valueless_entry(&mut self, selector: &str, value: &str, plain: bool) -> Option<Result<(), YerbaError>> {
|
|
251
|
+
let entry = self.find_entry(selector)?;
|
|
252
|
+
let colon = entry.children_with_tokens().find(|element| element.kind() == SyntaxKind::COLON)?;
|
|
253
|
+
let text = if plain {
|
|
254
|
+
value.to_string()
|
|
255
|
+
} else {
|
|
256
|
+
scalar_replacement_text(value, SyntaxKind::PLAIN_SCALAR)
|
|
257
|
+
};
|
|
258
|
+
|
|
259
|
+
Some(self.apply_edit(TextRange::empty(colon.text_range().end()), &format!(" {}", text)))
|
|
260
|
+
}
|
|
261
|
+
|
|
239
262
|
fn block_scalar_replacement(source: &str, block_scalar: &SyntaxNode, value: &str) -> String {
|
|
240
263
|
if value.is_empty() {
|
|
241
264
|
return "\"\"".to_string();
|
data/rust/src/document/sort.rs
CHANGED
|
@@ -1,38 +1,38 @@
|
|
|
1
1
|
use super::*;
|
|
2
2
|
|
|
3
3
|
impl Document {
|
|
4
|
-
pub fn move_item(&mut self,
|
|
4
|
+
pub fn move_item(&mut self, selector: &str, from: usize, to: usize) -> Result<(), YerbaError> {
|
|
5
5
|
if from == to {
|
|
6
6
|
return Ok(());
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
-
let current_node = self.navigate(
|
|
9
|
+
let current_node = self.navigate(selector)?;
|
|
10
10
|
|
|
11
|
-
let sequence = find_block_sequence(¤t_node).ok_or_else(|| YerbaError::NotASequence(
|
|
11
|
+
let sequence = find_block_sequence(¤t_node).ok_or_else(|| YerbaError::NotASequence(selector.to_string()))?;
|
|
12
12
|
|
|
13
13
|
let entries: Vec<_> = sequence.entries().collect();
|
|
14
14
|
|
|
15
15
|
self.reorder_entries(sequence.syntax(), &entries, from, to)
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
pub fn move_key(&mut self,
|
|
18
|
+
pub fn move_key(&mut self, selector: &str, from: usize, to: usize) -> Result<(), YerbaError> {
|
|
19
19
|
if from == to {
|
|
20
20
|
return Ok(());
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
let current_node = self.navigate(
|
|
23
|
+
let current_node = self.navigate(selector)?;
|
|
24
24
|
|
|
25
|
-
let map = find_block_map(¤t_node).ok_or_else(|| YerbaError::SelectorNotFound(
|
|
25
|
+
let map = find_block_map(¤t_node).ok_or_else(|| YerbaError::SelectorNotFound(selector.to_string()))?;
|
|
26
26
|
|
|
27
27
|
let entries: Vec<_> = map.entries().collect();
|
|
28
28
|
|
|
29
29
|
self.reorder_entries(map.syntax(), &entries, from, to)
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
pub fn resolve_key_index(&self,
|
|
33
|
-
let current_node = self.navigate(
|
|
32
|
+
pub fn resolve_key_index(&self, selector: &str, reference: &str) -> Result<usize, YerbaError> {
|
|
33
|
+
let current_node = self.navigate(selector)?;
|
|
34
34
|
|
|
35
|
-
let map = find_block_map(¤t_node).ok_or_else(|| YerbaError::SelectorNotFound(
|
|
35
|
+
let map = find_block_map(¤t_node).ok_or_else(|| YerbaError::SelectorNotFound(selector.to_string()))?;
|
|
36
36
|
|
|
37
37
|
if let Ok(index) = reference.parse::<usize>() {
|
|
38
38
|
let length = map.entries().count();
|
|
@@ -55,13 +55,13 @@ impl Document {
|
|
|
55
55
|
.unwrap_or(false)
|
|
56
56
|
})
|
|
57
57
|
.map(|(index, _entry)| index)
|
|
58
|
-
.ok_or_else(|| YerbaError::SelectorNotFound(format!("{} key '{}'",
|
|
58
|
+
.ok_or_else(|| YerbaError::SelectorNotFound(format!("{} key '{}'", selector, reference)))
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
-
pub fn resolve_sequence_index(&self,
|
|
62
|
-
let current_node = self.navigate(
|
|
61
|
+
pub fn resolve_sequence_index(&self, selector: &str, reference: &str) -> Result<usize, YerbaError> {
|
|
62
|
+
let current_node = self.navigate(selector)?;
|
|
63
63
|
|
|
64
|
-
let sequence = find_block_sequence(¤t_node).ok_or_else(|| YerbaError::NotASequence(
|
|
64
|
+
let sequence = find_block_sequence(¤t_node).ok_or_else(|| YerbaError::NotASequence(selector.to_string()))?;
|
|
65
65
|
|
|
66
66
|
if let Ok(index) = reference.parse::<usize>() {
|
|
67
67
|
let length = sequence.entries().count();
|
|
@@ -79,7 +79,7 @@ impl Document {
|
|
|
79
79
|
.enumerate()
|
|
80
80
|
.find(|(_index, entry)| self.evaluate_condition_on_node(entry.syntax(), reference))
|
|
81
81
|
.map(|(index, _entry)| index)
|
|
82
|
-
.ok_or_else(|| YerbaError::SelectorNotFound(format!("{} condition '{}'",
|
|
82
|
+
.ok_or_else(|| YerbaError::SelectorNotFound(format!("{} condition '{}'", selector, reference)));
|
|
83
83
|
}
|
|
84
84
|
|
|
85
85
|
sequence
|
|
@@ -93,15 +93,15 @@ impl Document {
|
|
|
93
93
|
.unwrap_or(false)
|
|
94
94
|
})
|
|
95
95
|
.map(|(index, _entry)| index)
|
|
96
|
-
.ok_or_else(|| YerbaError::SelectorNotFound(format!("{} item '{}'",
|
|
96
|
+
.ok_or_else(|| YerbaError::SelectorNotFound(format!("{} item '{}'", selector, reference)))
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
-
pub fn validate_sort_keys(&self,
|
|
100
|
-
if let Some(
|
|
101
|
-
return self.validate_each_sort_keys(
|
|
99
|
+
pub fn validate_sort_keys(&self, selector: &str, key_order: &[&str]) -> Result<(), YerbaError> {
|
|
100
|
+
if let Some(sequence_selector) = strip_bracket_suffix(selector) {
|
|
101
|
+
return self.validate_each_sort_keys(sequence_selector, key_order);
|
|
102
102
|
}
|
|
103
103
|
|
|
104
|
-
let current_node = match self.navigate(
|
|
104
|
+
let current_node = match self.navigate(selector) {
|
|
105
105
|
Ok(node) => node,
|
|
106
106
|
Err(_) => return Ok(()),
|
|
107
107
|
};
|
|
@@ -124,12 +124,12 @@ impl Document {
|
|
|
124
124
|
}
|
|
125
125
|
}
|
|
126
126
|
|
|
127
|
-
pub fn sort_keys(&mut self,
|
|
128
|
-
if let Some(
|
|
129
|
-
return self.sort_each_keys(
|
|
127
|
+
pub fn sort_keys(&mut self, selector: &str, key_order: &[&str]) -> Result<(), YerbaError> {
|
|
128
|
+
if let Some(sequence_selector) = strip_bracket_suffix(selector) {
|
|
129
|
+
return self.sort_each_keys(sequence_selector, key_order);
|
|
130
130
|
}
|
|
131
131
|
|
|
132
|
-
let current_node = match self.navigate(
|
|
132
|
+
let current_node = match self.navigate(selector) {
|
|
133
133
|
Ok(node) => node,
|
|
134
134
|
Err(_) => return Ok(()),
|
|
135
135
|
};
|
|
@@ -145,14 +145,14 @@ impl Document {
|
|
|
145
145
|
}
|
|
146
146
|
}
|
|
147
147
|
|
|
148
|
-
pub fn sort_each_keys(&mut self,
|
|
149
|
-
let nodes = if
|
|
150
|
-
match self.navigate(
|
|
148
|
+
pub fn sort_each_keys(&mut self, selector: &str, key_order: &[&str]) -> Result<(), YerbaError> {
|
|
149
|
+
let nodes = if selector.is_empty() {
|
|
150
|
+
match self.navigate(selector) {
|
|
151
151
|
Ok(node) => vec![node],
|
|
152
152
|
Err(_) => return Ok(()),
|
|
153
153
|
}
|
|
154
154
|
} else {
|
|
155
|
-
let found = self.navigate_all_compact(
|
|
155
|
+
let found = self.navigate_all_compact(selector);
|
|
156
156
|
if found.is_empty() {
|
|
157
157
|
return Ok(());
|
|
158
158
|
}
|
|
@@ -182,14 +182,14 @@ impl Document {
|
|
|
182
182
|
self.apply_edits(edits)
|
|
183
183
|
}
|
|
184
184
|
|
|
185
|
-
pub fn validate_each_sort_keys(&self,
|
|
186
|
-
let nodes = if
|
|
187
|
-
match self.navigate(
|
|
185
|
+
pub fn validate_each_sort_keys(&self, selector: &str, key_order: &[&str]) -> Result<(), YerbaError> {
|
|
186
|
+
let nodes = if selector.is_empty() {
|
|
187
|
+
match self.navigate(selector) {
|
|
188
188
|
Ok(node) => vec![node],
|
|
189
189
|
Err(_) => return Ok(()),
|
|
190
190
|
}
|
|
191
191
|
} else {
|
|
192
|
-
let found = self.navigate_all_compact(
|
|
192
|
+
let found = self.navigate_all_compact(selector);
|
|
193
193
|
if found.is_empty() {
|
|
194
194
|
return Ok(());
|
|
195
195
|
}
|
|
@@ -224,12 +224,12 @@ impl Document {
|
|
|
224
224
|
}
|
|
225
225
|
}
|
|
226
226
|
|
|
227
|
-
pub fn sort_items(&mut self,
|
|
228
|
-
if
|
|
229
|
-
return self.sort_each_items(
|
|
227
|
+
pub fn sort_items(&mut self, selector: &str, sort_fields: &[SortField], case_sensitive: bool) -> Result<(), YerbaError> {
|
|
228
|
+
if selector.contains("[].") {
|
|
229
|
+
return self.sort_each_items(selector, sort_fields, case_sensitive);
|
|
230
230
|
}
|
|
231
231
|
|
|
232
|
-
let current_node = self.navigate(
|
|
232
|
+
let current_node = self.navigate(selector)?;
|
|
233
233
|
|
|
234
234
|
let sequence = match find_block_sequence(¤t_node) {
|
|
235
235
|
Some(sequence) => sequence,
|
|
@@ -242,21 +242,21 @@ impl Document {
|
|
|
242
242
|
}
|
|
243
243
|
}
|
|
244
244
|
|
|
245
|
-
fn sort_each_items(&mut self,
|
|
246
|
-
let (
|
|
247
|
-
(&
|
|
245
|
+
fn sort_each_items(&mut self, selector: &str, sort_fields: &[SortField], case_sensitive: bool) -> Result<(), YerbaError> {
|
|
246
|
+
let (parent_selector, child_selector) = if let Some(last_bracket) = selector.rfind("[].") {
|
|
247
|
+
(&selector[..last_bracket + 2], &selector[last_bracket + 3..])
|
|
248
248
|
} else {
|
|
249
|
-
(
|
|
249
|
+
(selector, "")
|
|
250
250
|
};
|
|
251
251
|
|
|
252
|
-
let parent_nodes = self.navigate_all_compact(
|
|
252
|
+
let parent_nodes = self.navigate_all_compact(parent_selector);
|
|
253
253
|
let mut edits: Vec<(TextRange, String)> = Vec::new();
|
|
254
254
|
|
|
255
255
|
for parent_node in &parent_nodes {
|
|
256
|
-
let child_nodes = if
|
|
256
|
+
let child_nodes = if child_selector.is_empty() {
|
|
257
257
|
vec![parent_node.clone()]
|
|
258
258
|
} else {
|
|
259
|
-
navigate_from_node(parent_node,
|
|
259
|
+
navigate_from_node(parent_node, child_selector)
|
|
260
260
|
};
|
|
261
261
|
|
|
262
262
|
for child_node in &child_nodes {
|
|
@@ -274,20 +274,20 @@ impl Document {
|
|
|
274
274
|
self.apply_edits(edits)
|
|
275
275
|
}
|
|
276
276
|
|
|
277
|
-
pub fn reorder_items(&mut self,
|
|
277
|
+
pub fn reorder_items(&mut self, selector: &str, by: &str, desired_order: &[&str]) -> Result<(), YerbaError> {
|
|
278
278
|
let field = by.strip_prefix('.').unwrap_or(by);
|
|
279
279
|
let is_scalar = field.is_empty() || field == ".";
|
|
280
280
|
|
|
281
281
|
let items_selector = if is_scalar {
|
|
282
|
-
if
|
|
282
|
+
if selector.is_empty() {
|
|
283
283
|
"[]".to_string()
|
|
284
284
|
} else {
|
|
285
|
-
format!("{}[]",
|
|
285
|
+
format!("{}[]", selector)
|
|
286
286
|
}
|
|
287
|
-
} else if
|
|
287
|
+
} else if selector.is_empty() {
|
|
288
288
|
format!("[].{}", field)
|
|
289
289
|
} else {
|
|
290
|
-
format!("{}[].{}",
|
|
290
|
+
format!("{}[].{}", selector, field)
|
|
291
291
|
};
|
|
292
292
|
|
|
293
293
|
let labels: Vec<String> = match self.get_value(&items_selector) {
|
|
@@ -332,7 +332,7 @@ impl Document {
|
|
|
332
332
|
let source = moves[target];
|
|
333
333
|
|
|
334
334
|
if source != target {
|
|
335
|
-
self.move_item(
|
|
335
|
+
self.move_item(selector, source, target)?;
|
|
336
336
|
|
|
337
337
|
for item in moves.iter_mut().skip(target + 1) {
|
|
338
338
|
if *item >= target && *item < source {
|
|
@@ -439,10 +439,10 @@ fn entry_sort_values(entry: &yaml_parser::ast::BlockSeqEntry, sort_fields: &[Sor
|
|
|
439
439
|
sort_fields
|
|
440
440
|
.iter()
|
|
441
441
|
.map(|field| {
|
|
442
|
-
if field.
|
|
442
|
+
if field.selector.is_empty() {
|
|
443
443
|
scalar_value()
|
|
444
444
|
} else {
|
|
445
|
-
let nodes = navigate_from_node(entry.syntax(), &field.
|
|
445
|
+
let nodes = navigate_from_node(entry.syntax(), &field.selector);
|
|
446
446
|
nodes.first().and_then(extract_scalar_text).unwrap_or_default()
|
|
447
447
|
}
|
|
448
448
|
})
|
|
@@ -474,12 +474,12 @@ fn compare_sort_values(values_a: &[String], values_b: &[String], sort_fields: &[
|
|
|
474
474
|
std::cmp::Ordering::Equal
|
|
475
475
|
}
|
|
476
476
|
|
|
477
|
-
fn strip_bracket_suffix(
|
|
478
|
-
if
|
|
477
|
+
fn strip_bracket_suffix(selector: &str) -> Option<&str> {
|
|
478
|
+
if selector == "[]" {
|
|
479
479
|
Some("")
|
|
480
|
-
} else if let Some(stripped) =
|
|
480
|
+
} else if let Some(stripped) = selector.strip_suffix(".[]") {
|
|
481
481
|
Some(stripped)
|
|
482
482
|
} else {
|
|
483
|
-
|
|
483
|
+
selector.strip_suffix("[]")
|
|
484
484
|
}
|
|
485
485
|
}
|
data/rust/src/document/style.rs
CHANGED
|
@@ -49,10 +49,7 @@ impl Document {
|
|
|
49
49
|
if let Some(ref entry) = entry_node {
|
|
50
50
|
let entry_start: usize = entry.text_range().start().into();
|
|
51
51
|
let key_indent = column_at(&source, entry_start);
|
|
52
|
-
let
|
|
53
|
-
|
|
54
|
-
if let Some(colon_offset) = entry_text.find(':') {
|
|
55
|
-
let colon_position = entry_start + colon_offset;
|
|
52
|
+
if let Some(colon_position) = entry_colon_position(entry) {
|
|
56
53
|
let value_indent = key_indent + 2;
|
|
57
54
|
let block_text = crate::yaml_writer::yaml_value_to_block_text(&value, value_indent);
|
|
58
55
|
let replace_range = TextRange::new(rowan::TextSize::from((colon_position + 1) as u32), node.text_range().end());
|
|
@@ -212,11 +209,11 @@ impl Document {
|
|
|
212
209
|
self.apply_edits(edits)
|
|
213
210
|
}
|
|
214
211
|
|
|
215
|
-
pub fn enforce_collection_style(&mut self, style: &str,
|
|
216
|
-
let
|
|
212
|
+
pub fn enforce_collection_style(&mut self, style: &str, selector: Option<&str>) -> Result<(), YerbaError> {
|
|
213
|
+
let scope_selector = selector.unwrap_or("");
|
|
217
214
|
|
|
218
|
-
if
|
|
219
|
-
let concrete_selectors = self.resolve_selectors(
|
|
215
|
+
if scope_selector.contains("[]") {
|
|
216
|
+
let concrete_selectors = self.resolve_selectors(scope_selector);
|
|
220
217
|
|
|
221
218
|
for selector in concrete_selectors.iter().rev() {
|
|
222
219
|
self.enforce_collection_style(style, Some(selector))?;
|
|
@@ -246,18 +243,18 @@ impl Document {
|
|
|
246
243
|
}
|
|
247
244
|
}
|
|
248
245
|
|
|
249
|
-
let value = match self.get_value(
|
|
246
|
+
let value = match self.get_value(scope_selector) {
|
|
250
247
|
Some(value) => value,
|
|
251
248
|
None => return Ok(()),
|
|
252
249
|
};
|
|
253
250
|
|
|
254
251
|
let mut selectors = Vec::new();
|
|
255
252
|
|
|
256
|
-
if !
|
|
257
|
-
selectors.push(
|
|
253
|
+
if !scope_selector.is_empty() {
|
|
254
|
+
selectors.push(scope_selector.to_string());
|
|
258
255
|
}
|
|
259
256
|
|
|
260
|
-
collect_selectors(&value,
|
|
257
|
+
collect_selectors(&value, scope_selector, &mut selectors);
|
|
261
258
|
|
|
262
259
|
let mut collection_selectors: Vec<String> = selectors
|
|
263
260
|
.into_iter()
|
|
@@ -273,11 +270,11 @@ impl Document {
|
|
|
273
270
|
Ok(())
|
|
274
271
|
}
|
|
275
272
|
|
|
276
|
-
pub fn enforce_sequence_indent(&mut self, style: &str,
|
|
277
|
-
let
|
|
273
|
+
pub fn enforce_sequence_indent(&mut self, style: &str, selector: Option<&str>) -> Result<(), YerbaError> {
|
|
274
|
+
let scope_selector = selector.unwrap_or("");
|
|
278
275
|
|
|
279
|
-
if
|
|
280
|
-
let concrete_selectors = self.resolve_selectors(
|
|
276
|
+
if scope_selector.contains("[]") {
|
|
277
|
+
let concrete_selectors = self.resolve_selectors(scope_selector);
|
|
281
278
|
|
|
282
279
|
for selector in concrete_selectors.iter().rev() {
|
|
283
280
|
self.enforce_sequence_indent(style, Some(selector))?;
|
|
@@ -286,10 +283,10 @@ impl Document {
|
|
|
286
283
|
return Ok(());
|
|
287
284
|
}
|
|
288
285
|
|
|
289
|
-
let scope_node = if
|
|
286
|
+
let scope_node = if scope_selector.is_empty() {
|
|
290
287
|
self.root.clone()
|
|
291
288
|
} else {
|
|
292
|
-
match self.navigate(
|
|
289
|
+
match self.navigate(scope_selector) {
|
|
293
290
|
Ok(node) => node,
|
|
294
291
|
Err(_) => return Ok(()),
|
|
295
292
|
}
|
|
@@ -333,10 +330,10 @@ impl Document {
|
|
|
333
330
|
loop {
|
|
334
331
|
let source = self.source_text();
|
|
335
332
|
|
|
336
|
-
let scope_node = if
|
|
333
|
+
let scope_node = if scope_selector.is_empty() {
|
|
337
334
|
self.root.clone()
|
|
338
335
|
} else {
|
|
339
|
-
match self.navigate(
|
|
336
|
+
match self.navigate(scope_selector) {
|
|
340
337
|
Ok(node) => node,
|
|
341
338
|
Err(_) => return Ok(()),
|
|
342
339
|
}
|
|
@@ -437,10 +434,10 @@ impl Document {
|
|
|
437
434
|
}
|
|
438
435
|
}
|
|
439
436
|
|
|
440
|
-
pub fn set_sequence_indent(&mut self,
|
|
437
|
+
pub fn set_sequence_indent(&mut self, selector: &str, style: &str) -> Result<(), YerbaError> {
|
|
441
438
|
let current_style = self
|
|
442
|
-
.get_sequence_indent(
|
|
443
|
-
.ok_or_else(|| YerbaError::ParseError(format!("'{}' is not a block sequence",
|
|
439
|
+
.get_sequence_indent(selector)
|
|
440
|
+
.ok_or_else(|| YerbaError::ParseError(format!("'{}' is not a block sequence", selector)))?;
|
|
444
441
|
|
|
445
442
|
if current_style == style {
|
|
446
443
|
return Ok(());
|
|
@@ -453,7 +450,7 @@ impl Document {
|
|
|
453
450
|
)));
|
|
454
451
|
}
|
|
455
452
|
|
|
456
|
-
let current_node = self.navigate(
|
|
453
|
+
let current_node = self.navigate(selector)?;
|
|
457
454
|
let source = self.source_text();
|
|
458
455
|
|
|
459
456
|
let entry_node = current_node
|
|
@@ -510,16 +507,16 @@ impl Document {
|
|
|
510
507
|
self.apply_edit(replace_range, &reindented)
|
|
511
508
|
}
|
|
512
509
|
|
|
513
|
-
pub fn set_collection_style(&mut self,
|
|
510
|
+
pub fn set_collection_style(&mut self, selector: &str, style: &str) -> Result<(), YerbaError> {
|
|
514
511
|
let current_style = self
|
|
515
|
-
.get_collection_style(
|
|
516
|
-
.ok_or_else(|| YerbaError::ParseError(format!("'{}' is not a collection (sequence or map)",
|
|
512
|
+
.get_collection_style(selector)
|
|
513
|
+
.ok_or_else(|| YerbaError::ParseError(format!("'{}' is not a collection (sequence or map)", selector)))?;
|
|
517
514
|
|
|
518
515
|
if current_style == style {
|
|
519
516
|
return Ok(());
|
|
520
517
|
}
|
|
521
518
|
|
|
522
|
-
let current_node = self.navigate(
|
|
519
|
+
let current_node = self.navigate(selector)?;
|
|
523
520
|
let value = node_to_yaml_value(¤t_node);
|
|
524
521
|
|
|
525
522
|
match &value {
|
|
@@ -536,10 +533,7 @@ impl Document {
|
|
|
536
533
|
let entry_start: usize = entry.text_range().start().into();
|
|
537
534
|
let indent = column_at(&source, entry_start);
|
|
538
535
|
|
|
539
|
-
|
|
540
|
-
let colon_offset = entry_text.find(':').map(|offset| entry_start + offset);
|
|
541
|
-
|
|
542
|
-
(indent, colon_offset)
|
|
536
|
+
(indent, entry_colon_position(entry))
|
|
543
537
|
} else {
|
|
544
538
|
(0, None)
|
|
545
539
|
};
|
|
@@ -594,15 +588,15 @@ impl Document {
|
|
|
594
588
|
}
|
|
595
589
|
}
|
|
596
590
|
|
|
597
|
-
pub fn enforce_blank_lines(&mut self,
|
|
598
|
-
self.enforce_blank_lines_with(
|
|
591
|
+
pub fn enforce_blank_lines(&mut self, selector: &str, blank_lines: usize) -> Result<(), YerbaError> {
|
|
592
|
+
self.enforce_blank_lines_with(selector, blank_lines, &BlankLineOptions::default())
|
|
599
593
|
}
|
|
600
594
|
|
|
601
|
-
pub fn enforce_blank_lines_with(&mut self,
|
|
602
|
-
let nodes = if
|
|
603
|
-
self.navigate_all_compact(
|
|
595
|
+
pub fn enforce_blank_lines_with(&mut self, selector: &str, blank_lines: usize, options: &BlankLineOptions) -> Result<(), YerbaError> {
|
|
596
|
+
let nodes = if selector.contains('[') {
|
|
597
|
+
self.navigate_all_compact(selector)
|
|
604
598
|
} else {
|
|
605
|
-
vec![self.navigate(
|
|
599
|
+
vec![self.navigate(selector)?]
|
|
606
600
|
};
|
|
607
601
|
|
|
608
602
|
let mut edits: Vec<(TextRange, String)> = Vec::new();
|
|
@@ -666,7 +660,7 @@ impl Document {
|
|
|
666
660
|
.map(|element| {
|
|
667
661
|
let offset: usize = element.text_range().start().into();
|
|
668
662
|
|
|
669
|
-
(line_at(&source, offset), column_at(&source, offset)
|
|
663
|
+
(line_at(&source, offset), column_at(&source, offset))
|
|
670
664
|
})
|
|
671
665
|
.collect()
|
|
672
666
|
}
|
|
@@ -709,9 +703,9 @@ impl Document {
|
|
|
709
703
|
}
|
|
710
704
|
}
|
|
711
705
|
|
|
712
|
-
pub fn enforce_key_style(&mut self, style: &crate::KeyStyle,
|
|
713
|
-
let scope_ranges: Vec<TextRange> = match
|
|
714
|
-
Some(
|
|
706
|
+
pub fn enforce_key_style(&mut self, style: &crate::KeyStyle, selector: Option<&str>) -> Result<(), YerbaError> {
|
|
707
|
+
let scope_ranges: Vec<TextRange> = match selector {
|
|
708
|
+
Some(scope) if !scope.is_empty() => self.navigate_all_compact(scope).iter().map(|node| node.text_range()).collect(),
|
|
715
709
|
_ => vec![self.root.text_range()],
|
|
716
710
|
};
|
|
717
711
|
|
|
@@ -779,9 +773,9 @@ impl Document {
|
|
|
779
773
|
self.enforce_quotes_at(style, None)
|
|
780
774
|
}
|
|
781
775
|
|
|
782
|
-
pub fn decode_escapes(&mut self,
|
|
783
|
-
let scope_ranges: Vec<TextRange> = match
|
|
784
|
-
Some(
|
|
776
|
+
pub fn decode_escapes(&mut self, selector: Option<&str>) -> Result<usize, YerbaError> {
|
|
777
|
+
let scope_ranges: Vec<TextRange> = match selector {
|
|
778
|
+
Some(scope) if !scope.is_empty() => self.navigate_all_compact(scope).iter().map(|node| node.text_range()).collect(),
|
|
785
779
|
_ => vec![self.root.text_range()],
|
|
786
780
|
};
|
|
787
781
|
|
|
@@ -814,11 +808,11 @@ impl Document {
|
|
|
814
808
|
Ok(count)
|
|
815
809
|
}
|
|
816
810
|
|
|
817
|
-
pub fn enforce_quotes_at(&mut self, style: &QuoteStyle,
|
|
811
|
+
pub fn enforce_quotes_at(&mut self, style: &QuoteStyle, selector: Option<&str>) -> Result<Vec<String>, YerbaError> {
|
|
818
812
|
let source = self.source_text();
|
|
819
813
|
|
|
820
|
-
let scope_ranges: Vec<TextRange> = match
|
|
821
|
-
Some(
|
|
814
|
+
let scope_ranges: Vec<TextRange> = match selector {
|
|
815
|
+
Some(scope) if !scope.is_empty() => self.navigate_all_compact(scope).iter().map(|node| node.text_range()).collect(),
|
|
822
816
|
_ => vec![self.root.text_range()],
|
|
823
817
|
};
|
|
824
818
|
|
|
@@ -869,7 +863,7 @@ impl Document {
|
|
|
869
863
|
}
|
|
870
864
|
|
|
871
865
|
if is_block_scalar_text && !is_block_scalar_target {
|
|
872
|
-
if
|
|
866
|
+
if selector.is_none() || selector == Some("") {
|
|
873
867
|
continue;
|
|
874
868
|
}
|
|
875
869
|
|
|
@@ -1075,3 +1069,10 @@ fn inline_quote_replacement(raw_value: &str, current_kind: SyntaxKind, style: &Q
|
|
|
1075
1069
|
_ => None,
|
|
1076
1070
|
}
|
|
1077
1071
|
}
|
|
1072
|
+
|
|
1073
|
+
fn entry_colon_position(entry: &SyntaxNode) -> Option<usize> {
|
|
1074
|
+
entry
|
|
1075
|
+
.children_with_tokens()
|
|
1076
|
+
.find(|element| element.kind() == SyntaxKind::COLON)
|
|
1077
|
+
.map(|colon| colon.text_range().start().into())
|
|
1078
|
+
}
|