aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosh Rahm <joshuarahm@gmail.com>2023-11-30 10:50:16 -0700
committerJosh Rahm <joshuarahm@gmail.com>2023-11-30 10:50:16 -0700
commit8a98d50685575d20fcd6ad0dc7031d489d5e5361 (patch)
tree9a2b95594af2c6fc1128c7cbfb73b67c1a8749cc
parent49fd5b067fed9744ee7e84f7db9209417023b5db (diff)
parent23fd9a2b29cedef01ad6597854bc42ffb1bab86a (diff)
downloadrneovim-8a98d50685575d20fcd6ad0dc7031d489d5e5361.tar.gz
rneovim-8a98d50685575d20fcd6ad0dc7031d489d5e5361.tar.bz2
rneovim-8a98d50685575d20fcd6ad0dc7031d489d5e5361.zip
Merge branch 'userreg' into 20231130_mix
-rw-r--r--runtime/autoload/usermark.vim7
-rw-r--r--runtime/autoload/userreg.vim7
-rw-r--r--runtime/doc/options.txt51
-rw-r--r--runtime/lua/vim/usermark.lua68
-rw-r--r--runtime/lua/vim/userreg.lua51
-rw-r--r--runtime/plugin/usermark.vim1
-rw-r--r--runtime/plugin/userreg.vim1
-rw-r--r--src/nvim/buffer_defs.h2
-rw-r--r--src/nvim/eval.c10
-rw-r--r--src/nvim/eval/funcs.c2
-rw-r--r--src/nvim/eval/vars.c15
-rw-r--r--src/nvim/ex_docmd.c8
-rw-r--r--src/nvim/map.c3
-rw-r--r--src/nvim/map_defs.h1
-rw-r--r--src/nvim/mark.c159
-rw-r--r--src/nvim/ops.c412
-rw-r--r--src/nvim/ops.h11
-rw-r--r--src/nvim/option.c473
-rw-r--r--src/nvim/option_defs.h1
-rw-r--r--src/nvim/option_vars.h4
-rw-r--r--src/nvim/options.lua92
-rw-r--r--src/nvim/po/da.po2
-rw-r--r--src/nvim/po/fr.po2
-rw-r--r--src/nvim/po/tr.po2
-rw-r--r--src/nvim/po/uk.po2
-rw-r--r--src/nvim/shada.c4
-rw-r--r--src/nvim/yankmap.c45
-rw-r--r--src/nvim/yankmap.h25
28 files changed, 1107 insertions, 354 deletions
diff --git a/runtime/autoload/usermark.vim b/runtime/autoload/usermark.vim
new file mode 100644
index 0000000000..b1b4113d1a
--- /dev/null
+++ b/runtime/autoload/usermark.vim
@@ -0,0 +1,7 @@
+" This is used for the default userreg function.
+
+lua vim.usermark = require('vim.usermark')
+
+function! usermark#func(action, mark) abort
+ return v:lua.vim.usermark.fn(a:action, a:mark)
+endfunction
diff --git a/runtime/autoload/userreg.vim b/runtime/autoload/userreg.vim
new file mode 100644
index 0000000000..fd026a12e6
--- /dev/null
+++ b/runtime/autoload/userreg.vim
@@ -0,0 +1,7 @@
+" This is used for the default userreg function.
+
+lua vim.userreg = require('vim.userreg')
+
+function! userreg#func(action, register, content) abort
+ return v:lua.vim.userreg.fn(a:action, a:register, a:content)
+endfunction
diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt
index f47093782c..ba1d848962 100644
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -6757,6 +6757,57 @@ A jump table for the options with a short description can be found at |Q_op|.
written to disk (see |crash-recovery|). Also used for the
|CursorHold| autocommand event.
+ *'userregfunc'* *'urf'*
+'userregfunc' 'urf' string (default "")
+ global
+ The option specifies a function to be used to handle any registers
+ that Neovim does not natively handle. This option unlocks all
+ characters to be used as registers by the user.
+
+ The 'userregfunc' function is called each time a user register is read
+ from or written to.
+
+ The 'userregfunc' function must take the following parameters:
+
+ {action} The action being done on this register (either 'yank'
+ or 'put'
+
+ {register} The string holding the name of the register. This
+ is always a single character, though multi-byte
+ characters are allowed.
+
+ {content} If the action is 'yank' this is the content being
+ yanked into the register. The content is a dictionary
+ with the following items:
+
+ {lines} The lines being yanked, as a list.
+
+ {type} The type of yank, either "line", "char", or
+ "block"
+
+ {width} The width in case of "block" mode.
+
+ {additional_data} Additional data. (can be returned in
+ put mode).
+
+ In case the action is 'put', the 'userregfunc' function should return
+ the content to place in that location. The content can either be a
+ string, in which case "char" mode is inferred, or it can return a
+ dictionary of the same template that populates 'content'.
+
+ A very simple example of a 'userregfunc' function that behaves exactly
+ like traditional registers would look like: >
+
+ let s:contents = {}
+ function! MyUserregFunction(action, register, content) abort
+ if a:action == "put"
+ return get(s:contents, a:register, "")
+ else
+ let s:contents[a:register] = a:content
+ endif
+ endfunction
+ set userregfunc=MyUserregFunction
+<
*'varsofttabstop'* *'vsts'*
'varsofttabstop' 'vsts' string (default "")
local to buffer
diff --git a/runtime/lua/vim/usermark.lua b/runtime/lua/vim/usermark.lua
new file mode 100644
index 0000000000..0d1ec0ae0f
--- /dev/null
+++ b/runtime/lua/vim/usermark.lua
@@ -0,0 +1,68 @@
+-- Defualt implementation of the usermarkfunc. This default implementation is
+-- extensible and allows other plugins to register handlers for different
+-- registers.
+--
+-- The default handler behaves just as a normal register would.
+
+local vim = assert(vim)
+local usermark = {}
+
+-- Returns a "default handler" which behaves like normal global marks. When a
+-- call to set() is made, it stores the current line and col of the cursor and
+-- the filename of the current file.
+function usermark._default_handler()
+ local d = {}
+
+ -- Called when a mark is recalled using the "'" command. Just returns what was
+ -- stored before or nothing if it was never set before.
+ function d.get(self, mark)
+ return self.content or {}
+ end
+
+ -- Called when a mark is set using the "m" command. Stores the current cursor
+ -- position to be recalled at a later time.
+ function d.set(self, mark)
+ local r,c = unpack(vim.api.nvim_win_get_cursor(0))
+ local file = vim.fn.expand("%:p")
+
+ self.content = {
+ line = r;
+ col = c;
+ }
+
+ if file ~= '' then
+ self.content.file = file
+ end
+ end
+
+ return d
+end
+
+-- The store for register default handler
+usermark._marktable = {}
+
+-- Function for the 'usermarkfunc'. Will defer to the handler associated with
+-- the provided mark.
+--
+-- If not handler is registered to a given mark, the default handler is used,
+-- which is a re-implementation of standard mark behavior.
+function usermark.fn(action, mark)
+ if not usermark._marktable[mark] then
+ usermark._marktable[mark] = usermark._default_handler()
+ end
+
+ if action == "get" then
+ return usermark._marktable[mark]:get(mark)
+ else
+ usermark._marktable[mark]:set(mark)
+ return nil
+ end
+end
+
+-- Registers a handler with a mark. Gets and sets will then defer to this
+-- handler when determining the mark's behavior.
+function usermark.register_handler(mark, handler)
+ usermark._marktable[mark] = handler
+end
+
+return usermark
diff --git a/runtime/lua/vim/userreg.lua b/runtime/lua/vim/userreg.lua
new file mode 100644
index 0000000000..5abcff0407
--- /dev/null
+++ b/runtime/lua/vim/userreg.lua
@@ -0,0 +1,51 @@
+-- Defualt implementation of the userregfunc. This default implementation is
+-- extensible and allows other plugins to register handlers for different
+-- registers.
+--
+-- The default handler behaves just as a normal register would.
+
+local userreg = {}
+
+-- Returns a "default handler" which behaves exactly like the builtin registers
+-- in Vim. Simply stores whatever was yanked and returns the last thing that was
+-- yanked.
+function userreg._default_handler()
+ local d = {}
+
+ function d.do_yank(self, content)
+ self.content = content
+ end
+
+ function d.do_put(self)
+ return self.content or {}
+ end
+
+ return d
+end
+
+-- The store for registers default handler
+userreg._regtable = {}
+
+-- Function for the userreg. This function will defer to the handler registered
+-- to the given register. If no handler is registered to the given register, the
+-- default handler is used.
+function userreg.fn(action, register, content)
+ if not userreg._regtable[register] then
+ userreg._regtable[register] = userreg._default_handler()
+ end
+
+ if action == "yank" then
+ userreg._regtable[register]:do_yank(content)
+ return nil
+ else
+ return userreg._regtable[register]:do_put()
+ end
+end
+
+-- Registers a handler with a register. Future yanks and puts will defer to the
+-- handler when determining the content to put/yank.
+function userreg.register_handler(register, handler)
+ userreg._regtable[register] = handler
+end
+
+return userreg
diff --git a/runtime/plugin/usermark.vim b/runtime/plugin/usermark.vim
new file mode 100644
index 0000000000..917e7510f1
--- /dev/null
+++ b/runtime/plugin/usermark.vim
@@ -0,0 +1 @@
+set usermarkfunc=usermark#func
diff --git a/runtime/plugin/userreg.vim b/runtime/plugin/userreg.vim
new file mode 100644
index 0000000000..099e7c65cb
--- /dev/null
+++ b/runtime/plugin/userreg.vim
@@ -0,0 +1 @@
+set userregfunc=userreg#func
diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h
index 8928eea028..93dfdaf6b7 100644
--- a/src/nvim/buffer_defs.h
+++ b/src/nvim/buffer_defs.h
@@ -540,12 +540,14 @@ struct file_buffer {
#ifdef BACKSLASH_IN_FILENAME
char *b_p_csl; ///< 'completeslash'
#endif
+ char *b_p_umf; ///< 'usermarkfunc'
char *b_p_cfu; ///< 'completefunc'
Callback b_cfu_cb; ///< 'completefunc' callback
char *b_p_ofu; ///< 'omnifunc'
Callback b_ofu_cb; ///< 'omnifunc' callback
char *b_p_tfu; ///< 'tagfunc'
Callback b_tfu_cb; ///< 'tagfunc' callback
+ char *b_p_urf; ///< 'userregfunc'
int b_p_eof; ///< 'endoffile'
int b_p_eol; ///< 'endofline'
int b_p_fixeol; ///< 'fixendofline'
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index 6786316b8e..b11f2f2922 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -3165,12 +3165,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;
@@ -4483,7 +4481,7 @@ bool garbage_collect(bool testing)
// registers (ShaDa additional data)
{
- const void *reg_iter = NULL;
+ iter_register_T reg_iter = ITER_REGISTER_NULL;
do {
yankreg_T reg;
char name = NUL;
@@ -4492,7 +4490,7 @@ bool garbage_collect(bool testing)
if (name != NUL) {
ABORTING(set_ref_dict)(reg.additional_data, copyID);
}
- } while (reg_iter != NULL);
+ } while (reg_iter != ITER_REGISTER_NULL);
}
// global marks (ShaDa additional data)
diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c
index 0054c47678..7191ad34fc 100644
--- a/src/nvim/eval/funcs.c
+++ b/src/nvim/eval/funcs.c
@@ -3165,6 +3165,7 @@ static void f_has(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
"title",
"user-commands", // was accidentally included in 5.4
"user_commands",
+ "usermarks",
"vartabs",
"vertsplit",
"vimscript-1",
@@ -3181,6 +3182,7 @@ static void f_has(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
"xattr",
#endif
"nvim",
+ "rneovim",
};
// XXX: eval_has_provider() may shell out :(
diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c
index 670ee39f4b..74d70ca482 100644
--- a/src/nvim/eval/vars.c
+++ b/src/nvim/eval/vars.c
@@ -552,7 +552,7 @@ const char *skip_var_list(const char *arg, int *var_count, int *semicolon)
static const char *skip_var_one(const char *arg)
{
if (*arg == '@' && arg[1] != NUL) {
- return arg + 2;
+ return arg + 1 + utfc_ptr2len(arg + 1);
}
return find_name_end(*arg == '$' || *arg == '&' ? arg + 1 : arg,
NULL, NULL, FNE_INCL_BR | FNE_CHECK_START);
@@ -856,16 +856,20 @@ static char *ex_let_register(char *arg, typval_T *const tv, const bool is_const,
char *arg_end = NULL;
arg++;
+
+ int regname = utf_ptr2char(arg);
+ int mblen = utf_ptr2len(arg);
+
if (op != NULL && vim_strchr("+-*/%", (uint8_t)(*op)) != NULL) {
semsg(_(e_letwrong), op);
} else if (endchars != NULL
- && vim_strchr(endchars, (uint8_t)(*skipwhite(arg + 1))) == NULL) {
+ && vim_strchr(endchars, (uint8_t)(*skipwhite(arg + mblen))) == NULL) {
emsg(_(e_letunexp));
} else {
char *ptofree = NULL;
const char *p = tv_get_string_chk(tv);
if (p != NULL && op != NULL && *op == '.') {
- char *s = get_reg_contents(*arg == '@' ? '"' : *arg, kGRegExprSrc);
+ char *s = get_reg_contents(*arg == '@' ? '"' : regname, kGRegExprSrc);
if (s != NULL) {
ptofree = concat_str(s, p);
p = ptofree;
@@ -873,8 +877,9 @@ static char *ex_let_register(char *arg, typval_T *const tv, const bool is_const,
}
}
if (p != NULL) {
- write_reg_contents(*arg == '@' ? '"' : *arg, p, (ssize_t)strlen(p), false);
- arg_end = arg + 1;
+ write_reg_contents(*arg == '@' ? '"' : regname,
+ p, (ssize_t)strlen(p), false);
+ arg_end = arg + mblen;
}
xfree(ptofree);
}
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index bf5a3944e6..99e16bae11 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -3223,7 +3223,7 @@ char *skip_range(const char *cmd, int *ctx)
}
}
if (*cmd != NUL) {
- cmd++;
+ cmd += utf_ptr2len(cmd);
}
}
@@ -3367,13 +3367,13 @@ static linenr_T get_address(exarg_T *eap, char **ptr, cmd_addr_T addr_type, int
goto error;
}
if (skip) {
- cmd++;
+ cmd += utfc_ptr2len(cmd);
} else {
// Only accept a mark in another file when it is
// used by itself: ":'M".
MarkGet flag = to_other_file && cmd[1] == NUL ? kMarkAll : kMarkBufLocal;
- fmark_T *fm = mark_get(curbuf, curwin, NULL, flag, *cmd);
- cmd++;
+ fmark_T *fm = mark_get(curbuf, curwin, NULL, flag, utf_ptr2char(cmd));
+ cmd += utf_ptr2len(cmd);
if (fm != NULL && fm->fnum != curbuf->handle) {
(void)mark_move_to(fm, 0);
// Jumped to another file.
diff --git a/src/nvim/map.c b/src/nvim/map.c
index be6bf58daa..d7d1a00158 100644
--- a/src/nvim/map.c
+++ b/src/nvim/map.c
@@ -118,6 +118,9 @@ void mh_clear(MapHash *h)
#define VAL_NAME(x) quasiquote(x, ptr_t)
#include "nvim/map_value_impl.c.h"
#undef VAL_NAME
+#define VAL_NAME(x) quasiquote(x, int)
+#include "nvim/map_value_impl.c.h"
+#undef VAL_NAME
#undef KEY_NAME
#define KEY_NAME(x) x##cstr_t
diff --git a/src/nvim/map_defs.h b/src/nvim/map_defs.h
index 147c03327a..b6bb172bb0 100644
--- a/src/nvim/map_defs.h
+++ b/src/nvim/map_defs.h
@@ -152,6 +152,7 @@ KEY_DECLS(HlEntry)
KEY_DECLS(ColorKey)
MAP_DECLS(int, int)
+MAP_DECLS(ptr_t, int)
MAP_DECLS(int, ptr_t)
MAP_DECLS(cstr_t, ptr_t)
MAP_DECLS(cstr_t, int)
diff --git a/src/nvim/mark.c b/src/nvim/mark.c
index 5839cf7a2e..7dacd03891 100644
--- a/src/nvim/mark.c
+++ b/src/nvim/mark.c
@@ -22,6 +22,7 @@
#include "nvim/globals.h"
#include "nvim/highlight.h"
#include "nvim/mark.h"
+#include "nvim/mark_defs.h"
#include "nvim/mbyte.h"
#include "nvim/memline.h"
#include "nvim/memory.h"
@@ -37,6 +38,8 @@
#include "nvim/strings.h"
#include "nvim/textobject.h"
#include "nvim/vim_defs.h"
+#include "nvim/map_defs.h"
+#include "nvim/eval/userfunc.h"
// This file contains routines to maintain and manipulate marks.
@@ -46,6 +49,33 @@
// There are marks 'A - 'Z (set by user) and '0 to '9 (set when writing
// shada).
+static struct {
+ Map(int, ptr_t) named;
+} usermarks;
+bool usermarks_init;
+
+static xfmark_T* lookup_user_mark(int mark)
+{
+ if (!usermarks_init) {
+ usermarks.named = (Map(int, ptr_t)) MAP_INIT;
+ usermarks_init = 1;
+ }
+
+ bool is_new = false;
+ xfmark_T **ret =
+ (xfmark_T**) map_put_ref(int, ptr_t)(&usermarks.named, mark, NULL, &is_new);
+
+ if (ret) {
+ if (is_new) {
+ *ret = xcalloc(sizeof(xfmark_T), 1);
+ }
+
+ return *ret;
+ }
+
+ return NULL;
+}
+
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "mark.c.generated.h"
#endif
@@ -153,7 +183,8 @@ int setmark_pos(int c, pos_T *pos, int fnum, fmarkv_T *view_pt)
RESET_XFMARK(namedfm + i, *pos, fnum, view, NULL);
return OK;
}
- return FAIL;
+
+ return mark_set_user(buf, c);
}
// Set the previous context mark to the current position and add it to the
@@ -334,6 +365,15 @@ fmark_T *mark_get(buf_T *buf, win_T *win, fmark_T *fmp, MarkGet flag, int name)
// Local Marks
fm = mark_get_local(buf, win, name);
}
+
+ if (!fm) {
+ // Get usermark.
+ xfmark_T* xm = mark_get_user(buf, name);
+ if (xm) {
+ fm = &xm->fmark;
+ }
+ }
+
if (fmp != NULL && fm != NULL) {
*fmp = *fm;
return fmp;
@@ -422,6 +462,123 @@ fmark_T *mark_get_local(buf_T *buf, win_T *win, int name)
return mark;
}
+/// Loads the mark 'out' with the results from calling the usermarkfunc.
+///
+/// @param umf String for the usermarkfunc
+/// @param name name for the mark
+/// @param[out] out the mark to write the results to.
+static int call_umf(
+ const char* umf, int name, typval_T* out, const char* get_or_set_a)
+{
+ char markname_str[5];
+ char get_or_set[4];
+ int len;
+
+ strncpy(get_or_set, get_or_set_a, sizeof(get_or_set));
+ get_or_set[3] = 0;
+
+ len = (*utf_char2len)(name);
+ markname_str[len] = 0;
+ utf_char2bytes(name, markname_str);
+
+ typval_T args[3];
+ args[0].v_type = VAR_STRING;
+ args[1].v_type = VAR_STRING;
+ args[2].v_type = VAR_UNKNOWN;
+
+ args[0].vval.v_string = get_or_set;
+ args[1].vval.v_string = markname_str;
+
+ funcexe_T funcexe = FUNCEXE_INIT;
+ funcexe.fe_evaluate = true;
+
+ return call_func(umf, -1, out, 2, args, &funcexe);
+}
+
+static int typval_to_xfmark(buf_T* buf, xfmark_T* out, typval_T* in)
+{
+ varnumber_T line;
+ varnumber_T col;
+ char* filename = NULL;
+
+ switch (in->v_type) {
+ case VAR_DICT:
+ line = tv_dict_get_number(in->vval.v_dict, "line");
+ col = tv_dict_get_number(in->vval.v_dict, "col");
+ filename = tv_dict_get_string(in->vval.v_dict, "file", true);
+ break;
+
+ case VAR_NUMBER:
+ line = in->vval.v_number;
+ col = 1;
+ break;
+
+ default:
+ return -1;
+ }
+
+ free_xfmark(*out);
+ memset(out, 0, sizeof(*out));
+
+ out->fname = filename;
+ out->fmark.mark.col = (int) col;
+ out->fmark.mark.lnum = (int) line;
+ out->fmark.fnum = 0;
+ out->fmark.timestamp = os_time();
+
+ return 0;
+}
+
+/// Gets marks that are defined by the user.
+///
+/// @param buf the buffer
+/// @param name name fo the mark
+xfmark_T *mark_get_user(buf_T* buf, int name)
+{
+ const char* umf = (const char*) buf->b_p_umf;
+
+ if (!umf) {
+ return NULL;
+ }
+
+ xfmark_T* mark = lookup_user_mark(name);
+ if (mark) {
+ typval_T* typval = xcalloc(sizeof(typval_T), 1);
+ call_umf(umf, name, typval, "get");
+ typval_to_xfmark(buf, mark, typval);
+ tv_free(typval);
+
+ if (mark->fname) {
+ buf_T* buffer =
+ buflist_new(
+ mark->fname, NULL, mark->fmark.mark.lnum, BLN_CURBUF | BLN_LISTED);
+
+ if (buffer) {
+ mark->fmark.fnum = buffer->b_fnum;
+ }
+ } else {
+ mark->fmark.fnum = buf->b_fnum;
+ }
+ }
+
+ return mark;
+}
+
+int mark_set_user(buf_T* buf, int name)
+{
+ const char* umf = (const char*) buf->b_p_umf;
+
+ if (!umf) {
+ return FAIL;
+ }
+
+ typval_T* out = xcalloc(sizeof(typval_T), 1);
+ call_umf(umf, name, out, "set");
+ tv_free(out);
+
+ return OK;
+}
+
/// Get marks that are actually motions but return them as marks
///
/// Gets the following motions as marks: '{', '}', '(', ')'
diff --git a/src/nvim/ops.c b/src/nvim/ops.c
index 3a4e87edf7..8c8900710d 100644
--- a/src/nvim/ops.c
+++ b/src/nvim/ops.c
@@ -23,6 +23,7 @@
#include "nvim/edit.h"
#include "nvim/eval.h"
#include "nvim/eval/typval.h"
+#include "nvim/eval/userfunc.h"
#include "nvim/ex_cmds2.h"
#include "nvim/ex_cmds_defs.h"
#include "nvim/ex_getln.h"
@@ -62,8 +63,24 @@
#include "nvim/undo.h"
#include "nvim/vim_defs.h"
#include "nvim/window.h"
+#include "nvim/yankmap.h"
-static yankreg_T y_regs[NUM_REGISTERS] = { 0 };
+struct yank_registers {
+ yankmap_T inner;
+};
+
+yank_registers_T y_regs;
+
+static yankreg_T *get_reg(yank_registers_T *regs, int idx)
+{
+ return yankmap_get(&regs->inner, idx);
+
+}
+
+static yankreg_T *get_global_reg(int idx)
+{
+ return get_reg(&y_regs, idx);
+}
static yankreg_T *y_previous = NULL; // ptr to last written yankreg
@@ -771,6 +788,24 @@ char *get_expr_line_src(void)
return xstrdup(expr_line);
}
+
+int get_userreg(int regname)
+{
+ if ((regname >= 'a' && regname <= 'z')
+ || (regname >= 'A' && regname <= 'Z')
+ || (regname >= '0' && regname <= '9')
+ || (regname <= 127 && strchr("\"-:.%#=*+_/", regname))
+ || regname == Ctrl_F
+ || regname == Ctrl_P
+ || regname == Ctrl_W
+ || regname == Ctrl_A
+ || (regname + USER_REGISTERS_START) < regname) {
+ return -1;
+ }
+
+ return regname + USER_REGISTERS_START;
+}
+
/// @return whether `regname` is a valid name of a yank register.
///
/// @note: There is no check for 0 (default register), caller should do this.
@@ -787,12 +822,156 @@ bool valid_yank_reg(int regname, bool writing)
|| regname == '-'
|| regname == '_'
|| regname == '*'
- || regname == '+') {
+ || regname == '+'
+ || get_userreg(regname) != -1) {
return true;
}
return false;
}
+static int call_userreg_put(const char* urf, int regname, typval_T* out)
+{
+ char regname_str[5];
+ int len;
+
+ len = utf_char2len(regname);
+ regname_str[len] = 0;
+ utf_char2bytes(regname, regname_str);
+
+ typval_T args[3];
+ args[0].v_type = VAR_STRING;
+ args[1].v_type = VAR_STRING;
+ args[2].v_type = VAR_NUMBER;
+
+ args[0].vval.v_string = "put";
+ args[1].vval.v_string = regname_str;
+ args[2].vval.v_number = 0;
+
+ funcexe_T funcexe = FUNCEXE_INIT;
+ funcexe.fe_evaluate = true;
+
+ return call_func(
+ urf,
+ -1,
+ out,
+ /* argcount_in = */ 3,
+ args,
+ &funcexe);
+}
+
+// Converts a typval returned from the userregfunction to a register.
+static void typval_to_yankreg(yankreg_T* yankreg, typval_T* val)
+{
+ if (!yankreg || !val) {
+ return;
+ }
+
+ char* type;
+ dict_T* dict;
+ typval_T tv;
+ size_t i;
+ size_t sz;
+
+ free_register(yankreg);
+ memset(yankreg, 0, sizeof(*yankreg));
+
+ switch (val->v_type) {
+
+ case VAR_DICT:
+ dict = val->vval.v_dict;
+ type = tv_dict_get_string(dict, "type", false);
+
+ if (!strcmp(type, "block")) {
+ yankreg->y_width = (int) tv_dict_get_number(dict, "width");
+ yankreg->y_type = kMTBlockWise;
+ } else if (!strcmp(type, "line")) {
+ yankreg->y_type = kMTLineWise;
+ } else {
+ yankreg->y_type = kMTCharWise;
+ }
+
+ if (tv_dict_get_tv(dict, "lines", &tv) == OK) {
+ if (tv.v_type == VAR_STRING) {
+ yankreg->y_array = (char**) xcalloc(sizeof(char*), 1);
+ yankreg->y_array[0] = strdup(tv.vval.v_string);
+ } else if (tv.v_type == VAR_LIST) {
+ yankreg->y_array =
+ (char**) xcalloc(sizeof(char*), (size_t) tv_list_len(tv.vval.v_list));
+
+ i = 0;
+ TV_LIST_ITER_CONST(tv.vval.v_list, li, {
+ if (li->li_tv.v_type == VAR_STRING) {
+ yankreg->y_array[i] = strdup(tv_get_string(&li->li_tv));
+ } else {
+ yankreg->y_array[i] = NULL;
+ }
+ ++ i;
+ });
+
+ yankreg->y_size = i;
+ }
+ } else {
+ yankreg->y_array = NULL;
+ }
+
+ if (tv_dict_get_tv(dict, "additional_data", &tv) == OK) {
+ if (tv.v_type == VAR_DICT) {
+ yankreg->additional_data = tv.vval.v_dict;
+ }
+ }
+ break;
+
+ case VAR_LIST:
+ yankreg->y_type = kMTLineWise;
+ sz = (size_t) tv_list_len(val->vval.v_list);
+ yankreg->y_array = (char**) xcalloc(sizeof(char*), sz);
+ yankreg->y_size = sz;
+ i = 0;
+ TV_LIST_ITER_CONST(val->vval.v_list, li, {
+ yankreg->y_array[i] = strdup(tv_get_string(&li->li_tv));
+ i ++;
+ });
+ break;
+
+ default:
+ yankreg->y_type = kMTCharWise;
+ yankreg->y_size = 1;
+
+ if (val->vval.v_string) {
+ yankreg->y_array = (char**) xcalloc(sizeof(char*), 1);
+ yankreg->y_array[0] = strdup(tv_get_string(val));
+ } else {
+ yankreg->y_array = NULL;
+ }
+
+ break;
+
+ }
+
+ yankreg->timestamp = os_time();
+}
+
+static void copy_userreg(yankreg_T* into, int regname)
+{
+ if (!into) {
+ return;
+ }
+
+ if (!curbuf->b_p_urf || strlen(curbuf->b_p_urf) == 0) {
+ return;
+ }
+
+ typval_T* ret = xmalloc(sizeof(typval_T));
+
+ if (call_userreg_put(curbuf->b_p_urf, regname, ret) == FAIL) {
+ return;
+ }
+
+ typval_to_yankreg(into, ret);
+
+ tv_free(ret);
+}
+
/// @return yankreg_T to use, according to the value of `regname`.
/// Cannot handle the '_' (black hole) register.
/// Must only be called with a valid register name!
@@ -830,7 +1009,11 @@ yankreg_T *get_yank_register(int regname, int mode)
if (i == -1) {
i = 0;
}
- reg = &y_regs[i];
+ reg = get_global_reg(i);
+ if (get_userreg(regname) != -1 && mode != YREG_YANK) {
+ // If the mode is not yank, copy the userreg data to the reg.
+ copy_userreg(reg, regname);
+ }
if (mode == YREG_YANK) {
// remember the written register for unnamed paste
@@ -856,7 +1039,7 @@ yankreg_T *copy_register(int name)
if (copy->y_size == 0) {
copy->y_array = NULL;
} else {
- copy->y_array = xcalloc(copy->y_size, sizeof(char *));
+ copy->y_array = (char**) xcalloc(copy->y_size, sizeof(char *));
for (size_t i = 0; i < copy->y_size; i++) {
copy->y_array[i] = xstrdup(reg->y_array[i]);
}
@@ -887,8 +1070,7 @@ int do_record(int c)
if (reg_recording == 0) {
// start recording
- // registers 0-9, a-z and " are allowed
- if (c < 0 || (!ASCII_ISALNUM(c) && c != '"')) {
+ if (c < 0) {
retval = FAIL;
} else {
reg_recording = c;
@@ -913,9 +1095,10 @@ int do_record(int c)
}
// Name of requested register, or empty string for unnamed operation.
- char buf[NUMBUFLEN + 2];
- buf[0] = (char)regname;
- buf[1] = NUL;
+ char buf[NUMBUFLEN + 5];
+ int len = (*utf_char2len)(regname);
+ utf_char2bytes(regname, buf);
+ buf[len] = NUL;
(void)tv_dict_add_str(dict, S_LEN("regname"), buf);
tv_dict_set_keys_readonly(dict);
@@ -992,6 +1175,9 @@ static int stuff_yank(int regname, char *p)
reg->y_type = kMTCharWise;
}
reg->timestamp = os_time();
+ if (get_userreg(regname) != -1) {
+ return eval_yank_userreg(curbuf->b_p_urf, regname, reg);
+ }
return OK;
}
@@ -1284,6 +1470,90 @@ int insert_reg(int regname, bool literally_arg)
return retval;
}
+/// Converts a yankreg to a dict which can be used as an argument to the
+// userregfunc.
+static dict_T* yankreg_to_dict(yankreg_T* yankreg) {
+ dict_T *const dict = tv_dict_alloc();
+ dict->dv_refcount = 1;
+ tv_dict_add_nr(dict, S_LEN("width"), yankreg->y_width);
+
+ const char* type;
+
+ switch(yankreg->y_type) {
+ case kMTLineWise:
+ type = "line";
+ break;
+ case kMTCharWise:
+ type = "char";
+ break;
+ case kMTBlockWise:
+ type = "block";
+ break;
+ default:
+ type = "unknown";
+ }
+
+ tv_dict_add_str(dict, S_LEN("type"), type);
+ if (yankreg->additional_data) {
+ tv_dict_add_dict(dict, S_LEN("additional_data"), yankreg->additional_data);
+ }
+
+ list_T *const lines = tv_list_alloc((long)yankreg->y_size);
+
+ size_t i;
+ for (i = 0; i < yankreg->y_size; ++ i) {
+ tv_list_append_string(
+ lines, yankreg->y_array[i], (long)strlen(yankreg->y_array[i]));
+ }
+
+ tv_dict_add_list(dict, S_LEN("lines"), lines);
+
+ return dict;
+}
+
+/*
+ * Executes the yank() function on a user-defined register to set the contents
+ * of that register.
+ */
+static int eval_yank_userreg(const char *ufn, int regname, yankreg_T *reg)
+{
+ if (!reg)
+ return -1;
+
+ int ret, len;
+ char regname_str[5];
+
+ len = (*utf_char2len)(regname);
+ regname_str[len] = 0;
+ utf_char2bytes(regname, regname_str);
+
+ typval_T args[4];
+ args[0].v_type = VAR_STRING;
+ args[1].v_type = VAR_STRING;
+ args[2].v_type = VAR_DICT;
+ args[3].v_type = VAR_UNKNOWN;
+
+ args[0].vval.v_string = "yank";
+ args[1].vval.v_string = regname_str;
+ args[2].vval.v_dict = yankreg_to_dict(reg);
+
+ funcexe_T funcexe = FUNCEXE_INIT;
+ funcexe.fe_evaluate = true;
+
+ typval_T* out = xmalloc(sizeof(typval_T));
+ return call_func(
+ ufn,
+ -1,
+ out,
+ /* argcount_in = */ 3,
+ args,
+ &funcexe
+ );
+
+ tv_free(out);
+ return ret;
+}
+
/// If "regname" is a special register, return true and store a pointer to its
/// value in "argp".
///
@@ -1367,6 +1637,9 @@ bool get_spec_reg(int regname, char **argp, bool *allocated, bool errmsg)
case '_': // black hole: always empty
*argp = "";
return true;
+
+ default:
+ break;
}
return false;
@@ -1413,14 +1686,14 @@ bool cmdline_paste_reg(int regname, bool literally_arg, bool remcr)
/// Shift the delete registers: "9 is cleared, "8 becomes "9, etc.
static void shift_delete_registers(bool y_append)
{
- free_register(&y_regs[9]); // free register "9
+ free_register(get_global_reg(9)); // free register "9
for (int n = 9; n > 1; n--) {
- y_regs[n] = y_regs[n - 1];
+ *get_global_reg(n) = *get_global_reg(n - 1);
}
if (!y_append) {
- y_previous = &y_regs[1];
+ y_previous = get_global_reg(1);
}
- y_regs[1].y_array = NULL; // set register "1 to empty
+ get_global_reg(1)->y_array = NULL; // set register "1 to empty
}
/// Handle a delete operation.
@@ -1513,7 +1786,7 @@ int op_delete(oparg_T *oap)
if (oap->motion_type == kMTLineWise || oap->line_count > 1 || oap->use_reg_one) {
shift_delete_registers(is_append_register(oap->regname));
- reg = &y_regs[1];
+ reg = get_global_reg(1);
op_yank_reg(oap, false, reg, false);
did_yank = true;
}
@@ -2520,11 +2793,20 @@ int op_change(oparg_T *oap)
return retval;
}
+
+/*
+ * set all the yank registers to empty (called from main())
+ */
+void init_yank(void)
+{
+ init_yankmap(&y_regs.inner);
+}
+
#if defined(EXITFREE)
void clear_registers(void)
{
for (int i = 0; i < NUM_REGISTERS; i++) {
- free_register(&y_regs[i]);
+ free_register(get_global_reg(i));
}
}
@@ -2570,6 +2852,14 @@ bool op_yank(oparg_T *oap, bool message)
yankreg_T *reg = get_yank_register(oap->regname, YREG_YANK);
op_yank_reg(oap, message, reg, is_append_register(oap->regname));
+
+ if (get_userreg(oap->regname) != -1) {
+ if (eval_yank_userreg(curbuf->b_p_urf, oap->regname, reg) == -1) {
+ beep_flush();
+ return false;
+ }
+ }
+
set_clipboard(oap->regname, reg);
do_autocmd_textyankpost(oap, reg);
@@ -2748,7 +3038,11 @@ static void op_yank_reg(oparg_T *oap, bool message, yankreg_T *reg, bool append)
if (oap->regname == NUL) {
*namebuf = NUL;
} else {
- vim_snprintf(namebuf, sizeof(namebuf), _(" into \"%c"), oap->regname);
+ char buf[5];
+ int len = (*utf_char2len) (oap->regname);
+ utf_char2bytes(oap->regname, buf);
+ buf[len] = 0;
+ vim_snprintf(namebuf, sizeof(namebuf), _(" into \"%s"), buf);
}
// redisplay now, so message is not deleted
@@ -2818,6 +3112,7 @@ static void do_autocmd_textyankpost(oparg_T *oap, yankreg_T *reg)
FUNC_ATTR_NONNULL_ALL
{
static bool recursive = false;
+ int len;
if (recursive || !has_event(EVENT_TEXTYANKPOST)) {
// No autocommand was defined, or we yanked from this autocommand.
@@ -2839,13 +3134,15 @@ static void do_autocmd_textyankpost(oparg_T *oap, yankreg_T *reg)
(void)tv_dict_add_list(dict, S_LEN("regcontents"), list);
// Register type.
- char buf[NUMBUFLEN + 2];
+ char buf[NUMBUFLEN + 6];
format_reg_type(reg->y_type, reg->y_width, buf, ARRAY_SIZE(buf));
(void)tv_dict_add_str(dict, S_LEN("regtype"), buf);
// Name of requested register, or empty string for unnamed operation.
- buf[0] = (char)oap->regname;
- buf[1] = NUL;
+ len = (*utf_char2len)(oap->regname);
+ buf[len] = 0;
+ utf_char2bytes(oap->regname, buf);
+ recursive = true;
(void)tv_dict_add_str(dict, S_LEN("regname"), buf);
// Motion type: inclusive or exclusive.
@@ -3050,6 +3347,10 @@ void do_put(int regname, yankreg_T *reg, int dir, int count, int flags)
reg = get_yank_register(regname, YREG_PASTE);
}
+ if (get_userreg(regname) != -1) {
+ copy_userreg(reg, regname);
+ }
+
y_type = reg->y_type;
y_width = reg->y_width;
y_size = reg->y_size;
@@ -3724,7 +4025,7 @@ int get_register_name(int num)
/// @return the index of the register "" points to.
int get_unname_register(void)
{
- return y_previous == NULL ? -1 : (int)(y_previous - &y_regs[0]);
+ return yankmap_find(&y_regs.inner, y_previous);
}
/// ":dis" and ":registers": Display the contents of the yank registers.
@@ -3761,10 +4062,10 @@ void ex_display(exarg_T *eap)
if (y_previous != NULL) {
yb = y_previous;
} else {
- yb = &(y_regs[0]);
+ yb = get_global_reg(0);
}
} else {
- yb = &(y_regs[i]);
+ yb = get_global_reg(i);
}
get_clipboard(name, &yb, true);
@@ -4957,6 +5258,10 @@ static yankreg_T *init_write_reg(int name, yankreg_T **old_y_previous, bool must
static void finish_write_reg(int name, yankreg_T *reg, yankreg_T *old_y_previous)
{
+ if (get_userreg(name) != -1) {
+ eval_yank_userreg(curbuf->b_p_urf, name, reg);
+ }
+
// Send text of clipboard register to the clipboard.
set_clipboard(name, reg);
@@ -6409,7 +6714,7 @@ static yankreg_T *adjust_clipboard_name(int *name, bool quiet, bool writing)
}
if (explicit_cb_reg) {
- target = &y_regs[*name == '*' ? STAR_REGISTER : PLUS_REGISTER];
+ target = get_global_reg(*name == '*' ? STAR_REGISTER : PLUS_REGISTER);
if (writing && (cb_flags & (*name == '*' ? CB_UNNAMED : CB_UNNAMEDPLUS))) {
clipboard_needs_update = false;
}
@@ -6426,10 +6731,10 @@ static yankreg_T *adjust_clipboard_name(int *name, bool quiet, bool writing)
if (cb_flags & CB_UNNAMEDPLUS) {
*name = (cb_flags & CB_UNNAMED && writing) ? '"' : '+';
- target = &y_regs[PLUS_REGISTER];
+ target = get_global_reg(PLUS_REGISTER);
} else {
*name = '*';
- target = &y_regs[STAR_REGISTER];
+ target = get_global_reg(STAR_REGISTER);
}
goto end;
}
@@ -6745,11 +7050,11 @@ static inline bool reg_empty(const yankreg_T *const reg)
/// Iterate over global registers.
///
/// @see op_register_iter
-const void *op_global_reg_iter(const void *const iter, char *const name, yankreg_T *const reg,
- bool *is_unnamed)
+iter_register_T op_global_reg_iter(iter_register_T iter, char *const name,
+ yankreg_T *const reg, bool *is_unnamed)
FUNC_ATTR_NONNULL_ARG(2, 3, 4) FUNC_ATTR_WARN_UNUSED_RESULT
{
- return op_reg_iter(iter, y_regs, name, reg, is_unnamed);
+ return op_reg_iter(iter, &y_regs, name, reg, is_unnamed);
}
/// Iterate over registers `regs`.
@@ -6761,30 +7066,33 @@ const void *op_global_reg_iter(const void *const iter, char *const name, yankreg
///
/// @return Pointer that must be passed to next `op_register_iter` call or
/// NULL if iteration is over.
-const void *op_reg_iter(const void *const iter, const yankreg_T *const regs, char *const name,
- yankreg_T *const reg, bool *is_unnamed)
+iter_register_T op_reg_iter(iter_register_T iter, yank_registers_T *regs,
+ char *const name, yankreg_T *const reg,
+ bool *is_unnamed)
FUNC_ATTR_NONNULL_ARG(3, 4, 5) FUNC_ATTR_WARN_UNUSED_RESULT
{
*name = NUL;
- const yankreg_T *iter_reg = (iter == NULL
- ? &(regs[0])
- : (const yankreg_T *const)iter);
- while (iter_reg - &(regs[0]) < NUM_SAVED_REGISTERS && reg_empty(iter_reg)) {
- iter_reg++;
+ int iter_idx = (int)(iter == ITER_REGISTER_NULL ? 0 : iter - 1);
+
+ while (iter_idx < NUM_SAVED_REGISTERS && reg_empty(get_reg(regs, iter_idx))) {
+ ++iter_idx;
}
- if (iter_reg - &(regs[0]) == NUM_SAVED_REGISTERS || reg_empty(iter_reg)) {
- return NULL;
+
+ if (iter_idx >= NUM_SAVED_REGISTERS || reg_empty(get_reg(regs, iter_idx))) {
+ return ITER_REGISTER_NULL;
}
- int iter_off = (int)(iter_reg - &(regs[0]));
- *name = (char)get_register_name(iter_off);
- *reg = *iter_reg;
- *is_unnamed = (iter_reg == y_previous);
- while (++iter_reg - &(regs[0]) < NUM_SAVED_REGISTERS) {
- if (!reg_empty(iter_reg)) {
- return (void *)iter_reg;
+
+ *reg = *get_reg(regs, iter_idx);
+ *name = (char) get_register_name(iter_idx);
+ *is_unnamed = (get_reg(regs, iter_idx) == y_previous);
+
+ while (++iter_idx < NUM_SAVED_REGISTERS) {
+ if (!reg_empty(get_reg(regs, iter_idx))) {
+ return iter_idx + 1;
}
}
- return NULL;
+
+ return ITER_REGISTER_NULL;
}
/// Get a number of non-empty registers
@@ -6792,8 +7100,8 @@ size_t op_reg_amount(void)
FUNC_ATTR_WARN_UNUSED_RESULT
{
size_t ret = 0;
- for (size_t i = 0; i < NUM_SAVED_REGISTERS; i++) {
- if (!reg_empty(y_regs + i)) {
+ for (int i = 0; i < NUM_SAVED_REGISTERS; i++) {
+ if (!reg_empty(get_global_reg(i))) {
ret++;
}
}
@@ -6813,11 +7121,11 @@ bool op_reg_set(const char name, const yankreg_T reg, bool is_unnamed)
if (i == -1) {
return false;
}
- free_register(&y_regs[i]);
- y_regs[i] = reg;
+ free_register(get_global_reg(i));
+ *get_global_reg(i) = reg;
if (is_unnamed) {
- y_previous = &y_regs[i];
+ y_previous = get_global_reg(i);
}
return true;
}
@@ -6833,7 +7141,7 @@ const yankreg_T *op_reg_get(const char name)
if (i == -1) {
return NULL;
}
- return &y_regs[i];
+ return get_global_reg(i);
}
/// Set the previous yank register
@@ -6848,7 +7156,7 @@ bool op_reg_set_previous(const char name)
return false;
}
- y_previous = &y_regs[i];
+ y_previous = get_global_reg(i);
return true;
}
diff --git a/src/nvim/ops.h b/src/nvim/ops.h
index 4dab51b15d..519b946f6d 100644
--- a/src/nvim/ops.h
+++ b/src/nvim/ops.h
@@ -19,6 +19,7 @@ typedef int (*Indenter)(void);
/// flags for do_put()
enum {
+ ITER_REGISTER_NULL = 0,
PUT_FIXINDENT = 1, ///< make indent look nice
PUT_CURSEND = 2, ///< leave cursor after end of new text
PUT_CURSLINE = 4, ///< leave cursor on last line of new text
@@ -42,6 +43,7 @@ enum {
STAR_REGISTER = 37,
PLUS_REGISTER = 38,
NUM_REGISTERS = 39,
+ USER_REGISTERS_START = 39
};
/// Operator IDs; The order must correspond to opchars[] in ops.c!
@@ -101,6 +103,8 @@ typedef enum {
YREG_YANK,
YREG_PUT,
} yreg_mode_t;
+/// Returns a reference to a user-defined register.
+int get_userreg(const int regname);
static inline int op_reg_index(int regname)
REAL_FATTR_CONST;
@@ -125,13 +129,18 @@ static inline int op_reg_index(const int regname)
} else if (regname == '+') {
return PLUS_REGISTER;
} else {
- return -1;
+ return get_userreg(regname);
}
}
static inline bool is_literal_register(int regname)
REAL_FATTR_CONST;
+struct yank_registers;
+typedef struct yank_registers yank_registers_T;
+
+typedef size_t iter_register_T;
+
/// @see get_yank_register
/// @return true when register should be inserted literally
/// (selection or clipboard)
diff --git a/src/nvim/option.c b/src/nvim/option.c
index 882722a575..fd4f1eb50f 100644
--- a/src/nvim/option.c
+++ b/src/nvim/option.c
@@ -24,8 +24,6 @@
#include <stdlib.h>
#include <string.h>
-#include "auto/config.h"
-#include "klib/kvec.h"
#include "nvim/api/extmark.h"
#include "nvim/api/private/defs.h"
#include "nvim/api/private/helpers.h"
@@ -98,22 +96,20 @@
#include "nvim/vim_defs.h"
#include "nvim/window.h"
+#include "auto/config.h"
+#include "klib/kvec.h"
+
#ifdef BACKSLASH_IN_FILENAME
# include "nvim/arglist.h"
#endif
-static const char e_unknown_option[]
- = N_("E518: Unknown option");
-static const char e_not_allowed_in_modeline[]
- = N_("E520: Not allowed in a modeline");
+static const char e_unknown_option[] = N_("E518: Unknown option");
+static const char e_not_allowed_in_modeline[] = N_("E520: Not allowed in a modeline");
static const char e_not_allowed_in_modeline_when_modelineexpr_is_off[]
= N_("E992: Not allowed in a modeline when 'modelineexpr' is off");
-static const char e_key_code_not_set[]
- = N_("E846: Key code not set");
-static const char e_number_required_after_equal[]
- = N_("E521: Number required after =");
-static const char e_preview_window_already_exists[]
- = N_("E590: A preview window already exists");
+static const char e_key_code_not_set[] = N_("E846: Key code not set");
+static const char e_number_required_after_equal[] = N_("E521: Number required after =");
+static const char e_preview_window_already_exists[] = N_("E590: A preview window already exists");
static char *p_term = NULL;
static char *p_ttytype = NULL;
@@ -156,13 +152,10 @@ typedef enum {
# include "options.generated.h"
#endif
-static char *(p_bin_dep_opts[]) = {
- "textwidth", "wrapmargin", "modeline", "expandtab", NULL
-};
-static char *(p_paste_dep_opts[]) = {
- "autoindent", "expandtab", "ruler", "showmatch", "smarttab",
- "softtabstop", "textwidth", "wrapmargin", "revins", "varsofttabstop", NULL
-};
+static char *(p_bin_dep_opts[]) = { "textwidth", "wrapmargin", "modeline", "expandtab", NULL };
+static char *(p_paste_dep_opts[])
+ = { "autoindent", "expandtab", "ruler", "showmatch", "smarttab", "softtabstop",
+ "textwidth", "wrapmargin", "revins", "varsofttabstop", NULL };
void set_init_tablocal(void)
{
@@ -225,8 +218,7 @@ static void set_init_default_backupskip(void)
xstrlcpy(item, p, len);
add_pathsep(item);
xstrlcat(item, "*", len);
- if (find_dup_item(ga.ga_data, item, options[opt_idx].flags)
- == NULL) {
+ if (find_dup_item(ga.ga_data, item, options[opt_idx].flags) == NULL) {
ga_grow(&ga, (int)len);
if (!GA_EMPTY(&ga)) {
STRCAT(ga.ga_data, ",");
@@ -256,7 +248,7 @@ static void set_init_default_cdpath(void)
}
char *buf = xmalloc(2 * strlen(cdpath) + 2);
- buf[0] = ','; // start with ",", current dir first
+ buf[0] = ','; // start with ",", current dir first
int j = 1;
for (int i = 0; cdpath[i] != NUL; i++) {
if (vim_ispathlistsep(cdpath[i])) {
@@ -274,7 +266,7 @@ static void set_init_default_cdpath(void)
options[opt_idx].def_val = buf;
options[opt_idx].flags |= P_DEF_ALLOCED;
} else {
- xfree(buf); // cannot happen
+ xfree(buf); // cannot happen
}
xfree(cdpath);
}
@@ -347,12 +339,9 @@ void set_init_1(bool clean_arg)
memmove(backupdir + 2, backupdir, backupdir_len + 1);
memmove(backupdir, ".,", 2);
set_string_default("backupdir", backupdir, true);
- set_string_default("viewdir", stdpaths_user_state_subpath("view", 2, true),
- true);
- set_string_default("directory", stdpaths_user_state_subpath("swap", 2, true),
- true);
- set_string_default("undodir", stdpaths_user_state_subpath("undo", 2, true),
- true);
+ set_string_default("viewdir", stdpaths_user_state_subpath("view", 2, true), true);
+ set_string_default("directory", stdpaths_user_state_subpath("swap", 2, true), true);
+ set_string_default("undodir", stdpaths_user_state_subpath("undo", 2, true), true);
// Set default for &runtimepath. All necessary expansions are performed in
// this function.
char *rtp = runtimepath_default(clean_arg);
@@ -368,7 +357,7 @@ void set_init_1(bool clean_arg)
set_options_default(0);
curbuf->b_p_initialized = true;
- curbuf->b_p_ar = -1; // no local 'autoread' value
+ curbuf->b_p_ar = -1; // no local 'autoread' value
curbuf->b_p_ul = NO_LOCAL_UNDOLEVEL;
check_buf_options(curbuf);
check_win_options(curwin);
@@ -390,7 +379,7 @@ void set_init_1(bool clean_arg)
// Expand environment variables and things like "~" for the defaults.
set_init_expand_env();
- save_file_ff(curbuf); // Buffer is unchanged
+ save_file_ff(curbuf); // Buffer is unchanged
// Detect use of mlterm.
// Mlterm is a terminal emulator akin to xterm that has some special
@@ -428,7 +417,7 @@ static void set_option_default(const int opt_idx, int opt_flags)
vimoption_T *opt = &options[opt_idx];
void *varp = get_varp_scope(opt, both ? OPT_LOCAL : opt_flags);
uint32_t flags = opt->flags;
- if (varp != NULL) { // skip hidden option, nothing to do for it
+ if (varp != NULL) { // skip hidden option, nothing to do for it
if (flags & P_STRING) {
// Use set_string_option_direct() for local options to handle
// freeing and allocating the value.
@@ -446,8 +435,7 @@ static void set_option_default(const int opt_idx, int opt_flags)
win_comp_scroll(curwin);
} else {
OptInt def_val = (OptInt)(intptr_t)opt->def_val;
- if ((OptInt *)varp == &curwin->w_p_so
- || (OptInt *)varp == &curwin->w_p_siso) {
+ if ((OptInt *)varp == &curwin->w_p_so || (OptInt *)varp == &curwin->w_p_siso) {
// 'scrolloff' and 'sidescrolloff' local values have a
// different default value than the global default.
*(OptInt *)varp = -1;
@@ -469,8 +457,7 @@ static void set_option_default(const int opt_idx, int opt_flags)
#endif
// May also set global value for local option.
if (both) {
- *(int *)get_varp_scope(opt, OPT_GLOBAL) =
- *(int *)varp;
+ *(int *)get_varp_scope(opt, OPT_GLOBAL) = *(int *)varp;
}
}
@@ -507,8 +494,7 @@ static void set_options_default(int opt_flags)
/// @param name The name of the option
/// @param val The value of the option
/// @param allocated If true, do not copy default as it was already allocated.
-static void set_string_default(const char *name, char *val, bool allocated)
- FUNC_ATTR_NONNULL_ALL
+static void set_string_default(const char *name, char *val, bool allocated) FUNC_ATTR_NONNULL_ALL
{
int opt_idx = findoption(name);
if (opt_idx >= 0) {
@@ -543,8 +529,7 @@ static char *find_dup_item(char *origval, const char *newval, uint32_t flags)
// Count backslashes. Only a comma with an even number of backslashes
// or a single backslash preceded by a comma before it is recognized as
// a separator.
- if ((s > origval + 1 && s[-1] == '\\' && s[-2] != ',')
- || (s == origval + 1 && s[-1] == '\\')) {
+ if ((s > origval + 1 && s[-1] == '\\' && s[-2] != ',') || (s == origval + 1 && s[-1] == '\\')) {
bs++;
} else {
bs = 0;
@@ -611,19 +596,15 @@ void set_init_2(bool headless)
/// Initialize the options, part three: After reading the .vimrc
void set_init_3(void)
{
- parse_shape_opt(SHAPE_CURSOR); // set cursor shapes from 'guicursor'
+ parse_shape_opt(SHAPE_CURSOR); // set cursor shapes from 'guicursor'
// Set 'shellpipe' and 'shellredir', depending on the 'shell' option.
// This is done after other initializations, where 'shell' might have been
// set, but only if they have not been set before.
int idx_srr = findoption("srr");
- int do_srr = (idx_srr < 0)
- ? false
- : !(options[idx_srr].flags & P_WAS_SET);
+ int do_srr = (idx_srr < 0) ? false : !(options[idx_srr].flags & P_WAS_SET);
int idx_sp = findoption("sp");
- int do_sp = (idx_sp < 0)
- ? false
- : !(options[idx_sp].flags & P_WAS_SET);
+ int do_sp = (idx_sp < 0) ? false : !(options[idx_sp].flags & P_WAS_SET);
size_t len = 0;
char *p = (char *)invocation_path_tail(p_sh, &len);
@@ -634,8 +615,7 @@ void set_init_3(void)
// Default for p_sp is "| tee", for p_srr is ">".
// For known shells it is changed here to include stderr.
//
- if (path_fnamecmp(p, "csh") == 0
- || path_fnamecmp(p, "tcsh") == 0) {
+ if (path_fnamecmp(p, "csh") == 0 || path_fnamecmp(p, "tcsh") == 0) {
if (do_sp) {
p_sp = "|& tee";
options[idx_sp].def_val = p_sp;
@@ -644,16 +624,11 @@ void set_init_3(void)
p_srr = ">&";
options[idx_srr].def_val = p_srr;
}
- } else if (path_fnamecmp(p, "sh") == 0
- || path_fnamecmp(p, "ksh") == 0
- || path_fnamecmp(p, "mksh") == 0
- || path_fnamecmp(p, "pdksh") == 0
- || path_fnamecmp(p, "zsh") == 0
- || path_fnamecmp(p, "zsh-beta") == 0
- || path_fnamecmp(p, "bash") == 0
- || path_fnamecmp(p, "fish") == 0
- || path_fnamecmp(p, "ash") == 0
- || path_fnamecmp(p, "dash") == 0) {
+ } else if (path_fnamecmp(p, "sh") == 0 || path_fnamecmp(p, "ksh") == 0
+ || path_fnamecmp(p, "mksh") == 0 || path_fnamecmp(p, "pdksh") == 0
+ || path_fnamecmp(p, "zsh") == 0 || path_fnamecmp(p, "zsh-beta") == 0
+ || path_fnamecmp(p, "bash") == 0 || path_fnamecmp(p, "fish") == 0
+ || path_fnamecmp(p, "ash") == 0 || path_fnamecmp(p, "dash") == 0) {
// Always use POSIX shell style redirection if we reach this
if (do_sp) {
p_sp = "2>&1| tee";
@@ -795,13 +770,10 @@ static char *stropt_copy_value(char *origval, char **argp, set_op_T op,
while (*arg != NUL && !ascii_iswhite(*arg)) {
if (*arg == '\\' && arg[1] != NUL
#ifdef BACKSLASH_IN_FILENAME
- && !((flags & P_EXPAND)
- && vim_isfilec((uint8_t)arg[1])
- && !ascii_iswhite(arg[1])
- && (arg[1] != '\\'
- || (s == newval && arg[2] != '\\')))
+ && !((flags & P_EXPAND) && vim_isfilec((uint8_t)arg[1]) && !ascii_iswhite(arg[1])
+ && (arg[1] != '\\' || (s == newval && arg[2] != '\\')))
#endif
- ) {
+ ) {
arg++; // remove backslash
}
int i = utfc_ptr2len(arg);
@@ -848,9 +820,7 @@ static void stropt_concat_with_comma(char *origval, char *newval, set_op_T op, u
if (op == OP_ADDING) {
len = (int)strlen(origval);
// Strip a trailing comma, would get 2.
- if (comma && len > 1
- && (flags & P_ONECOMMA) == P_ONECOMMA
- && origval[len - 1] == ','
+ if (comma && len > 1 && (flags & P_ONECOMMA) == P_ONECOMMA && origval[len - 1] == ','
&& origval[len - 2] != '\\') {
len--;
}
@@ -898,15 +868,13 @@ static void stropt_remove_dupflags(char *newval, uint32_t flags)
for (s = newval; *s;) {
// if options have P_FLAGLIST and P_ONECOMMA such as 'whichwrap'
if (flags & P_ONECOMMA) {
- if (*s != ',' && *(s + 1) == ','
- && vim_strchr(s + 2, (uint8_t)(*s)) != NULL) {
+ if (*s != ',' && *(s + 1) == ',' && vim_strchr(s + 2, (uint8_t)(*s)) != NULL) {
// Remove the duplicated value and the next comma.
STRMOVE(s, s + 2);
continue;
}
} else {
- if ((!(flags & P_COMMA) || *s != ',')
- && vim_strchr(s + 1, (uint8_t)(*s)) != NULL) {
+ if ((!(flags & P_COMMA) || *s != ',') && vim_strchr(s + 1, (uint8_t)(*s)) != NULL) {
STRMOVE(s, s + 1);
continue;
}
@@ -1000,11 +968,11 @@ static set_op_T get_op(const char *arg)
set_op_T op = OP_NONE;
if (*arg != NUL && *(arg + 1) == '=') {
if (*arg == '+') {
- op = OP_ADDING; // "+="
+ op = OP_ADDING; // "+="
} else if (*arg == '^') {
- op = OP_PREPENDING; // "^="
+ op = OP_PREPENDING; // "^="
} else if (*arg == '-') {
- op = OP_REMOVING; // "-="
+ op = OP_REMOVING; // "-="
}
}
return op;
@@ -1090,14 +1058,12 @@ static int validate_opt_idx(win_T *win, int opt_idx, int opt_flags, uint32_t fla
// Skip all options that are not window-local (used when showing
// an already loaded buffer in a window).
- if ((opt_flags & OPT_WINONLY)
- && (opt_idx < 0 || options[opt_idx].var != VAR_WIN)) {
+ if ((opt_flags & OPT_WINONLY) && (opt_idx < 0 || options[opt_idx].var != VAR_WIN)) {
return FAIL;
}
// Skip all options that are window-local (used for :vimgrep).
- if ((opt_flags & OPT_NOWIN) && opt_idx >= 0
- && options[opt_idx].var == VAR_WIN) {
+ if ((opt_flags & OPT_NOWIN) && opt_idx >= 0 && options[opt_idx].var == VAR_WIN) {
return FAIL;
}
@@ -1114,10 +1080,8 @@ static int validate_opt_idx(win_T *win, int opt_idx, int opt_flags, uint32_t fla
// In diff mode some options are overruled. This avoids that
// 'foldmethod' becomes "marker" instead of "diff" and that
// "wrap" gets set.
- if (win->w_p_diff
- && opt_idx >= 0 // shut up coverity warning
- && (options[opt_idx].indir == PV_FDM
- || options[opt_idx].indir == PV_WRAP)) {
+ if (win->w_p_diff && opt_idx >= 0 // shut up coverity warning
+ && (options[opt_idx].indir == PV_FDM || options[opt_idx].indir == PV_WRAP)) {
return FAIL;
}
}
@@ -1134,8 +1098,8 @@ static int validate_opt_idx(win_T *win, int opt_idx, int opt_flags, uint32_t fla
/// Get new option value from argp. Allocated OptVal must be freed by caller.
static OptVal get_option_newval(int opt_idx, int opt_flags, set_prefix_T prefix, char **argp,
int nextchar, set_op_T op, uint32_t flags, void *varp, char *errbuf,
- const size_t errbuflen, const char **errmsg)
- FUNC_ATTR_WARN_UNUSED_RESULT
+ const size_t errbuflen,
+ const char **errmsg) FUNC_ATTR_WARN_UNUSED_RESULT
{
assert(varp != NULL);
@@ -1293,21 +1257,20 @@ static void do_one_set_option(int opt_flags, char **argp, bool *did_show, char *
uint8_t nextchar = (uint8_t)arg[len]; // next non-white char after option name
- if (opt_idx == -1 && key == 0) { // found a mismatch: skip
+ if (opt_idx == -1 && key == 0) { // found a mismatch: skip
*errmsg = e_unknown_option;
return;
}
- uint32_t flags; // flags for current option
+ uint32_t flags; // flags for current option
void *varp = NULL; // pointer to variable for current option
if (opt_idx >= 0) {
- if (options[opt_idx].var == NULL) { // hidden option: skip
+ if (options[opt_idx].var == NULL) { // hidden option: skip
// Only give an error message when requesting the value of
// a hidden option, ignore setting it.
if (vim_strchr("=:!&<", nextchar) == NULL
- && (!(options[opt_idx].flags & P_BOOL)
- || nextchar == '?')) {
+ && (!(options[opt_idx].flags & P_BOOL) || nextchar == '?')) {
*errmsg = e_unsupportedoption;
}
return;
@@ -1332,8 +1295,7 @@ static void do_one_set_option(int opt_flags, char **argp, bool *did_show, char *
*argp += 2;
}
}
- if (vim_strchr("?!&<", nextchar) != NULL
- && (*argp)[1] != NUL && !ascii_iswhite((*argp)[1])) {
+ if (vim_strchr("?!&<", nextchar) != NULL && (*argp)[1] != NUL && !ascii_iswhite((*argp)[1])) {
*errmsg = e_trailing;
return;
}
@@ -1344,15 +1306,13 @@ static void do_one_set_option(int opt_flags, char **argp, bool *did_show, char *
// '=' character per "set" command line. grrr. (jw)
//
if (nextchar == '?'
- || (prefix == PREFIX_NONE
- && vim_strchr("=:&<", nextchar) == NULL
- && !(flags & P_BOOL))) {
+ || (prefix == PREFIX_NONE && vim_strchr("=:&<", nextchar) == NULL && !(flags & P_BOOL))) {
// print value
if (*did_show) {
- msg_putchar('\n'); // cursor below last one
+ msg_putchar('\n'); // cursor below last one
} else {
- gotocmdline(true); // cursor at status line
- *did_show = true; // remember that we did a line
+ gotocmdline(true); // cursor at status line
+ *did_show = true; // remember that we did a line
}
if (opt_idx >= 0) {
showoneopt(&options[opt_idx], opt_flags);
@@ -1425,15 +1385,14 @@ static void do_one_set_option(int opt_flags, char **argp, bool *did_show, char *
/// @return FAIL if an error is detected, OK otherwise
int do_set(char *arg, int opt_flags)
{
- bool did_show = false; // already showed one value
+ bool did_show = false; // already showed one value
if (*arg == NUL) {
showoptions(false, opt_flags);
did_show = true;
} else {
- while (*arg != NUL) { // loop to process all options
- if (strncmp(arg, "all", 3) == 0 && !ASCII_ISALPHA(arg[3])
- && !(opt_flags & OPT_MODELINE)) {
+ while (*arg != NUL) { // loop to process all options
+ if (strncmp(arg, "all", 3) == 0 && !ASCII_ISALPHA(arg[3]) && !(opt_flags & OPT_MODELINE)) {
// ":set all" show all options.
// ":set all&" set all options to their default value.
arg += 3;
@@ -1450,7 +1409,7 @@ int do_set(char *arg, int opt_flags)
did_show = true;
}
} else {
- char *startarg = arg; // remember for error message
+ char *startarg = arg; // remember for error message
const char *errmsg = NULL;
char errbuf[80];
@@ -1481,8 +1440,8 @@ int do_set(char *arg, int opt_flags)
// make sure all characters are printable
trans_characters(IObuff, IOSIZE);
- no_wait_return++; // wait_return() done later
- emsg(IObuff); // show error highlighted
+ no_wait_return++; // wait_return() done later
+ emsg(IObuff); // show error highlighted
no_wait_return--;
return FAIL;
@@ -1496,10 +1455,10 @@ int do_set(char *arg, int opt_flags)
if (silent_mode && did_show) {
// After displaying option values in silent mode.
silent_mode = false;
- info_message = true; // use os_msg(), not os_errmsg()
+ info_message = true; // use os_msg(), not os_errmsg()
msg_putchar('\n');
silent_mode = true;
- info_message = false; // use os_msg(), not os_errmsg()
+ info_message = false; // use os_msg(), not os_errmsg()
}
return OK;
@@ -1537,7 +1496,7 @@ void set_options_bin(int oldval, int newval, int opt_flags)
// The option values that are changed when 'bin' changes are
// copied when 'bin is set and restored when 'bin' is reset.
if (newval) {
- if (!oldval) { // switched on
+ if (!oldval) { // switched on
if (!(opt_flags & OPT_GLOBAL)) {
curbuf->b_p_tw_nobin = curbuf->b_p_tw;
curbuf->b_p_wm_nobin = curbuf->b_p_wm;
@@ -1553,19 +1512,19 @@ void set_options_bin(int oldval, int newval, int opt_flags)
}
if (!(opt_flags & OPT_GLOBAL)) {
- curbuf->b_p_tw = 0; // no automatic line wrap
- curbuf->b_p_wm = 0; // no automatic line wrap
- curbuf->b_p_ml = 0; // no modelines
- curbuf->b_p_et = 0; // no expandtab
+ curbuf->b_p_tw = 0; // no automatic line wrap
+ curbuf->b_p_wm = 0; // no automatic line wrap
+ curbuf->b_p_ml = 0; // no modelines
+ curbuf->b_p_et = 0; // no expandtab
}
if (!(opt_flags & OPT_LOCAL)) {
p_tw = 0;
p_wm = 0;
p_ml = false;
p_et = false;
- p_bin = true; // needed when called for the "-b" argument
+ p_bin = true; // needed when called for the "-b" argument
}
- } else if (oldval) { // switched off
+ } else if (oldval) { // switched off
if (!(opt_flags & OPT_GLOBAL)) {
curbuf->b_p_tw = curbuf->b_p_tw_nobin;
curbuf->b_p_wm = curbuf->b_p_wm_nobin;
@@ -1607,11 +1566,11 @@ char *find_shada_parameter(int type)
if (*p == type) {
return p + 1;
}
- if (*p == 'n') { // 'n' is always the last one
+ if (*p == 'n') { // 'n' is always the last one
break;
}
- p = vim_strchr(p, ','); // skip until next ','
- if (p == NULL) { // hit the end without finding parameter
+ p = vim_strchr(p, ','); // skip until next ','
+ if (p == NULL) { // hit the end without finding parameter
break;
}
}
@@ -1643,11 +1602,9 @@ static char *option_expand(int opt_idx, char *val)
// Escape spaces when expanding 'tags', they are used to separate file
// names.
// For 'spellsuggest' expand after "file:".
- expand_env_esc(val, NameBuff, MAXPATHL,
- (char **)options[opt_idx].var == &p_tags, false,
- (char **)options[opt_idx].var == &p_sps ? "file:"
- : NULL);
- if (strcmp(NameBuff, val) == 0) { // they are the same
+ expand_env_esc(val, NameBuff, MAXPATHL, (char **)options[opt_idx].var == &p_tags, false,
+ (char **)options[opt_idx].var == &p_sps ? "file:" : NULL);
+ if (strcmp(NameBuff, val) == 0) { // they are the same
return NULL;
}
@@ -1691,7 +1648,7 @@ static void didset_options2(void)
xfree(curbuf->b_p_vsts_array);
(void)tabstop_set(curbuf->b_p_vsts, &curbuf->b_p_vsts_array);
xfree(curbuf->b_p_vts_array);
- (void)tabstop_set(curbuf->b_p_vts, &curbuf->b_p_vts_array);
+ (void)tabstop_set(curbuf->b_p_vts, &curbuf->b_p_vts_array);
}
/// Check for string options that are NULL (normally only termcap options).
@@ -1762,8 +1719,7 @@ bool valid_name(const char *val, const char *allowed)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
for (const char *s = val; *s != NUL; s++) {
- if (!ASCII_ISALNUM(*s)
- && vim_strchr(allowed, (uint8_t)(*s)) == NULL) {
+ if (!ASCII_ISALNUM(*s) && vim_strchr(allowed, (uint8_t)(*s)) == NULL) {
return false;
}
}
@@ -1772,8 +1728,7 @@ bool valid_name(const char *val, const char *allowed)
void check_blending(win_T *wp)
{
- wp->w_grid_alloc.blending =
- wp->w_p_winbl > 0 || (wp->w_floating && wp->w_float_config.shadow);
+ wp->w_grid_alloc.blending = wp->w_p_winbl > 0 || (wp->w_floating && wp->w_float_config.shadow);
}
/// Handle setting `winhighlight' in window "wp"
@@ -1857,7 +1812,7 @@ void set_option_sctx_idx(int opt_idx, int opt_flags, sctx_T script_ctx)
// Remember where the option was set. For local options need to do that
// in the buffer or window structure.
- if (both || (opt_flags & OPT_GLOBAL) || (indir & (PV_BUF|PV_WIN)) == 0) {
+ if (both || (opt_flags & OPT_GLOBAL) || (indir & (PV_BUF | PV_WIN)) == 0) {
options[opt_idx].last_set = last_set;
}
if (both || (opt_flags & OPT_LOCAL)) {
@@ -2017,8 +1972,7 @@ static const char *did_set_buflisted(optset_T *args)
// when 'buflisted' changes, trigger autocommands
if (args->os_oldval.boolean != buf->b_p_bl) {
- apply_autocmds(buf->b_p_bl ? EVENT_BUFADD : EVENT_BUFDELETE,
- NULL, NULL, true, buf);
+ apply_autocmds(buf->b_p_bl ? EVENT_BUFADD : EVENT_BUFDELETE, NULL, NULL, true, buf);
}
return NULL;
}
@@ -2192,7 +2146,7 @@ static const char *did_set_lisp(optset_T *args)
{
buf_T *buf = (buf_T *)args->os_buf;
// When 'lisp' option changes include/exclude '-' in keyword characters.
- (void)buf_init_chartab(buf, false); // ignore errors
+ (void)buf_init_chartab(buf, false); // ignore errors
return NULL;
}
@@ -2261,9 +2215,8 @@ static const char *did_set_paste(optset_T *args FUNC_ATTR_UNUSED)
if (buf->b_p_vsts_nopaste) {
xfree(buf->b_p_vsts_nopaste);
}
- buf->b_p_vsts_nopaste = buf->b_p_vsts && buf->b_p_vsts != empty_string_option
- ? xstrdup(buf->b_p_vsts)
- : NULL;
+ buf->b_p_vsts_nopaste
+ = buf->b_p_vsts && buf->b_p_vsts != empty_string_option ? xstrdup(buf->b_p_vsts) : NULL;
}
// save global options
@@ -2287,11 +2240,11 @@ static const char *did_set_paste(optset_T *args FUNC_ATTR_UNUSED)
// already on.
// set options for each buffer
FOR_ALL_BUFFERS(buf) {
- buf->b_p_tw = 0; // textwidth is 0
- buf->b_p_wm = 0; // wrapmargin is 0
- buf->b_p_sts = 0; // softtabstop is 0
- buf->b_p_ai = 0; // no auto-indent
- buf->b_p_et = 0; // no expandtab
+ buf->b_p_tw = 0; // textwidth is 0
+ buf->b_p_wm = 0; // wrapmargin is 0
+ buf->b_p_sts = 0; // softtabstop is 0
+ buf->b_p_ai = 0; // no auto-indent
+ buf->b_p_et = 0; // no expandtab
if (buf->b_p_vsts) {
free_string_option(buf->b_p_vsts);
}
@@ -2300,13 +2253,13 @@ static const char *did_set_paste(optset_T *args FUNC_ATTR_UNUSED)
}
// set global options
- p_sm = 0; // no showmatch
- p_sta = 0; // no smarttab
+ p_sm = 0; // no showmatch
+ p_sta = 0; // no smarttab
if (p_ru) {
- status_redraw_all(); // redraw to remove the ruler
+ status_redraw_all(); // redraw to remove the ruler
}
- p_ru = 0; // no ruler
- p_ri = 0; // no reverse insert
+ p_ru = 0; // no ruler
+ p_ri = 0; // no reverse insert
// set global values for local buffer options
p_tw = 0;
p_wm = 0;
@@ -2343,7 +2296,7 @@ static const char *did_set_paste(optset_T *args FUNC_ATTR_UNUSED)
p_sm = save_sm;
p_sta = save_sta;
if (p_ru != save_ru) {
- status_redraw_all(); // redraw to draw the ruler
+ status_redraw_all(); // redraw to draw the ruler
}
p_ru = save_ru;
p_ri = save_ri;
@@ -2524,11 +2477,11 @@ static const char *did_set_swapfile(optset_T *args)
buf_T *buf = (buf_T *)args->os_buf;
// when 'swf' is set, create swapfile, when reset remove swapfile
if (buf->b_p_swf && p_uc) {
- ml_open_file(buf); // create the swap file
+ ml_open_file(buf); // create the swap file
} else {
// no need to reset curbuf->b_may_swap, ml_open_file() will check
// buf->b_p_swf
- mf_close_file(buf, true); // remove the swap file
+ mf_close_file(buf, true); // remove the swap file
}
return NULL;
}
@@ -2581,9 +2534,8 @@ static const char *did_set_undofile(optset_T *args)
// only for the current buffer: Try to read in the undofile,
// if one exists, the buffer wasn't changed and the buffer was
// loaded
- if ((curbuf == bp
- || (args->os_flags & OPT_GLOBAL) || args->os_flags == 0)
- && !bufIsChanged(bp) && bp->b_ml.ml_mfp != NULL) {
+ if ((curbuf == bp || (args->os_flags & OPT_GLOBAL) || args->os_flags == 0) && !bufIsChanged(bp)
+ && bp->b_ml.ml_mfp != NULL) {
u_compute_hash(bp, hash);
u_read_undo(NULL, hash, bp->b_fname);
}
@@ -2619,9 +2571,9 @@ static const char *did_set_undolevels(optset_T *args)
buf_T *buf = (buf_T *)args->os_buf;
OptInt *pp = (OptInt *)args->os_varp;
- if (pp == &p_ul) { // global 'undolevels'
+ if (pp == &p_ul) { // global 'undolevels'
did_set_global_undolevels(args->os_newval.number, args->os_oldval.number);
- } else if (pp == &curbuf->b_p_ul) { // buffer local 'undolevels'
+ } else if (pp == &curbuf->b_p_ul) { // buffer local 'undolevels'
did_set_buflocal_undolevels(buf, args->os_newval.number, args->os_oldval.number);
}
@@ -2728,8 +2680,8 @@ static void do_syntax_autocmd(buf_T *buf, bool value_changed)
syn_recursive++;
// Only pass true for "force" when the value changed or not used
// recursively, to avoid endless recurrence.
- apply_autocmds(EVENT_SYNTAX, buf->b_p_syn, buf->b_fname,
- value_changed || syn_recursive == 1, buf);
+ apply_autocmds(EVENT_SYNTAX, buf->b_p_syn, buf->b_fname, value_changed || syn_recursive == 1,
+ buf);
buf->b_flags |= BF_SYN_SET;
syn_recursive--;
}
@@ -3096,9 +3048,7 @@ int findoption_len(const char *const arg, const size_t len)
bool is_tty_option(const char *name)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
- return (name[0] == 't' && name[1] == '_')
- || strequal(name, "term")
- || strequal(name, "ttytype");
+ return (name[0] == 't' && name[1] == '_') || strequal(name, "term") || strequal(name, "ttytype");
}
#define TCO_BUFFER_SIZE 8
@@ -3169,8 +3119,7 @@ bool set_tty_option(const char *name, char *value)
/// @param[in] arg Option name.
///
/// @return Option index or -1 if option was not found.
-int findoption(const char *const arg)
- FUNC_ATTR_NONNULL_ALL
+int findoption(const char *const arg) FUNC_ATTR_NONNULL_ALL
{
return findoption_len(arg, strlen(arg));
}
@@ -3547,20 +3496,18 @@ static const char *did_set_option(int opt_idx, void *varp, OptVal old_value, Opt
bool free_oldval = (opt->flags & P_ALLOCED);
bool value_changed = false;
- optset_T did_set_cb_args = {
- .os_varp = varp,
- .os_idx = opt_idx,
- .os_flags = opt_flags,
- .os_oldval = old_value.data,
- .os_newval = new_value.data,
- .os_value_checked = false,
- .os_value_changed = false,
- .os_restore_chartab = false,
- .os_errbuf = errbuf,
- .os_errbuflen = errbuflen,
- .os_buf = curbuf,
- .os_win = curwin
- };
+ optset_T did_set_cb_args = { .os_varp = varp,
+ .os_idx = opt_idx,
+ .os_flags = opt_flags,
+ .os_oldval = old_value.data,
+ .os_newval = new_value.data,
+ .os_value_checked = false,
+ .os_value_changed = false,
+ .os_restore_chartab = false,
+ .os_errbuf = errbuf,
+ .os_errbuflen = errbuflen,
+ .os_buf = curbuf,
+ .os_win = curwin };
// Disallow changing immutable options.
if (opt->immutable && !optval_equal(old_value, new_value)) {
@@ -3614,8 +3561,8 @@ static const char *did_set_option(int opt_idx, void *varp, OptVal old_value, Opt
// Check the bound for num options.
if (new_value.type == kOptValTypeNumber) {
- errmsg = check_num_option_bounds((OptInt *)varp, old_value.data.number, errbuf, errbuflen,
- errmsg);
+ errmsg
+ = check_num_option_bounds((OptInt *)varp, old_value.data.number, errbuf, errbuflen, errmsg);
// Re-assign new_value because the new value was modified by the bound check.
new_value = optval_from_varp(opt_idx, varp);
}
@@ -3703,12 +3650,10 @@ static const char *set_option(const int opt_idx, void *varp, OptVal value, int o
vimoption_T *opt = &options[opt_idx];
- static const char *optval_type_names[] = {
- [kOptValTypeNil] = "Nil",
- [kOptValTypeBoolean] = "Boolean",
- [kOptValTypeNumber] = "Number",
- [kOptValTypeString] = "String"
- };
+ static const char *optval_type_names[] = { [kOptValTypeNil] = "Nil",
+ [kOptValTypeBoolean] = "Boolean",
+ [kOptValTypeNumber] = "Number",
+ [kOptValTypeString] = "String" };
if (value.type == kOptValTypeNil) {
// Don't try to unset local value if scope is global.
@@ -3898,8 +3843,8 @@ int find_key_option_len(const char *arg_arg, size_t len, bool has_lt)
} else if (has_lt) {
arg--; // put arg at the '<'
int modifiers = 0;
- key = find_special_key(&arg, len + 1, &modifiers,
- FSK_KEYCODE | FSK_KEEP_X_KEY | FSK_SIMPLIFY, NULL);
+ key = find_special_key(&arg, len + 1, &modifiers, FSK_KEYCODE | FSK_KEEP_X_KEY | FSK_SIMPLIFY,
+ NULL);
if (modifiers) { // can't handle modifiers here
key = 0;
}
@@ -3958,13 +3903,12 @@ static void showoptions(bool all, int opt_flags)
if (opt_flags & OPT_ONECOLUMN) {
len = Columns;
} else if (p->flags & P_BOOL) {
- len = 1; // a toggle option fits always
+ len = 1; // a toggle option fits always
} else {
option_value2string(p, opt_flags);
len = (int)strlen(p->fullname) + vim_strsize(NameBuff) + 1;
}
- if ((len <= INC - GAP && run == 1)
- || (len > INC - GAP && run == 2)) {
+ if ((len <= INC - GAP && run == 1) || (len > INC - GAP && run == 2)) {
items[item_count++] = p;
}
}
@@ -3974,26 +3918,24 @@ static void showoptions(bool all, int opt_flags)
// display the items
if (run == 1) {
- assert(Columns <= INT_MAX - GAP
- && Columns + GAP >= INT_MIN + 3
- && (Columns + GAP - 3) / INC >= INT_MIN
- && (Columns + GAP - 3) / INC <= INT_MAX);
+ assert(Columns <= INT_MAX - GAP && Columns + GAP >= INT_MIN + 3
+ && (Columns + GAP - 3) / INC >= INT_MIN && (Columns + GAP - 3) / INC <= INT_MAX);
int cols = (Columns + GAP - 3) / INC;
if (cols == 0) {
cols = 1;
}
rows = (item_count + cols - 1) / cols;
- } else { // run == 2
+ } else { // run == 2
rows = item_count;
}
for (int row = 0; row < rows && !got_int; row++) {
- msg_putchar('\n'); // go to next line
- if (got_int) { // 'q' typed in more
+ msg_putchar('\n'); // go to next line
+ if (got_int) { // 'q' typed in more
break;
}
int col = 0;
for (int i = row; i < item_count; i += rows) {
- msg_col = col; // make columns
+ msg_col = col; // make columns
showoneopt(items[i], opt_flags);
col += INC;
}
@@ -4007,7 +3949,7 @@ static void showoptions(bool all, int opt_flags)
static int optval_default(vimoption_T *p, const void *varp)
{
if (varp == NULL) {
- return true; // hidden option is always at default
+ return true; // hidden option is always at default
}
if (p->flags & P_NUM) {
return *(OptInt *)varp == (OptInt)(intptr_t)p->def_val;
@@ -4054,13 +3996,13 @@ static void showoneopt(vimoption_T *p, int opt_flags)
int save_silent = silent_mode;
silent_mode = false;
- info_message = true; // use os_msg(), not os_errmsg()
+ info_message = true; // use os_msg(), not os_errmsg()
void *varp = get_varp_scope(p, opt_flags);
// for 'modified' we also need to check if 'ff' or 'fenc' changed.
- if ((p->flags & P_BOOL) && ((int *)varp == &curbuf->b_changed
- ? !curbufIsChanged() : !*(int *)varp)) {
+ if ((p->flags & P_BOOL)
+ && ((int *)varp == &curbuf->b_changed ? !curbufIsChanged() : !*(int *)varp)) {
msg_puts("no");
} else if ((p->flags & P_BOOL) && *(int *)varp < 0) {
msg_puts("--");
@@ -4110,8 +4052,7 @@ int makeset(FILE *fd, int opt_flags, int local_only)
// P_PRI_MKRC flag and once without.
for (int pri = 1; pri >= 0; pri--) {
for (vimoption_T *p = &options[0]; p->fullname; p++) {
- if (!(p->flags & P_NO_MKRC)
- && ((pri == 1) == ((p->flags & P_PRI_MKRC) != 0))) {
+ if (!(p->flags & P_NO_MKRC) && ((pri == 1) == ((p->flags & P_PRI_MKRC) != 0))) {
// skip global option when only doing locals
if (p->indir == PV_NONE && !(opt_flags & OPT_GLOBAL)) {
continue;
@@ -4133,8 +4074,7 @@ int makeset(FILE *fd, int opt_flags, int local_only)
continue;
}
- if ((opt_flags & OPT_SKIPRTP)
- && (p->var == &p_rtp || p->var == &p_pp)) {
+ if ((opt_flags & OPT_SKIPRTP) && (p->var == &p_rtp || p->var == &p_pp)) {
continue;
}
@@ -4177,14 +4117,13 @@ int makeset(FILE *fd, int opt_flags, int local_only)
if (put_setnum(fd, cmd, p->fullname, (OptInt *)varp) == FAIL) {
return FAIL;
}
- } else { // P_STRING
+ } else { // P_STRING
int do_endif = false;
// Don't set 'syntax' and 'filetype' again if the value is
// already right, avoids reloading the syntax file.
if (p->indir == PV_SYN || p->indir == PV_FT) {
- if (fprintf(fd, "if &%s != '%s'", p->fullname,
- *(char **)(varp)) < 0
+ if (fprintf(fd, "if &%s != '%s'", p->fullname, *(char **)(varp)) < 0
|| put_eol(fd) < 0) {
return FAIL;
}
@@ -4244,8 +4183,7 @@ static int put_setstring(FILE *fd, char *cmd, char *name, char **valuep, uint64_
// If the option value is longer than MAXPATHL, we need to append
// each comma separated part of the option separately, so that it
// can be expanded when read back.
- if (size >= MAXPATHL && (flags & P_COMMA) != 0
- && vim_strchr(*valuep, ',') != NULL) {
+ if (size >= MAXPATHL && (flags & P_COMMA) != 0 && vim_strchr(*valuep, ',') != NULL) {
part = xmalloc(size);
// write line break to clear the option, e.g. ':set rtp='
@@ -4309,11 +4247,10 @@ static int put_setnum(FILE *fd, char *cmd, char *name, OptInt *valuep)
static int put_setbool(FILE *fd, char *cmd, char *name, int value)
{
- if (value < 0) { // global/local option using global value
+ if (value < 0) { // global/local option using global value
return OK;
}
- if (fprintf(fd, "%s %s%s", cmd, value ? "" : "no", name) < 0
- || put_eol(fd) < 0) {
+ if (fprintf(fd, "%s %s%s", cmd, value ? "" : "no", name) < 0 || put_eol(fd) < 0) {
return FAIL;
}
return OK;
@@ -4386,7 +4323,7 @@ void *get_varp_scope_from(vimoption_T *p, int scope, buf_T *buf, win_T *win)
case PV_VE:
return &(win->w_p_ve);
}
- return NULL; // "cannot happen"
+ return NULL; // "cannot happen"
}
return get_varp_from(p, buf, win);
}
@@ -4586,6 +4523,8 @@ void *get_varp_from(vimoption_T *p, buf_T *buf, win_T *win)
return &(buf->b_p_cfu);
case PV_OFU:
return &(buf->b_p_ofu);
+ case PV_URF:
+ return &(buf->b_p_urf);
case PV_EOF:
return &(buf->b_p_eof);
case PV_EOL:
@@ -4666,6 +4605,8 @@ void *get_varp_from(vimoption_T *p, buf_T *buf, win_T *win)
return &(buf->b_p_sw);
case PV_TFU:
return &(buf->b_p_tfu);
+ case PV_UMF:
+ return &(buf->b_p_umf);
case PV_TS:
return &(buf->b_p_ts);
case PV_TW:
@@ -4789,7 +4730,7 @@ void copy_winopt(winopt_T *from, winopt_T *to)
// Copy the script context so that we know were the value was last set.
memmove(to->wo_script_ctx, from->wo_script_ctx, sizeof(to->wo_script_ctx));
- check_winopt(to); // don't want NULL pointers
+ check_winopt(to); // don't want NULL pointers
}
/// Check string options in a window for a NULL value.
@@ -4897,7 +4838,7 @@ static void init_buf_opt_idx(void)
void buf_copy_options(buf_T *buf, int flags)
{
int should_copy = true;
- char *save_p_isk = NULL; // init for GCC
+ char *save_p_isk = NULL; // init for GCC
int did_isk = false;
// Skip this when the option defaults have not been set yet. Happens when
@@ -4917,8 +4858,7 @@ void buf_copy_options(buf_T *buf, int flags)
///
if ((vim_strchr(p_cpo, CPO_BUFOPTGLOB) == NULL || !(flags & BCO_ENTER))
&& (buf->b_p_initialized
- || (!(flags & BCO_ENTER)
- && vim_strchr(p_cpo, CPO_BUFOPT) != NULL))) {
+ || (!(flags & BCO_ENTER) && vim_strchr(p_cpo, CPO_BUFOPT) != NULL))) {
should_copy = false;
}
@@ -4929,7 +4869,7 @@ void buf_copy_options(buf_T *buf, int flags)
// BCO_NOHELP is given or the options were initialized already
// (jumping back to a help file with CTRL-T or CTRL-O)
bool dont_do_help = ((flags & BCO_NOHELP) && buf->b_help) || buf->b_p_initialized;
- if (dont_do_help) { // don't free b_p_isk
+ if (dont_do_help) { // don't free b_p_isk
save_p_isk = buf->b_p_isk;
buf->b_p_isk = NULL;
}
@@ -4937,7 +4877,7 @@ void buf_copy_options(buf_T *buf, int flags)
// reset 'readonly' and copy 'fileformat'.
if (!buf->b_p_initialized) {
free_buf_options(buf, true);
- buf->b_p_ro = false; // don't copy readonly
+ buf->b_p_ro = false; // don't copy readonly
buf->b_p_fenc = xstrdup(p_fenc);
switch (*p_ffs) {
case 'm':
@@ -5006,9 +4946,13 @@ void buf_copy_options(buf_T *buf, int flags)
set_buflocal_cfu_callback(buf);
buf->b_p_ofu = xstrdup(p_ofu);
COPY_OPT_SCTX(buf, BV_OFU);
+ buf->b_p_urf = xstrdup(p_urf);
+ COPY_OPT_SCTX(buf, BV_URF);
set_buflocal_ofu_callback(buf);
buf->b_p_tfu = xstrdup(p_tfu);
COPY_OPT_SCTX(buf, BV_TFU);
+ buf->b_p_umf = xstrdup(p_umf);
+ COPY_OPT_SCTX(buf, BV_UMF);
set_buflocal_tfu_callback(buf);
buf->b_p_sts = p_sts;
COPY_OPT_SCTX(buf, BV_STS);
@@ -5160,7 +5104,7 @@ void buf_copy_options(buf_T *buf, int flags)
}
}
- check_buf_options(buf); // make sure we don't have NULLs
+ check_buf_options(buf); // make sure we don't have NULLs
if (did_isk) {
(void)buf_init_chartab(buf, false);
}
@@ -5246,12 +5190,12 @@ void set_context_in_set_cmd(expand_T *xp, char *arg, int opt_flags)
if (*arg == '<') {
while (*p != '>') {
- if (*p++ == NUL) { // expand terminal option name
+ if (*p++ == NUL) { // expand terminal option name
return;
}
}
int key = get_special_key_code(arg + 1);
- if (key == 0) { // unknown name
+ if (key == 0) { // unknown name
xp->xp_context = EXPAND_NOTHING;
return;
}
@@ -5266,7 +5210,7 @@ void set_context_in_set_cmd(expand_T *xp, char *arg, int opt_flags)
p++;
}
if (*p == NUL) {
- return; // expand option name
+ return; // expand option name
}
nextchar = *++p;
is_term_option = true;
@@ -5306,8 +5250,7 @@ void set_context_in_set_cmd(expand_T *xp, char *arg, int opt_flags)
p++;
nextchar = '=';
}
- if ((nextchar != '=' && nextchar != ':')
- || xp->xp_context == EXPAND_BOOL_SETTINGS) {
+ if ((nextchar != '=' && nextchar != ':') || xp->xp_context == EXPAND_BOOL_SETTINGS) {
xp->xp_context = EXPAND_UNSUCCESSFUL;
return;
}
@@ -5339,8 +5282,7 @@ void set_context_in_set_cmd(expand_T *xp, char *arg, int opt_flags)
if (expand_option_subtract) {
xp->xp_context = EXPAND_SETTING_SUBTRACT;
return;
- } else if (expand_option_idx >= 0
- && options[expand_option_idx].opt_expand_cb != NULL) {
+ } else if (expand_option_idx >= 0 && options[expand_option_idx].opt_expand_cb != NULL) {
xp->xp_context = EXPAND_STRING_SETTING;
} else if (*xp->xp_pattern == NUL) {
xp->xp_context = EXPAND_OLD_SETTING;
@@ -5358,13 +5300,8 @@ void set_context_in_set_cmd(expand_T *xp, char *arg, int opt_flags)
// Options that have P_EXPAND are considered to all use file/dir expansion.
if (flags & P_EXPAND) {
p = options[opt_idx].var;
- if (p == (char *)&p_bdir
- || p == (char *)&p_dir
- || p == (char *)&p_path
- || p == (char *)&p_pp
- || p == (char *)&p_rtp
- || p == (char *)&p_cdpath
- || p == (char *)&p_vdir) {
+ if (p == (char *)&p_bdir || p == (char *)&p_dir || p == (char *)&p_path || p == (char *)&p_pp
+ || p == (char *)&p_rtp || p == (char *)&p_cdpath || p == (char *)&p_vdir) {
xp->xp_context = EXPAND_DIRECTORIES;
if (p == (char *)&p_path || p == (char *)&p_cdpath) {
xp->xp_backslash = XP_BS_THREE;
@@ -5488,10 +5425,9 @@ int ExpandSettings(expand_T *xp, regmatch_T *regmatch, char *fuzzystr, int *numM
for (int loop = 0; loop <= 1; loop++) {
regmatch->rm_ic = ic;
if (xp->xp_context != EXPAND_BOOL_SETTINGS) {
- for (int match = 0; match < (int)ARRAY_SIZE(names);
- match++) {
- if (match_str(names[match], regmatch, *matches,
- count, (loop == 0), fuzzy, fuzzystr, fuzmatch)) {
+ for (int match = 0; match < (int)ARRAY_SIZE(names); match++) {
+ if (match_str(names[match], regmatch, *matches, count, (loop == 0), fuzzy, fuzzystr,
+ fuzmatch)) {
if (loop == 0) {
num_normal++;
} else {
@@ -5501,18 +5437,15 @@ int ExpandSettings(expand_T *xp, regmatch_T *regmatch, char *fuzzystr, int *numM
}
}
char *str;
- for (size_t opt_idx = 0; (str = options[opt_idx].fullname) != NULL;
- opt_idx++) {
+ for (size_t opt_idx = 0; (str = options[opt_idx].fullname) != NULL; opt_idx++) {
if (options[opt_idx].var == NULL) {
continue;
}
- if (xp->xp_context == EXPAND_BOOL_SETTINGS
- && !(options[opt_idx].flags & P_BOOL)) {
+ if (xp->xp_context == EXPAND_BOOL_SETTINGS && !(options[opt_idx].flags & P_BOOL)) {
continue;
}
- if (match_str(str, regmatch, *matches, count, (loop == 0),
- fuzzy, fuzzystr, fuzmatch)) {
+ if (match_str(str, regmatch, *matches, count, (loop == 0), fuzzy, fuzzystr, fuzmatch)) {
if (loop == 0) {
num_normal++;
} else {
@@ -5565,10 +5498,8 @@ static char *escape_option_str_cmdline(char *var)
// before a file name character.
// The reverse is found at stropt_copy_value().
for (var = buf; *var != NUL; MB_PTR_ADV(var)) {
- if (var[0] == '\\' && var[1] == '\\'
- && expand_option_idx >= 0
- && (options[expand_option_idx].flags & P_EXPAND)
- && vim_isfilec((uint8_t)var[2])
+ if (var[0] == '\\' && var[1] == '\\' && expand_option_idx >= 0
+ && (options[expand_option_idx].flags & P_EXPAND) && vim_isfilec((uint8_t)var[2])
&& (var[2] != '\\' || (var == buf && var[4] != '\\'))) {
STRMOVE(var, var + 1);
}
@@ -5608,8 +5539,7 @@ int ExpandOldSetting(int *numMatches, char ***matches)
/// Expansion handler for :set=/:set+= when the option has a custom expansion handler.
int ExpandStringSetting(expand_T *xp, regmatch_T *regmatch, int *numMatches, char ***matches)
{
- if (expand_option_idx < 0
- || options[expand_option_idx].opt_expand_cb == NULL) {
+ if (expand_option_idx < 0 || options[expand_option_idx].opt_expand_cb == NULL) {
// Not supposed to reach this. This function is only for options with
// custom expansion callbacks.
return FAIL;
@@ -5646,9 +5576,8 @@ int ExpandSettingSubtract(expand_T *xp, regmatch_T *regmatch, int *numMatches, c
return ExpandOldSetting(numMatches, matches);
}
- char *option_val = *(char **)get_option_varp_scope_from(expand_option_idx,
- expand_option_flags,
- curbuf, curwin);
+ char *option_val
+ = *(char **)get_option_varp_scope_from(expand_option_idx, expand_option_flags, curbuf, curwin);
uint32_t option_flags = options[expand_option_idx].flags;
@@ -5759,10 +5688,7 @@ static void option_value2string(vimoption_T *opp, int scope)
} else if (wc != 0) {
xstrlcpy(NameBuff, transchar((int)wc), sizeof(NameBuff));
} else {
- snprintf(NameBuff,
- sizeof(NameBuff),
- "%" PRId64,
- (int64_t)(*(OptInt *)varp));
+ snprintf(NameBuff, sizeof(NameBuff), "%" PRId64, (int64_t)(*(OptInt *)varp));
}
} else { // P_STRING
varp = *(char **)(varp);
@@ -5796,8 +5722,7 @@ bool shortmess(int x)
{
return (p_shm != NULL
&& (vim_strchr(p_shm, x) != NULL
- || (vim_strchr(p_shm, 'a') != NULL
- && vim_strchr(SHM_ALL_ABBREVIATIONS, x) != NULL)));
+ || (vim_strchr(p_shm, 'a') != NULL && vim_strchr(SHM_ALL_ABBREVIATIONS, x) != NULL)));
}
/// vimrc_found() - Called when a vimrc or "VIMINIT" has been found.
@@ -5921,8 +5846,7 @@ int option_set_callback_func(char *optval, Callback *optcb)
}
typval_T *tv;
- if (*optval == '{'
- || (strncmp(optval, "function(", 9) == 0)
+ if (*optval == '{' || (strncmp(optval, "function(", 9) == 0)
|| (strncmp(optval, "funcref(", 8) == 0)) {
// Lambda expression or a funcref
tv = eval_expr(optval, NULL);
@@ -6008,8 +5932,7 @@ unsigned get_ve_flags(void)
///
/// @param win If not NULL, the window to get the local option from; global
/// otherwise.
-char *get_showbreak_value(win_T *const win)
- FUNC_ATTR_WARN_UNUSED_RESULT
+char *get_showbreak_value(win_T *const win) FUNC_ATTR_WARN_UNUSED_RESULT
{
if (win->w_p_sbr == NULL || *win->w_p_sbr == NUL) {
return p_sbr;
@@ -6039,16 +5962,14 @@ int get_fileformat(const buf_T *buf)
/// argument.
///
/// @param eap can be NULL!
-int get_fileformat_force(const buf_T *buf, const exarg_T *eap)
- FUNC_ATTR_NONNULL_ARG(1)
+int get_fileformat_force(const buf_T *buf, const exarg_T *eap) FUNC_ATTR_NONNULL_ARG(1)
{
int c;
if (eap != NULL && eap->force_ff != 0) {
c = eap->force_ff;
} else {
- if ((eap != NULL && eap->force_bin != 0)
- ? (eap->force_bin == FORCE_BIN) : buf->b_p_bin) {
+ if ((eap != NULL && eap->force_bin != 0) ? (eap->force_bin == FORCE_BIN) : buf->b_p_bin) {
return EOL_UNIX;
}
c = (unsigned char)(*buf->b_p_ff);
@@ -6151,7 +6072,7 @@ size_t copy_option_part(char **option, char *buf, size_t maxlen, char *sep_chars
if (*p != NUL && *p != ',') { // skip non-standard separator
p++;
}
- p = skip_to_option_part(p); // p points to next file name
+ p = skip_to_option_part(p); // p points to next file name
*option = p;
return len;
@@ -6184,25 +6105,21 @@ int win_signcol_count(win_T *wp)
}
/// Get window or buffer local options
-dict_T *get_winbuf_options(const int bufopt)
- FUNC_ATTR_WARN_UNUSED_RESULT
+dict_T *get_winbuf_options(const int bufopt) FUNC_ATTR_WARN_UNUSED_RESULT
{
dict_T *const d = tv_dict_alloc();
for (int opt_idx = 0; options[opt_idx].fullname; opt_idx++) {
struct vimoption *opt = &options[opt_idx];
- if ((bufopt && (opt->indir & PV_BUF))
- || (!bufopt && (opt->indir & PV_WIN))) {
+ if ((bufopt && (opt->indir & PV_BUF)) || (!bufopt && (opt->indir & PV_WIN))) {
void *varp = get_varp(opt);
if (varp != NULL) {
if (opt->flags & P_STRING) {
- tv_dict_add_str(d, opt->fullname, strlen(opt->fullname),
- *(const char **)varp);
+ tv_dict_add_str(d, opt->fullname, strlen(opt->fullname), *(const char **)varp);
} else if (opt->flags & P_NUM) {
- tv_dict_add_nr(d, opt->fullname, strlen(opt->fullname),
- *(OptInt *)varp);
+ tv_dict_add_nr(d, opt->fullname, strlen(opt->fullname), *(OptInt *)varp);
} else {
tv_dict_add_nr(d, opt->fullname, strlen(opt->fullname), *(int *)varp);
}
@@ -6234,9 +6151,8 @@ int get_sidescrolloff_value(win_T *wp)
Dictionary get_vimoption(String name, int scope, buf_T *buf, win_T *win, Error *err)
{
int opt_idx = findoption_len(name.data, name.size);
- VALIDATE_S(opt_idx >= 0, "option (not found)", name.data, {
- return (Dictionary)ARRAY_DICT_INIT;
- });
+ VALIDATE_S(opt_idx >= 0, "option (not found)", name.data,
+ { return (Dictionary)ARRAY_DICT_INIT; });
return vimoption2dict(&options[opt_idx], scope, buf, win);
}
@@ -6310,7 +6226,8 @@ static Dictionary vimoption2dict(vimoption_T *opt, int req_scope, buf_T *buf, wi
type = "boolean";
def = BOOLEAN_OBJ((intptr_t)def_val);
} else {
- type = ""; def = NIL;
+ type = "";
+ def = NIL;
}
PUT(dict, "type", CSTR_TO_OBJ(type));
PUT(dict, "default", def);
diff --git a/src/nvim/option_defs.h b/src/nvim/option_defs.h
index b2e8081a08..1bbff8e522 100644
--- a/src/nvim/option_defs.h
+++ b/src/nvim/option_defs.h
@@ -23,7 +23,6 @@ typedef union {
String string;
} OptValData;
-/// Option value
typedef struct {
OptValType type;
OptValData data;
diff --git a/src/nvim/option_vars.h b/src/nvim/option_vars.h
index b0e9ff9434..af2e31f7c7 100644
--- a/src/nvim/option_vars.h
+++ b/src/nvim/option_vars.h
@@ -733,6 +733,8 @@ EXTERN char *p_udir; ///< 'undodir'
EXTERN int p_udf; ///< 'undofile'
EXTERN OptInt p_ul; ///< 'undolevels'
EXTERN OptInt p_ur; ///< 'undoreload'
+EXTERN char* p_umf; ///< 'usermarkfunc'
+EXTERN char* p_urf; ///< 'userregfunction'
EXTERN OptInt p_uc; ///< 'updatecount'
EXTERN OptInt p_ut; ///< 'updatetime'
EXTERN char *p_shada; ///< 'shada'
@@ -874,6 +876,8 @@ enum {
BV_TX,
BV_UDF,
BV_UL,
+ BV_UMF,
+ BV_URF,
BV_WM,
BV_VSTS,
BV_VTS,
diff --git a/src/nvim/options.lua b/src/nvim/options.lua
index daaf73d241..4fdee925ad 100644
--- a/src/nvim/options.lua
+++ b/src/nvim/options.lua
@@ -9217,6 +9217,98 @@ return {
varname = 'p_ut',
},
{
+ abbreviation='umf',
+ full_name='usermarkfunc',
+ desc= [=[
+ This option specifies a function to be used to handle any marks
+ that Neovim does not natively handle. This option unlocks all
+ characters to be used as marks by the user.
+
+ The 'usermarkfunc' function is called each time a user mark is read
+ from or written to.
+
+ The 'usermarkfunc' function must take the following parameters:
+
+ {get_or_set} The action being done on this mark (either 'set'
+ or 'get'
+
+ {markname} The name of the mark either being read or .
+
+ In case the action is 'get', the 'usermarkfunc' function should return
+ the content associated with that mark. This can be a number indicating a
+ line number or it could be a dictionary with the keys:
+
+ {line} the line number
+
+ {col} the column number
+
+ {filename} the filename
+<
+ ]=],
+ short_desc=N_("Function used to define behavior of user-defined marks."),
+ type='string', scope={'buffer'},
+ varname='p_umf',
+ defaults={if_true=""}
+ },
+ {
+ abbreviation='urf',
+ full_name='userregfunc',
+ desc= [=[
+ This option specifies a function to be used to handle any registers
+ that Neovim does not natively handle. This option unlocks all
+ characters to be used as registers by the user.
+
+ The 'userregfunc' function is called each time a user register is read
+ from or written to.
+
+ The 'userregfunc' function must take the following parameters:
+
+ {action} The action being done on this register (either 'yank'
+ or 'put'
+
+ {register} The string holding the name of the register. This
+ is always a single character, though multi-byte
+ characters are allowed.
+
+ {content} If the action is 'yank' this is the content being
+ yanked into the register. The content is a dictionary
+ with the following items:
+
+ {lines} The lines being yanked, as a list.
+
+ {type} The type of yank, either "line", "char", or
+ "block"
+
+ {width} The width in case of "block" mode.
+
+ {additional_data} Additional data. (can be returned in
+ put mode).
+
+ In case the action is 'put', the 'userregfunc' function should return
+ the content to place in that location. The content can either be a
+ string, in which case "char" mode is inferred, or it can return a
+ dictionary of the same template that populates 'content'.
+
+ A very simple example of a 'userregfunc' function that behaves exactly
+ like traditional registers would look like: >
+
+ let s:contents = {}
+ function! MyUserregFunction(action, register, content) abort
+ if a:action == "put"
+ return get(s:contents, a:register, "")
+ else
+ let s:contents[a:register] = a:content
+ endif
+ endfunction
+ set userregfunc=MyUserregFunction
+<
+ ]=],
+ short_desc=N_("Function used to define behavior of user-defined registers."),
+ type='string', scope={'buffer'},
+ varname='p_urf',
+ defaults={if_true=""}
+ },
+ {
abbreviation = 'vsts',
cb = 'did_set_varsofttabstop',
defaults = { if_true = '' },
diff --git a/src/nvim/po/da.po b/src/nvim/po/da.po
index 0345d3e243..ba0301589c 100644
--- a/src/nvim/po/da.po
+++ b/src/nvim/po/da.po
@@ -4049,7 +4049,7 @@ msgid "freeing %ld lines"
msgstr "frigør %ld linjer"
#, c-format
-msgid " into \"%c"
+msgid " into \"%s"
msgstr " i \"%c"
#, c-format
diff --git a/src/nvim/po/fr.po b/src/nvim/po/fr.po
index d9058326d5..fae6fe2297 100644
--- a/src/nvim/po/fr.po
+++ b/src/nvim/po/fr.po
@@ -4313,7 +4313,7 @@ msgid "freeing %ld lines"
msgstr "libration de %ld lignes"
#, c-format
-msgid " into \"%c"
+msgid " into \"%s"
msgstr " dans \"%c"
#, c-format
diff --git a/src/nvim/po/tr.po b/src/nvim/po/tr.po
index f3c55fe9ab..08b97ec180 100644
--- a/src/nvim/po/tr.po
+++ b/src/nvim/po/tr.po
@@ -4208,7 +4208,7 @@ msgstr[0] "%<PRId64> satır değiştirildi"
msgstr[1] "%<PRId64> satır değiştirildi"
#, c-format
-msgid " into \"%c"
+msgid " into \"%s"
msgstr " \"%c"
#, c-format
diff --git a/src/nvim/po/uk.po b/src/nvim/po/uk.po
index 83898cda12..1c1da14a22 100644
--- a/src/nvim/po/uk.po
+++ b/src/nvim/po/uk.po
@@ -5360,7 +5360,7 @@ msgstr[1] "Змінено %<PRId64> рядки"
msgstr[2] "Змінено %<PRId64> рядків"
#, c-format
-msgid " into \"%c"
+msgid " into \"%s"
msgstr " у \"%c"
#, c-format
diff --git a/src/nvim/shada.c b/src/nvim/shada.c
index 819fbcf885..f64dd0e786 100644
--- a/src/nvim/shada.c
+++ b/src/nvim/shada.c
@@ -2372,7 +2372,7 @@ static inline void add_search_pattern(PossiblyFreedShadaEntry *const ret_pse,
static inline void shada_initialize_registers(WriteMergerState *const wms, int max_reg_lines)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_ALWAYS_INLINE
{
- const void *reg_iter = NULL;
+ iter_register_T reg_iter = ITER_REGISTER_NULL;
const bool limit_reg_lines = max_reg_lines >= 0;
do {
yankreg_T reg;
@@ -2403,7 +2403,7 @@ static inline void shada_initialize_registers(WriteMergerState *const wms, int m
}
}
};
- } while (reg_iter != NULL);
+ } while (reg_iter != ITER_REGISTER_NULL);
}
/// Replace numbered mark in WriteMergerState
diff --git a/src/nvim/yankmap.c b/src/nvim/yankmap.c
new file mode 100644
index 0000000000..591bcffe33
--- /dev/null
+++ b/src/nvim/yankmap.c
@@ -0,0 +1,45 @@
+#include "nvim/yankmap.h"
+
+#include "nvim/memory.h"
+
+void init_yankmap(yankmap_T* map)
+{
+ memset(map, 0, sizeof(yankmap_T));
+
+ map->reg_to_yankreg = (Map(int, ptr_t))MAP_INIT;
+ map->yankreg_to_reg = (Map(ptr_t, int))MAP_INIT;
+ // map_init(int, ptr_t, &map->reg_to_yankreg);
+ // map_init(ptr_t, int, &map->yankreg_to_reg);
+}
+
+yankreg_T* yankmap_get(yankmap_T* yankmap, int reg)
+{
+ bool is_new = false;
+ yankreg_T** ret
+ = (yankreg_T**)map_put_ref(int, ptr_t)(&yankmap->reg_to_yankreg, reg, NULL, &is_new);
+
+ if (ret) {
+ if (is_new) {
+ *ret = xcalloc(sizeof(yankreg_T), 1);
+ }
+
+ /* Add the back-reference */
+ int* ref = map_put_ref(ptr_t, int)(&yankmap->yankreg_to_reg, *ret, NULL, NULL);
+ *ref = reg;
+
+ return *ret;
+ }
+
+ return NULL;
+}
+
+int yankmap_find(yankmap_T* yankmap, yankreg_T* yankreg)
+{
+ int* ref = map_ref(ptr_t, int)(&yankmap->yankreg_to_reg, yankreg, NULL);
+
+ if (ref) {
+ return *ref;
+ }
+
+ return -1;
+}
diff --git a/src/nvim/yankmap.h b/src/nvim/yankmap.h
new file mode 100644
index 0000000000..4468f3a016
--- /dev/null
+++ b/src/nvim/yankmap.h
@@ -0,0 +1,25 @@
+#ifndef YANK_TRIE_H_
+#define YANK_TRIE_H_
+
+#include <stdbool.h>
+
+#include "nvim/map_defs.h"
+#include "nvim/ops.h"
+
+typedef struct {
+ /* Register name to yank register. */
+ Map(int, ptr_t) reg_to_yankreg;
+
+ /* Yank register to register name. */
+ Map(ptr_t, int) yankreg_to_reg;
+} yankmap_T;
+
+void init_yankmap(yankmap_T* yankmap);
+
+yankreg_T* yankmap_get(yankmap_T* yankmap, int reg);
+
+yankreg_T* yankmap_put(yankmap_T* yankmap, int index);
+
+int yankmap_find(yankmap_T* yankmap, yankreg_T* yankreg);
+
+#endif