mirror of
https://github.com/Zedfrigg/ironbar.git
synced 2025-07-01 18:51:04 +02:00
Merge pull request #421 from JakeStanger/fix/dynamic-string
Dynamic String Fixes
This commit is contained in:
commit
8aef093ac9
2 changed files with 32 additions and 18 deletions
|
@ -1,7 +1,7 @@
|
||||||
Ironvars are runtime variables that can be referenced in several places in your config,
|
Ironvars are runtime variables that can be referenced in several places in your config,
|
||||||
then set using the IPC server (such as via the CLI) using the `set` command.
|
then set using the IPC server (such as via the CLI) using the `set` command.
|
||||||
|
|
||||||
Any UTF-8 string *without whitespace* is a valid key.
|
Keys can consist of alphanumeric characters, `-` and `_` only.
|
||||||
Any UTF-8 string is a valid value.
|
Any UTF-8 string is a valid value.
|
||||||
|
|
||||||
Reference values using `#my_variable`. These update as soon as the value changes.
|
Reference values using `#my_variable`. These update as soon as the value changes.
|
||||||
|
|
|
@ -29,7 +29,7 @@ pub fn dynamic_string<F>(input: &str, mut f: F)
|
||||||
where
|
where
|
||||||
F: FnMut(String) + 'static,
|
F: FnMut(String) + 'static,
|
||||||
{
|
{
|
||||||
let tokens = parse_input(input);
|
let (tokens, is_static) = parse_input(input);
|
||||||
|
|
||||||
let label_parts = arc_mut!(vec![]);
|
let label_parts = arc_mut!(vec![]);
|
||||||
let (tx, rx) = mpsc::channel(32);
|
let (tx, rx) = mpsc::channel(32);
|
||||||
|
@ -91,17 +91,17 @@ where
|
||||||
glib_recv_mpsc!(rx , val => f(val));
|
glib_recv_mpsc!(rx , val => f(val));
|
||||||
|
|
||||||
// initialize
|
// initialize
|
||||||
{
|
if is_static {
|
||||||
let label_parts = lock!(label_parts).join("");
|
let label_parts = lock!(label_parts).join("");
|
||||||
try_send!(tx, label_parts);
|
try_send!(tx, label_parts);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses the input string into static and dynamic segments
|
/// Parses the input string into static and dynamic segments
|
||||||
fn parse_input(input: &str) -> Vec<DynamicStringSegment> {
|
fn parse_input(input: &str) -> (Vec<DynamicStringSegment>, bool) {
|
||||||
// short-circuit parser if it's all static
|
// short-circuit parser if it's all static
|
||||||
if !input.contains("{{") && !input.contains('#') {
|
if !input.contains("{{") && !input.contains('#') {
|
||||||
return vec![DynamicStringSegment::Static(input.to_string())];
|
return (vec![DynamicStringSegment::Static(input.to_string())], true);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut tokens = vec![];
|
let mut tokens = vec![];
|
||||||
|
@ -129,7 +129,7 @@ fn parse_input(input: &str) -> Vec<DynamicStringSegment> {
|
||||||
chars.drain(..skip);
|
chars.drain(..skip);
|
||||||
}
|
}
|
||||||
|
|
||||||
tokens
|
(tokens, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_script(chars: &[char]) -> (DynamicStringSegment, usize) {
|
fn parse_script(chars: &[char]) -> (DynamicStringSegment, usize) {
|
||||||
|
@ -155,7 +155,7 @@ fn parse_variable(chars: &[char]) -> (DynamicStringSegment, usize) {
|
||||||
let str = chars
|
let str = chars
|
||||||
.iter()
|
.iter()
|
||||||
.skip(1)
|
.skip(1)
|
||||||
.take_while(|&c| !c.is_whitespace())
|
.take_while(|&c| c.is_ascii_alphanumeric() || c == &'_' || c == &'-')
|
||||||
.collect::<String>();
|
.collect::<String>();
|
||||||
|
|
||||||
let len = str.chars().count() + SKIP_HASH;
|
let len = str.chars().count() + SKIP_HASH;
|
||||||
|
@ -190,7 +190,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_static() {
|
fn test_static() {
|
||||||
const INPUT: &str = "hello world";
|
const INPUT: &str = "hello world";
|
||||||
let tokens = parse_input(INPUT);
|
let (tokens, _) = parse_input(INPUT);
|
||||||
|
|
||||||
assert_eq!(tokens.len(), 1);
|
assert_eq!(tokens.len(), 1);
|
||||||
assert!(matches!(&tokens[0], DynamicStringSegment::Static(value) if value == INPUT))
|
assert!(matches!(&tokens[0], DynamicStringSegment::Static(value) if value == INPUT))
|
||||||
|
@ -199,7 +199,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_static_odd_char_count() {
|
fn test_static_odd_char_count() {
|
||||||
const INPUT: &str = "hello";
|
const INPUT: &str = "hello";
|
||||||
let tokens = parse_input(INPUT);
|
let (tokens, _) = parse_input(INPUT);
|
||||||
|
|
||||||
assert_eq!(tokens.len(), 1);
|
assert_eq!(tokens.len(), 1);
|
||||||
assert!(matches!(&tokens[0], DynamicStringSegment::Static(value) if value == INPUT))
|
assert!(matches!(&tokens[0], DynamicStringSegment::Static(value) if value == INPUT))
|
||||||
|
@ -208,7 +208,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_script() {
|
fn test_script() {
|
||||||
const INPUT: &str = "{{echo hello}}";
|
const INPUT: &str = "{{echo hello}}";
|
||||||
let tokens = parse_input(INPUT);
|
let (tokens, _) = parse_input(INPUT);
|
||||||
|
|
||||||
assert_eq!(tokens.len(), 1);
|
assert_eq!(tokens.len(), 1);
|
||||||
assert!(
|
assert!(
|
||||||
|
@ -219,7 +219,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_variable() {
|
fn test_variable() {
|
||||||
const INPUT: &str = "#variable";
|
const INPUT: &str = "#variable";
|
||||||
let tokens = parse_input(INPUT);
|
let (tokens, _) = parse_input(INPUT);
|
||||||
|
|
||||||
assert_eq!(tokens.len(), 1);
|
assert_eq!(tokens.len(), 1);
|
||||||
assert!(
|
assert!(
|
||||||
|
@ -230,7 +230,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_static_script() {
|
fn test_static_script() {
|
||||||
const INPUT: &str = "hello {{echo world}}";
|
const INPUT: &str = "hello {{echo world}}";
|
||||||
let tokens = parse_input(INPUT);
|
let (tokens, _) = parse_input(INPUT);
|
||||||
|
|
||||||
assert_eq!(tokens.len(), 2);
|
assert_eq!(tokens.len(), 2);
|
||||||
assert!(matches!(&tokens[0], DynamicStringSegment::Static(str) if str == "hello "));
|
assert!(matches!(&tokens[0], DynamicStringSegment::Static(str) if str == "hello "));
|
||||||
|
@ -242,7 +242,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_static_variable() {
|
fn test_static_variable() {
|
||||||
const INPUT: &str = "hello #subject";
|
const INPUT: &str = "hello #subject";
|
||||||
let tokens = parse_input(INPUT);
|
let (tokens, _) = parse_input(INPUT);
|
||||||
|
|
||||||
assert_eq!(tokens.len(), 2);
|
assert_eq!(tokens.len(), 2);
|
||||||
assert!(matches!(&tokens[0], DynamicStringSegment::Static(str) if str == "hello "));
|
assert!(matches!(&tokens[0], DynamicStringSegment::Static(str) if str == "hello "));
|
||||||
|
@ -254,7 +254,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_static_script_static() {
|
fn test_static_script_static() {
|
||||||
const INPUT: &str = "hello {{echo world}} foo";
|
const INPUT: &str = "hello {{echo world}} foo";
|
||||||
let tokens = parse_input(INPUT);
|
let (tokens, _) = parse_input(INPUT);
|
||||||
|
|
||||||
assert_eq!(tokens.len(), 3);
|
assert_eq!(tokens.len(), 3);
|
||||||
assert!(matches!(&tokens[0], DynamicStringSegment::Static(str) if str == "hello "));
|
assert!(matches!(&tokens[0], DynamicStringSegment::Static(str) if str == "hello "));
|
||||||
|
@ -267,7 +267,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_static_variable_static() {
|
fn test_static_variable_static() {
|
||||||
const INPUT: &str = "hello #subject foo";
|
const INPUT: &str = "hello #subject foo";
|
||||||
let tokens = parse_input(INPUT);
|
let (tokens, _) = parse_input(INPUT);
|
||||||
|
|
||||||
assert_eq!(tokens.len(), 3);
|
assert_eq!(tokens.len(), 3);
|
||||||
assert!(matches!(&tokens[0], DynamicStringSegment::Static(str) if str == "hello "));
|
assert!(matches!(&tokens[0], DynamicStringSegment::Static(str) if str == "hello "));
|
||||||
|
@ -280,7 +280,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_static_script_variable() {
|
fn test_static_script_variable() {
|
||||||
const INPUT: &str = "hello {{echo world}} #foo";
|
const INPUT: &str = "hello {{echo world}} #foo";
|
||||||
let tokens = parse_input(INPUT);
|
let (tokens, _) = parse_input(INPUT);
|
||||||
|
|
||||||
assert_eq!(tokens.len(), 4);
|
assert_eq!(tokens.len(), 4);
|
||||||
assert!(matches!(&tokens[0], DynamicStringSegment::Static(str) if str == "hello "));
|
assert!(matches!(&tokens[0], DynamicStringSegment::Static(str) if str == "hello "));
|
||||||
|
@ -296,7 +296,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_escape_hash() {
|
fn test_escape_hash() {
|
||||||
const INPUT: &str = "number ###num";
|
const INPUT: &str = "number ###num";
|
||||||
let tokens = parse_input(INPUT);
|
let (tokens, _) = parse_input(INPUT);
|
||||||
|
|
||||||
assert_eq!(tokens.len(), 3);
|
assert_eq!(tokens.len(), 3);
|
||||||
assert!(matches!(&tokens[0], DynamicStringSegment::Static(str) if str == "number "));
|
assert!(matches!(&tokens[0], DynamicStringSegment::Static(str) if str == "number "));
|
||||||
|
@ -309,11 +309,25 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_script_with_hash() {
|
fn test_script_with_hash() {
|
||||||
const INPUT: &str = "{{echo #hello}}";
|
const INPUT: &str = "{{echo #hello}}";
|
||||||
let tokens = parse_input(INPUT);
|
let (tokens, _) = parse_input(INPUT);
|
||||||
|
|
||||||
assert_eq!(tokens.len(), 1);
|
assert_eq!(tokens.len(), 1);
|
||||||
assert!(
|
assert!(
|
||||||
matches!(&tokens[0], DynamicStringSegment::Script(script) if script.cmd == "echo #hello")
|
matches!(&tokens[0], DynamicStringSegment::Script(script) if script.cmd == "echo #hello")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_pango_attribute() {
|
||||||
|
const INPUT: &str = "<span color='#color'>hello</span>";
|
||||||
|
let (tokens, _) = parse_input(INPUT);
|
||||||
|
|
||||||
|
assert_eq!(tokens.len(), 3);
|
||||||
|
|
||||||
|
assert!(matches!(&tokens[0], DynamicStringSegment::Static(str) if str == "<span color='"));
|
||||||
|
assert!(
|
||||||
|
matches!(&tokens[1], DynamicStringSegment::Variable(var) if var.to_string() == "color")
|
||||||
|
);
|
||||||
|
assert!(matches!(&tokens[2], DynamicStringSegment::Static(str) if str == "'>hello</span>"))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue