mirror of
https://github.com/YGGverse/Yoda.git
synced 2026-03-31 16:45:27 +00:00
use shared code widget, remove duplicated components (used in gemtext and markdown renderers)
This commit is contained in:
parent
45e8824a2e
commit
f4b1aa9ecc
19 changed files with 166 additions and 741 deletions
|
|
@ -1,12 +1,12 @@
|
|||
mod common;
|
||||
mod gemini;
|
||||
mod markdown;
|
||||
mod nex;
|
||||
mod plain;
|
||||
mod source;
|
||||
|
||||
use crate::{app::browser::window::tab::item::page::Page, profile::Profile};
|
||||
|
||||
use super::{ItemAction, WindowAction};
|
||||
use crate::{app::browser::window::tab::item::page::Page, profile::Profile};
|
||||
use adw::ClampScrollable;
|
||||
use gemini::Gemini;
|
||||
use gtk::{ScrolledWindow, TextView, glib::Uri};
|
||||
|
|
|
|||
|
|
@ -0,0 +1,4 @@
|
|||
/// Shared widgets:
|
||||
/// e.g. Gemtext and Markdown renderers have single implementation for the code blocks
|
||||
pub mod code;
|
||||
pub use code::Code;
|
||||
139
src/app/browser/window/tab/item/page/content/text/common/code.rs
Normal file
139
src/app/browser/window/tab/item/page/content/text/common/code.rs
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
mod ansi;
|
||||
mod syntax;
|
||||
|
||||
use gtk::{
|
||||
Align, Box, Button, Label, Orientation, PolicyType, ScrolledWindow, Separator, TextBuffer,
|
||||
TextTagTable, TextView, WrapMode,
|
||||
gdk::Display,
|
||||
glib::{ControlFlow, idle_add_local},
|
||||
prelude::{BoxExt, ButtonExt, DisplayExt, TextBufferExt, TextBufferExtManual, WidgetExt},
|
||||
};
|
||||
use std::{cell::Cell, rc::Rc};
|
||||
use syntax::Syntax;
|
||||
|
||||
pub struct Code {
|
||||
pub widget: Box,
|
||||
}
|
||||
|
||||
impl Code {
|
||||
pub fn init(parent: &TextView, source: &str, alt: Option<&String>) -> Self {
|
||||
let syntax = Syntax::new();
|
||||
let copied = Rc::new(Cell::new(None));
|
||||
|
||||
let widget = Box::builder()
|
||||
.css_classes(["card"])
|
||||
.halign(Align::Fill)
|
||||
.hexpand(true)
|
||||
.margin_bottom(MARGIN / 2)
|
||||
.orientation(Orientation::Vertical)
|
||||
.build();
|
||||
widget.append(&{
|
||||
let header = Box::builder()
|
||||
.halign(Align::Fill)
|
||||
.hexpand(true)
|
||||
.orientation(Orientation::Horizontal)
|
||||
.build();
|
||||
if let Some(label) = alt {
|
||||
header.append(
|
||||
&Label::builder()
|
||||
.halign(Align::Start)
|
||||
.hexpand(true)
|
||||
.label(label)
|
||||
.margin_bottom(MARGIN)
|
||||
.margin_end(MARGIN)
|
||||
.margin_start(MARGIN)
|
||||
.margin_top(MARGIN)
|
||||
.selectable(true)
|
||||
.build(),
|
||||
);
|
||||
}
|
||||
header.append(&{
|
||||
const TOGGLE_BUTTON_CLASS: &str = "dimmed";
|
||||
const TOGGLE_BUTTON_TOOLTIP: (&str, &str) = ("Copy", "Copied");
|
||||
let copy = Button::builder()
|
||||
.css_classes(["circular", "flat", TOGGLE_BUTTON_CLASS])
|
||||
.halign(Align::End)
|
||||
.icon_name("edit-copy-symbolic")
|
||||
.margin_bottom(MARGIN / 2)
|
||||
.margin_end(MARGIN / 2)
|
||||
.margin_start(MARGIN / 2)
|
||||
.margin_top(MARGIN / 2)
|
||||
.tooltip_text(TOGGLE_BUTTON_TOOLTIP.0)
|
||||
.valign(Align::Center)
|
||||
.build();
|
||||
copy.set_cursor_from_name(Some("pointer"));
|
||||
copy.connect_clicked({
|
||||
let source = String::from(source);
|
||||
let copied = copied.clone();
|
||||
move |this| {
|
||||
if let Some(prev) = copied.replace(Some(this.clone())) {
|
||||
prev.set_tooltip_text(Some(TOGGLE_BUTTON_TOOLTIP.0));
|
||||
prev.add_css_class(TOGGLE_BUTTON_CLASS)
|
||||
}
|
||||
this.set_tooltip_text(Some(TOGGLE_BUTTON_TOOLTIP.1));
|
||||
this.remove_css_class(TOGGLE_BUTTON_CLASS);
|
||||
|
||||
Display::default().unwrap().clipboard().set_text(&source)
|
||||
}
|
||||
});
|
||||
copy
|
||||
});
|
||||
header
|
||||
});
|
||||
widget.append(
|
||||
&Separator::builder()
|
||||
.orientation(Orientation::Horizontal)
|
||||
.build(),
|
||||
);
|
||||
widget.append(&{
|
||||
ScrolledWindow::builder()
|
||||
.child(
|
||||
&TextView::builder()
|
||||
.buffer(&{
|
||||
let b = TextBuffer::new(Some(&TextTagTable::new()));
|
||||
let mut start = b.start_iter();
|
||||
match syntax.highlight(source, alt) {
|
||||
Ok(highlight) => {
|
||||
for (syntax_tag, entity) in highlight {
|
||||
assert!(b.tag_table().add(&syntax_tag));
|
||||
b.insert_with_tags(&mut start, &entity, &[&syntax_tag])
|
||||
}
|
||||
}
|
||||
Err(_) => {
|
||||
// Try ANSI/SGR format (terminal emulation) @TODO optional
|
||||
for (syntax_tag, entity) in ansi::format(source) {
|
||||
assert!(b.tag_table().add(&syntax_tag));
|
||||
b.insert_with_tags(&mut start, &entity, &[&syntax_tag])
|
||||
}
|
||||
}
|
||||
}
|
||||
b
|
||||
})
|
||||
.css_classes(["code-block"])
|
||||
.cursor_visible(false)
|
||||
.editable(false)
|
||||
.wrap_mode(WrapMode::None)
|
||||
.build(),
|
||||
)
|
||||
.margin_bottom(MARGIN)
|
||||
.margin_end(MARGIN)
|
||||
.margin_start(MARGIN)
|
||||
.margin_top(MARGIN)
|
||||
.vscrollbar_policy(PolicyType::Never)
|
||||
.hscrollbar_policy(PolicyType::Automatic)
|
||||
.propagate_natural_height(true)
|
||||
.build()
|
||||
});
|
||||
idle_add_local({
|
||||
let widget = widget.clone();
|
||||
let parent = parent.clone();
|
||||
move || {
|
||||
widget.set_width_request(parent.width() - 22);
|
||||
ControlFlow::Break
|
||||
}
|
||||
});
|
||||
Self { widget }
|
||||
}
|
||||
}
|
||||
|
||||
const MARGIN: i32 = 16;
|
||||
|
|
@ -1,8 +1,6 @@
|
|||
mod ansi;
|
||||
pub mod error;
|
||||
mod gutter;
|
||||
mod icon;
|
||||
mod syntax;
|
||||
mod tag;
|
||||
|
||||
use super::{ItemAction, WindowAction};
|
||||
|
|
@ -20,7 +18,6 @@ use gutter::Gutter;
|
|||
use icon::Icon;
|
||||
use sourceview::prelude::{ActionExt, ActionMapExt, DisplayExt, ToVariant};
|
||||
use std::{cell::Cell, collections::HashMap, rc::Rc};
|
||||
use syntax::Syntax;
|
||||
use tag::Tag;
|
||||
|
||||
pub const NEW_LINE: &str = "\n";
|
||||
|
|
@ -63,9 +60,6 @@ impl Gemini {
|
|||
RGBA::new(0.208, 0.518, 0.894, 0.9),
|
||||
);
|
||||
|
||||
// Init syntect highlight features
|
||||
let syntax = Syntax::new();
|
||||
|
||||
// Init icons
|
||||
let icon = Icon::new();
|
||||
|
||||
|
|
@ -125,60 +119,17 @@ impl Gemini {
|
|||
Some(ref mut c) => {
|
||||
match c.continue_from(line) {
|
||||
Ok(()) => {
|
||||
// Close tag found:
|
||||
// Closing tag found:
|
||||
if c.is_completed {
|
||||
// Is alt provided
|
||||
let alt = match c.alt {
|
||||
Some(ref alt) => {
|
||||
// Insert alt value to the main buffer
|
||||
buffer.insert_with_tags(
|
||||
&mut buffer.end_iter(),
|
||||
alt.as_str(),
|
||||
&[&tag.title],
|
||||
);
|
||||
|
||||
// Append new line after alt text
|
||||
buffer.insert(&mut buffer.end_iter(), NEW_LINE);
|
||||
|
||||
// Return value as wanted also for syntax highlight detection
|
||||
Some(alt)
|
||||
}
|
||||
None => None,
|
||||
};
|
||||
|
||||
// Begin code block construction
|
||||
// Try auto-detect code syntax for given `value` and `alt` @TODO optional
|
||||
match syntax.highlight(&c.value, alt) {
|
||||
Ok(highlight) => {
|
||||
for (syntax_tag, entity) in highlight {
|
||||
// Register new tag
|
||||
if !tag.text_tag_table.add(&syntax_tag) {
|
||||
todo!()
|
||||
}
|
||||
// Append tag to buffer
|
||||
buffer.insert_with_tags(
|
||||
&mut buffer.end_iter(),
|
||||
&entity,
|
||||
&[&syntax_tag],
|
||||
);
|
||||
}
|
||||
}
|
||||
Err(_) => {
|
||||
// Try ANSI/SGR format (terminal emulation) @TODO optional
|
||||
for (syntax_tag, entity) in ansi::format(&c.value) {
|
||||
// Register new tag
|
||||
if !tag.text_tag_table.add(&syntax_tag) {
|
||||
todo!()
|
||||
}
|
||||
// Append tag to buffer
|
||||
buffer.insert_with_tags(
|
||||
&mut buffer.end_iter(),
|
||||
&entity,
|
||||
&[&syntax_tag],
|
||||
);
|
||||
}
|
||||
} // @TODO handle
|
||||
}
|
||||
text_view.add_child_at_anchor(
|
||||
&super::common::Code::init(
|
||||
&text_view,
|
||||
c.value.trim_end(),
|
||||
c.alt.as_ref(),
|
||||
)
|
||||
.widget,
|
||||
&buffer.create_child_anchor(&mut buffer.end_iter()),
|
||||
);
|
||||
|
||||
// Reset
|
||||
code = None;
|
||||
|
|
|
|||
|
|
@ -1,29 +0,0 @@
|
|||
use gtk::{TextTag, WrapMode};
|
||||
|
||||
/// Default [TextTag](https://docs.gtk.org/gtk4/class.TextTag.html) preset
|
||||
/// for ANSI buffer
|
||||
pub struct Tag {
|
||||
pub text_tag: TextTag,
|
||||
}
|
||||
|
||||
impl Default for Tag {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl Tag {
|
||||
// Constructors
|
||||
|
||||
/// Create new `Self`
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
text_tag: TextTag::builder()
|
||||
.family("monospace") // @TODO
|
||||
.left_margin(28)
|
||||
.scale(0.81) // * the rounded `0.8` value crops text for some reason @TODO
|
||||
.wrap_mode(WrapMode::None)
|
||||
.build(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
use gtk::{TextTag, WrapMode};
|
||||
|
||||
/// Default [TextTag](https://docs.gtk.org/gtk4/class.TextTag.html) preset
|
||||
/// for syntax highlight buffer
|
||||
pub struct Tag {
|
||||
pub text_tag: TextTag,
|
||||
}
|
||||
|
||||
impl Default for Tag {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl Tag {
|
||||
// Constructors
|
||||
|
||||
/// Create new `Self`
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
text_tag: TextTag::builder()
|
||||
.family("monospace") // @TODO
|
||||
.left_margin(28)
|
||||
.scale(0.81) // * the rounded `0.8` value crops text for some reason @TODO
|
||||
.wrap_mode(WrapMode::None)
|
||||
.build(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,14 +2,12 @@ mod header;
|
|||
mod list;
|
||||
mod plain;
|
||||
mod quote;
|
||||
mod title;
|
||||
|
||||
use gtk::{TextTag, TextTagTable};
|
||||
use header::Header;
|
||||
use list::List;
|
||||
use plain::Plain;
|
||||
use quote::Quote;
|
||||
use title::Title;
|
||||
|
||||
pub struct Tag {
|
||||
pub text_tag_table: TextTagTable,
|
||||
|
|
@ -19,7 +17,6 @@ pub struct Tag {
|
|||
pub h3: TextTag,
|
||||
pub list: TextTag,
|
||||
pub quote: TextTag,
|
||||
pub title: TextTag,
|
||||
pub plain: TextTag,
|
||||
}
|
||||
|
||||
|
|
@ -38,7 +35,6 @@ impl Tag {
|
|||
let h3 = TextTag::h3();
|
||||
let list = TextTag::list();
|
||||
let quote = TextTag::quote();
|
||||
let title = TextTag::title();
|
||||
let plain = TextTag::plain();
|
||||
|
||||
// Init tag table
|
||||
|
|
@ -47,7 +43,6 @@ impl Tag {
|
|||
text_tag_table.add(&h1);
|
||||
text_tag_table.add(&h2);
|
||||
text_tag_table.add(&h3);
|
||||
text_tag_table.add(&title);
|
||||
text_tag_table.add(&list);
|
||||
text_tag_table.add("e);
|
||||
text_tag_table.add(&plain);
|
||||
|
|
@ -60,7 +55,6 @@ impl Tag {
|
|||
h3,
|
||||
list,
|
||||
quote,
|
||||
title,
|
||||
plain,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,16 +0,0 @@
|
|||
use gtk::{TextTag, WrapMode};
|
||||
|
||||
pub trait Title {
|
||||
fn title() -> Self;
|
||||
}
|
||||
|
||||
impl Title for TextTag {
|
||||
fn title() -> Self {
|
||||
TextTag::builder()
|
||||
.pixels_above_lines(4)
|
||||
.pixels_below_lines(8)
|
||||
.weight(500)
|
||||
.wrap_mode(WrapMode::None)
|
||||
.build()
|
||||
}
|
||||
}
|
||||
|
|
@ -1,18 +1,10 @@
|
|||
mod ansi;
|
||||
mod syntax;
|
||||
|
||||
use gtk::{
|
||||
Align, Box, Button, Label, Orientation, PolicyType, ScrolledWindow, Separator, TextBuffer,
|
||||
TextSearchFlags, TextTagTable, TextView, WrapMode,
|
||||
gdk::Display,
|
||||
glib::{ControlFlow, GString, idle_add_local, uuid_string_random},
|
||||
prelude::{
|
||||
BoxExt, ButtonExt, DisplayExt, TextBufferExt, TextBufferExtManual, TextViewExt, WidgetExt,
|
||||
},
|
||||
TextBuffer, TextSearchFlags, TextView,
|
||||
glib::{GString, uuid_string_random},
|
||||
prelude::{TextBufferExt, TextBufferExtManual, TextViewExt},
|
||||
};
|
||||
use regex::Regex;
|
||||
use std::{cell::Cell, collections::HashMap, rc::Rc};
|
||||
use syntax::Syntax;
|
||||
use std::collections::HashMap;
|
||||
|
||||
const REGEX_CODE: &str = r"(?s)```[ \t]*(?P<alt>.*?)\n(?P<data>.*?)```";
|
||||
|
||||
|
|
@ -69,8 +61,6 @@ impl Code {
|
|||
/// Apply code `Tag` to given `TextView` using `Self.index`
|
||||
pub fn render(&mut self, text_view: &TextView) {
|
||||
let buffer = text_view.buffer();
|
||||
let syntax = Syntax::new();
|
||||
let copied = Rc::new(Cell::new(None));
|
||||
for (k, v) in self.0.iter() {
|
||||
while let Some((mut m_start, mut m_end)) =
|
||||
buffer
|
||||
|
|
@ -79,134 +69,14 @@ impl Code {
|
|||
{
|
||||
buffer.delete(&mut m_start, &mut m_end);
|
||||
text_view.add_child_at_anchor(
|
||||
&{
|
||||
const MARGIN: i32 = 16;
|
||||
let widget = Box::builder()
|
||||
.css_classes(["card"])
|
||||
.halign(Align::Fill)
|
||||
.hexpand(true)
|
||||
.margin_bottom(MARGIN / 2)
|
||||
.orientation(Orientation::Vertical)
|
||||
.build();
|
||||
widget.append(&{
|
||||
let header = Box::builder()
|
||||
.halign(Align::Fill)
|
||||
.hexpand(true)
|
||||
.orientation(Orientation::Horizontal)
|
||||
.build();
|
||||
if let Some(ref alt) = v.alt {
|
||||
header.append(
|
||||
&Label::builder()
|
||||
.halign(Align::Start)
|
||||
.hexpand(true)
|
||||
.label(alt)
|
||||
.margin_bottom(MARGIN)
|
||||
.margin_end(MARGIN)
|
||||
.margin_start(MARGIN)
|
||||
.margin_top(MARGIN)
|
||||
.selectable(true)
|
||||
.build(),
|
||||
);
|
||||
}
|
||||
header.append(&{
|
||||
const TOGGLE_BUTTON_CLASS: &str = "dimmed";
|
||||
const TOGGLE_BUTTON_TOOLTIP: (&str, &str) = ("Copy", "Copied");
|
||||
let copy = Button::builder()
|
||||
.css_classes(["circular", "flat", TOGGLE_BUTTON_CLASS])
|
||||
.halign(Align::End)
|
||||
.icon_name("edit-copy-symbolic")
|
||||
.margin_bottom(MARGIN / 2)
|
||||
.margin_end(MARGIN / 2)
|
||||
.margin_start(MARGIN / 2)
|
||||
.margin_top(MARGIN / 2)
|
||||
.tooltip_text(TOGGLE_BUTTON_TOOLTIP.0)
|
||||
.valign(Align::Center)
|
||||
.build();
|
||||
copy.set_cursor_from_name(Some("pointer"));
|
||||
copy.connect_clicked({
|
||||
let source = v.data.clone();
|
||||
let copied = copied.clone();
|
||||
move |this| {
|
||||
if let Some(prev) = copied.replace(Some(this.clone())) {
|
||||
prev.set_tooltip_text(Some(TOGGLE_BUTTON_TOOLTIP.0));
|
||||
prev.add_css_class(TOGGLE_BUTTON_CLASS)
|
||||
}
|
||||
this.set_tooltip_text(Some(TOGGLE_BUTTON_TOOLTIP.1));
|
||||
this.remove_css_class(TOGGLE_BUTTON_CLASS);
|
||||
|
||||
Display::default().unwrap().clipboard().set_text(&source)
|
||||
}
|
||||
});
|
||||
copy
|
||||
});
|
||||
header
|
||||
});
|
||||
widget.append(
|
||||
&Separator::builder()
|
||||
.orientation(Orientation::Horizontal)
|
||||
.build(),
|
||||
);
|
||||
widget.append(&{
|
||||
ScrolledWindow::builder()
|
||||
.child(
|
||||
&TextView::builder()
|
||||
.buffer(&{
|
||||
let b = TextBuffer::new(Some(&TextTagTable::new()));
|
||||
let mut start = b.start_iter();
|
||||
match syntax.highlight(&v.data, v.alt.as_ref()) {
|
||||
Ok(highlight) => {
|
||||
for (syntax_tag, entity) in highlight {
|
||||
assert!(b.tag_table().add(&syntax_tag));
|
||||
b.insert_with_tags(
|
||||
&mut start,
|
||||
&entity,
|
||||
&[&syntax_tag],
|
||||
)
|
||||
}
|
||||
}
|
||||
Err(_) => {
|
||||
// Try ANSI/SGR format (terminal emulation) @TODO optional
|
||||
for (syntax_tag, entity) in
|
||||
ansi::format(&v.data)
|
||||
{
|
||||
assert!(b.tag_table().add(&syntax_tag));
|
||||
b.insert_with_tags(
|
||||
&mut start,
|
||||
&entity,
|
||||
&[&syntax_tag],
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
b
|
||||
})
|
||||
.css_classes(["code-block"])
|
||||
.cursor_visible(false)
|
||||
.editable(false)
|
||||
.wrap_mode(WrapMode::None)
|
||||
.build(),
|
||||
)
|
||||
.margin_bottom(MARGIN)
|
||||
.margin_end(MARGIN)
|
||||
.margin_start(MARGIN)
|
||||
.margin_top(MARGIN)
|
||||
.vscrollbar_policy(PolicyType::Never)
|
||||
.hscrollbar_policy(PolicyType::Automatic)
|
||||
.propagate_natural_height(true)
|
||||
.build()
|
||||
});
|
||||
idle_add_local({
|
||||
let widget = widget.clone();
|
||||
let text_view = text_view.clone();
|
||||
move || {
|
||||
widget.set_width_request(text_view.width() - 22);
|
||||
ControlFlow::Break
|
||||
}
|
||||
});
|
||||
widget
|
||||
},
|
||||
&super::super::super::common::Code::init(
|
||||
text_view,
|
||||
v.data.as_ref(),
|
||||
v.alt.as_ref(),
|
||||
)
|
||||
.widget,
|
||||
&buffer.create_child_anchor(&mut m_end),
|
||||
);
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,33 +0,0 @@
|
|||
mod rgba;
|
||||
mod tag;
|
||||
|
||||
use tag::Tag;
|
||||
|
||||
use ansi_parser::{AnsiParser, AnsiSequence, Output};
|
||||
use gtk::{TextTag, prelude::TextTagExt};
|
||||
|
||||
/// Apply ANSI/SGR format to new buffer
|
||||
pub fn format(source_code: &str) -> Vec<(TextTag, String)> {
|
||||
let mut buffer = Vec::new();
|
||||
let mut tag = Tag::new();
|
||||
|
||||
for ref entity in source_code.ansi_parse() {
|
||||
if let Output::Escape(AnsiSequence::SetGraphicsMode(color)) = entity
|
||||
&& color.len() > 1
|
||||
{
|
||||
if color[0] == 38 {
|
||||
tag.text_tag
|
||||
.set_foreground_rgba(rgba::default(*color.last().unwrap()).as_ref());
|
||||
} else {
|
||||
tag.text_tag
|
||||
.set_background_rgba(rgba::default(*color.last().unwrap()).as_ref());
|
||||
}
|
||||
}
|
||||
if let Output::TextBlock(text) = entity {
|
||||
buffer.push((tag.text_tag, text.to_string()));
|
||||
tag = Tag::new();
|
||||
}
|
||||
}
|
||||
|
||||
buffer
|
||||
}
|
||||
|
|
@ -1,256 +0,0 @@
|
|||
use gtk::gdk::RGBA;
|
||||
|
||||
/// Default RGBa palette for ANSI terminal emulation
|
||||
pub fn default(color: u8) -> Option<RGBA> {
|
||||
match color {
|
||||
7 => Some(RGBA::new(0.854, 0.854, 0.854, 1.0)),
|
||||
8 => Some(RGBA::new(0.424, 0.424, 0.424, 1.0)),
|
||||
10 => Some(RGBA::new(0.0, 1.0, 0.0, 1.0)),
|
||||
11 => Some(RGBA::new(1.0, 1.0, 0.0, 1.0)),
|
||||
12 => Some(RGBA::new(0.0, 0.0, 1.0, 1.0)),
|
||||
13 => Some(RGBA::new(1.0, 0.0, 1.0, 1.0)),
|
||||
14 => Some(RGBA::new(0.0, 1.0, 1.0, 1.0)),
|
||||
15 => Some(RGBA::new(1.0, 1.0, 1.0, 1.0)),
|
||||
16 => Some(RGBA::new(0.0, 0.0, 0.0, 1.0)),
|
||||
17 => Some(RGBA::new(0.0, 0.020, 0.373, 1.0)),
|
||||
18 => Some(RGBA::new(0.0, 0.031, 0.529, 1.0)),
|
||||
19 => Some(RGBA::new(0.0, 0.0, 0.686, 1.0)),
|
||||
20 => Some(RGBA::new(0.0, 0.0, 0.823, 1.0)),
|
||||
21 => Some(RGBA::new(0.0, 0.0, 1.0, 1.0)),
|
||||
22 => Some(RGBA::new(0.0, 0.373, 0.0, 1.0)),
|
||||
23 => Some(RGBA::new(0.0, 0.373, 0.373, 1.0)),
|
||||
24 => Some(RGBA::new(0.0, 0.373, 0.529, 1.0)),
|
||||
25 => Some(RGBA::new(0.0, 0.373, 0.686, 1.0)),
|
||||
26 => Some(RGBA::new(0.0, 0.373, 0.823, 1.0)),
|
||||
27 => Some(RGBA::new(0.0, 0.373, 1.0, 1.0)),
|
||||
28 => Some(RGBA::new(0.0, 0.533, 0.0, 1.0)),
|
||||
29 => Some(RGBA::new(0.0, 0.533, 0.373, 1.0)),
|
||||
30 => Some(RGBA::new(0.0, 0.533, 0.533, 1.0)),
|
||||
31 => Some(RGBA::new(0.0, 0.533, 0.686, 1.0)),
|
||||
32 => Some(RGBA::new(0.0, 0.533, 0.823, 1.0)),
|
||||
33 => Some(RGBA::new(0.0, 0.533, 1.0, 1.0)),
|
||||
34 => Some(RGBA::new(0.039, 0.686, 0.0, 1.0)),
|
||||
35 => Some(RGBA::new(0.039, 0.686, 0.373, 1.0)),
|
||||
36 => Some(RGBA::new(0.039, 0.686, 0.529, 1.0)),
|
||||
37 => Some(RGBA::new(0.039, 0.686, 0.686, 1.0)),
|
||||
38 => Some(RGBA::new(0.039, 0.686, 0.823, 1.0)),
|
||||
39 => Some(RGBA::new(0.039, 0.686, 1.0, 1.0)),
|
||||
40 => Some(RGBA::new(0.0, 0.843, 0.0, 1.0)),
|
||||
41 => Some(RGBA::new(0.0, 0.843, 0.373, 1.0)),
|
||||
42 => Some(RGBA::new(0.0, 0.843, 0.529, 1.0)),
|
||||
43 => Some(RGBA::new(0.0, 0.843, 0.686, 1.0)),
|
||||
44 => Some(RGBA::new(0.0, 0.843, 0.843, 1.0)),
|
||||
45 => Some(RGBA::new(0.0, 0.843, 1.0, 1.0)),
|
||||
46 => Some(RGBA::new(0.0, 1.0, 0.0, 1.0)),
|
||||
47 => Some(RGBA::new(0.0, 1.0, 0.373, 1.0)),
|
||||
48 => Some(RGBA::new(0.0, 1.0, 0.529, 1.0)),
|
||||
49 => Some(RGBA::new(0.0, 1.0, 0.686, 1.0)),
|
||||
50 => Some(RGBA::new(0.0, 1.0, 0.843, 1.0)),
|
||||
51 => Some(RGBA::new(0.0, 1.0, 1.0, 1.0)),
|
||||
52 => Some(RGBA::new(0.373, 0.0, 0.0, 1.0)),
|
||||
53 => Some(RGBA::new(0.373, 0.0, 0.373, 1.0)),
|
||||
54 => Some(RGBA::new(0.373, 0.0, 0.529, 1.0)),
|
||||
55 => Some(RGBA::new(0.373, 0.0, 0.686, 1.0)),
|
||||
56 => Some(RGBA::new(0.373, 0.0, 0.843, 1.0)),
|
||||
57 => Some(RGBA::new(0.373, 0.0, 1.0, 1.0)),
|
||||
58 => Some(RGBA::new(0.373, 0.373, 0.0, 1.0)),
|
||||
59 => Some(RGBA::new(0.373, 0.373, 0.373, 1.0)),
|
||||
60 => Some(RGBA::new(0.373, 0.373, 0.529, 1.0)),
|
||||
61 => Some(RGBA::new(0.373, 0.373, 0.686, 1.0)),
|
||||
62 => Some(RGBA::new(0.373, 0.373, 0.843, 1.0)),
|
||||
63 => Some(RGBA::new(0.373, 0.373, 1.0, 1.0)),
|
||||
64 => Some(RGBA::new(0.373, 0.529, 0.0, 1.0)),
|
||||
65 => Some(RGBA::new(0.373, 0.529, 0.373, 1.0)),
|
||||
66 => Some(RGBA::new(0.373, 0.529, 0.529, 1.0)),
|
||||
67 => Some(RGBA::new(0.373, 0.529, 0.686, 1.0)),
|
||||
68 => Some(RGBA::new(0.373, 0.529, 0.843, 1.0)),
|
||||
69 => Some(RGBA::new(0.373, 0.529, 1.0, 1.0)),
|
||||
70 => Some(RGBA::new(0.373, 0.686, 0.0, 1.0)),
|
||||
71 => Some(RGBA::new(0.373, 0.686, 0.373, 1.0)),
|
||||
72 => Some(RGBA::new(0.373, 0.686, 0.529, 1.0)),
|
||||
73 => Some(RGBA::new(0.373, 0.686, 0.686, 1.0)),
|
||||
74 => Some(RGBA::new(0.373, 0.686, 0.843, 1.0)),
|
||||
75 => Some(RGBA::new(0.373, 0.686, 1.0, 1.0)),
|
||||
76 => Some(RGBA::new(0.373, 0.843, 0.0, 1.0)),
|
||||
77 => Some(RGBA::new(0.373, 0.843, 0.373, 1.0)),
|
||||
78 => Some(RGBA::new(0.373, 0.843, 0.529, 1.0)),
|
||||
79 => Some(RGBA::new(0.373, 0.843, 0.686, 1.0)),
|
||||
80 => Some(RGBA::new(0.373, 0.843, 0.843, 1.0)),
|
||||
81 => Some(RGBA::new(0.373, 0.843, 1.0, 1.0)),
|
||||
82 => Some(RGBA::new(0.373, 1.0, 0.0, 1.0)),
|
||||
83 => Some(RGBA::new(0.373, 1.0, 0.373, 1.0)),
|
||||
84 => Some(RGBA::new(0.373, 1.0, 0.529, 1.0)),
|
||||
85 => Some(RGBA::new(0.373, 1.0, 0.686, 1.0)),
|
||||
86 => Some(RGBA::new(0.373, 1.0, 0.843, 1.0)),
|
||||
87 => Some(RGBA::new(0.373, 1.0, 1.0, 1.0)),
|
||||
88 => Some(RGBA::new(0.529, 0.0, 0.0, 1.0)),
|
||||
89 => Some(RGBA::new(0.529, 0.0, 0.373, 1.0)),
|
||||
90 => Some(RGBA::new(0.529, 0.0, 0.529, 1.0)),
|
||||
91 => Some(RGBA::new(0.529, 0.0, 0.686, 1.0)),
|
||||
92 => Some(RGBA::new(0.529, 0.0, 0.843, 1.0)),
|
||||
93 => Some(RGBA::new(0.529, 0.0, 1.0, 1.0)),
|
||||
94 => Some(RGBA::new(0.529, 0.373, 0.0, 1.0)),
|
||||
95 => Some(RGBA::new(0.529, 0.373, 0.373, 1.0)),
|
||||
96 => Some(RGBA::new(0.529, 0.373, 0.529, 1.0)),
|
||||
97 => Some(RGBA::new(0.529, 0.373, 0.686, 1.0)),
|
||||
98 => Some(RGBA::new(0.529, 0.373, 0.843, 1.0)),
|
||||
99 => Some(RGBA::new(0.529, 0.373, 1.0, 1.0)),
|
||||
100 => Some(RGBA::new(0.529, 0.529, 0.0, 1.0)),
|
||||
101 => Some(RGBA::new(0.529, 0.529, 0.373, 1.0)),
|
||||
102 => Some(RGBA::new(0.529, 0.529, 0.529, 1.0)),
|
||||
103 => Some(RGBA::new(0.529, 0.529, 0.686, 1.0)),
|
||||
104 => Some(RGBA::new(0.529, 0.529, 0.843, 1.0)),
|
||||
105 => Some(RGBA::new(0.529, 0.529, 1.0, 1.0)),
|
||||
106 => Some(RGBA::new(0.533, 0.686, 0.0, 1.0)),
|
||||
107 => Some(RGBA::new(0.533, 0.686, 0.373, 1.0)),
|
||||
108 => Some(RGBA::new(0.533, 0.686, 0.529, 1.0)),
|
||||
109 => Some(RGBA::new(0.533, 0.686, 0.686, 1.0)),
|
||||
110 => Some(RGBA::new(0.533, 0.686, 0.843, 1.0)),
|
||||
111 => Some(RGBA::new(0.533, 0.686, 1.0, 1.0)),
|
||||
112 => Some(RGBA::new(0.533, 0.843, 0.0, 1.0)),
|
||||
113 => Some(RGBA::new(0.533, 0.843, 0.373, 1.0)),
|
||||
114 => Some(RGBA::new(0.533, 0.843, 0.529, 1.0)),
|
||||
115 => Some(RGBA::new(0.533, 0.843, 0.686, 1.0)),
|
||||
116 => Some(RGBA::new(0.533, 0.843, 0.843, 1.0)),
|
||||
117 => Some(RGBA::new(0.533, 0.843, 1.0, 1.0)),
|
||||
118 => Some(RGBA::new(0.533, 1.0, 0.0, 1.0)),
|
||||
119 => Some(RGBA::new(0.533, 1.0, 0.373, 1.0)),
|
||||
120 => Some(RGBA::new(0.533, 1.0, 0.529, 1.0)),
|
||||
121 => Some(RGBA::new(0.533, 1.0, 0.686, 1.0)),
|
||||
122 => Some(RGBA::new(0.533, 1.0, 0.843, 1.0)),
|
||||
123 => Some(RGBA::new(0.533, 1.0, 1.0, 1.0)),
|
||||
124 => Some(RGBA::new(0.686, 0.0, 0.0, 1.0)),
|
||||
125 => Some(RGBA::new(0.686, 0.0, 0.373, 1.0)),
|
||||
126 => Some(RGBA::new(0.686, 0.0, 0.529, 1.0)),
|
||||
127 => Some(RGBA::new(0.686, 0.0, 0.686, 1.0)),
|
||||
128 => Some(RGBA::new(0.686, 0.0, 0.843, 1.0)),
|
||||
129 => Some(RGBA::new(0.686, 0.0, 1.0, 1.0)),
|
||||
130 => Some(RGBA::new(0.686, 0.373, 0.0, 1.0)),
|
||||
131 => Some(RGBA::new(0.686, 0.373, 0.373, 1.0)),
|
||||
132 => Some(RGBA::new(0.686, 0.373, 0.529, 1.0)),
|
||||
133 => Some(RGBA::new(0.686, 0.373, 0.686, 1.0)),
|
||||
134 => Some(RGBA::new(0.686, 0.373, 0.843, 1.0)),
|
||||
135 => Some(RGBA::new(0.686, 0.373, 1.0, 1.0)),
|
||||
136 => Some(RGBA::new(0.686, 0.529, 0.0, 1.0)),
|
||||
137 => Some(RGBA::new(0.686, 0.529, 0.373, 1.0)),
|
||||
138 => Some(RGBA::new(0.686, 0.529, 0.529, 1.0)),
|
||||
139 => Some(RGBA::new(0.686, 0.529, 0.686, 1.0)),
|
||||
140 => Some(RGBA::new(0.686, 0.529, 0.843, 1.0)),
|
||||
141 => Some(RGBA::new(0.686, 0.529, 1.0, 1.0)),
|
||||
142 => Some(RGBA::new(0.686, 0.686, 0.0, 1.0)),
|
||||
143 => Some(RGBA::new(0.686, 0.686, 0.373, 1.0)),
|
||||
144 => Some(RGBA::new(0.686, 0.686, 0.529, 1.0)),
|
||||
145 => Some(RGBA::new(0.686, 0.686, 0.686, 1.0)),
|
||||
146 => Some(RGBA::new(0.686, 0.686, 0.843, 1.0)),
|
||||
147 => Some(RGBA::new(0.686, 0.686, 1.0, 1.0)),
|
||||
148 => Some(RGBA::new(0.686, 0.843, 0.0, 1.0)),
|
||||
149 => Some(RGBA::new(0.686, 0.843, 0.373, 1.0)),
|
||||
150 => Some(RGBA::new(0.686, 0.843, 0.529, 1.0)),
|
||||
151 => Some(RGBA::new(0.686, 0.843, 0.686, 1.0)),
|
||||
152 => Some(RGBA::new(0.686, 0.843, 0.843, 1.0)),
|
||||
153 => Some(RGBA::new(0.686, 0.843, 1.0, 1.0)),
|
||||
154 => Some(RGBA::new(0.686, 1.0, 0.0, 1.0)),
|
||||
155 => Some(RGBA::new(0.686, 1.0, 0.373, 1.0)),
|
||||
156 => Some(RGBA::new(0.686, 1.0, 0.529, 1.0)),
|
||||
157 => Some(RGBA::new(0.686, 1.0, 0.686, 1.0)),
|
||||
158 => Some(RGBA::new(0.686, 1.0, 0.843, 1.0)),
|
||||
159 => Some(RGBA::new(0.686, 1.0, 1.0, 1.0)),
|
||||
160 => Some(RGBA::new(0.847, 0.0, 0.0, 1.0)),
|
||||
161 => Some(RGBA::new(0.847, 0.0, 0.373, 1.0)),
|
||||
162 => Some(RGBA::new(0.847, 0.0, 0.529, 1.0)),
|
||||
163 => Some(RGBA::new(0.847, 0.0, 0.686, 1.0)),
|
||||
164 => Some(RGBA::new(0.847, 0.0, 0.843, 1.0)),
|
||||
165 => Some(RGBA::new(0.847, 0.0, 1.0, 1.0)),
|
||||
166 => Some(RGBA::new(0.847, 0.373, 0.0, 1.0)),
|
||||
167 => Some(RGBA::new(0.847, 0.373, 0.373, 1.0)),
|
||||
168 => Some(RGBA::new(0.847, 0.373, 0.529, 1.0)),
|
||||
169 => Some(RGBA::new(0.847, 0.373, 0.686, 1.0)),
|
||||
170 => Some(RGBA::new(0.847, 0.373, 0.843, 1.0)),
|
||||
171 => Some(RGBA::new(0.847, 0.373, 1.0, 1.0)),
|
||||
172 => Some(RGBA::new(0.847, 0.529, 0.0, 1.0)),
|
||||
173 => Some(RGBA::new(0.847, 0.529, 0.373, 1.0)),
|
||||
174 => Some(RGBA::new(0.847, 0.529, 0.529, 1.0)),
|
||||
175 => Some(RGBA::new(0.847, 0.529, 0.686, 1.0)),
|
||||
176 => Some(RGBA::new(0.847, 0.529, 0.843, 1.0)),
|
||||
177 => Some(RGBA::new(0.847, 0.529, 1.0, 1.0)),
|
||||
178 => Some(RGBA::new(0.847, 0.686, 0.0, 1.0)),
|
||||
179 => Some(RGBA::new(0.847, 0.686, 0.373, 1.0)),
|
||||
180 => Some(RGBA::new(0.847, 0.686, 0.529, 1.0)),
|
||||
181 => Some(RGBA::new(0.847, 0.686, 0.686, 1.0)),
|
||||
182 => Some(RGBA::new(0.847, 0.686, 0.843, 1.0)),
|
||||
183 => Some(RGBA::new(0.847, 0.686, 1.0, 1.0)),
|
||||
184 => Some(RGBA::new(0.847, 0.843, 0.0, 1.0)),
|
||||
185 => Some(RGBA::new(0.847, 0.843, 0.373, 1.0)),
|
||||
186 => Some(RGBA::new(0.847, 0.843, 0.529, 1.0)),
|
||||
187 => Some(RGBA::new(0.847, 0.843, 0.686, 1.0)),
|
||||
188 => Some(RGBA::new(0.847, 0.843, 0.843, 1.0)),
|
||||
189 => Some(RGBA::new(0.847, 0.843, 1.0, 1.0)),
|
||||
190 => Some(RGBA::new(0.847, 1.0, 0.0, 1.0)),
|
||||
191 => Some(RGBA::new(0.847, 1.0, 0.373, 1.0)),
|
||||
192 => Some(RGBA::new(0.847, 1.0, 0.529, 1.0)),
|
||||
193 => Some(RGBA::new(0.847, 1.0, 0.686, 1.0)),
|
||||
194 => Some(RGBA::new(0.847, 1.0, 0.843, 1.0)),
|
||||
195 => Some(RGBA::new(0.847, 1.0, 1.0, 1.0)),
|
||||
196 => Some(RGBA::new(1.0, 0.0, 0.0, 1.0)),
|
||||
197 => Some(RGBA::new(1.0, 0.0, 0.373, 1.0)),
|
||||
198 => Some(RGBA::new(1.0, 0.0, 0.529, 1.0)),
|
||||
199 => Some(RGBA::new(1.0, 0.0, 0.686, 1.0)),
|
||||
200 => Some(RGBA::new(1.0, 0.0, 0.843, 1.0)),
|
||||
201 => Some(RGBA::new(1.0, 0.0, 1.0, 1.0)),
|
||||
202 => Some(RGBA::new(1.0, 0.373, 0.0, 1.0)),
|
||||
203 => Some(RGBA::new(1.0, 0.373, 0.373, 1.0)),
|
||||
204 => Some(RGBA::new(1.0, 0.373, 0.529, 1.0)),
|
||||
205 => Some(RGBA::new(1.0, 0.373, 0.686, 1.0)),
|
||||
206 => Some(RGBA::new(1.0, 0.373, 0.843, 1.0)),
|
||||
207 => Some(RGBA::new(1.0, 0.373, 1.0, 1.0)),
|
||||
208 => Some(RGBA::new(1.0, 0.529, 0.0, 1.0)),
|
||||
209 => Some(RGBA::new(1.0, 0.529, 0.373, 1.0)),
|
||||
210 => Some(RGBA::new(1.0, 0.529, 0.529, 1.0)),
|
||||
211 => Some(RGBA::new(1.0, 0.529, 0.686, 1.0)),
|
||||
212 => Some(RGBA::new(1.0, 0.529, 0.843, 1.0)),
|
||||
213 => Some(RGBA::new(1.0, 0.529, 1.0, 1.0)),
|
||||
214 => Some(RGBA::new(1.0, 0.686, 0.0, 1.0)),
|
||||
215 => Some(RGBA::new(1.0, 0.686, 0.373, 1.0)),
|
||||
216 => Some(RGBA::new(1.0, 0.686, 0.529, 1.0)),
|
||||
217 => Some(RGBA::new(1.0, 0.686, 0.686, 1.0)),
|
||||
218 => Some(RGBA::new(1.0, 0.686, 0.843, 1.0)),
|
||||
219 => Some(RGBA::new(1.0, 0.686, 1.0, 1.0)),
|
||||
220 => Some(RGBA::new(1.0, 0.843, 0.0, 1.0)),
|
||||
221 => Some(RGBA::new(1.0, 0.843, 0.373, 1.0)),
|
||||
222 => Some(RGBA::new(1.0, 0.843, 0.529, 1.0)),
|
||||
223 => Some(RGBA::new(1.0, 0.843, 0.686, 1.0)),
|
||||
224 => Some(RGBA::new(1.0, 0.843, 0.843, 1.0)),
|
||||
225 => Some(RGBA::new(1.0, 0.843, 1.0, 1.0)),
|
||||
226 => Some(RGBA::new(1.0, 1.0, 0.0, 1.0)),
|
||||
227 => Some(RGBA::new(1.0, 1.0, 0.373, 1.0)),
|
||||
228 => Some(RGBA::new(1.0, 1.0, 0.529, 1.0)),
|
||||
229 => Some(RGBA::new(1.0, 1.0, 0.686, 1.0)),
|
||||
230 => Some(RGBA::new(1.0, 1.0, 0.843, 1.0)),
|
||||
231 => Some(RGBA::new(1.0, 1.0, 1.0, 1.0)),
|
||||
232 => Some(RGBA::new(0.031, 0.031, 0.031, 1.0)),
|
||||
233 => Some(RGBA::new(0.071, 0.071, 0.071, 1.0)),
|
||||
234 => Some(RGBA::new(0.110, 0.110, 0.110, 1.0)),
|
||||
235 => Some(RGBA::new(0.149, 0.149, 0.149, 1.0)),
|
||||
236 => Some(RGBA::new(0.188, 0.188, 0.188, 1.0)),
|
||||
237 => Some(RGBA::new(0.227, 0.227, 0.227, 1.0)),
|
||||
238 => Some(RGBA::new(0.267, 0.267, 0.267, 1.0)),
|
||||
239 => Some(RGBA::new(0.306, 0.306, 0.306, 1.0)),
|
||||
240 => Some(RGBA::new(0.345, 0.345, 0.345, 1.0)),
|
||||
241 => Some(RGBA::new(0.384, 0.384, 0.384, 1.0)),
|
||||
242 => Some(RGBA::new(0.424, 0.424, 0.424, 1.0)),
|
||||
243 => Some(RGBA::new(0.462, 0.462, 0.462, 1.0)),
|
||||
244 => Some(RGBA::new(0.502, 0.502, 0.502, 1.0)),
|
||||
245 => Some(RGBA::new(0.541, 0.541, 0.541, 1.0)),
|
||||
246 => Some(RGBA::new(0.580, 0.580, 0.580, 1.0)),
|
||||
247 => Some(RGBA::new(0.620, 0.620, 0.620, 1.0)),
|
||||
248 => Some(RGBA::new(0.659, 0.659, 0.659, 1.0)),
|
||||
249 => Some(RGBA::new(0.694, 0.694, 0.694, 1.0)),
|
||||
250 => Some(RGBA::new(0.733, 0.733, 0.733, 1.0)),
|
||||
251 => Some(RGBA::new(0.777, 0.777, 0.777, 1.0)),
|
||||
252 => Some(RGBA::new(0.816, 0.816, 0.816, 1.0)),
|
||||
253 => Some(RGBA::new(0.855, 0.855, 0.855, 1.0)),
|
||||
254 => Some(RGBA::new(0.890, 0.890, 0.890, 1.0)),
|
||||
255 => Some(RGBA::new(0.933, 0.933, 0.933, 1.0)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
|
@ -1,152 +0,0 @@
|
|||
pub mod error;
|
||||
mod tag;
|
||||
|
||||
pub use error::Error;
|
||||
use tag::Tag;
|
||||
|
||||
use adw::StyleManager;
|
||||
use gtk::{
|
||||
TextTag,
|
||||
gdk::RGBA,
|
||||
pango::{Style, Underline},
|
||||
prelude::TextTagExt,
|
||||
};
|
||||
use syntect::{
|
||||
easy::HighlightLines,
|
||||
highlighting::{Color, FontStyle, ThemeSet},
|
||||
parsing::{SyntaxReference, SyntaxSet},
|
||||
};
|
||||
|
||||
/* Default theme
|
||||
@TODO make optional
|
||||
base16-ocean.dark
|
||||
base16-eighties.dark
|
||||
base16-mocha.dark
|
||||
base16-ocean.light
|
||||
InspiredGitHub
|
||||
Solarized (dark)
|
||||
Solarized (light)
|
||||
*/
|
||||
pub const DEFAULT_THEME_DARK: &str = "base16-eighties.dark";
|
||||
pub const DEFAULT_THEME_LIGHT: &str = "InspiredGitHub";
|
||||
|
||||
pub struct Syntax {
|
||||
syntax_set: SyntaxSet,
|
||||
theme_set: ThemeSet,
|
||||
}
|
||||
|
||||
impl Default for Syntax {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl Syntax {
|
||||
// Constructors
|
||||
|
||||
/// Create new `Self`
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
syntax_set: SyntaxSet::load_defaults_newlines(),
|
||||
theme_set: ThemeSet::load_defaults(),
|
||||
}
|
||||
}
|
||||
|
||||
// Actions
|
||||
|
||||
/// Apply `Syntect` highlight to new buffer returned,
|
||||
/// according to given `alt` and `source_code` content
|
||||
pub fn highlight(
|
||||
&self,
|
||||
source_code: &str,
|
||||
alt: Option<&String>,
|
||||
) -> Result<Vec<(TextTag, String)>, Error> {
|
||||
if let Some(value) = alt {
|
||||
if let Some(reference) = self.syntax_set.find_syntax_by_name(value) {
|
||||
return self.buffer(source_code, reference);
|
||||
}
|
||||
|
||||
if let Some(reference) = self.syntax_set.find_syntax_by_token(value) {
|
||||
return self.buffer(source_code, reference);
|
||||
}
|
||||
|
||||
if let Some(reference) = self.syntax_set.find_syntax_by_path(value) {
|
||||
return self.buffer(source_code, reference);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(reference) = self.syntax_set.find_syntax_by_first_line(source_code) {
|
||||
return self.buffer(source_code, reference);
|
||||
}
|
||||
|
||||
Err(Error::Parse)
|
||||
}
|
||||
|
||||
fn buffer(
|
||||
&self,
|
||||
source: &str,
|
||||
syntax_reference: &SyntaxReference,
|
||||
) -> Result<Vec<(TextTag, String)>, Error> {
|
||||
// Init new line buffer
|
||||
let mut buffer = Vec::new();
|
||||
|
||||
// Apply syntect decorator
|
||||
let mut ranges = HighlightLines::new(
|
||||
syntax_reference,
|
||||
&self.theme_set.themes[if StyleManager::default().is_dark() {
|
||||
DEFAULT_THEME_DARK
|
||||
} else {
|
||||
DEFAULT_THEME_LIGHT
|
||||
}], // @TODO apply on env change
|
||||
);
|
||||
|
||||
match ranges.highlight_line(source, &self.syntax_set) {
|
||||
Ok(result) => {
|
||||
// Build tags
|
||||
for (style, entity) in result {
|
||||
// Create new tag from default preset
|
||||
let tag = Tag::new();
|
||||
|
||||
// Tuneup using syntect conversion
|
||||
// tag.set_background_rgba(Some(&color_to_rgba(style.background)));
|
||||
tag.text_tag
|
||||
.set_foreground_rgba(Some(&color_to_rgba(style.foreground)));
|
||||
tag.text_tag
|
||||
.set_style(font_style_to_style(style.font_style));
|
||||
tag.text_tag
|
||||
.set_underline(font_style_to_underline(style.font_style));
|
||||
|
||||
// Append
|
||||
buffer.push((tag.text_tag, entity.to_string()));
|
||||
}
|
||||
Ok(buffer)
|
||||
}
|
||||
Err(e) => Err(Error::Syntect(e)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Tools
|
||||
|
||||
fn color_to_rgba(color: Color) -> RGBA {
|
||||
RGBA::new(
|
||||
color.r as f32 / 255.0,
|
||||
color.g as f32 / 255.0,
|
||||
color.b as f32 / 255.0,
|
||||
color.a as f32 / 255.0,
|
||||
)
|
||||
}
|
||||
|
||||
fn font_style_to_style(font_style: FontStyle) -> Style {
|
||||
match font_style {
|
||||
FontStyle::ITALIC => Style::Italic,
|
||||
_ => Style::Normal,
|
||||
}
|
||||
}
|
||||
|
||||
fn font_style_to_underline(font_style: FontStyle) -> Underline {
|
||||
match font_style {
|
||||
FontStyle::UNDERLINE => Underline::Single,
|
||||
_ => Underline::None,
|
||||
}
|
||||
}
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
use std::fmt::{Display, Formatter, Result};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
Parse,
|
||||
Syntect(syntect::Error),
|
||||
}
|
||||
|
||||
impl Display for Error {
|
||||
fn fmt(&self, f: &mut Formatter) -> Result {
|
||||
match self {
|
||||
Self::Parse => write!(f, "Parse error"),
|
||||
Self::Syntect(e) => {
|
||||
write!(f, "Syntect error: {e}")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue