aboutsummaryrefslogtreecommitdiff
path: root/crates/syntax/src/ted.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/syntax/src/ted.rs')
-rw-r--r--crates/syntax/src/ted.rs78
1 files changed, 78 insertions, 0 deletions
diff --git a/crates/syntax/src/ted.rs b/crates/syntax/src/ted.rs
new file mode 100644
index 000000000..8d6175ed9
--- /dev/null
+++ b/crates/syntax/src/ted.rs
@@ -0,0 +1,78 @@
1//! Primitive tree editor, ed for trees
2#![allow(unused)]
3use std::ops::RangeInclusive;
4
5use crate::{SyntaxElement, SyntaxNode};
6
7#[derive(Debug)]
8pub struct Position {
9 repr: PositionRepr,
10}
11
12#[derive(Debug)]
13enum PositionRepr {
14 FirstChild(SyntaxNode),
15 After(SyntaxElement),
16}
17
18impl Position {
19 pub fn after(elem: impl Into<SyntaxElement>) -> Position {
20 let repr = PositionRepr::After(elem.into());
21 Position { repr }
22 }
23 pub fn before(elem: impl Into<SyntaxElement>) -> Position {
24 let elem = elem.into();
25 let repr = match elem.prev_sibling_or_token() {
26 Some(it) => PositionRepr::After(it),
27 None => PositionRepr::FirstChild(elem.parent().unwrap()),
28 };
29 Position { repr }
30 }
31 pub fn first_child_of(node: impl Into<SyntaxNode>) -> Position {
32 let repr = PositionRepr::FirstChild(node.into());
33 Position { repr }
34 }
35 pub fn last_child_of(node: impl Into<SyntaxNode>) -> Position {
36 let node = node.into();
37 let repr = match node.last_child_or_token() {
38 Some(it) => PositionRepr::After(it),
39 None => PositionRepr::FirstChild(node),
40 };
41 Position { repr }
42 }
43}
44
45pub fn insert(position: Position, elem: impl Into<SyntaxElement>) {
46 insert_all(position, vec![elem.into()])
47}
48pub fn insert_all(position: Position, elements: Vec<SyntaxElement>) {
49 let (parent, index) = match position.repr {
50 PositionRepr::FirstChild(parent) => (parent, 0),
51 PositionRepr::After(child) => (child.parent().unwrap(), child.index() + 1),
52 };
53 parent.splice_children(index..index, elements);
54}
55
56pub fn remove(elem: impl Into<SyntaxElement>) {
57 let elem = elem.into();
58 remove_all(elem.clone()..=elem)
59}
60pub fn remove_all(range: RangeInclusive<SyntaxElement>) {
61 replace_all(range, Vec::new())
62}
63
64pub fn replace(old: impl Into<SyntaxElement>, new: impl Into<SyntaxElement>) {
65 let old = old.into();
66 replace_all(old.clone()..=old, vec![new.into()])
67}
68pub fn replace_all(range: RangeInclusive<SyntaxElement>, new: Vec<SyntaxElement>) {
69 let start = range.start().index();
70 let end = range.end().index();
71 let parent = range.start().parent().unwrap();
72 parent.splice_children(start..end + 1, new)
73}
74
75pub fn append_child(node: impl Into<SyntaxNode>, child: impl Into<SyntaxElement>) {
76 let position = Position::last_child_of(node);
77 insert(position, child)
78}