diff options
author | Josh Rahm <joshuarahm@gmail.com> | 2025-04-09 23:46:29 +0000 |
---|---|---|
committer | Josh Rahm <joshuarahm@gmail.com> | 2025-04-16 17:41:19 +0000 |
commit | 2034a8419e1c5675592cdd0d0ffeaadfda58001a (patch) | |
tree | 4ba185d58c2ea2b8893aad66aa96f6e5efaec1ef /src/nvim/eval.c | |
parent | f068386c9f709c586f44169f4566b4e31ce973de (diff) | |
download | rneovim-2034a8419e1c5675592cdd0d0ffeaadfda58001a.tar.gz rneovim-2034a8419e1c5675592cdd0d0ffeaadfda58001a.tar.bz2 rneovim-2034a8419e1c5675592cdd0d0ffeaadfda58001a.zip |
feat(userregfunc): programmable user-defined registers with multibyte support
This patch introduces a new global option `userregfunc`, allowing users
to define custom behavior for registers not handled by Neovim
internally. This enables programmable registers using any Unicode
character — including multibyte characters.
- A new register slot `USER_REGISTER` is introduced. Any register not
matching the standard set (`0-9a-zA-Z"+-*%#/:.=`, etc.) is routed
through this system.
- When such a register is accessed, the function defined in
`userregfunc` is called with three arguments:
1. `{action}` (string): either `"yank"` or `"put"`
2. `{register}` (string): UTF-8 character name of the register
3. `{content}`:
- If `action == "yank"`: a dictionary with these keys:
- `lines` (list of strings): the yanked text
- `type` (string): one of `"v"` (charwise), `"V"` (linewise), or `"b"` (blockwise)
- `width` (number, optional): present if `type == "b"`
- `additional_data` (dict, optional): user-extensible metadata
- If `action == "put"`: this is always `v:null`
- The function may return either:
- A **string** (used as a charwise register), or
- A **dictionary** matching the structure above
- Internally, `read_userregister()` and `write_userregister()` convert
between `yankreg_T` and typval dictionaries.
- Messages and internal logic fully support multibyte register names via
UTF-8.
- A new `USER_REGISTER` slot is used for logical separation in the
register table.
Included in this patch is an extensible Lua framework (`vim.userregs`)
for defining user register handlers in Lua. It provides per-register
handlers via `register_handler(registers, handler)`
The global function `_G.def_userreg_func` is registered as the default
implementation of `'userregfunc'`, enabling seamless integration with
the Lua framework.
- Register `λ` dynamically inserts the current date
- Register `&` reads and writes from a "global register" file under
`stdpath("run")`
- Register `?` returns the result of a shell command
- Registers that auto-adjust based on filetype, cursor context, or
Treesitter nodes
This change expands the register model into a programmable abstraction —
fully scriptable and extensible — without breaking compatibility.
Diffstat (limited to 'src/nvim/eval.c')
-rw-r--r-- | src/nvim/eval.c | 13 |
1 files changed, 6 insertions, 7 deletions
diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 3f73074333..370565c441 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -3446,12 +3446,10 @@ static int eval7(char **arg, typval_T *rettv, evalarg_T *const evalarg, bool wan // Register contents: @r. case '@': (*arg)++; + int regname = mb_cptr2char_adv((const char**) arg); if (evaluate) { rettv->v_type = VAR_STRING; - rettv->vval.v_string = get_reg_contents(**arg, kGRegExprSrc); - } - if (**arg != NUL) { - (*arg)++; + rettv->vval.v_string = get_reg_contents(regname, kGRegExprSrc); } break; @@ -7073,16 +7071,17 @@ void set_argv_var(char **argv, int argc) /// Set v:register if needed. void set_reg_var(int c) { - char regname; + int regname; if (c == 0 || c == ' ') { regname = '"'; } else { - regname = (char)c; + regname = c; } + // Avoid free/alloc when the value is already right. if (vimvars[VV_REG].vv_str == NULL || vimvars[VV_REG].vv_str[0] != c) { - set_vim_var_string(VV_REG, ®name, 1); + set_vim_var_string(VV_REG, reg_to_mb(regname), -1); } } |