diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/buffer_defs.h | 1 | ||||
-rw-r--r-- | src/nvim/eval/funcs.c | 1 | ||||
-rw-r--r-- | src/nvim/ex_docmd.c | 8 | ||||
-rw-r--r-- | src/nvim/map.c | 1 | ||||
-rw-r--r-- | src/nvim/map.h | 1 | ||||
-rw-r--r-- | src/nvim/mark.c | 158 | ||||
-rw-r--r-- | src/nvim/option.c | 4 | ||||
-rw-r--r-- | src/nvim/option_defs.h | 2 | ||||
-rw-r--r-- | src/nvim/options.lua | 7 |
9 files changed, 178 insertions, 5 deletions
diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h index f01edd1ad2..fa76377c4e 100644 --- a/src/nvim/buffer_defs.h +++ b/src/nvim/buffer_defs.h @@ -657,6 +657,7 @@ 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' diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 5a31288ecd..a6dc41d0f3 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -3137,6 +3137,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", diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index a24e8458a6..5d271e4ef6 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -3195,7 +3195,7 @@ char *skip_range(const char *cmd, int *ctx) } } if (*cmd != NUL) { - cmd++; + cmd += utf_ptr2len(cmd); } } @@ -3338,13 +3338,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) { // Jumped to another file. lnum = curwin->w_cursor.lnum; diff --git a/src/nvim/map.c b/src/nvim/map.c index 191a459863..24066659a8 100644 --- a/src/nvim/map.c +++ b/src/nvim/map.c @@ -162,6 +162,7 @@ static inline bool ColorKey_eq(ColorKey ae1, ColorKey ae2) return memcmp(&ae1, &ae2, sizeof(ae1)) == 0; } +MAP_IMPL(int, ptr_t, DEFAULT_INITIALIZER) MAP_IMPL(int, int, DEFAULT_INITIALIZER) MAP_IMPL(int, cstr_t, DEFAULT_INITIALIZER) MAP_IMPL(cstr_t, ptr_t, DEFAULT_INITIALIZER) diff --git a/src/nvim/map.h b/src/nvim/map.h index 92f0b32255..6a548ad30b 100644 --- a/src/nvim/map.h +++ b/src/nvim/map.h @@ -39,6 +39,7 @@ // // NOTE: Keys AND values must be allocated! khash.h does not make a copy. // +MAP_DECLS(int, ptr_t) MAP_DECLS(int, int) MAP_DECLS(int, cstr_t) MAP_DECLS(cstr_t, ptr_t) diff --git a/src/nvim/mark.c b/src/nvim/mark.c index f1a1f25e6c..0c7f5efd89 100644 --- a/src/nvim/mark.c +++ b/src/nvim/mark.c @@ -26,6 +26,7 @@ #include "nvim/globals.h" #include "nvim/highlight_defs.h" #include "nvim/mark.h" +#include "nvim/mark_defs.h" #include "nvim/mbyte.h" #include "nvim/memline.h" #include "nvim/memory.h" @@ -42,6 +43,8 @@ #include "nvim/textobject.h" #include "nvim/undo_defs.h" #include "nvim/vim.h" +#include "nvim/map.h" +#include "nvim/eval/userfunc.h" // This file contains routines to maintain and manipulate marks. @@ -54,6 +57,32 @@ /// Global marks (marks with file number or name) static xfmark_T namedfm[NGLOBALMARKS]; +static struct { + Map(int, ptr_t) named; +} usermarks; +bool usermarks_init; + +static xfmark_T* lookup_user_mark(int mark) +{ + if (!usermarks_init) { + map_init(int, ptr_t, &usermarks.named); + usermarks_init = 1; + } + + xfmark_T **ret = + (xfmark_T**) map_ref(int, ptr_t)(&usermarks.named, mark, true); + + if (ret) { + if (! (*ret)) { + *ret = xcalloc(sizeof(xfmark_T), 1); + } + + return *ret; + } + + return NULL; +} + #ifdef INCLUDE_GENERATED_DECLARATIONS # include "mark.c.generated.h" #endif @@ -160,7 +189,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 @@ -341,6 +371,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; @@ -429,6 +468,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/option.c b/src/nvim/option.c index 01a5c7677f..1e7cd62d22 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -4003,6 +4003,8 @@ static char_u *get_varp_from(vimoption_T *p, buf_T *buf, win_T *win) return (char_u *)&(buf->b_p_sw); case PV_TFU: return (char_u *)&(buf->b_p_tfu); + case PV_UMF: + return (char_u *)&(buf->b_p_umf); case PV_TS: return (char_u *)&(buf->b_p_ts); case PV_TW: @@ -4342,6 +4344,8 @@ void buf_copy_options(buf_T *buf, int flags) 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); diff --git a/src/nvim/option_defs.h b/src/nvim/option_defs.h index d190fc5999..16b46dca7a 100644 --- a/src/nvim/option_defs.h +++ b/src/nvim/option_defs.h @@ -398,6 +398,7 @@ EXTERN long p_channel; ///< 'channel' EXTERN char *p_cink; ///< 'cinkeys' EXTERN char *p_cinsd; ///< 'cinscopedecls' EXTERN char *p_cinw; ///< 'cinwords' +EXTERN char *p_umf; ///< 'usermarkfunc' EXTERN char *p_cfu; ///< 'completefunc' EXTERN char *p_ofu; ///< 'omnifunc' EXTERN char *p_tsrfu; ///< 'thesaurusfunc' @@ -903,6 +904,7 @@ enum { BV_SW, BV_SWF, BV_TFU, + BV_UMF, BV_TSRFU, BV_TAGS, BV_TC, diff --git a/src/nvim/options.lua b/src/nvim/options.lua index 387ccd0888..bfbfdd938e 100644 --- a/src/nvim/options.lua +++ b/src/nvim/options.lua @@ -2629,6 +2629,13 @@ return { defaults={if_true=4000} }, { + full_name='usermarkfunc', abbreviation='umf', + short_desc=N_("function used to perform jumps/sets to user marks."), + type='string', scope={'buffer'}, + varname='p_umf', + defaults={if_true=""} + }, + { full_name='varsofttabstop', abbreviation='vsts', short_desc=N_("list of numbers of spaces that <Tab> uses while editing"), type='string', list='comma', scope={'buffer'}, |