mg is a fine little editor, but it just seems so emacs-centric. This little diff fixes that. Please test and get back to me.
Maybe *now* we'll get some users. -kj Index: Makefile =================================================================== RCS file: /cvs/src/usr.bin/mg/Makefile,v retrieving revision 1.19 diff -u -r1.19 Makefile --- Makefile 16 Dec 2006 17:00:03 -0000 1.19 +++ Makefile 1 Apr 2007 18:33:37 -0000 @@ -13,14 +13,15 @@ # XKEYS and bsmap mode do _not_ get along. # REGEX -- create regular expression functions # -CFLAGS+=-Wall -DXKEYS -DFKEYS -DREGEX +# VI -- the one true way +CFLAGS+=-Wall -DXKEYS -DFKEYS -DREGEX -DVI SRCS= cinfo.c fileio.c spawn.c ttyio.c tty.c ttykbd.c \ basic.c dir.c dired.c file.c line.c match.c paragraph.c \ random.c region.c search.c version.c window.c word.c \ buffer.c display.c echo.c extend.c help.c kbd.c keymap.c \ macro.c main.c modes.c re_search.c funmap.c undo.c autoexec.c \ - yank.c + yank.c vi.c # # More or less standalone extensions. Index: basic.c =================================================================== RCS file: /cvs/src/usr.bin/mg/basic.c,v retrieving revision 1.28 diff -u -r1.28 basic.c --- basic.c 20 Dec 2006 21:21:09 -0000 1.28 +++ basic.c 1 Apr 2007 18:33:37 -0000 @@ -64,6 +64,10 @@ int gotoeol(int f, int n) { + while (n > 1) { + forwline(FFRAND, 1); + n--; + } curwp->w_doto = llength(curwp->w_dotp); return (TRUE); } Index: def.h =================================================================== RCS file: /cvs/src/usr.bin/mg/def.h,v retrieving revision 1.99 diff -u -r1.99 def.h --- def.h 21 Feb 2007 23:33:12 -0000 1.99 +++ def.h 1 Apr 2007 18:33:37 -0000 @@ -109,6 +109,17 @@ #define KBACK 2 /* + * Search codes + */ +#define SRCH_BEGIN (0) +#define SRCH_FORW (-1) +#define SRCH_BACK (-2) +#define SRCH_NOPR (-3) +#define SRCH_ACCM (-4) +#define SRCH_MARK (-5) + + +/* * This structure holds the starting position * (as a line/offset pair) and the number of characters in a * region of a buffer. This makes passing the specification @@ -272,7 +283,10 @@ #endif #define BFOVERWRITE 0x08 /* overwrite mode */ #define BFREADONLY 0x10 /* read only mode */ - +#ifdef VI +#define BFVICMD 0x20 /* VI command mode */ +#define BFVIINS 0x40 /* VI insert mode */ +#endif /* * This structure holds information about recent actions for the Undo command. */ @@ -573,6 +587,7 @@ #endif /* !NO_MACRO */ /* modes.c X */ +int changemode(int, int, char *); int indentmode(int, int); int fillmode(int, int); int blinkparen(int, int); Index: extend.c =================================================================== RCS file: /cvs/src/usr.bin/mg/extend.c,v retrieving revision 1.50 diff -u -r1.50 extend.c --- extend.c 30 Dec 2006 14:11:06 -0000 1.50 +++ extend.c 1 Apr 2007 18:33:38 -0000 @@ -555,11 +555,16 @@ { PF funct; char xname[NXNAME], *bufp; + char *pref = "M-x "; +#ifdef VI + if (curbp->b_flag & BFVICMD) + pref = ":"; +#endif if (!(f & FFARG)) - bufp = eread("M-x ", xname, NXNAME, EFNEW | EFFUNC); + bufp = eread("%s", xname, NXNAME, EFNEW | EFFUNC, pref); else - bufp = eread("%d M-x ", xname, NXNAME, EFNEW | EFFUNC, n); + bufp = eread("%d %s", xname, NXNAME, EFNEW | EFFUNC, n, pref); if (bufp == NULL) return (ABORT); else if (bufp[0] == '\0') Index: main.c =================================================================== RCS file: /cvs/src/usr.bin/mg/main.c,v retrieving revision 1.56 diff -u -r1.56 main.c --- main.c 20 Feb 2007 04:39:45 -0000 1.56 +++ main.c 1 Apr 2007 18:33:38 -0000 @@ -76,7 +76,11 @@ extern void theo_init(void); extern void mail_init(void); extern void dired_init(void); +#ifdef VI + extern void vi_init(void); + vi_init(); +#endif dired_init(); grep_init(); theo_init(); Index: modes.c =================================================================== RCS file: /cvs/src/usr.bin/mg/modes.c,v retrieving revision 1.16 diff -u -r1.16 modes.c --- modes.c 13 Dec 2005 07:20:13 -0000 1.16 +++ modes.c 1 Apr 2007 18:33:38 -0000 @@ -11,13 +11,13 @@ #include "def.h" #include "kbd.h" -static int changemode(int, int, char *); +int changemode(int, int, char *); int defb_nmodes = 0; struct maps_s *defb_modes[PBMODES] = { &fundamental_mode }; int defb_flag = 0; -static int +int changemode(int f, int n, char *mode) { int i; Index: search.c =================================================================== RCS file: /cvs/src/usr.bin/mg/search.c,v retrieving revision 1.35 diff -u -r1.35 search.c --- search.c 13 Feb 2007 17:50:26 -0000 1.35 +++ search.c 1 Apr 2007 18:33:38 -0000 @@ -18,13 +18,6 @@ #include "macro.h" #endif /* !NO_MACRO */ -#define SRCH_BEGIN (0) /* Search sub-codes. */ -#define SRCH_FORW (-1) -#define SRCH_BACK (-2) -#define SRCH_NOPR (-3) -#define SRCH_ACCM (-4) -#define SRCH_MARK (-5) - struct srchcom { int s_code; struct line *s_dotp; Index: search.c =================================================================== --- /dev/null Thu Mar 15 02:19:17 2007 +++ vi.c Thu Mar 15 02:13:37 2007 @@ -0,0 +1,391 @@ +/* $OpenBSD$ */ + +/* This file is in the public domain. */ + +/* vi-mode for mg. By Kjell Wooding. + */ + +#ifdef VI +#include "def.h" +#include "funmap.h" +#include "kbd.h" + +/* last search direction */ +extern int srch_lastdir; + +void vi_init(void); +static int vi(int, int); +int vi_toggle(int, int); +int vi_append(int, int); +int vi_search(int, int); +int vi_rsearch(int, int); +int vi_open(int, int); +int vi_Open(int, int); +int vi_paste(int, int); + +extern struct keymap_s helpmap, cXmap, metamap; + +static PF vicmd_cc[] = { + rescan, /* ^@ */ + rescan, /* ^A */ + backpage, /* ^B */ + rescan, /* ^C */ + rescan, /* ^D */ + rescan, /* ^E */ + forwpage, /* ^F */ + rescan, /* ^G */ + backchar, /* ^H */ + rescan, /* ^I */ + forwline, /* ^J */ + rescan, /* ^K */ + reposition, /* ^L */ + rescan, /* ^M */ + forwline, /* ^N */ + rescan, /* ^O */ + backline, /* ^P */ + rescan, /* ^Q */ + reposition, /* ^R */ + rescan, /* ^S */ + rescan, /* ^T */ + rescan, /* ^U */ + rescan, /* ^V */ + nextwind, /* ^W */ + rescan, /* ^X */ + rescan, /* ^Y */ + rescan, /* ^Z */ +}; + +static PF vicmd_s0[] = { + rescan, /* ! */ + rescan, /* " */ + rescan, /* # */ + gotoeol, /* $ */ + rescan, /* % */ + rescan, /* & */ + rescan, /* ' */ + rescan, /* ( */ + rescan, /* ) */ + rescan, /* * */ + rescan, /* + */ + rescan, /* , */ + rescan, /* - */ + rescan, /* . */ + vi_search, /* / */ +}; + +static PF vicmd_n[] = { + gotobol, /* 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 */ +}; + +static PF vicmd_s1[] = { + extend, /* : */ + rescan, /* ; */ + rescan, /* < */ + rescan, /* = */ + rescan, /* > */ + vi_rsearch, /* ? */ + rescan, /* @ */ +}; + +static PF vicmd_uc[] = { + rescan, /* A */ + rescan, /* B */ + rescan, /* C */ + killline, /* D */ + rescan, /* E */ + rescan, /* F */ + rescan, /* G */ + backline, /* H */ + rescan, /* I */ + backchar, /* J */ + forwchar, /* K */ + forwline, /* L */ + rescan, /* M */ + rescan, /* N */ + vi_Open, /* O */ + rescan, /* P */ + rescan, /* Q */ + rescan, /* R */ + rescan, /* S */ + rescan, /* T */ + rescan, /* U */ + rescan, /* V */ + forwword, /* W */ + forwdel, /* X */ + rescan, /* Y */ + rescan, /* Z */ +}; + +static PF vicmd_lcs1[] = { + rescan, /* [ */ + rescan, /* \ */ + rescan, /* ] */ + gotobol, /* ^ */ + rescan, /* _ */ + rescan, /* ` */ +}; + +static PF vicmd_lc[] = { + vi_append, /* a */ + backword, /* b */ + rescan, /* c */ + rescan, /* d */ + forwword, /* e */ + rescan, /* f */ + rescan, /* g */ + backchar, /* h */ + vi_toggle, /* i */ + forwline, /* j */ + backline, /* k */ + forwchar, /* l */ + rescan, /* m */ + rescan, /* n */ + vi_open, /* o */ + vi_paste, /* p */ + rescan, /* q */ + rescan, /* r */ + rescan, /* s */ + rescan, /* t */ + undo, /* u */ + rescan, /* v */ + forwword, /* w */ + forwdel, /* x */ + rescan, /* y */ + rescan, /* z */ +}; + +static PF vicmd_lcs2[] = { + gotobop, /* { */ + rescan, /* | */ + gotoeop, /* } */ + rescan, /* ~ */ + rescan /* DEL */ +}; + +static struct KEYMAPE (8 + IMAPEXT) vicmdmap = { + 8, + 8 + IMAPEXT, + rescan, + { + { CCHR('@'), CCHR('Z'), vicmd_cc, NULL }, + { '!', '/', vicmd_s0, NULL }, + { '0', '9', vicmd_n, NULL }, + { ':', '@', vicmd_s1, NULL }, + { 'A', 'Z', vicmd_uc, NULL }, + { 'a', 'z', vicmd_lc, NULL }, + { '[', '`', vicmd_lcs1, NULL }, + { '{', CCHR('?'), vicmd_lcs2, NULL }, + } +}; + +/* + * VI Insertion mode. + */ +static PF vii_esc[] = { + vi_toggle /* ESC */ +}; + +static struct KEYMAPE (1 + IMAPEXT) viimap = { + 1, + 1 + IMAPEXT, + rescan, + { + { CCHR('['), CCHR('['), vii_esc, NULL } + } +}; + +void +vi_init(void) +{ + funmap_add(vi, "vi-mode"); + funmap_add(vi_toggle, "vi-mode-toggle"); + maps_add((KEYMAP *)&vicmdmap, "vi"); + maps_add((KEYMAP *)&viimap, "vi-ins"); +} + +/* + * Enable / dsable vi-mode + */ +/* ARGSUSED */ +int +vi(int f, int n) +{ + int ret1 = TRUE, ret2 = TRUE; + + if (curbp->b_flag & (BFVICMD | BFVIINS)) { + /* disable vi-mode */ + if (curbp->b_flag & BFVICMD) { + curbp->b_flag &= ~BFVICMD; + ret1 = changemode(f, n, "vi"); + } + if (curbp->b_flag & BFVIINS) { + curbp->b_flag &= ~BFVIINS; + ret2 =changemode(f, n, "vi-ins"); + } + return (ret1 == TRUE && ret2 == TRUE); + } + /* enable vi-mode */ + curbp->b_flag |= BFVICMD; + return (changemode(f, n, "vi")); +} + +/* + * If vi-mode is enabled, toggle between cmd and ins modes + */ +/* ARGSUSED */ +int +vi_toggle(int f, int n) +{ + int ret1, ret2; + + /* we must be enabled */ + if ((curbp->b_flag & (BFVICMD | BFVIINS)) == 0) + return (FALSE); + + if (curbp->b_flag & BFVICMD) { + curbp->b_flag &= ~BFVICMD; + curbp->b_flag |= BFVIINS; + } else { + curbp->b_flag &= ~BFVIINS; + curbp->b_flag |= BFVICMD; + } + + ret1 = changemode(f, n, "vi-ins"); + ret2 = changemode(f, n, "vi"); + + return (ret1 == TRUE && ret2 == TRUE); +} + +/* + * move forward (past cursor) and append text + */ +/* ARGSUSED */ +int +vi_append(int f, int n) +{ + forwchar(FFARG, 1); + return (vi_toggle(f, n)); +} + +/* + * read in a pattern and search for it + */ +/* ARGSUSED */ +int +vi_search(int f, int n) +{ + char tpat[NPAT], *rep; + int retval; + int again = FALSE; + + rep = eread("/", tpat, NPAT, EFNUL | EFNEW | EFCR); + + if (rep == NULL) + return(ABORT); + if (rep[0] != '\0') { + (void)strlcpy(pat, tpat, sizeof(pat)); + retval = TRUE; + } else { + again = forwchar(FFRAND, 1); + } + if (pat[0] == '\0') + return(FALSE); + + srch_lastdir = SRCH_FORW; + if (forwsrch() == FALSE) { + ewprintf("Pattern not found"); + if (again == TRUE) + backchar(FFRAND, 1); + return (FALSE); + } + backchar(FFRAND, strlen(pat)); + return (TRUE); +} + +/* + * read in a pattern and search (backwards) for it + */ +/* ARGSUSED */ +int +vi_rsearch(int f, int n) +{ + char tpat[NPAT], *rep; + int retval; + int again = FALSE; + + rep = eread("?", tpat, NPAT, EFNUL | EFNEW | EFCR); + + if (rep == NULL) + return(ABORT); + if (rep[0] != '\0') { + (void)strlcpy(pat, tpat, sizeof(pat)); + retval = TRUE; + } else { + again = backchar(FFRAND, 1); + } + if (pat[0] == '\0') + return(FALSE); + + srch_lastdir = SRCH_BACK; + if (backsrch() == FALSE) { + ewprintf("Pattern not found"); + if (again == TRUE) + forwchar(FFRAND, 1); + return (FALSE); + } + return (TRUE); +} + +/* + * open a new line below the current line and start adding text + */ +/* ARGSUSED */ +int +vi_open(int f, int n) +{ + gotoeol(FFRAND, 1); + newline(FFRAND, 1); + vi_toggle(f, n); + return (TRUE); +} +/* + * open a new line above the current line and start adding text + */ +/* ARGSUSED */ +int +vi_Open(int f, int n) +{ + gotobol(FFRAND, 1); + newline(FFRAND, 1); + backchar(FFRAND, 1); + vi_toggle(f, n); + return (TRUE); +} + +/* + * + */ +/* ARGSUSED */ +int +vi_paste(int f, int n) +{ + + gotoeol(FFRAND, 1); + while (n--) { + newline(FFRAND, 1); + yank(FFRAND, 1); + } + gotobol(FFRAND, 1); + return (TRUE); +} +#endif + -- Kjell Wooding <[EMAIL PROTECTED]>