Mercurial > vim
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