But none of the others are there in the list.
Are you sure they’re not just further down? If you start typing Builtin does BuiltinTransform show up?
But none of the others are there in the list.
Are you sure they’re not just further down? If you start typing Builtin does BuiltinTransform show up?
Hmmm, yes you’re right. That then does pop up. I can’t scroll down the list at all.
I was expecting the full list I supplied to be there, and scrollable.
I’d like this to be a prompt list of the specific available keywords.
That was what I was expecting. Which may be an incorrect expectations…
I have also tried this format:
{
"scope": "source.yaml",
"completions": [
"View","Views","Look","BuiltinTransform",
{
"trigger": "!<",
"contents": "Rule> $0",
"kind": "type",
"annotation": "OCIO Rule"
}
]
}
When I save this file, and type !< I get a similar popup.
The bottom item is the trigger condition referenced in the above sublime-completions file.
My understanding from the docs is that “annotation” text should appear in the bottom item. To enable a small explanation. Since it appears its not making any attempt to put in the “contents” or the result in the line. But that seems wrong as well.
Note that I cannot scroll through the popup.
ST only provides a limited list of nearest matching words according to internal heuristics. It should update the list as you type. Alternatively hit ctrl+space.
static completion files don’t work well for tokens which do not look like normal words. !
and <
are word separator chars, which causes !<
not to be recognized as proper word / trigger. You could try to escape them, but AFAIK the only way to get such completions is via plugins, currently.
When you say “nearest matching words” does that mean nearest matching from the list of completions in the completions file plus the auto generated list? I assume so, otherwise the completions files are pointless.
As for ctrl+space… Why is that any different from the automatic list?
This is all incredibly confusing, and totally unexplained in the docs. The docs can also explain limitations in software. That’s a good service to users too.
Also ctrl+space gives worse results in the list than the automatic popup. Presumably because it hasn’t been activated by the trigger.
Is there any reason that the annotations aren’t working? Or the name of the replacement text isn’t appearing in the completion from the completion list?
I’d like to just get the parts workjing that are promised in the docs. ie actually seeing the contents in the pop up. Along with annotations.
With a sublime-completions
file like:
{
"scope": "source.yaml",
"completions": [
{
"trigger": "rule",
"contents": "Rule> $0",
"kind": "type",
"annotation": "OCIO Rule",
"details": "Insert an OCIO Rule"
}
]
}
The trigger
is the text that will be matched and replaced with the completion contents, so long as the word to the left of all of the active cursors in the file is a prefix substring of the trigger (so r
, ru
, rul
and rule
would work, but rub
would not). This also takes fuzzy filtering into account as well, so re
works because the filter has an r
and an e
in it, in that order.
The contents
is the text that gets replaced. That’s not generally placed into the popup panel because it’s arbitrarily big.
The kind
is used to provide a colorized icon/text to the left of the completion in the menu, to provide some additional hints as to what it is.
The annotation
is a piece of text that gets displayed to the right of the completion (aligned on the right edge of the popup), which gives you context hints as to what the completion is or will insert (i.e. this is here because it’s more controlled than just dumping the entire contents
out).
details
provide an extra piece of text along the bottom of the panel, to provide more detailed context, since normally you want the annotation to be a shorter piece of text or the AC panel would get to wide.
So with the above, in a YAML file typing just r
(as the shortest possible prefix substring of the completion), you see:
The prefix matching wants to match the word to the left of the cursor to an autocomplete and show you all of the possible matching completions, so:
auto_complete_use_history
and auto_complete_preserve_order
for examplelong_rule_here
could be filtered down to via lr
or lrh
word
with the replacement text; characters like !<
are not considered words and so would not be considered to be part of the trigger text.If the up and down arrows don’t scroll through the AC panel, you might want to double check if any bindings are blocking it; perhaps a package has overridden a key binding in a way that’s stopping it from working.
Thank you for the extensive reply.
Given the difficulty with using !< as a trigger, perhaps there’s away of using scopes to limit where particular completions appear.
I notice that as I type “!<” it gets highlit with red, indicating a scope of:
invalid.illegal.tag-handle.yaml
So I thought I could use that scope as a way of indicating where my completions file should be used.
However, when I examine the scope at the cursor position immediately after “!<” it shows the root scope of:
source.yaml
If I move the cursor between the “!<” then it shows the expected scope.
source.yaml meta.property.yaml invalid.illegal.tag-handle.yaml
The docs say that Ctrl+Alt+Shift+P gets the scope under the cursor. Which I guess in this case means that the cursor is outside the scope.
Is there any way of capturing the scope immediately to the left of the cursor? Or perhaps the scope that’s just been created?
Sorry, what I meant was that the arrow keys scroll up and down the list, but they don’t scroll to any more completions that don’t show already.
My understanding from context and a comment from someone else, was that we could scroll to more completions that are off the bottom of the pop up list.
When I use Ctrl+Space to invoke the completion popup, it also doesn’t let me scroll to any more completions that might be off the bottom of the list.
I only have Package Manager, and PackageDev installed.
The autocompletion popup shows a bunch of keywords associated with a YAML tag rule. Fair rnough.
However, when I add my own completion rule, the auto created rule/s remain. This is at best incredibly confusing.
You can see in the above popup the Rule at the top of the list has been auto generated.
And immediately below it, is my completion rule.
I would have hoped that rules from completion files replace auto generated rules.
I’m unsure if there are any settings that may help this.
ST limits the number of completions it provides. It is likely desired ones are therefore missing, because internal ST heuristics judged them not relevant enough. That’s why my suggestion to re-trigger via ctrl+space. Depending on already typed trigger it may or may not improve the presented items. If no trigger has been typed - st has no info about what you might want and thus the list might be a bit of not useful.
Then how do completion files for HTML work? They are using <> etc all the time.
HTML ships plugin-based completions. That’s way more flexible as trigger can be analyzed by python code to make decisions of what items to return. The entry point is https://github.com/sublimehq/Packages/blob/b451c77f8c7303d44ce0a09288d6ff25958a2425/HTML/html_completions.py#L457
ST uses various internal heuristics based on already existing content, typed trigger, etc. to decide, which completion items may be most relevant. I don’t know the exact algorithm though, but I know it sometimes feels like magic - as if ST already knows what you want - and sometimes it epically fails. Quality of syntax defintions and symbol definitions are quite important to get good results.
That is correct; the syntax rule that is matching that only consumes the text that it thinks is invalid, so if the cursor is after !<
it’s not invalid at that point, only within.
Yes, but only via plugin code, similar to what the plugin that DeathAxe linked above from the HTML
package.
A minimal example for a plugin based completions plugin would be:
import sublime
import sublime_plugin
class YamlCompletions(sublime_plugin.EventListener):
def on_query_completions(self, view, prefix, locations):
if not view.match_selector(locations[0], "source.yaml"):
return
pt = locations[0]
# get the text in front of first caret
token = view.substr(sublime.Region(pt - 2, pt))
if token == "!<":
return sublime.CompletionList(
[
sublime.CompletionItem(
trigger="!<Rule",
kind=[sublime.KindId.FUNCTION, "r", "Rule"],
annotation="My Rule",
details="This is a rule to..."
)
]
)
We need to read content from before caret’s location as prefix
is empty due to !<
being word separator characters (which is also the reason why static completions don’t work).
So we get the text left to caret manually and return completions, if they match certain criteria.
Thank you for the example. Very helpful.
Am I correct that it would also be possible to move the cursor one character to the left, then read the context of that block? I was looking at the ScopeContext plugin and it appears to have functions that use view.scope_name to retrieve the current scope.
I am investigating further…