mirror of
https://github.com/Myriad-Dreamin/tinymist.git
synced 2025-08-03 17:58:17 +00:00
feat: replace rule completion with scoped type completion (#861)
* feat: replace rule completion with scoped type completion * test: update snapshot
This commit is contained in:
parent
e2c8418c35
commit
d8ee287b77
19 changed files with 205 additions and 243 deletions
|
@ -77,7 +77,7 @@ input_file: crates/tinymist-query/src/fixtures/completion/func_args.typ
|
|||
"labelDetails": {
|
||||
"description": "type"
|
||||
},
|
||||
"sortText": "052",
|
||||
"sortText": "031",
|
||||
"textEdit": {
|
||||
"newText": "content",
|
||||
"range": {
|
||||
|
|
|
@ -35,7 +35,7 @@ input_file: crates/tinymist-query/src/fixtures/completion/func_builtin_args.typ
|
|||
"labelDetails": {
|
||||
"description": "(int, content, gutter: relative) => columns"
|
||||
},
|
||||
"sortText": "056",
|
||||
"sortText": "037",
|
||||
"textEdit": {
|
||||
"newText": "columns(${1:})",
|
||||
"range": {
|
||||
|
|
|
@ -77,7 +77,7 @@ input_file: crates/tinymist-query/src/fixtures/completion/func_with_args.typ
|
|||
"labelDetails": {
|
||||
"description": "type"
|
||||
},
|
||||
"sortText": "052",
|
||||
"sortText": "031",
|
||||
"textEdit": {
|
||||
"newText": "content",
|
||||
"range": {
|
||||
|
|
|
@ -14,6 +14,7 @@ input_file: crates/tinymist-query/src/fixtures/completion/set.typ
|
|||
"labelDetails": {
|
||||
"description": "(str, align: alignment, block: bool, lang: none | str, syntaxes: [syntax], tab-size: int, theme: [theme]) => raw"
|
||||
},
|
||||
"sortText": "052",
|
||||
"textEdit": {
|
||||
"newText": "raw(${1:})",
|
||||
"range": {
|
||||
|
|
|
@ -14,6 +14,7 @@ input_file: crates/tinymist-query/src/fixtures/completion/set2.typ
|
|||
"labelDetails": {
|
||||
"description": "(str, align: alignment, block: bool, lang: none | str, syntaxes: [syntax], tab-size: int, theme: [theme]) => raw"
|
||||
},
|
||||
"sortText": "052",
|
||||
"textEdit": {
|
||||
"newText": "raw(${1:})",
|
||||
"range": {
|
||||
|
|
|
@ -14,6 +14,7 @@ input_file: crates/tinymist-query/src/fixtures/completion/set_in_show.typ
|
|||
"labelDetails": {
|
||||
"description": "(str, align: alignment, block: bool, lang: none | str, syntaxes: [syntax], tab-size: int, theme: [theme]) => raw"
|
||||
},
|
||||
"sortText": "052",
|
||||
"textEdit": {
|
||||
"newText": "raw(${1:})",
|
||||
"range": {
|
||||
|
|
|
@ -8,12 +8,31 @@ input_file: crates/tinymist-query/src/fixtures/completion/show.typ
|
|||
{
|
||||
"isIncomplete": false,
|
||||
"items": [
|
||||
{
|
||||
"kind": 15,
|
||||
"label": "regex selector",
|
||||
"sortText": "000",
|
||||
"textEdit": {
|
||||
"newText": "regex(\"${1:regex}\"): ${2:}",
|
||||
"range": {
|
||||
"end": {
|
||||
"character": 7,
|
||||
"line": 1
|
||||
},
|
||||
"start": {
|
||||
"character": 6,
|
||||
"line": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"kind": 3,
|
||||
"label": "raw",
|
||||
"labelDetails": {
|
||||
"description": "(str, align: alignment, block: bool, lang: none | str, syntaxes: [syntax], tab-size: int, theme: [theme]) => raw"
|
||||
},
|
||||
"sortText": "096",
|
||||
"textEdit": {
|
||||
"newText": "raw: ${1:}",
|
||||
"range": {
|
||||
|
@ -34,6 +53,7 @@ input_file: crates/tinymist-query/src/fixtures/completion/show.typ
|
|||
"labelDetails": {
|
||||
"description": "(str, align: alignment, block: bool, lang: none | str, syntaxes: [syntax], tab-size: int, theme: [theme]) => raw"
|
||||
},
|
||||
"sortText": "097",
|
||||
"textEdit": {
|
||||
"newText": "raw.where(${1:}): ${2:}",
|
||||
"range": {
|
||||
|
@ -47,23 +67,6 @@ input_file: crates/tinymist-query/src/fixtures/completion/show.typ
|
|||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"kind": 15,
|
||||
"label": "regex selector",
|
||||
"textEdit": {
|
||||
"newText": "regex(\"${1:regex}\"): ${2:}",
|
||||
"range": {
|
||||
"end": {
|
||||
"character": 7,
|
||||
"line": 1
|
||||
},
|
||||
"start": {
|
||||
"character": 6,
|
||||
"line": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -8,12 +8,31 @@ input_file: crates/tinymist-query/src/fixtures/completion/show2.typ
|
|||
{
|
||||
"isIncomplete": false,
|
||||
"items": [
|
||||
{
|
||||
"kind": 15,
|
||||
"label": "regex selector",
|
||||
"sortText": "000",
|
||||
"textEdit": {
|
||||
"newText": "regex(\"${1:regex}\"): ${2:}",
|
||||
"range": {
|
||||
"end": {
|
||||
"character": 6,
|
||||
"line": 1
|
||||
},
|
||||
"start": {
|
||||
"character": 6,
|
||||
"line": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"kind": 3,
|
||||
"label": "raw",
|
||||
"labelDetails": {
|
||||
"description": "(str, align: alignment, block: bool, lang: none | str, syntaxes: [syntax], tab-size: int, theme: [theme]) => raw"
|
||||
},
|
||||
"sortText": "096",
|
||||
"textEdit": {
|
||||
"newText": "raw: ${1:}",
|
||||
"range": {
|
||||
|
@ -34,6 +53,7 @@ input_file: crates/tinymist-query/src/fixtures/completion/show2.typ
|
|||
"labelDetails": {
|
||||
"description": "(str, align: alignment, block: bool, lang: none | str, syntaxes: [syntax], tab-size: int, theme: [theme]) => raw"
|
||||
},
|
||||
"sortText": "097",
|
||||
"textEdit": {
|
||||
"newText": "raw.where(${1:}): ${2:}",
|
||||
"range": {
|
||||
|
@ -47,23 +67,6 @@ input_file: crates/tinymist-query/src/fixtures/completion/show2.typ
|
|||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"kind": 15,
|
||||
"label": "regex selector",
|
||||
"textEdit": {
|
||||
"newText": "regex(\"${1:regex}\"): ${2:}",
|
||||
"range": {
|
||||
"end": {
|
||||
"character": 6,
|
||||
"line": 1
|
||||
},
|
||||
"start": {
|
||||
"character": 6,
|
||||
"line": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -8,12 +8,31 @@ input_file: crates/tinymist-query/src/fixtures/completion/show3.typ
|
|||
{
|
||||
"isIncomplete": false,
|
||||
"items": [
|
||||
{
|
||||
"kind": 15,
|
||||
"label": "regex selector",
|
||||
"sortText": "000",
|
||||
"textEdit": {
|
||||
"newText": "regex(\"${1:regex}\"): ${2:}",
|
||||
"range": {
|
||||
"end": {
|
||||
"character": 6,
|
||||
"line": 1
|
||||
},
|
||||
"start": {
|
||||
"character": 6,
|
||||
"line": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"kind": 3,
|
||||
"label": "raw",
|
||||
"labelDetails": {
|
||||
"description": "(str, align: alignment, block: bool, lang: none | str, syntaxes: [syntax], tab-size: int, theme: [theme]) => raw"
|
||||
},
|
||||
"sortText": "096",
|
||||
"textEdit": {
|
||||
"newText": "raw: ${1:}",
|
||||
"range": {
|
||||
|
@ -34,6 +53,7 @@ input_file: crates/tinymist-query/src/fixtures/completion/show3.typ
|
|||
"labelDetails": {
|
||||
"description": "(str, align: alignment, block: bool, lang: none | str, syntaxes: [syntax], tab-size: int, theme: [theme]) => raw"
|
||||
},
|
||||
"sortText": "097",
|
||||
"textEdit": {
|
||||
"newText": "raw.where(${1:}): ${2:}",
|
||||
"range": {
|
||||
|
@ -47,23 +67,6 @@ input_file: crates/tinymist-query/src/fixtures/completion/show3.typ
|
|||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"kind": 15,
|
||||
"label": "regex selector",
|
||||
"textEdit": {
|
||||
"newText": "regex(\"${1:regex}\"): ${2:}",
|
||||
"range": {
|
||||
"end": {
|
||||
"character": 6,
|
||||
"line": 1
|
||||
},
|
||||
"start": {
|
||||
"character": 6,
|
||||
"line": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -9,13 +9,11 @@ input_file: crates/tinymist-query/src/fixtures/completion/show_transform.typ
|
|||
"isIncomplete": false,
|
||||
"items": [
|
||||
{
|
||||
"kind": 3,
|
||||
"label": "raw",
|
||||
"labelDetails": {
|
||||
"description": "(str, align: alignment, block: bool, lang: none | str, syntaxes: [syntax], tab-size: int, theme: [theme]) => raw"
|
||||
},
|
||||
"kind": 15,
|
||||
"label": "replacement",
|
||||
"sortText": "000",
|
||||
"textEdit": {
|
||||
"newText": "raw",
|
||||
"newText": "[${1:content}]",
|
||||
"range": {
|
||||
"end": {
|
||||
"character": 12,
|
||||
|
@ -30,12 +28,13 @@ input_file: crates/tinymist-query/src/fixtures/completion/show_transform.typ
|
|||
},
|
||||
{
|
||||
"kind": 3,
|
||||
"label": "raw.where",
|
||||
"label": "raw",
|
||||
"labelDetails": {
|
||||
"description": "(str, align: alignment, block: bool, lang: none | str, syntaxes: [syntax], tab-size: int, theme: [theme]) => raw"
|
||||
},
|
||||
"sortText": "157",
|
||||
"textEdit": {
|
||||
"newText": "raw.where(${1:})",
|
||||
"newText": "raw(${1:})",
|
||||
"range": {
|
||||
"end": {
|
||||
"character": 12,
|
||||
|
@ -54,6 +53,7 @@ input_file: crates/tinymist-query/src/fixtures/completion/show_transform.typ
|
|||
"labelDetails": {
|
||||
"description": "(str, align: alignment, block: bool, lang: none | str, syntaxes: [syntax], tab-size: int, theme: [theme]) => raw"
|
||||
},
|
||||
"sortText": "158",
|
||||
"textEdit": {
|
||||
"newText": "raw.with(${1:})",
|
||||
"range": {
|
||||
|
@ -74,8 +74,9 @@ input_file: crates/tinymist-query/src/fixtures/completion/show_transform.typ
|
|||
"labelDetails": {
|
||||
"description": "([any], encoding: \"utf8\" | none) => bytes | str"
|
||||
},
|
||||
"sortText": "159",
|
||||
"textEdit": {
|
||||
"newText": "read",
|
||||
"newText": "read(${1:})",
|
||||
"range": {
|
||||
"end": {
|
||||
"character": 12,
|
||||
|
@ -94,6 +95,7 @@ input_file: crates/tinymist-query/src/fixtures/completion/show_transform.typ
|
|||
"labelDetails": {
|
||||
"description": "([any], encoding: \"utf8\" | none) => bytes | str"
|
||||
},
|
||||
"sortText": "160",
|
||||
"textEdit": {
|
||||
"newText": "read.with(${1:})",
|
||||
"range": {
|
||||
|
@ -107,23 +109,6 @@ input_file: crates/tinymist-query/src/fixtures/completion/show_transform.typ
|
|||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"kind": 15,
|
||||
"label": "replacement",
|
||||
"textEdit": {
|
||||
"newText": "[${1:content}]",
|
||||
"range": {
|
||||
"end": {
|
||||
"character": 12,
|
||||
"line": 1
|
||||
},
|
||||
"start": {
|
||||
"character": 11,
|
||||
"line": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -8,14 +8,33 @@ input_file: crates/tinymist-query/src/fixtures/completion/show_transform2.typ
|
|||
{
|
||||
"isIncomplete": false,
|
||||
"items": [
|
||||
{
|
||||
"kind": 15,
|
||||
"label": "replacement",
|
||||
"sortText": "000",
|
||||
"textEdit": {
|
||||
"newText": "[${1:content}]",
|
||||
"range": {
|
||||
"end": {
|
||||
"character": 11,
|
||||
"line": 1
|
||||
},
|
||||
"start": {
|
||||
"character": 11,
|
||||
"line": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"kind": 3,
|
||||
"label": "raw",
|
||||
"labelDetails": {
|
||||
"description": "(str, align: alignment, block: bool, lang: none | str, syntaxes: [syntax], tab-size: int, theme: [theme]) => raw"
|
||||
},
|
||||
"sortText": "157",
|
||||
"textEdit": {
|
||||
"newText": "raw",
|
||||
"newText": "raw(${1:})",
|
||||
"range": {
|
||||
"end": {
|
||||
"character": 11,
|
||||
|
@ -30,12 +49,13 @@ input_file: crates/tinymist-query/src/fixtures/completion/show_transform2.typ
|
|||
},
|
||||
{
|
||||
"kind": 3,
|
||||
"label": "raw.where",
|
||||
"label": "raw.with",
|
||||
"labelDetails": {
|
||||
"description": "(str, align: alignment, block: bool, lang: none | str, syntaxes: [syntax], tab-size: int, theme: [theme]) => raw"
|
||||
},
|
||||
"sortText": "158",
|
||||
"textEdit": {
|
||||
"newText": "raw.where(${1:})",
|
||||
"newText": "raw.with(${1:})",
|
||||
"range": {
|
||||
"end": {
|
||||
"character": 11,
|
||||
|
@ -49,10 +69,35 @@ input_file: crates/tinymist-query/src/fixtures/completion/show_transform2.typ
|
|||
}
|
||||
},
|
||||
{
|
||||
"kind": 15,
|
||||
"label": "replacement",
|
||||
"kind": 3,
|
||||
"label": "read",
|
||||
"labelDetails": {
|
||||
"description": "([any], encoding: \"utf8\" | none) => bytes | str"
|
||||
},
|
||||
"sortText": "159",
|
||||
"textEdit": {
|
||||
"newText": "[${1:content}]",
|
||||
"newText": "read(${1:})",
|
||||
"range": {
|
||||
"end": {
|
||||
"character": 11,
|
||||
"line": 1
|
||||
},
|
||||
"start": {
|
||||
"character": 11,
|
||||
"line": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"kind": 3,
|
||||
"label": "read.with",
|
||||
"labelDetails": {
|
||||
"description": "([any], encoding: \"utf8\" | none) => bytes | str"
|
||||
},
|
||||
"sortText": "160",
|
||||
"textEdit": {
|
||||
"newText": "read.with(${1:})",
|
||||
"range": {
|
||||
"end": {
|
||||
"character": 11,
|
||||
|
|
|
@ -14,7 +14,7 @@ input_file: crates/tinymist-query/src/fixtures/pkgs/touying-core-slides.typ
|
|||
"labelDetails": {
|
||||
"description": "() => any"
|
||||
},
|
||||
"sortText": "050",
|
||||
"sortText": "029",
|
||||
"textEdit": {
|
||||
"newText": "config-xxx()${1:}",
|
||||
"range": {
|
||||
|
|
|
@ -56,7 +56,7 @@ input_file: crates/tinymist-query/src/fixtures/pkgs/touying-core-slides.typ
|
|||
"labelDetails": {
|
||||
"description": "(content, gap: length, justify: bool) => repeat"
|
||||
},
|
||||
"sortText": "249",
|
||||
"sortText": "139",
|
||||
"textEdit": {
|
||||
"newText": "repeat[${1:}]",
|
||||
"range": {
|
||||
|
|
|
@ -35,7 +35,7 @@ input_file: crates/tinymist-query/src/fixtures/pkgs/touying-utils-cover-with-rec
|
|||
"labelDetails": {
|
||||
"description": "type"
|
||||
},
|
||||
"sortText": "295",
|
||||
"sortText": "161",
|
||||
"textEdit": {
|
||||
"newText": "stroke(${1:})",
|
||||
"range": {
|
||||
|
|
|
@ -32,7 +32,7 @@ input_file: crates/tinymist-query/src/fixtures/pkgs/touying-utils-current-headin
|
|||
"labelDetails": {
|
||||
"description": "type"
|
||||
},
|
||||
"sortText": "133",
|
||||
"sortText": "079",
|
||||
"textEdit": {
|
||||
"newText": "int(${1:})",
|
||||
"range": {
|
||||
|
|
|
@ -68,7 +68,7 @@ input_file: crates/tinymist-query/src/fixtures/pkgs/touying-utils-markup-text.ty
|
|||
"labelDetails": {
|
||||
"description": "type"
|
||||
},
|
||||
"sortText": "287",
|
||||
"sortText": "156",
|
||||
"textEdit": {
|
||||
"newText": "str(${1:})",
|
||||
"range": {
|
||||
|
|
|
@ -42,7 +42,6 @@ pub fn autocomplete(
|
|||
complete_labels(&mut ctx)
|
||||
|| complete_field_accesses(&mut ctx)
|
||||
|| complete_imports(&mut ctx)
|
||||
|| complete_rules(&mut ctx)
|
||||
|| complete_markup(&mut ctx)
|
||||
|| complete_math(&mut ctx)
|
||||
|| complete_code(&mut ctx, false)
|
||||
|
@ -341,7 +340,7 @@ fn complete_math(ctx: &mut CompletionContext) -> bool {
|
|||
/// Add completions for math snippets.
|
||||
#[rustfmt::skip]
|
||||
fn math_completions(ctx: &mut CompletionContext) {
|
||||
ctx.scope_completions(true, |_, _| true);
|
||||
ctx.scope_completions(true);
|
||||
|
||||
ctx.snippet_completion(
|
||||
"subscript",
|
||||
|
@ -589,109 +588,20 @@ fn import_item_completions<'a>(
|
|||
}
|
||||
}
|
||||
|
||||
/// Complete set and show rules.
|
||||
fn complete_rules(ctx: &mut CompletionContext) -> bool {
|
||||
let Some(prev) = ctx.leaf.prev_leaf() else {
|
||||
return false;
|
||||
};
|
||||
|
||||
// Behind the set keyword: "set |".
|
||||
if matches!(prev.kind(), SyntaxKind::Set) {
|
||||
ctx.from = if ctx.leaf.kind().is_trivia() {
|
||||
ctx.cursor
|
||||
} else {
|
||||
ctx.leaf.offset()
|
||||
};
|
||||
set_rule_completions(ctx);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Behind the show keyword: "show |".
|
||||
if matches!(prev.kind(), SyntaxKind::Show) {
|
||||
ctx.from = if ctx.leaf.kind().is_trivia() {
|
||||
ctx.cursor
|
||||
} else {
|
||||
ctx.leaf.offset()
|
||||
};
|
||||
show_rule_selector_completions(ctx);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Behind a half-completed show rule: "show strong: |".
|
||||
if_chain! {
|
||||
if let Some(prev) = ctx.leaf.prev_leaf();
|
||||
if matches!(prev.kind(), SyntaxKind::Colon);
|
||||
if matches!(prev.parent_kind(), Some(SyntaxKind::ShowRule));
|
||||
then {
|
||||
ctx.from = if ctx.leaf.kind().is_trivia() {
|
||||
ctx.cursor
|
||||
} else {
|
||||
ctx.leaf.offset()
|
||||
};
|
||||
show_rule_recipe_completions(ctx);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
/// Add completions for all functions from the global scope.
|
||||
fn set_rule_completions(ctx: &mut CompletionContext) {
|
||||
ctx.scope_completions(true, |_, _| true);
|
||||
}
|
||||
|
||||
/// Add completions for selectors.
|
||||
fn show_rule_selector_completions(ctx: &mut CompletionContext) {
|
||||
ctx.scope_completions(false, |_, _| true);
|
||||
|
||||
ctx.snippet_completion(
|
||||
"text selector",
|
||||
"\"${text}\"",
|
||||
"Replace occurrences of specific text.",
|
||||
);
|
||||
|
||||
ctx.snippet_completion(
|
||||
"regex selector",
|
||||
"regex(\"${regex}\")",
|
||||
"Replace matches of a regular expression.",
|
||||
);
|
||||
|
||||
ctx.enrich("", ": ${}");
|
||||
}
|
||||
|
||||
/// Add completions for recipes.
|
||||
fn show_rule_recipe_completions(ctx: &mut CompletionContext) {
|
||||
ctx.snippet_completion(
|
||||
"replacement",
|
||||
"[${content}]",
|
||||
"Replace the selected element with content.",
|
||||
);
|
||||
|
||||
ctx.snippet_completion(
|
||||
"replacement (string)",
|
||||
"\"${text}\"",
|
||||
"Replace the selected element with a string of text.",
|
||||
);
|
||||
|
||||
ctx.snippet_completion(
|
||||
"transformation",
|
||||
"element => [${content}]",
|
||||
"Transform the element with a function.",
|
||||
);
|
||||
|
||||
ctx.scope_completions(false, |_, c| !c.functions.is_empty());
|
||||
}
|
||||
|
||||
/// Complete in code mode.
|
||||
fn complete_code(ctx: &mut CompletionContext, from_type: bool) -> bool {
|
||||
let surrounding_syntax = ctx.surrounding_syntax();
|
||||
|
||||
if matches!(
|
||||
ctx.leaf.parent_kind(),
|
||||
None | Some(SyntaxKind::Markup)
|
||||
| Some(SyntaxKind::Math)
|
||||
| Some(SyntaxKind::MathFrac)
|
||||
| Some(SyntaxKind::MathAttach)
|
||||
| Some(SyntaxKind::MathRoot)
|
||||
(ctx.leaf.parent_kind(), surrounding_syntax),
|
||||
(
|
||||
None | Some(SyntaxKind::Markup)
|
||||
| Some(SyntaxKind::Math)
|
||||
| Some(SyntaxKind::MathFrac)
|
||||
| Some(SyntaxKind::MathAttach)
|
||||
| Some(SyntaxKind::MathRoot),
|
||||
SurroundingSyntax::Regular
|
||||
)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
@ -730,11 +640,9 @@ fn complete_code(ctx: &mut CompletionContext, from_type: bool) -> bool {
|
|||
/// Add completions for expression snippets.
|
||||
#[rustfmt::skip]
|
||||
fn code_completions(ctx: &mut CompletionContext, hash: bool) {
|
||||
ctx.scope_completions(true, |_value, _| !hash || {
|
||||
// todo: filter code completions
|
||||
// matches!(value, Value::Symbol(_) | Value::Func(_) | Value::Type(_) | Value::Module(_))
|
||||
true
|
||||
});
|
||||
// todo: filter code completions
|
||||
// matches!(value, Value::Symbol(_) | Value::Func(_) | Value::Type(_) | Value::Module(_))
|
||||
ctx.scope_completions(true);
|
||||
|
||||
ctx.snippet_completion(
|
||||
"function call",
|
||||
|
|
|
@ -107,19 +107,11 @@ impl<'a> CompletionContext<'a> {
|
|||
self.ctx.world()
|
||||
}
|
||||
|
||||
pub fn scope_completions(
|
||||
&mut self,
|
||||
parens: bool,
|
||||
filter: impl Fn(&Ty, &CompletionKindChecker) -> bool,
|
||||
) {
|
||||
self.scope_completions_(parens, filter);
|
||||
}
|
||||
|
||||
fn seen_field(&mut self, field: Interned<str>) -> bool {
|
||||
!self.seen_fields.insert(field)
|
||||
}
|
||||
|
||||
fn surrounding_syntax(&mut self) -> SurroundingSyntax {
|
||||
pub(crate) fn surrounding_syntax(&mut self) -> SurroundingSyntax {
|
||||
check_previous_syntax(&self.leaf)
|
||||
.or_else(|| check_surrounding_syntax(&self.leaf))
|
||||
.unwrap_or(SurroundingSyntax::Regular)
|
||||
|
@ -402,11 +394,7 @@ impl<'a> CompletionContext<'a> {
|
|||
/// Add completions for definitions that are available at the cursor.
|
||||
///
|
||||
/// Filters the global/math scope with the given filter.
|
||||
pub fn scope_completions_(
|
||||
&mut self,
|
||||
parens: bool,
|
||||
filter: impl Fn(&Ty, &CompletionKindChecker) -> bool,
|
||||
) {
|
||||
pub fn scope_completions(&mut self, parens: bool) {
|
||||
let Some((_, defines)) = self.defines() else {
|
||||
return;
|
||||
};
|
||||
|
@ -421,8 +409,8 @@ impl<'a> CompletionContext<'a> {
|
|||
functions: HashSet::default(),
|
||||
};
|
||||
|
||||
let filter = |ty: &Ty, c: &CompletionKindChecker| {
|
||||
let s = match surrounding_syntax {
|
||||
let filter = |c: &CompletionKindChecker| {
|
||||
match surrounding_syntax {
|
||||
SurroundingSyntax::Regular => true,
|
||||
SurroundingSyntax::Selector => 'selector: {
|
||||
for func in &c.functions {
|
||||
|
@ -433,6 +421,7 @@ impl<'a> CompletionContext<'a> {
|
|||
|
||||
false
|
||||
}
|
||||
SurroundingSyntax::ShowTransform => !c.functions.is_empty(),
|
||||
SurroundingSyntax::SetRule => 'set_rule: {
|
||||
// todo: user defined elements
|
||||
for func in &c.functions {
|
||||
|
@ -445,8 +434,7 @@ impl<'a> CompletionContext<'a> {
|
|||
|
||||
false
|
||||
}
|
||||
};
|
||||
s && filter(ty, c)
|
||||
}
|
||||
};
|
||||
|
||||
// we don't check literal type here for faster completion
|
||||
|
@ -456,7 +444,7 @@ impl<'a> CompletionContext<'a> {
|
|||
}
|
||||
|
||||
kind_checker.check(&ty);
|
||||
if !filter(&ty, &kind_checker) {
|
||||
if !filter(&kind_checker) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -492,7 +480,7 @@ impl<'a> CompletionContext<'a> {
|
|||
|
||||
log::debug!("fn_feat: {name} {ty:?} -> {fn_feat:?}");
|
||||
|
||||
if matches!(surrounding_syntax, SurroundingSyntax::Regular)
|
||||
if matches!(surrounding_syntax, SurroundingSyntax::ShowTransform)
|
||||
&& (fn_feat.min_pos() > 0 || fn_feat.min_named() > 0)
|
||||
{
|
||||
self.completions.push(Completion {
|
||||
|
@ -501,7 +489,7 @@ impl<'a> CompletionContext<'a> {
|
|||
..base.clone()
|
||||
});
|
||||
}
|
||||
if fn_feat.is_element && !matches!(surrounding_syntax, SurroundingSyntax::SetRule) {
|
||||
if fn_feat.is_element && matches!(surrounding_syntax, SurroundingSyntax::Selector) {
|
||||
self.completions.push(Completion {
|
||||
label: eco_format!("{}.where", name),
|
||||
apply: Some(eco_format!("{}.where(${{}})", name)),
|
||||
|
@ -514,7 +502,7 @@ impl<'a> CompletionContext<'a> {
|
|||
SurroundingSyntax::Selector | SurroundingSyntax::SetRule
|
||||
) && !fn_feat.is_element;
|
||||
if !bad_instantiate {
|
||||
if !parens {
|
||||
if !parens || matches!(surrounding_syntax, SurroundingSyntax::Selector) {
|
||||
self.completions.push(Completion {
|
||||
label: name,
|
||||
..base
|
||||
|
@ -554,10 +542,11 @@ impl<'a> CompletionContext<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum SurroundingSyntax {
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub(crate) enum SurroundingSyntax {
|
||||
Regular,
|
||||
Selector,
|
||||
ShowTransform,
|
||||
SetRule,
|
||||
}
|
||||
|
||||
|
@ -594,13 +583,13 @@ fn check_surrounding_syntax(mut leaf: &LinkedNode) -> Option<SurroundingSyntax>
|
|||
.to_untyped()
|
||||
.children()
|
||||
.find(|s| s.kind() == SyntaxKind::Colon);
|
||||
if colon.is_none() {
|
||||
let Some(colon) = colon.and_then(|colon| parent.find(colon.span())) else {
|
||||
// incomplete show rule
|
||||
return Some(Selector);
|
||||
}
|
||||
};
|
||||
|
||||
if encolsed_by(parent, Some(rule.transform().span()), leaf) {
|
||||
return Some(Regular);
|
||||
if leaf.offset() >= colon.offset() {
|
||||
return Some(ShowTransform);
|
||||
} else {
|
||||
return Some(Selector); // query's first argument
|
||||
}
|
||||
|
@ -1410,14 +1399,11 @@ pub(crate) fn complete_type(ctx: &mut CompletionContext) -> Option<()> {
|
|||
{
|
||||
args_node = e.parent().map(|s| s.get().clone());
|
||||
}
|
||||
Some(CheckTarget::Normal(e))
|
||||
if matches!(
|
||||
e.kind(),
|
||||
SyntaxKind::Ident | SyntaxKind::Label | SyntaxKind::Ref | SyntaxKind::Str
|
||||
) => {}
|
||||
Some(CheckTarget::Paren { .. }) => {}
|
||||
Some(CheckTarget::Normal(..)) => return None,
|
||||
None => return None,
|
||||
// todo: complete type field
|
||||
Some(CheckTarget::Normal(e)) if matches!(e.kind(), SyntaxKind::FieldAccess) => {
|
||||
return None;
|
||||
}
|
||||
Some(CheckTarget::Paren { .. } | CheckTarget::Normal(..)) | None => {}
|
||||
}
|
||||
|
||||
log::debug!("ctx.leaf {:?}", ctx.leaf.clone());
|
||||
|
@ -1425,16 +1411,24 @@ pub(crate) fn complete_type(ctx: &mut CompletionContext) -> Option<()> {
|
|||
let ty = ctx
|
||||
.ctx
|
||||
.literal_type_of_node(ctx.leaf.clone())
|
||||
.filter(|ty| !matches!(ty, Ty::Any))?;
|
||||
.filter(|ty| !matches!(ty, Ty::Any));
|
||||
|
||||
let scope = ctx.surrounding_syntax();
|
||||
if matches!((scope, &ty), (SurroundingSyntax::Regular, None)) {
|
||||
return None;
|
||||
}
|
||||
|
||||
log::debug!("complete_type: {:?} -> ({scope:?}, {ty:#?})", ctx.leaf);
|
||||
|
||||
// adjust the completion position
|
||||
if is_ident_like(&ctx.leaf) {
|
||||
ctx.from = ctx.leaf.offset();
|
||||
}
|
||||
|
||||
log::debug!("complete_type: ty {:?} -> {ty:#?}", ctx.leaf);
|
||||
if let Some(ty) = ty {
|
||||
type_completion(ctx, &ty, None);
|
||||
}
|
||||
|
||||
type_completion(ctx, &ty, None);
|
||||
if ctx.before.ends_with(',') || ctx.before.ends_with(':') {
|
||||
ctx.enrich(" ", "");
|
||||
}
|
||||
|
@ -1454,9 +1448,7 @@ pub(crate) fn complete_type(ctx: &mut CompletionContext) -> Option<()> {
|
|||
}
|
||||
}
|
||||
|
||||
let surrounding_syntax = ctx.surrounding_syntax();
|
||||
|
||||
match surrounding_syntax {
|
||||
match scope {
|
||||
SurroundingSyntax::Regular => {}
|
||||
SurroundingSyntax::Selector => {
|
||||
ctx.snippet_completion(
|
||||
|
@ -1471,16 +1463,36 @@ pub(crate) fn complete_type(ctx: &mut CompletionContext) -> Option<()> {
|
|||
"Replace matches of a regular expression.",
|
||||
);
|
||||
}
|
||||
SurroundingSyntax::ShowTransform => {
|
||||
ctx.snippet_completion(
|
||||
"replacement",
|
||||
"[${content}]",
|
||||
"Replace the selected element with content.",
|
||||
);
|
||||
|
||||
ctx.snippet_completion(
|
||||
"replacement (string)",
|
||||
"\"${text}\"",
|
||||
"Replace the selected element with a string of text.",
|
||||
);
|
||||
|
||||
ctx.snippet_completion(
|
||||
"transformation",
|
||||
"element => [${content}]",
|
||||
"Transform the element with a function.",
|
||||
);
|
||||
}
|
||||
SurroundingSyntax::SetRule => {}
|
||||
}
|
||||
|
||||
sort_and_explicit_code_completion(ctx);
|
||||
|
||||
match surrounding_syntax {
|
||||
match scope {
|
||||
SurroundingSyntax::Regular => {}
|
||||
SurroundingSyntax::Selector => {
|
||||
ctx.enrich("", ": ${}");
|
||||
}
|
||||
SurroundingSyntax::ShowTransform => {}
|
||||
SurroundingSyntax::SetRule => {}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue