mod analyze;
mod complete;
mod jump;
mod tooltip;
pub use self::analyze::analyze_labels;
pub use self::complete::{autocomplete, Completion, CompletionKind};
pub use self::jump::{jump_from_click, jump_from_cursor, Jump};
pub use self::tooltip::{tooltip, Tooltip};
use std::fmt::Write;
use ecow::{eco_format, EcoString};
use typst::text::{FontInfo, FontStyle};
fn plain_docs_sentence(docs: &str) -> EcoString {
let mut s = unscanny::Scanner::new(docs);
let mut output = EcoString::new();
let mut link = false;
while let Some(c) = s.eat() {
match c {
'`' => {
let mut raw = s.eat_until('`');
if (raw.starts_with('{') && raw.ends_with('}'))
|| (raw.starts_with('[') && raw.ends_with(']'))
{
raw = &raw[1..raw.len() - 1];
}
s.eat();
output.push('`');
output.push_str(raw);
output.push('`');
}
'[' => link = true,
']' if link => {
if s.eat_if('(') {
s.eat_until(')');
s.eat();
} else if s.eat_if('[') {
s.eat_until(']');
s.eat();
}
link = false
}
'*' | '_' => {}
'.' => {
output.push('.');
break;
}
_ => output.push(c),
}
}
output
}
fn summarize_font_family<'a>(variants: impl Iterator<Item = &'a FontInfo>) -> EcoString {
let mut infos: Vec<_> = variants.collect();
infos.sort_by_key(|info| info.variant);
let mut has_italic = false;
let mut min_weight = u16::MAX;
let mut max_weight = 0;
for info in &infos {
let weight = info.variant.weight.to_number();
has_italic |= info.variant.style == FontStyle::Italic;
min_weight = min_weight.min(weight);
max_weight = min_weight.max(weight);
}
let count = infos.len();
let mut detail = eco_format!("{count} variant{}.", if count == 1 { "" } else { "s" });
if min_weight == max_weight {
write!(detail, " Weight {min_weight}.").unwrap();
} else {
write!(detail, " Weights {min_weight}–{max_weight}.").unwrap();
}
if has_italic {
detail.push_str(" Has italics.");
}
detail
}