Skip to content

Commit

Permalink
Add cursup parser
Browse files Browse the repository at this point in the history
  • Loading branch information
gyscos committed Jun 17, 2024
1 parent 778bec7 commit 042a2f8
Show file tree
Hide file tree
Showing 5 changed files with 124 additions and 0 deletions.
5 changes: 5 additions & 0 deletions cursive-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@ version = "0.8"
default-features = false
version = "0.4"

[dependencies.regex]
optional = true
version = "1"

[dependencies.pulldown-cmark]
default-features = false
optional = true
Expand All @@ -69,6 +73,7 @@ version = "0.11"
default = []
doc-cfg = []
builder = ["inventory", "cursive-macros/builder"]
cursup = ["regex"]
markdown = ["pulldown-cmark"]
ansi = ["ansi-parser"]
unstable_scroll = [] # Deprecated feature, remove in next version
Expand Down
17 changes: 17 additions & 0 deletions cursive-core/src/theme/style.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use std::iter::FromIterator;
use std::str::FromStr;

use super::{
Color, ColorPair, ColorStyle, ColorType, ConcreteEffects, Effect, Effects, Palette,
Expand Down Expand Up @@ -164,6 +165,22 @@ impl Style {
}
}

impl FromStr for Style {
type Err = super::NoSuchColor;

fn from_str(s: &str) -> Result<Self, Self::Err> {
if let Ok(front) = s.parse::<ColorType>() {
return Ok(front.into());
}

if let Ok(effect) = s.parse::<Effect>() {
return Ok(effect.into());
}

Err(super::NoSuchColor)
}
}

impl From<Effect> for Style {
fn from(effect: Effect) -> Self {
Style {
Expand Down
96 changes: 96 additions & 0 deletions cursive-core/src/utils/markup/cursup.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
//! A simple markup format.
//!
//! # Examples
//!
//! ```
//! /red{This} /green{text} /blue{is} /bold{very} /underline{styled}!
//! /red+bold{This too!}
//! ```
#![cfg(feature = "cursup")]
#![cfg_attr(feature = "doc-cfg", doc(cfg(feature = "cursup")))]
use crate::theme::Style;
use crate::utils::markup::{StyledIndexedSpan, StyledString};
use crate::utils::span::IndexedCow;

use unicode_width::UnicodeWidthStr;

/// Parse spans for the given text.
pub fn parse_spans(input: &str) -> Vec<StyledIndexedSpan> {
let mut result = Vec::new();

let re = regex::Regex::new(r"\/(?:(\w+)(?:\+(\w+))*)\{(.+)\}").unwrap();

let mut offset = 0;
let mut content = input;
while let Some(c) = re.captures(content) {
let m = c.get(0).unwrap();
let start = m.start();
let end = m.end();

// First, append the entire content up to here.
if start != 0 {
result.push(StyledIndexedSpan {
content: IndexedCow::Borrowed {
start: offset,
end: offset + start,
},
attr: Style::default(),
width: content[..start].width(),
});
}

let len = c.len();
assert!(
len > 2,
"The regex should always yield at least 2 groups (+ the entire match)."
);
let body = c.get(len - 1).unwrap();

let mut style = Style::default();

for i in 1..len - 1 {
let Some(action) = c.get(i) else {
continue;
};

style = style.combine(action.as_str().parse::<Style>().unwrap());
}

result.push(StyledIndexedSpan {
content: IndexedCow::Borrowed {
start: offset + body.start(),
end: offset + body.end(),
},
attr: style,
width: body.as_str().width(),
});

content = &content[end..];
offset += end;
}

if !content.is_empty() {
result.push(StyledIndexedSpan {
content: IndexedCow::Borrowed {
start: offset,
end: offset + content.len(),
},
attr: Style::default(),
width: content.width(),
});
}

result
}

/// Parse the given text into a styled string.
pub fn parse<S>(input: S) -> crate::utils::markup::StyledString
where
S: Into<String>,
{
let input = input.into();

let spans = parse_spans(&input);

StyledString::with_spans(input, spans)
}
1 change: 1 addition & 0 deletions cursive-core/src/utils/markup/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
//! Each module is optional and relies on a feature.
pub mod ansi;
pub mod cursup;
pub mod markdown;

use crate::theme::Style;
Expand Down
5 changes: 5 additions & 0 deletions cursive/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ version = "0.27"
doc-cfg = ["cursive_core/doc-cfg"] # Enable doc_cfg, a nightly-only doc feature.
builder = ["cursive_core/builder"]
blt-backend = ["bear-lib-terminal"]
cursup = ["cursive_core/cursup"]
default = ["ncurses-backend"]
ncurses-backend = ["ncurses", "maplit"]
pancurses-backend = ["pancurses", "maplit"]
Expand Down Expand Up @@ -80,6 +81,10 @@ required-features = ["ansi"]
name = "builder"
required-features = ["builder"]

[[example]]
name = "mockup"
required-features = ["cursup"]

[dev-dependencies]
rand = "0.8"
atty = "0.2"
Expand Down

0 comments on commit 042a2f8

Please sign in to comment.