summaryrefslogtreecommitdiff
path: root/src/ide/tooltip.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/ide/tooltip.rs')
-rw-r--r--src/ide/tooltip.rs74
1 files changed, 54 insertions, 20 deletions
diff --git a/src/ide/tooltip.rs b/src/ide/tooltip.rs
index 076e2b45..202efd8e 100644
--- a/src/ide/tooltip.rs
+++ b/src/ide/tooltip.rs
@@ -1,40 +1,71 @@
use if_chain::if_chain;
+use unicode_segmentation::UnicodeSegmentation;
-use super::{plain_docs_sentence, summarize_font_family};
-use crate::model::{CastInfo, Value};
+use super::{analyze, plain_docs_sentence, summarize_font_family};
+use crate::model::{CastInfo, Tracer, Value};
use crate::syntax::ast;
use crate::syntax::{LinkedNode, Source, SyntaxKind};
use crate::World;
/// Describe the item under the cursor.
-pub fn tooltip(world: &dyn World, source: &Source, cursor: usize) -> Option<String> {
+pub fn tooltip(
+ world: &(dyn World + 'static),
+ source: &Source,
+ cursor: usize,
+) -> Option<String> {
let leaf = LinkedNode::new(source.root()).leaf_at(cursor)?;
- function_tooltip(world, &leaf)
- .or_else(|| named_param_tooltip(world, &leaf))
+ named_param_tooltip(world, &leaf)
.or_else(|| font_family_tooltip(world, &leaf))
+ .or_else(|| expr_tooltip(world, &leaf))
}
-/// Tooltip for a function or set rule name.
-fn function_tooltip(world: &dyn World, leaf: &LinkedNode) -> Option<String> {
- if_chain! {
- if let Some(ident) = leaf.cast::<ast::Ident>();
- if matches!(
- leaf.parent_kind(),
- Some(SyntaxKind::FuncCall | SyntaxKind::SetRule),
- );
- if let Some(Value::Func(func)) = world.library().global.scope().get(&ident);
- if let Some(info) = func.info();
- then {
- return Some(plain_docs_sentence(info.docs));
+/// Tooltip for a hovered expression.
+fn expr_tooltip(world: &(dyn World + 'static), leaf: &LinkedNode) -> Option<String> {
+ if !leaf.is::<ast::Expr>() {
+ return None;
+ }
+
+ let values = analyze(world, leaf);
+ if let [value] = values.as_slice() {
+ if let Some(docs) = value.docs() {
+ return Some(plain_docs_sentence(docs));
}
}
- None
+ let mut tooltip = String::new();
+ let mut iter = values.into_iter().enumerate();
+ for (i, value) in (&mut iter).take(Tracer::MAX - 1) {
+ if i > 0 && !tooltip.is_empty() {
+ tooltip.push_str(", ");
+ }
+ let repr = value.repr();
+ let repr = repr.as_str();
+ let len = repr.len();
+ if len <= 40 {
+ tooltip.push_str(repr);
+ } else {
+ let mut graphemes = repr.graphemes(true);
+ let r = graphemes.next_back().map_or(0, str::len);
+ let l = graphemes.take(40).map(str::len).sum();
+ tooltip.push_str(&repr[..l]);
+ tooltip.push_str("...");
+ tooltip.push_str(&repr[len - r..]);
+ }
+ }
+
+ if iter.next().is_some() {
+ tooltip.push_str(", ...");
+ }
+
+ (!tooltip.is_empty()).then(|| tooltip)
}
/// Tooltips for components of a named parameter.
-fn named_param_tooltip(world: &dyn World, leaf: &LinkedNode) -> Option<String> {
+fn named_param_tooltip(
+ world: &(dyn World + 'static),
+ leaf: &LinkedNode,
+) -> Option<String> {
let (info, named) = if_chain! {
// Ensure that we are in a named pair in the arguments to a function
// call or set rule.
@@ -92,7 +123,10 @@ fn find_string_doc(info: &CastInfo, string: &str) -> Option<&'static str> {
}
/// Tooltip for font family.
-fn font_family_tooltip(world: &dyn World, leaf: &LinkedNode) -> Option<String> {
+fn font_family_tooltip(
+ world: &(dyn World + 'static),
+ leaf: &LinkedNode,
+) -> Option<String> {
if_chain! {
// Ensure that we are on top of a string.
if let Some(string) = leaf.cast::<ast::Str>();