Sublime Forum

Table of Key Bindings

#32

Hm, do you already have an EventListener and listen for on_activated/deactivated? They fire for panel buffers as well as all other views (IIRC). I usually have a little state where I keep track of that if I need that information. I have these (non-async!) handlers very, very thin, e.g. just store the active view or active window or viewport and then do any computation when needed, lazy and/or on the “async”/worker thread.

Then you have e.g. https://www.sublimetext.com/docs/api_reference.html#sublime.View.element to ask what type a view is; IIRC they don’t change their type, so if you once detected which id a panel, find input box etc has they never change; likely that’s per Window of course but still. It is recommended to call view api function like view.element() while being on the UI/main thread as the worker thread would need a lock on the view anyways (which it already has running on the UI/blocking thread).

sublime-context Package from ST2 had a lot of bugs

I thin ST2 only had EventListeners and ViewEventListener was invented for ST3.

How are these bindings ordered? A while back, it was User package first, then unpacked packages, then packed/zipped packages, for both: py33 before py38. Packages sorted in reversed alpha sort (not casefold). But I now do wonder if you can get a better picture by just observing sublime_plugin.py’s internal state.

0 Likes

#33

Excellent idea!

It also dawned on me as I was waking up this morning that the “real” current view comes with TEXT COMMANDS! I remember having seen it in BoxDrawing and I put something in that Package to avoid permitting box drawing in the various Panels and Overlays. I’ve been using an ApplicationCommand! And of course window.active_view() only gives views attached to Sheets! And sure enough, it works! and I THINK that is also going to solve 2 the “overlay_has_focus” tests. Check this out (from a quick test):

Console:

window.views()

produces:

>>> window.views()
[View(13), View(33), View(22), View(14), View(16), View(18), View(19), View(23)]

TestTextCommand:

        print(self.view)
        print(self.view.element())

Produces (when focus is on Console input View):

View(34)     // <-- note this is not in the "active views" list.
console:input

Solved! :partying_face:

I think ST2 only had EventListeners and ViewEventListener was invented for ST3.

That would account for what I saw!

About ordering, lucky for us that keymap_paths = sublime.find_resources('*.sublime-keymap') appears to be returning them in initialization-time LOAD ordering, which I have been purposely taking advantage of in ordering of data collected for each report! :slight_smile:

P.S.

While I was collecting those ViewEventLister objects, I also noted that they “already know the View they are listening for” in an attribute, and I’m updating that too so they have the current View (at the beginning of each report).

    context.update_view_event_listeners(self.view)

P.P.S.

I also got an answer on what “panel_type” is—found it in Default (Windows).sublime-keymap!

I don’t know what OTHER values it might have, but it appears in 6 key bindings combined with the panel_has_focus test like this (shows possible values of “find” and “input”):

	{ "keys": ["alt+c"], "command": "toggle_case_sensitive", "context":
		[{"key": "panel_type", "operand": "find"}, {"key": "panel_has_focus"}],
	},
	{ "keys": ["enter"], "command": "select", "context":
		[
			{ "key": "panel_has_focus", "operator": "equal", "operand": true },
			{ "key": "panel_type", "operand": "input"},
		],
	},

And testing is showing Sublime Text defines:

  • “input” = (didn’t know how to test this one, but I am guessing any panel created by window.create_io_panel())
  • “find” = any input View on any of these Panels:
    • Find
    • Find-in-Files
    • Replace
    • Incremental Find
  • “output” = output of a Build System, but not of the console (probably any output Panel), which means any panel created with window.create_output_panel().

*grrrrrr I wish this stuff was documented… :frowning: *

A look into the list produced by window.panels() contains ONLY the above Find panels plus input and output panels, and the console, which seems to be an exception. I noted in the view.element() API documentation that it says the console output View is not accessible via the API. So the above kind of makes sense.

And testing with “exec” didn’t succeed, so it does not appear to be in the above list.

P.P.P.S.

…and just to document it: the possible values for “overlay_name” are (as proven in testing it with Sublime Text response to an actual key binding):

  • “goto”, and
  • “command_palette”

“goto_anything” does not work.

0 Likes

#34

Goodness, I love this editor!! :smile:

0 Likes

#35

Final results for CONTEXT logic:

All implemented, tested and working except:

  • has_next_field (I found no approach to implement it with current API)
  • has_prev_field (I found no approach to implement it with current API)
  • is_recording_macro (I found no approach to implement it with current API, though there is a way to get info about a macro already recorded)
  • overlay_visible (partial implementation)

With overlay_visible, it works correctly for Goto-Anything Overlay because it closes when you move focus back to the editing area (or anywhere else). However, it does not work for the Command Palette since it “lingers” when focus is moved elsewhere, or rather, it works when it has focus, and not when it doesn’t.

And that is the conclusion of the CONTEXT logic! I’m building it like a library so it can be re-used elsewhere.

Now for the output logic… and documenting everything I have learned so far that isn’t documented elsewhere.

0 Likes

#36

