diff options
Diffstat (limited to 'crates/typst-ide/src/complete.rs')
| -rw-r--r-- | crates/typst-ide/src/complete.rs | 50 |
1 files changed, 44 insertions, 6 deletions
diff --git a/crates/typst-ide/src/complete.rs b/crates/typst-ide/src/complete.rs index b58a9bcc..94679552 100644 --- a/crates/typst-ide/src/complete.rs +++ b/crates/typst-ide/src/complete.rs @@ -6,7 +6,7 @@ use if_chain::if_chain; use serde::{Deserialize, Serialize}; use typst::foundations::{ fields_on, format_str, mutable_methods_on, repr, AutoValue, CastInfo, Func, Label, - NoneValue, Repr, Scope, Type, Value, + NoneValue, Repr, Scope, StyleChain, Styles, Type, Value, }; use typst::model::Document; use typst::syntax::{ @@ -135,6 +135,17 @@ fn complete_markup(ctx: &mut CompletionContext) -> bool { } } + // Behind a half-completed context block: "#context |". + if_chain! { + if let Some(prev) = ctx.leaf.prev_leaf(); + if prev.kind() == SyntaxKind::Context; + then { + ctx.from = ctx.cursor; + code_completions(ctx, false); + return true; + } + } + // Directly after a raw block. let mut s = Scanner::new(ctx.text); s.jump(ctx.leaf.offset()); @@ -333,10 +344,10 @@ fn complete_field_accesses(ctx: &mut CompletionContext) -> bool { if prev.is::<ast::Expr>(); if prev.parent_kind() != Some(SyntaxKind::Markup) || prev.prev_sibling_kind() == Some(SyntaxKind::Hash); - if let Some(value) = analyze_expr(ctx.world, &prev).into_iter().next(); + if let Some((value, styles)) = analyze_expr(ctx.world, &prev).into_iter().next(); then { ctx.from = ctx.cursor; - field_access_completions(ctx, &value); + field_access_completions(ctx, &value, &styles); return true; } } @@ -348,10 +359,10 @@ fn complete_field_accesses(ctx: &mut CompletionContext) -> bool { if prev.kind() == SyntaxKind::Dot; if let Some(prev_prev) = prev.prev_sibling(); if prev_prev.is::<ast::Expr>(); - if let Some(value) = analyze_expr(ctx.world, &prev_prev).into_iter().next(); + if let Some((value, styles)) = analyze_expr(ctx.world, &prev_prev).into_iter().next(); then { ctx.from = ctx.leaf.offset(); - field_access_completions(ctx, &value); + field_access_completions(ctx, &value, &styles); return true; } } @@ -360,7 +371,11 @@ fn complete_field_accesses(ctx: &mut CompletionContext) -> bool { } /// Add completions for all fields on a value. -fn field_access_completions(ctx: &mut CompletionContext, value: &Value) { +fn field_access_completions( + ctx: &mut CompletionContext, + value: &Value, + styles: &Option<Styles>, +) { for (name, value) in value.ty().scope().iter() { ctx.value_completion(Some(name.clone()), value, true, None); } @@ -421,6 +436,23 @@ fn field_access_completions(ctx: &mut CompletionContext, value: &Value) { ctx.value_completion(Some(name.clone().into()), value, false, None); } } + Value::Func(func) => { + // Autocomplete get rules. + if let Some((elem, styles)) = func.element().zip(styles.as_ref()) { + for param in elem.params().iter().filter(|param| !param.required) { + if let Some(value) = elem.field_id(param.name).and_then(|id| { + elem.field_from_styles(id, StyleChain::new(styles)) + }) { + ctx.value_completion( + Some(param.name.into()), + &value, + false, + None, + ); + } + } + } + } Value::Plugin(plugin) => { for name in plugin.iter() { ctx.completions.push(Completion { @@ -863,6 +895,12 @@ fn code_completions(ctx: &mut CompletionContext, hash: bool) { ); ctx.snippet_completion( + "context expression", + "context ${}", + "Provides contextual data.", + ); + + ctx.snippet_completion( "let binding", "let ${name} = ${value}", "Saves a value in a variable.", |
