pub macro status($($parts:tt)*) {
...
}Expand description
The macro that creates a StatusLine
This macro works like the txt! macro, in that Forms
are pushed with [{FormName}]. However, txt! is
evaluated immediately, while status! is evaluated when
updates occur.
The macro will mostly read from the File widget and its
related structs. In order to do that, it will accept functions
as arguments. These functions take the following parameters:
- The
&Filewidget; - A specific
&impl Widget, which is glued to theFile;
Both of these can also have a second argument of type
&Area. This will include the Widget’s Area when
creating the status part. Additionally, you may include a
first argument of type &Pass (e.g. fn(&Pass, &File),
`fn(&Pass, &Widget, &Area), etc.), giving you non mutating
access to global state.
Here’s some examples:
setup_duat!(setup);
use duat::prelude::*;
fn name_but_funky(file: &File) -> String {
file.name()
.chars()
.enumerate()
.map(|(i, char)| {
if i % 2 == 1 {
char.to_uppercase().to_string()
} else {
char.to_lowercase().to_string()
}
})
.collect()
}
fn powerline_main_txt(file: &File, area: &Area) -> Text {
let selections = file.selections();
let cfg = file.print_cfg();
let v_caret = selections
.get_main()
.unwrap()
.v_caret(file.text(), area, cfg);
txt!(
"[separator][coord]{}[separator][coord]{}[separator][coord]{}",
v_caret.visual_col(),
v_caret.line(),
file.len_lines()
)
.build()
}
fn setup() {
hook::add::<WindowCreated>(|_, builder| {
builder.push(status!("[file]{name_but_funky}[] {powerline_main_txt}"));
});
}Now, there are other types of arguments that you can also
pass. They update differently from the previous ones. The
previous arguments update when the File updates. The
following types of arguments update independently or not
at all:
- A
Textargument, which can be formatted in a similar way throught thetxt!macro; - Any
impl Display, such as numbers, strings, chars, etc.impl Debugtypes also work, when including the usual":?"and derived suffixes; RwDataorDataMaps of the previous two types. These will update whenever the data inside is changed;- An
(Fn(&Pass) -> Text/Display/Debug, Fn(&Pass) -> bool)tuple. The first function returns what will be shown, while the second function checks for updates, which will call the first function again;
Here’s an examples:
setup_duat!(setup);
use std::sync::atomic::{AtomicUsize, Ordering};
use duat::prelude::*;
fn setup() {
let changing_str = RwData::new("Initial text".to_string());
fn counter(update: bool) -> usize {
static COUNT: AtomicUsize = AtomicUsize::new(0);
if update {
COUNT.fetch_add(1, Ordering::Relaxed) + 1
} else {
COUNT.load(Ordering::Relaxed)
}
}
hook::add::<WindowCreated>({
let changing_str = changing_str.clone();
move |_, builder| {
let changing_str = changing_str.clone();
let checker = changing_str.checker();
let text = txt!("Static text").build();
let counter = move |_: &File| counter(checker());
builder.push(status!("{changing_str} [counter]{counter}[] {text}",));
}
});
cmd::add!("set-text", |pa, new: &str| {
*changing_str.write(pa) = new.to_string();
Ok(None)
})
}In the above example, I added some dynamic Text, through
the usage of an RwData<Text>, I added some static
Text, some Forms ("counter" and "default") and
even a counter,.