mirror of
https://github.com/Zedfrigg/ironbar.git
synced 2025-07-01 18:51:04 +02:00
fix(dynamic string): parser issue related to incorrectly matching braces
This commit is contained in:
parent
dfe1964abf
commit
910945306c
1 changed files with 60 additions and 41 deletions
|
@ -4,6 +4,9 @@ use gtk::prelude::*;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
use tokio::spawn;
|
use tokio::spawn;
|
||||||
|
|
||||||
|
/// A segment of a dynamic string,
|
||||||
|
/// containing either a static string
|
||||||
|
/// or a script.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
enum DynamicStringSegment {
|
enum DynamicStringSegment {
|
||||||
Static(String),
|
Static(String),
|
||||||
|
@ -20,47 +23,7 @@ impl DynamicString {
|
||||||
where
|
where
|
||||||
F: FnMut(String) -> Continue + 'static,
|
F: FnMut(String) -> Continue + 'static,
|
||||||
{
|
{
|
||||||
let mut segments = vec![];
|
let segments = Self::parse_input(input);
|
||||||
|
|
||||||
let mut chars = input.chars().collect::<Vec<_>>();
|
|
||||||
while !chars.is_empty() {
|
|
||||||
let char = &chars[..=1];
|
|
||||||
|
|
||||||
let (token, skip) = if let ['{', '{'] = char {
|
|
||||||
const SKIP_BRACKETS: usize = 4;
|
|
||||||
|
|
||||||
let str = chars
|
|
||||||
.iter()
|
|
||||||
.skip(2)
|
|
||||||
.enumerate()
|
|
||||||
.take_while(|(i, &c)| c != '}' && chars[i + 1] != '}')
|
|
||||||
.map(|(_, c)| c)
|
|
||||||
.collect::<String>();
|
|
||||||
|
|
||||||
let len = str.len();
|
|
||||||
|
|
||||||
(
|
|
||||||
DynamicStringSegment::Dynamic(Script::from(str.as_str())),
|
|
||||||
len + SKIP_BRACKETS,
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
let str = chars
|
|
||||||
.iter()
|
|
||||||
.enumerate()
|
|
||||||
.take_while(|(i, &c)| !(c == '{' && chars[i + 1] == '{'))
|
|
||||||
.map(|(_, c)| c)
|
|
||||||
.collect::<String>();
|
|
||||||
|
|
||||||
let len = str.len();
|
|
||||||
|
|
||||||
(DynamicStringSegment::Static(str), len)
|
|
||||||
};
|
|
||||||
|
|
||||||
assert_ne!(skip, 0);
|
|
||||||
|
|
||||||
segments.push(token);
|
|
||||||
chars.drain(..skip);
|
|
||||||
}
|
|
||||||
|
|
||||||
let label_parts = Arc::new(Mutex::new(Vec::new()));
|
let label_parts = Arc::new(Mutex::new(Vec::new()));
|
||||||
let (tx, rx) = glib::MainContext::channel(glib::PRIORITY_DEFAULT);
|
let (tx, rx) = glib::MainContext::channel(glib::PRIORITY_DEFAULT);
|
||||||
|
@ -105,6 +68,62 @@ impl DynamicString {
|
||||||
|
|
||||||
Self
|
Self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Parses the input string into static and dynamic segments
|
||||||
|
fn parse_input(input: &str) -> Vec<DynamicStringSegment> {
|
||||||
|
if !input.contains("{{") {
|
||||||
|
return vec![DynamicStringSegment::Static(input.to_string())];
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut segments = vec![];
|
||||||
|
|
||||||
|
let mut chars = input.chars().collect::<Vec<_>>();
|
||||||
|
while !chars.is_empty() {
|
||||||
|
let char_pair = &chars[..=1];
|
||||||
|
|
||||||
|
let (token, skip) = if let ['{', '{'] = char_pair {
|
||||||
|
const SKIP_BRACKETS: usize = 4; // two braces either side
|
||||||
|
|
||||||
|
let str = chars
|
||||||
|
.windows(2)
|
||||||
|
.skip(2)
|
||||||
|
.take_while(|win| win != &['}', '}'])
|
||||||
|
.map(|w| w[0])
|
||||||
|
.collect::<String>();
|
||||||
|
|
||||||
|
let len = str.len();
|
||||||
|
|
||||||
|
(
|
||||||
|
DynamicStringSegment::Dynamic(Script::from(str.as_str())),
|
||||||
|
len + SKIP_BRACKETS,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
let mut str = chars
|
||||||
|
.windows(2)
|
||||||
|
.take_while(|win| win != &['{', '{'])
|
||||||
|
.map(|w| w[0])
|
||||||
|
.collect::<String>();
|
||||||
|
|
||||||
|
// if segment is at end of string, last char gets missed above due to uneven window.
|
||||||
|
if chars.len() == str.len() + 1 {
|
||||||
|
let remaining_char = *chars.get(str.len()).expect("Failed to find last char");
|
||||||
|
str.push(remaining_char);
|
||||||
|
}
|
||||||
|
|
||||||
|
let len = str.len();
|
||||||
|
|
||||||
|
(DynamicStringSegment::Static(str), len)
|
||||||
|
};
|
||||||
|
|
||||||
|
// quick runtime check to make sure the parser is working as expected
|
||||||
|
assert_ne!(skip, 0);
|
||||||
|
|
||||||
|
segments.push(token);
|
||||||
|
chars.drain(..skip);
|
||||||
|
}
|
||||||
|
|
||||||
|
segments
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue