aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/nvim/buffer_defs.h1
-rw-r--r--src/nvim/ex_docmd.c8
-rw-r--r--src/nvim/map.c1
-rw-r--r--src/nvim/map.h1
-rw-r--r--src/nvim/mark.c159
-rw-r--r--src/nvim/option.c5
-rw-r--r--src/nvim/option_defs.h1
-rw-r--r--src/nvim/options.lua7
8 files changed, 178 insertions, 5 deletions
diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h
index 3ef5ea7e02..9457051947 100644
--- a/src/nvim/buffer_defs.h
+++ b/src/nvim/buffer_defs.h
@@ -712,6 +712,7 @@ struct file_buffer {
char_u *b_p_cfu; ///< 'completefunc'
char_u *b_p_ofu; ///< 'omnifunc'
char_u *b_p_tfu; ///< 'tagfunc'
+ char_u *b_p_umf; ///< 'usermarkfunc'
int b_p_eol; ///< 'endofline'
int b_p_fixeol; ///< 'fixendofline'
int b_p_et; ///< 'expandtab'
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index 4ac9847e53..0dde82c235 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -4017,7 +4017,7 @@ char *skip_range(const char *cmd, int *ctx)
}
}
if (*cmd != NUL) {
- ++cmd;
+ cmd += utf_ptr2len(cmd);
}
}
@@ -4162,13 +4162,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 d3058a5d52..907c1d5996 100644
--- a/src/nvim/map.c
+++ b/src/nvim/map.c
@@ -163,6 +163,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 845daac3f7..92c9ebcc34 100644
--- a/src/nvim/map.h
+++ b/src/nvim/map.h
@@ -34,6 +34,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 1fe3327b29..344d55a473 100644
--- a/src/nvim/mark.c
+++ b/src/nvim/mark.c
@@ -17,11 +17,13 @@
#include "nvim/diff.h"
#include "nvim/edit.h"
#include "nvim/eval.h"
+#include "nvim/eval/typval.h"
#include "nvim/ex_cmds.h"
#include "nvim/extmark.h"
#include "nvim/fileio.h"
#include "nvim/fold.h"
#include "nvim/mark.h"
+#include "nvim/mark_defs.h"
#include "nvim/mbyte.h"
#include "nvim/memline.h"
#include "nvim/memory.h"
@@ -39,6 +41,8 @@
#include "nvim/strings.h"
#include "nvim/ui.h"
#include "nvim/vim.h"
+#include "nvim/map.h"
+#include "nvim/eval/userfunc.h"
/*
* This file contains routines to maintain and manipulate marks.
@@ -55,6 +59,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
@@ -164,7 +194,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);
}
/*
@@ -349,6 +380,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;
@@ -437,6 +477,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.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 12c5889703..4958c10220 100644
--- a/src/nvim/option.c
+++ b/src/nvim/option.c
@@ -142,6 +142,7 @@ static char_u *p_cpt;
static char_u *p_cfu;
static char_u *p_ofu;
static char_u *p_tfu;
+static char_u *p_umf;
static int p_eol;
static int p_fixeol;
static int p_et;
@@ -6273,6 +6274,8 @@ static char_u *get_varp(vimoption_T *p)
return (char_u *)&(curbuf->b_p_sw);
case PV_TFU:
return (char_u *)&(curbuf->b_p_tfu);
+ case PV_UMF:
+ return (char_u *)&(curbuf->b_p_umf);
case PV_TS:
return (char_u *)&(curbuf->b_p_ts);
case PV_TW:
@@ -6596,6 +6599,8 @@ void buf_copy_options(buf_T *buf, int flags)
COPY_OPT_SCTX(buf, BV_OFU);
buf->b_p_tfu = vim_strsave(p_tfu);
COPY_OPT_SCTX(buf, BV_TFU);
+ buf->b_p_umf = vim_strsave(p_umf);
+ COPY_OPT_SCTX(buf, BV_UMF);
buf->b_p_sts = p_sts;
COPY_OPT_SCTX(buf, BV_STS);
buf->b_p_sts_nopaste = p_sts_nopaste;
diff --git a/src/nvim/option_defs.h b/src/nvim/option_defs.h
index 237288fbad..92ab7489bb 100644
--- a/src/nvim/option_defs.h
+++ b/src/nvim/option_defs.h
@@ -838,6 +838,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 2f941f5d0c..5e4c73a5db 100644
--- a/src/nvim/options.lua
+++ b/src/nvim/options.lua
@@ -2691,6 +2691,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'},