To: vim_dev@googlegroups.com Subject: Patch 8.2.0861 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.2.0861 Problem: Cannot easily get all the current marks. Solution: Add getmarklist(). (Yegappan Lakshmanan, closes #6032) Files: runtime/doc/eval.txt, runtime/doc/usr_41.txt, src/evalfunc.c, src/mark.c, src/proto/mark.pro, src/testdir/test_marks.vim *** ../vim-8.2.0860/runtime/doc/eval.txt 2020-05-30 21:52:49.238816739 +0200 --- runtime/doc/eval.txt 2020-05-31 15:36:50.376200139 +0200 *************** *** 2491,2496 **** --- 2497,2503 ---- 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 *************** *** 5355,5360 **** --- 5366,5390 ---- |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. *** ../vim-8.2.0860/runtime/doc/usr_41.txt 2020-03-15 16:12:16.548208667 +0100 --- runtime/doc/usr_41.txt 2020-05-31 15:29:55.977504175 +0200 *************** *** 724,729 **** --- 727,733 ---- 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 *** ../vim-8.2.0860/src/evalfunc.c 2020-05-30 18:14:37.824521074 +0200 --- src/evalfunc.c 2020-05-31 15:29:55.981504159 +0200 *************** *** 579,584 **** --- 579,585 ---- {"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}, *** ../vim-8.2.0860/src/mark.c 2019-12-27 17:33:23.475080942 +0100 --- src/mark.c 2020-05-31 15:29:55.981504159 +0200 *************** *** 1412,1414 **** --- 1412,1535 ---- { 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 *** ../vim-8.2.0860/src/proto/mark.pro 2019-12-12 12:55:26.000000000 +0100 --- src/proto/mark.pro 2020-05-31 15:40:05.231523743 +0200 *************** *** 27,30 **** --- 27,31 ---- 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 : */ *** ../vim-8.2.0860/src/testdir/test_marks.vim 2020-04-09 18:42:08.358066443 +0200 --- src/testdir/test_marks.vim 2020-05-31 15:29:55.981504159 +0200 *************** *** 259,262 **** --- 259,287 ---- 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 *** ../vim-8.2.0860/src/version.c 2020-05-31 15:08:55.118721233 +0200 --- src/version.c 2020-05-31 15:40:22.511462518 +0200 *************** *** 748,749 **** --- 748,751 ---- { /* Add new patch number below this line */ + /**/ + 861, /**/ -- A computer without Windows is like a fish without a bicycle. /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ an exciting new programming language -- http://www.Zimbu.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///