updated for version 7.4.218
Problem: It's not easy to remove duplicates from a list.
Solution: Add the uniq() function. (LCD)
diff --git a/src/eval.c b/src/eval.c
index 12794d4..baaa12f 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -744,6 +744,7 @@
static void f_type __ARGS((typval_T *argvars, typval_T *rettv));
static void f_undofile __ARGS((typval_T *argvars, typval_T *rettv));
static void f_undotree __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_uniq __ARGS((typval_T *argvars, typval_T *rettv));
static void f_values __ARGS((typval_T *argvars, typval_T *rettv));
static void f_virtcol __ARGS((typval_T *argvars, typval_T *rettv));
static void f_visualmode __ARGS((typval_T *argvars, typval_T *rettv));
@@ -8150,6 +8151,7 @@
{"type", 1, 1, f_type},
{"undofile", 1, 1, f_undofile},
{"undotree", 0, 0, f_undotree},
+ {"uniq", 1, 3, f_uniq},
{"values", 1, 1, f_values},
{"virtcol", 1, 1, f_virtcol},
{"visualmode", 0, 1, f_visualmode},
@@ -17023,10 +17025,11 @@
static char_u *item_compare_func;
static dict_T *item_compare_selfdict;
static int item_compare_func_err;
+static void do_sort_uniq __ARGS((typval_T *argvars, typval_T *rettv, int sort));
#define ITEM_COMPARE_FAIL 999
/*
- * Compare functions for f_sort() below.
+ * Compare functions for f_sort() and f_uniq() below.
*/
static int
#ifdef __BORLANDC__
@@ -17100,9 +17103,10 @@
* "sort({list})" function
*/
static void
-f_sort(argvars, rettv)
+do_sort_uniq(argvars, rettv, sort)
typval_T *argvars;
typval_T *rettv;
+ int sort;
{
list_T *l;
listitem_T *li;
@@ -17111,12 +17115,12 @@
long i;
if (argvars[0].v_type != VAR_LIST)
- EMSG2(_(e_listarg), "sort()");
+ EMSG2(_(e_listarg), sort ? "sort()" : "uniq()");
else
{
l = argvars[0].vval.v_list;
if (l == NULL || tv_check_lock(l->lv_lock,
- (char_u *)_("sort() argument")))
+ (char_u *)(sort ? _("sort() argument") : _("uniq() argument"))))
return;
rettv->vval.v_list = l;
rettv->v_type = VAR_LIST;
@@ -17163,29 +17167,72 @@
ptrs = (listitem_T **)alloc((int)(len * sizeof(listitem_T *)));
if (ptrs == NULL)
return;
- i = 0;
- for (li = l->lv_first; li != NULL; li = li->li_next)
- ptrs[i++] = li;
- item_compare_func_err = FALSE;
- /* test the compare function */
- if (item_compare_func != NULL
- && item_compare2((void *)&ptrs[0], (void *)&ptrs[1])
+ i = 0;
+ if (sort)
+ {
+ /* sort(): ptrs will be the list to sort */
+ for (li = l->lv_first; li != NULL; li = li->li_next)
+ ptrs[i++] = li;
+
+ item_compare_func_err = FALSE;
+ /* test the compare function */
+ if (item_compare_func != NULL
+ && item_compare2((void *)&ptrs[0], (void *)&ptrs[1])
== ITEM_COMPARE_FAIL)
- EMSG(_("E702: Sort compare function failed"));
+ EMSG(_("E702: Sort compare function failed"));
+ else
+ {
+ /* Sort the array with item pointers. */
+ qsort((void *)ptrs, (size_t)len, sizeof(listitem_T *),
+ item_compare_func == NULL ? item_compare : item_compare2);
+
+ if (!item_compare_func_err)
+ {
+ /* Clear the List and append the items in sorted order. */
+ l->lv_first = l->lv_last = l->lv_idx_item = NULL;
+ l->lv_len = 0;
+ for (i = 0; i < len; ++i)
+ list_append(l, ptrs[i]);
+ }
+ }
+ }
else
{
- /* Sort the array with item pointers. */
- qsort((void *)ptrs, (size_t)len, sizeof(listitem_T *),
- item_compare_func == NULL ? item_compare : item_compare2);
+ int (*item_compare_func_ptr)__ARGS((const void *, const void *));
+
+ /* f_uniq(): ptrs will be a stack of items to remove */
+ item_compare_func_err = FALSE;
+ item_compare_func_ptr = item_compare_func
+ ? item_compare2 : item_compare;
+
+ for (li = l->lv_first; li != NULL && li->li_next != NULL;
+ li = li->li_next)
+ {
+ if (item_compare_func_ptr((void *)&li, (void *)&li->li_next)
+ == 0)
+ ptrs[i++] = li;
+ if (item_compare_func_err)
+ {
+ EMSG(_("E882: Uniq compare function failed"));
+ break;
+ }
+ }
if (!item_compare_func_err)
{
- /* Clear the List and append the items in the sorted order. */
- l->lv_first = l->lv_last = l->lv_idx_item = NULL;
- l->lv_len = 0;
- for (i = 0; i < len; ++i)
- list_append(l, ptrs[i]);
+ while (--i >= 0)
+ {
+ li = ptrs[i]->li_next;
+ ptrs[i]->li_next = li->li_next;
+ if (li->li_next != NULL)
+ li->li_next->li_prev = ptrs[i];
+ else
+ l->lv_last = ptrs[i];
+ list_fix_watch(l, li);
+ listitem_free(li);
+ l->lv_len--;
+ }
}
}
@@ -17194,6 +17241,28 @@
}
/*
+ * "sort({list})" function
+ */
+ static void
+f_sort(argvars, rettv)
+ typval_T *argvars;
+ typval_T *rettv;
+{
+ do_sort_uniq(argvars, rettv, TRUE);
+}
+
+/*
+ * "uniq({list})" function
+ */
+ static void
+f_uniq(argvars, rettv)
+ typval_T *argvars;
+ typval_T *rettv;
+{
+ do_sort_uniq(argvars, rettv, FALSE);
+}
+
+/*
* "soundfold({word})" function
*/
static void