From 1a63804b026c488762068f4eaa7d804b708a73a1 Mon Sep 17 00:00:00 2001 From: FichteFoll Date: Sat, 15 Feb 2025 19:53:26 +0100 Subject: [PATCH 1/2] Fix zipball link --- docs/guide/extensibility/plugins/input_handlers/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/guide/extensibility/plugins/input_handlers/index.md b/docs/guide/extensibility/plugins/input_handlers/index.md index ba316b22..3ffcc548 100644 --- a/docs/guide/extensibility/plugins/input_handlers/index.md +++ b/docs/guide/extensibility/plugins/input_handlers/index.md @@ -323,7 +323,7 @@ Try for yourself! The final code examples presented on this page [are included in the source git repository][code]. -You can download a [zip][] of it (via [DownGit][]) +You can download a [zipball][] of it (via [DownGit][]) and extract it into your Packages folder to experiment with them. From 8cbb764ba03fb76e7aa8cd11318b0d9086f3e3fd Mon Sep 17 00:00:00 2001 From: FichteFoll Date: Sat, 15 Feb 2025 19:59:17 +0100 Subject: [PATCH 2/2] Add "Accumulating Inputs from a List" section Provide and discuss an example for accumulating multiple input values in a single list, utilizing the 2-tuple return value of `list_items`, event info when specifying `want_event`, and a sort of self-overriding `next_input` return value. I initially made this during a discussion on Discord: https://discord.com/channels/280102180189634562/280157067396775936/1192776891183140955 --- .../code/Input Handlers.sublime-commands | 1 + .../plugins/input_handlers/code/accumulate.py | 51 ++++++++++ .../input_handlers/images/accumulate.mp4 | 3 + .../plugins/input_handlers/index.md | 96 +++++++++++++++++++ 4 files changed, 151 insertions(+) create mode 100644 docs/guide/extensibility/plugins/input_handlers/code/accumulate.py create mode 100644 docs/guide/extensibility/plugins/input_handlers/images/accumulate.mp4 diff --git a/docs/guide/extensibility/plugins/input_handlers/code/Input Handlers.sublime-commands b/docs/guide/extensibility/plugins/input_handlers/code/Input Handlers.sublime-commands index 712f149f..9db9cc27 100644 --- a/docs/guide/extensibility/plugins/input_handlers/code/Input Handlers.sublime-commands +++ b/docs/guide/extensibility/plugins/input_handlers/code/Input Handlers.sublime-commands @@ -2,4 +2,5 @@ { "caption": "Simple Command", "command": "simple" }, { "caption": "Insert Html Entity", "command": "insert_html_entity" }, { "caption": "Multiply", "command": "multiply" }, + { "caption": "Accumulate", "command": "accumulate" }, ] diff --git a/docs/guide/extensibility/plugins/input_handlers/code/accumulate.py b/docs/guide/extensibility/plugins/input_handlers/code/accumulate.py new file mode 100644 index 00000000..12915355 --- /dev/null +++ b/docs/guide/extensibility/plugins/input_handlers/code/accumulate.py @@ -0,0 +1,51 @@ +import sublime_plugin + + +class ItemsInputHandler(sublime_plugin.ListInputHandler): + def __init__(self, choices, accumulated=None, selected_index=0): + self.choices = choices + self.accumulated = accumulated or [] + self.selected_index = selected_index + + self.alt_pressed = False + self.selected = None + + def want_event(self): + # Declare that we want to receive the `event` argument. + return True + + def validate(self, _value, _event): + # We must override this method because we define `want_event`. + # https://github.com/sublimehq/sublime_text/issues/6258 + return True + + def list_items(self): + # Each selectable item represents + # all accumulated items plus the new item as a list. + return ( + [(item, self.accumulated + [item]) for item in self.choices], + self.selected_index, + ) + + def confirm(self, value, event): + # Record that the alt key was pressed when confirming + # so that we can return a follow-up input handler + # in `next_input`. + self.alt_pressed = event["modifier_keys"].get("alt", False) + self.selected = value + + def next_input(self, _args): + if self.alt_pressed: + selected_index = self.choices.index(self.selected[-1]) + return ItemsInputHandler(self.choices, self.selected, selected_index) + return None + + +class AccumulateCommand(sublime_plugin.WindowCommand): + def input(self, args): + if "items" not in args: + choices = "a b c d e".split(" ") + return ItemsInputHandler(choices=choices) + + def run(self, items): + self.window.run_command('insert', {'characters': " ".join(items)}) diff --git a/docs/guide/extensibility/plugins/input_handlers/images/accumulate.mp4 b/docs/guide/extensibility/plugins/input_handlers/images/accumulate.mp4 new file mode 100644 index 00000000..7dae8296 --- /dev/null +++ b/docs/guide/extensibility/plugins/input_handlers/images/accumulate.mp4 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:369c64b5371943e299f4d4e6efed8775fa4c7e89dba75e1fb0747ad4b5daadab +size 293113 diff --git a/docs/guide/extensibility/plugins/input_handlers/index.md b/docs/guide/extensibility/plugins/input_handlers/index.md index 3ffcc548..1aa6b15a 100644 --- a/docs/guide/extensibility/plugins/input_handlers/index.md +++ b/docs/guide/extensibility/plugins/input_handlers/index.md @@ -319,6 +319,102 @@ Try for yourself! ::: +### Accumulating Inputs from a List + +It is also possible to accumulate multiple inputs dynamically. +We can achieve this +by using lists as the values +of our ListInputHandler's `list_items` return value. + +To allow the user to signal that they want to select more values, +we define the `want_event` method and `return True` from it. +This tells Sublime Text to add an [`event` argument][Event] +to the `validate` and `confirm` methods, +which we use to determine +if a certain modifier key was held +and whether to return another input handler +in the `next_input` method. + +:::tip +Due to [a bug in the plugin API][core-6258], +we need to define *both* methods, +`validate` and `confirm`, +and have them accept this additional `event` argument, +even when we don't need them. +::: + +<<< ./code/accumulate.py {13-15,25-28,34-35,38-40,47-48} + +Here is what it looks like in action: + +