mirror of
https://github.com/YGGverse/Yoda.git
synced 2026-03-31 16:45:27 +00:00
add underline tag support
This commit is contained in:
parent
ea2f4656a0
commit
5b8a469b5b
2 changed files with 93 additions and 0 deletions
|
|
@ -4,6 +4,7 @@ mod list;
|
|||
mod quote;
|
||||
mod reference;
|
||||
mod title;
|
||||
mod underline;
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
|
|
@ -18,6 +19,7 @@ use header::Header;
|
|||
use list::List;
|
||||
use quote::Quote;
|
||||
use title::Title;
|
||||
use underline::Underline;
|
||||
|
||||
pub struct Tags {
|
||||
pub text_tag_table: TextTagTable,
|
||||
|
|
@ -27,6 +29,7 @@ pub struct Tags {
|
|||
pub list: TextTag,
|
||||
pub quote: Quote,
|
||||
pub title: TextTag,
|
||||
pub underline: Underline,
|
||||
}
|
||||
|
||||
impl Default for Tags {
|
||||
|
|
@ -55,6 +58,7 @@ impl Tags {
|
|||
list,
|
||||
quote: Quote::new(),
|
||||
title,
|
||||
underline: Underline::new(),
|
||||
}
|
||||
}
|
||||
pub fn render(
|
||||
|
|
@ -70,6 +74,7 @@ impl Tags {
|
|||
self.quote.render(buffer);
|
||||
|
||||
self.bold.render(buffer);
|
||||
self.underline.render(buffer);
|
||||
|
||||
reference::render_images_links(&buffer, base, &link_color, links);
|
||||
reference::render_images(&buffer, base, &link_color, links);
|
||||
|
|
@ -78,6 +83,7 @@ impl Tags {
|
|||
title.map(|mut s| {
|
||||
s = reference::strip_tags(&s);
|
||||
s = bold::strip_tags(&s);
|
||||
s = underline::strip_tags(&s);
|
||||
s // @TODO other tags
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,87 @@
|
|||
use gtk::{
|
||||
TextBuffer, TextTag,
|
||||
WrapMode::Word,
|
||||
pango::Underline::Single,
|
||||
prelude::{TextBufferExt, TextBufferExtManual},
|
||||
};
|
||||
use regex::Regex;
|
||||
|
||||
const REGEX_UNDERLINE: &str = r"\b_(?P<text>[^_]+)_\b";
|
||||
|
||||
pub struct Underline(TextTag);
|
||||
|
||||
impl Underline {
|
||||
pub fn new() -> Self {
|
||||
Self(TextTag::builder().underline(Single).wrap_mode(Word).build())
|
||||
}
|
||||
|
||||
/// Apply _underline_ `Tag` to given `TextBuffer`
|
||||
pub fn render(&self, buffer: &TextBuffer) {
|
||||
assert!(buffer.tag_table().add(&self.0));
|
||||
|
||||
let (start, end) = buffer.bounds();
|
||||
let full_content = buffer.text(&start, &end, true).to_string();
|
||||
|
||||
let matches: Vec<_> = Regex::new(REGEX_UNDERLINE)
|
||||
.unwrap()
|
||||
.captures_iter(&full_content)
|
||||
.collect();
|
||||
|
||||
for cap in matches.into_iter().rev() {
|
||||
let full_match = cap.get(0).unwrap();
|
||||
|
||||
let start_char_offset = full_content[..full_match.start()].chars().count() as i32;
|
||||
let end_char_offset = full_content[..full_match.end()].chars().count() as i32;
|
||||
|
||||
let mut start_iter = buffer.iter_at_offset(start_char_offset);
|
||||
let mut end_iter = buffer.iter_at_offset(end_char_offset);
|
||||
|
||||
buffer.delete(&mut start_iter, &mut end_iter);
|
||||
buffer.insert_with_tags(&mut start_iter, &cap["text"], &[&self.0])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn strip_tags(value: &str) -> String {
|
||||
let mut result = String::from(value);
|
||||
for cap in Regex::new(REGEX_UNDERLINE)
|
||||
.unwrap()
|
||||
.captures_iter(&value)
|
||||
.into_iter()
|
||||
{
|
||||
if let Some(m) = cap.get(0) {
|
||||
result = result.replace(m.as_str(), &cap["text"]);
|
||||
}
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_strip_tags() {
|
||||
const VALUE: &str = r"Some _underline 1_ and _underline 2_ with ";
|
||||
let mut result = String::from(VALUE);
|
||||
for cap in Regex::new(REGEX_UNDERLINE)
|
||||
.unwrap()
|
||||
.captures_iter(VALUE)
|
||||
.into_iter()
|
||||
{
|
||||
if let Some(m) = cap.get(0) {
|
||||
result = result.replace(m.as_str(), &cap["text"]);
|
||||
}
|
||||
}
|
||||
assert_eq!(
|
||||
result,
|
||||
"Some underline 1 and underline 2 with "
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_regex() {
|
||||
let cap: Vec<_> = Regex::new(REGEX_UNDERLINE)
|
||||
.unwrap()
|
||||
.captures_iter(r"Some _underline 1_ and _underline 2_ with ")
|
||||
.collect();
|
||||
|
||||
assert_eq!(&cap.get(0).unwrap()["text"], "underline 1");
|
||||
assert_eq!(&cap.get(1).unwrap()["text"], "underline 2");
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue