use super::*;
impl App {
pub fn md_toggle_focused_task(&mut self) {
if self.is_raw_source() {
return; }
let Some(f) = self.focused_item else { return };
let Some(MdItem {
kind: MdItemKind::Task { state },
..
}) = self.md_items.get(f)
else {
return;
};
let expected = *state;
let ordinal = self.md_items[..=f]
.iter()
.filter(|it| matches!(it.kind, MdItemKind::Task { .. }))
.count()
.saturating_sub(1);
let total = self
.md_items
.iter()
.filter(|it| matches!(it.kind, MdItemKind::Task { .. }))
.count();
let Some(path) = self.preview_path.clone() else {
return;
};
let states = self.cfg.ui.md_task_state_chars();
let src = match std::fs::read_to_string(&path) {
Ok(s) => s,
Err(e) => {
self.flash = Some(format!(
"{}{e}",
crate::i18n::tr(self.lang, crate::i18n::Msg::OperationFailed)
));
return;
}
};
let locs = crate::preview::markdown::task_source_locs(&src, &states);
let ok = locs.len() == total
&& locs
.get(ordinal)
.is_some_and(|l| norm_state(l.state) == norm_state(expected));
if !ok {
self.flash = Some(crate::i18n::tr(self.lang, crate::i18n::Msg::TaskFileChanged).into());
self.reload_preview();
return;
}
let loc = &locs[ordinal];
let cur = loc.state;
let next = match states
.iter()
.position(|s| norm_state(*s) == norm_state(cur))
{
Some(i) => states[(i + 1) % states.len()],
None => states[0], };
let mut lines: Vec<String> = src.split('\n').map(str::to_string).collect();
let Some(line) = lines.get_mut(loc.line) else {
return; };
line.replace_range(
loc.state_off..loc.state_off + cur.len_utf8(),
&next.to_string(),
);
let new_src = lines.join("\n");
if let Err(e) = std::fs::write(&path, new_src) {
self.flash = Some(format!(
"{}{e}",
crate::i18n::tr(self.lang, crate::i18n::Msg::OperationFailed)
));
return;
}
self.reload_preview();
}
}
fn norm_state(c: char) -> char {
if c == 'X' {
'x'
} else {
c
}
}