Skip to content

Instantly share code, notes, and snippets.

@koron
Created September 29, 2011 08:55
Show Gist options
  • Save koron/1250339 to your computer and use it in GitHub Desktop.
Save koron/1250339 to your computer and use it in GitHub Desktop.
eval_marks, complete with some bugs.
# HG changeset patch
# Parent 9eda149d53d824729a0953951eb0f9b8be567669
diff -r 9eda149d53d8 runtime/doc/eval.txt
--- a/runtime/doc/eval.txt Sat Sep 24 12:15:30 2011 +0900
+++ b/runtime/doc/eval.txt Sat Oct 01 22:49:27 2011 +0900
@@ -1844,6 +1844,10 @@
String rhs of mapping {name} in mode {mode}
mapcheck( {name}[, {mode} [, {abbr}]])
String check for mappings matching {name}
+markadd( {pos}) Number create a new mark
+markdelete( {id}) none delete mark identified by {id}
+markget( {id}) List get mark identified by {id}
+markupdate( {id}, {pos}) none update mark identified by {id}
match( {expr}, {pat}[, {start}[, {count}]])
Number position where {pat} matches in {expr}
matchadd( {group}, {pattern}[, {priority}[, {id}]])
diff -r 9eda149d53d8 src/buffer.c
--- a/src/buffer.c Sat Sep 24 12:15:30 2011 +0900
+++ b/src/buffer.c Sat Oct 01 22:49:27 2011 +0900
@@ -679,6 +679,9 @@
#endif
}
#ifdef FEAT_EVAL
+ emarklist_cleanup(&buf->b_emarklist);
+#endif
+#ifdef FEAT_EVAL
vars_clear(&buf->b_vars.dv_hashtab); /* free all internal variables */
hash_init(&buf->b_vars.dv_hashtab);
#endif
@@ -1731,6 +1734,9 @@
#ifdef FEAT_EVAL
init_var_dict(&buf->b_vars, &buf->b_bufvar); /* init b: variables */
#endif
+#ifdef FEAT_EVAL
+ emarklist_init(&buf->b_emarklist);
+#endif
#ifdef FEAT_SYN_HL
hash_init(&buf->b_s.b_keywtab);
hash_init(&buf->b_s.b_keywtab_ic);
diff -r 9eda149d53d8 src/eval.c
--- a/src/eval.c Sat Sep 24 12:15:30 2011 +0900
+++ b/src/eval.c Sat Oct 01 22:49:27 2011 +0900
@@ -622,6 +622,10 @@
static void f_map __ARGS((typval_T *argvars, typval_T *rettv));
static void f_maparg __ARGS((typval_T *argvars, typval_T *rettv));
static void f_mapcheck __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_markadd __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_markdelete __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_markget __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_markupdate __ARGS((typval_T *argvars, typval_T *rettv));
static void f_match __ARGS((typval_T *argvars, typval_T *rettv));
static void f_matchadd __ARGS((typval_T *argvars, typval_T *rettv));
static void f_matcharg __ARGS((typval_T *argvars, typval_T *rettv));
@@ -7868,6 +7872,10 @@
{"map", 2, 2, f_map},
{"maparg", 1, 4, f_maparg},
{"mapcheck", 1, 3, f_mapcheck},
+ {"markadd", 1, 1, f_markadd},
+ {"markdelete", 1, 1, f_markdelete},
+ {"markget", 1, 1, f_markget},
+ {"markupdate", 2, 2, f_markupdate},
{"match", 2, 4, f_match},
{"matchadd", 2, 4, f_matchadd},
{"matcharg", 1, 1, f_matcharg},
@@ -13512,6 +13520,95 @@
get_maparg(argvars, rettv, FALSE);
}
+/*
+ * "markadd()" function
+ */
+ static void
+f_markadd(argvars, rettv)
+ typval_T *argvars;
+ typval_T *rettv;
+{
+ pos_T *fp;
+ int fnum = curbuf->b_fnum;
+ emark_T *markp = NULL;
+
+ fp = var2fpos(&argvars[0], FALSE, &fnum);
+ if (fp != NULL && fnum == curbuf->b_fnum)
+ markp = emarklist_add(&curbuf->b_emarklist, fp);
+
+ rettv->vval.v_number = markp != NULL ? markp->em_id : -1;
+}
+
+/*
+ * "markdelete()" function
+ */
+ static void
+f_markdelete(argvars, rettv)
+ typval_T *argvars;
+ typval_T *rettv UNUSED;
+{
+ long id;
+
+ id = get_tv_number_chk(&argvars[0], NULL);
+ if (id >= 0)
+ emarklist_remove(&curbuf->b_emarklist, (int_u)id);
+}
+
+/*
+ * "markget()" function
+ */
+ static void
+f_markget(argvars, rettv)
+ typval_T *argvars;
+ typval_T *rettv;
+{
+ long id;
+ emark_T **markpp = NULL;
+ list_T *l;
+
+ id = get_tv_number_chk(&argvars[0], NULL);
+ if (id >= 0)
+ markpp = emarklist_find(&curbuf->b_emarklist, (int_u)id);
+
+ if (rettv_list_alloc(rettv) == OK)
+ {
+ l = rettv->vval.v_list;
+ if (markpp != NULL && *markpp != NULL)
+ {
+ pos_T *fp = &(*markpp)->em_pos;
+ list_append_number(l, (varnumber_T)fp->lnum);
+ list_append_number(l, (varnumber_T)fp->col == MAXCOL ? MAXCOL
+ : fp->col + 1);
+ }
+ }
+ else
+ rettv->vval.v_number = FALSE;
+}
+
+/*
+ * "markupdate()" function
+ */
+ static void
+f_markupdate(argvars, rettv)
+ typval_T *argvars;
+ typval_T *rettv UNUSED;
+{
+ long id;
+ emark_T **markpp = NULL;
+ pos_T *fp;
+ int fnum = curbuf->b_fnum;
+
+ id = get_tv_number_chk(&argvars[0], NULL);
+ fp = var2fpos(&argvars[1], FALSE, &fnum);
+
+ if (id >= 0 && fp != NULL && fnum == curbuf->b_fnum)
+ {
+ markpp = emarklist_find(&curbuf->b_emarklist, (int_u)id);
+ if (markpp != NULL && *markpp != NULL)
+ (*markpp)->em_pos = *fp;
+ }
+}
+
static void find_some_match __ARGS((typval_T *argvars, typval_T *rettv, int start));
static void
diff -r 9eda149d53d8 src/mark.c
--- a/src/mark.c Sat Sep 24 12:15:30 2011 +0900
+++ b/src/mark.c Sat Oct 01 22:49:27 2011 +0900
@@ -37,6 +37,12 @@
#ifdef FEAT_VIMINFO
static void write_one_filemark __ARGS((FILE *fp, xfmark_T *fm, int c1, int c2));
#endif
+#ifdef FEAT_EVAL
+static emark_T ** emark_find __ARGS((emark_T **first, int_u (*find)(emark_T *, void *), void *data));
+static int_u emark_find_equals_id __ARGS((emark_T *p, void *data));
+static int_u emark_find_over_pos __ARGS((emark_T *p, void *data));
+static void emarklist_adjust __ARGS((emarklist_T *list, linenr_T line1, linenr_T, long amount, long amount_after));
+#endif
/*
* Set named mark "c" at current cursor position.
@@ -1169,6 +1175,11 @@
/* adjust diffs */
diff_mark_adjust(line1, line2, amount, amount_after);
#endif
+
+#ifdef FEAT_EVAL
+ /* Adjust eval marks */
+ emarklist_adjust(&curbuf->b_emarklist, line1, line2, amount, amount_after);
+#endif
}
/* This code is used often, needs to be fast. */
@@ -1201,6 +1212,7 @@
int fnum = curbuf->b_fnum;
win_T *win;
pos_T *posp;
+ emark_T *emarkp;
if ((col_amount == 0L && lnum_amount == 0L) || cmdmod.lockmarks)
return; /* nothing to do */
@@ -1269,6 +1281,15 @@
col_adjust(&win->w_cursor);
}
}
+
+#ifdef FEAT_EVAL
+ /*
+ * Adjust eval marks of current buffer.
+ */
+ for (emarkp = curbuf->b_emarklist.eml_first; emarkp;
+ emarkp = emarkp->em_next)
+ col_adjust(&emarkp->em_pos);
+#endif
}
#ifdef FEAT_JUMPLIST
@@ -1799,3 +1820,163 @@
vim_free(name_buf);
}
#endif /* FEAT_VIMINFO */
+
+#ifdef FEAT_EVAL
+ void
+emarklist_init(list)
+ emarklist_T *list;
+{
+ list->eml_first = NULL;
+ list->eml_count = 0;
+ list->eml_next_id = 0;
+}
+
+ void
+emarklist_cleanup(list)
+ emarklist_T *list;
+{
+ emark_T *m;
+ emark_T *next;
+
+ for (m = list->eml_first; m; m = next)
+ {
+ next = m->em_next;
+ vim_free(m);
+ }
+ list->eml_count = 0;
+ list->eml_next_id = 0;
+}
+
+ static emark_T **
+emark_find(first, find, data)
+ emark_T **first;
+ int_u (*find)(emark_T *, void *);
+ void *data;
+{
+ emark_T **pp;
+
+ for (pp = first; *pp; pp = &(*pp)->em_next)
+ {
+ switch ((*find)(*pp, data))
+ {
+ case 1:
+ return pp;
+ case 2:
+ return &(*pp)->em_next;
+ }
+ }
+ /* not found, until end. */
+ return NULL;
+}
+
+ static int_u
+emark_find_equals_id(p, data)
+ emark_T *p;
+ void *data;
+{
+ return (p->em_id == *((int_u*)data)) ? 1 : 0;
+}
+
+ static int_u
+emark_find_over_pos(p, data)
+ emark_T *p;
+ void *data;
+{
+ pos_T *pos;
+
+ /* find an emark_T which have larger pos_T than data */
+ pos = (pos_T *)data;
+ if ((pos->lnum < p->em_pos.lnum) ||
+ (pos->lnum == p->em_pos.lnum && pos->col <= p->em_pos.col))
+ return 1;
+
+ return (p->em_next == NULL) ? 2 : 0;
+}
+
+ emark_T*
+emarklist_add(list, pos)
+ emarklist_T *list;
+ pos_T *pos;
+{
+ emark_T **pp;
+ emark_T *p;
+
+ pp = emark_find(&list->eml_first, emark_find_over_pos, pos);
+ if (pp == NULL)
+ pp = &list->eml_first;
+
+ p = (emark_T*)alloc(sizeof(*p));
+ if (p)
+ {
+ ++list->eml_count;
+ p->em_id = list->eml_next_id++;
+ p->em_pos = *pos;
+ p->em_next = *pp;
+ *pp = p;
+ }
+
+ return p;
+}
+
+ emark_T**
+emarklist_find(list, id)
+ emarklist_T *list;
+ int_u id;
+{
+ return emark_find(&list->eml_first, emark_find_equals_id, &id);
+}
+
+ void
+emarklist_remove(list, id)
+ emarklist_T *list;
+ int_u id;
+{
+ emark_T **pp;
+ emark_T *p;
+
+ pp = emarklist_find(list, id);
+ if (pp && *pp)
+ {
+ p = *pp;
+ *pp = p->em_next;
+ vim_free(p);
+ --list->eml_count;
+ }
+}
+
+ static void
+emarklist_adjust(list, line1, line2, amount, amount_after)
+ emarklist_T *list;
+ linenr_T line1;
+ linenr_T line2;
+ long amount;
+ long amount_after;
+{
+ emark_T **pp;
+ emark_T **ppnext;
+ linenr_T *lp;
+
+ /* Adjust all eval marks. */
+ for (pp = &curbuf->b_emarklist.eml_first; *pp; pp = &(*pp)->em_next)
+ one_adjust_nodel(&(*pp)->em_pos.lnum);
+
+ /* Remove invalid marks, which lnum is 0. */
+ for (pp = &curbuf->b_emarklist.eml_first; *pp; pp = ppnext)
+ {
+ if ((*pp)->em_pos.lnum != 0)
+ {
+ /* Keep current mark. */
+ ppnext = &(*pp)->em_next;
+ }
+ else
+ {
+ /* Remove current mark. */
+ emark_T *p = (*pp);
+
+ *pp = p->em_next;
+ vim_free(p);
+ --list->eml_count;
+ }
+ }
+}
+#endif /* FEAT_EVAL */
diff -r 9eda149d53d8 src/proto/mark.pro
--- a/src/proto/mark.pro Sat Sep 24 12:15:30 2011 +0900
+++ b/src/proto/mark.pro Sat Oct 01 22:49:27 2011 +0900
@@ -27,4 +27,9 @@
int removable __ARGS((char_u *name));
int write_viminfo_marks __ARGS((FILE *fp_out));
void copy_viminfo_marks __ARGS((vir_T *virp, FILE *fp_out, int count, int eof, int flags));
+void emarklist_init __ARGS((emarklist_T *list));
+void emarklist_cleanup __ARGS((emarklist_T *list));
+emark_T* emarklist_add __ARGS((emarklist_T *list, pos_T *pos));
+emark_T** emarklist_find __ARGS((emarklist_T *list, int_u id));
+void emarklist_remove __ARGS((emarklist_T *list, int_u id));
/* vim: set ft=c : */
diff -r 9eda149d53d8 src/structs.h
--- a/src/structs.h Sat Sep 24 12:15:30 2011 +0900
+++ b/src/structs.h Sat Oct 01 22:49:27 2011 +0900
@@ -111,6 +111,26 @@
char_u *fname; /* file name, used when fnum == 0 */
} xfmark_T;
+#ifdef FEAT_EVAL
+
+typedef struct evalmark_S emark_T;
+
+struct evalmark_S
+{
+ int em_id;
+ pos_T em_pos;
+ emark_T *em_next;
+};
+
+typedef struct evalmarklist_S
+{
+ emark_T *eml_first;
+ int_u eml_count;
+ int_u eml_next_id;
+} emarklist_T;
+
+#endif /* FEAT_EVAL */
+
/*
* The taggy struct is used to store the information about a :tag command.
*/
@@ -1603,6 +1623,10 @@
dict_T b_vars; /* internal variables, local to buffer */
#endif
+#ifdef FEAT_EVAL
+ emarklist_T b_emarklist;
+#endif
+
#if defined(FEAT_BEVAL) && defined(FEAT_EVAL)
char_u *b_p_bexpr; /* 'balloonexpr' local value */
long_u b_p_bexpr_flags;/* flags for 'balloonexpr' */
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment