Skip to content

Instantly share code, notes, and snippets.

@mattn
Last active February 19, 2016 10:56
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/ca264155959f476bc8dd to your computer and use it in GitHub Desktop.
Save mattn/ca264155959f476bc8dd to your computer and use it in GitHub Desktop.
patch for mapgroup
diff --git a/runtime/doc/map.txt b/runtime/doc/map.txt
index 4e7a784..3f46f24 100644
--- a/runtime/doc/map.txt
+++ b/runtime/doc/map.txt
@@ -21,6 +21,7 @@ manual.
1.9 Using mappings |map-typing|
1.10 Mapping alt-keys |:map-alt-keys|
1.11 Mapping an operator |:map-operator|
+ 1.12 Groups |:mapgroup|
2. Abbreviations |abbreviations|
3. Local mappings and functions |script-local|
4. User-defined commands |user-commands|
@@ -850,6 +851,38 @@ Also note that there is a separate mapping for Visual mode. It removes the
"'<,'>" range that ":" inserts in Visual mode and invokes the function with
visualmode() and an extra argument.
+1.12 GROUPS *:mapgroup*
+
+Mapping can be put together in a group. This is useful for removing mappings
+in each groups.
+
+ *:mapg* *:mapgroup*
+:mapg[roup] {name} Define the map group name for the
+ following ":map" commands. The name "end"
+ or "END" selects the default group.
+ To avoid confusion, the name should be
+ different from existing {mapping} names, as
+ this most likely will not do what you
+ intended. i.e. plugin name.
+
+ *:mapgroup-delete* *E367*
+:mapg[roup]! {name} Delete the map group {name}. Don't use
+ this if there is still map using this group!
+ This is not checked.
+
+When mappings are registered in the group, you can remove them like below.
+
+Example: >
+ :mapgroup ToolWindow
+ : map <F2> call toolwindow#prev()
+ : map <F3> call toolwindow#next()
+ : map <F4> call toolwindow#close()
+ :mapgroup END
+
+ :mapgroup ToolWindow
+ : mapclear
+ :mapgroup END
+
==============================================================================
2. Abbreviations *abbreviations* *Abbreviations*
diff --git a/src/ex_cmds.h b/src/ex_cmds.h
index 89f84ed..ea6f4b6 100644
--- a/src/ex_cmds.h
+++ b/src/ex_cmds.h
@@ -877,6 +877,9 @@ EX(CMD_map, "map", ex_map,
EX(CMD_mapclear, "mapclear", ex_mapclear,
EXTRA|BANG|TRLBAR|CMDWIN,
ADDR_LINES),
+EX(CMD_mapgroup, "mapgroup", ex_mapgroup,
+ BANG|WORD1|TRLBAR|CMDWIN,
+ ADDR_LINES),
EX(CMD_marks, "marks", do_marks,
EXTRA|TRLBAR|CMDWIN,
ADDR_LINES),
diff --git a/src/ex_docmd.c b/src/ex_docmd.c
index 1321b7f..cad0712 100644
--- a/src/ex_docmd.c
+++ b/src/ex_docmd.c
@@ -76,6 +76,7 @@ static void ex_map(exarg_T *eap);
static void ex_unmap(exarg_T *eap);
static void ex_mapclear(exarg_T *eap);
static void ex_abclear(exarg_T *eap);
+static void ex_mapgroup(exarg_T *eap);
#ifndef FEAT_MENU
# define ex_emenu ex_ni
# define ex_menu ex_ni
@@ -5416,6 +5417,11 @@ ex_mapclear(exarg_T *eap)
map_clear(eap->cmd, eap->arg, eap->forceit, FALSE);
}
+ static void
+ex_mapgroup(exarg_T *eap)
+{
+ do_mapgroup(eap->arg, eap->forceit);
+}
/*
* ":abclear" and friends.
*/
diff --git a/src/getchar.c b/src/getchar.c
index 0347514..88f0200 100644
--- a/src/getchar.c
+++ b/src/getchar.c
@@ -102,6 +102,21 @@ static int KeyNoremap = 0; /* remapping flags */
#define RM_SCRIPT 2 /* tb_noremap: remap local script mappings */
#define RM_ABBR 4 /* tb_noremap: don't remap, do abbrev. */
+# define MAPGROUP_DEFAULT -1 /* default map group */
+# define MAPGROUP_ERROR -2 /* erroneous map group */
+# define MAPGROUP_ALL -3 /* all map groups */
+
+/*
+ * mapgroups stores a list of map group names.
+ */
+static garray_T mapgroups = {0, 0, sizeof(char_u *), 10, NULL};
+#define MAPGROUP_NAME(i) (((char_u **)mapgroups.ga_data)[i])
+
+/*
+ * The ID of the current map group. Group 0 is the default one.
+ */
+int current_mapgroup = MAPGROUP_DEFAULT;
+
/* typebuf.tb_buf has three parts: room in front (for result of mappings), the
* middle for typeahead and room for new characters (which needs to be 3 *
* MAXMAPLEN) for the Amiga).
@@ -3642,6 +3657,7 @@ do_map(
mp->m_expr = expr;
mp->m_script_ID = current_SID;
#endif
+ mp->m_group = current_mapgroup;
did_it = TRUE;
}
}
@@ -3748,6 +3764,7 @@ do_map(
mp->m_expr = expr;
mp->m_script_ID = current_SID;
#endif
+ mp->m_group = current_mapgroup;
/* add the new entry in front of the abbrlist or maphash[] list */
if (abbrev)
@@ -3872,6 +3889,93 @@ map_clear(
abbr);
}
+ static int
+map_find_group(char_u *name)
+{
+ int i;
+
+ for (i = 0; i < mapgroups.ga_len; ++i)
+ if (MAPGROUP_NAME(i) != NULL && STRCMP(MAPGROUP_NAME(i), name) == 0)
+ return i;
+ return MAPGROUP_ERROR;
+}
+
+ static int
+map_new_group(char_u *name)
+{
+ int i;
+
+ i = map_find_group(name);
+ if (i == MAPGROUP_ERROR) /* the group doesn't exist yet, add it */
+ {
+ /* First try using a free entry. */
+ for (i = 0; i < mapgroups.ga_len; ++i)
+ if (MAPGROUP_NAME(i) == NULL)
+ break;
+ if (i == mapgroups.ga_len && ga_grow(&mapgroups, 1) == FAIL)
+ return MAPGROUP_ERROR;
+
+ MAPGROUP_NAME(i) = vim_strsave(name);
+ if (MAPGROUP_NAME(i) == NULL)
+ return MAPGROUP_ERROR;
+ if (i == mapgroups.ga_len)
+ ++mapgroups.ga_len;
+ }
+
+ return i;
+}
+
+ static void
+map_del_group(char_u *name)
+{
+ int i;
+
+ i = map_find_group(name);
+ if (i == MAPGROUP_ERROR) /* the group doesn't exist */
+ EMSG2(_("E367: No such group: \"%s\""), name);
+ else
+ {
+ vim_free(MAPGROUP_NAME(i));
+ MAPGROUP_NAME(i) = NULL;
+ }
+}
+
+ void
+do_mapgroup(char_u *arg, int del_group)
+{
+ int i;
+
+ if (del_group)
+ {
+ if (arg == NULL)
+ EMSG(_(e_argreq));
+ else
+ map_del_group(arg);
+ }
+ else if (STRICMP(arg, "end") == 0) /* ":mapg end": back to group 0 */
+ current_mapgroup = MAPGROUP_DEFAULT;
+ else if (*arg) /* ":mapg xxx": switch to group xxx */
+ {
+ i = map_new_group(arg);
+ if (i != MAPGROUP_ERROR)
+ current_mapgroup = i;
+ }
+ else /* ":mapg": list the group names */
+ {
+ msg_start();
+ for (i = 0; i < mapgroups.ga_len; ++i)
+ {
+ if (MAPGROUP_NAME(i) != NULL)
+ {
+ msg_puts(MAPGROUP_NAME(i));
+ msg_puts((char_u *)" ");
+ }
+ }
+ msg_clr_eos();
+ msg_end();
+ }
+}
+
/*
* Clear all mappings in "mode".
*/
@@ -3913,7 +4017,9 @@ map_clear_int(
while (*mpp != NULL)
{
mp = *mpp;
- if (mp->m_mode & mode)
+ if ((current_mapgroup == MAPGROUP_DEFAULT ||
+ mp->m_group == current_mapgroup)
+ && mp->m_mode & mode)
{
mp->m_mode &= ~mode;
if (mp->m_mode == 0) /* entry can be deleted */
diff --git a/src/proto/getchar.pro b/src/proto/getchar.pro
index 97a2828..b217287 100644
--- a/src/proto/getchar.pro
+++ b/src/proto/getchar.pro
@@ -51,6 +51,7 @@ int inchar(char_u *buf, int maxlen, long wait_time, int tb_change_cnt);
int fix_input_buffer(char_u *buf, int len, int script);
int input_available(void);
int do_map(int maptype, char_u *arg, int mode, int abbrev);
+void do_mapgroup(char_u *arg, int del_group);
int get_map_mode(char_u **cmdp, int forceit);
void map_clear(char_u *cmdp, char_u *arg, int forceit, int abbr);
void map_clear_int(buf_T *buf, int mode, int local, int abbr);
diff --git a/src/structs.h b/src/structs.h
index 802180b..179ebaa 100644
--- a/src/structs.h
+++ b/src/structs.h
@@ -1046,6 +1046,7 @@ struct mapblock
char m_expr; /* <expr> used, m_str is an expression */
scid_T m_script_ID; /* ID of script where map was defined */
#endif
+ int m_group; /* mapgroup */
};
/*
nnoremap <leader>foo :<c-u>echo "foo"<cr>
function! s:StartMapGroup()
mapgroup SuperMomonga
mapclear
nnoremap <leader>bar :<c-u>echo "bar"<cr>
mapgroup END
endfunction
function! s:EndMapGroup()
mapgroup SuperMomonga
mapclear
mapgroup END
endfunction
command StartMapGroup :call <SID>StartMapGroup()
command EndMapGroup :call <SID>EndMapGroup()
@cvwillegen
Copy link

Not sure if I caught this correctly on the mailing list, but aren't 'old' C-style function definitions not used any more?

@cvwillegen
Copy link

Excellent idea, by the way 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment