]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 8.2.0861: cannot easily get all the current marks v8.2.0861
authorBram Moolenaar <Bram@vim.org>
Sun, 31 May 2020 13:41:57 +0000 (15:41 +0200)
committerBram Moolenaar <Bram@vim.org>
Sun, 31 May 2020 13:41:57 +0000 (15:41 +0200)
Problem:    Cannot easily get all the current marks.
Solution:   Add getmarklist(). (Yegappan Lakshmanan, closes #6032)

runtime/doc/eval.txt
runtime/doc/usr_41.txt
src/evalfunc.c
src/mark.c
src/proto/mark.pro
src/testdir/test_marks.vim
src/version.c

index 11cc772b2fd620d776f6cc86549cfe02d7b62d2e..75936679f950fa30921a3d8145ca1df61084e20c 100644 (file)
@@ -2497,6 +2497,7 @@ getjumplist([{winnr} [, {tabnr}]])
 getline({lnum})                        String  line {lnum} of current buffer
 getline({lnum}, {end})         List    lines {lnum} to {end} of current buffer
 getloclist({nr} [, {what}])    List    list of location list items
+getmarklist([{expr}])          List    list of global/local marks
 getmatches([{win}])            List    list of current matches
 getmousepos()                  Dict    last known mouse position
 getpid()                       Number  process ID of Vim
@@ -5365,6 +5366,25 @@ getloclist({nr} [, {what}])                              *getloclist()*
                                        |location-list-file-window| for more
                                        details.
 
+getmarklist([{expr}]                                   *getmarklist()*
+               Without the {expr} argument returns a |List| with information
+               about all the global marks. |mark|
+
+               If the optional {expr} argument is specified, returns the
+               local marks defined in buffer {expr}.  For the use of {expr},
+               see |bufname()|.
+
+               Each item in the retuned List is a |Dict| with the following:
+                   name - name of the mark prefixed by "'"
+                   pos - a |List| with the position of the mark:
+                               [bufnum, lnum, col, off]
+                         Refer to |getpos()| for more information.
+                   file - file name
+
+               Refer to |getpos()| for getting information about a specific
+               mark.
+
+
 getmatches([{win}])                                    *getmatches()*
                Returns a |List| with all matches previously defined for the
                current window by |matchadd()| and the |:match| commands.
index 8fece1a177c8e17b19d0a7df6da4a517c1c26af4..2642e0b39ee12c8b6be28b12c125c7c3a7f1f34b 100644 (file)
@@ -724,6 +724,7 @@ Cursor and mark position:           *cursor-functions* *mark-functions*
        getcurpos()             get position of the cursor
        getpos()                get position of cursor, mark, etc.
        setpos()                set position of cursor, mark, etc.
+       getmarklist()           list of global/local marks
        byte2line()             get line number at a specific byte count
        line2byte()             byte count at a specific line
        diff_filler()           get the number of filler lines above a line
index fc8b044839fa7cb6ae572a66f9970e9b796ac92c..f40a2ee6d09f4053bf6d725ed47dfad12f5e5562 100644 (file)
@@ -579,6 +579,7 @@ static funcentry_T global_functions[] =
     {"getjumplist",    0, 2, FEARG_1,    ret_list_any, f_getjumplist},
     {"getline",                1, 2, FEARG_1,    ret_f_getline, f_getline},
     {"getloclist",     1, 2, 0,          ret_list_dict_any, f_getloclist},
+    {"getmarklist",    0, 1, 0,          ret_list_dict_any,  f_getmarklist},
     {"getmatches",     0, 1, 0,          ret_list_dict_any, f_getmatches},
     {"getmousepos",    0, 0, 0,          ret_dict_number, f_getmousepos},
     {"getpid",         0, 0, 0,          ret_number,   f_getpid},
index e1dbe3a7468194b69899420dc1c0df5bc2e2f75d..ca64c90e14b8b0de571b9f0cee1454718982eb5e 100644 (file)
@@ -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
index a28fa9a378839eb08239fb630a8b16b6c3e5783c..cc45f0d3c3a9e13bc558a9b2acbece95e38fa82e 100644 (file)
@@ -27,4 +27,5 @@ void free_jumplist(win_T *wp);
 void set_last_cursor(win_T *win);
 void free_all_marks(void);
 xfmark_T *get_namedfm(void);
+void f_getmarklist(typval_T *argvars, typval_T *rettv);
 /* vim: set ft=c : */
index fcae2ac137a353340ed025b94ae30ecc05924923..ffd50a12ca3c702950f7ea56c1171f837c8e5067 100644 (file)
@@ -259,4 +259,29 @@ func Test_file_mark()
   call delete('Xtwo')
 endfunc
 
+" Test for the getmarklist() function
+func Test_getmarklist()
+  new
+  " global marks
+  delmarks A-Z 0-9 \" ^.[]
+  call assert_equal([], getmarklist())
+  call setline(1, ['one', 'two', 'three'])
+  mark A
+  call cursor(3, 5)
+  normal mN
+  call assert_equal([{'file' : '', 'mark' : "'A", 'pos' : [bufnr(), 1, 0, 0]},
+        \ {'file' : '', 'mark' : "'N", 'pos' : [bufnr(), 3, 4, 0]}],
+        \ getmarklist())
+  " buffer local marks
+  delmarks!
+  call assert_equal([{'mark' : "''", 'pos' : [bufnr(), 1, 0, 0]},
+        \ {'mark' : "'\"", 'pos' : [bufnr(), 1, 0, 0]}], getmarklist(bufnr()))
+  call cursor(2, 2)
+  normal mr
+  call assert_equal({'mark' : "'r", 'pos' : [bufnr(), 2, 1, 0]},
+        \ getmarklist(bufnr())[0])
+  call assert_equal([], getmarklist({}))
+  close!
+endfunc
+
 " vim: shiftwidth=2 sts=2 expandtab
index f63cb0c1cf733a6bc6d2dd2063bf35dad444b8c8..d1ebe5b1a397e34b7f334172329d5bada3443d27 100644 (file)
@@ -746,6 +746,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    861,
 /**/
     860,
 /**/