Skip to content

Expose full config to Lua setup and add runtime context (repo + terminal)#553

Merged
idursun merged 4 commits intomainfrom
feat/use-config-object-in-lua
Feb 25, 2026
Merged

Expose full config to Lua setup and add runtime context (repo + terminal)#553
idursun merged 4 commits intomainfrom
feat/use-config-object-in-lua

Conversation

@idursun
Copy link
Copy Markdown
Owner

@idursun idursun commented Feb 24, 2026

Current Lua setup function is called with a config object it is actually a table with two methods defined action and bind. I thought it would be nice if we pass the actual config object so that the users can customise it even further. Imagine someone creating jjui-sensible plugin with selection of preview commands that make more sense.

This PR converts the Config loaded from TOML into Lua table and passes it to the setup function. setup function can read and modify these values when it runs. Once Lua setup is complete, then the Lua config table is converted back to config instance and that's what is used in the app after that point.

This PR also adds a couple of runtime fields to the config object:

  • config.repo the repository location so that config.lua can define different actions based on the repository.
  • config.terminal.dark_mode true if the terminal is in dark mode
  • config.terminal.fg default foreground colour of the terminal
  • config.terminal.bg default background of the terminal.

While adding those, I also took the opportunity to get rid of the merge.go file and updated the action/binding resolution:

  • duplicate action names are allowed (last definition wins)
  • overlay actions/bindings are appended instead of merged by replacement logic
  • dispatcher/help key resolution now prefers later bindings in the same scope
  • merge.go is removed

conversion.go is AI generated. I cannot be asked to write lua conversion code.

Usage Examples

Here are a couple of usage examples:

You can change the default preview commands:

function setup(config) 
  config.preview.evolog_command = { "evolog", "--color", "always", "-r", "$commit_id", "-p", "-n", "1" }
end

Loading different themes based on repository name:

local dynamic_theme_plugin = require("plugins.dynamic_theme")

function setup(config)
  if config.repo:match("jjui$") then
    dynamic_theme_plugin.setup("#0000AA", config)
  else
    dynamic_theme_plugin.setup("#AA0000", config)
  end
end

What's dynamic_theme?? Well, you can actually create dynamic themes using Lua functions, here's an example which uses a single primary colour and every other colour derived by lightening or darkening that colour.

local function clamp(n, lo, hi)
  if n < lo then return lo end
  if n > hi then return hi end
  return n
end

local function parse_hex(color)
  if type(color) ~= "string" then
    return nil
  end

  local hex = color:gsub("^#", "")
  if #hex ~= 6 or not hex:match("^[0-9a-fA-F]+$") then
    return nil
  end

  local r = tonumber(hex:sub(1, 2), 16)
  local g = tonumber(hex:sub(3, 4), 16)
  local b = tonumber(hex:sub(5, 6), 16)
  return r, g, b
end

local function to_hex(r, g, b)
  return string.format("#%02X%02X%02X", clamp(math.floor(r + 0.5), 0, 255), clamp(math.floor(g + 0.5), 0, 255),
    clamp(math.floor(b + 0.5), 0, 255))
end

local function lighten(color, pct)
  local r, g, b = parse_hex(color)
  if not r then
    return color
  end
  pct = clamp(tonumber(pct) or 0, 0, 100)
  local t = pct / 100.0
  return to_hex(
    r + (255 - r) * t,
    g + (255 - g) * t,
    b + (255 - b) * t
  )
end

local function darken(color, pct)
  local r, g, b = parse_hex(color)
  if not r then
    return color
  end
  pct = clamp(tonumber(pct) or 0, 0, 100)
  local t = 1.0 - (pct / 100.0)
  return to_hex(r * t, g * t, b * t)
end

local M = {}

function M.setup(primary, config)
  -- Single base accent; all variants are derived from this.
  local accent_a = primary
  local accent_b = lighten(primary, 18)
  local accent_c = darken(primary, 14)
  local accent_d = lighten(primary, 34)

  -- Brighter text + darker highlights.
  local a_very_dark = lighten(accent_a, 78)
  local a_dark = lighten(accent_a, 58)
  local a_mid = lighten(accent_a, 40)
  local a_soft = darken(accent_a, 44)
  local a_soft2 = darken(accent_a, 56)
  local a_soft3 = darken(accent_a, 68)

  local b_dark = lighten(accent_b, 62)
  local b_mid = lighten(accent_b, 48)
  local b_soft = darken(accent_b, 24)
  local b_soft2 = darken(accent_b, 36)

  local c_dark = lighten(accent_c, 55)
  local c_mid = lighten(accent_c, 40)
  local c_soft = darken(accent_c, 30)

  local d_dark = lighten(accent_d, 52)
  local d_mid = lighten(accent_d, 40)
  local d_soft = darken(accent_d, 24)

  config.ui = config.ui or {}
  config.ui.colors = config.ui.colors or {}

  -- global primitives
  config.ui.colors.title = { fg = accent_a, bold = true }
  config.ui.colors.dimmed = { fg = a_mid }
  config.ui.colors.shortcut = { fg = b_dark, bold = true }
  config.ui.colors.matched = { fg = d_mid, bold = true }
  config.ui.colors.selected = { fg = a_very_dark, bg = a_soft3, bold = true }
  config.ui.colors.success = { fg = c_dark, bold = true }
  config.ui.colors.error = { fg = d_dark, bold = true }
  config.ui.colors.source_marker = { fg = a_very_dark, bg = c_mid, bold = true }
  config.ui.colors.target_marker = { fg = a_very_dark, bg = accent_b, bold = true }

  -- status + command line surfaces
  config.ui.colors["status text"] = { fg = a_dark }
  config.ui.colors["status dimmed"] = { fg = a_mid }
  config.ui.colors["status shortcut"] = { fg = b_mid, bold = true }
  config.ui.colors["status success"] = { fg = c_dark, bold = true }
  config.ui.colors["status error"] = { fg = d_dark, bold = true }
  config.ui.colors["status title"] = { fg = a_very_dark, bg = c_soft, bold = true }
  config.ui.colors["input title"] = { fg = c_dark, bold = true }
  config.ui.colors["input text"] = { fg = a_dark }
  config.ui.colors["password title"] = { fg = d_mid, bold = true }

  -- chooser / picker / menu overlays
  config.ui.colors["choose title"] = { fg = c_dark, bold = true }
  config.ui.colors["choose text"] = { fg = a_dark }
  config.ui.colors["choose selected"] = { fg = a_very_dark, bg = a_soft3, bold = true }
  config.ui.colors["menu title"] = { fg = a_very_dark, bg = b_soft2, bold = true }
  config.ui.colors["menu subtitle"] = { fg = a_mid, bold = true }
  config.ui.colors["menu text"] = { fg = a_dark }
  config.ui.colors["menu dimmed"] = { fg = a_mid }
  config.ui.colors["menu shortcut"] = { fg = b_mid, bold = true }
  config.ui.colors["menu matched"] = { fg = d_dark, bold = true }
  config.ui.colors["menu selected"] = { fg = a_very_dark, bg = a_soft3, bold = true }
  config.ui.colors["menu border"] = { fg = a_soft }

  config.ui.colors["bookmarks menu title"] = { fg = a_very_dark, bg = b_soft, bold = true }
  config.ui.colors["bookmarks menu text"] = { fg = a_dark }
  config.ui.colors["bookmarks menu dimmed"] = { fg = a_mid }
  config.ui.colors["bookmarks menu shortcut"] = { fg = b_mid, bold = true }
  config.ui.colors["bookmarks menu matched"] = { fg = d_dark, bold = true }
  config.ui.colors["bookmarks menu selected"] = { fg = a_very_dark, bg = a_soft3, bold = true }
  config.ui.colors["bookmarks menu border"] = { fg = a_soft }

  config.ui.colors["git menu title"] = { fg = a_very_dark, bg = b_soft, bold = true }
  config.ui.colors["git menu text"] = { fg = a_dark }
  config.ui.colors["git menu dimmed"] = { fg = a_mid }
  config.ui.colors["git menu shortcut"] = { fg = b_mid, bold = true }
  config.ui.colors["git menu matched"] = { fg = d_dark, bold = true }
  config.ui.colors["git menu selected"] = { fg = a_very_dark, bg = a_soft3, bold = true }
  config.ui.colors["git menu border"] = { fg = a_soft }

  config.ui.colors["picker text"] = { fg = a_dark }
  config.ui.colors["picker dimmed"] = { fg = a_mid }
  config.ui.colors["picker matched"] = { fg = d_dark, bold = true }
  config.ui.colors["picker bookmark"] = { fg = c_dark, bold = true }
  config.ui.colors["picker selected"] = { fg = a_very_dark, bg = a_soft3, bold = true }

  -- revisions + oplog
  config.ui.colors["revisions text"] = { fg = a_dark }
  config.ui.colors["revisions dimmed"] = { fg = a_mid }
  config.ui.colors["revisions selected"] = { fg = a_very_dark, bg = a_soft3, bold = true }
  config.ui.colors["revisions matched"] = { fg = d_dark, underline = true, bold = true }
  config.ui.colors["oplog text"] = { fg = a_dark }
  config.ui.colors["oplog selected"] = { fg = a_very_dark, bg = a_soft3, bold = true }
  config.ui.colors["oplog matched"] = { fg = d_dark, underline = true, bold = true }

  -- revset completion
  config.ui.colors["revset title"] = { fg = c_dark, bold = true }
  config.ui.colors["revset text"] = { fg = a_dark, bold = true }
  config.ui.colors["revset completion"] = { bg = a_soft3 }
  config.ui.colors["revset completion text"] = { fg = a_dark }
  config.ui.colors["revset completion matched"] = { fg = d_dark, bold = true }
  config.ui.colors["revset completion selected"] = { fg = a_very_dark, bg = b_soft, bold = true }
  config.ui.colors["revset completion dimmed"] = { fg = a_mid }
  config.ui.colors["revset completion background"] = { bg = a_soft3 }

  -- confirmation surfaces
  config.ui.colors["confirmation text"] = { fg = a_dark, bold = true }
  config.ui.colors["confirmation selected"] = { fg = a_very_dark, bg = c_soft, bold = true }
  config.ui.colors["confirmation dimmed"] = { fg = a_mid }

  -- operation-specific markers / ids
  config.ui.colors["abandon source_marker"] = { fg = a_very_dark, bg = c_mid, bold = true }

  config.ui.colors["duplicate change_id"] = { fg = d_dark, bold = true }
  config.ui.colors["duplicate dimmed"] = { fg = a_mid }
  config.ui.colors["duplicate source_marker"] = { fg = a_very_dark, bg = c_mid, bold = true }
  config.ui.colors["duplicate target_marker"] = { fg = a_very_dark, bg = accent_b, bold = true }

  config.ui.colors["evolog change_id"] = { fg = d_dark, bold = true }
  config.ui.colors["evolog commit_id"] = { fg = b_mid, bold = true }
  config.ui.colors["evolog dimmed"] = { fg = a_mid }
  config.ui.colors["evolog text"] = { fg = a_dark }
  config.ui.colors["evolog selected"] = { fg = a_very_dark, bg = a_soft3, bold = true }
  config.ui.colors["evolog target_marker"] = { fg = a_very_dark, bg = accent_b, bold = true }

  config.ui.colors["rebase change_id"] = { fg = d_dark, bold = true }
  config.ui.colors["rebase shortcut"] = { fg = b_mid, bold = true }
  config.ui.colors["rebase dimmed"] = { fg = a_mid }
  config.ui.colors["rebase source_marker"] = { fg = a_very_dark, bg = c_mid, bold = true }
  config.ui.colors["rebase target_marker"] = { fg = a_very_dark, bg = accent_b, bold = true }

  config.ui.colors["revert change_id"] = { fg = d_dark, bold = true }
  config.ui.colors["revert shortcut"] = { fg = b_mid, bold = true }
  config.ui.colors["revert dimmed"] = { fg = a_mid }
  config.ui.colors["revert source_marker"] = { fg = a_very_dark, bg = c_mid, bold = true }
  config.ui.colors["revert target_marker"] = { fg = a_very_dark, bg = accent_b, bold = true }

  config.ui.colors["set_parents dimmed"] = { fg = a_mid }
  config.ui.colors["set_parents source_marker"] = { fg = a_very_dark, bg = c_mid, bold = true }
  config.ui.colors["set_parents target_marker"] = { fg = a_very_dark, bg = accent_b, bold = true }

  config.ui.colors["squash dimmed"] = { fg = a_mid }
  config.ui.colors["squash source_marker"] = { fg = a_very_dark, bg = c_mid, bold = true }
  config.ui.colors["squash target_marker"] = { fg = a_very_dark, bg = accent_b, bold = true }

  -- revision details + diff aliases
  config.ui.colors["revisions details text"] = { fg = a_dark }
  config.ui.colors["revisions details dimmed"] = { fg = a_mid }
  config.ui.colors["revisions details selected"] = { bg = a_soft2 }
  config.ui.colors["revisions details target_marker"] = { fg = a_very_dark, bg = b_soft, bold = true }
  config.ui.colors["revisions details added"] = { fg = c_dark }
  config.ui.colors["revisions details modified"] = { fg = b_mid }
  config.ui.colors["revisions details deleted"] = { fg = d_dark }
  config.ui.colors["revisions details renamed"] = { fg = lighten(accent_a, 14), italic = true }
  config.ui.colors["revisions details copied"] = { fg = lighten(accent_b, 8), italic = true }
  config.ui.colors["revisions details conflict"] = { fg = darken(accent_d, 8), bg = d_soft, bold = true }

  config.ui.colors["diff added"] = { fg = c_dark }
  config.ui.colors["diff modified"] = { fg = b_mid }
  config.ui.colors["diff removed"] = { fg = d_dark }
  config.ui.colors["diff renamed"] = { fg = lighten(accent_a, 14), italic = true }
  config.ui.colors["diff copied"] = { fg = lighten(accent_b, 8), italic = true }

  config.ui.colors.added = { fg = c_dark }
  config.ui.colors.modified = { fg = b_mid }
  config.ui.colors.deleted = { fg = d_dark }
  config.ui.colors.renamed = { fg = lighten(accent_a, 14), italic = true }
  config.ui.colors.copied = { fg = lighten(accent_b, 8), italic = true }
end

return M

This ensures the user configuration is always overwrites the default configuration
terminal bg/fg and repo location can be helpful to customise jjui look & feel  and custom actions based on where it is running at.
@idursun idursun marked this pull request as ready for review February 24, 2026 20:56
@baggiiiie
Copy link
Copy Markdown
Collaborator

i was a bit lost at first reading this PR, until i saw

Loading different themes based on repository name

okay i see, you're doing your wizardry again 🚀

@idursun
Copy link
Copy Markdown
Owner Author

idursun commented Feb 25, 2026

Yes, sorry the PR description is not the best. Idea is simple though, config object is the actual config from the TOML file + some runtime information to customise the configuration even further.

I am going to merge this and follow it up if I notice any regressions.

@idursun idursun merged commit 3e6ae51 into main Feb 25, 2026
4 checks passed
@idursun idursun deleted the feat/use-config-object-in-lua branch February 25, 2026 20:52
@vic
Copy link
Copy Markdown
Collaborator

vic commented Feb 25, 2026

This is awesome, that means themes are not static anymore, but computed at first load? Maybe in the future we wont need tinted-jjui to generate all files, but just use the color scheme and compute theme configuration by loading a lua file with them.

I also always wanted to have color-per working directory, eg, use fire-theme when working on main branch of some project, just like I do for color-coding connection to production dbs.

