Skip to content

Instantly share code, notes, and snippets.

@mattn
Last active December 17, 2015 22:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mattn/5684747 to your computer and use it in GitHub Desktop.
Save mattn/5684747 to your computer and use it in GitHub Desktop.
diff -r b792349dc858 runtime/doc/eval.txt
--- a/runtime/doc/eval.txt Thu May 30 22:44:02 2013 +0200
+++ b/runtime/doc/eval.txt Fri May 31 22:28:00 2013 +0900
@@ -1477,6 +1477,8 @@
in a different language than what is used for character
encoding. See |multi-lang|.
+v:lhs Left hand side of compareing for |sort()|.
+
*v:lc_time* *lc_time-variable*
v:lc_time The current locale setting for time messages of the runtime
environment. This allows Vim scripts to be aware of the
@@ -1558,6 +1560,9 @@
'*' or '+'.
Also see |getreg()| and |setreg()|
+v:rhs Right hand side of compareing for |sort()|.
+
+ *v:lc_time* *lc_time-variable*
*v:scrollstart* *scrollstart-variable*
v:scrollstart String describing the script or function that caused the
screen to scroll up. It's only set when it is empty, thus the
@@ -5438,13 +5443,15 @@
Numbers sort after Strings, |Lists| after Numbers.
For sorting text in the current buffer use |:sort|.
When {func} is given and it is one then case is ignored.
- {dict} is for functions with the "dict" attribute. It will be
- used to set the local variable "self". |Dictionary-function|
- When {func} is a |Funcref| or a function name, this function
- is called to compare items. The function is invoked with two
- items as argument and must return zero if they are equal, 1 or
- bigger if the first one sorts after the second one, -1 or
- smaller if the first one sorts before the second one.
+ {dict} is for functions with the "dict" attribute. It will b
+ e used to set the local variable "self". |Dictionary-function|
+ When {func} is a |Funcref| or a function name, or expression.
+ The {func} is called/evaluate to compare items. The function
+ is invoked with two items as argument and must return zero if
+ they are equal, 1 or bigger if the first one sorts after th
+ e second one, -1 or smaller if the first one sorts before the
+ second one.
+ Example: >
Example: >
func MyCompare(i1, i2)
return a:i1 == a:i2 ? 0 : a:i1 > a:i2 ? 1 : -1
@@ -5455,6 +5462,10 @@
func MyCompare(i1, i2)
return a:i1 - a:i2
endfunc
+< If {func} is expression, |v:lhs| and |v:rhs| are given to
+ compareing: >
+ let mylist = [{"foo":3},{"foo":2},{"foo":4}]
+ :echo sort(mylist, "v:lhs.foo - v:rhs.foo")
<
*soundfold()*
soundfold({word})
diff -r b792349dc858 src/eval.c
--- a/src/eval.c Thu May 30 22:44:02 2013 +0200
+++ b/src/eval.c Fri May 31 22:28:00 2013 +0900
@@ -355,6 +355,8 @@
{VV_NAME("searchforward", VAR_NUMBER), 0},
{VV_NAME("oldfiles", VAR_LIST), 0},
{VV_NAME("windowid", VAR_NUMBER), VV_RO},
+ {VV_NAME("lhs", VAR_UNKNOWN), VV_RO},
+ {VV_NAME("rhs", VAR_UNKNOWN), VV_RO},
};
/* shorthand */
@@ -16831,6 +16833,7 @@
item_compare2 __ARGS((const void *s1, const void *s2));
static int item_compare_ic;
+static int item_compare_expr;
static char_u *item_compare_func;
static dict_T *item_compare_selfdict;
static int item_compare_func_err;
@@ -16891,7 +16894,23 @@
copy_tv(&(*(listitem_T **)s2)->li_tv, &argv[1]);
rettv.v_type = VAR_UNKNOWN; /* clear_tv() uses this */
- res = call_func(item_compare_func, (int)STRLEN(item_compare_func),
+
+ if (item_compare_expr)
+ {
+ char_u *expr = item_compare_func;
+ typval_T save_lhs, save_rhs;
+ prepare_vimvar(VV_LHS, &save_lhs);
+ prepare_vimvar(VV_RHS, &save_rhs);
+ vimvars[VV_LHS].vv_type = VAR_UNKNOWN;
+ vimvars[VV_LHS].vv_tv = argv[0];
+ vimvars[VV_RHS].vv_type = VAR_UNKNOWN;
+ vimvars[VV_RHS].vv_tv = argv[1];
+ res = eval1(&expr, &rettv, TRUE);
+ restore_vimvar(VV_LHS, &save_lhs);
+ restore_vimvar(VV_RHS, &save_rhs);
+ }
+ else
+ res = call_func(item_compare_func, (int)STRLEN(item_compare_func),
&rettv, 2, argv, 0L, 0L, &dummy, TRUE,
item_compare_selfdict);
clear_tv(&argv[0]);
@@ -16938,6 +16957,7 @@
return; /* short list sorts pretty quickly */
item_compare_ic = FALSE;
+ item_compare_expr = FALSE;
item_compare_func = NULL;
item_compare_selfdict = NULL;
if (argvars[1].v_type != VAR_UNKNOWN)
@@ -16968,6 +16988,17 @@
}
item_compare_selfdict = argvars[2].vval.v_dict;
}
+
+ if (item_compare_func != NULL && item_compare_selfdict == NULL)
+ {
+ char_u* name;
+ if ((name = get_expanded_name(item_compare_func,
+ vim_strchr(item_compare_func, AUTOLOAD_CHAR) == NULL))
+ == NULL)
+ {
+ item_compare_expr = TRUE;
+ }
+ }
}
/* Make an array with each entry pointing to an item in the List. */
diff -r b792349dc858 src/vim.h
--- a/src/vim.h Thu May 30 22:44:02 2013 +0200
+++ b/src/vim.h Fri May 31 22:28:00 2013 +0900
@@ -1862,7 +1862,9 @@
#define VV_SEARCHFORWARD 53
#define VV_OLDFILES 54
#define VV_WINDOWID 55
-#define VV_LEN 56 /* number of v: vars */
+#define VV_LHS 56
+#define VV_RHS 57
+#define VV_LEN 58 /* number of v: vars */
#ifdef FEAT_CLIPBOARD
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment