Migrate command execution to structured argv lists across the plugin, replacing shell-string command construction with `vim.system` argv execution. The runner API now exposes argv-based execution as the default path:
- `runner.execute_command` -> `runner.execute`
- `runner.execute_command_async` -> `runner.execute_async`
- `runner.execute_command_raw` -> `runner.execute_raw`
- `runner.execute_command_raw_async` -> `runner.execute_raw_async`
- `runner.execute_command_sync` was removed; use `runner.execute` and handle the result directly
BREAKING CHANGES:
- `cmd.new({ args = ... })` now requires `args` as `string[]` argv tokens, not a single string.
- `cmd.log({ ... })` now uses `raw_flags` as `string[]` for raw passthrough flags; `raw = "..."` is no longer supported.
- Direct users of `jj.core.runner` must migrate from the old `execute_command*` string helpers to the new argv-based `execute*` helpers.
Add first-class conflict resolution support to jj.nvim.
- add `jj.cmd.resolve` to run `jj resolve` in a floating terminal or via an
external tool
- add `:J resolve` with support for `-r/--revision`, `--tool`,
`--external/--ext`, and positional filesets
- integrate resolve into the log buffer with the `gr` mapping and optional
`resolve_strategies` picker
- add `utils.is_change_conflicted()` and avoid opening resolve when the
selected revision has no conflicts
- document resolve usage, config, and keymaps in the README
- add tests for resolve arg parsing and conflict detection helpers
In the status picker, pressing Ctrl-d opens the selected file in the
current window and immediately runs :Jdiff, so the diff view follows
without a second step.
This new command is natively implemented by both the `codediff` and `diffview` backends allowing to easily navigate the changes between two revsets while diffing the.
It also gives a new `:J diff_hisotyr` command that optionally takes a range of revsets formatted `<rev1>..<rev2>` otherwise it prompts the user for the range.
Add split command that allows splitting a change into multiple revisions
from the log buffer or via :J split. Supports --parallel, --message,
--fileset, and --ignore-immutable flags. Includes immutability checks
with user confirmation and empty change detection.
- Refactor diff into modular architecture (native, diffview, codediff)
- Add the possibility for users to define their own diff backend
- Support external diff tools like diffview.nvim codediff.nvim
- Enable visual mode selection to diff two changes in log buffer
- Add summary tooltip integration with terminal
- Update documentation with new diff workflows
Display a summary of changed files for any revision in the log buffer
using a floating tooltip. From the tooltip, users can diff or edit
specific files directly.
- Add summary tooltip triggered by <S-k> in log buffer
- Integrate tooltip as stateful component of terminal
- Make summary keymaps configurable
- Add documentation and demo gif
- Squash: behaves like rebase, the user can select 1 or more
revisions to squash and then a destination
- Quick squash: `-r {rev} -u --ignore-immutable` flag from jj allowing
for quick visuall squashes
Changes add support for rebasing while ignoring immutability constraints with new keymaps (<S-CR>, <S-o>, <S-a>, <S-b>) and update documentation. Refactors rebase handler to accept optional ignore_immut parameter and includes minor comment improvements in buffer and command modules.
Now it is possible to rebase interactively from the log buffer with visual feedback. You can rebase one or many visually selected changes.
Supported target modes are: `-o` / `-A` / `-B`.
Limitation:
- As of now you cannot rebase a whole branch (-b) from the log view.
Bonus from this pr:
- Now keymaps support different modes
- Add `prefix` option to `bookmark_create()` function for setting default bookmark names
- Add `bookmark.prefix` configuration option for global bookmark prefix defaults
- Update README with bookmark prefix usage examples
Convert blocking jj commands to async using vim.fn.jobstart() to prevent UI
freezing during fetch, push, rebase, squash, and other heavy operations.
Changes:
- Implement execute_command_async() in runner with proper error handling
- Captures stdout from job and passes to success callback
- Supports stdin input for commands that require it
- Includes silent flag to suppress error notifications
- Replicates sync version's error handling behavior
- Convert blocking operations to async:
- handle_log_fetch, handle_log_push_all, handle_log_new
- handle_log_edit, handle_log_abandon, handle_log_describe
- describe.execute_describe, all init.lua commands
- Add push/fetch as public commands with CLI support:
- M.fetch() - fetch from remote
- M.push(opts) - push all changes or specific bookmark
- CLI: :J push, :J push <bookmark>, :J fetch
- Implement handle_log_push_bookmark() for revision under cursor:
- Retrieves and strips modified bookmark indicator (*)
- Pushes specific bookmark to remote
- Keybind: Shift+p in log buffer
- Update README with new keybinds:
- a: abandon revision under cursor
- f: fetch from remote
- p: push all changes
- Shift+p: push revision's bookmark
- Add Lua API docs for push command options
- Add close_on_edit option to close log buffer after editing a change (default: false)
- Rename handle_log_enter to handle_log_edit with close_on_exit parameter
- Update log keymaps to pass close_on_edit config to handlers
- Update config types and defaults in init.lua
Add cursor position restoration with configurable timing to handle terminal
buffer rendering asynchronously. This fixes cursor column being reset to 0
when refreshing jj log commands.
Changes:
- Add `terminal.cursor_render_delay` configuration option (default: 10ms)
- Add buffer.get_cursor() and buffer.set_cursor() helpers in core/buffer
* buffer.set_cursor() uses defer_fn with configurable delay for terminal buffers
* Automatic position validation with clamping to buffer bounds
* Line number clamped to [1, line_count]
* Column clamped to [0, line_length] based on actual line content
* Validation happens inside deferred callback to check against final rendered content
- Extract clamp_cursor_position() helper to eliminate code duplication
- Refactor terminal module to use new buffer cursor helpers
- Store and restore cursor position when cycling through log commands
- Update README with terminal configuration section and example usage
The delay is necessary because nvim_open_term() + nvim_chan_send() have
asynchronous rendering in the terminal emulator layer. Setting the cursor
before rendering completes results in the column being reset to 0. Users
experiencing issues can increase the delay value if needed.