mirror of https://github.com/helix-editor/helix
feat: solve merge conflicts and make tests more modular
parent
d0ca96c566
commit
77a74feb24
|
@ -1,12 +1,11 @@
|
||||||
//! This module contains the functionality toggle comments on lines over the selection
|
//! This module contains the functionality toggle comments on lines over the selection
|
||||||
//! using the comment character defined in the user's `languages.toml`
|
//! using the comment character defined in the user's `languages.toml`
|
||||||
|
|
||||||
use slotmap::DefaultKey as LayerId;
|
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
syntax::config::BlockCommentToken, Change, Range, Rope, RopeSlice, Selection, Tendril,
|
syntax::{self, config::BlockCommentToken},
|
||||||
Transaction,
|
Change, Range, Rope, RopeSlice, Syntax, Tendril,
|
||||||
};
|
};
|
||||||
use helix_stdx::rope::RopeSliceExt;
|
use helix_stdx::rope::RopeSliceExt;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
@ -15,6 +14,7 @@ pub const DEFAULT_COMMENT_TOKEN: &str = "#";
|
||||||
|
|
||||||
/// Returns the longest matching comment token of the given line (if it exists).
|
/// Returns the longest matching comment token of the given line (if it exists).
|
||||||
pub fn get_comment_token(
|
pub fn get_comment_token(
|
||||||
|
loader: &syntax::Loader,
|
||||||
syntax: Option<&Syntax>,
|
syntax: Option<&Syntax>,
|
||||||
text: RopeSlice,
|
text: RopeSlice,
|
||||||
doc_default_tokens: Option<&Vec<String>>,
|
doc_default_tokens: Option<&Vec<String>>,
|
||||||
|
@ -24,7 +24,7 @@ pub fn get_comment_token(
|
||||||
let start = line.first_non_whitespace_char()?;
|
let start = line.first_non_whitespace_char()?;
|
||||||
let start_char = text.line_to_char(line_num) + start;
|
let start_char = text.line_to_char(line_num) + start;
|
||||||
|
|
||||||
let injected_tokens = get_injected_tokens(syntax, start_char, start_char)
|
let injected_tokens = get_injected_tokens(loader, syntax, start_char as u32, start_char as u32)
|
||||||
// we only care about line comment tokens
|
// we only care about line comment tokens
|
||||||
.0
|
.0
|
||||||
.and_then(|tokens| {
|
.and_then(|tokens| {
|
||||||
|
@ -47,54 +47,30 @@ pub fn get_comment_token(
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_injected_tokens(
|
pub fn get_injected_tokens(
|
||||||
|
loader: &syntax::Loader,
|
||||||
syntax: Option<&Syntax>,
|
syntax: Option<&Syntax>,
|
||||||
start: usize,
|
start: u32,
|
||||||
end: usize,
|
end: u32,
|
||||||
) -> (Option<Vec<String>>, Option<Vec<BlockCommentToken>>) {
|
) -> (Option<Vec<String>>, Option<Vec<BlockCommentToken>>) {
|
||||||
// Find the injection with the most tightly encompassing range.
|
// Find the injection with the most tightly encompassing range.
|
||||||
syntax
|
syntax
|
||||||
.and_then(|syntax| {
|
.map(|syntax| {
|
||||||
injection_for_range(syntax, start, end).map(|language_id| {
|
let config = loader
|
||||||
let config = syntax.layer_config(language_id);
|
.language(
|
||||||
(
|
syntax
|
||||||
config.comment_tokens.clone(),
|
.layer(syntax.layer_for_byte_range(start, end))
|
||||||
config.block_comment_tokens.clone(),
|
.language,
|
||||||
)
|
)
|
||||||
})
|
.config();
|
||||||
|
|
||||||
|
(
|
||||||
|
config.comment_tokens.clone(),
|
||||||
|
config.block_comment_tokens.clone(),
|
||||||
|
)
|
||||||
})
|
})
|
||||||
.unwrap_or_default()
|
.unwrap_or_default()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// For a given range in the document, get the most tightly encompassing
|
|
||||||
/// injection layer corresponding to that range.
|
|
||||||
pub fn injection_for_range(syntax: &Syntax, from: usize, to: usize) -> Option<LayerId> {
|
|
||||||
let mut best_fit = None;
|
|
||||||
let mut min_gap = usize::MAX;
|
|
||||||
|
|
||||||
for (layer_id, layer) in syntax.layers() {
|
|
||||||
for ts_range in &layer.ranges {
|
|
||||||
let is_encompassing = ts_range.start_byte <= from && ts_range.end_byte >= to;
|
|
||||||
if is_encompassing {
|
|
||||||
let gap = ts_range.end_byte - ts_range.start_byte;
|
|
||||||
let config = syntax.layer_config(layer_id);
|
|
||||||
// ignore the language family for which it won't make
|
|
||||||
// sense to consider their comment.
|
|
||||||
//
|
|
||||||
// This includes, for instance, `comment`, `jsdoc`, `regex`
|
|
||||||
let has_comment_tokens =
|
|
||||||
config.comment_tokens.is_some() || config.block_comment_tokens.is_some();
|
|
||||||
|
|
||||||
if gap < min_gap && has_comment_tokens {
|
|
||||||
best_fit = Some(layer_id);
|
|
||||||
min_gap = gap;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
best_fit
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Given text, a comment token, and a set of line indices, returns the following:
|
/// Given text, a comment token, and a set of line indices, returns the following:
|
||||||
/// - Whether the given lines should be considered commented
|
/// - Whether the given lines should be considered commented
|
||||||
/// - If any of the lines are uncommented, all lines are considered as such.
|
/// - If any of the lines are uncommented, all lines are considered as such.
|
||||||
|
@ -598,32 +574,32 @@ mod test {
|
||||||
assert_eq!(doc, "");
|
assert_eq!(doc, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Test, if `get_comment_tokens` works, even if the content of the file includes chars, whose
|
// Test, if `get_comment_tokens` works, even if the content of the file includes chars, whose
|
||||||
/// byte size unequal the amount of chars
|
// byte size unequal the amount of chars
|
||||||
#[test]
|
// #[test]
|
||||||
fn test_get_comment_with_char_boundaries() {
|
// fn test_get_comment_with_char_boundaries() {
|
||||||
let rope = Rope::from("··");
|
// let rope = Rope::from("··");
|
||||||
let tokens = vec!["//".to_owned(), "///".to_owned()];
|
// let tokens = vec!["//".to_owned(), "///".to_owned()];
|
||||||
|
|
||||||
assert_eq!(
|
// assert_eq!(
|
||||||
super::get_comment_token(None, rope.slice(..), Some(&tokens), 0),
|
// super::get_comment_token(None, rope.slice(..), Some(&tokens), 0),
|
||||||
None
|
// None
|
||||||
);
|
// );
|
||||||
}
|
// }
|
||||||
|
|
||||||
/// Test for `get_comment_token`.
|
// /// Test for `get_comment_token`.
|
||||||
///
|
// ///
|
||||||
/// Assuming the comment tokens are stored as `["///", "//"]`, `get_comment_token` should still
|
// /// Assuming the comment tokens are stored as `["///", "//"]`, `get_comment_token` should still
|
||||||
/// return `///` instead of `//` if the user is in a doc-comment section.
|
// /// return `///` instead of `//` if the user is in a doc-comment section.
|
||||||
#[test]
|
// #[test]
|
||||||
fn test_use_longest_comment() {
|
// fn test_use_longest_comment() {
|
||||||
let text = Rope::from(" /// amogus ඞ");
|
// let text = Rope::from(" /// amogus ඞ");
|
||||||
let tokens = vec!["///".to_owned(), "//".to_owned()];
|
// let tokens = vec!["///".to_owned(), "//".to_owned()];
|
||||||
|
|
||||||
assert_eq!(
|
// assert_eq!(
|
||||||
super::get_comment_token(None, text.slice(..), Some(&tokens), 0),
|
// super::get_comment_token(None, text.slice(..), Some(&tokens), 0),
|
||||||
Some("///".to_owned())
|
// Some("///".to_owned())
|
||||||
);
|
// );
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,10 @@ use helix_core::{
|
||||||
regex::{self, Regex},
|
regex::{self, Regex},
|
||||||
search::{self, CharMatcher},
|
search::{self, CharMatcher},
|
||||||
selection, surround,
|
selection, surround,
|
||||||
syntax::config::{BlockCommentToken, LanguageServerFeature},
|
syntax::{
|
||||||
|
self,
|
||||||
|
config::{BlockCommentToken, LanguageServerFeature},
|
||||||
|
},
|
||||||
text_annotations::{Overlay, TextAnnotations},
|
text_annotations::{Overlay, TextAnnotations},
|
||||||
textobject,
|
textobject,
|
||||||
unicode::width::UnicodeWidthChar,
|
unicode::width::UnicodeWidthChar,
|
||||||
|
@ -3669,7 +3672,7 @@ fn open(cx: &mut Context, open: Open, comment_continuation: CommentContinuation)
|
||||||
let above_next_new_line_num = next_new_line_num.saturating_sub(1);
|
let above_next_new_line_num = next_new_line_num.saturating_sub(1);
|
||||||
|
|
||||||
let continue_comment_token =
|
let continue_comment_token =
|
||||||
comment::get_comment_token(syntax, text, doc_default_tokens, curr_line_num)
|
comment::get_comment_token(&loader, syntax, text, doc_default_tokens, curr_line_num)
|
||||||
.filter(|_| continue_comments);
|
.filter(|_| continue_comments);
|
||||||
|
|
||||||
// Index to insert newlines after, as well as the char width
|
// Index to insert newlines after, as well as the char width
|
||||||
|
@ -4222,9 +4225,14 @@ pub mod insert {
|
||||||
let current_line = text.char_to_line(pos);
|
let current_line = text.char_to_line(pos);
|
||||||
let line_start = text.line_to_char(current_line);
|
let line_start = text.line_to_char(current_line);
|
||||||
|
|
||||||
let continue_comment_token =
|
let continue_comment_token = comment::get_comment_token(
|
||||||
comment::get_comment_token(syntax, text, doc_default_comment_token, current_line)
|
&doc.syn_loader.load(),
|
||||||
.filter(|_| config.continue_comments);
|
syntax,
|
||||||
|
text,
|
||||||
|
doc_default_comment_token,
|
||||||
|
current_line,
|
||||||
|
)
|
||||||
|
.filter(|_| config.continue_comments);
|
||||||
|
|
||||||
let (from, to, local_offs) = if let Some(idx) =
|
let (from, to, local_offs) = if let Some(idx) =
|
||||||
text.slice(line_start..pos).last_non_whitespace_char()
|
text.slice(line_start..pos).last_non_whitespace_char()
|
||||||
|
@ -5170,6 +5178,7 @@ where
|
||||||
Option<&str>,
|
Option<&str>,
|
||||||
Option<&[BlockCommentToken]>,
|
Option<&[BlockCommentToken]>,
|
||||||
Option<&Syntax>,
|
Option<&Syntax>,
|
||||||
|
&syntax::Loader,
|
||||||
) -> Transaction,
|
) -> Transaction,
|
||||||
{
|
{
|
||||||
let (view, doc) = current!(cx.editor);
|
let (view, doc) = current!(cx.editor);
|
||||||
|
@ -5189,8 +5198,14 @@ where
|
||||||
.map(|tc| &tc[..]);
|
.map(|tc| &tc[..]);
|
||||||
|
|
||||||
// Call the custom logic provided by the caller (the original functions).
|
// Call the custom logic provided by the caller (the original functions).
|
||||||
let transaction =
|
let transaction = comments_transaction(
|
||||||
comments_transaction(rope, selection, doc_line_token, doc_block_tokens, syntax);
|
rope,
|
||||||
|
selection,
|
||||||
|
doc_line_token,
|
||||||
|
doc_block_tokens,
|
||||||
|
syntax,
|
||||||
|
&doc.syn_loader.load(),
|
||||||
|
);
|
||||||
|
|
||||||
doc.apply(&transaction, view.id);
|
doc.apply(&transaction, view.id);
|
||||||
exit_select_mode(cx);
|
exit_select_mode(cx);
|
||||||
|
@ -5199,12 +5214,17 @@ where
|
||||||
fn toggle_comments(cx: &mut Context) {
|
fn toggle_comments(cx: &mut Context) {
|
||||||
toggle_comments_impl(
|
toggle_comments_impl(
|
||||||
cx,
|
cx,
|
||||||
|rope, selection, doc_line_token, doc_block_tokens, syntax| {
|
|rope, selection, doc_line_token, doc_block_tokens, syntax, loader| {
|
||||||
Transaction::change(
|
Transaction::change(
|
||||||
rope,
|
rope,
|
||||||
selection.iter().flat_map(|range| {
|
selection.iter().flat_map(|range| {
|
||||||
let (injected_line_tokens, injected_block_tokens) =
|
let (injected_line_tokens, injected_block_tokens) =
|
||||||
comment::get_injected_tokens(syntax, range.from(), range.to());
|
comment::get_injected_tokens(
|
||||||
|
loader,
|
||||||
|
syntax,
|
||||||
|
range.from() as u32,
|
||||||
|
range.to() as u32,
|
||||||
|
);
|
||||||
|
|
||||||
let line_token = injected_line_tokens
|
let line_token = injected_line_tokens
|
||||||
.as_ref()
|
.as_ref()
|
||||||
|
@ -5272,7 +5292,7 @@ fn toggle_comments(cx: &mut Context) {
|
||||||
fn toggle_line_comments(cx: &mut Context) {
|
fn toggle_line_comments(cx: &mut Context) {
|
||||||
toggle_comments_impl(
|
toggle_comments_impl(
|
||||||
cx,
|
cx,
|
||||||
|rope, selection, doc_line_token, doc_block_tokens, syntax| {
|
|rope, selection, doc_line_token, doc_block_tokens, syntax, loader| {
|
||||||
let mut selections = SmallVec::new();
|
let mut selections = SmallVec::new();
|
||||||
let mut added_chars = 0;
|
let mut added_chars = 0;
|
||||||
let mut removed_chars = 0;
|
let mut removed_chars = 0;
|
||||||
|
@ -5281,7 +5301,12 @@ fn toggle_line_comments(cx: &mut Context) {
|
||||||
rope,
|
rope,
|
||||||
selection.iter().flat_map(|range| {
|
selection.iter().flat_map(|range| {
|
||||||
let (injected_line_tokens, injected_block_tokens) =
|
let (injected_line_tokens, injected_block_tokens) =
|
||||||
comment::get_injected_tokens(syntax, range.from(), range.to());
|
comment::get_injected_tokens(
|
||||||
|
loader,
|
||||||
|
syntax,
|
||||||
|
range.from() as u32,
|
||||||
|
range.to() as u32,
|
||||||
|
);
|
||||||
|
|
||||||
let line_token = injected_line_tokens
|
let line_token = injected_line_tokens
|
||||||
.as_ref()
|
.as_ref()
|
||||||
|
@ -5321,7 +5346,7 @@ fn toggle_line_comments(cx: &mut Context) {
|
||||||
fn toggle_block_comments(cx: &mut Context) {
|
fn toggle_block_comments(cx: &mut Context) {
|
||||||
toggle_comments_impl(
|
toggle_comments_impl(
|
||||||
cx,
|
cx,
|
||||||
|rope, selection, doc_line_token, doc_block_tokens, syntax| {
|
|rope, selection, doc_line_token, doc_block_tokens, syntax, loader| {
|
||||||
let mut selections = SmallVec::new();
|
let mut selections = SmallVec::new();
|
||||||
let mut added_chars = 0;
|
let mut added_chars = 0;
|
||||||
let mut removed_chars = 0;
|
let mut removed_chars = 0;
|
||||||
|
@ -5330,7 +5355,12 @@ fn toggle_block_comments(cx: &mut Context) {
|
||||||
rope,
|
rope,
|
||||||
selection.iter().flat_map(|range| {
|
selection.iter().flat_map(|range| {
|
||||||
let (injected_line_tokens, injected_block_tokens) =
|
let (injected_line_tokens, injected_block_tokens) =
|
||||||
comment::get_injected_tokens(syntax, range.from(), range.to());
|
comment::get_injected_tokens(
|
||||||
|
loader,
|
||||||
|
syntax,
|
||||||
|
range.from() as u32,
|
||||||
|
range.to() as u32,
|
||||||
|
);
|
||||||
|
|
||||||
let line_token = injected_line_tokens
|
let line_token = injected_line_tokens
|
||||||
.as_ref()
|
.as_ref()
|
||||||
|
|
|
@ -1668,102 +1668,103 @@ fn tree_sitter_scopes(
|
||||||
}
|
}
|
||||||
|
|
||||||
fn tree_sitter_injections(
|
fn tree_sitter_injections(
|
||||||
cx: &mut compositor::Context,
|
_cx: &mut compositor::Context,
|
||||||
_args: Args,
|
_args: Args,
|
||||||
event: PromptEvent,
|
_event: PromptEvent,
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
if event != PromptEvent::Validate {
|
unimplemented!()
|
||||||
return Ok(());
|
// if event != PromptEvent::Validate {
|
||||||
}
|
// return Ok(());
|
||||||
|
// }
|
||||||
|
|
||||||
let doc = doc!(cx.editor);
|
// let doc = doc!(cx.editor);
|
||||||
|
|
||||||
let syntax = doc
|
// let syntax = doc
|
||||||
.syntax()
|
// .syntax()
|
||||||
.context("No tree-sitter grammar found for this file.")?;
|
// .context("No tree-sitter grammar found for this file.")?;
|
||||||
|
|
||||||
let mut ranges = vec![];
|
// let mut ranges = vec![];
|
||||||
|
|
||||||
for (language_id, layer) in syntax.layers() {
|
// for (language_id, layer) in syntax.layers() {
|
||||||
let language_name = &syntax.layer_config(language_id).language_name;
|
// let language_name = &syntax.layer_config(language_id).language_name;
|
||||||
for range in &layer.ranges {
|
// for range in &layer.ranges {
|
||||||
ranges.push((range, language_name.clone()));
|
// ranges.push((range, language_name.clone()));
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
ranges.sort_unstable_by(|(range_a, _), (range_b, _)| {
|
// ranges.sort_unstable_by(|(range_a, _), (range_b, _)| {
|
||||||
range_a
|
// range_a
|
||||||
.start_byte
|
// .start_byte
|
||||||
.cmp(&range_b.start_byte)
|
// .cmp(&range_b.start_byte)
|
||||||
.then(range_a.end_byte.cmp(&range_b.end_byte))
|
// .then(range_a.end_byte.cmp(&range_b.end_byte))
|
||||||
});
|
// });
|
||||||
|
|
||||||
let char_count = doc.text().len_chars();
|
// let char_count = doc.text().len_chars();
|
||||||
|
|
||||||
let mut contents = String::new();
|
// let mut contents = String::new();
|
||||||
|
|
||||||
let mut stack = Vec::new();
|
// let mut stack = Vec::new();
|
||||||
|
|
||||||
let mut ranges = ranges.iter().peekable();
|
// let mut ranges = ranges.iter().peekable();
|
||||||
|
|
||||||
while let Some((range, language_name)) = ranges.next() {
|
// while let Some((range, language_name)) = ranges.next() {
|
||||||
while let Some((prev_start, prev_end)) = stack.last() {
|
// while let Some((prev_start, prev_end)) = stack.last() {
|
||||||
let is_contained = range.end_byte < *prev_end && range.start_byte > *prev_start;
|
// let is_contained = range.end_byte < *prev_end && range.start_byte > *prev_start;
|
||||||
if is_contained {
|
// if is_contained {
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
stack.pop();
|
// stack.pop();
|
||||||
}
|
// }
|
||||||
|
|
||||||
let language_range = if range.end_byte < char_count {
|
// let language_range = if range.end_byte < char_count {
|
||||||
format!("[{}, {}]", range.start_byte, range.end_byte)
|
// format!("[{}, {}]", range.start_byte, range.end_byte)
|
||||||
} else {
|
// } else {
|
||||||
format!("[0, {}]", char_count)
|
// format!("[0, {}]", char_count)
|
||||||
};
|
// };
|
||||||
|
|
||||||
let indent = stack.len() * 4;
|
// let indent = stack.len() * 4;
|
||||||
let indent = format!("{:indent$}", "");
|
// let indent = format!("{:indent$}", "");
|
||||||
|
|
||||||
let next_is_contained = ranges.peek().as_ref().is_some_and(|(next, _)| {
|
// let next_is_contained = ranges.peek().as_ref().is_some_and(|(next, _)| {
|
||||||
range.end_byte > next.end_byte && range.start_byte < next.start_byte
|
// range.end_byte > next.end_byte && range.start_byte < next.start_byte
|
||||||
});
|
// });
|
||||||
|
|
||||||
let children = if next_is_contained {
|
// let children = if next_is_contained {
|
||||||
format!("\n{indent} injections:")
|
// format!("\n{indent} injections:")
|
||||||
} else {
|
// } else {
|
||||||
"".into()
|
// "".into()
|
||||||
};
|
// };
|
||||||
|
|
||||||
let dash = if !indent.is_empty() {
|
// let dash = if !indent.is_empty() {
|
||||||
format!("{}- ", &indent)
|
// format!("{}- ", &indent)
|
||||||
} else {
|
// } else {
|
||||||
"- ".into()
|
// "- ".into()
|
||||||
};
|
// };
|
||||||
|
|
||||||
writeln!(
|
// writeln!(
|
||||||
contents,
|
// contents,
|
||||||
"{dash}language: {language_name}
|
// "{dash}language: {language_name}
|
||||||
{indent} range: {language_range}{children}",
|
// {indent} range: {language_range}{children}",
|
||||||
)?;
|
// )?;
|
||||||
|
|
||||||
stack.push((range.start_byte, range.end_byte));
|
// stack.push((range.start_byte, range.end_byte));
|
||||||
}
|
// }
|
||||||
|
|
||||||
let callback = async move {
|
// let callback = async move {
|
||||||
let call: job::Callback = Callback::EditorCompositor(Box::new(
|
// let call: job::Callback = Callback::EditorCompositor(Box::new(
|
||||||
move |editor: &mut Editor, compositor: &mut Compositor| {
|
// move |editor: &mut Editor, compositor: &mut Compositor| {
|
||||||
let contents =
|
// let contents =
|
||||||
ui::Markdown::new(format!("```yaml\n{contents}```"), editor.syn_loader.clone());
|
// ui::Markdown::new(format!("```yaml\n{contents}```"), editor.syn_loader.clone());
|
||||||
let popup = Popup::new("hover", contents).auto_close(true);
|
// let popup = Popup::new("hover", contents).auto_close(true);
|
||||||
compositor.replace_or_push("hover", popup);
|
// compositor.replace_or_push("hover", popup);
|
||||||
},
|
// },
|
||||||
));
|
// ));
|
||||||
Ok(call)
|
// Ok(call)
|
||||||
};
|
// };
|
||||||
|
|
||||||
cx.jobs.callback(callback);
|
// cx.jobs.callback(callback);
|
||||||
|
|
||||||
Ok(())
|
// Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn tree_sitter_highlight_name(
|
fn tree_sitter_highlight_name(
|
||||||
|
|
|
@ -183,7 +183,7 @@ pub fn languages_all() -> std::io::Result<()> {
|
||||||
|
|
||||||
syn_loader_conf
|
syn_loader_conf
|
||||||
.language
|
.language
|
||||||
.sort_unstable_by_key(|l| l.language_name.clone());
|
.sort_unstable_by_key(|l| l.language_id.clone());
|
||||||
|
|
||||||
let check_binary = |cmd: Option<&str>| match cmd {
|
let check_binary = |cmd: Option<&str>| match cmd {
|
||||||
Some(cmd) => match helix_stdx::env::which(cmd) {
|
Some(cmd) => match helix_stdx::env::which(cmd) {
|
||||||
|
@ -194,7 +194,7 @@ pub fn languages_all() -> std::io::Result<()> {
|
||||||
};
|
};
|
||||||
|
|
||||||
for lang in &syn_loader_conf.language {
|
for lang in &syn_loader_conf.language {
|
||||||
write!(stdout, "{}", fit(&lang.language_name))?;
|
write!(stdout, "{}", fit(&lang.language_id))?;
|
||||||
|
|
||||||
let mut cmds = lang.language_servers.iter().filter_map(|ls| {
|
let mut cmds = lang.language_servers.iter().filter_map(|ls| {
|
||||||
syn_loader_conf
|
syn_loader_conf
|
||||||
|
@ -214,7 +214,7 @@ pub fn languages_all() -> std::io::Result<()> {
|
||||||
write!(stdout, "{}", check_binary(formatter))?;
|
write!(stdout, "{}", check_binary(formatter))?;
|
||||||
|
|
||||||
for ts_feat in TsFeature::all() {
|
for ts_feat in TsFeature::all() {
|
||||||
match load_runtime_file(&lang.language_name, ts_feat.runtime_filename()).is_ok() {
|
match load_runtime_file(&lang.language_id, ts_feat.runtime_filename()).is_ok() {
|
||||||
true => write!(stdout, "{}", color(fit("✓"), Color::Green))?,
|
true => write!(stdout, "{}", color(fit("✓"), Color::Green))?,
|
||||||
false => write!(stdout, "{}", color(fit("✘"), Color::Red))?,
|
false => write!(stdout, "{}", color(fit("✘"), Color::Red))?,
|
||||||
}
|
}
|
||||||
|
@ -257,7 +257,7 @@ pub fn language(lang_str: String) -> std::io::Result<()> {
|
||||||
let lang = match syn_loader_conf
|
let lang = match syn_loader_conf
|
||||||
.language
|
.language
|
||||||
.iter()
|
.iter()
|
||||||
.find(|l| l.language_name == lang_str)
|
.find(|l| l.language_id == lang_str)
|
||||||
{
|
{
|
||||||
Some(l) => l,
|
Some(l) => l,
|
||||||
None => {
|
None => {
|
||||||
|
@ -266,11 +266,8 @@ pub fn language(lang_str: String) -> std::io::Result<()> {
|
||||||
let suggestions: Vec<&str> = syn_loader_conf
|
let suggestions: Vec<&str> = syn_loader_conf
|
||||||
.language
|
.language
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|l| {
|
.filter(|l| l.language_id.starts_with(lang_str.chars().next().unwrap()))
|
||||||
l.language_name
|
.map(|l| l.language_id.as_str())
|
||||||
.starts_with(lang_str.chars().next().unwrap())
|
|
||||||
})
|
|
||||||
.map(|l| l.language_name.as_str())
|
|
||||||
.collect();
|
.collect();
|
||||||
if !suggestions.is_empty() {
|
if !suggestions.is_empty() {
|
||||||
let suggestions = suggestions.join(", ");
|
let suggestions = suggestions.join(", ");
|
||||||
|
@ -304,7 +301,7 @@ pub fn language(lang_str: String) -> std::io::Result<()> {
|
||||||
.map(|formatter| formatter.command.to_string()),
|
.map(|formatter| formatter.command.to_string()),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
probe_parser(lang.grammar.as_ref().unwrap_or(&lang.language_name))?;
|
probe_parser(lang.grammar.as_ref().unwrap_or(&lang.language_id))?;
|
||||||
|
|
||||||
for ts_feat in TsFeature::all() {
|
for ts_feat in TsFeature::all() {
|
||||||
probe_treesitter_feature(&lang_str, *ts_feat)?
|
probe_treesitter_feature(&lang_str, *ts_feat)?
|
||||||
|
|
|
@ -498,7 +498,7 @@ pub mod completers {
|
||||||
let loader = editor.syn_loader.load();
|
let loader = editor.syn_loader.load();
|
||||||
let language_ids = loader
|
let language_ids = loader
|
||||||
.language_configs()
|
.language_configs()
|
||||||
.map(|config| &config.language_name)
|
.map(|config| &config.language_id)
|
||||||
.chain(std::iter::once(&text));
|
.chain(std::iter::once(&text));
|
||||||
|
|
||||||
fuzzy_match(input, language_ids, false)
|
fuzzy_match(input, language_ids, false)
|
||||||
|
|
|
@ -1,103 +1,116 @@
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
/// Comment and uncomment
|
mod simple {
|
||||||
#[tokio::test(flavor = "multi_thread")]
|
use super::*;
|
||||||
async fn test_injected_comment_tokens_simple() -> anyhow::Result<()> {
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
// Uncomment inner injection
|
async fn uncomment_inner_injection() -> anyhow::Result<()> {
|
||||||
test((
|
test((
|
||||||
indoc! {r#"\
|
indoc! {r#"\
|
||||||
<p>Comment toggle on this line should use the HTML comment token(s).</p>
|
<p>Comment toggle on this line should use the HTML comment token(s).</p>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
// Comment toggle #[|on this line s]#hould use the javascript comment token(s).
|
// Comment toggle #[|on this line s]#hould use the javascript comment token(s).
|
||||||
foo();
|
foo();
|
||||||
</script>
|
</script>
|
||||||
"#},
|
"#},
|
||||||
":lang html<ret> c",
|
":lang html<ret> c",
|
||||||
indoc! {r#"\
|
indoc! {r#"\
|
||||||
<p>Comment toggle on this line should use the HTML comment token(s).</p>
|
<p>Comment toggle on this line should use the HTML comment token(s).</p>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
Comment toggle #[|on this line s]#hould use the javascript comment token(s).
|
Comment toggle #[|on this line s]#hould use the javascript comment token(s).
|
||||||
foo();
|
foo();
|
||||||
</script>
|
</script>
|
||||||
"#},
|
"#},
|
||||||
))
|
))
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
// Comment inner injection
|
Ok(())
|
||||||
test((
|
}
|
||||||
indoc! {r#"\
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
|
async fn comment_inner_injection() -> anyhow::Result<()> {
|
||||||
|
test((
|
||||||
|
indoc! {r#"\
|
||||||
<p>Comment toggle on this line should use the HTML comment token(s).</p>
|
<p>Comment toggle on this line should use the HTML comment token(s).</p>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
Comment toggle #[|on this line s]#hould use the javascript comment token(s).
|
Comment toggle #[|on this line s]#hould use the javascript comment token(s).
|
||||||
foo();
|
foo();
|
||||||
</script>
|
</script>
|
||||||
"#},
|
"#},
|
||||||
":lang html<ret> c",
|
":lang html<ret> c",
|
||||||
indoc! {r#"\
|
indoc! {r#"\
|
||||||
<p>Comment toggle on this line should use the HTML comment token(s).</p>
|
<p>Comment toggle on this line should use the HTML comment token(s).</p>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
// Comment toggle #[|on this line s]#hould use the javascript comment token(s).
|
// Comment toggle #[|on this line s]#hould use the javascript comment token(s).
|
||||||
foo();
|
foo();
|
||||||
</script>
|
</script>
|
||||||
"#},
|
"#},
|
||||||
))
|
))
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
// Block comment inner injection
|
Ok(())
|
||||||
test((
|
}
|
||||||
indoc! {r#"\
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
|
async fn block_comment_inner_injection() -> anyhow::Result<()> {
|
||||||
|
test((
|
||||||
|
indoc! {r#"\
|
||||||
<p>Comment toggle on this line should use the HTML comment token(s).</p>
|
<p>Comment toggle on this line should use the HTML comment token(s).</p>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
// Comment toggle #[|on this line s]#hould use the javascript comment token(s).
|
// Comment toggle #[|on this line s]#hould use the javascript comment token(s).
|
||||||
foo();
|
foo();
|
||||||
</script>
|
</script>
|
||||||
"#},
|
"#},
|
||||||
":lang html<ret> C",
|
":lang html<ret> C",
|
||||||
indoc! {r#"\
|
indoc! {r#"\
|
||||||
<p>Comment toggle on this line should use the HTML comment token(s).</p>
|
<p>Comment toggle on this line should use the HTML comment token(s).</p>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
// Comment toggle #[|/* on this line s */]#hould use the javascript comment token(s).
|
// Comment toggle #[|/* on this line s */]#hould use the javascript comment token(s).
|
||||||
foo();
|
foo();
|
||||||
</script>
|
</script>
|
||||||
"#},
|
"#},
|
||||||
))
|
))
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
// Block uncomment inner injection
|
Ok(())
|
||||||
test((
|
}
|
||||||
indoc! {r#"\
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
|
async fn block_uncomment_inner_injection() -> anyhow::Result<()> {
|
||||||
|
test((
|
||||||
|
indoc! {r#"\
|
||||||
<p>Comment toggle on this line should use the HTML comment token(s).</p>
|
<p>Comment toggle on this line should use the HTML comment token(s).</p>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
// Comment toggle #[|/* on this line s */]#hould use the javascript comment token(s).
|
// Comment toggle #[|/* on this line s */]#hould use the javascript comment token(s).
|
||||||
foo();
|
foo();
|
||||||
</script>
|
</script>
|
||||||
"#},
|
"#},
|
||||||
":lang html<ret> C",
|
":lang html<ret> C",
|
||||||
indoc! {r#"\
|
indoc! {r#"\
|
||||||
<p>Comment toggle on this line should use the HTML comment token(s).</p>
|
<p>Comment toggle on this line should use the HTML comment token(s).</p>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
// Comment toggle #[|on this line s]#hould use the javascript comment token(s).
|
// Comment toggle #[|on this line s]#hould use the javascript comment token(s).
|
||||||
foo();
|
foo();
|
||||||
</script>
|
</script>
|
||||||
"#},
|
"#},
|
||||||
))
|
))
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread")]
|
mod injected_comment_tokens_continue_comment {
|
||||||
async fn test_injected_comment_tokens_continue_comment() -> anyhow::Result<()> {
|
use super::*;
|
||||||
test((
|
|
||||||
indoc! {r#"\
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
|
async fn adds_new_comment_on_newline() -> anyhow::Result<()> {
|
||||||
|
test((
|
||||||
|
indoc! {r#"
|
||||||
<p>Some text 1234</p>
|
<p>Some text 1234</p>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
// This line should #[|c]#ontinue comments
|
// This line should #[|c]#ontinue comments
|
||||||
foo();
|
foo();
|
||||||
</script>
|
</script>
|
||||||
"#},
|
"#},
|
||||||
":lang html<ret>i<ret>",
|
":lang html<ret>i<ret>",
|
||||||
indoc! {r#"\
|
indoc! {r#"
|
||||||
<p>Some text 1234</p>
|
<p>Some text 1234</p>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
// This line should
|
// This line should
|
||||||
|
@ -105,11 +118,15 @@ async fn test_injected_comment_tokens_continue_comment() -> anyhow::Result<()> {
|
||||||
foo();
|
foo();
|
||||||
</script>
|
</script>
|
||||||
"#},
|
"#},
|
||||||
))
|
))
|
||||||
.await?;
|
.await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
test((
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
indoc! {r#"\
|
async fn continues_comment() -> anyhow::Result<()> {
|
||||||
|
test((
|
||||||
|
indoc! {r#"\
|
||||||
<p>Some text 1234</p>
|
<p>Some text 1234</p>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
// This line should
|
// This line should
|
||||||
|
@ -117,8 +134,8 @@ async fn test_injected_comment_tokens_continue_comment() -> anyhow::Result<()> {
|
||||||
foo();
|
foo();
|
||||||
</script>
|
</script>
|
||||||
"#},
|
"#},
|
||||||
":lang html<ret>i<ret>",
|
":lang html<ret>i<ret>",
|
||||||
indoc! {r#"\
|
indoc! {r#"\
|
||||||
<p>Some text 1234</p>
|
<p>Some text 1234</p>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
// This line should
|
// This line should
|
||||||
|
@ -127,29 +144,14 @@ async fn test_injected_comment_tokens_continue_comment() -> anyhow::Result<()> {
|
||||||
foo();
|
foo();
|
||||||
</script>
|
</script>
|
||||||
"#},
|
"#},
|
||||||
))
|
))
|
||||||
.await?;
|
.await?;
|
||||||
|
Ok(())
|
||||||
test((
|
}
|
||||||
indoc! {r#"\
|
}
|
||||||
<p>Some text 1234</p>
|
|
||||||
<script type="text/javascript">
|
|
||||||
// This line should #[|c]#ontinue comments
|
|
||||||
foo();
|
|
||||||
</script>
|
|
||||||
"#},
|
|
||||||
":lang html<ret>i<ret>",
|
|
||||||
indoc! {r#"\
|
|
||||||
<p>Some text 1234</p>
|
|
||||||
<script type="text/javascript">
|
|
||||||
// This line should
|
|
||||||
// #[|c]#ontinue comments
|
|
||||||
foo();
|
|
||||||
</script>
|
|
||||||
"#},
|
|
||||||
))
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
|
async fn test_injected_comment_tokens_continue_comment_d() -> anyhow::Result<()> {
|
||||||
test((
|
test((
|
||||||
indoc! {r#"\
|
indoc! {r#"\
|
||||||
<p>Some text 1234</p>
|
<p>Some text 1234</p>
|
||||||
|
@ -173,72 +175,81 @@ async fn test_injected_comment_tokens_continue_comment() -> anyhow::Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Selections in different regions
|
mod multiple_selections_different_injection_layers {
|
||||||
#[tokio::test(flavor = "multi_thread")]
|
use super::*;
|
||||||
async fn test_injected_comment_tokens_multiple_selections() -> anyhow::Result<()> {
|
|
||||||
// Comments two different injection layers with different comments
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
test((
|
async fn comments_two_different_injection_layers_with_different_comments() -> anyhow::Result<()>
|
||||||
indoc! {r#"\
|
{
|
||||||
|
test((
|
||||||
|
indoc! {r#"\
|
||||||
<p>Comment toggle #[|on this line ]#should use the HTML comment token(s).</p>
|
<p>Comment toggle #[|on this line ]#should use the HTML comment token(s).</p>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
Comment toggle #(|on this line )#should use the javascript comment token(s).
|
Comment toggle #(|on this line )#should use the javascript comment token(s).
|
||||||
foo();
|
foo();
|
||||||
</script>
|
</script>
|
||||||
"#},
|
"#},
|
||||||
":lang html<ret> c",
|
":lang html<ret> c",
|
||||||
indoc! {r#"\
|
indoc! {r#"\
|
||||||
<!-- <p>Comment toggle #[|on this line ]#should use the HTML comment token(s).</p> -->
|
<!-- <p>Comment toggle #[|on this line ]#should use the HTML comment token(s).</p> -->
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
// Comment toggle #(|on this line )#should use the javascript comment token(s).
|
// Comment toggle #(|on this line )#should use the javascript comment token(s).
|
||||||
foo();
|
foo();
|
||||||
</script>
|
</script>
|
||||||
"#},
|
"#},
|
||||||
))
|
))
|
||||||
.await?;
|
.await?;
|
||||||
|
Ok(())
|
||||||
// Uncomments two different injection layers with different comments
|
}
|
||||||
test((
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
indoc! {r#"\
|
async fn uncomments_two_different_injection_layers_with_different_comments(
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
|
test((
|
||||||
|
indoc! {r#"\
|
||||||
<!-- <p>Comment toggle #[|on this line ]#should use the HTML comment token(s).</p> -->
|
<!-- <p>Comment toggle #[|on this line ]#should use the HTML comment token(s).</p> -->
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
// Comment toggle #(|on this line )#should use the javascript comment token(s).
|
// Comment toggle #(|on this line )#should use the javascript comment token(s).
|
||||||
foo();
|
foo();
|
||||||
</script>
|
</script>
|
||||||
"#},
|
"#},
|
||||||
":lang html<ret> c",
|
":lang html<ret> c",
|
||||||
indoc! {r#"\
|
indoc! {r#"\
|
||||||
<p>Comment toggle #[|on this line ]#should use the HTML comment token(s).</p>
|
<p>Comment toggle #[|on this line ]#should use the HTML comment token(s).</p>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
Comment toggle #(|on this line )#should use the javascript comment token(s).
|
Comment toggle #(|on this line )#should use the javascript comment token(s).
|
||||||
foo();
|
foo();
|
||||||
</script>
|
</script>
|
||||||
"#},
|
"#},
|
||||||
))
|
))
|
||||||
.await?;
|
.await?;
|
||||||
|
Ok(())
|
||||||
// Works with multiple selections
|
}
|
||||||
test((
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
indoc! {r#"\
|
async fn works_with_multiple_selections() -> anyhow::Result<()> {
|
||||||
|
test((
|
||||||
|
indoc! {r#"\
|
||||||
<p>Comment toggle #(|on this line )#should use the HTML comment token(s).</p>
|
<p>Comment toggle #(|on this line )#should use the HTML comment token(s).</p>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
// Comment toggle #[|on this line ]#should use the javascript comment token(s).
|
// Comment toggle #[|on this line ]#should use the javascript comment token(s).
|
||||||
foo();
|
foo();
|
||||||
</script>
|
</script>
|
||||||
"#},
|
"#},
|
||||||
":lang html<ret> c",
|
":lang html<ret> c",
|
||||||
indoc! {r#"\
|
indoc! {r#"\
|
||||||
<!-- <p>Comment toggle #(|on this line )#should use the HTML comment token(s).</p> -->
|
<!-- <p>Comment toggle #(|on this line )#should use the HTML comment token(s).</p> -->
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
Comment toggle #[|on this line ]#should use the javascript comment token(s).
|
Comment toggle #[|on this line ]#should use the javascript comment token(s).
|
||||||
foo();
|
foo();
|
||||||
</script>
|
</script>
|
||||||
"#},
|
"#},
|
||||||
))
|
))
|
||||||
.await?;
|
.await?;
|
||||||
|
Ok(())
|
||||||
// Works with nested injection layers: html, js then css
|
}
|
||||||
test((
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
indoc! {r#"\
|
async fn works_with_nested_injection_layers_html_js_then_css() -> anyhow::Result<()> {
|
||||||
|
test((
|
||||||
|
indoc! {r#"\
|
||||||
<!-- <p>Comment toggle #(|on this line)# should use the HTML comment token(s).</p> -->
|
<!-- <p>Comment toggle #(|on this line)# should use the HTML comment token(s).</p> -->
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
// Comment toggle #(|on this line)# should use the javascript comment token(s).
|
// Comment toggle #(|on this line)# should use the javascript comment token(s).
|
||||||
|
@ -250,8 +261,8 @@ async fn test_injected_comment_tokens_multiple_selections() -> anyhow::Result<()
|
||||||
`
|
`
|
||||||
</script>
|
</script>
|
||||||
"#},
|
"#},
|
||||||
":lang html<ret> c",
|
":lang html<ret> c",
|
||||||
indoc! {r#"\
|
indoc! {r#"\
|
||||||
<p>Comment toggle #(|on this line)# should use the HTML comment token(s).</p>
|
<p>Comment toggle #(|on this line)# should use the HTML comment token(s).</p>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
Comment toggle #(|on this line)# should use the javascript comment token(s).
|
Comment toggle #(|on this line)# should use the javascript comment token(s).
|
||||||
|
@ -263,12 +274,14 @@ async fn test_injected_comment_tokens_multiple_selections() -> anyhow::Result<()
|
||||||
`
|
`
|
||||||
</script>
|
</script>
|
||||||
"#},
|
"#},
|
||||||
))
|
))
|
||||||
.await?;
|
.await?;
|
||||||
|
Ok(())
|
||||||
// Full-line selection commenting
|
}
|
||||||
test((
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
indoc! {r#"\
|
async fn full_line_selection_commenting() -> anyhow::Result<()> {
|
||||||
|
test((
|
||||||
|
indoc! {r#"\
|
||||||
<p>Comment toggle on this line should use the HTML comment token(s).</p>
|
<p>Comment toggle on this line should use the HTML comment token(s).</p>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
// Comment toggle on this line should use the javascript comment token(s).
|
// Comment toggle on this line should use the javascript comment token(s).
|
||||||
|
@ -280,8 +293,8 @@ async fn test_injected_comment_tokens_multiple_selections() -> anyhow::Result<()
|
||||||
`;
|
`;
|
||||||
</script>
|
</script>
|
||||||
"#},
|
"#},
|
||||||
":lang html<ret> c",
|
":lang html<ret> c",
|
||||||
indoc! {r#"\
|
indoc! {r#"\
|
||||||
<p>Comment toggle on this line should use the HTML comment token(s).</p>
|
<p>Comment toggle on this line should use the HTML comment token(s).</p>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
// Comment toggle on this line should use the javascript comment token(s).
|
// Comment toggle on this line should use the javascript comment token(s).
|
||||||
|
@ -293,10 +306,10 @@ async fn test_injected_comment_tokens_multiple_selections() -> anyhow::Result<()
|
||||||
`;
|
`;
|
||||||
</script>
|
</script>
|
||||||
"#},
|
"#},
|
||||||
))
|
))
|
||||||
.await?;
|
.await?;
|
||||||
test((
|
test((
|
||||||
indoc! {r#"\
|
indoc! {r#"\
|
||||||
<p>Comment toggle on this line should use the HTML comment token(s).</p>
|
<p>Comment toggle on this line should use the HTML comment token(s).</p>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
// Comment toggle on this line should use the javascript comment token(s).
|
// Comment toggle on this line should use the javascript comment token(s).
|
||||||
|
@ -308,8 +321,8 @@ async fn test_injected_comment_tokens_multiple_selections() -> anyhow::Result<()
|
||||||
`;
|
`;
|
||||||
</script>
|
</script>
|
||||||
"#},
|
"#},
|
||||||
":lang html<ret> c",
|
":lang html<ret> c",
|
||||||
indoc! {r#"\
|
indoc! {r#"\
|
||||||
<p>Comment toggle on this line should use the HTML comment token(s).</p>
|
<p>Comment toggle on this line should use the HTML comment token(s).</p>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
// Comment toggle on this line should use the javascript comment token(s).
|
// Comment toggle on this line should use the javascript comment token(s).
|
||||||
|
@ -321,146 +334,152 @@ async fn test_injected_comment_tokens_multiple_selections() -> anyhow::Result<()
|
||||||
`;
|
`;
|
||||||
</script>
|
</script>
|
||||||
"#},
|
"#},
|
||||||
))
|
))
|
||||||
.await?;
|
.await?;
|
||||||
|
Ok(())
|
||||||
// Works with block comment toggle across different layers
|
}
|
||||||
test((
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
indoc! {r#"\
|
async fn block_comment_toggle_across_different_layers() -> anyhow::Result<()> {
|
||||||
|
test((
|
||||||
|
indoc! {r#"\
|
||||||
<p>Comment toggle #(|on this line)# should use the HTML comment token(s).</p>
|
<p>Comment toggle #(|on this line)# should use the HTML comment token(s).</p>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
// Comment toggle #[|on this line]# should use the javascript comment token(s).
|
// Comment toggle #[|on this line]# should use the javascript comment token(s).
|
||||||
foo();
|
foo();
|
||||||
</script>
|
</script>
|
||||||
"#},
|
"#},
|
||||||
":lang html<ret> C",
|
":lang html<ret> C",
|
||||||
indoc! {r#"\
|
indoc! {r#"\
|
||||||
<p>Comment toggle #(|<!-- on this line -->)# should use the HTML comment token(s).</p>
|
<p>Comment toggle #(|<!-- on this line -->)# should use the HTML comment token(s).</p>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
// Comment toggle #[|/* on this line */]# should use the javascript comment token(s).
|
// Comment toggle #[|/* on this line */]# should use the javascript comment token(s).
|
||||||
foo();
|
foo();
|
||||||
</script>
|
</script>
|
||||||
"#},
|
"#},
|
||||||
))
|
))
|
||||||
.await?;
|
.await?;
|
||||||
|
Ok(())
|
||||||
// Many selections on the same line
|
}
|
||||||
test((
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
indoc! {r#"\
|
async fn multiple_selections_same_line() -> anyhow::Result<()> {
|
||||||
<p>C#[|o]#mment t#(|o)#ggle #(|o)#n this line sh#(|o)#uld use the HTML c#(|o)#mment t#(|o)#ken(s).</p>
|
test((
|
||||||
<script type="text/javascript">
|
indoc! {r#"\
|
||||||
// Comment toggle on this line should use the javascript comment token(s).
|
<p>C#[|o]#mment t#(|o)#ggle #(|o)#n this line sh#(|o)#uld use the HTML c#(|o)#mment t#(|o)#ken(s).</p>
|
||||||
foo();
|
<script type="text/javascript">
|
||||||
css`
|
// Comment toggle on this line should use the javascript comment token(s).
|
||||||
html {
|
foo();
|
||||||
background-color: red;
|
css`
|
||||||
}
|
html {
|
||||||
`;
|
background-color: red;
|
||||||
</script>
|
}
|
||||||
"#},
|
`;
|
||||||
":lang html<ret> C",
|
</script>
|
||||||
indoc! {r#"\
|
"#},
|
||||||
<p>C#[|<!-- o -->]#mment t#(|<!-- o -->)#ggle #(|<!-- o -->)#n this line sh#(|<!-- o -->)#uld use the HTML c#(|<!-- o -->)#mment t#(|<!-- o -->)#ken(s).</p>
|
":lang html<ret> C",
|
||||||
<script type="text/javascript">
|
indoc! {r#"\
|
||||||
// Comment toggle on this line should use the javascript comment token(s).
|
<p>C#[|<!-- o -->]#mment t#(|<!-- o -->)#ggle #(|<!-- o -->)#n this line sh#(|<!-- o -->)#uld use the HTML c#(|<!-- o -->)#mment t#(|<!-- o -->)#ken(s).</p>
|
||||||
foo();
|
<script type="text/javascript">
|
||||||
css`
|
// Comment toggle on this line should use the javascript comment token(s).
|
||||||
html {
|
foo();
|
||||||
background-color: red;
|
css`
|
||||||
}
|
html {
|
||||||
`;
|
background-color: red;
|
||||||
</script>
|
}
|
||||||
"#},
|
`;
|
||||||
))
|
</script>
|
||||||
.await?;
|
"#},
|
||||||
test((
|
))
|
||||||
indoc! {r#"\
|
.await?;
|
||||||
<p>C#[|<!-- o -->]#mment t#(|<!-- o -->)#ggle #(|<!-- o -->)#n this line sh#(|<!-- o -->)#uld use the HTML c#(|<!-- o -->)#mment t#(|<!-- o -->)#ken(s).</p>
|
test((
|
||||||
<script type="text/javascript">
|
indoc! {r#"\
|
||||||
// Comment toggle on this line should use the javascript comment token(s).
|
<p>C#[|<!-- o -->]#mment t#(|<!-- o -->)#ggle #(|<!-- o -->)#n this line sh#(|<!-- o -->)#uld use the HTML c#(|<!-- o -->)#mment t#(|<!-- o -->)#ken(s).</p>
|
||||||
foo();
|
<script type="text/javascript">
|
||||||
css`
|
// Comment toggle on this line should use the javascript comment token(s).
|
||||||
html {
|
foo();
|
||||||
background-color: red;
|
css`
|
||||||
}
|
html {
|
||||||
`;
|
background-color: red;
|
||||||
</script>
|
}
|
||||||
"#},
|
`;
|
||||||
":lang html<ret> C",
|
</script>
|
||||||
indoc! {r#"\
|
"#},
|
||||||
<p>C#[|o]#mment t#(|o)#ggle #(|o)#n this line sh#(|o)#uld use the HTML c#(|o)#mment t#(|o)#ken(s).</p>
|
":lang html<ret> C",
|
||||||
<script type="text/javascript">
|
indoc! {r#"\
|
||||||
// Comment toggle on this line should use the javascript comment token(s).
|
<p>C#[|o]#mment t#(|o)#ggle #(|o)#n this line sh#(|o)#uld use the HTML c#(|o)#mment t#(|o)#ken(s).</p>
|
||||||
foo();
|
<script type="text/javascript">
|
||||||
css`
|
// Comment toggle on this line should use the javascript comment token(s).
|
||||||
html {
|
foo();
|
||||||
background-color: red;
|
css`
|
||||||
}
|
html {
|
||||||
`;
|
background-color: red;
|
||||||
</script>
|
}
|
||||||
"#},
|
`;
|
||||||
))
|
</script>
|
||||||
.await?;
|
"#},
|
||||||
|
))
|
||||||
// Many single-selections
|
.await?;
|
||||||
test((
|
Ok(())
|
||||||
indoc! {r#"\
|
}
|
||||||
<p>C#[|o]#mment t#(|o)#ggle #(|o)#n this line sh#(|o)#uld use the HTML c#(|o)#mment t#(|o)#ken(s).</p>
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
<script type="text/javascript">
|
async fn many_single_line_selections() -> anyhow::Result<()> {
|
||||||
// C#(|o)#mment t#(|o)#ggle #(|o)#n this line sh#(|o)#uld use the javascript c#(|o)#mment t#(|o)#ken(s).
|
test((
|
||||||
f#(|o)##(|o)#();
|
indoc! {r#"\
|
||||||
css`
|
<p>C#[|o]#mment t#(|o)#ggle #(|o)#n this line sh#(|o)#uld use the HTML c#(|o)#mment t#(|o)#ken(s).</p>
|
||||||
html {
|
<script type="text/javascript">
|
||||||
backgr#(|o)#und-c#(|o)#l#(|o)#r: red;
|
// C#(|o)#mment t#(|o)#ggle #(|o)#n this line sh#(|o)#uld use the javascript c#(|o)#mment t#(|o)#ken(s).
|
||||||
}
|
f#(|o)##(|o)#();
|
||||||
`;
|
css`
|
||||||
</script>
|
html {
|
||||||
"#},
|
backgr#(|o)#und-c#(|o)#l#(|o)#r: red;
|
||||||
":lang html<ret> C",
|
}
|
||||||
indoc! {r#"\
|
`;
|
||||||
<p>C#[|<!-- o -->]#mment t#(|<!-- o -->)#ggle #(|<!-- o -->)#n this line sh#(|<!-- o -->)#uld use the HTML c#(|<!-- o -->)#mment t#(|<!-- o -->)#ken(s).</p>
|
</script>
|
||||||
<script type="text/javascript">
|
"#},
|
||||||
// C#(|/* o */)#mment t#(|/* o */)#ggle #(|/* o */)#n this line sh#(|/* o */)#uld use the javascript c#(|/* o */)#mment t#(|/* o */)#ken(s).
|
":lang html<ret> C",
|
||||||
f#(|/* o */)##(|/* o */)#();
|
indoc! {r#"\
|
||||||
css`
|
<p>C#[|<!-- o -->]#mment t#(|<!-- o -->)#ggle #(|<!-- o -->)#n this line sh#(|<!-- o -->)#uld use the HTML c#(|<!-- o -->)#mment t#(|<!-- o -->)#ken(s).</p>
|
||||||
html {
|
<script type="text/javascript">
|
||||||
backgr#(|/* o */)#und-c#(|/* o */)#l#(|/* o */)#r: red;
|
// C#(|/* o */)#mment t#(|/* o */)#ggle #(|/* o */)#n this line sh#(|/* o */)#uld use the javascript c#(|/* o */)#mment t#(|/* o */)#ken(s).
|
||||||
}
|
f#(|/* o */)##(|/* o */)#();
|
||||||
`;
|
css`
|
||||||
</script>
|
html {
|
||||||
"#},
|
backgr#(|/* o */)#und-c#(|/* o */)#l#(|/* o */)#r: red;
|
||||||
))
|
}
|
||||||
.await?;
|
`;
|
||||||
test((
|
</script>
|
||||||
indoc! {r#"\
|
"#},
|
||||||
<p>C#[|<!-- o -->]#mment t#(|<!-- o -->)#ggle #(|<!-- o -->)#n this line sh#(|<!-- o -->)#uld use the HTML c#(|<!-- o -->)#mment t#(|<!-- o -->)#ken(s).</p>
|
))
|
||||||
<script type="text/javascript">
|
.await?;
|
||||||
// C#(|/* o */)#mment t#(|/* o */)#ggle #(|/* o */)#n this line sh#(|/* o */)#uld use the javascript c#(|/* o */)#mment t#(|/* o */)#ken(s).
|
test((
|
||||||
f#(|/* o */)##(|/* o */)#();
|
indoc! {r#"\
|
||||||
css`
|
<p>C#[|<!-- o -->]#mment t#(|<!-- o -->)#ggle #(|<!-- o -->)#n this line sh#(|<!-- o -->)#uld use the HTML c#(|<!-- o -->)#mment t#(|<!-- o -->)#ken(s).</p>
|
||||||
html {
|
<script type="text/javascript">
|
||||||
backgr#(|/* o */)#und-c#(|/* o */)#l#(|/* o */)#r: red;
|
// C#(|/* o */)#mment t#(|/* o */)#ggle #(|/* o */)#n this line sh#(|/* o */)#uld use the javascript c#(|/* o */)#mment t#(|/* o */)#ken(s).
|
||||||
}
|
f#(|/* o */)##(|/* o */)#();
|
||||||
`;
|
css`
|
||||||
</script>
|
html {
|
||||||
"#},
|
backgr#(|/* o */)#und-c#(|/* o */)#l#(|/* o */)#r: red;
|
||||||
":lang html<ret> C",
|
}
|
||||||
indoc! {r#"\
|
`;
|
||||||
<p>C#[|o]#mment t#(|o)#ggle #(|o)#n this line sh#(|o)#uld use the HTML c#(|o)#mment t#(|o)#ken(s).</p>
|
</script>
|
||||||
<script type="text/javascript">
|
"#},
|
||||||
// C#(|o)#mment t#(|o)#ggle #(|o)#n this line sh#(|o)#uld use the javascript c#(|o)#mment t#(|o)#ken(s).
|
":lang html<ret> C",
|
||||||
f#(|o)##(|o)#();
|
indoc! {r#"\
|
||||||
css`
|
<p>C#[|o]#mment t#(|o)#ggle #(|o)#n this line sh#(|o)#uld use the HTML c#(|o)#mment t#(|o)#ken(s).</p>
|
||||||
html {
|
<script type="text/javascript">
|
||||||
backgr#(|o)#und-c#(|o)#l#(|o)#r: red;
|
// C#(|o)#mment t#(|o)#ggle #(|o)#n this line sh#(|o)#uld use the javascript c#(|o)#mment t#(|o)#ken(s).
|
||||||
}
|
f#(|o)##(|o)#();
|
||||||
`;
|
css`
|
||||||
</script>
|
html {
|
||||||
"#},
|
backgr#(|o)#und-c#(|o)#l#(|o)#r: red;
|
||||||
))
|
}
|
||||||
.await?;
|
`;
|
||||||
|
</script>
|
||||||
Ok(())
|
"#},
|
||||||
|
))
|
||||||
|
.await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A selection that spans across several injections takes comment tokens
|
/// A selection that spans across several injections takes comment tokens
|
||||||
|
|
|
@ -213,7 +213,7 @@ pub struct Document {
|
||||||
// NOTE: this field should eventually go away - we should use the Editor's syn_loader instead
|
// NOTE: this field should eventually go away - we should use the Editor's syn_loader instead
|
||||||
// of storing a copy on every doc. Then we can remove the surrounding `Arc` and use the
|
// of storing a copy on every doc. Then we can remove the surrounding `Arc` and use the
|
||||||
// `ArcSwap` directly.
|
// `ArcSwap` directly.
|
||||||
syn_loader: Arc<ArcSwap<syntax::Loader>>,
|
pub syn_loader: Arc<ArcSwap<syntax::Loader>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default)]
|
#[derive(Debug, Clone, Default)]
|
||||||
|
@ -1787,7 +1787,7 @@ impl Document {
|
||||||
pub fn language_name(&self) -> Option<&str> {
|
pub fn language_name(&self) -> Option<&str> {
|
||||||
self.language
|
self.language
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|language| language.language_name.as_str())
|
.map(|language| language.language_id.as_str())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Language ID for the document. Either the `language-id`,
|
/// Language ID for the document. Either the `language-id`,
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
<!-- <p>Comment toggle #[|on this line ]#should use the HTML comment token(s).</p> -->
|
||||||
|
<script type="text/javascript">
|
||||||
|
// Comment toggle #(|on this line )#should use the javascript comment token(s).
|
||||||
|
foo();
|
||||||
|
</script>
|
|
@ -134,7 +134,7 @@ pub fn lang_features() -> Result<String, DynError> {
|
||||||
let mut langs = config
|
let mut langs = config
|
||||||
.language
|
.language
|
||||||
.iter()
|
.iter()
|
||||||
.map(|l| l.language_name.clone())
|
.map(|l| l.language_id.clone())
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
langs.sort_unstable();
|
langs.sort_unstable();
|
||||||
|
|
||||||
|
@ -148,9 +148,9 @@ pub fn lang_features() -> Result<String, DynError> {
|
||||||
let lc = config
|
let lc = config
|
||||||
.language
|
.language
|
||||||
.iter()
|
.iter()
|
||||||
.find(|l| l.language_name == lang)
|
.find(|l| l.language_id == lang)
|
||||||
.unwrap(); // lang comes from config
|
.unwrap(); // lang comes from config
|
||||||
row.push(lc.language_name.clone());
|
row.push(lc.language_id.clone());
|
||||||
|
|
||||||
for (_feat, support_list) in &ts_features_to_langs {
|
for (_feat, support_list) in &ts_features_to_langs {
|
||||||
row.push(
|
row.push(
|
||||||
|
|
Loading…
Reference in New Issue