Bugfixes
This commit is contained in:
parent
fd3d3b10ce
commit
94b90761eb
@ -23,6 +23,12 @@ use crate::prelude::*;
|
||||
/// - path: EcoString (positional, required)
|
||||
/// Path to an image file.
|
||||
///
|
||||
/// - width: Rel<Length> (named)
|
||||
/// The width of the image.
|
||||
///
|
||||
/// - height: Rel<Length> (named)
|
||||
/// The height of the image.
|
||||
///
|
||||
/// ## Category
|
||||
/// visualize
|
||||
#[func]
|
||||
|
@ -2,7 +2,7 @@ use std::collections::HashSet;
|
||||
|
||||
use if_chain::if_chain;
|
||||
|
||||
use super::summarize_font_family;
|
||||
use super::{plain_docs_sentence, summarize_font_family};
|
||||
use crate::model::{CastInfo, Scope, Value};
|
||||
use crate::syntax::ast::AstNode;
|
||||
use crate::syntax::{ast, LinkedNode, Source, SyntaxKind};
|
||||
@ -453,7 +453,7 @@ impl<'a> CompletionContext<'a> {
|
||||
kind: CompletionKind::Param,
|
||||
label: param.name.into(),
|
||||
apply: Some(format_eco!("{}: ${{}}", param.name)),
|
||||
detail: Some(plain_docs_sentence(param.docs)),
|
||||
detail: Some(plain_docs_sentence(param.docs).into()),
|
||||
});
|
||||
}
|
||||
|
||||
@ -504,8 +504,8 @@ impl<'a> CompletionContext<'a> {
|
||||
self.snippet_completion("auto", "auto", "A smart default.");
|
||||
}
|
||||
CastInfo::Type("boolean") => {
|
||||
self.snippet_completion("false", "false", "Yes / Enabled.");
|
||||
self.snippet_completion("true", "true", "No / Disabled.");
|
||||
self.snippet_completion("false", "false", "No / Disabled.");
|
||||
self.snippet_completion("true", "true", "Yes / Enabled.");
|
||||
}
|
||||
CastInfo::Type("color") => {
|
||||
self.snippet_completion(
|
||||
@ -566,7 +566,9 @@ impl<'a> CompletionContext<'a> {
|
||||
}
|
||||
|
||||
let detail = docs.map(Into::into).or_else(|| match value {
|
||||
Value::Func(func) => func.info().map(|info| plain_docs_sentence(info.docs)),
|
||||
Value::Func(func) => {
|
||||
func.info().map(|info| plain_docs_sentence(info.docs).into())
|
||||
}
|
||||
Value::Color(color) => Some(format_eco!("The color {color:?}.")),
|
||||
Value::Auto => Some("A smart default.".into()),
|
||||
_ => None,
|
||||
@ -986,48 +988,3 @@ impl<'a> CompletionContext<'a> {
|
||||
self.scope_completions(|value| matches!(value, Value::Func(_)));
|
||||
}
|
||||
}
|
||||
|
||||
/// Extract the first sentence of plain text of a piece of documentation.
|
||||
///
|
||||
/// Removes Markdown formatting.
|
||||
fn plain_docs_sentence(docs: &str) -> EcoString {
|
||||
let mut s = unscanny::Scanner::new(docs);
|
||||
let mut output = String::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.into()
|
||||
}
|
||||
|
@ -7,3 +7,84 @@ mod tooltip;
|
||||
pub use complete::*;
|
||||
pub use highlight::*;
|
||||
pub use tooltip::*;
|
||||
|
||||
use std::fmt::Write;
|
||||
|
||||
use crate::font::{FontInfo, FontStyle};
|
||||
|
||||
/// Extract the first sentence of plain text of a piece of documentation.
|
||||
///
|
||||
/// Removes Markdown formatting.
|
||||
fn plain_docs_sentence(docs: &str) -> String {
|
||||
let mut s = unscanny::Scanner::new(docs);
|
||||
let mut output = String::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
|
||||
}
|
||||
|
||||
/// Create a short description of a font family.
|
||||
pub fn summarize_font_family<'a>(variants: impl Iterator<Item = &'a FontInfo>) -> String {
|
||||
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 s = if count == 1 { "" } else { "s" };
|
||||
let mut detail = format!("{count} variant{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
|
||||
}
|
||||
|
@ -1,8 +1,6 @@
|
||||
use std::fmt::Write;
|
||||
|
||||
use if_chain::if_chain;
|
||||
|
||||
use crate::font::{FontInfo, FontStyle};
|
||||
use super::{plain_docs_sentence, summarize_font_family};
|
||||
use crate::model::{CastInfo, Value};
|
||||
use crate::syntax::ast::{self, AstNode};
|
||||
use crate::syntax::{LinkedNode, Source, SyntaxKind};
|
||||
@ -28,7 +26,7 @@ fn function_tooltip(world: &dyn World, leaf: &LinkedNode) -> Option<String> {
|
||||
if let Some(Value::Func(func)) = world.library().scope.get(ident);
|
||||
if let Some(info) = func.info();
|
||||
then {
|
||||
return Some(info.docs.into());
|
||||
return Some(plain_docs_sentence(&info.docs));
|
||||
}
|
||||
}
|
||||
|
||||
@ -65,7 +63,7 @@ fn named_param_tooltip(world: &dyn World, leaf: &LinkedNode) -> Option<String> {
|
||||
if let SyntaxKind::Ident(ident) = leaf.kind();
|
||||
if let Some(param) = info.param(ident);
|
||||
then {
|
||||
return Some(param.docs.into());
|
||||
return Some(plain_docs_sentence(param.docs));
|
||||
}
|
||||
}
|
||||
|
||||
@ -126,37 +124,3 @@ fn font_family_tooltip(world: &dyn World, leaf: &LinkedNode) -> Option<String> {
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
/// Create a short description of a font family.
|
||||
pub(super) fn summarize_font_family<'a>(
|
||||
variants: impl Iterator<Item = &'a FontInfo>,
|
||||
) -> String {
|
||||
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 s = if count == 1 { "" } else { "s" };
|
||||
let mut detail = format!("{count} variant{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
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user