diff options
author | Marco Hinz <mh.codebro@gmail.com> | 2014-04-13 20:26:17 +0200 |
---|---|---|
committer | Thiago de Arruda <tpadilha84@gmail.com> | 2014-04-16 09:29:33 -0300 |
commit | f54c050cf3389a6e646bd0e6cd80476c01cd752c (patch) | |
tree | 1f9ffe605ddb0d41945b976e6cbcd1738b6d5caf /src | |
parent | 98b0a6ffb460ffdc6b84b4273d8f9834803bfd31 (diff) | |
download | rneovim-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
Diffstat (limited to 'src')
-rw-r--r-- | src/eval.c | 112 | ||||
-rw-r--r-- | src/testdir/test55.in | 6 | ||||
-rw-r--r-- | src/testdir/test55.ok | 12 | ||||
-rw-r--r-- | src/version.c | 2 |
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, |