]> git.lizzy.rs Git - rust.git/commitdiff
Move html highlightig to a separate module
authorAleksey Kladov <aleksey.kladov@gmail.com>
Wed, 26 Feb 2020 22:13:48 +0000 (23:13 +0100)
committerAleksey Kladov <aleksey.kladov@gmail.com>
Thu, 27 Feb 2020 08:32:00 +0000 (09:32 +0100)
crates/ra_ide/src/syntax_highlighting.rs
crates/ra_ide/src/syntax_highlighting/html.rs [new file with mode: 0644]

index c0f13f1713f120d93311e42f3227dfa6ed65c68d..4e95b9ce5630d772e2595b98f4df4651dcacafad 100644 (file)
@@ -1,9 +1,9 @@
 //! FIXME: write short doc here
 
 mod highlight;
+mod html;
 
 use hir::{Name, Semantics};
-use ra_db::SourceDatabase;
 use ra_ide_db::{
     defs::{classify_name, NameDefinition},
     RootDatabase,
@@ -19,6 +19,8 @@
 
 pub use highlight::{Highlight, HighlightModifier, HighlightModifiers, HighlightTag};
 
+pub(crate) use html::highlight_as_html;
+
 #[derive(Debug)]
 pub struct HighlightedRange {
     pub range: TextRange,
@@ -257,69 +259,6 @@ fn hash<T: std::hash::Hash + std::fmt::Debug>(x: T) -> u64 {
     }
 }
 
-pub(crate) fn highlight_as_html(db: &RootDatabase, file_id: FileId, rainbow: bool) -> String {
-    let parse = db.parse(file_id);
-
-    fn rainbowify(seed: u64) -> String {
-        use rand::prelude::*;
-        let mut rng = SmallRng::seed_from_u64(seed);
-        format!(
-            "hsl({h},{s}%,{l}%)",
-            h = rng.gen_range::<u16, _, _>(0, 361),
-            s = rng.gen_range::<u16, _, _>(42, 99),
-            l = rng.gen_range::<u16, _, _>(40, 91),
-        )
-    }
-
-    let mut ranges = highlight(db, file_id, None);
-    ranges.sort_by_key(|it| it.range.start());
-    // quick non-optimal heuristic to intersect token ranges and highlighted ranges
-    let mut frontier = 0;
-    let mut could_intersect: Vec<&HighlightedRange> = Vec::new();
-
-    let mut buf = String::new();
-    buf.push_str(&STYLE);
-    buf.push_str("<pre><code>");
-    let tokens = parse.tree().syntax().descendants_with_tokens().filter_map(|it| it.into_token());
-    for token in tokens {
-        could_intersect.retain(|it| token.text_range().start() <= it.range.end());
-        while let Some(r) = ranges.get(frontier) {
-            if r.range.start() <= token.text_range().end() {
-                could_intersect.push(r);
-                frontier += 1;
-            } else {
-                break;
-            }
-        }
-        let text = html_escape(&token.text());
-        let ranges = could_intersect
-            .iter()
-            .filter(|it| token.text_range().is_subrange(&it.range))
-            .collect::<Vec<_>>();
-        if ranges.is_empty() {
-            buf.push_str(&text);
-        } else {
-            let classes = ranges
-                .iter()
-                .map(|it| it.highlight.to_string().replace('.', " "))
-                .collect::<Vec<_>>()
-                .join(" ");
-            let binding_hash = ranges.first().and_then(|x| x.binding_hash);
-            let color = match (rainbow, binding_hash) {
-                (true, Some(hash)) => format!(
-                    " data-binding-hash=\"{}\" style=\"color: {};\"",
-                    hash,
-                    rainbowify(hash)
-                ),
-                _ => "".into(),
-            };
-            buf.push_str(&format!("<span class=\"{}\"{}>{}</span>", classes, color, text));
-        }
-    }
-    buf.push_str("</code></pre>");
-    buf
-}
-
 fn highlight_name(db: &RootDatabase, def: NameDefinition) -> Highlight {
     match def {
         NameDefinition::Macro(_) => HighlightTag::Macro,
@@ -348,39 +287,6 @@ fn highlight_name(db: &RootDatabase, def: NameDefinition) -> Highlight {
     .into()
 }
 
-//FIXME: like, real html escaping
-fn html_escape(text: &str) -> String {
-    text.replace("<", "&lt;").replace(">", "&gt;")
-}
-
-const STYLE: &str = "
-<style>
-body                { margin: 0; }
-pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padding: 0.4em; }
-
-.comment            { color: #7F9F7F; }
-.string             { color: #CC9393; }
-.field              { color: #94BFF3; }
-.function           { color: #93E0E3; }
-.parameter          { color: #94BFF3; }
-.text               { color: #DCDCCC; }
-.type               { color: #7CB8BB; }
-.type.builtin       { color: #8CD0D3; }
-.type.param         { color: #20999D; }
-.attribute          { color: #94BFF3; }
-.literal            { color: #BFEBBF; }
-.literal.numeric    { color: #6A8759; }
-.macro              { color: #94BFF3; }
-.module             { color: #AFD8AF; }
-.variable           { color: #DCDCCC; }
-.variable.mut       { color: #DCDCCC; text-decoration: underline; }
-
-.keyword            { color: #F0DFAF; }
-.keyword.unsafe     { color: #DFAF8F; }
-.keyword.control    { color: #F0DFAF; font-weight: bold; }
-</style>
-";
-
 #[cfg(test)]
 mod tests {
     use std::fs;
diff --git a/crates/ra_ide/src/syntax_highlighting/html.rs b/crates/ra_ide/src/syntax_highlighting/html.rs
new file mode 100644 (file)
index 0000000..210d9a5
--- /dev/null
@@ -0,0 +1,104 @@
+//! Renders a bit of code as HTML.
+
+use ra_db::SourceDatabase;
+use ra_syntax::AstNode;
+
+use crate::{FileId, HighlightedRange, RootDatabase};
+
+use super::highlight;
+
+pub(crate) fn highlight_as_html(db: &RootDatabase, file_id: FileId, rainbow: bool) -> String {
+    let parse = db.parse(file_id);
+
+    fn rainbowify(seed: u64) -> String {
+        use rand::prelude::*;
+        let mut rng = SmallRng::seed_from_u64(seed);
+        format!(
+            "hsl({h},{s}%,{l}%)",
+            h = rng.gen_range::<u16, _, _>(0, 361),
+            s = rng.gen_range::<u16, _, _>(42, 99),
+            l = rng.gen_range::<u16, _, _>(40, 91),
+        )
+    }
+
+    let mut ranges = highlight(db, file_id, None);
+    ranges.sort_by_key(|it| it.range.start());
+    // quick non-optimal heuristic to intersect token ranges and highlighted ranges
+    let mut frontier = 0;
+    let mut could_intersect: Vec<&HighlightedRange> = Vec::new();
+
+    let mut buf = String::new();
+    buf.push_str(&STYLE);
+    buf.push_str("<pre><code>");
+    let tokens = parse.tree().syntax().descendants_with_tokens().filter_map(|it| it.into_token());
+    for token in tokens {
+        could_intersect.retain(|it| token.text_range().start() <= it.range.end());
+        while let Some(r) = ranges.get(frontier) {
+            if r.range.start() <= token.text_range().end() {
+                could_intersect.push(r);
+                frontier += 1;
+            } else {
+                break;
+            }
+        }
+        let text = html_escape(&token.text());
+        let ranges = could_intersect
+            .iter()
+            .filter(|it| token.text_range().is_subrange(&it.range))
+            .collect::<Vec<_>>();
+        if ranges.is_empty() {
+            buf.push_str(&text);
+        } else {
+            let classes = ranges
+                .iter()
+                .map(|it| it.highlight.to_string().replace('.', " "))
+                .collect::<Vec<_>>()
+                .join(" ");
+            let binding_hash = ranges.first().and_then(|x| x.binding_hash);
+            let color = match (rainbow, binding_hash) {
+                (true, Some(hash)) => format!(
+                    " data-binding-hash=\"{}\" style=\"color: {};\"",
+                    hash,
+                    rainbowify(hash)
+                ),
+                _ => "".into(),
+            };
+            buf.push_str(&format!("<span class=\"{}\"{}>{}</span>", classes, color, text));
+        }
+    }
+    buf.push_str("</code></pre>");
+    buf
+}
+
+//FIXME: like, real html escaping
+fn html_escape(text: &str) -> String {
+    text.replace("<", "&lt;").replace(">", "&gt;")
+}
+
+const STYLE: &str = "
+<style>
+body                { margin: 0; }
+pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padding: 0.4em; }
+
+.comment            { color: #7F9F7F; }
+.string             { color: #CC9393; }
+.field              { color: #94BFF3; }
+.function           { color: #93E0E3; }
+.parameter          { color: #94BFF3; }
+.text               { color: #DCDCCC; }
+.type               { color: #7CB8BB; }
+.type.builtin       { color: #8CD0D3; }
+.type.param         { color: #20999D; }
+.attribute          { color: #94BFF3; }
+.literal            { color: #BFEBBF; }
+.literal.numeric    { color: #6A8759; }
+.macro              { color: #94BFF3; }
+.module             { color: #AFD8AF; }
+.variable           { color: #DCDCCC; }
+.variable.mut       { color: #DCDCCC; text-decoration: underline; }
+
+.keyword            { color: #F0DFAF; }
+.keyword.unsafe     { color: #DFAF8F; }
+.keyword.control    { color: #F0DFAF; font-weight: bold; }
+</style>
+";