File: [local] / src / usr.bin / mg / keymap.c (download)
Revision 1.61, Mon Apr 17 09:49:04 2023 UTC (13 months, 3 weeks ago) by op
Branch: MAIN
CVS Tags: OPENBSD_7_5_BASE, OPENBSD_7_5, OPENBSD_7_4_BASE, OPENBSD_7_4, HEAD Changes since 1.60: +1 -5 lines
resurrect mg' no-tab-mode
It's a mode that makes mg insert spaces up to the next tab stop upon
pressing TAB, along with the various tweaks needed in other places so
for e.g. auto-indent-mode also uses spaces.
This is not just an unifdef NOTAB: even under no-tab-mode mg should
consider literal TAB characters wide up to the next tab stop, while the
hidden code considered hard tabs to be just control character (i.e. ^I)
with width of two columns. I'm also introducing the helper function
doindent() in utils.c to de-obfuscate the insertion of tabs/spaces until
the given column.
ok tb@
|
/* $OpenBSD: keymap.c,v 1.61 2023/04/17 09:49:04 op Exp $ */
/* This file is in the public domain. */
/*
* Keyboard maps. This is character set dependent. The terminal specific
* parts of building the keymap has been moved to a better place.
*/
#include <sys/queue.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "def.h"
#include "kbd.h"
/*
* initial keymap declarations, deepest first
*/
static PF cHcG[] = {
ctrlg, /* ^G */
help_help /* ^H */
};
static PF cHa[] = {
apropos_command, /* a */
wallchart, /* b */
desckey /* c */
};
struct KEYMAPE (2) helpmap = {
2,
2,
rescan,
{
{
CCHR('G'), CCHR('H'), cHcG, NULL
},
{
'a', 'c', cHa, NULL
}
}
};
static PF cCsc[] = {
cscallerfuncs, /* c */
csdefinition, /* d */
csegrep, /* e */
csfindfile, /* f */
rescan, /* g */
rescan, /* h */
csfindinc, /* i */
rescan, /* j */
rescan, /* k */
rescan, /* l */
rescan, /* m */
csnextmatch, /* n */
rescan, /* o */
csprevmatch, /* p */
rescan, /* q */
rescan, /* r */
cssymbol, /* s */
csfindtext /* t */
};
static struct KEYMAPE (1) cCsmap = {
1,
1,
rescan,
{
{
'c', 't', cCsc, NULL
}
}
};
static PF cCs[] = {
NULL /* s */
};
struct KEYMAPE (2) ccmap = {
2,
2,
rescan,
{
{
CCHR('@'), CCHR('@'), (PF[]){ rescan }, NULL
},
{
's', 's', cCs, (KEYMAP *) & cCsmap
}
}
};
static PF cX4cF[] = {
poptofile, /* ^f */
ctrlg /* ^g */
};
static PF cX4b[] = {
poptobuffer, /* b */
rescan, /* c */
rescan, /* d */
rescan, /* e */
poptofile /* f */
};
static struct KEYMAPE (2) cX4map = {
2,
2,
rescan,
{
{
CCHR('F'), CCHR('G'), cX4cF, NULL
},
{
'b', 'f', cX4b, NULL
}
}
};
static PF cXcB[] = {
listbuffers, /* ^B */
quit, /* ^C */
rescan, /* ^D */
rescan, /* ^E */
filevisit, /* ^F */
ctrlg /* ^G */
};
static PF cXcJ[] = {
dired_jump, /* ^J */
rescan, /* ^K */
lowerregion, /* ^L */
rescan, /* ^M */
rescan, /* ^N */
deblank, /* ^O */
rescan, /* ^P */
togglereadonly, /* ^Q */
filevisitro, /* ^R */
filesave, /* ^S */
rescan, /* ^T */
upperregion, /* ^U */
filevisitalt, /* ^V */
filewrite, /* ^W */
swapmark /* ^X */
};
static PF cXlp[] = {
definemacro, /* ( */
finishmacro /* ) */
};
static PF cX0[] = {
delwind, /* 0 */
onlywind, /* 1 */
splitwind, /* 2 */
rescan, /* 3 */
NULL /* 4 */
};
static PF cXeq[] = {
showcpos /* = */
};
static PF cXcar[] = {
enlargewind, /* ^ */
rescan, /* _ */
next_error, /* ` */
rescan, /* a */
usebuffer, /* b */
rescan, /* c */
rescan, /* d */
executemacro, /* e */
setfillcol, /* f */
gotoline, /* g */
markbuffer, /* h */
fileinsert, /* i */
rescan, /* j */
killbuffer_cmd, /* k */
rescan, /* l */
rescan, /* m */
nextwind, /* n */
nextwind, /* o */
prevwind, /* p */
rescan, /* q */
rescan, /* r */
savebuffers, /* s */
rescan, /* t */
undo /* u */
};
struct KEYMAPE (6) cXmap = {
6,
6,
rescan,
{
{
CCHR('B'), CCHR('G'), cXcB, NULL
},
{
CCHR('J'), CCHR('X'), cXcJ, NULL
},
{
'(', ')', cXlp, NULL
},
{
'0', '4', cX0, (KEYMAP *) & cX4map
},
{
'=', '=', cXeq, NULL
},
{
'^', 'u', cXcar, NULL
}
}
};
static PF metacG[] = {
ctrlg /* ^G */
};
static PF metacV[] = {
pagenext /* ^V */
};
static PF metaspex[] = {
justone, /* space */
shellcommand /* ! */
};
static PF metapct[] = {
queryrepl /* % */
};
static PF metami[] = {
poptag, /* * */
rescan, /* + */
rescan, /* , */
negative_argument, /* - */
findtag, /* . */
rescan, /* / */
digit_argument, /* 0 */
digit_argument, /* 1 */
digit_argument, /* 2 */
digit_argument, /* 3 */
digit_argument, /* 4 */
digit_argument, /* 5 */
digit_argument, /* 6 */
digit_argument, /* 7 */
digit_argument, /* 8 */
digit_argument, /* 9 */
rescan, /* : */
rescan, /* ; */
gotobob, /* < */
rescan, /* = */
gotoeob /* > */
};
static PF metasqf[] = {
NULL, /* [ */
delwhite, /* \ */
rescan, /* ] */
joinline, /* ^ */
rescan, /* _ */
rescan, /* ` */
rescan, /* a */
backword, /* b */
capword, /* c */
delfword, /* d */
rescan, /* e */
forwword, /* f */
rescan, /* g */
markpara /* h */
};
static PF metal[] = {
lowerword, /* l */
backtoindent, /* m */
rescan, /* n */
rescan, /* o */
rescan, /* p */
fillpara, /* q */
backsearch, /* r */
forwsearch, /* s */
transposeword, /* t */
upperword, /* u */
backpage, /* v */
copyregion, /* w */
extend, /* x */
rescan, /* y */
zaptochar, /* z */
gotobop, /* { */
piperegion, /* | */
gotoeop /* } */
};
static PF metasqlZ[] = {
rescan /* Z */
};
static PF metatilde[] = {
notmodified, /* ~ */
delbword /* DEL */
};
struct KEYMAPE (1) metasqlmap = {
1,
1,
rescan,
{
{
'Z', 'Z', metasqlZ, NULL
}
}
};
struct KEYMAPE (8) metamap = {
8,
8,
rescan,
{
{
CCHR('G'), CCHR('G'), metacG, NULL
},
{
CCHR('V'), CCHR('V'), metacV, NULL
},
{
' ', '!', metaspex, NULL
},
{
'%', '%', metapct, NULL
},
{
'*', '>', metami, NULL
},
{
'[', 'h', metasqf, (KEYMAP *) &metasqlmap
},
{
'l', '}', metal, NULL
},
{
'~', CCHR('?'), metatilde, NULL
}
}
};
static PF fund_at[] = {
setmark, /* ^@ */
gotobol, /* ^A */
backchar, /* ^B */
NULL, /* ^C */
forwdel, /* ^D */
gotoeol, /* ^E */
forwchar, /* ^F */
ctrlg, /* ^G */
};
static PF fund_h[] = {
NULL, /* ^H */
};
/* ^I is selfinsert */
static PF fund_CJ[] = {
lfindent, /* ^J */
killline, /* ^K */
reposition, /* ^L */
enewline, /* ^M */
forwline, /* ^N */
openline, /* ^O */
backline, /* ^P */
quote, /* ^Q */
backisearch, /* ^R */
forwisearch, /* ^S */
twiddle, /* ^T */
universal_argument, /* ^U */
forwpage, /* ^V */
killregion, /* ^W */
NULL, /* ^X */
yank, /* ^Y */
spawncli /* ^Z */
};
static PF fund_esc[] = {
NULL, /* esc */
rescan, /* ^\ selfinsert is default on fundamental */
rescan, /* ^] */
rescan, /* ^^ */
undo /* ^_ */
};
static PF fund_del[] = {
backdel /* DEL */
};
static PF fund_cb[] = {
showmatch /* ) ] } */
};
static struct KEYMAPE (8) fundmap = {
8,
8,
selfinsert,
{
{
CCHR('@'), CCHR('G'), fund_at, (KEYMAP *) & ccmap
},
{
CCHR('H'), CCHR('H'), fund_h, (KEYMAP *) & helpmap
},
{
CCHR('J'), CCHR('Z'), fund_CJ, (KEYMAP *) & cXmap
},
{
CCHR('['), CCHR('_'), fund_esc, (KEYMAP *) & metamap
},
{
')', ')', fund_cb, NULL
},
{
']', ']', fund_cb, NULL
},
{
'}', '}', fund_cb, NULL
},
{
CCHR('?'), CCHR('?'), fund_del, NULL
},
}
};
static PF fill_sp[] = {
fillword /* ' ' */
};
static struct KEYMAPE (1) fillmap = {
1,
1,
rescan,
{
{ ' ', ' ', fill_sp, NULL }
}
};
static PF indent_lf[] = {
enewline, /* ^J */
rescan, /* ^K */
rescan, /* ^L */
lfindent /* ^M */
};
static struct KEYMAPE (1) indntmap = {
1,
1,
rescan,
{
{
CCHR('J'), CCHR('M'), indent_lf, NULL
}
}
};
static PF notab_tab[] = {
space_to_tabstop /* ^I */
};
static struct KEYMAPE (1) notabmap = {
1,
1,
rescan,
{
{
CCHR('I'), CCHR('I'), notab_tab, NULL
}
}
};
static struct KEYMAPE (1) overwmap = {
0,
1, /* 1 to avoid 0 sized array */
rescan,
{
/* unused dummy entry for VMS C */
{
(KCHAR)0, (KCHAR)0, NULL, NULL
}
}
};
/*
* The basic (root) keyboard map
*/
struct maps_s fundamental_mode = { (KEYMAP *)&fundmap, "fundamental" };
/*
* give names to the maps, for use by help etc. If the map is to be bindable,
* it must also be listed in the function name table below with the same
* name. Maps created dynamically currently don't get added here, thus are
* unnamed. Modes are just named keymaps with functions to add/subtract them
* from a buffer's list of modes. If you change a mode name, change it in
* modes.c also.
*/
static struct maps_s map_table[] = {
{(KEYMAP *) &fillmap, "fill",},
{(KEYMAP *) &indntmap, "indent",},
{(KEYMAP *) ¬abmap, "notab",},
{(KEYMAP *) &overwmap, "overwrite",},
{(KEYMAP *) &metamap, "esc prefix",},
{(KEYMAP *) &cXmap, "c-x prefix",},
{(KEYMAP *) &cX4map, "c-x 4 prefix",},
{(KEYMAP *) &helpmap, "help",},
{NULL, NULL}
};
struct maps_s *maps;
void
maps_init(void)
{
int i;
struct maps_s *mp;
maps = &fundamental_mode;
for (i = 0; map_table[i].p_name != NULL; i++) {
mp = &map_table[i];
mp->p_next = maps;
maps = mp;
}
}
/*
* Insert a new (named) keymap at the head of the keymap list.
*/
int
maps_add(KEYMAP *map, const char *name)
{
struct maps_s *mp;
if ((mp = malloc(sizeof(*mp))) == NULL)
return (FALSE);
mp->p_name = name;
mp->p_map = map;
mp->p_next = maps;
maps = mp;
return (TRUE);
}
struct maps_s *
name_mode(const char *name)
{
struct maps_s *mp;
for (mp = maps; mp != NULL; mp = mp->p_next)
if (strcmp(mp->p_name, name) == 0)
return (mp);
return (NULL);
}
KEYMAP *
name_map(const char *name)
{
struct maps_s *mp;
return ((mp = name_mode(name)) == NULL ? NULL : mp->p_map);
}