aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarco Hinz <mh.codebro@gmail.com>2014-04-13 20:26:17 +0200
committerThiago de Arruda <tpadilha84@gmail.com>2014-04-16 09:29:33 -0300
commitf54c050cf3389a6e646bd0e6cd80476c01cd752c (patch)
tree1f9ffe605ddb0d41945b976e6cbcd1738b6d5caf
parent98b0a6ffb460ffdc6b84b4273d8f9834803bfd31 (diff)
downloadrneovim-f54c050cf3389a6e646bd0e6cd80476c01cd752c.tar.gz
rneovim-f54c050cf3389a6e646bd0e6cd80476c01cd752c.tar.bz2
rneovim-f54c050cf3389a6e646bd0e6cd80476c01cd752c.zip
vim-patch:7.4.218
Problem: It's not easy to remove duplicates from a list. Solution: Add the uniq() function. (LCD) https://code.google.com/p/vim/source/detail?r=ddc3f32a4b2191f829206322d46f0e9c7e365e22
-rw-r--r--src/eval.c112
-rw-r--r--src/testdir/test55.in6
-rw-r--r--src/testdir/test55.ok12
-rw-r--r--src/version.c2
4 files changed, 95 insertions, 37 deletions
diff --git a/src/eval.c b/src/eval.c
index 187a7014b2..fa5a920939 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -758,6 +758,7 @@ static void f_trunc(typval_T *argvars, typval_T *rettv);
static void f_type(typval_T *argvars, typval_T *rettv);
static void f_undofile(typval_T *argvars, typval_T *rettv);
static void f_undotree(typval_T *argvars, typval_T *rettv);
+static void f_uniq(typval_T *argvars, typval_T *rettv);
static void f_values(typval_T *argvars, typval_T *rettv);
static void f_virtcol(typval_T *argvars, typval_T *rettv);
static void f_visualmode(typval_T *argvars, typval_T *rettv);
@@ -7074,6 +7075,7 @@ static struct fst {
{"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},
@@ -13777,10 +13779,11 @@ static int item_compare_ic;
static char_u *item_compare_func;
static dict_T *item_compare_selfdict;
static int item_compare_func_err;
+static void do_sort_uniq(typval_T *argvars, typval_T *rettv, bool sort);
#define ITEM_COMPARE_FAIL 999
/*
- * Compare functions for f_sort() below.
+ * Compare functions for f_sort() and f_uniq() below.
*/
static int item_compare(const void *s1, const void *s2)
{
@@ -13841,7 +13844,7 @@ static int item_compare2(const void *s1, const void *s2)
/*
* "sort({list})" function
*/
-static void f_sort(typval_T *argvars, typval_T *rettv)
+static void do_sort_uniq(typval_T *argvars, typval_T *rettv, bool sort)
{
list_T *l;
listitem_T *li;
@@ -13849,13 +13852,14 @@ static void f_sort(typval_T *argvars, typval_T *rettv)
long len;
long i;
- if (argvars[0].v_type != VAR_LIST)
- EMSG2(_(e_listarg), "sort()");
- else {
+ if (argvars[0].v_type != VAR_LIST) {
+ 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;
++l->lv_refcount;
@@ -13867,11 +13871,12 @@ static void f_sort(typval_T *argvars, typval_T *rettv)
item_compare_ic = FALSE;
item_compare_func = NULL;
item_compare_selfdict = NULL;
+
if (argvars[1].v_type != VAR_UNKNOWN) {
/* optional second argument: {func} */
- if (argvars[1].v_type == VAR_FUNC)
+ if (argvars[1].v_type == VAR_FUNC) {
item_compare_func = argvars[1].vval.v_string;
- else {
+ } else {
int error = FALSE;
i = get_tv_number_chk(&argvars[1], &error);
@@ -13894,30 +13899,67 @@ static void f_sort(typval_T *argvars, typval_T *rettv)
}
/* Make an array with each entry pointing to an item in the List. */
- ptrs = (listitem_T **)alloc((int)(len * sizeof(listitem_T *)));
- if (ptrs == NULL)
- return;
+ ptrs = xmalloc((size_t)(len * sizeof (listitem_T *)));
+
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])
- == ITEM_COMPARE_FAIL)
- 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 (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(&ptrs[0], &ptrs[1]) == ITEM_COMPARE_FAIL) {
+ EMSG(_("E702: Sort compare function failed"));
+ } else {
+ // Sort the array with item pointers.
+ qsort(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 the sorted order.
+ l->lv_first = NULL;
+ l->lv_last = NULL;
+ l->lv_idx_item = NULL;
+ l->lv_len = 0;
+
+ for (i = 0; i < len; i++) {
+ list_append(l, ptrs[i]);
+ }
+ }
+ }
+ } else {
+ int (*item_compare_func_ptr)(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(&li, &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--;
+ }
}
}
@@ -13925,6 +13967,18 @@ static void f_sort(typval_T *argvars, typval_T *rettv)
}
}
+/// "sort"({list})" function
+static void f_sort(typval_T *argvars, typval_T *rettv)
+{
+ do_sort_uniq(argvars, rettv, true);
+}
+
+/// "uniq({list})" function
+static void f_uniq(typval_T *argvars, typval_T *rettv)
+{
+ do_sort_uniq(argvars, rettv, false);
+}
+
/*
* "soundfold({word})" function
*/
diff --git a/src/testdir/test55.in b/src/testdir/test55.in
index 4b20de403f..85a8063774 100644
--- a/src/testdir/test55.in
+++ b/src/testdir/test55.in
@@ -323,13 +323,15 @@ let l = [0, 1, 2, 3]
: $put ='caught ' . v:exception
:endtry
:"
-:" reverse() and sort()
-:let l = ['-0', 'A11', 2, 'xaaa', 4, 'foo', 'foo6', [0, 1, 2], 'x8']
+:" reverse(), sort(), uniq()
+:let l = ['-0', 'A11', 2, 2, 'xaaa', 4, 'foo', 'foo6', 'foo', [0, 1, 2], 'x8', [0, 1, 2], 1.5]
+:$put =string(uniq(copy(l)))
:$put =string(reverse(l))
:$put =string(reverse(reverse(l)))
:$put =string(sort(l))
:$put =string(reverse(sort(l)))
:$put =string(sort(reverse(sort(l))))
+:$put =string(uniq(sort(l)))
:"
:" splitting a string to a List
:$put =string(split(' aa bb '))
diff --git a/src/testdir/test55.ok b/src/testdir/test55.ok
index 396c9bed19..be476e8e93 100644
--- a/src/testdir/test55.ok
+++ b/src/testdir/test55.ok
@@ -94,11 +94,13 @@ caught a:000[0]
caught a:000[2]
caught a:000[3]
[1, 2, [3, 9, 5, 6], {'a': 12, '5': 8}]
-['x8', [0, 1, 2], 'foo6', 'foo', 4, 'xaaa', 2, 'A11', '-0']
-['x8', [0, 1, 2], 'foo6', 'foo', 4, 'xaaa', 2, 'A11', '-0']
-['-0', 'A11', 'foo', 'foo6', 'x8', 'xaaa', 2, 4, [0, 1, 2]]
-[[0, 1, 2], 4, 2, 'xaaa', 'x8', 'foo6', 'foo', 'A11', '-0']
-['-0', 'A11', 'foo', 'foo6', 'x8', 'xaaa', 2, 4, [0, 1, 2]]
+['-0', 'A11', 2, 'xaaa', 4, 'foo', 'foo6', 'foo', [0, 1, 2], 'x8', [0, 1, 2], 1.5]
+[1.5, [0, 1, 2], 'x8', [0, 1, 2], 'foo', 'foo6', 'foo', 4, 'xaaa', 2, 2, 'A11', '-0']
+[1.5, [0, 1, 2], 'x8', [0, 1, 2], 'foo', 'foo6', 'foo', 4, 'xaaa', 2, 2, 'A11', '-0']
+['-0', 'A11', 'foo', 'foo', 'foo6', 'x8', 'xaaa', 1.5, 2, 2, 4, [0, 1, 2], [0, 1, 2]]
+[[0, 1, 2], [0, 1, 2], 4, 2, 2, 1.5, 'xaaa', 'x8', 'foo6', 'foo', 'foo', 'A11', '-0']
+['-0', 'A11', 'foo', 'foo', 'foo6', 'x8', 'xaaa', 1.5, 2, 2, 4, [0, 1, 2], [0, 1, 2]]
+['-0', 'A11', 'foo', 'foo6', 'x8', 'xaaa', 1.5, 2, 4, [0, 1, 2]]
['aa', 'bb']
['aa', 'bb']
['', 'aa', 'bb', '']
diff --git a/src/version.c b/src/version.c
index 2df590f1a7..a9d8e3f753 100644
--- a/src/version.c
+++ b/src/version.c
@@ -243,7 +243,7 @@ static int included_patches[] = {
//221,
//220,
219,
- //218,
+ 218,
//217,
//216,
215,