@idursun
Copy link
Copy Markdown
Owner Author

idursun commented Feb 26, 2026

Maybe in the future we wont need tinted-jjui to generate all files

Potentially yes. Having different theme per working directory is possible now too. These are great use cases.

However, all I wanted was to be able to set the selected colour to be a slightly lighter version of the terminal's default background colour :) This is pretty much how it all started.

tmeijn pushed a commit to tmeijn/dotfiles that referenced this pull request Mar 11, 2026
This MR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [idursun/jjui](https://github.com/idursun/jjui) | minor | `v0.9.12` → `v0.10.0` |

MR created with the help of [el-capitano/tools/renovate-bot](https://gitlab.com/el-capitano/tools/renovate-bot).

**Proposed changes to behavior should be submitted there as MRs.**

---

### Release Notes

<details>
<summary>idursun/jjui (idursun/jjui)</summary>

### [`v0.10.0`](https://github.com/idursun/jjui/releases/tag/v0.10.0)

[Compare Source](idursun/jjui@v0.9.12...v0.10.0)

Wow, a major release after a very long time. As promised, `v0.10` is ready, and it comes with **breaking changes**.

First, thank you to everybody who contributed code, bug reports, ideas, and testing for this release. In particular, thanks to [@&#8203;baggiiiie](https://github.com/baggiiiie) for various features and fixes, [@&#8203;nickchomey](https://github.com/nickchomey) for contributions and continuous feedback, and [@&#8203;vic](https://github.com/vic) for updating the documentation website. Thanks as well to everyone else for various code contributions, reporting issues, and verifying fixes.

We changed a lot in `v0.10`, but the biggest shift is that we finally got rid of some **legacy configuration** and moved to a unified **actions + bindings** model. Old concepts like `[custom_commands]` and `[leader]` are now replaced by a more consistent system built around **actions**, **bindings**, and first-class support for leader-style key sequences.

This release also introduces `config.lua`, which makes it much easier to customise and extend `jjui` with **real scripting** instead of only static configuration. Between `config.toml`, `config.lua`, Lua actions, and bindings, much more of the UI can now be customised in one consistent way.

The documentation has been updated with [**migration notes**](https://idursun.github.io/jjui/migrating/v0_10/) and examples such as the [**Lua Cookbook**](https://idursun.github.io/jjui/lua-cookbook/).

From my testing it looks ready, but I am sure more rough edges will show up once more people start using it, so please keep reporting issues as you find them.

#### ⚠️ Breaking Changes

`v0.10` replaces the **legacy keybinding and customisation model** with the new **actions + bindings** system.

- `[keys]` configuration is no longer used.
- `[custom_commands]` is replaced by `[[actions]]` and `[[bindings]]`.
- `[leader]` sequences are replaced by sequence bindings via `seq`.

If you have an existing configuration, plan to **migrate it** rather than expecting a drop-in upgrade from `v0.9.x`.

#### ✨Highlights

- **Unified actions + bindings system.** Keyboard input now flows through a single dispatch pipeline, default bindings are declared in TOML, actions are discoverable, and custom behaviour can be defined in both TOML and Lua.
- **Much stronger scripting support.** Lua `setup` now receives the full config plus runtime context, generated intent-backed actions replace handwritten drift-prone bridges, and new helpers like `wait_close()` and `wait_refresh()` make multi-step scripts more predictable.
- **Upgraded TUI foundations.** Moving from **Bubble Tea v1** to **v2** brings better terminal support, a new rendering engine for better performance, and better input handling, including support for bindings like `ctrl+space` and dedicated `shift+...` style keys.
- **Improved diff and selection workflows.** The `diff` view now supports word wrap, `revisions` and `details` support modifier-based mouse selection, and several `details` and `evolog` interactions are more consistent.

#### 🚀 New and Improved

##### Command History

- Added [**command history**](https://idursun.github.io/jjui/command-history/), available with `shift+w`, to review dismissed command runs together with their output.
- Moved **running command** information out of the status area and into dedicated `flash` messages, so the command and its output are now shown together in one place.

##### Help and Status

- Reintroduced a dedicated **Help view** for full keybinding discovery, with filtering and scrolling, alongside the existing inline help.
- Changed **status/help** binding presentation to **column-major order** so related bindings are easier to scan.

##### Lua and Configuration

- Shipped the unified **actions + bindings** architecture introduced in `v0.10`.
- Exposed the full config object to Lua `setup`, including runtime context such as repository path via `config.repo`, and terminal state via `config.terminal.dark_mode`, `config.terminal.fg`, and `config.terminal.bg`.
- Standardised closeable action naming around `open_*` and aligned apply/close semantics for more predictable scripted workflows.

##### Oplog

- Added **quick search** to `oplog` and shared the search behavior with revision search.

##### Evolog

- Changed `evolog` preview defaults to show **interdiff** output, matching `jj evolog -p` more closely.

##### Abandon

- Added `s` in `abandon` mode to target descendants of the selected revision(s).

##### Revset

- Kept `revset` editing open when the expression is invalid, improving iteration while editing.
- Improved `revset` editing so function completion inserts `(` when appropriate, while the function list display is cleaner and less noisy.

##### Diff

- Added **word wrap** in the `diff` view, with explicit wrapped and unwrapped modes plus soft-wrap-aware scrolling.
- Added `g` and `G` in the `diff` view to jump to the top and bottom.

##### Details and Revisions

- Added `Ctrl+click` single-item toggle and `Alt+click` range selection in `revisions` and `details`.
- Added a `revisions.details.select_file` action for finer control in `details` workflows.

#### 🛠️ Fixes

- Fixed rendering issues with **double-width characters**.
- Simplified divergent revision handling by using `change_id/offset` directly from the `jj log` prefix template.
- Fixed `git push --all` behaviour for deleted bookmarks and corrected related command descriptions.

#### ⚙️ Internal Updates

- Upgraded to **Bubble Tea v2**.
- Replaced remaining `cellbuf` usage with `ultraviolet`.
- Hardcoded model-level key handling has been removed in favor of dispatcher-driven intents.
- Continued internal cleanup around rendering, overlays, display context, and generated action plumbing to support the new architecture.

#### What's Changed

- Unified Actions + Bindings system by [@&#8203;idursun](https://github.com/idursun) in [#&#8203;533](idursun/jjui#533)
- feat(oplog): add QuickSearch to oplog, share logic with revision search by [@&#8203;baggiiiie](https://github.com/baggiiiie) in [#&#8203;521](idursun/jjui#521)
- fix: add missing keys in bindings by [@&#8203;baggiiiie](https://github.com/baggiiiie) in [#&#8203;538](idursun/jjui#538)
- feat(evolog): change default evolog command to show interdiff by [@&#8203;academician](https://github.com/academician) in [#&#8203;539](idursun/jjui#539)
- fix: add back `esc` to clear checked revisions by [@&#8203;baggiiiie](https://github.com/baggiiiie) in [#&#8203;541](idursun/jjui#541)
- remove gh-pages workflow from main branch. by [@&#8203;vic](https://github.com/vic) in [#&#8203;542](idursun/jjui#542)
- docs: fix readme links by [@&#8203;baggiiiie](https://github.com/baggiiiie) in [#&#8203;549](idursun/jjui#549)
- Update CONTRIBUTING.md for documentation by [@&#8203;vic](https://github.com/vic) in [#&#8203;547](idursun/jjui#547)
- feat(lua): add "filter" and "ordered" option to `choose` lua api by [@&#8203;baggiiiie](https://github.com/baggiiiie) in [#&#8203;548](idursun/jjui#548)
- feat(abandon): use `s` for selecting descendants by [@&#8203;idursun](https://github.com/idursun) in [#&#8203;544](idursun/jjui#544)
- feat: add change\_offset in jj log prefix template for divergent revisions by [@&#8203;baggiiiie](https://github.com/baggiiiie) in [#&#8203;550](idursun/jjui#550)
- fix: make bookmark input visible when user has custom template-aliases by [@&#8203;baggiiiie](https://github.com/baggiiiie) in [#&#8203;551](idursun/jjui#551)
- fix(evolog): keep restore mode navigation on revisions and esc close by [@&#8203;baggiiiie](https://github.com/baggiiiie) in [#&#8203;554](idursun/jjui#554)
- Expose full config to Lua setup and add runtime context (repo + terminal) by [@&#8203;idursun](https://github.com/idursun) in [#&#8203;553](idursun/jjui#553)
- feat(flash): command history by [@&#8203;idursun](https://github.com/idursun) in [#&#8203;556](idursun/jjui#556)
- Update to bubbletea v2 by [@&#8203;idursun](https://github.com/idursun) in [#&#8203;558](idursun/jjui#558)
- Ctrl+click and Alt+click for single and range selection by [@&#8203;idursun](https://github.com/idursun) in [#&#8203;563](idursun/jjui#563)
- feat: add `(` to functions when autocompleted by [@&#8203;nickchomey](https://github.com/nickchomey) in [#&#8203;564](idursun/jjui#564)
- feat(status): change display to column major order by [@&#8203;baggiiiie](https://github.com/baggiiiie) in [#&#8203;569](idursun/jjui#569)
- fix: remove parentheses from functions list, but add when autocomplete by [@&#8203;nickchomey](https://github.com/nickchomey) in [#&#8203;567](idursun/jjui#567)
- fix(git): prevent panic when opening git menu with no selected revision by [@&#8203;baggiiiie](https://github.com/baggiiiie) in [#&#8203;571](idursun/jjui#571)
- Refactor/Lua bridge by [@&#8203;idursun](https://github.com/idursun) in [#&#8203;572](idursun/jjui#572)
- fix(ui): guard against nil commit in OpenBookmarks intent by [@&#8203;baggiiiie](https://github.com/baggiiiie) in [#&#8203;573](idursun/jjui#573)
- feat(diff): word wrap by [@&#8203;idursun](https://github.com/idursun) in [#&#8203;575](idursun/jjui#575)
- Add pgup/pgdown keybindings to evolog and details by [@&#8203;academician](https://github.com/academician) in [#&#8203;576](idursun/jjui#576)
- feat(lua): make default actions overridable and expose jjui.builtin.\* by [@&#8203;idursun](https://github.com/idursun) in [#&#8203;577](idursun/jjui#577)
- feat(help): add "help view" bound to `f1` by [@&#8203;idursun](https://github.com/idursun) in [#&#8203;578](idursun/jjui#578)

#### New Contributors

- [@&#8203;academician](https://github.com/academician) made their first contribution in [#&#8203;539](idursun/jjui#539)

**Full Changelog**: <idursun/jjui@v0.9.12...v0.10.0>

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever MR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this MR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this MR, check this box

---

This MR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My41OS40IiwidXBkYXRlZEluVmVyIjoiNDMuNTkuNCIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOlsiUmVub3ZhdGUgQm90IiwiYXV0b21hdGlvbjpib3QtYXV0aG9yZWQiLCJkZXBlbmRlbmN5LXR5cGU6Om1pbm9yIl19-->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants