0
0
mirror of https://github.com/vim/vim.git synced 2025-07-26 11:04:33 -04:00

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 #6032)
This commit is contained in:
Bram Moolenaar 2020-05-31 15:41:57 +02:00
parent aaad995f83
commit cfb4b47de0
7 changed files with 171 additions and 0 deletions

View File

@ -2497,6 +2497,7 @@ getjumplist([{winnr} [, {tabnr}]])
getline({lnum}) String line {lnum} of current buffer getline({lnum}) String line {lnum} of current buffer
getline({lnum}, {end}) List lines {lnum} to {end} of current buffer getline({lnum}, {end}) List lines {lnum} to {end} of current buffer
getloclist({nr} [, {what}]) List list of location list items getloclist({nr} [, {what}]) List list of location list items
getmarklist([{expr}]) List list of global/local marks
getmatches([{win}]) List list of current matches getmatches([{win}]) List list of current matches
getmousepos() Dict last known mouse position getmousepos() Dict last known mouse position
getpid() Number process ID of Vim getpid() Number process ID of Vim
@ -5365,6 +5366,25 @@ getloclist({nr} [, {what}]) *getloclist()*
|location-list-file-window| for more |location-list-file-window| for more
details. 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()* getmatches([{win}]) *getmatches()*
Returns a |List| with all matches previously defined for the Returns a |List| with all matches previously defined for the
current window by |matchadd()| and the |:match| commands. current window by |matchadd()| and the |:match| commands.

View File

@ -724,6 +724,7 @@ Cursor and mark position: *cursor-functions* *mark-functions*
getcurpos() get position of the cursor getcurpos() get position of the cursor
getpos() get position of cursor, mark, etc. getpos() get position of cursor, mark, etc.
setpos() set 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 byte2line() get line number at a specific byte count
line2byte() byte count at a specific line line2byte() byte count at a specific line
diff_filler() get the number of filler lines above a line diff_filler() get the number of filler lines above a line

View File

@ -579,6 +579,7 @@ static funcentry_T global_functions[] =
{"getjumplist", 0, 2, FEARG_1, ret_list_any, f_getjumplist}, {"getjumplist", 0, 2, FEARG_1, ret_list_any, f_getjumplist},
{"getline", 1, 2, FEARG_1, ret_f_getline, f_getline}, {"getline", 1, 2, FEARG_1, ret_f_getline, f_getline},
{"getloclist", 1, 2, 0, ret_list_dict_any, f_getloclist}, {"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}, {"getmatches", 0, 1, 0, ret_list_dict_any, f_getmatches},
{"getmousepos", 0, 0, 0, ret_dict_number, f_getmousepos}, {"getmousepos", 0, 0, 0, ret_dict_number, f_getmousepos},
{"getpid", 0, 0, 0, ret_number, f_getpid}, {"getpid", 0, 0, 0, ret_number, f_getpid},

View File

@ -1412,3 +1412,124 @@ get_namedfm(void)
{ {
return namedfm; 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

View File

@ -27,4 +27,5 @@ void free_jumplist(win_T *wp);
void set_last_cursor(win_T *win); void set_last_cursor(win_T *win);
void free_all_marks(void); void free_all_marks(void);
xfmark_T *get_namedfm(void); xfmark_T *get_namedfm(void);
void f_getmarklist(typval_T *argvars, typval_T *rettv);
/* vim: set ft=c : */ /* vim: set ft=c : */

View File

@ -259,4 +259,29 @@ func Test_file_mark()
call delete('Xtwo') call delete('Xtwo')
endfunc 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: shiftwidth=2 sts=2 expandtab

View File

@ -746,6 +746,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
861,
/**/ /**/
860, 860,
/**/ /**/