diff src/mark.c @ 20615:8eed1e9389bb v8.2.0861

patch 8.2.0861: cannot easily get all the current marks Commit: https://github.com/vim/vim/commit/cfb4b47de08e4437c692d382067dc1692cd83c23 Author: Bram Moolenaar <Bram@vim.org> Date: Sun May 31 15:41:57 2020 +0200 patch 8.2.0861: cannot easily get all the current marks Problem: Cannot easily get all the current marks. Solution: Add getmarklist(). (Yegappan Lakshmanan, closes https://github.com/vim/vim/issues/6032)
author Bram Moolenaar <Bram@vim.org>
date Sun, 31 May 2020 15:45:04 +0200
parents de2d1820215a
children 3e36a51ff152
line wrap: on
line diff
--- a/src/mark.c
+++ b/src/mark.c
@@ -1412,3 +1412,124 @@ get_namedfm(void)
 {
     return namedfm;
 }
+
+#if defined(FEAT_EVAL) || defined(PROTO)
+/*
+ * Add information about mark 'mname' to list 'l'
+ */
+    static int
+add_mark(list_T *l, char_u *mname, pos_T *pos, int bufnr, char_u *fname)
+{
+    dict_T	*d;
+    list_T	*lpos;
+
+    if (pos->lnum <= 0)
+	return OK;
+
+    d = dict_alloc();
+    if (d == NULL)
+	return FAIL;
+
+    if (list_append_dict(l, d) == FAIL)
+    {
+	dict_unref(d);
+	return FAIL;
+    }
+
+    lpos = list_alloc();
+    if (lpos == NULL)
+	return FAIL;
+
+    list_append_number(lpos, bufnr);
+    list_append_number(lpos, pos->lnum);
+    list_append_number(lpos, pos->col);
+    list_append_number(lpos, pos->coladd);
+
+    if (dict_add_string(d, "mark", mname) == FAIL
+	    || dict_add_list(d, "pos", lpos) == FAIL
+	    || (fname != NULL && dict_add_string(d, "file", fname) == FAIL))
+	return FAIL;
+
+    return OK;
+}
+
+/*
+ * Get information about marks local to a buffer.
+ */
+    static void
+get_buf_local_marks(buf_T *buf, list_T *l)
+{
+    char_u	mname[3] = "' ";
+    int		i;
+
+    // Marks 'a' to 'z'
+    for (i = 0; i < NMARKS; ++i)
+    {
+	mname[1] = 'a' + i;
+	add_mark(l, mname, &buf->b_namedm[i], buf->b_fnum, NULL);
+    }
+
+    // Mark '' is a window local mark and not a buffer local mark
+    add_mark(l, (char_u *)"''", &curwin->w_pcmark, curbuf->b_fnum, NULL);
+
+    add_mark(l, (char_u *)"'\"", &buf->b_last_cursor, buf->b_fnum, NULL);
+    add_mark(l, (char_u *)"'[", &buf->b_op_start, buf->b_fnum, NULL);
+    add_mark(l, (char_u *)"']", &buf->b_op_end, buf->b_fnum, NULL);
+    add_mark(l, (char_u *)"'^", &buf->b_last_insert, buf->b_fnum, NULL);
+    add_mark(l, (char_u *)"'.", &buf->b_last_change, buf->b_fnum, NULL);
+    add_mark(l, (char_u *)"'<", &buf->b_visual.vi_start, buf->b_fnum, NULL);
+    add_mark(l, (char_u *)"'>", &buf->b_visual.vi_end, buf->b_fnum, NULL);
+}
+
+/*
+ * Get information about global marks ('A' to 'Z' and '0' to '9')
+ */
+    static void
+get_global_marks(list_T *l)
+{
+    char_u	mname[3] = "' ";
+    int		i;
+    char_u	*name;
+
+    // Marks 'A' to 'Z' and '0' to '9'
+    for (i = 0; i < NMARKS + EXTRA_MARKS; ++i)
+    {
+	if (namedfm[i].fmark.fnum != 0)
+	    name = buflist_nr2name(namedfm[i].fmark.fnum, TRUE, TRUE);
+	else
+	    name = namedfm[i].fname;
+	if (name != NULL)
+	{
+	    mname[1] = i >= NMARKS ? i - NMARKS + '0' : i + 'A';
+	    add_mark(l, mname, &namedfm[i].fmark.mark,
+		    namedfm[i].fmark.fnum, name);
+	    if (namedfm[i].fmark.fnum != 0)
+		vim_free(name);
+	}
+    }
+}
+
+/*
+ * getmarklist() function
+ */
+    void
+f_getmarklist(typval_T *argvars, typval_T *rettv)
+{
+    buf_T	*buf = NULL;
+
+    if (rettv_list_alloc(rettv) != OK)
+	return;
+
+    if (argvars[0].v_type == VAR_UNKNOWN)
+    {
+	get_global_marks(rettv->vval.v_list);
+	return;
+    }
+
+    buf = tv_get_buf(&argvars[0], FALSE);
+    if (buf == NULL)
+	return;
+
+    get_buf_local_marks(buf, rettv->vval.v_list);
+}
+#endif