diff options
Diffstat (limited to 'crates/ra_editor/src')
-rw-r--r-- | crates/ra_editor/src/typing.rs | 52 |
1 files changed, 16 insertions, 36 deletions
diff --git a/crates/ra_editor/src/typing.rs b/crates/ra_editor/src/typing.rs index 6c1a91ffb..ae82ff89b 100644 --- a/crates/ra_editor/src/typing.rs +++ b/crates/ra_editor/src/typing.rs | |||
@@ -58,14 +58,19 @@ pub fn join_lines(file: &File, range: TextRange) -> LocalEdit { | |||
58 | } | 58 | } |
59 | 59 | ||
60 | pub fn on_enter(file: &File, offset: TextUnit) -> Option<LocalEdit> { | 60 | pub fn on_enter(file: &File, offset: TextUnit) -> Option<LocalEdit> { |
61 | let comment = find_leaf_at_offset(file.syntax(), offset).left_biased().filter(|it| it.kind() == COMMENT)?; | 61 | let comment = find_leaf_at_offset(file.syntax(), offset).left_biased().and_then(|it| ast::Comment::cast(it))?; |
62 | let prefix = comment_preffix(comment)?; | 62 | |
63 | if offset < comment.range().start() + TextUnit::of_str(prefix) { | 63 | if let ast::CommentFlavor::Multiline = comment.flavor() { |
64 | return None; | ||
65 | } | ||
66 | |||
67 | let prefix = comment.prefix(); | ||
68 | if offset < comment.syntax().range().start() + TextUnit::of_str(prefix) + TextUnit::from(1) { | ||
64 | return None; | 69 | return None; |
65 | } | 70 | } |
66 | 71 | ||
67 | let indent = node_indent(file, comment)?; | 72 | let indent = node_indent(file, comment.syntax())?; |
68 | let inserted = format!("\n{}{}", indent, prefix); | 73 | let inserted = format!("\n{}{} ", indent, prefix); |
69 | let cursor_position = offset + TextUnit::of_str(&inserted); | 74 | let cursor_position = offset + TextUnit::of_str(&inserted); |
70 | let mut edit = EditBuilder::new(); | 75 | let mut edit = EditBuilder::new(); |
71 | edit.insert(offset, inserted); | 76 | edit.insert(offset, inserted); |
@@ -75,20 +80,6 @@ pub fn on_enter(file: &File, offset: TextUnit) -> Option<LocalEdit> { | |||
75 | }) | 80 | }) |
76 | } | 81 | } |
77 | 82 | ||
78 | fn comment_preffix(comment: SyntaxNodeRef) -> Option<&'static str> { | ||
79 | let text = comment.leaf_text().unwrap(); | ||
80 | let res = if text.starts_with("///") { | ||
81 | "/// " | ||
82 | } else if text.starts_with("//!") { | ||
83 | "//! " | ||
84 | } else if text.starts_with("//") { | ||
85 | "// " | ||
86 | } else { | ||
87 | return None; | ||
88 | }; | ||
89 | Some(res) | ||
90 | } | ||
91 | |||
92 | fn node_indent<'a>(file: &'a File, node: SyntaxNodeRef) -> Option<&'a str> { | 83 | fn node_indent<'a>(file: &'a File, node: SyntaxNodeRef) -> Option<&'a str> { |
93 | let ws = match find_leaf_at_offset(file.syntax(), node.range().start()) { | 84 | let ws = match find_leaf_at_offset(file.syntax(), node.range().start()) { |
94 | LeafAtOffset::Between(l, r) => { | 85 | LeafAtOffset::Between(l, r) => { |
@@ -166,31 +157,27 @@ fn remove_newline( | |||
166 | // Removes: comma, newline (incl. surrounding whitespace) | 157 | // Removes: comma, newline (incl. surrounding whitespace) |
167 | // Adds: a single whitespace | 158 | // Adds: a single whitespace |
168 | edit.replace(range, " ".to_string()); | 159 | edit.replace(range, " ".to_string()); |
169 | } else if prev.kind() == COMMENT && next.kind() == COMMENT { | 160 | } else if let (Some(_), Some(next)) = (ast::Comment::cast(prev), ast::Comment::cast(next)) { |
170 | // Removes: newline (incl. surrounding whitespace), start of the next comment | 161 | // Removes: newline (incl. surrounding whitespace), start of the next comment |
171 | 162 | let comment_text = next.text(); | |
172 | // FIXME: I guess it is safe to unwrap here? A comment always has text, right? | ||
173 | let comment_text = next.leaf_text().unwrap().as_str(); | ||
174 | let comment_start_length = comment_start_length(comment_text); | ||
175 | |||
176 | if let Some(newline_pos) = comment_text.find('\n') { | 163 | if let Some(newline_pos) = comment_text.find('\n') { |
177 | // Special case for multi-line c-like comments: join the comment content but | 164 | // Special case for multi-line c-like comments: join the comment content but |
178 | // keep the leading `/*` | 165 | // keep the leading `/*` |
179 | 166 | ||
180 | let newline_offset = next.range().start() | 167 | let newline_offset = next.syntax().range().start() |
181 | + TextUnit::from(newline_pos as u32) | 168 | + TextUnit::from(newline_pos as u32) |
182 | + TextUnit::of_char('\n'); | 169 | + TextUnit::of_char('\n'); |
183 | 170 | ||
184 | edit.insert(newline_offset, "/*".to_string()); | 171 | edit.insert(newline_offset, "/*".to_string()); |
185 | edit.delete(TextRange::from_to( | 172 | edit.delete(TextRange::from_to( |
186 | node.range().start(), | 173 | node.range().start(), |
187 | next.range().start() + comment_start_length | 174 | next.syntax().range().start() + TextUnit::of_str(next.prefix()) |
188 | )); | 175 | )); |
189 | } else { | 176 | } else { |
190 | // Single-line comments | 177 | // Single-line comments |
191 | edit.delete(TextRange::from_to( | 178 | edit.delete(TextRange::from_to( |
192 | node.range().start(), | 179 | node.range().start(), |
193 | next.range().start() + comment_start_length | 180 | next.syntax().range().start() + TextUnit::of_str(next.prefix()) |
194 | )); | 181 | )); |
195 | } | 182 | } |
196 | } else { | 183 | } else { |
@@ -205,7 +192,7 @@ fn remove_newline( | |||
205 | } | 192 | } |
206 | } | 193 | } |
207 | 194 | ||
208 | // FIXME: do we ever reach this point? What does it mean to be here? I think we should document it | 195 | // The node is either the first or the last in the file |
209 | let suff = &node_text[TextRange::from_to( | 196 | let suff = &node_text[TextRange::from_to( |
210 | offset - node.range().start() + TextUnit::of_char('\n'), | 197 | offset - node.range().start() + TextUnit::of_char('\n'), |
211 | TextUnit::of_str(node_text), | 198 | TextUnit::of_str(node_text), |
@@ -218,13 +205,6 @@ fn remove_newline( | |||
218 | ); | 205 | ); |
219 | } | 206 | } |
220 | 207 | ||
221 | // Return the start length of the comment (e.g. 2 for `//` and 3 for `//!`) | ||
222 | fn comment_start_length(_text: &str) -> TextUnit { | ||
223 | // TODO: use the parser here instead of reimplementing comment parsing? | ||
224 | // Otherwise, reimplement comment parsing :) | ||
225 | return TextUnit::from(2); | ||
226 | } | ||
227 | |||
228 | fn is_trailing_comma(left: SyntaxKind, right: SyntaxKind) -> bool { | 208 | fn is_trailing_comma(left: SyntaxKind, right: SyntaxKind) -> bool { |
229 | match (left, right) { | 209 | match (left, right) { |
230 | (COMMA, R_PAREN) | (COMMA, R_BRACK) => true, | 210 | (COMMA, R_PAREN) | (COMMA, R_BRACK) => true, |