SublimeText / sublime_lib

Utility library for frequently used functionality in Sublime Text and convenience functions or classes
https://sublimetext.github.io/sublime_lib
MIT License
52 stars 4 forks source link

API to list/inspect commands #124

Open Thom1729 opened 5 years ago

Thom1729 commented 5 years ago

PackageDev needs to know what commands exist in order to perform autocompletion, and it provides an implementation of the necessary logic (as well as a list of known built-in commands). The same logic could be useful for other packages as well. For instance, I have an unpublished concise keymap package that could provide similar autocomplete functionality.

Integrating this functionality into sublime_lib, in a similar-ish manner to sublime_lib.list_syntaxes() and such, would allow other plugins to easily make use of it. It would also be an opportunity to add a robust test suite.

FichteFoll commented 5 years ago

I have to wonder how packages would use the quite specific implementation for PackageDev and how many those would be tbh. Currently it has a large focus on auto completion, which is why built-in commands are included separately, at which point I believe that another package looking to implement completions for their own configuration format might as well require PD to be installed and use the module from there.

Thom1729 commented 5 years ago

I imagine that the API would be something like this:

Where CommandInfo is a namedtuple with the following properties:

A builtin command would have a command_class of None.

Currently, one of the PackageDev completions is implemented as follows:

from ..lib import sorted_completions
from .commandinfo import (
    get_command_name,
    get_builtin_commands,
    iter_python_command_classes
)

class SublimeTextCommandCompletionListener(sublime_plugin.EventListener):

    @staticmethod
    def _create_completion(c):
        name = get_command_name(c)
        module = c.__module__
        package = module.split(".")[0]
        show = "{name}\t{package}".format(**locals())
        return show, name

    def on_query_completions(self, view, prefix, locations):
        # scope check omitted

        command_classes = iter_python_command_classes()

        completions = set()
        completions.update((c + "\tbuilt-in", c) for c in get_builtin_commands())
        completions.update(self._create_completion(c) for c in command_classes)
        return sorted_completions(completions), sublime.INHIBIT_WORD_COMPLETIONS

With this API, it could be implemented thus:

from ..lib import sorted_completions
from sublime_lib import list_commands

class SublimeTextCommandCompletionListener(sublime_plugin.EventListener):

    def on_query_completions(self, view, prefix, locations):
        # scope check omitted

        def command_source(klass):
            if klass is None:
                return 'built-in'
            else:
                return klass.__module__.split(".")[0]

        completions = [
            ("{name}\t{source}".format(
                name=command.name,
                source=command_source(command.command_class)
            ), command.name)
            for commmand in list_commands()
        ]

        return sorted_completions(completions), sublime.INHIBIT_WORD_COMPLETIONS

The sublime_lib API would determine the command names and merge the builtin and class-based commands so that the client code would be presented with a uniform list.

FichteFoll commented 5 years ago

Can you think of a use case other than what PD already provides?

The only other thing I know is EditPreferences which opens a command palette with all commands implemented through plugins and allows you to view their source. But that doesn't need the commands' arguments or built-in commands and would barely make use of this in form of a library.