aboutsummaryrefslogtreecommitdiff
path: root/crates/libeditor/src
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2018-08-23 18:55:23 +0100
committerAleksey Kladov <[email protected]>2018-08-23 18:55:23 +0100
commit6dcf87fb5f17393028a031b00a562ea8b74267ca (patch)
tree05de66dc2944ca78e34b507f80e7e12056d4f867 /crates/libeditor/src
parentec706175645172ee4bd5d3d4c0645ffb45d79bbf (diff)
Start join-lines
Diffstat (limited to 'crates/libeditor/src')
-rw-r--r--crates/libeditor/src/code_actions.rs1
-rw-r--r--crates/libeditor/src/lib.rs4
-rw-r--r--crates/libeditor/src/typing.rs81
3 files changed, 85 insertions, 1 deletions
diff --git a/crates/libeditor/src/code_actions.rs b/crates/libeditor/src/code_actions.rs
index 6c41923dd..c25ee973c 100644
--- a/crates/libeditor/src/code_actions.rs
+++ b/crates/libeditor/src/code_actions.rs
@@ -14,6 +14,7 @@ use libsyntax2::{
14 14
15use {TextUnit, EditBuilder, Edit}; 15use {TextUnit, EditBuilder, Edit};
16 16
17#[derive(Debug)]
17pub struct ActionResult { 18pub struct ActionResult {
18 pub edit: Edit, 19 pub edit: Edit,
19 pub cursor_position: Option<TextUnit>, 20 pub cursor_position: Option<TextUnit>,
diff --git a/crates/libeditor/src/lib.rs b/crates/libeditor/src/lib.rs
index 6bae7a3fa..f8bc73ae9 100644
--- a/crates/libeditor/src/lib.rs
+++ b/crates/libeditor/src/lib.rs
@@ -7,11 +7,12 @@ mod symbols;
7mod line_index; 7mod line_index;
8mod edit; 8mod edit;
9mod code_actions; 9mod code_actions;
10mod typing;
10 11
11use libsyntax2::{ 12use libsyntax2::{
12 ast::{self, NameOwner}, 13 ast::{self, NameOwner},
13 AstNode, 14 AstNode,
14 algo::{walk, find_leaf_at_offset}, 15 algo::{walk, find_leaf_at_offset, find_covering_node},
15 SyntaxKind::{self, *}, 16 SyntaxKind::{self, *},
16}; 17};
17pub use libsyntax2::{ParsedFile, TextRange, TextUnit}; 18pub use libsyntax2::{ParsedFile, TextRange, TextUnit};
@@ -24,6 +25,7 @@ pub use self::{
24 ActionResult, find_node, 25 ActionResult, find_node,
25 flip_comma, add_derive, add_impl, 26 flip_comma, add_derive, add_impl,
26 }, 27 },
28 typing::join_lines,
27}; 29};
28 30
29#[derive(Debug)] 31#[derive(Debug)]
diff --git a/crates/libeditor/src/typing.rs b/crates/libeditor/src/typing.rs
new file mode 100644
index 000000000..f49dd0fdc
--- /dev/null
+++ b/crates/libeditor/src/typing.rs
@@ -0,0 +1,81 @@
1use libsyntax2::{
2 TextUnit, TextRange, SyntaxNodeRef,
3 ast,
4 algo::{
5 walk::preorder,
6 find_covering_node,
7 },
8};
9
10use {ActionResult, EditBuilder};
11
12pub fn join_lines(file: &ast::ParsedFile, range: TextRange) -> ActionResult {
13 let range = if range.is_empty() {
14 let text = file.syntax().text();
15 let text = &text[TextRange::from_to(range.start(), TextUnit::of_str(&text))];
16 let pos = text.bytes().take_while(|&b| b != b'\n').count();
17 if pos == text.len() {
18 return ActionResult {
19 edit: EditBuilder::new().finish(),
20 cursor_position: None
21 };
22 }
23 let pos: TextUnit = (pos as u32).into();
24 TextRange::offset_len(
25 range.start() + pos,
26 TextUnit::of_char('\n'),
27 )
28 } else {
29 range
30 };
31 let node = find_covering_node(file.syntax(), range);
32 let mut edit = EditBuilder::new();
33 for node in preorder(node) {
34 let text = match node.leaf_text() {
35 Some(text) => text,
36 None => continue,
37 };
38 let range = match intersect(range, node.range()) {
39 Some(range) => range,
40 None => continue,
41 } - node.range().start();
42 for (pos, _) in text[range].bytes().enumerate().filter(|&(_, b)| b == b'\n') {
43 let pos: TextUnit = (pos as u32).into();
44 let off = node.range().start() + range.start() + pos;
45 remove_newline(&mut edit, node, text.as_str(), off);
46 }
47 }
48
49 ActionResult {
50 edit: edit.finish(),
51 cursor_position: None,
52 }
53}
54
55fn intersect(r1: TextRange, r2: TextRange) -> Option<TextRange> {
56 let start = r1.start().max(r2.start());
57 let end = r1.end().min(r2.end());
58 if start <= end {
59 Some(TextRange::from_to(start, end))
60 } else {
61 None
62 }
63}
64
65fn remove_newline(
66 edit: &mut EditBuilder,
67 node: SyntaxNodeRef,
68 node_text: &str,
69 offset: TextUnit,
70) {
71 let suff = &node_text[TextRange::from_to(
72 offset - node.range().start() + TextUnit::of_char('\n'),
73 TextUnit::of_str(node_text),
74 )];
75 let spaces = suff.bytes().take_while(|&b| b == b' ').count();
76
77 edit.replace(
78 TextRange::offset_len(offset, ((spaces + 1) as u32).into()),
79 " ".to_string(),
80 );
81}