Skip to content

Instantly share code, notes, and snippets.

@mattn
Created August 19, 2014 10:38
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/a9591869fb5d4139a2aa to your computer and use it in GitHub Desktop.
Save mattn/a9591869fb5d4139a2aa to your computer and use it in GitHub Desktop.
diff -r 7af530381fec runtime/doc/autocmd.txt
--- a/runtime/doc/autocmd.txt Sun Aug 17 17:24:07 2014 +0200
+++ b/runtime/doc/autocmd.txt Tue Aug 19 19:38:34 2014 +0900
@@ -278,6 +278,7 @@
|ShellCmdPost| after executing a shell command
|ShellFilterPost| after filtering with a shell command
+|CmdUndefined| a user command is used but it isn't defined
|FuncUndefined| a user function is used but it isn't defined
|SpellFileMissing| a spell file is used but it can't be found
|SourcePre| before sourcing a Vim script
@@ -465,6 +466,13 @@
*BufWritePost*
BufWritePost After writing the whole buffer to a file
(should undo the commands for BufWritePre).
+ *CmdUndefined*
+CmdUndefined When a user command is used but it isn't
+ defined. Useful for defining a command only
+ when it's used. The pattern is matched
+ against the command name. Both <amatch> and
+ <afile> are set to the name of the function.
+ Also the command-line is set to |v:rhs|.
*CmdwinEnter*
CmdwinEnter After entering the command-line window.
Useful for setting options specifically for
@@ -670,6 +678,7 @@
when it's used. The pattern is matched
against the function name. Both <amatch> and
<afile> are set to the name of the function.
+ Also the function name is set to |v:rhs|.
See |autoload-functions|.
*GUIEnter*
GUIEnter After starting the GUI successfully, and after
diff -r 7af530381fec runtime/doc/eval.txt
--- a/runtime/doc/eval.txt Sun Aug 17 17:24:07 2014 +0200
+++ b/runtime/doc/eval.txt Tue Aug 19 19:38:34 2014 +0900
@@ -1493,6 +1493,10 @@
This variable can not be set directly, use the |:language|
command. See |multi-lang|.
+ *v:lhs*
+v:lhs Left hand side value. This value is used for:
+ Currently, not used
+
*v:lnum* *lnum-variable*
v:lnum Line number for the 'foldexpr' |fold-expr|, 'formatexpr' and
'indentexpr' expressions, tab page number for 'guitablabel'
@@ -1578,6 +1582,11 @@
'*' or '+'.
Also see |getreg()| and |setreg()|
+ *v:rhs*
+v:rhs Right hand side value. This value is used for:
+ Command line when |CmdUndefined| occured.
+ Function name when |FuncUndefined| occured.
+
*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
diff -r 7af530381fec src/eval.c
--- a/src/eval.c Sun Aug 17 17:24:07 2014 +0200
+++ b/src/eval.c Tue Aug 19 19:38:34 2014 +0900
@@ -365,6 +365,8 @@
{VV_NAME("oldfiles", VAR_LIST), 0},
{VV_NAME("windowid", VAR_NUMBER), VV_RO},
{VV_NAME("progpath", VAR_STRING), VV_RO},
+ {VV_NAME("lhs", VAR_UNKNOWN), VV_RO},
+ {VV_NAME("rhs", VAR_UNKNOWN), VV_RO},
};
/* shorthand */
@@ -378,8 +380,6 @@
static dictitem_T vimvars_var; /* variable used for v: */
#define vimvarht vimvardict.dv_hashtab
-static void prepare_vimvar __ARGS((int idx, typval_T *save_tv));
-static void restore_vimvar __ARGS((int idx, typval_T *save_tv));
static int ex_let_vars __ARGS((char_u *arg, typval_T *tv, int copy, int semicolon, int var_count, char_u *nextchars));
static char_u *skip_var_list __ARGS((char_u *arg, int *var_count, int *semicolon));
static char_u *skip_var_one __ARGS((char_u *arg));
@@ -1453,7 +1453,7 @@
* Save the current typeval in "save_tv".
* When not used yet add the variable to the v: hashtable.
*/
- static void
+ void
prepare_vimvar(idx, save_tv)
int idx;
typval_T *save_tv;
@@ -1467,7 +1467,7 @@
* Restore v: variable "idx" to typeval "save_tv".
* When no longer defined, remove the variable from the v: hashtable.
*/
- static void
+ void
restore_vimvar(idx, save_tv)
int idx;
typval_T *save_tv;
@@ -8530,13 +8530,23 @@
#ifdef FEAT_AUTOCMD
/* Trigger FuncUndefined event, may load the function. */
- if (fp == NULL
- && apply_autocmds(EVENT_FUNCUNDEFINED,
- rfname, rfname, TRUE, NULL)
- && !aborting())
- {
- /* executed an autocommand, search for the function again */
- fp = find_func(rfname);
+ if (fp == NULL && has_funcundefined())
+ {
+ int ret;
+ typval_T rhs, save_rhs;
+ prepare_vimvar(VV_RHS, &save_rhs);
+ mch_memmove(&rhs, &save_rhs, sizeof(rhs));
+ rhs.v_type = VAR_STRING;
+ rhs.vval.v_string = rfname;
+ restore_vimvar(VV_RHS, &rhs);
+ ret = apply_autocmds(EVENT_FUNCUNDEFINED,
+ rfname, rfname, TRUE, NULL);
+ restore_vimvar(VV_RHS, &save_rhs);
+ if (ret && !aborting())
+ {
+ /* executed an autocommand, search for the function again */
+ fp = find_func(rfname);
+ }
}
#endif
/* Try loading a package. */
diff -r 7af530381fec src/ex_docmd.c
--- a/src/ex_docmd.c Sun Aug 17 17:24:07 2014 +0200
+++ b/src/ex_docmd.c Tue Aug 19 19:38:34 2014 +0900
@@ -2142,6 +2142,23 @@
/* Find the command and let "p" point to after it. */
p = find_command(&ea, NULL);
+#ifdef FEAT_AUTOCMD
+ if (p != NULL && ea.cmdidx == CMD_SIZE && !ea.skip &&
+ ASCII_ISUPPER(*ea.cmd) && has_cmdundefined())
+ {
+ int ret;
+ typval_T rhs, save_rhs;
+ prepare_vimvar(VV_RHS, &save_rhs);
+ mch_memmove(&rhs, &save_rhs, sizeof(rhs));
+ rhs.v_type = VAR_STRING;
+ rhs.vval.v_string = *cmdlinep;
+ restore_vimvar(VV_RHS, &rhs);
+ ret = apply_autocmds(EVENT_CMDUNDEFINED, NULL, NULL, FALSE, curbuf);
+ restore_vimvar(VV_RHS, &save_rhs);
+ if (ret && !aborting())
+ p = find_command(&ea, NULL);
+ }
+#endif
#ifdef FEAT_USR_CMDS
if (p == NULL)
diff -r 7af530381fec src/fileio.c
--- a/src/fileio.c Sun Aug 17 17:24:07 2014 +0200
+++ b/src/fileio.c Tue Aug 19 19:38:34 2014 +0900
@@ -7642,6 +7642,7 @@
{"CmdwinEnter", EVENT_CMDWINENTER},
{"CmdwinLeave", EVENT_CMDWINLEAVE},
{"ColorScheme", EVENT_COLORSCHEME},
+ {"CmdUndefined", EVENT_CMDUNDEFINED},
{"CompleteDone", EVENT_COMPLETEDONE},
{"CursorHold", EVENT_CURSORHOLD},
{"CursorHoldI", EVENT_CURSORHOLDI},
@@ -9159,6 +9160,25 @@
return (first_autopat[(int)EVENT_INSERTCHARPRE] != NULL);
}
+/*
+ * Return TRUE when there is an CmdUndefined autocommand defined.
+ */
+ int
+has_cmdundefined()
+{
+ return (first_autopat[(int)EVENT_CMDUNDEFINED] != NULL);
+}
+
+/*
+ * Return TRUE when there is an FuncUndefined autocommand defined.
+ */
+ int
+has_funcundefined()
+{
+ return (first_autopat[(int)EVENT_FUNCUNDEFINED] != NULL);
+}
+
+
static int
apply_autocmds_group(event, fname, fname_io, force, group, buf, eap)
event_T event;
diff -r 7af530381fec src/proto/eval.pro
--- a/src/proto/eval.pro Sun Aug 17 17:24:07 2014 +0200
+++ b/src/proto/eval.pro Tue Aug 19 19:38:34 2014 +0900
@@ -134,4 +134,6 @@
void ex_oldfiles __ARGS((exarg_T *eap));
int modify_fname __ARGS((char_u *src, int *usedlen, char_u **fnamep, char_u **bufp, int *fnamelen));
char_u *do_string_sub __ARGS((char_u *str, char_u *pat, char_u *sub, char_u *flags));
+void prepare_vimvar __ARGS((int idx, typval_T *save_tv));
+void restore_vimvar __ARGS((int idx, typval_T *save_tv));
/* vim: set ft=c : */
diff -r 7af530381fec src/proto/fileio.pro
--- a/src/proto/fileio.pro Sun Aug 17 17:24:07 2014 +0200
+++ b/src/proto/fileio.pro Tue Aug 19 19:38:34 2014 +0900
@@ -47,6 +47,8 @@
int has_textchanged __ARGS((void));
int has_textchangedI __ARGS((void));
int has_insertcharpre __ARGS((void));
+int has_cmdundefined __ARGS((void));
+int has_funcundefined __ARGS((void));
void block_autocmds __ARGS((void));
void unblock_autocmds __ARGS((void));
int is_autocmd_blocked __ARGS((void));
diff -r 7af530381fec src/vim.h
--- a/src/vim.h Sun Aug 17 17:24:07 2014 +0200
+++ b/src/vim.h Tue Aug 19 19:38:34 2014 +0900
@@ -1326,6 +1326,7 @@
EVENT_SHELLFILTERPOST, /* after ":1,2!cmd", ":w !cmd", ":r !cmd". */
EVENT_TEXTCHANGED, /* text was modified */
EVENT_TEXTCHANGEDI, /* text was modified in Insert mode*/
+ EVENT_CMDUNDEFINED, /* command undefined */
NUM_EVENTS /* MUST be the last one */
};
@@ -1888,7 +1889,9 @@
#define VV_OLDFILES 55
#define VV_WINDOWID 56
#define VV_PROGPATH 57
-#define VV_LEN 58 /* number of v: vars */
+#define VV_LHS 58
+#define VV_RHS 59
+#define VV_LEN 60 /* 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