Which license applies to your docs (http://crystal-clear-research.com/docs/quickrefs/sublime_text/), I only see a copyright notice. Asking as there might be things that could be added to https://docs.sublimetext.io/ (I did only see that you seem to have written quite much). If you could put it under a free license, your work could be reused.

1 Like

#37

The above answers my puzzle as a sole experimenter. I was puzzling how do I put these ideas to use? These are very comprehensive works to learn from. My thoughts are to experiment with building a higher layer of UI-bindings. Not based on keys memory. Thanks for the contribution.

1 Like

#38

Hi, @milkman!

Good question. Because this is such an important topic, I have moved it here. I look forward to discussing this with you and others who are involved at the Sublime HQ decision-making level.

Kind regards,
Vic

0 Likes

#39

Hi, @herr.kaste !

It’s coming along… A little wide but readable. The Package, File and Comments columns are optional, generated by passing flags into the report request. The use case for a Comments was copy/pasting the report into a documentation file and filling in information there appropriate to whatever the person was documenting. The reStructuredText version comes out in legal reST format with markup for linked footnotes.

What do you think?


KeyBindingReport:  Specified Key-Bindings
=========================================

Report generated:  2026-04-26 16:39:45

Key:

  - S = Shift
  - C = Ctrl
  - A = Alt
  - (Footnote ref) prefixing command means context is shown in footnote.

+---+-+-+-+------------------------------------------+---------+----------------------------------+--------------------------------------------------------------+
|Key|S|C|A| Command                                  | Package | File                             | Comments                                                     |
| ' | | | | (1) insert_snippet({'contents': "'$0'"}) | Default | Default (Windows).sublime-keymap |                                                              |
| ' | | | | (2) insert({'characters': "'"})          | Python  | Default.sublime-keymap           |                                                              |
| ' | | | | (3) insert_snippet({'contents': "'$0'"}) | Python  | Default.sublime-keymap           |                                                              |
| " | | | | (4) insert_snippet({'contents': '"$0"'}) | Default | Default (Windows).sublime-keymap |                                                              |
| " | | | | (5) insert({'characters': '"'})          | Python  | Default.sublime-keymap           |                                                              |
| " | | | | (6) insert_snippet({'contents': '"$0"'}) | Python  | Default.sublime-keymap           |                                                              |
+---+-+-+-+------------------------------------------+---------+----------------------------------+--------------------------------------------------------------+

(1)
    "context": [
      { "key": "setting.auto_match_enabled", "operator": "equal"             , "operand": True },
      { "key": "selection_empty"           , "operator": "equal"             , "operand": True, "match_all": True },
      { "key": "following_text"            , "operator": "regex_contains"    , "operand": '^(?:\t| |\\)|]|\\}|>|$)', "match_all": True },
      { "key": "preceding_text"            , "operator": "not_regex_contains", "operand": "['a-zA-Z0-9_]$", "match_all": True },
      { "key": "eol_selector"              , "operator": "not_equal"         , "operand": 'string.quoted.single - punctuation.definition.string.end', "match_all": True }
    ]
(2)
    "context": [
      { "key": "setting.auto_match_enabled" },
      { "key": "selector"                  , "operand": 'source.python - string.quoted.single' },
      { "key": "selection_empty"           , "match_all": True }
    ]
(3)
    "context": [
      { "key": "setting.auto_match_enabled" },
      { "key": "selector"                  , "operand": 'source.python - string.quoted.single' },
      { "key": "selection_empty"           , "match_all": True },
      { "key": "preceding_text"            , "operator": "regex_contains", "operand": "(?i:^|[^'\\w\\\\]|\\b[bfru]+)$", "match_all": True },
      { "key": "following_text"            , "operator": "regex_contains", "operand": '^(?:\t| |\\)|]|\\}|\\.|,|:|;|$)', "match_all": True }
    ]
(4)
    "context": [
      { "key": "setting.auto_match_enabled", "operator": "equal"             , "operand": True },
      { "key": "selection_empty"           , "operator": "equal"             , "operand": True, "match_all": True },
      { "key": "following_text"            , "operator": "regex_contains"    , "operand": '^(?:\t| |\\)|]|\\}|>|$)', "match_all": True },
      { "key": "preceding_text"            , "operator": "not_regex_contains", "operand": '["a-zA-Z0-9_]$', "match_all": True },
      { "key": "eol_selector"              , "operator": "not_equal"         , "operand": 'string.quoted.double - punctuation.definition.string.end', "match_all": True }
    ]
(5)
    "context": [
      { "key": "setting.auto_match_enabled" },
      { "key": "selector"                  , "operand": 'source.python - string.quoted.double' },
      { "key": "selection_empty"           , "match_all": True }
    ]
(6)
    "context": [
      { "key": "setting.auto_match_enabled" },
      { "key": "selector"                  , "operand": 'source.python - string.quoted.double' },
      { "key": "selection_empty"           , "match_all": True },
      { "key": "preceding_text"            , "operator": "regex_contains", "operand": '(?i:^|[^"\\w\\\\]|\\b[bfru]+)$', "match_all": True },
      { "key": "following_text"            , "operator": "regex_contains", "operand": '^(?:\t| |\\)|]|\\}|\\.|,|:|;|$)', "match_all": True }
    ]
0 Likes

#40

The report looks good. I could bike-shed but I would need to use it to make actual suggestions. How do you open that? Is that a kind of context-sensitive help?

0 Likes

#41

At the moment, it’s just a loose Command. I’ve attached it to a key binding for the moment for testing. Also, the extra ' and " key bindings in the report are there because I copy/pasted the original ones into my own override .sublime-keymap file, and the current command I’m running fetches info for just those 2 unmodified keys LIMITED to the current context.

At the moment, it’s a TextCommand with these arguments:

    def run(
            self            : sublime_plugin.ApplicationCommand,
            edit            : sublime.Edit,
            key_groups      : Optional[Iterable[data.KeyGroup]] = None,
            key_names       : Optional[Iterable[str]] = None,
            keypress_list   : Optional[Iterable[Iterable[str]]] = None,
            packages        : Optional[Iterable[str]] = None,
            limit_to_context: Optional[bool] = False,
            format          : ascii_table.Format = ascii_table.Format.OUTLINED,
            flags           : output.FlagBits = output.FlagBits.INCLUDE_UNBOUND_KEY_COMBINATIONS
            ):

and I’m running it with this key binding:

	{
		"keys": ["ctrl+alt+shift+f4"],
		"command": "key_binding_report",
		"args": {
			// class KeyGroup(IntEnum):
			//     """ Non-negative values index into ``key_name_groups``. """
			//     ALL            = -2  # Equivalent to specifying all groups >= 0.
			//     KEY_SEQUENCES  = -1  # Multiple-keypress sequences, e.g. ["ctrl+k", "ctrl+u"]

			//     LETTER_KEYS    =  0  # \
			//     NUMBER_KEYS    =  1  #  \
			//     F_KEYS         =  2  #   \__ These index into ``key_name_groups``.
			//     SYMBOL_KEYS    =  3  #   /
			//     NAMED_KEYS     =  4  #  /
			//     KEYPAD_KEYS    =  5  # /
			// "key_groups": [1],
			// "key_names": ["("],
			// "key_names": ["enter"],
			// "keypress_list": [["ctrl+p"], ["ctrl+shift+p"], ["ctrl+k", "ctrl+u"], ["ctrl+p"], ["ctrl+k", "ctrl+u"], ["alt+r"]],
			// "keypress_list": [["enter"]],
			// "keypress_list": [["alt+left"]],
			"keypress_list": [["\""], ["'"], ["`"]],
			// "packages": ["Default"],
			// "packages": ["User"],
			"limit_to_context": true,
			// class Format(IntEnum):
			//     """ Formats supported by AsciiTable """
			//     BARE             = 0
			//     OUTLINED         = 1
			//     RESTRUCTUREDTEXT = 2
			"format": 1,
			"flags": 255,
		},
	},

I left several lines commented so you can see the variety.

class FlagBits(IntFlag):
    # Output Flags
    INCLUDE_UNBOUND_KEY_COMBINATIONS = 0b00000001  #   1
    INCLUDE_UNTRANSLATED_CONTEXTS    = 0b00000010  #   2
    INCLUDE_ENGLISH_CONTEXTS         = 0b00000100  #   4
    ADD_PACKAGE_COLUMN               = 0b00001000  #   8
    ADD_FILE_COLUMN                  = 0b00010000  #  16
    ADD_COMMENTS_COLUMN              = 0b00100000  #  32

    # Utility Bits
    ANY_CONTEXT                      = 0b00000010 | 0b00000100
    NONE                             = 0b00000000  #   0
    ALL                              = 0b11111111  # 255
    ANY                              = 0b11111111  # 255

I’m overriding the flags variable for now for testing. All the parameters act as “additive” except for the packages parameter which is “limiting”. If no packages is passed, it loads up its input data from all Packages. The way to get EVERYTHING is pass in ALL in key groups and don’t pass in anything for packages. I have yet to put the Syntax limiting in as part of current context, but it should only take 5 minutes, and it happened in this test that Python was the only syntax to carry keypress overrides for ' and ".

It’s set up so that if you only pass 1 key combination in keypress_list that you will get a report that includes all bindings found for that key combination (the logic includes key sequences like ctrl+k, ctrl+u). And what gets passed in for keypress_list, just like .sublime-keymap files, can be [["ctrl+shift+left"]] as well as [["shift+ctrl+left"]] it will still produce the same results.

0 Likes

#42

Next installment: I separated the “command-as-a-function” representation into separate Command and Args columns, because I found it more readable.

This key binding (to execute the command):

	{
		"keys": ["ctrl+alt+shift+f4"],   // <== What I am using to test the command.
		"command": "key_binding_report",
		"args": {
			// class KeyGroup(IntEnum):
			//     """ Non-negative values index into ``key_name_groups``. """
			//     ALL            = -2  # Equivalent to specifying all groups >= 0.
			//     KEY_SEQUENCES  = -1  # Multiple-keypress sequences, e.g. ["ctrl+k", "ctrl+u"]

			//     LETTER_KEYS    =  0  # \
			//     NUMBER_KEYS    =  1  #  \
			//     F_KEYS         =  2  #   \__ These index into ``key_name_groups``.
			//     SYMBOL_KEYS    =  3  #   /
			//     NAMED_KEYS     =  4  #  /
			//     KEYPAD_KEYS    =  5  # /
			// "key_groups": [1],
			// "key_names": ["("],
			// "key_names": ["enter"],
			// "keypress_list": [["ctrl+p"], ["ctrl+shift+p"], ["ctrl+k", "ctrl+u"], ["ctrl+p"], ["ctrl+k", "ctrl+u"], ["alt+r"]],
			// "keypress_list": [["enter"]],
			// "keypress_list": [["alt+left"]],
			"keypress_list": [["\""], ["'"], ["`"]],
			// "packages": ["Default"],
			// "packages": ["User"],
			"limit_to_context": true,

			// class Format(IntEnum):
			//     """ Formats supported by AsciiTable """
			//     BARE             = 0
			//     OUTLINED         = 1
			//     RESTRUCTUREDTEXT = 2
			"format": 2,

			// class FlagBits(IntFlag):
			//     # Output Flags
			//     INCLUDE_UNBOUND_KEY_COMBINATIONS = 0b00000001  #   1
			//     INCLUDE_UNTRANSLATED_CONTEXTS    = 0b00000010  #   2
			//     INCLUDE_ENGLISH_CONTEXTS         = 0b00000100  #   4
			//     ADD_PACKAGE_COLUMN               = 0b00001000  #   8
			//     ADD_FILE_COLUMN                  = 0b00010000  #  16
			//     ADD_COMMENTS_COLUMN              = 0b00100000  #  32

			//     # Utility Bits
			//     ANY_CONTEXT                      = 0b00000010 | 0b00000100
			//     NONE                             = 0b00000000  #   0
			//     ALL                              = 0b11111111  # 255
			//     ANY                              = 0b11111111  # 255
			"flags": 31,
		},
	},

…produces this output (context is a .py file not inside a comment):


KeyBindingReport:  Specified Key-Bindings
=========================================

Report generated:  2026-04-29 19:37:15

Key:

  - S = Shift
  - C = Ctrl
  - A = Alt
  - (Footnote ref) prefixing command means context is shown in footnote.

+---+-+-+-+-----------------------+----------------------+---------+----------------------------------+
|Key|S|C|A| Command               | Args                 | Package | File                             |
+===+=+=+=+=======================+======================+=========+==================================+
| ' | | | | ([1]_) insert_snippet | {'contents': "'$0'"} | Default | Default (Windows).sublime-keymap |
+---+-+-+-+-----------------------+----------------------+---------+----------------------------------+
| ' | | | | ([2]_) insert         | {'characters': "'"}  | Python  | Default.sublime-keymap           |
+---+-+-+-+-----------------------+----------------------+---------+----------------------------------+
| ' | | | | ([3]_) insert_snippet | {'contents': "'$0'"} | Python  | Default.sublime-keymap           |
+---+-+-+-+-----------------------+----------------------+---------+----------------------------------+
| ' |x| | |                       |                      |         |                                  |
+---+-+-+-+-----------------------+----------------------+---------+----------------------------------+
| ' | |x| |                       |                      |         |                                  |
+---+-+-+-+-----------------------+----------------------+---------+----------------------------------+
| ' |x|x| |                       |                      |         |                                  |
+---+-+-+-+-----------------------+----------------------+---------+----------------------------------+
| ' | | |x|                       |                      |         |                                  |
+---+-+-+-+-----------------------+----------------------+---------+----------------------------------+
| ' |x| |x|                       |                      |         |                                  |
+---+-+-+-+-----------------------+----------------------+---------+----------------------------------+
| ' | |x|x|                       |                      |         |                                  |
+---+-+-+-+-----------------------+----------------------+---------+----------------------------------+
| ' |x|x|x|                       |                      |         |                                  |
+---+-+-+-+-----------------------+----------------------+---------+----------------------------------+
| " | | | | ([4]_) insert_snippet | {'contents': '"$0"'} | Default | Default (Windows).sublime-keymap |
+---+-+-+-+-----------------------+----------------------+---------+----------------------------------+
| " | | | | ([5]_) insert         | {'characters': '"'}  | Python  | Default.sublime-keymap           |
+---+-+-+-+-----------------------+----------------------+---------+----------------------------------+
| " | | | | ([6]_) insert_snippet | {'contents': '"$0"'} | Python  | Default.sublime-keymap           |
+---+-+-+-+-----------------------+----------------------+---------+----------------------------------+
| " |x| | |                       |                      |         |                                  |
+---+-+-+-+-----------------------+----------------------+---------+----------------------------------+
| " | |x| |                       |                      |         |                                  |
+---+-+-+-+-----------------------+----------------------+---------+----------------------------------+
| " |x|x| |                       |                      |         |                                  |
+---+-+-+-+-----------------------+----------------------+---------+----------------------------------+
| " | | |x|                       |                      |         |                                  |
+---+-+-+-+-----------------------+----------------------+---------+----------------------------------+
| " |x| |x|                       |                      |         |                                  |
+---+-+-+-+-----------------------+----------------------+---------+----------------------------------+
| " | |x|x|                       |                      |         |                                  |
+---+-+-+-+-----------------------+----------------------+---------+----------------------------------+
| " |x|x|x|                       |                      |         |                                  |
+---+-+-+-+-----------------------+----------------------+---------+----------------------------------+

.. [1]
    "context": [
      { "key": "setting.auto_match_enabled", "operator": "equal"             , "operand": True }
        English:  Description of ContextCondition,
      { "key": "selection_empty"           , "operator": "equal"             , "operand": True, "match_all": True }
        English:  Description of ContextCondition,
      { "key": "following_text"            , "operator": "regex_contains"    , "operand": '^(?:\t| |\\)|]|\\}|>|$)', "match_all": True }
        English:  Description of ContextCondition,
      { "key": "preceding_text"            , "operator": "not_regex_contains", "operand": "['a-zA-Z0-9_]$", "match_all": True }
        English:  Description of ContextCondition,
      { "key": "eol_selector"              , "operator": "not_equal"         , "operand": 'string.quoted.single - punctuation.definition.string.end', "match_all": True }
        English:  Description of ContextCondition
    ]
.. [2]
    "context": [
      { "key": "setting.auto_match_enabled" }
        English:  Description of ContextCondition,
      { "key": "selector"                  , "operand": 'source.python - string.quoted.single' }
        English:  Description of ContextCondition,
      { "key": "selection_empty"           , "match_all": True }
        English:  Description of ContextCondition
    ]
.. [3]
    "context": [
      { "key": "setting.auto_match_enabled" }
        English:  Description of ContextCondition,
      { "key": "selector"                  , "operand": 'source.python - string.quoted.single' }
        English:  Description of ContextCondition,
      { "key": "selection_empty"           , "match_all": True }
        English:  Description of ContextCondition,
      { "key": "preceding_text"            , "operator": "regex_contains", "operand": "(?i:^|[^'\\w\\\\]|\\b[bfru]+)$", "match_all": True }
        English:  Description of ContextCondition,
      { "key": "following_text"            , "operator": "regex_contains", "operand": '^(?:\t| |\\)|]|\\}|\\.|,|:|;|$)', "match_all": True }
        English:  Description of ContextCondition
    ]
.. [4]
    "context": [
      { "key": "setting.auto_match_enabled", "operator": "equal"             , "operand": True }
        English:  Description of ContextCondition,
      { "key": "selection_empty"           , "operator": "equal"             , "operand": True, "match_all": True }
        English:  Description of ContextCondition,
      { "key": "following_text"            , "operator": "regex_contains"    , "operand": '^(?:\t| |\\)|]|\\}|>|$)', "match_all": True }
        English:  Description of ContextCondition,
      { "key": "preceding_text"            , "operator": "not_regex_contains", "operand": '["a-zA-Z0-9_]$', "match_all": True }
        English:  Description of ContextCondition,
      { "key": "eol_selector"              , "operator": "not_equal"         , "operand": 'string.quoted.double - punctuation.definition.string.end', "match_all": True }
        English:  Description of ContextCondition
    ]
.. [5]
    "context": [
      { "key": "setting.auto_match_enabled" }
        English:  Description of ContextCondition,
      { "key": "selector"                  , "operand": 'source.python - string.quoted.double' }
        English:  Description of ContextCondition,
      { "key": "selection_empty"           , "match_all": True }
        English:  Description of ContextCondition
    ]
.. [6]
    "context": [
      { "key": "setting.auto_match_enabled" }
        English:  Description of ContextCondition,
      { "key": "selector"                  , "operand": 'source.python - string.quoted.double' }
        English:  Description of ContextCondition,
      { "key": "selection_empty"           , "match_all": True }
        English:  Description of ContextCondition,
      { "key": "preceding_text"            , "operator": "regex_contains", "operand": '(?i:^|[^"\\w\\\\]|\\b[bfru]+)$', "match_all": True }
        English:  Description of ContextCondition,
      { "key": "following_text"            , "operator": "regex_contains", "operand": '^(?:\t| |\\)|]|\\}|\\.|,|:|;|$)', "match_all": True }
        English:  Description of ContextCondition
    ]

If the context is in an .rst file in an “open area” (not in existing text) then it also produces results for the ` (back-quote) key since the reStructuredText Package contains key bindings for it.

0 Likes

#43

Hi, @herr.kaste!

I’m curious: what were you going to bike-shed about? I’m interested…

Kind regards,
Vic

0 Likes

#44

Minor things are:

  • Report generated … at EOF

  • Also the help text S = Shift …

  • Command without the footnote indicator, that can be a column at EOL.

  • Args: if you do it that way flip the quotes so one can copy/paste; iirc
    JSON is picky and keys must be in "".

  • Play with a custom syntax to get rid of some of the noisy characters. Likely
    you can have a table with less “special chars”.

  • If you really have help text (“English: Description of ContextCondition”) you can
    do that as hover popups, and/or if the cursor is on the word “selector”, press ?
    to toggle a phantom or popup with the description.

  • You have Package and File separate which has pros and cons; relative paths
    (relative to what?) can be shorter and also readable Python/Default.subl…

    Double-cicking the filename, or hover opens a popup with clickable link, or
    o when the cursor is in the filename, all of that opens the file at the correct
    position (line:col).

LoL

1 Like

#45

Can you help me better understand what this means? I’m not seeing a “…” at the end of the report.

What about the help text would you change?

Are you saying you’d prefer the footnote reference (indicating a context) be in its own column on the far right?

If I am understanding this correctly, you’d like to be able to copy/paste contents of the report back into a .sublime-keymap file. Correct?

Which do you consider noisy characters?

That was meant as a “placeholder” until I get the English translation implemented, just to show it was being seriously considered as an option. However, the option of a more compact display with a popup is an interesting idea!

Very good idea!!

0 Likes

#46

Move to EOF. Sorry for being short.

Yes

Yes, I think that’s useful. If you show it like that, it should be valid JSON.

This one we discussed elsewhere. You can have rst/ASCII tables like that, or just styled tables without the =+| etc chars, where the rows/columns/cells are still clearly separated by using colors/scopes/styles. This is like rendering in Sublime Text.

I think I showed examples/screenshots of that vs the more traditional OverrideAudit reports.

0 Likes

#47

Typical is still

but I had other screenshots IIRC as well.

EDIT, e.g.:

0 Likes

#48

Understood on all points now. Thank you!

Kind regards,
Vic

0 Likes

#49

The latest… Interestingly, I’m growing more and more impressed by the power of this thing… In testing I discovered I had inadvertently masked a built-in key binding with [Alt-A], which I just used to bind to a Plugin that generates an ASCII table in a floating window (yet another feature of my old editor which I just replicated). Now that I am aware of it, I can switch it to something else. (I left the report that made me aware of it below so you can see the 2 adjacent occurrences of the use of [Alt-A].)

2 things happened since we last spoke:

  • I surveyed a few people about how they like to use the modifier keys. One of them was a Mac user and this made me keenly aware of the Command key—the most-often-used modifier key on a Mac for him (also true in the OSX default keymap!). Additionally, he likes to use them in this order (of increasing significance for him, which matches the keyboard layout of these keys): Command, Option, Ctrl, and finally Shift.
  • I turned off Windows HotKeys (because I NEVER use my Windows key for anything!), and this freed up the Windows key as “wide-open territory” for use as a modifier key in ST!

Thus, there is a new modifier-key column.

Additionally, the column headings are either “W A C S” for Windows and Linux and “C O ^ S” for OSX platform. I would have used the character as column heading for both except that character is wider than the standard width in the default font used by ST (as is the ‘⌥’ character), and so throws off the alignment of the column headings. :slightly_frowning_face: So I settled for ‘W’ and ‘C’, which preserve the alignment. I did, however, use both in the table key, which now resides just below the table and before any footnotes. The various (all 8) modifier key names are all now correctly mapped into these 4 columns for all 3 platforms.

And FYI, the feature of an English description of the individual context conditions is meant to be an option for the user: either raw context syntax (now JSON compatible), or English, or both together, in which case the English is indented under each JSON condition.


KeyBindingReport:  Specified Key-Bindings
=========================================

Report generated:  2026-05-04 14:02:09


Key  W  A  C  S  Command               Args             Context  Source
 a
 a            x
 a         x     select_all                                      Default/Default (Windows).sublime-keymap
 a         x  x  expand_selection      {"to": "smart"}           Default/Default (Windows).sublime-keymap
 a         x  x  expand_selection      {"to": "tag"}      (1)    Default/Default (Windows).sublime-keymap
 a      x        toggle_preserve_case                     (2)    Default/Default (Windows).sublime-keymap
 a      x        vics_ascii_table                                User/Default (Windows).sublime-keymap
 a      x     x
 a      x  x
 a      x  x  x
 a   x
 a   x        x
 a   x     x
 a   x     x  x
 a   x  x
 a   x  x     x
 a   x  x  x
 a   x  x  x  x

Key:
  W = ⌘ Windows
  A = Alt
  C = Ctrl
  S = Shift

(1):
    "context": [
      { "key": "selector", "operator": "equal", "operand": "(text.html, text.xml) - source", "match_all": true }
    ]
(2):
    "context": [
      { "key": "panel_type"     , "operand": "find" },
      { "key": "panel_has_focus" }
    ]

On the OSX platform, the report for the ‘a’ key looks like this:


KeyBindingReport:  Specified Key-Bindings
=========================================

Report generated:  2026-05-04 14:10:54


Key  C  O  ^  S  Command               Args             Context  Source
 a
 a            x
 a         x
 a         x  x
 a      x
 a      x     x
 a      x  x
 a      x  x  x
 a   x           select_all                                      Default/Default (OSX).sublime-keymap
 a   x        x  expand_selection      {"to": "smart"}           Default/Default (OSX).sublime-keymap
 a   x        x  expand_selection      {"to": "tag"}      (1)    Default/Default (OSX).sublime-keymap
 a   x     x
 a   x     x  x
 a   x  x        toggle_preserve_case                     (2)    Default/Default (OSX).sublime-keymap
 a   x  x     x
 a   x  x  x
 a   x  x  x  x

Key:
  C = ⌘ Command
  O = ⌥ Option
  ^ = Ctrl
  S = Shift

(1):
    "context": [
      { "key": "selector", "operator": "equal", "operand": "(text.html, text.xml) - source", "match_all": true }
    ]
(2):
    "context": [
      { "key": "panel_type"     , "operand": "find" },
      { "key": "panel_has_focus" }
    ]

Kind regards,
Vic

Edit:

Greg ( @gbird ), I thought I would tag you here so you could see why I was asking about modifier keys a week ago.

0 Likes

#50

Getting close…

flags = (
          FlagBits.INCLUDE_UNBOUND_KEY_COMBINATIONS
        | FlagBits.INCLUDE_UNTRANSLATED_CONTEXTS
        | FlagBits.ADD_SOURCE_COLUMN
        )

args = {
        "key_groups": [KeyGroup.KEY_SEQUENCES],
        "key_names" : ["k"],
        "fmt"       : Format.BARE
        "flags"     : flags
        }
view.run_command("key_binding_report", args)

Yields:


KeyBindingReport:  Specified Key-Bindings
*****************************************

Report generated:  2026-05-06 20:07:12



Single-Keypress Table
=====================

Key  W  A  C  S  Command                    Args                                                          Context  Source                                                 
 k                                                                                                                                                                        
 k            x                                                                                                                                                           
 k         x                                                                                                                                                              
 k         x  x  run_macro_file             {"file": "res://Packages/Default/Delete Line.sublime-macro"}           Default/Default (Windows).sublime-keymap               
 k      x                                                                                                                                                                 
 k      x     x                                                                                                                                                           
 k      x  x     literal                                                                                    (1)    sublime-rst-completion/Default (Windows).sublime-keymap
 k      x  x     vics_rst_encapsulate_role  {"role_name": "kbd"}                                            (2)    User/Default (Windows).sublime-keymap                  
 k      x  x  x                                                                                                                                                           
 k   x                                                                                                                                                                    
 k   x        x                                                                                                                                                           
 k   x     x                                                                                                                                                              
 k   x     x  x                                                                                                                                                           
 k   x  x                                                                                                                                                                 
 k   x  x     x                                                                                                                                                           
 k   x  x  x                                                                                                                                                              
 k   x  x  x  x                                                                                                                                                           

Key:
  W = ⌘ Windows
  A = Alt
  C = Ctrl
  S = Shift

(1):
    "context": [
      { "key": "selector", "operator": "equal", "operand": "text.restructuredtext" }
    ]
(2):
    "context": [
      { "key": "selector"       , "operand": "text.restructuredtext | source.python comment | source.python comment.block.documentation.python" },
      { "key": "selection_empty", "operand": false, "match_all": true }
    ]



Multi-Keypress Tables
=====================


Ctrl-J
------

  Key     W  A  C  S  Command            Args  Context  Source                                  
   j            x     primary_j_changed                 Default/Default (Windows).sublime-keymap
   up           x     unselect_others                   Default/Default (Windows).sublime-keymap
  left          x     unselect_to_left                  Default/Default (Windows).sublime-keymap
  left          x  x  select_to_left                    Default/Default (Windows).sublime-keymap
 right          x     unselect_to_right                 Default/Default (Windows).sublime-keymap
 right          x  x  select_to_right                   Default/Default (Windows).sublime-keymap
 pageup         x     focus_to_left                     Default/Default (Windows).sublime-keymap
pagedown        x     focus_to_right                    Default/Default (Windows).sublime-keymap

Key:
  W = ⌘ Windows
  A = Alt
  C = Ctrl
  S = Shift


Ctrl-K
------

   Key     W  A  C  S  Command                      Args                                                                 Context  Source                                  
    0            x     unfold_all                                                                                                 Default/Default (Windows).sublime-keymap
    1            x     fold_by_level                {"level": 1}                                                                  Default/Default (Windows).sublime-keymap
    2            x     fold_by_level                {"level": 2}                                                                  Default/Default (Windows).sublime-keymap
    3            x     fold_by_level                {"level": 3}                                                                  Default/Default (Windows).sublime-keymap
    4            x     fold_by_level                {"level": 4}                                                                  Default/Default (Windows).sublime-keymap
    5            x     fold_by_level                {"level": 5}                                                                  Default/Default (Windows).sublime-keymap
    6            x     fold_by_level                {"level": 6}                                                                  Default/Default (Windows).sublime-keymap
    7            x     fold_by_level                {"level": 7}                                                                  Default/Default (Windows).sublime-keymap
    8            x     fold_by_level                {"level": 8}                                                                  Default/Default (Windows).sublime-keymap
    9            x     fold_by_level                {"level": 9}                                                                  Default/Default (Windows).sublime-keymap
    a            x     select_to_mark                                                                                             Default/Default (Windows).sublime-keymap
    a            x     vics_open_sublime_api_files                                                                                User/Default (Windows).sublime-keymap   
    b            x     toggle_side_bar                                                                                            Default/Default (Windows).sublime-keymap
    c            x     show_at_center                                                                                             Default/Default (Windows).sublime-keymap
    d            x     find_under_expand_skip                                                                                     Default/Default (Windows).sublime-keymap
    g            x     clear_bookmarks              {"name": "mark"}                                                              Default/Default (Windows).sublime-keymap
    j            x     unfold_all                                                                                                 Default/Default (Windows).sublime-keymap
    k            x     run_macro_file               {"file": "res://Packages/Default/Delete to Hard EOL.sublime-macro"}           Default/Default (Windows).sublime-keymap
    l            x     lower_case                                                                                                 Default/Default (Windows).sublime-keymap
    s            x     vics_split_view_vertically                                                                                 User/Default (Windows).sublime-keymap   
    t            x     fold_tag_attributes                                                                                        Default/Default (Windows).sublime-keymap
    u            x     upper_case                                                                                                 Default/Default (Windows).sublime-keymap
    v            x     paste_from_history                                                                                         Default/Default (Windows).sublime-keymap
    w            x     delete_to_mark                                                                                             Default/Default (Windows).sublime-keymap
    w            x     vics_toggle_draw_whitespace                                                                                User/Default (Windows).sublime-keymap   
    x            x     swap_with_mark                                                                                             Default/Default (Windows).sublime-keymap
    y            x     yank                                                                                                       Default/Default (Windows).sublime-keymap
    z            x     revert_hunk                                                                                                Default/Default (Windows).sublime-keymap
    z            x  x  revert_modification                                                                                        Default/Default (Windows).sublime-keymap
    /            x     toggle_inline_diff                                                                                         Default/Default (Windows).sublime-keymap
    ;            x     toggle_inline_diff           {"prefer_hide": true}                                                         Default/Default (Windows).sublime-keymap
    ]            x     reindent                     {"single_line": true}                                                         Default/Default (Windows).sublime-keymap
   up            x     new_pane                                                                                                   Default/Default (Windows).sublime-keymap
   up            x  x  new_pane                     {"move": false}                                                               Default/Default (Windows).sublime-keymap
  down           x     close_pane                                                                                                 Default/Default (Windows).sublime-keymap
  left           x     focus_neighboring_group      {"forward": false}                                                            Default/Default (Windows).sublime-keymap
  left           x  x  move_to_neighboring_group    {"forward": false}                                                            Default/Default (Windows).sublime-keymap
  right          x     focus_neighboring_group                                                                                    Default/Default (Windows).sublime-keymap
  right          x  x  move_to_neighboring_group                                                                                  Default/Default (Windows).sublime-keymap
backspace        x     run_macro_file               {"file": "res://Packages/Default/Delete to Hard BOL.sublime-macro"}           Default/Default (Windows).sublime-keymap
  space          x     set_mark                                                                                                   Default/Default (Windows).sublime-keymap

Key:
  W = ⌘ Windows
  A = Alt
  C = Ctrl
  S = Shift


Ctrl-T
------

 Key   W  A  C  S  Command            Args  Context  Source                                                 
  r                flowtable                  (3)    sublime-rst-completion/Default (Windows).sublime-keymap
  s                simpletable                (4)    sublime-rst-completion/Default (Windows).sublime-keymap
 up                merge_cells_up             (5)    sublime-rst-completion/Default (Windows).sublime-keymap
down               merge_cells_down           (6)    sublime-rst-completion/Default (Windows).sublime-keymap
left               merge_cells_left           (7)    sublime-rst-completion/Default (Windows).sublime-keymap
right              merge_cells_right          (8)    sublime-rst-completion/Default (Windows).sublime-keymap
enter              table                      (9)    sublime-rst-completion/Default (Windows).sublime-keymap

Key:
  W = ⌘ Windows
  A = Alt
  C = Ctrl
  S = Shift

(3):
    "context": [
      { "key": "selector", "operator": "equal", "operand": "text.restructuredtext" }
    ]
(4):
    "context": [
      { "key": "selector", "operator": "equal", "operand": "text.restructuredtext" }
    ]
(5):
    "context": [
      { "key": "selector"      , "operator": "equal"         , "operand": "text.restructuredtext" },
      { "key": "preceding_text", "operator": "regex_contains", "operand": "^\\s*\\|*" }
    ]
(6):
    "context": [
      { "key": "selector"      , "operator": "equal"         , "operand": "text.restructuredtext" },
      { "key": "preceding_text", "operator": "regex_contains", "operand": "^\\s*\\|*" }
    ]
(7):
    "context": [
      { "key": "selector"      , "operator": "equal"         , "operand": "text.restructuredtext" },
      { "key": "preceding_text", "operator": "regex_contains", "operand": "^\\s*\\|*" }
    ]
(8):
    "context": [
      { "key": "selector"      , "operator": "equal"         , "operand": "text.restructuredtext" },
      { "key": "preceding_text", "operator": "regex_contains", "operand": "^\\s*\\|*" }
    ]
(9):
    "context": [
      { "key": "selector", "operator": "equal", "operand": "text.restructuredtext" }
    ]
0 Likes

Anyone else still sticking with Sublime in 2026?
#51

Hi, @herr.kaste ! It’s nearing maturity…

Currently I have one command generating 24 files (one table each) that get included (with an reST .. include:: directive) into the 3 child web pages of this page.

It’s nearly turn-key: I press a key, it runs 1 command (using flag ALL_PLATFORMS ), so it runs the command internally 3 times, once for each platform, each generating 8 files (one for each key group), to a user-configurable path for each platform.

I run the build for that docs website, and push the updated files to the web server. The arguments passed are:

  • key_groups = KeyGroups.ALL
  • limit_to_packages = ["Default"]
  • format = ascii_table.Format.RESTRUCTUREDTEXT
  • flags =
    • output.FlagBits.INCLUDE_UNBOUND_KEY_COMBINATIONS
    • output.FlagBits.INCLUDE_UNTRANSLATED_CONTEXTS
    • output.FlagBits.ADD_SOURCE_COLUMN
    • output.FlagBits.SEPARATE_TABLES_BY_KEY_GROUPS
    • output.FlagBits.OUTPUT_TO_FILES
    • output.FlagBits.ALL_PLATFORMS

An optional TABLE_KEY_AFTER_TABLE flag moves the table key below the table as you requested above.

Another optional flag: INCLUDE_WINDOWS_KEY can be used with Linux and Windows platforms to add a 4th key column for the Windows key. (That column is always added for OSX because the default keymap for OSX uses all 4 modifier keys.)

With this Package I found (and reported) a bug in both the Python and Default Package key bindings, and found and fixed 2 bugs in my own key bindings where I was unintentionally overriding 2 keypresses I had not been previously aware of! The Python package is already fixed (thank you @deathaxe) and the Default package is being reviewed by bschaaf.

0 Likes