yerba 0.9.2-arm-linux-gnu → 0.10.1-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 +53 -17
- data/exe/arm-linux-gnu/yerba +0 -0
- data/ext/yerba/include/yerba.h +58 -35
- data/ext/yerba/yerba.c +281 -187
- 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/commands/sort.rs +5 -1
- 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 +202 -76
- 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 +105 -60
- 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 +234 -107
- data/rust/src/json.rs +62 -2
- data/rust/src/lib.rs +4 -2
- 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 +168 -94
- metadata +3 -2
data/rust/src/document/delete.rs
CHANGED
|
@@ -1,70 +1,72 @@
|
|
|
1
1
|
use super::*;
|
|
2
2
|
|
|
3
3
|
impl Document {
|
|
4
|
-
pub fn rename(&mut self,
|
|
5
|
-
Self::
|
|
6
|
-
Self::
|
|
4
|
+
pub fn rename(&mut self, source_selector: &str, destination_selector: &str) -> Result<(), YerbaError> {
|
|
5
|
+
Self::validate_selector(source_selector)?;
|
|
6
|
+
Self::validate_selector(destination_selector)?;
|
|
7
7
|
|
|
8
|
-
let source_parent =
|
|
9
|
-
let destination_parent =
|
|
10
|
-
let destination_key =
|
|
8
|
+
let source_parent = source_selector.rsplit_once('.').map(|(parent, _)| parent).unwrap_or("");
|
|
9
|
+
let destination_parent = destination_selector.rsplit_once('.').map(|(parent, _)| parent).unwrap_or("");
|
|
10
|
+
let destination_key = destination_selector.rsplit_once('.').map(|(_, key)| key).unwrap_or(destination_selector);
|
|
11
11
|
|
|
12
12
|
if source_parent == destination_parent {
|
|
13
|
-
let (
|
|
13
|
+
let (parent_selector, source_key) = source_selector.rsplit_once('.').unwrap_or(("", source_selector));
|
|
14
14
|
|
|
15
|
-
let parent_node = self.navigate(
|
|
16
|
-
let map = find_block_map(&parent_node).ok_or_else(|| YerbaError::SelectorNotFound(
|
|
15
|
+
let parent_node = self.navigate(parent_selector)?;
|
|
16
|
+
let map = find_block_map(&parent_node).ok_or_else(|| YerbaError::SelectorNotFound(source_selector.to_string()))?;
|
|
17
17
|
|
|
18
|
-
let entry = find_entry_by_key(&map, source_key).ok_or_else(|| YerbaError::SelectorNotFound(
|
|
19
|
-
let key_node = entry.key().ok_or_else(|| YerbaError::SelectorNotFound(
|
|
20
|
-
let key_token = find_scalar_token(key_node.syntax()).ok_or_else(|| YerbaError::SelectorNotFound(
|
|
18
|
+
let entry = find_entry_by_key(&map, source_key).ok_or_else(|| YerbaError::SelectorNotFound(source_selector.to_string()))?;
|
|
19
|
+
let key_node = entry.key().ok_or_else(|| YerbaError::SelectorNotFound(source_selector.to_string()))?;
|
|
20
|
+
let key_token = find_scalar_token(key_node.syntax()).ok_or_else(|| YerbaError::SelectorNotFound(source_selector.to_string()))?;
|
|
21
21
|
let new_text = format_scalar_value(destination_key, key_token.kind());
|
|
22
22
|
|
|
23
23
|
self.replace_token(&key_token, &new_text)
|
|
24
24
|
} else {
|
|
25
|
-
let value = self
|
|
25
|
+
let value = self
|
|
26
|
+
.get(source_selector)
|
|
27
|
+
.ok_or_else(|| YerbaError::SelectorNotFound(source_selector.to_string()))?;
|
|
26
28
|
|
|
27
|
-
self.delete(
|
|
28
|
-
self.insert_into(
|
|
29
|
+
self.delete(source_selector)?;
|
|
30
|
+
self.insert_into(destination_selector, &value, InsertPosition::Last)
|
|
29
31
|
}
|
|
30
32
|
}
|
|
31
33
|
|
|
32
|
-
pub fn delete(&mut self,
|
|
33
|
-
Self::
|
|
34
|
-
self.refuse_flow_target(
|
|
34
|
+
pub fn delete(&mut self, selector: &str) -> Result<(), YerbaError> {
|
|
35
|
+
Self::validate_selector(selector)?;
|
|
36
|
+
self.refuse_flow_target(selector)?;
|
|
35
37
|
|
|
36
|
-
let
|
|
37
|
-
let segments =
|
|
38
|
-
let last_segment = segments.last().ok_or_else(|| YerbaError::SelectorNotFound(
|
|
39
|
-
let
|
|
38
|
+
let parsed = crate::selector::Selector::parse(selector);
|
|
39
|
+
let segments = parsed.segments();
|
|
40
|
+
let last_segment = segments.last().ok_or_else(|| YerbaError::SelectorNotFound(selector.to_string()))?;
|
|
41
|
+
let parent_selector = parsed.parent_selector();
|
|
40
42
|
|
|
41
43
|
match last_segment {
|
|
42
44
|
crate::selector::SelectorSegment::Key(last_key) => {
|
|
43
|
-
let has_wildcard =
|
|
44
|
-
let has_brackets =
|
|
45
|
+
let has_wildcard = parsed.has_wildcard();
|
|
46
|
+
let has_brackets = parsed.has_brackets();
|
|
45
47
|
|
|
46
|
-
if
|
|
47
|
-
let parent_node = self.navigate(&
|
|
48
|
-
let map = find_block_map(&parent_node).ok_or_else(|| YerbaError::SelectorNotFound(
|
|
48
|
+
if parent_selector.is_empty() && (!has_wildcard || !has_brackets) {
|
|
49
|
+
let parent_node = self.navigate(&parent_selector)?;
|
|
50
|
+
let map = find_block_map(&parent_node).ok_or_else(|| YerbaError::SelectorNotFound(selector.to_string()))?;
|
|
49
51
|
|
|
50
|
-
let entry = find_entry_by_key(&map, last_key).ok_or_else(|| YerbaError::SelectorNotFound(
|
|
52
|
+
let entry = find_entry_by_key(&map, last_key).ok_or_else(|| YerbaError::SelectorNotFound(selector.to_string()))?;
|
|
51
53
|
|
|
52
54
|
return self.remove_map_entry(&entry);
|
|
53
55
|
}
|
|
54
56
|
|
|
55
|
-
let parent_nodes = self.navigate_all_compact(&
|
|
57
|
+
let parent_nodes = self.navigate_all_compact(&parent_selector);
|
|
56
58
|
|
|
57
59
|
if parent_nodes.is_empty() {
|
|
58
60
|
if has_wildcard {
|
|
59
61
|
return Ok(());
|
|
60
62
|
}
|
|
61
63
|
|
|
62
|
-
return Err(YerbaError::SelectorNotFound(
|
|
64
|
+
return Err(YerbaError::SelectorNotFound(selector.to_string()));
|
|
63
65
|
}
|
|
64
66
|
|
|
65
67
|
if parent_nodes.len() == 1 && (!has_wildcard || !has_brackets) {
|
|
66
|
-
let map = find_block_map(&parent_nodes[0]).ok_or_else(|| YerbaError::SelectorNotFound(
|
|
67
|
-
let entry = find_entry_by_key(&map, last_key).ok_or_else(|| YerbaError::SelectorNotFound(
|
|
68
|
+
let map = find_block_map(&parent_nodes[0]).ok_or_else(|| YerbaError::SelectorNotFound(selector.to_string()))?;
|
|
69
|
+
let entry = find_entry_by_key(&map, last_key).ok_or_else(|| YerbaError::SelectorNotFound(selector.to_string()))?;
|
|
68
70
|
|
|
69
71
|
if map.entries().count() == 1 {
|
|
70
72
|
return self.collapse_to_empty_flow_map(&parent_nodes[0]);
|
|
@@ -88,19 +90,31 @@ impl Document {
|
|
|
88
90
|
self.apply_edits(edits)
|
|
89
91
|
}
|
|
90
92
|
|
|
91
|
-
crate::selector::SelectorSegment::Index(index) => self.remove_at(&
|
|
92
|
-
crate::selector::SelectorSegment::
|
|
93
|
+
crate::selector::SelectorSegment::Index(index) => self.remove_at(&parent_selector, *index),
|
|
94
|
+
crate::selector::SelectorSegment::IndexFromEnd(_) => {
|
|
95
|
+
let parent_node = self.navigate(&parent_selector)?;
|
|
96
|
+
let length = find_block_sequence(&parent_node)
|
|
97
|
+
.map(|sequence| sequence.entries().count())
|
|
98
|
+
.or_else(|| find_flow_sequence(&parent_node).map(|sequence| flow_sequence_entries(&sequence).len()))
|
|
99
|
+
.ok_or_else(|| YerbaError::NotASequence(parent_selector.clone()))?;
|
|
100
|
+
let index = last_segment
|
|
101
|
+
.sequence_index(length)
|
|
102
|
+
.ok_or_else(|| YerbaError::SelectorNotFound(selector.to_string()))?;
|
|
103
|
+
|
|
104
|
+
self.remove_at(&parent_selector, index)
|
|
105
|
+
}
|
|
106
|
+
crate::selector::SelectorSegment::AllItems | crate::selector::SelectorSegment::AllKeys => Err(YerbaError::SelectorNotFound(selector.to_string())),
|
|
93
107
|
}
|
|
94
108
|
}
|
|
95
109
|
|
|
96
|
-
pub fn remove(&mut self,
|
|
97
|
-
let current_node = self.navigate(
|
|
110
|
+
pub fn remove(&mut self, selector: &str, value: &str) -> Result<(), YerbaError> {
|
|
111
|
+
let current_node = self.navigate(selector)?;
|
|
98
112
|
|
|
99
113
|
if find_flow_sequence(¤t_node).is_some() {
|
|
100
|
-
return Err(YerbaError::FlowCollectionNotWritable(
|
|
114
|
+
return Err(YerbaError::FlowCollectionNotWritable(selector.to_string()));
|
|
101
115
|
}
|
|
102
116
|
|
|
103
|
-
let sequence = find_block_sequence(¤t_node).ok_or_else(|| YerbaError::NotASequence(
|
|
117
|
+
let sequence = find_block_sequence(¤t_node).ok_or_else(|| YerbaError::NotASequence(selector.to_string()))?;
|
|
104
118
|
|
|
105
119
|
let target_entry = sequence
|
|
106
120
|
.entries()
|
|
@@ -111,7 +125,7 @@ impl Document {
|
|
|
111
125
|
.map(|text| text == value)
|
|
112
126
|
.unwrap_or(false)
|
|
113
127
|
})
|
|
114
|
-
.ok_or_else(|| YerbaError::SelectorNotFound(format!("{} item '{}'",
|
|
128
|
+
.ok_or_else(|| YerbaError::SelectorNotFound(format!("{} item '{}'", selector, value)))?;
|
|
115
129
|
|
|
116
130
|
if sequence.entries().count() == 1 {
|
|
117
131
|
return self.collapse_to_empty_flow_sequence(¤t_node);
|
|
@@ -120,12 +134,12 @@ impl Document {
|
|
|
120
134
|
self.remove_node(target_entry.syntax())
|
|
121
135
|
}
|
|
122
136
|
|
|
123
|
-
pub fn remove_at(&mut self,
|
|
124
|
-
Self::
|
|
137
|
+
pub fn remove_at(&mut self, selector: &str, index: usize) -> Result<(), YerbaError> {
|
|
138
|
+
Self::validate_selector(selector)?;
|
|
125
139
|
|
|
126
|
-
let current_node = self.navigate(
|
|
140
|
+
let current_node = self.navigate(selector)?;
|
|
127
141
|
|
|
128
|
-
let sequence = find_block_sequence(¤t_node).ok_or_else(|| YerbaError::NotASequence(
|
|
142
|
+
let sequence = find_block_sequence(¤t_node).ok_or_else(|| YerbaError::NotASequence(selector.to_string()))?;
|
|
129
143
|
|
|
130
144
|
let entries: Vec<_> = sequence.entries().collect();
|
|
131
145
|
|
data/rust/src/document/get.rs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
use super::*;
|
|
2
2
|
|
|
3
|
-
fn key_of(node: &SyntaxNode,
|
|
3
|
+
fn key_of(node: &SyntaxNode, index: &LineIndex) -> (Option<String>, Location) {
|
|
4
4
|
node
|
|
5
5
|
.parent()
|
|
6
6
|
.and_then(|parent| {
|
|
@@ -13,7 +13,7 @@ fn key_of(node: &SyntaxNode, source: &str) -> (Option<String>, Location) {
|
|
|
13
13
|
|
|
14
14
|
let key_text = extract_scalar_text(&key_node)?;
|
|
15
15
|
let key_range = key_node.text_range();
|
|
16
|
-
let key_location = compute_location(
|
|
16
|
+
let key_location = compute_location(index, key_range.start().into(), key_range.end().into());
|
|
17
17
|
|
|
18
18
|
Some((key_text, key_location))
|
|
19
19
|
})
|
|
@@ -22,30 +22,39 @@ fn key_of(node: &SyntaxNode, source: &str) -> (Option<String>, Location) {
|
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
impl Document {
|
|
25
|
-
pub fn is_valid_selector(&self,
|
|
26
|
-
if
|
|
25
|
+
pub fn is_valid_selector(&self, selector: &str) -> bool {
|
|
26
|
+
if selector.is_empty() {
|
|
27
27
|
return true;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
let selectors = self.selectors();
|
|
31
31
|
|
|
32
|
-
if selectors.contains(&
|
|
32
|
+
if selectors.contains(&selector.to_string()) {
|
|
33
33
|
return true;
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
if crate::selector::Selector::parse(
|
|
36
|
+
if crate::selector::Selector::parse(selector).has_wildcard() && !self.navigate_all_compact(selector).is_empty() {
|
|
37
37
|
return true;
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
let wildcard_version =
|
|
40
|
+
let wildcard_version = selector.replace(|c: char| c.is_ascii_digit(), "").replace("[.", "[");
|
|
41
41
|
|
|
42
42
|
let mut normalized = String::new();
|
|
43
|
-
let mut chars =
|
|
43
|
+
let mut chars = selector.chars().peekable();
|
|
44
44
|
|
|
45
45
|
while let Some(char) = chars.next() {
|
|
46
46
|
if char == '[' {
|
|
47
47
|
normalized.push('[');
|
|
48
48
|
|
|
49
|
+
if chars.peek() == Some(&'-') {
|
|
50
|
+
let mut lookahead = chars.clone();
|
|
51
|
+
lookahead.next();
|
|
52
|
+
|
|
53
|
+
if lookahead.peek().map(|char| char.is_ascii_digit()).unwrap_or(false) {
|
|
54
|
+
chars.next();
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
49
58
|
while chars.peek().map(|char| char.is_ascii_digit()).unwrap_or(false) {
|
|
50
59
|
chars.next();
|
|
51
60
|
}
|
|
@@ -57,26 +66,26 @@ impl Document {
|
|
|
57
66
|
selectors.contains(&normalized) || selectors.contains(&wildcard_version)
|
|
58
67
|
}
|
|
59
68
|
|
|
60
|
-
pub fn get(&self,
|
|
61
|
-
if
|
|
62
|
-
return self.get_all(
|
|
69
|
+
pub fn get(&self, selector: &str) -> Option<String> {
|
|
70
|
+
if selector.contains('[') {
|
|
71
|
+
return self.get_all(selector).into_iter().next();
|
|
63
72
|
}
|
|
64
73
|
|
|
65
|
-
let current_node = self.navigate(
|
|
74
|
+
let current_node = self.navigate(selector).ok()?;
|
|
66
75
|
|
|
67
76
|
extract_scalar_text(¤t_node)
|
|
68
77
|
}
|
|
69
78
|
|
|
70
|
-
pub fn get_all(&self,
|
|
71
|
-
self.navigate_all_compact(
|
|
79
|
+
pub fn get_all(&self, selector: &str) -> Vec<String> {
|
|
80
|
+
self.navigate_all_compact(selector).iter().filter_map(extract_scalar_text).collect()
|
|
72
81
|
}
|
|
73
82
|
|
|
74
|
-
pub fn get_typed(&self,
|
|
75
|
-
if crate::selector::Selector::parse(
|
|
76
|
-
return self.get_all_typed(
|
|
83
|
+
pub fn get_typed(&self, selector: &str) -> Option<ScalarValue> {
|
|
84
|
+
if crate::selector::Selector::parse(selector).has_wildcard() {
|
|
85
|
+
return self.get_all_typed(selector).into_iter().next();
|
|
77
86
|
}
|
|
78
87
|
|
|
79
|
-
let current_node = self.navigate(
|
|
88
|
+
let current_node = self.navigate(selector).ok()?;
|
|
80
89
|
|
|
81
90
|
if current_node.descendants().any(|child| {
|
|
82
91
|
matches!(
|
|
@@ -90,9 +99,9 @@ impl Document {
|
|
|
90
99
|
extract_scalar(¤t_node)
|
|
91
100
|
}
|
|
92
101
|
|
|
93
|
-
pub fn get_all_typed(&self,
|
|
102
|
+
pub fn get_all_typed(&self, selector: &str) -> Vec<ScalarValue> {
|
|
94
103
|
self
|
|
95
|
-
.navigate_all_compact(
|
|
104
|
+
.navigate_all_compact(selector)
|
|
96
105
|
.iter()
|
|
97
106
|
.filter(|node| {
|
|
98
107
|
!node
|
|
@@ -103,15 +112,15 @@ impl Document {
|
|
|
103
112
|
.collect()
|
|
104
113
|
}
|
|
105
114
|
|
|
106
|
-
pub fn resolve_selectors(&self,
|
|
107
|
-
self.navigate_all_compact(
|
|
115
|
+
pub fn resolve_selectors(&self, selector: &str) -> Vec<String> {
|
|
116
|
+
self.navigate_all_compact(selector).iter().map(node_selector).collect()
|
|
108
117
|
}
|
|
109
118
|
|
|
110
|
-
pub fn keys_at(&self,
|
|
111
|
-
let node = if
|
|
119
|
+
pub fn keys_at(&self, selector: &str) -> Vec<String> {
|
|
120
|
+
let node = if selector.is_empty() {
|
|
112
121
|
self.root.clone()
|
|
113
122
|
} else {
|
|
114
|
-
match self.navigate_all_compact(
|
|
123
|
+
match self.navigate_all_compact(selector).into_iter().next() {
|
|
115
124
|
Some(node) => node,
|
|
116
125
|
None => return Vec::new(),
|
|
117
126
|
}
|
|
@@ -150,19 +159,19 @@ impl Document {
|
|
|
150
159
|
Vec::new()
|
|
151
160
|
}
|
|
152
161
|
|
|
153
|
-
pub fn get_all_located(&self,
|
|
154
|
-
let
|
|
162
|
+
pub fn get_all_located(&self, selector: &str) -> Vec<LocatedNode> {
|
|
163
|
+
let index = self.line_index();
|
|
155
164
|
let file_path = self.path.as_ref().map(|p| p.to_string_lossy().to_string());
|
|
156
165
|
|
|
157
166
|
self
|
|
158
|
-
.navigate_all_compact(
|
|
167
|
+
.navigate_all_compact(selector)
|
|
159
168
|
.iter()
|
|
160
169
|
.map(|node| {
|
|
161
170
|
let range = node.text_range();
|
|
162
171
|
let offset: usize = range.start().into();
|
|
163
|
-
let line = line_at(
|
|
164
|
-
let location = compute_location(
|
|
165
|
-
let
|
|
172
|
+
let line = index.line_at(offset);
|
|
173
|
+
let location = compute_location(index, offset, range.end().into());
|
|
174
|
+
let item_selector = node_selector(node);
|
|
166
175
|
let is_scalar = !node
|
|
167
176
|
.descendants()
|
|
168
177
|
.any(|child| child.kind() == SyntaxKind::BLOCK_MAP || child.kind() == SyntaxKind::BLOCK_SEQ);
|
|
@@ -184,14 +193,14 @@ impl Document {
|
|
|
184
193
|
}
|
|
185
194
|
};
|
|
186
195
|
|
|
187
|
-
let (key_name, key_location) = key_of(node,
|
|
196
|
+
let (key_name, key_location) = key_of(node, index);
|
|
188
197
|
|
|
189
198
|
LocatedNode {
|
|
190
199
|
node_type: node_type.to_string(),
|
|
191
200
|
text,
|
|
192
201
|
value_type,
|
|
193
202
|
file_path: file_path.clone(),
|
|
194
|
-
selector,
|
|
203
|
+
selector: item_selector,
|
|
195
204
|
line,
|
|
196
205
|
location,
|
|
197
206
|
key_name,
|
|
@@ -201,8 +210,8 @@ impl Document {
|
|
|
201
210
|
.collect()
|
|
202
211
|
}
|
|
203
212
|
|
|
204
|
-
pub fn node_type(&self,
|
|
205
|
-
match self.get_value(
|
|
213
|
+
pub fn node_type(&self, selector: &str) -> NodeType {
|
|
214
|
+
match self.get_value(selector) {
|
|
206
215
|
Some(yaml_serde::Value::Mapping(_)) => NodeType::Map,
|
|
207
216
|
Some(yaml_serde::Value::Sequence(_)) => NodeType::Sequence,
|
|
208
217
|
Some(_) => NodeType::Scalar,
|
|
@@ -210,14 +219,14 @@ impl Document {
|
|
|
210
219
|
}
|
|
211
220
|
}
|
|
212
221
|
|
|
213
|
-
pub fn get_node_info(&self,
|
|
214
|
-
let
|
|
215
|
-
let
|
|
222
|
+
pub fn get_node_info(&self, selector: &str) -> NodeInfo {
|
|
223
|
+
let parsed = crate::selector::Selector::parse(selector);
|
|
224
|
+
let index = self.line_index();
|
|
216
225
|
|
|
217
|
-
let (location, key_name, key_location) = self.resolve_location(
|
|
226
|
+
let (location, key_name, key_location) = self.resolve_location(selector);
|
|
218
227
|
|
|
219
|
-
if
|
|
220
|
-
let values = self.get_all_typed(
|
|
228
|
+
if parsed.has_wildcard() {
|
|
229
|
+
let values = self.get_all_typed(selector);
|
|
221
230
|
|
|
222
231
|
return NodeInfo {
|
|
223
232
|
node_type: NodeType::Sequence,
|
|
@@ -230,7 +239,7 @@ impl Document {
|
|
|
230
239
|
};
|
|
231
240
|
}
|
|
232
241
|
|
|
233
|
-
match self.get_typed(
|
|
242
|
+
match self.get_typed(selector) {
|
|
234
243
|
Some(scalar) => NodeInfo {
|
|
235
244
|
node_type: NodeType::Scalar,
|
|
236
245
|
is_list: false,
|
|
@@ -241,17 +250,17 @@ impl Document {
|
|
|
241
250
|
key_location,
|
|
242
251
|
},
|
|
243
252
|
None => {
|
|
244
|
-
let (node_type, entry_location, entry_key_name, entry_key_location) = if self.navigate(
|
|
245
|
-
if let Some(entry_node) = self.find_entry(
|
|
253
|
+
let (node_type, entry_location, entry_key_name, entry_key_location) = if self.navigate(selector).is_err() {
|
|
254
|
+
if let Some(entry_node) = self.find_entry(selector) {
|
|
246
255
|
let range = entry_node.text_range();
|
|
247
|
-
let entry_location = compute_location(
|
|
256
|
+
let entry_location = compute_location(index, range.start().into(), range.end().into());
|
|
248
257
|
|
|
249
258
|
let (node, location) = yaml_parser::ast::BlockMapEntry::cast(entry_node.clone())
|
|
250
259
|
.and_then(|entry| {
|
|
251
260
|
entry.key().and_then(|key_node| {
|
|
252
261
|
let key_text = extract_scalar_text(key_node.syntax())?;
|
|
253
262
|
let key_range = key_node.syntax().text_range();
|
|
254
|
-
let key_location = compute_location(
|
|
263
|
+
let key_location = compute_location(index, key_range.start().into(), key_range.end().into());
|
|
255
264
|
|
|
256
265
|
Some((key_text, key_location))
|
|
257
266
|
})
|
|
@@ -261,10 +270,10 @@ impl Document {
|
|
|
261
270
|
|
|
262
271
|
(NodeType::Scalar, entry_location, node, location)
|
|
263
272
|
} else {
|
|
264
|
-
(self.node_type(
|
|
273
|
+
(self.node_type(selector), location, key_name, key_location)
|
|
265
274
|
}
|
|
266
275
|
} else {
|
|
267
|
-
(self.node_type(
|
|
276
|
+
(self.node_type(selector), location, key_name, key_location)
|
|
268
277
|
};
|
|
269
278
|
|
|
270
279
|
NodeInfo {
|
|
@@ -280,13 +289,13 @@ impl Document {
|
|
|
280
289
|
}
|
|
281
290
|
}
|
|
282
291
|
|
|
283
|
-
fn resolve_location(&self,
|
|
284
|
-
match self.navigate(
|
|
292
|
+
fn resolve_location(&self, selector: &str) -> (Location, Option<String>, Location) {
|
|
293
|
+
match self.navigate(selector) {
|
|
285
294
|
Ok(node) => {
|
|
286
295
|
let range = node.text_range();
|
|
287
|
-
let location = compute_location(
|
|
296
|
+
let location = compute_location(self.line_index(), range.start().into(), range.end().into());
|
|
288
297
|
|
|
289
|
-
let (key_name, key_location) = key_of(&node,
|
|
298
|
+
let (key_name, key_location) = key_of(&node, self.line_index());
|
|
290
299
|
|
|
291
300
|
(location, key_name, key_location)
|
|
292
301
|
}
|
|
@@ -294,10 +303,10 @@ impl Document {
|
|
|
294
303
|
}
|
|
295
304
|
}
|
|
296
305
|
|
|
297
|
-
pub fn find_items(&self,
|
|
306
|
+
pub fn find_items(&self, selector: &str, condition: Option<&str>, select: Option<&str>) -> Result<Vec<serde_json::Value>, YerbaError> {
|
|
298
307
|
let values = match condition {
|
|
299
|
-
Some(cond) => self.filter(
|
|
300
|
-
None => self.get_values(
|
|
308
|
+
Some(cond) => self.filter(selector, cond)?,
|
|
309
|
+
None => self.get_values(selector),
|
|
301
310
|
};
|
|
302
311
|
|
|
303
312
|
let select_fields: Option<Vec<&str>> = select.map(|s| s.split(',').collect());
|
|
@@ -323,15 +332,15 @@ impl Document {
|
|
|
323
332
|
Ok(items)
|
|
324
333
|
}
|
|
325
334
|
|
|
326
|
-
pub fn get_value(&self,
|
|
327
|
-
if
|
|
335
|
+
pub fn get_value(&self, selector: &str) -> Option<yaml_serde::Value> {
|
|
336
|
+
if selector.is_empty() {
|
|
328
337
|
return Some(node_to_yaml_value(&self.root));
|
|
329
338
|
}
|
|
330
339
|
|
|
331
|
-
let parsed = crate::selector::Selector::parse(
|
|
340
|
+
let parsed = crate::selector::Selector::parse(selector);
|
|
332
341
|
|
|
333
342
|
if parsed.has_wildcard() {
|
|
334
|
-
let padded = self.navigate_all(
|
|
343
|
+
let padded = self.navigate_all(selector);
|
|
335
344
|
|
|
336
345
|
if padded.is_empty() {
|
|
337
346
|
return None;
|
|
@@ -347,7 +356,7 @@ impl Document {
|
|
|
347
356
|
|
|
348
357
|
Some(yaml_serde::Value::Sequence(values))
|
|
349
358
|
} else {
|
|
350
|
-
let nodes = self.navigate_all_compact(
|
|
359
|
+
let nodes = self.navigate_all_compact(selector);
|
|
351
360
|
|
|
352
361
|
if nodes.is_empty() {
|
|
353
362
|
return None;
|
|
@@ -363,12 +372,12 @@ impl Document {
|
|
|
363
372
|
}
|
|
364
373
|
}
|
|
365
374
|
|
|
366
|
-
pub fn get_values(&self,
|
|
367
|
-
let parsed = crate::selector::Selector::parse(
|
|
375
|
+
pub fn get_values(&self, selector: &str) -> Vec<yaml_serde::Value> {
|
|
376
|
+
let parsed = crate::selector::Selector::parse(selector);
|
|
368
377
|
|
|
369
378
|
if parsed.has_wildcard() {
|
|
370
379
|
self
|
|
371
|
-
.navigate_all(
|
|
380
|
+
.navigate_all(selector)
|
|
372
381
|
.iter()
|
|
373
382
|
.map(|maybe_node| match maybe_node {
|
|
374
383
|
Some(node) => node_to_yaml_value(node),
|
|
@@ -376,7 +385,7 @@ impl Document {
|
|
|
376
385
|
})
|
|
377
386
|
.collect()
|
|
378
387
|
} else {
|
|
379
|
-
self.navigate_all_compact(
|
|
388
|
+
self.navigate_all_compact(selector).iter().map(node_to_yaml_value).collect()
|
|
380
389
|
}
|
|
381
390
|
}
|
|
382
391
|
|
|
@@ -394,30 +403,30 @@ impl Document {
|
|
|
394
403
|
selectors
|
|
395
404
|
}
|
|
396
405
|
|
|
397
|
-
pub fn exists(&self,
|
|
398
|
-
if crate::selector::Selector::parse(
|
|
399
|
-
if !self.navigate_all_compact(
|
|
406
|
+
pub fn exists(&self, selector: &str) -> bool {
|
|
407
|
+
if crate::selector::Selector::parse(selector).has_wildcard() {
|
|
408
|
+
if !self.navigate_all_compact(selector).is_empty() {
|
|
400
409
|
return true;
|
|
401
410
|
}
|
|
402
|
-
} else if self.navigate(
|
|
411
|
+
} else if self.navigate(selector).is_ok() {
|
|
403
412
|
return true;
|
|
404
413
|
}
|
|
405
414
|
|
|
406
|
-
self.find_entry(
|
|
415
|
+
self.find_entry(selector).is_some()
|
|
407
416
|
}
|
|
408
417
|
|
|
409
|
-
fn find_entry(&self,
|
|
410
|
-
let (
|
|
418
|
+
pub(crate) fn find_entry(&self, selector: &str) -> Option<SyntaxNode> {
|
|
419
|
+
let (parent_selector, last_key) = match selector.rsplit_once('.') {
|
|
411
420
|
Some((parent, key)) => (parent, key),
|
|
412
|
-
None => ("",
|
|
421
|
+
None => ("", selector),
|
|
413
422
|
};
|
|
414
423
|
|
|
415
|
-
let parent_node = if
|
|
424
|
+
let parent_node = if parent_selector.is_empty() {
|
|
416
425
|
let root = Root::cast(self.root.clone())?;
|
|
417
426
|
let document = root.documents().next()?;
|
|
418
427
|
document.syntax().clone()
|
|
419
428
|
} else {
|
|
420
|
-
self.navigate(
|
|
429
|
+
self.navigate(parent_selector).ok()?
|
|
421
430
|
};
|
|
422
431
|
|
|
423
432
|
let map = find_block_map(&parent_node)?;
|
|
@@ -425,8 +434,8 @@ impl Document {
|
|
|
425
434
|
find_entry_by_key(&map, last_key).map(|entry| entry.syntax().clone())
|
|
426
435
|
}
|
|
427
436
|
|
|
428
|
-
pub fn get_sequence_values(&self,
|
|
429
|
-
let current_node = match self.navigate(
|
|
437
|
+
pub fn get_sequence_values(&self, selector: &str) -> Vec<String> {
|
|
438
|
+
let current_node = match self.navigate(selector) {
|
|
430
439
|
Ok(node) => node,
|
|
431
440
|
Err(_) => return Vec::new(),
|
|
432
441
|
};
|
|
@@ -442,8 +451,8 @@ impl Document {
|
|
|
442
451
|
.collect()
|
|
443
452
|
}
|
|
444
453
|
|
|
445
|
-
pub fn get_collection_style(&self,
|
|
446
|
-
let current_node = self.navigate(
|
|
454
|
+
pub fn get_collection_style(&self, selector: &str) -> Option<&'static str> {
|
|
455
|
+
let current_node = self.navigate(selector).ok()?;
|
|
447
456
|
|
|
448
457
|
for descendant in current_node.descendants() {
|
|
449
458
|
match descendant.kind() {
|
|
@@ -456,8 +465,8 @@ impl Document {
|
|
|
456
465
|
None
|
|
457
466
|
}
|
|
458
467
|
|
|
459
|
-
pub fn get_sequence_indent(&self,
|
|
460
|
-
let current_node = self.navigate(
|
|
468
|
+
pub fn get_sequence_indent(&self, selector: &str) -> Option<&'static str> {
|
|
469
|
+
let current_node = self.navigate(selector).ok()?;
|
|
461
470
|
|
|
462
471
|
let sequence = find_block_sequence(¤t_node)?;
|
|
463
472
|
let first_entry = sequence.entries().next()?;
|
|
@@ -477,8 +486,8 @@ impl Document {
|
|
|
477
486
|
}
|
|
478
487
|
}
|
|
479
488
|
|
|
480
|
-
pub fn get_quote_style(&self,
|
|
481
|
-
let current_node = self.navigate(
|
|
489
|
+
pub fn get_quote_style(&self, selector: &str) -> Option<&'static str> {
|
|
490
|
+
let current_node = self.navigate(selector).ok()?;
|
|
482
491
|
|
|
483
492
|
for element in current_node.descendants_with_tokens() {
|
|
484
493
|
match element.kind() {
|