Actions and Bindings
Actions are named operations. Bindings connect actions to keys. Both can be defined in config.toml or config.lua — use whichever fits your workflow.
Defining an action
Section titled “Defining an action”In config.toml
Section titled “In config.toml”Use [[actions]] with an inline Lua snippet:
[[actions]]name = "copy-change-id"desc = "copy change id to clipboard"lua = '''local id = context.change_id()if id then copy_to_clipboard(id) flash("Copied: " .. id)end'''In config.lua
Section titled “In config.lua”Pass a function directly to config.action:
function setup(config) config.action("copy-change-id", function() local id = context.change_id() if id then copy_to_clipboard(id) flash("Copied: " .. id) end end, { desc = "copy change id to clipboard" })endBinding an action to a key
Section titled “Binding an action to a key”In config.toml
Section titled “In config.toml”[[bindings]]action = "copy-change-id"key = "Y"scope = "revisions"desc = "copy change id"In config.lua
Section titled “In config.lua”Either pass binding options directly to config.action:
config.action("copy-change-id", fn, { key = "Y", scope = "revisions", desc = "copy change id",})Or bind separately with config.bind:
config.bind({ action = "copy-change-id", key = "Y", scope = "revisions", desc = "copy change id",})Binding fields
Section titled “Binding fields”| Field | Required | Notes |
|---|---|---|
action | yes | Action name or built-in action ID |
scope | yes | Where the binding is active |
key or seq | yes | Set exactly one |
desc | no | Label shown in the help/status bar |
args | no | Arguments for built-in actions |
key accepts a single key or a list of alternatives:
key = "r"key = ["up", "k"]seq defines an ordered key sequence (chord):
[[bindings]]action = "ui.open_revset"seq = ["g", "r"]scope = "revisions"desc = "open revset"Rebinding built-in actions
Section titled “Rebinding built-in actions”You can bind any built-in action by its action ID:
[[bindings]]action = "ui.open_revset"key = "L"scope = "revisions"desc = "revset"All built-in action IDs and their default bindings are defined in internal/config/default/bindings.toml in the source repository.
Overriding built-in actions
Section titled “Overriding built-in actions”You can replace a built-in action’s behavior entirely by defining an action with the same name as a built-in. Use jjui.builtin.* to call the original implementation from your override.
In config.toml
Section titled “In config.toml”[[actions]]name = "revisions.move_down"lua = '''jjui.builtin.revisions.move_down()flash("Moved down to: " .. context.change_id())'''In config.lua
Section titled “In config.lua”function setup(config) config.action("revisions.move_down", function() jjui.builtin.revisions.move_down() flash("Moved down to: " .. context.change_id()) end)endBoth examples override move_down to show a flash message with the change ID after each move, while still performing the original navigation via jjui.builtin.revisions.move_down().
You can use this pattern with any built-in action — for example, making toggle_select automatically advance the cursor:
config.action("revisions.toggle_select", function() jjui.builtin.revisions.toggle_select() jjui.builtin.revisions.move_down()end)Migration notes
Section titled “Migration notes”Legacy [custom_commands] and [leader] sections are no longer supported. See Migrating to v0.10.