mg: replace-regexp

2021-04-20 Thread Mark Lumsden
This diff adds a non-interactive version of mg's query-replace-regexp 
function called replace-regexp. Unfortunately query-replace-regexp can't 
be used in a startup file.


Ok?

Index: def.h
===
RCS file: /cvs/src/usr.bin/mg/def.h,v
retrieving revision 1.172
diff -u -p -u -p -r1.172 def.h
--- def.h   20 Apr 2021 10:02:50 -  1.172
+++ def.h   20 Apr 2021 16:12:50 -
@@ -673,6 +673,7 @@ int  re_forwsearch(int, int);
 int re_backsearch(int, int);
 int re_searchagain(int, int);
 int re_queryrepl(int, int);
+int re_repl(int, int);
 int replstr(int, int);
 int setcasefold(int, int);
 int delmatchlines(int, int);
Index: funmap.c
===
RCS file: /cvs/src/usr.bin/mg/funmap.c,v
retrieving revision 1.61
diff -u -p -u -p -r1.61 funmap.c
--- funmap.c20 Apr 2021 10:02:50 -  1.61
+++ funmap.c20 Apr 2021 16:12:50 -
@@ -181,6 +181,7 @@ static struct funmap functnames[] = {
{reposition, "recenter", 0},
{redraw, "redraw-display", 0},
 #ifdef REGEX
+   {re_repl, "replace-regexp", 2},
{replstr, "replace-string", 2},
 #endif /* REGEX */
{revertbuffer, "revert-buffer", 0},
Index: mg.1
===
RCS file: /cvs/src/usr.bin/mg/mg.1,v
retrieving revision 1.123
diff -u -p -u -p -r1.123 mg.1
--- mg.120 Apr 2021 10:02:50 -  1.123
+++ mg.120 Apr 2021 16:12:50 -
@@ -778,6 +778,8 @@ Display current (global) working directo
 .It query-replace
 Query Replace.
 Search and replace strings selectively, prompting after each match.
+.It replace-regexp
+Replace regular expression globally without individual prompting.
 .It replace-string
 Replace string globally without individual prompting.
 .It query-replace-regexp
Index: re_search.c
===
RCS file: /cvs/src/usr.bin/mg/re_search.c,v
retrieving revision 1.35
diff -u -p -u -p -r1.35 re_search.c
--- re_search.c 22 Jul 2020 13:29:05 -  1.35
+++ re_search.c 20 Apr 2021 16:12:50 -
@@ -211,6 +211,34 @@ stopsearch:
return (TRUE);
 }

+int
+re_repl(int f, int n)
+{
+int rcnt = 0;   /* replacements made so far */
+int plen, s;/* length of found string   */
+charnews[NPAT]; /* replacement string   */
+
+if ((s = re_readpattern("RE Replace")) != TRUE)
+return (s);
+if (eread("Replace %s with: ", news, NPAT,
+EFNUL | EFNEW | EFCR, re_pat) == NULL)
+return (ABORT);
+
+   while (re_forwsrch() == TRUE) {
+   plen = regex_match[0].rm_eo - regex_match[0].rm_so;
+   if (re_doreplace((RSIZE)plen, news) == FALSE)
+   return (FALSE);
+   rcnt++;
+   }
+ 
+	curwp->w_rflag |= WFFULL;

+   update(CMODE);
+   if (!inmacro)
+   ewprintf("(%d replacement(s) done)", rcnt);
+ 
+	return(TRUE);

+}
+
 /*
  * Routine re_doreplace calls lreplace to make replacements needed by
  * re_query replace.  Its reason for existence is to deal with \1, \2. etc.



mg list-buffers

2021-03-25 Thread Mark Lumsden

This is the current format of the output of the mg 'list-buffer'
command:

 MR Buffer  Size   File
 -- --     
*Buffer List*   0
.** file1.c 6810   /tmp/file1.c
file2.c 7105   /tmp/file2.c
  * *scratch*   0

The 'M' column indicates if the buffer is modified by having an
asterisk next to the buffer name. The 'R' column indicates if a buffer
is read-only by not having an asterisk in the 'R' column.  Therefor
the files above with an asterisk in the column next to them are
writable.  Isn't that unintuitive?

Also, perhaps less confusing than the 'R' column, is the first column
(note it doesn't have a header character), it has a '.' next to
'file1.c'. The '.' indicates that this is the active buffer in mg.
Could a different character indicate the active buffer? The diff below
makes the state of buffers above look like this:

 MR Buffer  Size   File
 -- --     
  * *Buffer List*   0

*  file1.c 6810   /tmp/file1.c

  * file2.c 7105   /tmp/file2.c
*scratch*   0

Read-only buffers have an asterisk in the 'R' column and I'm using a
'>' character to indicate the active buffer. Is that better?

Also, since I had to check the code to see what 'R' meant (I guessed
'M'), and I didn't even notice the '.' character (I thought it was a dodgy
pixel), I have added a short explaination to the man page about the 3
columns.

Objectsions, oks?

Index: buffer.c
===
RCS file: /cvs/src/usr.bin/mg/buffer.c,v
retrieving revision 1.111
diff -u -p -r1.111 buffer.c
--- buffer.c23 Mar 2021 18:40:29 -  1.111
+++ buffer.c25 Mar 2021 15:08:36 -
@@ -368,9 +368,9 @@ makelist(void)
}

if (addlinef(blp, "%c%c%c %-*.*s%c%-6d %-*s",
-   (bp == curbp) ? '.' : ' ',  /* current buffer ? */
+   (bp == curbp) ? '>' : ' ',   /* current buffer ? */
((bp->b_flag & BFCHG) != 0) ? '*' : ' ', /* changed ? */
-   ((bp->b_flag & BFREADONLY) != 0) ? ' ' : '*',
+   ((bp->b_flag & BFREADONLY) != 0) ? '*' : ' ',
w - 5,  /* four chars already written */
w - 5,  /* four chars already written */
bp->b_bname, /* buffer name */
Index: mg.1
===
RCS file: /cvs/src/usr.bin/mg/mg.1,v
retrieving revision 1.121
diff -u -p -r1.121 mg.1
--- mg.120 Mar 2021 09:00:49 -  1.121
+++ mg.125 Mar 2021 15:08:36 -
@@ -692,6 +692,11 @@ directory.
 Toggle whether the line number is displayed in the modeline.
 .It list-buffers
 Display the list of available buffers.
+The first column in the output indicates which buffer is active with a '>'
+character.
+The second column indicates which buffers are modified.
+The third column indicates which buffers are read-only.
+The remaining columns are self-explanatory.
 .It load
 Prompt the user for a filename, and then execute commands
 from that file.



mg: interactive evaluation

2021-03-23 Thread Mark Lumsden

This diff gives mg the ability to have an interactive session with
interpreter.c via the 'eval-current-buffer' command. With this diff
the interactive mode is switched off by default of course. So if you
are in the habit of evaluting startup files you won't see any
difference. With this diff applied, you would need to give the 'M-x
eval-interactive' command to toggle this functionality on. Even then
you will only see a difference with 'eval-current-buffer' if there are
commands with parenthesis* at the start of a line in the startup
buffer you are evaluating. For example, having the following line in a
buffer and executing 'eval-current-buffer' the behaviour is the same
as previously:

column-number-mode

The command will toggle whether the column number shows in the
modeline. If you instead have the following in the buffer:

(column-number-mode)

And issue the 'eval-current-buffer' command, with this diff applied
(and whilst previously having toggled 'M-x eval-interactive' to on).
You will achieve the same effect as the 1st command of toggling the
column number in the modeline to on, but a buffer called
*display-output* will have opened since you have entered the
interpreter.c code by having '(' as the first none white character of
the line. The contents of the *display-output* buffer will be empty
because 'column-number-mode' creates no output. However with commands
like:

(insert "abc")

The text "abc" will show in the *display-output* buffer.

My initial goal is to have an interpreter that allows mg to combine
different mg commands together and have some form of user defined
functions, but I am a long way from that. The interpreter
functionaility is still in the PoC stage and I wouldn't use it without
expecting to see bugs (lots of them), and I expect it will go through
more rewrites as I learn and understand more things about what is
required. The functionality in the diff bellow allows me to test
quicker though.

As an outline, currently the interpreter can do things like:

(define avar(list "a" "b" "c"))
(insert avar)
(newline 4)
(insert avar)

The string "abc" will appear twice in *display-output*, with 4 newline
characters between them. Its pretty basic at the moment, I must
admit

I'm not intending this to be a scheme interpreter, but am using scheme
syntax and a similar behaviour to be the glue of different mg commands
which hopefully together can create mg user defined functions.

This interpreter kind of functionality will also help me with
intergrating mg's regress tests with OpenBSD's regress framework. For
example, I am hoping to have something like:

(define curdir(shell-command "echo $CURDIR"))

To be able to import an environment variable, then use 'curdir' where
required in mg's regress tests.

If you would like to test, that would be much appreciated, there are
also notes at the top of interpreter.c.

I have not included anything in the mg man page about the interactive
mode since I don't think the code is ready for that.

Comments/oks/criticisms?

Mark

*parenthesis have been ignored in mg evaluation routines since mg being
imported into the OpenBSD tree 21 years ago - and probably way before
that, so I reckoned that no-one would have parenthesis in their
startup files, or if they did, my interpreter code wouldn't change the
behaviour of those lines anyway.

Index: buffer.c
===
RCS file: /cvs/src/usr.bin/mg/buffer.c,v
retrieving revision 1.111
diff -u -p -r1.111 buffer.c
--- buffer.c23 Mar 2021 18:40:29 -  1.111
+++ buffer.c23 Mar 2021 22:58:45 -
@@ -128,8 +128,6 @@ usebuffer(int f, int n)
 int
 poptobuffer(int f, int n)
 {
-   struct buffer *bp;
-   struct mgwin  *wp;
charbufn[NBUFN], *bufp;

/* Get buffer to use from user */
@@ -142,6 +140,16 @@ poptobuffer(int f, int n)
bufn, NBUFN, EFNUL | EFNEW | EFBUF, curbp->b_altb->b_bname);
if (bufp == NULL)
return (ABORT);
+
+   return (do_poptobuffer(f, n, bufp));
+}
+
+int
+do_poptobuffer(int f, int n, char *bufp)
+{
+   struct buffer *bp;
+   struct mgwin  *wp;
+
if (bufp[0] == '\0' && curbp->b_altb != NULL)
bp = curbp->b_altb;
else if ((bp = bfind(bufp, TRUE)) == NULL)
Index: def.h
===
RCS file: /cvs/src/usr.bin/mg/def.h,v
retrieving revision 1.170
diff -u -p -r1.170 def.h
--- def.h   21 Mar 2021 12:56:16 -  1.170
+++ def.h   23 Mar 2021 22:58:45 -
@@ -381,6 +381,7 @@ int  writeout(FILE **, struct buffer *,
 voidupmodes(struct buffer *);
 size_t  xbasename(char *, const char *, size_t);
 int do_filevisitalt(char *);
+int do_poptofile(int, int, char *);

 /* line.c X */
 struct line*lalloc(int);
@@ -444,6 +445,7 @@ int  revertbuffer(int, int);
 int dorevert(void);
 int

mg: buffer pointer change after eread()

2021-03-23 Thread Mark Lumsden

When reading in from the modeline in buffer.c, mg uses a pointer
called bufp pointing to a buffer called bufn. It would seem to make
sense to use bufp in any further processing. These functions don't:

switch-to-buffer-other-window   (poptobuffer())
kill-buffer (killbuffer_cmd())
insert-buffer   (bufferinsert())

This diff changes the above three instances to use bufp instead of
bufn once eread() has been used.  No functional change intended.

ok?

Index: buffer.c
===
RCS file: /cvs/src/usr.bin/mg/buffer.c,v
retrieving revision 1.110
diff -u -p -r1.110 buffer.c
--- buffer.c18 Mar 2021 18:09:21 -  1.110
+++ buffer.c23 Mar 2021 10:00:31 -
@@ -144,7 +144,7 @@ poptobuffer(int f, int n)
return (ABORT);
if (bufp[0] == '\0' && curbp->b_altb != NULL)
bp = curbp->b_altb;
-   else if ((bp = bfind(bufn, TRUE)) == NULL)
+   else if ((bp = bfind(bufp, TRUE)) == NULL)
return (FALSE);
if (bp == curbp)
return (splitwind(f, n));
@@ -178,7 +178,7 @@ killbuffer_cmd(int f, int n)
return (ABORT);
else if (bufp[0] == '\0')
bp = curbp;
-   else if ((bp = bfind(bufn, FALSE)) == NULL)
+   else if ((bp = bfind(bufp, FALSE)) == NULL)
return (FALSE);
ret = killbuffer(bp);
eerase();
@@ -782,7 +782,7 @@ bufferinsert(int f, int n)
return (ABORT);
if (bufp[0] == '\0' && curbp->b_altb != NULL)
bp = curbp->b_altb;
-   else if ((bp = bfind(bufn, FALSE)) == NULL)
+   else if ((bp = bfind(bufp, FALSE)) == NULL)
return (FALSE);

if (bp == curbp)



Re: mg(1): dired-jump

2021-03-19 Thread Mark Lumsden

Should this be "if (fname != NULL)"?  Some other callers of
adjustname() check for a NULL pointer.  strlen(NULL) would crash by
SIGSEGV; strlen("") would return 0, because "" is a non-NULL pointer
to an ASCII NUL '\0'.


I agree. Amended diff below.

Index: def.h
===
RCS file: /cvs/src/usr.bin/mg/def.h,v
retrieving revision 1.168
diff -u -p -r1.168 def.h
--- def.h   1 Mar 2021 10:51:14 -   1.168
+++ def.h   19 Mar 2021 06:02:05 -
@@ -363,6 +363,7 @@ int  ask_makedir(void);

 /* dired.c */
 struct buffer  *dired_(char *);
+int dired_jump(int, int);
 int do_dired(char *);

 /* file.c X */
Index: dired.c
===
RCS file: /cvs/src/usr.bin/mg/dired.c,v
retrieving revision 1.98
diff -u -p -r1.98 dired.c
--- dired.c 5 Mar 2021 16:16:53 -   1.98
+++ dired.c 19 Mar 2021 06:02:05 -
@@ -53,6 +53,7 @@ static int d_refreshbuffer(int, int);
 static int  d_filevisitalt(int, int);
 static int  d_gotofile(int, int);
 static void reaper(int);
+static int  gotofile(char*);
 static struct buffer   *refreshbuffer(struct buffer *);
 static int  createlist(struct buffer *);
 static void redelete(struct buffer *);
@@ -1091,13 +1092,38 @@ createlist(struct buffer *bp)
 }

 int
+dired_jump(int f, int n)
+{
+   char dname[NFILEN], *fname;
+   struct buffer   *bp;
+   int  ret;
+
+   if (getbufcwd(dname, sizeof(dname)) != TRUE)
+   return (FALSE);
+
+   fname = curbp->b_fname;
+
+   if ((bp = dired_(dname)) == NULL)
+   return (FALSE);
+   curbp = bp;
+
+   ret = showbuffer(bp, curwp, WFFULL | WFMODE);
+   if (ret != TRUE)
+   return ret;
+
+   fname = adjustname(fname, TRUE);
+   if (fname != NULL)
+   gotofile(fname);
+
+   return (TRUE);
+}
+
+int
 d_gotofile(int f, int n)
 {
-   struct line *lp, *nlp;
size_t   lenfpath;
-   char fpath[NFILEN], fname[NFILEN];
-   char*p, *fpth, *fnp = NULL;
-   int  tmp;
+   char fpath[NFILEN];
+   char*fpth, *fnp = NULL;

if (getbufcwd(fpath, sizeof(fpath)) != TRUE)
fpath[0] = '\0';
@@ -1114,8 +1140,18 @@ d_gotofile(int f, int n)
ewprintf("No file to find");  /* Current directory given so  */
return (TRUE);  /* return at present location. 
*/
}
+   return gotofile(fpth);
+}
+
+int
+gotofile(char *fpth)
+{
+   struct line *lp, *nlp;
+   char fname[NFILEN];
+   char*p;
+   int  tmp;
+
(void)xbasename(fname, fpth, NFILEN);
-   curbp = curwp->w_bufp;
tmp = 0;
for (lp = bfirstlp(curbp); lp != curbp->b_headp; lp = nlp) {
tmp++;
Index: funmap.c
===
RCS file: /cvs/src/usr.bin/mg/funmap.c,v
retrieving revision 1.59
diff -u -p -r1.59 funmap.c
--- funmap.c11 Jul 2019 18:20:18 -  1.59
+++ funmap.c19 Mar 2021 06:02:05 -
@@ -98,6 +98,7 @@ static struct funmap functnames[] = {
{desckey, "describe-key-briefly", 1},
{diffbuffer, "diff-buffer-with-file", 0},
{digit_argument, "digit-argument", 1},
+   {dired_jump, "dired-jump", 1},
{lowerregion, "downcase-region", 0},
{lowerword, "downcase-word", 0},
{showversion, "emacs-version", 0},
Index: keymap.c
===
RCS file: /cvs/src/usr.bin/mg/keymap.c,v
retrieving revision 1.58
diff -u -p -r1.58 keymap.c
--- keymap.c29 Dec 2015 19:44:32 -  1.58
+++ keymap.c19 Mar 2021 06:02:05 -
@@ -129,7 +129,8 @@ static PF cXcB[] = {
ctrlg   /* ^G */
 };

-static PF cXcL[] = {
+static PF cXcJ[] = {
+   dired_jump, /* ^J */
lowerregion,/* ^L */
rescan, /* ^M */
rescan, /* ^N */
@@ -198,7 +199,7 @@ struct KEYMAPE (6) cXmap = {
CCHR('B'), CCHR('G'), cXcB, NULL
},
{
-   CCHR('L'), CCHR('X'), cXcL, NULL
+   CCHR('J'), CCHR('X'), cXcJ, NULL
},
{
'(', ')', cXlp, NULL
Index: mg.1
===
RCS file: /cvs/src/usr.bin/mg/mg.1,v
retrieving revision 1.120
diff -u -p -r1.120 mg.1
--- mg.123 Feb 2021 18:45:33 -  1.120
+++ mg.119 Mar 2021 06:02:05 -
@@ -198,6 +198,8 @@ list-buffers
 save-buffers-kill-emacs
 .It C-x C-f
 find-file
+.It C-x C-j
+dired-jump
 .It C-x C-g
 keyboard-quit
 .It C-x C-l
@@ -523,6 +525,8 @@ Display the 

mg(1): dired-jump

2021-03-18 Thread Mark Lumsden
This diff was first seen on the tech list just under a year ago. It is 
from Philip K. and was tested by George Koehler. I have modified it 
slightly. From Philips original post:


this patch implements "dired-jump" for mg. For those not familiar with
what dired-jump does in GNU Emacs, here's it's docstring:

Jump to Dired buffer corresponding to current buffer.
If in a file, Dired the current directory and move to files line.


I find this useful. ok?

Index: def.h
===
RCS file: /cvs/src/usr.bin/mg/def.h,v
retrieving revision 1.168
diff -u -p -r1.168 def.h
--- def.h   1 Mar 2021 10:51:14 -   1.168
+++ def.h   18 Mar 2021 20:15:34 -
@@ -363,6 +363,7 @@ int  ask_makedir(void);

 /* dired.c */
 struct buffer  *dired_(char *);
+int dired_jump(int, int);
 int do_dired(char *);

 /* file.c X */
Index: dired.c
===
RCS file: /cvs/src/usr.bin/mg/dired.c,v
retrieving revision 1.98
diff -u -p -r1.98 dired.c
--- dired.c 5 Mar 2021 16:16:53 -   1.98
+++ dired.c 18 Mar 2021 20:15:34 -
@@ -53,6 +53,7 @@ static int d_refreshbuffer(int, int);
 static int  d_filevisitalt(int, int);
 static int  d_gotofile(int, int);
 static void reaper(int);
+static int  gotofile(char*);
 static struct buffer   *refreshbuffer(struct buffer *);
 static int  createlist(struct buffer *);
 static void redelete(struct buffer *);
@@ -1091,13 +1092,38 @@ createlist(struct buffer *bp)
 }

 int
+dired_jump(int f, int n)
+{
+   char dname[NFILEN], *fname;
+   struct buffer   *bp;
+   int  ret;
+
+   if (getbufcwd(dname, sizeof(dname)) != TRUE)
+   return (FALSE);
+
+   fname = curbp->b_fname;
+
+   if ((bp = dired_(dname)) == NULL)
+   return (FALSE);
+   curbp = bp;
+
+   ret = showbuffer(bp, curwp, WFFULL | WFMODE);
+   if (ret != TRUE)
+   return ret;
+
+   fname = adjustname(fname, TRUE);
+   if (strlen(fname))
+   gotofile(fname);
+
+   return (TRUE);
+}
+
+int
 d_gotofile(int f, int n)
 {
-   struct line *lp, *nlp;
size_t   lenfpath;
-   char fpath[NFILEN], fname[NFILEN];
-   char*p, *fpth, *fnp = NULL;
-   int  tmp;
+   char fpath[NFILEN];
+   char*fpth, *fnp = NULL;

if (getbufcwd(fpath, sizeof(fpath)) != TRUE)
fpath[0] = '\0';
@@ -1114,8 +1140,18 @@ d_gotofile(int f, int n)
ewprintf("No file to find");  /* Current directory given so  */
return (TRUE);  /* return at present location. 
*/
}
+   return gotofile(fpth);
+}
+
+int
+gotofile(char *fpth)
+{
+   struct line *lp, *nlp;
+   char fname[NFILEN];
+   char*p;
+   int  tmp;
+
(void)xbasename(fname, fpth, NFILEN);
-   curbp = curwp->w_bufp;
tmp = 0;
for (lp = bfirstlp(curbp); lp != curbp->b_headp; lp = nlp) {
tmp++;
Index: funmap.c
===
RCS file: /cvs/src/usr.bin/mg/funmap.c,v
retrieving revision 1.59
diff -u -p -r1.59 funmap.c
--- funmap.c11 Jul 2019 18:20:18 -  1.59
+++ funmap.c18 Mar 2021 20:15:34 -
@@ -98,6 +98,7 @@ static struct funmap functnames[] = {
{desckey, "describe-key-briefly", 1},
{diffbuffer, "diff-buffer-with-file", 0},
{digit_argument, "digit-argument", 1},
+   {dired_jump, "dired-jump", 1},
{lowerregion, "downcase-region", 0},
{lowerword, "downcase-word", 0},
{showversion, "emacs-version", 0},
Index: keymap.c
===
RCS file: /cvs/src/usr.bin/mg/keymap.c,v
retrieving revision 1.58
diff -u -p -r1.58 keymap.c
--- keymap.c29 Dec 2015 19:44:32 -  1.58
+++ keymap.c18 Mar 2021 20:15:34 -
@@ -129,7 +129,8 @@ static PF cXcB[] = {
ctrlg   /* ^G */
 };

-static PF cXcL[] = {
+static PF cXcJ[] = {
+   dired_jump, /* ^J */
lowerregion,/* ^L */
rescan, /* ^M */
rescan, /* ^N */
@@ -198,7 +199,7 @@ struct KEYMAPE (6) cXmap = {
CCHR('B'), CCHR('G'), cXcB, NULL
},
{
-   CCHR('L'), CCHR('X'), cXcL, NULL
+   CCHR('J'), CCHR('X'), cXcJ, NULL
},
{
'(', ')', cXlp, NULL
Index: mg.1
===
RCS file: /cvs/src/usr.bin/mg/mg.1,v
retrieving revision 1.120
diff -u -p -r1.120 mg.1
--- mg.123 Feb 2021 18:45:33 -  1.120
+++ mg.1 

mg(1): regress tests and pty

2021-03-18 Thread Mark Lumsden
I am currently writing regress tests for mg which use an mg startup file's 
capabilities to process mg commands to test mg's internal functions. In 
order to facilitate mg fitting into the OpenBSD regress test framework and
be able to run via a cron job I have amended mg to be able to run with a 
pty. The diff below adds a 'batch' mode to mg via the '-b' command line 
option which will initialise a pty, run the specified file of mg commands 
and then exit.


There are other things to do to get mg fully integrated into the regress 
framework, but this diff is independant of them and offers a solution to 
no tty being available when being executed vi cron.


Comments/oks/criticisms?

Mark

Index: def.h
===
RCS file: /cvs/src/usr.bin/mg/def.h,v
retrieving revision 1.168
diff -u -p -r1.168 def.h
--- def.h   1 Mar 2021 10:51:14 -   1.168
+++ def.h   18 Mar 2021 15:58:39 -
@@ -750,6 +750,7 @@ extern int   doaudiblebell;
 extern int  dovisiblebell;
 extern int  dblspace;
 extern int  allbro;
+extern int  batch;
 extern char cinfo[];
 extern char*keystrings[];
 extern char pat[NPAT];
Index: main.c
===
RCS file: /cvs/src/usr.bin/mg/main.c,v
retrieving revision 1.88
diff -u -p -r1.88 main.c
--- main.c  23 Feb 2021 08:10:51 -  1.88
+++ main.c  18 Mar 2021 15:58:40 -
@@ -14,7 +14,9 @@
 #include 
 #include 
 #include 
+#include 
 #include 
+#include 

 #include "def.h"
 #include "kbd.h"
@@ -33,6 +35,7 @@ intdoaudiblebell; /* audible bell 
t
 int dovisiblebell; /* visible bell toggle  */
 int dblspace;  /* sentence end #spaces */
 int allbro;/* all buffs read-only  */
+int batch; /* for regress tests*/
 struct buffer  *curbp; /* current buffer   */
 struct buffer  *bheadp;/* BUFFER list head */
 struct mgwin   *curwp; /* current window   */
@@ -40,6 +43,7 @@ struct mgwin  *wheadp;/* MGWIN listhea
 charpat[NPAT]; /* pattern  */

 static void edinit(struct buffer *);
+static void pty_init(void);
 static __dead void usage(void);

 extern char*__progname;
@@ -48,8 +52,8 @@ extern void closetags(void);
 static __dead void
 usage()
 {
-   fprintf(stderr, "usage: %s [-nR] [-f mode] [-u file] [+number] "
-   "[file ...]\n",
+   fprintf(stderr, "usage: %s [-nR] [-b file] [-f mode] [-u file] "
+   " [+number] [file ...]\n",
__progname);
exit(1);
 }
@@ -58,6 +62,7 @@ int
 main(int argc, char **argv)
 {
char*cp, *conffile = NULL, *init_fcn_name = NULL;
+   char*batchfile = NULL;
PF   init_fcn = NULL;
int  o, i, nfiles;
int  nobackups = 0;
@@ -67,8 +72,12 @@ main(int argc, char **argv)
NULL) == -1)
err(1, "pledge");

-   while ((o = getopt(argc, argv, "nRf:u:")) != -1)
+   while ((o = getopt(argc, argv, "nRb:f:u:")) != -1)
switch (o) {
+   case 'b':
+   batch = 1;
+   batchfile = optarg;
+   break;
case 'R':
allbro = 1;
break;
@@ -87,6 +96,20 @@ main(int argc, char **argv)
default:
usage();
}
+
+   if (batch && (conffile != NULL)) {
+fprintf(stderr, "%s: -b and -u are mutually exclusive.\n",
+__progname);
+exit(1);
+   } else if (batch) {
+   pty_init();
+   conffile = batchfile;
+   }
+   if (conffile != NULL && access(conffile, R_OK) != 0) {
+fprintf(stderr, "%s: Missing file: %s\n", __progname, 
conffile);
+exit(1);
+   }
+
argc -= optind;
argv += optind;

@@ -136,6 +159,9 @@ main(int argc, char **argv)
if ((cp = startupfile(NULL, conffile)) != NULL)
(void)load(cp);

+   if (batch)
+   return (0);
+
/*
 * Now ensure any default buffer modes from the startup file are
 * given to any files opened when parsing the startup file.
@@ -249,6 +275,26 @@ edinit(struct buffer *bp)
wp->w_linep = wp->w_dotp = bp->b_headp;
wp->w_ntrows = nrow - 2; /* 2 = mode, echo.   */
wp->w_rflag = WFMODE | WFFULL;   /* Full. */
+}
+
+/*
+ * Create pty for batch mode.
+ */
+static void
+pty_init(void)
+{
+   struct winsize  

Re: mg: Fix Coverity Scan warning: Insecure data handling

2021-03-09 Thread Mark Lumsden

Thanks Todd. I'll pass your analysis on to Joachim.


Date: Tue, 09 Mar 2021 14:14:33 -0700
From: Todd C. Miller 
To: Mark Lumsden 
Cc: tech@openbsd.org
Subject: Re: mg: Fix Coverity Scan warning: Insecure data handling 


On Tue, 09 Mar 2021 20:14:19 +, Mark Lumsden wrote:


Here is a diff from Joachim Wiberg's version of mg.

"The strlcpy() function is guaranteed to never copy more than 'len - 1'
bytes, so there is no need to check if we copied more.  This is a bogus
warning since the introduction of strlcpy()."


That looks wrong to me.  strlcpy() returns the number of bytes it
would have copied if there was space.  But if there was insufficient
space then the return value can be larger.  It is not safe to blindly
use the return value without checking it first.

- todd





mg: Fix Coverity Scan warning: Insecure data handling

2021-03-09 Thread Mark Lumsden

Here is a diff from Joachim Wiberg's version of mg.

"The strlcpy() function is guaranteed to never copy more than 'len - 1'
bytes, so there is no need to check if we copied more.  This is a bogus
warning since the introduction of strlcpy()."

Tested and seems reasonable. ok?

Index: cinfo.c
===
RCS file: /cvs/src/usr.bin/mg/cinfo.c,v
retrieving revision 1.18
diff -u -p -r1.18 cinfo.c
--- cinfo.c 19 Mar 2015 21:22:15 -  1.18
+++ cinfo.c 9 Mar 2021 20:09:54 -
@@ -106,7 +106,6 @@ char *
 getkeyname(char *cp, size_t len, int k)
 {
const char  *np;
-   size_t   copied;

if (k < 0)
k = CHARMASK(k);/* sign extended char */
@@ -151,8 +150,6 @@ getkeyname(char *cp, size_t len, int k)
*cp = '\0';
return (cp);
}
-   copied = strlcpy(cp, np, len);
-   if (copied >= len)
-   copied = len - 1;
-   return (cp + copied);
+
+   return (cp + strlcpy(cp, np, len));
 }



Clear status line after killing or switching buffers

2021-03-09 Thread Mark Lumsden

From Joachim Wiberg's version of mg.


"This patch makes sure to clear the status/echo line after killing and
switching buffers by name.  Otherwise the kill/switch prompt lingers"

ok?

It also adds back a CVS tag on the first line of buffer.c that I 
inadvertantly removed a while back.


Index: buffer.c
===
RCS file: /cvs/src/usr.bin/mg/buffer.c,v
retrieving revision 1.109
diff -u -p -u -p -r1.109 buffer.c
--- buffer.c1 Mar 2021 10:51:14 -   1.109
+++ buffer.c9 Mar 2021 17:19:25 -
@@ -1,4 +1,4 @@
-
+/* $OpenBSD$ */

 /* This file is in the public domain. */

@@ -78,6 +78,7 @@ int
 usebufname(const char *bufp)
 {
struct buffer *bp = NULL;
+   int rc;

if (bufp == NULL) {
if ((bp = bfind("*scratch*", TRUE)) == NULL)
@@ -89,7 +90,10 @@ usebufname(const char *bufp)

/* and put it in current window */
curbp = bp;
-   return (showbuffer(bp, curwp, WFFRAME | WFFULL));
+   rc = showbuffer(bp, curwp, WFFRAME | WFFULL);
+   eerase();
+
+   return (rc);
 }

 /*
@@ -165,6 +169,7 @@ killbuffer_cmd(int f, int n)
 {
struct buffer *bp;
charbufn[NBUFN], *bufp;
+   int rc;

if (f & FFRAND) /* dired mode 'q' */
bp = curbp;
@@ -175,7 +180,10 @@ killbuffer_cmd(int f, int n)
bp = curbp;
else if ((bp = bfind(bufn, FALSE)) == NULL)
return (FALSE);
-   return (killbuffer(bp));
+   rc = killbuffer(bp);
+   eerase();
+
+   return (rc);
 }

 int



mg: Dired opening directory error

2021-03-01 Thread Mark Lumsden
If invoking 'M-x dired' and an error is encountered opening a directory, 
mg isn't very helpful. Though it will display a message on an EACCES 
problem. This diff doesn't go into the specifcs of which other error 
access(2) has encountered but does display an error msg:


"Error opening: /non/existant/dir/"

ok?

Index: dired.c
===
RCS file: /cvs/src/usr.bin/mg/dired.c,v
retrieving revision 1.97
diff -u -p -u -p -r1.97 dired.c
--- dired.c 1 Mar 2021 10:51:14 -   1.97
+++ dired.c 1 Mar 2021 13:26:49 -
@@ -243,7 +243,7 @@ dired(int f, int n)
dname[0] = '\0';
}

-   if ((bufp = eread("Dired: ", dname, NFILEN,
+   if ((bufp = eread("Dired (directory): ", dname, NFILEN,
EFDEF | EFNEW | EFCR)) == NULL)
return (ABORT);
if (bufp[0] == '\0')
@@ -928,6 +928,9 @@ dired_(char *dname)
if (errno == EACCES) {
dobeep();
ewprintf("Permission denied: %s", dname);
+   } else {
+   dobeep();
+   ewprintf("Error opening: %s", dname);
}
return (NULL);
}



Variablise \n and some regression tests

2021-02-26 Thread Mark Lumsden
This diff puts the hardcoded '\n' character which is found throughout mg 
into a buffer specific variable. The diff should not produce any behavourial

difference in mg, it is only to facilitate other work I am doing on mg.

In order for me to validate that there is no behavioural difference I 
created some regression tests:


https://mg-regress.s3-eu-west-1.amazonaws.com/regress.dir.007.tgz

If you want to run the regressions tests, the instructions are in 
the file: regress/mg.regress.tests. The tests are performed by the mg 
eval-current-buffer function, they are not 'make' style tests. I will add 
more tests as time allows.


Are there any objections to the diff? Or oks?

Feedback on the tests, or more tests added would be appreciated.

Mark

Index: buffer.c
===
RCS file: /cvs/src/usr.bin/mg/buffer.c,v
retrieving revision 1.107
diff -u -p -u -p -r1.107 buffer.c
--- buffer.c24 Jun 2019 14:57:56 -  1.107
+++ buffer.c26 Feb 2021 14:33:43 -
@@ -589,6 +589,8 @@ bnew(const char *bname)
bheadp = bp;
bp->b_dotline = bp->b_markline = 1;
bp->b_lines = 1;
+   bp->b_nlseq = "\n";/* use unix default */
+   bp->b_nlchr = bp->b_nlseq;
if ((bp->b_bname = strdup(bname)) == NULL) {
dobeep();
ewprintf("Can't get %d bytes", strlen(bname) + 1);
@@ -1022,7 +1024,7 @@ diffbuffer(int f, int n)
ttext += llength(lp);
}
if (lforw(lp) != lpend) /* no implied \n on last line */
-   *ttext++ = '\n';
+   *ttext++ = *curbp->b_nlchr;
}

bp = bfind("*Diff*", TRUE);
Index: cscope.c
===
RCS file: /cvs/src/usr.bin/mg/cscope.c,v
retrieving revision 1.18
diff -u -p -u -p -r1.18 cscope.c
--- cscope.c3 Jul 2019 03:24:02 -   1.18
+++ cscope.c26 Feb 2021 14:33:43 -
@@ -226,7 +226,7 @@ cscreatelist(int f, int n)
addline(bp, title);
addline(bp, "");
while ((len = getline(, , fpipe)) != -1) {
-   if (line[len - 1] == '\n')
+   if (line[len - 1] == *bp->b_nlchr)
line[len - 1] = '\0';
addline(bp, line);
}
@@ -459,7 +459,7 @@ do_cscope(int i)
addline(bp, "");
addline(bp, 
"---");
while ((len = getline(, , fpipe)) != -1) {
-   if (buf[len - 1] == '\n')
+   if (buf[len - 1] == *bp->b_nlchr)
buf[len - 1] = '\0';
if (addentry(bp, buf) != TRUE) {
free(buf);
Index: def.h
===
RCS file: /cvs/src/usr.bin/mg/def.h,v
retrieving revision 1.167
diff -u -p -u -p -r1.167 def.h
--- def.h   23 Feb 2021 08:10:51 -  1.167
+++ def.h   26 Feb 2021 14:33:43 -
@@ -267,6 +267,8 @@ struct buffer {
char b_flag;/* Flags */
char b_fname[NFILEN]; /* File name   */
char b_cwd[NFILEN]; /* working directory */
+   char*b_nlseq;   /* Newline sequence of chars */
+   char*b_nlchr;   /* 1st newline character */
struct fileinfo  b_fi;  /* File attributes   */
struct undoq b_undo;/* Undo actions list */
struct undo_rec *b_undoptr;
Index: dired.c
===
RCS file: /cvs/src/usr.bin/mg/dired.c,v
retrieving revision 1.96
diff -u -p -u -p -r1.96 dired.c
--- dired.c 26 Feb 2021 07:21:23 -  1.96
+++ dired.c 26 Feb 2021 14:33:43 -
@@ -698,11 +698,12 @@ d_exec(int space, struct buffer *bp, con
if ((fin = fdopen(fds[0], "r")) == NULL)
goto out;
while (fgets(buf, sizeof(buf), fin) != NULL) {
-   cp = strrchr(buf, '\n');
+   cp = strrchr(buf, *bp->b_nlchr);
if (cp == NULL && !feof(fin)) { /* too long a line */
int c;
addlinef(bp, "%*s%s...", space, "", buf);
-   while ((c = getc(fin)) != EOF && c != '\n')
+   while ((c = getc(fin)) != EOF &&
+   c != *bp->b_nlchr)
;
continue;
} else if (cp)
Index: echo.c
===
RCS file: /cvs/src/usr.bin/mg/echo.c,v
retrieving revision 1.66
diff -u -p -u -p -r1.66 echo.c
--- echo.c  24 Oct 2016 

mg: minibuffer anomaly

2021-02-25 Thread Mark Lumsden
I was testing mg's goto-line function via the minibuffer (M-x goto-line) 
and I just kept my finger on the '0' key. After a brief time '0's 
started appearing in the main buffer, where the cursor had been. For a 
second I thought there had been an issue with memory allocation but after 
looking at the code I see what happens is when the memory allocated to the 
minibuffer fills up, a message "Line too long." should show in the 
minibuffer. It probably did, but since I was pressing the '0' key it 
disappeared instantly and I didn't realise that mg had tried to inform me 
of my error. mg then continued to accept my '0's as normal input.


This diff soaks up the user input while the the maximum character length 
boundary is crossed in the minbuffer and allows the user to see the error 
message and respond accordingly.


There may be other ways to handle this situation (like not pressing the 
'0' key so many times) but I think having mg do something is better than
it *seemingly* not do anything. Any suggestions/preferences/better 
solutions?


Mark

Index: echo.c
===
RCS file: /cvs/src/usr.bin/mg/echo.c,v
retrieving revision 1.66
diff -u -p -u -p -r1.66 echo.c
--- echo.c  24 Oct 2016 17:18:42 -  1.66
+++ echo.c  25 Feb 2021 19:06:21 -
@@ -336,8 +336,8 @@ veread(const char *fp, char *buf, size_t
}
if (!dynbuf && epos + 1 >= nbuf) {
dobeep();
-   ewprintf("Line too long");
-   return (emptyval);
+   ewprintf("Line too long. Press Enter.");
+   goto null;
}
for (t = epos; t > cpos; t--)
buf[t] = buf[t - 1];
@@ -492,8 +492,8 @@ veread(const char *fp, char *buf, size_t
}
if (!dynbuf && epos + 1 >= nbuf) {
dobeep();
-   ewprintf("Line too long");
-   return (emptyval);
+   ewprintf("Line too long. Press Enter.");
+   goto null;
}
for (i = epos; i > cpos; i--)
buf[i] = buf[i - 1];
@@ -507,6 +507,9 @@ veread(const char *fp, char *buf, size_t
ttmove(rr, cc);
ttflush();
}
+
+null:  /* soak up any continuing key strokes */
+;
}
 done:
if (cwin == TRUE) {



mg: fix direction of mark-paragraph

2021-02-23 Thread Mark Lumsden

The current direction of marking paragraphs using 'mark-paragraph' in mg
is the opposite of emacs. Emacs goes backwards, mg goes forwards. This 
diff brings mg inline with emacs, and also simplifies the code, and fixes 
another bug with the current code.


ok?

Index: paragraph.c
===
RCS file: /cvs/src/usr.bin/mg/paragraph.c,v
retrieving revision 1.46
diff -u -p -u -p -r1.46 paragraph.c
--- paragraph.c 17 Nov 2018 09:52:34 -  1.46
+++ paragraph.c 23 Feb 2021 20:32:43 -
@@ -302,23 +302,16 @@ killpara(int f, int n)
 int
 markpara(int f, int n)
 {
-   int i = 0;
-
if (n == 0)
return (TRUE);

clearmark(FFARG, 0);

-   if (findpara() == FALSE)
-   return (TRUE);
-
-   (void)do_gotoeop(FFRAND, n, );
-
/* set the mark here */
curwp->w_markp = curwp->w_dotp;
curwp->w_marko = curwp->w_doto;

-   (void)gotobop(FFRAND, i);
+   (void)gotobop(FFRAND, n);

return (TRUE);
 }



mg: specify a different startup file

2021-02-21 Thread Mark Lumsden

This diff allows mg(1) to specify an alternative startup file on
the fly when starting mg:

$ mg -u ~/.mg2

I decided to use "u" since that is what emacs uses to load
another user's init file:

https://www.gnu.org/software/emacs/manual/html_node/emacs/Init-File.html

Perhaps "f" would be better but that is being used to set mg modes

Also, I decided not to load the default startup file if the
alternative is not found since it seems more obvious that something
is wrong that way.

Any comments/ok?

Mark

Index: def.h
===
RCS file: /cvs/src/usr.bin/mg/def.h,v
retrieving revision 1.166
diff -u -p -u -p -r1.166 def.h
--- def.h   9 Feb 2020 10:13:13 -   1.166
+++ def.h   21 Feb 2021 12:55:41 -
@@ -471,7 +471,7 @@ int  ffputbuf(FILE *, struct buffer *,
 int ffgetline(FILE *, char *, int, int *);
 int fbackupfile(const char *);
 char   *adjustname(const char *, int);
-char   *startupfile(char *);
+char   *startupfile(char *, char *);
 int copy(char *, char *);
 struct list*make_file_list(char *);
 int fisdir(const char *);
Index: fileio.c
===
RCS file: /cvs/src/usr.bin/mg/fileio.c,v
retrieving revision 1.106
diff -u -p -u -p -r1.106 fileio.c
--- fileio.c22 Jun 2019 10:21:57 -  1.106
+++ fileio.c21 Feb 2021 12:55:41 -
@@ -330,7 +330,7 @@ adjustname(const char *fn, int slashslas
  * to the startup file name.
  */
 char *
-startupfile(char *suffix)
+startupfile(char *suffix, char *conffile)
 {
static char  file[NFILEN];
char*home;
@@ -339,7 +339,9 @@ startupfile(char *suffix)
if ((home = getenv("HOME")) == NULL || *home == '\0')
goto nohome;

-   if (suffix == NULL) {
+   if (conffile != NULL) {
+   (void)strncpy(file, conffile, NFILEN);
+   } else if (suffix == NULL) {
ret = snprintf(file, sizeof(file), _PATH_MG_STARTUP, home);
if (ret < 0 || ret >= sizeof(file))
return (NULL);
Index: main.c
===
RCS file: /cvs/src/usr.bin/mg/main.c,v
retrieving revision 1.87
diff -u -p -u -p -r1.87 main.c
--- main.c  22 Jun 2019 15:38:15 -  1.87
+++ main.c  21 Feb 2021 12:55:41 -
@@ -48,7 +48,8 @@ extern void closetags(void);
 static __dead void
 usage()
 {
-   fprintf(stderr, "usage: %s [-nR] [-f mode] [+number] [file ...]\n",
+   fprintf(stderr, "usage: %s [-nR] [-f mode] [-u file] [+number] "
+   "[file ...]\n",
__progname);
exit(1);
 }
@@ -56,7 +57,7 @@ usage()
 int
 main(int argc, char **argv)
 {
-   char*cp, *init_fcn_name = NULL;
+   char*cp, *conffile = NULL, *init_fcn_name = NULL;
PF   init_fcn = NULL;
int  o, i, nfiles;
int  nobackups = 0;
@@ -66,7 +67,7 @@ main(int argc, char **argv)
NULL) == -1)
err(1, "pledge");

-   while ((o = getopt(argc, argv, "nRf:")) != -1)
+   while ((o = getopt(argc, argv, "nRf:u:")) != -1)
switch (o) {
case 'R':
allbro = 1;
@@ -80,6 +81,9 @@ main(int argc, char **argv)
"initial function");
init_fcn_name = optarg;
break;
+   case 'u':
+   conffile = optarg;
+   break;
default:
usage();
}
@@ -129,7 +133,7 @@ main(int argc, char **argv)
update(CMODE);

/* user startup file. */
-   if ((cp = startupfile(NULL)) != NULL)
+   if ((cp = startupfile(NULL, conffile)) != NULL)
(void)load(cp);

/*
Index: mg.1
===
RCS file: /cvs/src/usr.bin/mg/mg.1,v
retrieving revision 1.118
diff -u -p -u -p -r1.118 mg.1
--- mg.18 Nov 2019 19:54:40 -   1.118
+++ mg.121 Feb 2021 12:55:42 -
@@ -11,6 +11,7 @@
 .Nm mg
 .Op Fl nR
 .Op Fl f Ar mode
+.Op Fl u Ar file
 .Op + Ns Ar number
 .Op Ar
 .Sh DESCRIPTION
@@ -38,6 +39,11 @@ line of the file, +-2 will be second las
 Run the mode command for all buffers created from
 arguments on the command line, including the
 scratch buffer and all files.
+.It Fl u Ar file
+Use
+.Ar file
+as the startup file, instead of the default
+.Pa ~/.mg .
 .It Fl n
 Turn off backup file generation.
 .It Fl R
Index: ttykbd.c
===
RCS file: /cvs/src/usr.bin/mg/ttykbd.c,v
retrieving revision 1.19
diff -u -p -u -p -r1.19 ttykbd.c
--- ttykbd.c17 Dec 2017 14:37:57 -  1.19
+++ ttykbd.c21 Feb 2021 12:55:42 -
@@ -58,7 

mg(1) list evaluation

2019-07-15 Thread Mark Lumsden
This diff introduces lists to the startup file of mg. With this diff 
applied you could have something similar to:


(define y(list b.txt c.txt))
(define z(list d.txt e.txt))
(find-file a.txt y f.txt z)

in your .mg file, and when you opened mg, there would be 7 buffers opened 
(a.txt, b.txt, c.txt, d.txt, e.txt, and f.txt, including the *scratch* 
buffer)


When I got about 3/4 of the way through this diff I realised I was 
probably not doing it the best way. I should have a list of 'key' words 
and multi-line parsing and lists within lists etc... I think I need to go 
back and take those ideas and apply them bit by bit to this diff. However, 
as a way forward does anyone object to this diff going in? My plan is to 
hopefully have some kind of user definable functions in mg, but functions 
(usually) need conditionals and variables, so I am trying to add in the 
basics beforehand. I'm using this for regress tests within mg, but 
arguably there could be other uses, depending on how much was developed.


Like with the previous multi arg diff, if your .mg file has no '(' 
characters on the first line, you won't (or shouldn't) see any functional 
difference in mg. Any comments/objections?


Mark

Index: bell.c
===
RCS file: /cvs/src/usr.bin/mg/bell.c,v
retrieving revision 1.4
diff -u -p -u -p -r1.4 bell.c
--- bell.c  3 Jan 2016 19:37:08 -   1.4
+++ bell.c  15 Jul 2019 20:12:00 -
@@ -26,6 +26,23 @@ bellinit(void)
dovisiblebell = 0;
 }

+
+int
+dobeep_msgs(const char *msg, const char *s)
+{
+   ewprintf("%s %s", msg, s);
+   dobeep();
+   return (FALSE);
+}
+
+int
+dobeep_msg(const char *msg)
+{
+   ewprintf("%s", msg);
+   dobeep();
+   return (FALSE);
+}
+
 void
 dobeep(void)
 {
Index: def.h
===
RCS file: /cvs/src/usr.bin/mg/def.h,v
retrieving revision 1.162
diff -u -p -u -p -r1.162 def.h
--- def.h   3 Jul 2019 18:11:07 -   1.162
+++ def.h   15 Jul 2019 20:12:00 -
@@ -711,6 +711,8 @@ int  compile(int, int);
 voidbellinit(void);
 int toggleaudiblebell(int, int);
 int togglevisiblebell(int, int);
+int dobeep_msgs(const char *, const char *);
+int dobeep_msg(const char *);
 voiddobeep(void);

 /*
Index: extend.c
===
RCS file: /cvs/src/usr.bin/mg/extend.c,v
retrieving revision 1.67
diff -u -p -u -p -r1.67 extend.c
--- extend.c11 Jul 2019 18:20:18 -  1.67
+++ extend.c15 Jul 2019 20:12:00 -
@@ -29,6 +29,17 @@ static intdobind(KEYMAP *, const char
 static char*skipwhite(char *);
 static char*parsetoken(char *);
 static int  bindkey(KEYMAP **, const char *, KCHAR *, int);
+static int  clearvars(void);
+
+struct varentry {
+   SLIST_ENTRY(varentry) entry;
+   char*name;
+   char*vals;
+   int  count;
+};
+SLIST_HEAD(slisthead, varentry) varhead = SLIST_HEAD_INITIALIZER(varhead);
+
+#defineBUFSIZE 128 /* Size of line contents - could be 
larger? */

 /*
  * Insert a string, mainly for use from macros (created by selfinsert).
@@ -37,7 +48,7 @@ static int bindkey(KEYMAP **, const cha
 int
 insert(int f, int n)
 {
-   char buf[128], *bufp, *cp;
+   char buf[BUFSIZE], *bufp, *cp;
int  count, c;

if (inmacro) {
@@ -595,7 +606,7 @@ extend(int f, int n)
 int
 evalexpr(int f, int n)
 {
-   char exbuf[128], *bufp;
+   char exbuf[BUFSIZE], *bufp;

if ((bufp = eread("Eval: ", exbuf, sizeof(exbuf),
EFNEW | EFCR)) == NULL)
@@ -616,18 +627,21 @@ evalbuffer(int f, int n)
struct line *lp;
struct buffer   *bp = curbp;
int  s;
-   static char  excbuf[128];
+   static char  excbuf[BUFSIZE];

for (lp = bfirstlp(bp); lp != bp->b_headp; lp = lforw(lp)) {
-   if (llength(lp) >= 128)
+   if (llength(lp) >= BUFSIZE)
return (FALSE);
(void)strncpy(excbuf, ltext(lp), llength(lp));

/* make sure it's terminated */
excbuf[llength(lp)] = '\0';
-   if ((s = excline(excbuf)) != TRUE)
+   if ((s = excline(excbuf)) != TRUE) {
+   (void) clearvars();
return (s);
+   }
}
+   (void) clearvars();
return (TRUE);
 }

@@ -657,7 +671,7 @@ load(const char *fname)
 {
int  s = TRUE, line, ret;
int  nbytes = 0;
-   char excbuf[128], fncpy[NFILEN];
+   char excbuf[BUFSIZE], fncpy[NFILEN];
FILE*ffp;

if ((fname = adjustname(fname, TRUE)) == NULL)
@@ -693,17 +707,39 @@ load(const char *fname)
 }

 /*
- * Line has a '(' as the first 

Re: mg(1) evaluate multi-argument commands

2019-07-09 Thread Mark Lumsden
This is a modified diff of the previous evaluate multi-argument diff. The 
main difference is that all functions are given a number of parameters in 
the function map, this number represents how many arguments are required 
for the function to work. This extra column indicates to multiarg() how it 
should treat the list of arguments it receives, it needs to know how many 
arguments are 'normal' for the function being used, in order to separate 
the different invocations of the function to have the correct number of 
arguments. For example, this call to functionX:


(functionX w x y z)

Does functionX need 4 invocations, or 2, or 1?

The new value is not used in any other situation other than evaluating 
the startup file or using an evaluate command, therefor it doesn't 
interfere with using mg as an interactive editor.


I'd appreciate if this diff could be tested, to show if there are 
regressions in peoples .mg files. This diff does treat the '(' and ')' 
chars differently than previously, in-so-far as they are not ignored if 
they are at the end or start of a line now. However, even though these 
characters are not ignored, this diff should not change the behaviour of 
an extant .mg file, with '(' and ')' chars at the end and start of a line. 
This situation is accomodated for in this diff (with limited testing 
though).


Does the above text explain what I am trying to do? In a general sense, 
this diff is to aid in the programability/extensibility of mg. If you have 
any thoughts or suggestions on how this could be acheived, please feel 
free to give me feedback/observations/criticisms etc.. Thanks.


Mark

Index: cmode.c
===
RCS file: /cvs/src/usr.bin/mg/cmode.c,v
retrieving revision 1.16
diff -u -p -u -p -r1.16 cmode.c
--- cmode.c 26 Sep 2015 21:51:58 -  1.16
+++ cmode.c 9 Jul 2019 16:54:49 -
@@ -91,12 +91,12 @@ static struct KEYMAPE (3) cmodemap = {
 void
 cmode_init(void)
 {
-   funmap_add(cmode, "c-mode");
-   funmap_add(cc_char, "c-handle-special-char");
-   funmap_add(cc_brace, "c-handle-special-brace");
-   funmap_add(cc_tab, "c-tab-or-indent");
-   funmap_add(cc_indent, "c-indent");
-   funmap_add(cc_lfindent, "c-indent-and-newline");
+   funmap_add(cmode, "c-mode", 0);
+   funmap_add(cc_char, "c-handle-special-char", 0);
+   funmap_add(cc_brace, "c-handle-special-brace", 0);
+   funmap_add(cc_tab, "c-tab-or-indent", 0);
+   funmap_add(cc_indent, "c-indent", 0);
+   funmap_add(cc_lfindent, "c-indent-and-newline", 0);
maps_add((KEYMAP *), "c");
 }

Index: dired.c
===
RCS file: /cvs/src/usr.bin/mg/dired.c,v
retrieving revision 1.92
diff -u -p -u -p -r1.92 dired.c
--- dired.c 1 Jul 2019 19:36:17 -   1.92
+++ dired.c 9 Jul 2019 16:54:49 -
@@ -204,24 +204,24 @@ static struct KEYMAPE (7) diredmap = {
 void
 dired_init(void)
 {
-   funmap_add(dired, "dired");
-   funmap_add(d_create_directory, "dired-create-directory");
-   funmap_add(d_copy, "dired-do-copy");
-   funmap_add(d_expunge, "dired-do-flagged-delete");
-   funmap_add(d_rename, "dired-do-rename");
-   funmap_add(d_findfile, "dired-find-file");
-   funmap_add(d_ffotherwindow, "dired-find-file-other-window");
-   funmap_add(d_del, "dired-flag-file-deletion");
-   funmap_add(d_gotofile, "dired-goto-file");
-   funmap_add(d_forwline, "dired-next-line");
-   funmap_add(d_otherwindow, "dired-other-window");
-   funmap_add(d_backline, "dired-previous-line");
-   funmap_add(d_refreshbuffer, "dired-revert");
-   funmap_add(d_backpage, "dired-scroll-down");
-   funmap_add(d_forwpage, "dired-scroll-up");
-   funmap_add(d_undel, "dired-unmark");
-   funmap_add(d_undelbak, "dired-unmark-backward");
-   funmap_add(d_killbuffer_cmd, "quit-window");
+   funmap_add(dired, "dired", 1);
+   funmap_add(d_create_directory, "dired-create-directory", 1);
+   funmap_add(d_copy, "dired-do-copy", 1);
+   funmap_add(d_expunge, "dired-do-flagged-delete", 0);
+   funmap_add(d_rename, "dired-do-rename", 1);
+   funmap_add(d_findfile, "dired-find-file", 1);
+   funmap_add(d_ffotherwindow, "dired-find-file-other-window", 1);
+   funmap_add(d_del, "dired-flag-file-deletion", 0);
+   funmap_add(d_gotofile, "dired-goto-file", 1);
+   funmap_add(d_forwline, "dired-next-line", 0);
+   funmap_add(d_otherwindow, "dired-other-window", 0);
+   funmap_add(d_backline, "dired-previous-line", 0);
+   funmap_add(d_refreshbuffer, "dired-revert", 0);
+   funmap_add(d_backpage, "dired-scroll-down", 0);
+   funmap_add(d_forwpage, "dired-scroll-up", 0);
+   funmap_add(d_undel, "dired-unmark", 0);
+   funmap_add(d_undelbak, "dired-unmark-backward", 0);
+   funmap_add(d_killbuffer_cmd, "quit-window", 0);
maps_add((KEYMAP 

Re: mg(1) evaluate multi-argument commands

2019-07-05 Thread Mark Lumsden
I should add, I meant to put checks in for the calls to strlcpy and 
strlcat, but was pushed for time and forgot.. but of course they would be 
put in.




mg(1) evaluate multi-argument commands

2019-07-05 Thread Mark Lumsden
I was finding it a bit tedious with long evaluation buffers so I wrote a 
function that would translate these three (or more) lines:


find-file a.txt
find-file b.txt
find-file c.txt

into this one line:

(find-file a.txt b.txt c.txt)

There are a few commands that can be used like this: insert, 
self-insert-char, kill-buffer, make-directory and some others. 
Interestingly 'insert-buffer' makes mg segv when used in this way, though 
it does behave the same without the below diff applied. I'll have to 
have a look and see why.


I'm thinking I might write some kind of loop in the buffer evaulation 
code.


However, does anyone object to this code? There is the side effect that 
the '(' and ')' characters are no longer seen as white space during buffer 
evaluation.


Mark

Index: extend.c
===
RCS file: /cvs/src/usr.bin/mg/extend.c,v
retrieving revision 1.66
diff -u -p -u -p -r1.66 extend.c
--- extend.c5 Jul 2019 14:50:59 -   1.66
+++ extend.c5 Jul 2019 14:58:23 -
@@ -8,6 +8,7 @@

 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -693,6 +694,93 @@ load(const char *fname)
 }

 /*
+ * Line has a '(' as the first non-white char.
+ */
+int
+multiarg(char *funstr)
+{
+   regex_t  regex_buff;
+   PF   funcp;
+   char excbuf[128];
+   char*cmdp, *argp, *fendp, *endp, *p, *s = " ";
+   int  singlecmd = 0, spc;
+ 
+	endp = strrchr(funstr, ')');

+   if (endp == NULL) {
+   ewprintf("No closing parenthesis found");
+   return(FALSE);
+   }
+   p = endp + 1;
+   /* we now know that string starts with '(' and ends with ')' */
+   *p = '\0';
+
+   if (regcomp(_buff, "^\([\t ]*)$", 0)) {
+   dobeep();
+   ewprintf("Could not compile regex");
+   return(FALSE);
+   }
+   if (!regexec(_buff, funstr, 0, NULL, 0)) {
+   dobeep();
+   ewprintf("No command found");
+   return(FALSE);
+   }
+ 
+	/* currently there are no mg commands that don't have a letter */

+   if (regcomp(_buff, "^\([\t ]*[A-Za-z]*[\t ]*)$", 0)) {
+   dobeep();
+   ewprintf("Could not compile regex");
+   return(FALSE);
+   }
+   if (!regexec(_buff, funstr, 0, NULL, 0))
+   singlecmd = 1;
+
+   p = funstr + 1; /* move past first '(' char.*/
+   cmdp = skipwhite(p);/* find first char of command.  */
+
+   if (singlecmd) {
+   cmdp[strlen(cmdp) - 1] = '\0'; /* remove ')'*/
+   return(excline(cmdp));
+   }
+   if (((fendp = strchr(cmdp, ' ')) == NULL) &&
+   ((fendp = strchr(cmdp, '\t')) == NULL)) {
+   dobeep();
+   ewprintf("Regular expression misuse");
+   return (FALSE);
+   }
+   *fendp = '\0';
+
+   if ((funcp = name_function(cmdp)) == NULL) {
+   dobeep();
+   ewprintf("Unknown command: %s", cmdp);
+   return (FALSE);
+   }
+   /* now find the first argument */
+	p = fendp + 1; 
+	argp = skipwhite(p);

+   spc = 1; /* initally fake a space so we find first argument */
+
+   for (p = argp; *p != '\0'; p++) {
+   if (*p == ' ' || *p == '\t' || *p == ')') {
+   if (spc == 0) {
+   *p = '\0';  /* terminate arg string */
+   excbuf[0] = '\0';
+   strlcpy(excbuf, cmdp, sizeof(excbuf));
+   strlcat(excbuf, s, sizeof(excbuf));
+   strlcat(excbuf, argp, sizeof(excbuf));
+   excline(excbuf);
+   *p = ' ';   /* so 'for' loop can continue */
+   }
+   spc = 1;
+   } else {
+   if (spc == 1)
+   argp = p;
+   spc = 0;
+   }
+   }
+   return (TRUE);
+}
+
+/*
  * excline - run a line from a load file or eval-expression.
  */
 int
@@ -724,6 +812,8 @@ excline(char *line)
funcp = skipwhite(line);
if (*funcp == '\0')
return (TRUE);  /* No error on blank lines */
+   if (*funcp == '(')
+   return (multiarg(funcp));
line = parsetoken(funcp);
if (*line != '\0') {
*line++ = '\0';
@@ -928,7 +1018,7 @@ cleanup:
 static char *
 skipwhite(char *s)
 {
-   while (*s == ' ' || *s == '\t' || *s == ')' || *s == '(')
+   while (*s == ' ' || *s == '\t')
s++;
if ((*s == ';') || (*s == '#'))
*s = '\0';



startup file - error message

2019-07-03 Thread Mark Lumsden

If you have something like this in your .mg file:

find-file /home/lum/test
imaginary-command

When you open mg you will see an error:

Error loading file /home/lum/test at line 2

If you open files in your .mg file, but then have any kind of error with 
the evaluation of lines afterwards (even non file opening/closing errors), 
mg uses the last filename opened in the error message. Hence, the error 
should have said:


Error loading file /home/lum/.mg at line 2

..since 'imaginary-command' IS imaginary.

Comments/oks?

Mark

Index: extend.c
===
RCS file: /cvs/src/usr.bin/mg/extend.c,v
retrieving revision 1.65
diff -u -p -u -p -r1.65 extend.c
--- extend.c22 Jun 2019 15:38:15 -  1.65
+++ extend.c3 Jul 2019 21:25:00 -
@@ -657,7 +657,7 @@ load(const char *fname)
 {
int  s = TRUE, line, ret;
int  nbytes = 0;
-   char excbuf[128];
+   char excbuf[128], fncpy[NFILEN];
FILE*ffp;

if ((fname = adjustname(fname, TRUE)) == NULL)
@@ -670,7 +670,8 @@ load(const char *fname)
(void)ffclose(ffp, NULL);
return (FALSE);
}
-
+   /* keep a copy of fname incase of evaluation errors in excline. */
+   (void)strlcpy(fncpy, fname, sizeof(fncpy));
line = 0;
while ((s = ffgetline(ffp, excbuf, sizeof(excbuf) - 1, ))
== FIOSUC) {
@@ -679,7 +680,7 @@ load(const char *fname)
if (excline(excbuf) != TRUE) {
s = FIOERR;
dobeep();
-   ewprintf("Error loading file %s at line %d", fname, 
line);
+   ewprintf("Error loading file %s at line %d", fncpy, 
line);
break;
}
}



mg(1) self-insert-char

2019-07-02 Thread Mark Lumsden
In order to test certain aspects of mg, I use the eval-current-buffer 
function. However, that doesn't let me insert a character like 'a' unless 
mg is getting that character from another file or previously existing 
text, somewhere on disk, or in RAM.


This diff allows eval-current-buffer (or an mg startup file) to insert a 
character into a buffer via the self-insert-char function, which emulates 
the self-insert-command. For example:


find-file test
self-insert-char a
self-insert-char b
self-insert-char c
newline
save-buffer

The above would create a file called test (if it didn't exist already) 
with the contents 'abc\n' when invoked via eval-current-buffer (or an mg 
startup file).


The self-insert-command (which is the usual way of inserting a character 
into a buffer - but invoked via a 'normal' key press, not M-x 
self-insert-command) has other functionality when invoked via 
eval-current-buffer (or an mg startup file), see the man page. However, I 
may have missed some functionality of mg that allows a character to be 
inserted into a buffer via eval-current-buffer in this way. If so, please 
let me know. Though this new function does use the code I want to use/test 
(self-insert-command). Also, I have not included a man page addition since 
I am not too sure how useful the new function is to others. However should 
you run mg regress tests, it could be useful.


Comments/criticisms/advice welcome. As are oks.

Mark

Index: def.h
===
RCS file: /cvs/src/usr.bin/mg/def.h,v
retrieving revision 1.161
diff -u -p -u -p -r1.161 def.h
--- def.h   2 Jul 2019 16:25:39 -   1.161
+++ def.h   2 Jul 2019 16:56:09 -
@@ -490,6 +490,7 @@ int  rescan(int, int);
 int universal_argument(int, int);
 int digit_argument(int, int);
 int negative_argument(int, int);
+int ask_selfinsert(int, int);
 int selfinsert(int, int);
 int quote(int, int);

Index: funmap.c
===
RCS file: /cvs/src/usr.bin/mg/funmap.c,v
retrieving revision 1.57
diff -u -p -u -p -r1.57 funmap.c
--- funmap.c2 Jul 2019 16:25:39 -   1.57
+++ funmap.c2 Jul 2019 16:56:09 -
@@ -179,6 +179,7 @@ static struct funmap functnames[] = {
{searchagain, "search-again",},
{backsearch, "search-backward",},
{forwsearch, "search-forward",},
+   {ask_selfinsert, "self-insert-char",},
{selfinsert, "self-insert-command",},
{sentencespace, "sentence-end-double-space",},
 #ifdef REGEX
Index: kbd.c
===
RCS file: /cvs/src/usr.bin/mg/kbd.c,v
retrieving revision 1.32
diff -u -p -u -p -r1.32 kbd.c
--- kbd.c   26 Jun 2019 16:54:29 -  1.32
+++ kbd.c   2 Jul 2019 16:56:09 -
@@ -323,6 +323,22 @@ negative_argument(int f, int n)
return (mgwrap(funct, FFNEGARG, nn));
 }

+int
+ask_selfinsert(int f, int n)
+{
+   char*c, cbuf[2];
+
+   if ((c = eread("Insert a character: ", cbuf, sizeof(cbuf),
+   EFNEW)) == NULL || (c[0] == '\0'))
+   return (ABORT);
+
+   key.k_chars[0] = *c;
+   key.k_chars[1] = '\0';
+   key.k_count = 1;
+
+   return (selfinsert(FFRAND, 1));
+}
+
 /*
  * Insert a character. While defining a macro, create a "LINE" containing
  * all inserted characters.



Re: mg(1) M-x blink-and-insert

2019-07-01 Thread Mark Lumsden
I totally forgot about the instance where blink-and-insert can be called 
from the mg startup file. My previous diff broke that instance. So this 
diff reverts my change but adds a man page line to blink-and-insert (and 
comment).


ok?

Index: def.h
===
RCS file: /cvs/src/usr.bin/mg/def.h,v
retrieving revision 1.160
diff -u -p -u -p -r1.160 def.h
--- def.h   26 Jun 2019 16:42:30 -  1.160
+++ def.h   1 Jul 2019 17:00:48 -
@@ -642,7 +642,6 @@ void ttykeymapinit(void);
 voidttykeymaptidy(void);

 /* match.c X */
-int ask_showmatch(int, int);
 int showmatch(int, int);

 /* version.c X */
Index: funmap.c
===
RCS file: /cvs/src/usr.bin/mg/funmap.c,v
retrieving revision 1.56
diff -u -p -u -p -r1.56 funmap.c
--- funmap.c26 Jun 2019 16:42:30 -  1.56
+++ funmap.c1 Jul 2019 17:00:48 -
@@ -39,7 +39,7 @@ static struct funmap functnames[] = {
{backword, "backward-word",},
{gotobob, "beginning-of-buffer",},
{gotobol, "beginning-of-line",},
-   {ask_showmatch, "blink-and-insert",},
+   {showmatch, "blink-and-insert",},
{bsmap, "bsmap-mode",},
{NULL, "c-x 4 prefix",},
{NULL, "c-x prefix",},
Index: match.c
===
RCS file: /cvs/src/usr.bin/mg/match.c,v
retrieving revision 1.20
diff -u -p -u -p -r1.20 match.c
--- match.c 26 Jun 2019 16:42:30 -  1.20
+++ match.c 1 Jul 2019 17:00:48 -
@@ -35,30 +35,11 @@ static struct balance {
{ '\0', '\0' }
 };

-
 /*
- * Self-insert character, then show matching character.
- * Bound to "blink-and-insert".
- */
-int
-ask_showmatch(int f, int n)
-{
-   char*c, cbuf[2];
-
-   if ((c = eread("Insert a character: ", cbuf, sizeof(cbuf),
-   EFNEW)) == NULL || (c[0] == '\0'))
-   return (ABORT);
- 
-	key.k_chars[0] = *c;

-   key.k_chars[1] = '\0';
-   key.k_count = 1;
-
-   return (showmatch(FFRAND, 1));
-}
-
-
-/*
- * Hack to show matching paren. Bound to balance stucture chars ),],}.
+ * Hack to show matching paren.  Self-insert character, then show matching
+ * character, if any.  Bound to "blink-and-insert".  Used in the mg startup
+ * file to amend the default cursor behaviour of a key press, e.g:
+ *   global-set-key "%" blink-and-insert
  */
 int
 showmatch(int f, int n)
Index: mg.1
===
RCS file: /cvs/src/usr.bin/mg/mg.1,v
retrieving revision 1.115
diff -u -p -u -p -r1.115 mg.1
--- mg.117 Jun 2019 11:39:26 -  1.115
+++ mg.11 Jul 2019 17:00:48 -
@@ -417,6 +417,7 @@ matching delimiter.
 For delimiters other than
 parenthesis, brackets, and braces, the character itself
 is used as its own match.
+Can be used in the startup file with the global-set-key command.
 .It bsmap-mode
 Toggle bsmap mode, where DEL and C-h are swapped.
 .It c-mode



mg(1) dired-goto-file

2019-06-29 Thread Mark Lumsden

This add dired-goto-file to mg. Comments/ok?

Mark

Index: dired.c
===
RCS file: /cvs/src/usr.bin/mg/dired.c,v
retrieving revision 1.90
diff -u -p -u -p -r1.90 dired.c
--- dired.c 28 Jun 2019 13:35:02 -  1.90
+++ dired.c 29 Jun 2019 16:47:06 -
@@ -51,6 +51,7 @@ static int d_backline(int, int);
 static int  d_killbuffer_cmd(int, int);
 static int  d_refreshbuffer(int, int);
 static int  d_filevisitalt(int, int);
+static int  d_gotofile(int, int);
 static void reaper(int);
 static struct buffer   *refreshbuffer(struct buffer *);
 static int  createlist(struct buffer *);
@@ -127,7 +128,10 @@ static PF direda[] = {
d_del,  /* d */
d_findfile, /* e */
d_findfile, /* f */
-   d_refreshbuffer /* g */
+   d_refreshbuffer,/* g */
+   rescan, /* h */
+   rescan, /* i */
+   d_gotofile  /* j */
 };

 static PF diredn[] = {
@@ -186,7 +190,7 @@ static struct KEYMAPE (7) diredmap = {
CCHR('Z'), '+', diredcz, (KEYMAP *) & metamap
},
{
-   'a', 'g', direda, NULL
+   'a', 'j', direda, NULL
},
{
'n', 'x', diredn, NULL
@@ -208,6 +212,7 @@ dired_init(void)
funmap_add(d_findfile, "dired-find-file");
funmap_add(d_ffotherwindow, "dired-find-file-other-window");
funmap_add(d_del, "dired-flag-file-deletion");
+   funmap_add(d_gotofile, "dired-goto-file");
funmap_add(d_forwline, "dired-next-line");
funmap_add(d_otherwindow, "dired-other-window");
funmap_add(d_backline, "dired-previous-line");
@@ -1071,6 +1076,51 @@ createlist(struct buffer *bp)
nlp = lforw(lp);
}
return (ret);
+}
+
+int
+d_gotofile(int f, int n)
+{
+   struct line *lp, *nlp;
+   struct buffer   *curbp;
+   char fpath[NFILEN], fname[NFILEN];
+   char*p, *fnp = NULL;
+   int  tmp;
+
+   if (getbufcwd(fpath, sizeof(fpath)) != TRUE)
+   fpath[0] = '\0';
+   fnp = eread("Goto file: ", fpath, NFILEN,
+   EFNEW | EFCR | EFFILE | EFDEF);
+   if (fnp == NULL)
+   return (ABORT);
+   else if (fnp[0] == '\0')
+   return (FALSE);
+
+   (void)xbasename(fname, fpath, NFILEN);
+   curbp = curwp->w_bufp;
+   tmp = 0;
+   for (lp = bfirstlp(curbp); lp != curbp->b_headp; lp = nlp) {
+   tmp++;
+   if ((p = findfname(lp, p)) == NULL) {
+   nlp = lforw(lp);
+   continue;
+   }
+   if (strcmp(fname, p) == 0) {
+   curwp->w_dotp = lp;
+   curwp->w_dotline = tmp;
+   (void)d_warpdot(curwp->w_dotp, >w_doto);
+   tmp--;
+   break;
+   }
+   nlp = lforw(lp);
+   }
+   if (tmp == curbp->b_lines - 1) {
+   ewprintf("File not found %s", fname);
+   return (FALSE);
+   } else {
+   ewprintf("");
+   return (TRUE);
+   }
 }

 /*
Index: mg.1
===
RCS file: /cvs/src/usr.bin/mg/mg.1,v
retrieving revision 1.115
diff -u -p -u -p -r1.115 mg.1
--- mg.117 Jun 2019 11:39:26 -  1.115
+++ mg.129 Jun 2019 16:47:06 -
@@ -983,6 +983,8 @@ dired-do-copy
 dired-flag-file-deletion
 .It g
 dired-revert
+.It j
+dired-goto-file
 .It o
 dired-find-file-other-window
 .It p
@@ -1025,6 +1027,8 @@ is executed.
 .It dired-find-file-other-window
 Open the file on the current line of the dired buffer in a
 different window.
+.It dired-goto-file
+Move the cursor to a file name in the dired buffer.
 .It dired-next-line
 Move the cursor to the next line.
 .It dired-other-window



mg(1) copy file in dired mode

2019-06-25 Thread Mark Lumsden

In dired mode, if you try to copy a file without giving the new path a
file name, similar to:

cp /xdir/ydir/filname /xdir/

mg fails silently and doesn't copy the file into 'xdir' by using the
existing filename as the copied filename.

This diff uses the existing filename as the new filename if none is
specified. Comments/ok?

Mark

Index: dired.c
===
RCS file: /cvs/src/usr.bin/mg/dired.c,v
retrieving revision 1.85
diff -u -p -u -p -r1.85 dired.c
--- dired.c 25 Jun 2019 13:51:47 -  1.85
+++ dired.c 25 Jun 2019 15:22:19 -
@@ -445,6 +445,7 @@ d_expunge(int f, int n)
 int
 d_copy(int f, int n)
 {
+   struct stat  statbuf;
char frname[NFILEN], toname[NFILEN], sname[NFILEN];
char*topath, *bufp;
int  ret;
@@ -471,6 +472,18 @@ d_copy(int f, int n)
return (FALSE);

topath = adjustname(toname, TRUE);
+   if (stat(topath, ) == 0) {
+   if (S_ISDIR(statbuf.st_mode)) {
+   off = snprintf(toname, sizeof(toname), "%s/%s",
+   topath, sname);
+   if (off < 0 || off >= sizeof(toname) - 1) {
+   dobeep();
+   ewprintf("Directory name too long");
+   return (FALSE);
+   }
+   topath = adjustname(toname, TRUE);
+   }
+   }
ret = (copy(frname, topath) >= 0) ? TRUE : FALSE;
if (ret != TRUE)
return (ret);



mg(1) M-x blink-and-insert

2019-06-24 Thread Mark Lumsden

The man page for mg says this about blink-and-insert:

blink-and-insert
Self-insert a character, then search backwards and blink its matching
delimiter. For delimiters other than parenthesis, brackets, and braces,
the character itself is used as its own match.

However, if you do 'M-x blink-and-insert', mg inserts an 'x' character at 
the cursor and then tries to find the previous 'x' character. By, 'x', I 
mean a literal 'x' character, not a user typed character. The 'x' would 
seem to come from the keystroke 'M-x'. Which is very handy if you want to 
insert an 'x' and find a match with the previous 'x' (if there is one).


This diff attempts to make blink-and-insert do as the man page says it 
should do.


If you do 'M-x blink-and-insert', you are asked for a character. mg will 
then insert it at the current cursor position and then search backwards 
for a corresponding match.


The normal behaviour of typing a ),] or } hasn't changed.

Comments/ok?

Mark

Index: def.h
===
RCS file: /cvs/src/usr.bin/mg/def.h,v
retrieving revision 1.159
diff -u -p -u -p -r1.159 def.h
--- def.h   22 Jun 2019 15:38:15 -  1.159
+++ def.h   24 Jun 2019 19:20:11 -
@@ -642,6 +642,7 @@ void ttykeymapinit(void);
 voidttykeymaptidy(void);

 /* match.c X */
+int ask_showmatch(int, int);
 int showmatch(int, int);

 /* version.c X */
Index: funmap.c
===
RCS file: /cvs/src/usr.bin/mg/funmap.c,v
retrieving revision 1.55
diff -u -p -u -p -r1.55 funmap.c
--- funmap.c13 Dec 2018 14:59:16 -  1.55
+++ funmap.c24 Jun 2019 19:20:11 -
@@ -39,7 +39,7 @@ static struct funmap functnames[] = {
{backword, "backward-word",},
{gotobob, "beginning-of-buffer",},
{gotobol, "beginning-of-line",},
-   {showmatch, "blink-and-insert",},
+   {ask_showmatch, "blink-and-insert",},
{bsmap, "bsmap-mode",},
{NULL, "c-x 4 prefix",},
{NULL, "c-x prefix",},
Index: match.c
===
RCS file: /cvs/src/usr.bin/mg/match.c,v
retrieving revision 1.19
diff -u -p -u -p -r1.19 match.c
--- match.c 3 Jun 2015 23:40:01 -   1.19
+++ match.c 24 Jun 2019 19:20:11 -
@@ -35,9 +35,30 @@ static struct balance {
{ '\0', '\0' }
 };

+
 /*
- * Hack to show matching paren.  Self-insert character, then show matching
- * character, if any.  Bound to "blink-and-insert".
+ * Self-insert character, then show matching character.
+ * Bound to "blink-and-insert".
+ */
+int
+ask_showmatch(int f, int n)
+{
+   char*c, cbuf[2];
+
+   if ((c = eread("Insert a character: ", cbuf, sizeof(cbuf),
+   EFNEW)) == NULL || (c[0] == '\0'))
+   return (ABORT);
+ 
+	key.k_chars[0] = *c;

+   key.k_chars[1] = '\0';
+   key.k_count = 1;
+
+   return (showmatch(FFRAND, 1));
+}
+
+
+/*
+ * Hack to show matching paren. Bound to balance stucture chars ),],}.
  */
 int
 showmatch(int f, int n)



mg(1): don't withold data indefinitely.

2019-06-20 Thread Mark Lumsden

Currently if you have a file 'test' and cat it:

$ cat test
abc
def
ghk
$

Then open 'test' in mg and remove the newline at the end of the buffer and 
try to save it, mg will offer the opportunity to add a newline at the end 
of the buffer:


"No newline at end of file, add one? (y or n)"

Before you answer this question, if you then cat the 'test' file again you 
will see:


$ cat test
$

mg is waiting for your answer before writing the contents of the buffer to 
disk (the file it has already opened for writing).


This diff moves the check for the newline at the end of the buffer earlier 
so file data doesn't 'disappear' for an indefinite period (or arguably 
infinite period, if mg or the machine mg is running on crashes) before 
the user answers yes or no.


Comments/ok?
Mark

Index: def.h
===
RCS file: /cvs/src/usr.bin/mg/def.h,v
retrieving revision 1.157
diff -u -p -u -p -r1.157 def.h
--- def.h   13 Dec 2018 14:59:16 -  1.157
+++ def.h   20 Jun 2019 17:17:06 -
@@ -466,7 +466,7 @@ int  ffropen(FILE **, const char *, str
 voidffstat(FILE *, struct buffer *);
 int ffwopen(FILE **, const char *, struct buffer *);
 int ffclose(FILE *, struct buffer *);
-int ffputbuf(FILE *, struct buffer *);
+int ffputbuf(FILE *, struct buffer *, int);
 int ffgetline(FILE *, char *, int, int *);
 int fbackupfile(const char *);
 char   *adjustname(const char *, int);
Index: file.c
===
RCS file: /cvs/src/usr.bin/mg/file.c,v
retrieving revision 1.100
diff -u -p -u -p -r1.100 file.c
--- file.c  2 Jan 2016 10:39:19 -   1.100
+++ file.c  20 Jun 2019 17:17:06 -
@@ -668,9 +668,10 @@ makebkfile(int f, int n)
 int
 writeout(FILE ** ffp, struct buffer *bp, char *fn)
 {
-   struct stat statbuf;
-   int  s;
-   char dp[NFILEN];
+   struct stat  statbuf;
+   struct line *lpend;
+   int  s, eobnl;
+   char dp[NFILEN];

if (stat(fn, ) == -1 && errno == ENOENT) {
errno = 0;
@@ -686,10 +687,16 @@ writeout(FILE ** ffp, struct buffer *bp,
return (FIOERR);
}
 }
+   lpend = bp->b_headp;
+   eobnl = 0;
+   if (llength(lback(lpend)) != 0) {
+   if (eyorn("No newline at end of file, add one") == TRUE)
+   eobnl = 1;
+   }
/* open writes message */
if ((s = ffwopen(ffp, fn, bp)) != FIOSUC)
return (FALSE);
-   s = ffputbuf(*ffp, bp);
+   s = ffputbuf(*ffp, bp, eobnl);
if (s == FIOSUC) {
/* no write error */
s = ffclose(*ffp, bp);
Index: fileio.c
===
RCS file: /cvs/src/usr.bin/mg/fileio.c,v
retrieving revision 1.105
diff -u -p -u -p -r1.105 fileio.c
--- fileio.c13 Apr 2018 14:11:37 -  1.105
+++ fileio.c20 Jun 2019 17:17:06 -
@@ -150,11 +150,12 @@ ffclose(FILE *ffp, struct buffer *bp)
  * buffer. Return the status.
  */
 int
-ffputbuf(FILE *ffp, struct buffer *bp)
+ffputbuf(FILE *ffp, struct buffer *bp, int eobnl)
 {
-   struct line   *lp, *lpend;
+   struct line *lp, *lpend;

lpend = bp->b_headp;
+
for (lp = lforw(lpend); lp != lpend; lp = lforw(lp)) {
if (fwrite(ltext(lp), 1, llength(lp), ffp) != llength(lp)) {
dobeep();
@@ -164,14 +165,9 @@ ffputbuf(FILE *ffp, struct buffer *bp)
if (lforw(lp) != lpend) /* no implied \n on last line */
putc('\n', ffp);
}
-   /*
-* XXX should be variable controlled (once we have variables)
-*/
-   if (llength(lback(lpend)) != 0) {
-   if (eyorn("No newline at end of file, add one") == TRUE) {
-   lnewline_at(lback(lpend), llength(lback(lpend)));
-   putc('\n', ffp);
-   }
+   if (eobnl) {
+   lnewline_at(lback(lpend), llength(lback(lpend)));
+   putc('\n', ffp);
}
return (FIOSUC);
 }



Re: About transient mark mode

2019-06-13 Thread Mark Lumsden
Leonid's diff would seem to be an improvement on current behaviour, any 
objections to adding it to mg? Or comments/ok?


Mark


From openbsd-tech  Tue Jun 11 15:16:29 2019

From: Leonid Bobrov 
Date: Tue, 11 Jun 2019 15:16:29 +
To: openbsd-tech
Subject: About transient mark mode
Message-Id: <20190611151629.GA7591 () mazocomp ! lan>
X-MARC-Message: https://marc.info/?l=openbsd-tech=156026622527096

Hi!

If we don't have to follow what GNU Emacs is doing anyway, let's just
change behavior of {beginning,end}-of-buffer to this instead of
implementing a useless mode:

Index: basic.c
===
RCS file: /cvs/src/usr.bin/mg/basic.c,v
retrieving revision 1.48
diff -u -p -r1.48 basic.c
--- basic.c 3 Jun 2019 16:26:30 -   1.48
+++ basic.c 11 Jun 2019 15:15:15 -
@@ -124,7 +124,8 @@ forwchar(int f, int n)
 int
 gotobob(int f, int n)
 {
-   (void) setmark(f, n);
+   if (!curwp-w_markp)
+   (void) setmark(f, n);
curwp-w_dotp = bfirstlp(curbp);
curwp-w_doto = 0;
curwp-w_rflag |= WFFULL;
@@ -150,7 +151,8 @@ gotoeob(int f, int n)
int  ln;
struct line *lp;

-   (void) setmark(f, n);
+   if (!curwp-w_markp)
+   (void) setmark(f, n);
curwp-w_dotp = blastlp(curbp);
curwp-w_doto = llength(curwp-w_dotp);
curwp-w_dotline = curwp-w_bufp-b_lines;
Index: mg.1
===
RCS file: /cvs/src/usr.bin/mg/mg.1,v
retrieving revision 1.114
diff -u -p -r1.114 mg.1
--- mg.16 Jun 2019 18:17:34 -   1.114
+++ mg.111 Jun 2019 15:15:15 -
@@ -1,7 +1,7 @@
 .\"   $OpenBSD: mg.1,v 1.114 2019/06/06 18:17:34 jmc Exp $
 .\" This file is in the public domain.
 .\"
-.Dd $Mdocdate: June 6 2019 $
+.Dd $Mdocdate: June 11 2019 $
 .Dt MG 1
 .Os
 .Sh NAME
@@ -408,6 +408,7 @@ Move cursor to the top of the buffer.
 A numeric argument
 .Va n
 will move n/10th of the way from the top.
+Set mark at previous position if mark is not set.
 .It beginning-of-line
 Move cursor to the beginning of the line.
 .It blink-and-insert
@@ -532,6 +533,7 @@ Move cursor to the end of the buffer.
 A numeric argument
 .Va n
 will move n/10th of the way from the end.
+Set mark at previous position if mark is not set.
 .It end-of-line
 Move cursor to the end of the line.
 .It enlarge-window
Index: region.c
===
RCS file: /cvs/src/usr.bin/mg/region.c,v
retrieving revision 1.37
diff -u -p -r1.37 region.c
--- region.c9 Sep 2016 06:05:51 -   1.37
+++ region.c11 Jun 2019 15:15:15 -
@@ -405,6 +405,7 @@ markbuffer(int f, int n)
 {
if (gotoeob(f,n) == FALSE)
return (FALSE);
+   (void) clearmark(f, n);
if (gotobob(f,n) == FALSE)
return (FALSE);
return (TRUE);



mg(1) log internals to file

2019-06-07 Thread Mark Lumsden
This diff allows mg to log its internal status to a file. At the moment it 
only logs line information like front and back pointers in the linked 
list, how many characters are used and where the cursor is placed in the 
file, but I am finding it incredibly useful debugging mg at the moment.


Below is an example log file after opening a file with this contents:

abc
def
ghk

After I open the file in mg, I move forward a line (C-n), then move 
forward a character (C-f):


$ cat log/mg.log
next-line

3 3 0xc3a3557ae00 b^0xc3a592eac20 f.0xc3a592ea4a0 abc

 3 3 0xc3a592ea4a0 b^0xc3a3557ae00 f.0xc3a592ea660 def
 3 3 0xc3a592ea660 b^0xc3a592ea4a0 f.0xc3a307830e0 ghk
 0 0 0xc3a307830e0 b^0xc3a592ea660 f.0xc3a592eac20 (null)
 head 0xc3a592eac20 b^0xc3a307830e0 f.0xc3a3557ae00
(EOB)

forward-char
 3 3 0xc3a3557ae00 b^0xc3a592eac20 f.0xc3a592ea4a0 abc

3 3 0xc3a592ea4a0 b^0xc3a3557ae00 f.0xc3a592ea660 def

 3 3 0xc3a592ea660 b^0xc3a592ea4a0 f.0xc3a307830e0 ghk
 0 0 0xc3a307830e0 b^0xc3a592ea660 f.0xc3a592eac20 (null)
 head 0xc3a592eac20 b^0xc3a307830e0 f.0xc3a3557ae00
(EOB)

The three columns of pointer addresses are (from the 'def' line):

0xc3a592ea4a0 the lines own pointer.
0xc3a3557ae00 the pointer to back(b^) line
0xc3a592ea660 the pointer to forward(f.) line

The numbers at the start of the first four lines are l_size and l_used.

With this diff logging is not switched on by default and has to compiled 
into mg.  -DMGDEBUG has to be added to the Makefile:


CFLAGS+=-Wall -DREGEX  -DMGDEBUG

And the comment removed from:

#SRCS+=  log.c

The information logged at the moment is viewable by gdb, however, if a bug 
that I have introduced doesn't present itself for XX number of key 
presses, I can struggle to work out what has caused it in gdb, logging 
like this makes problems I have introduced much more obvious and easier 
to fix.


I have tried to make the ifdefs as minimal as possible. Any objections to 
this diff?


Mark

Index: Makefile
===
RCS file: /cvs/src/usr.bin/mg/Makefile,v
retrieving revision 1.33
diff -u -p -u -p -r1.33 Makefile
--- Makefile16 Sep 2016 17:17:40 -  1.33
+++ Makefile7 Jun 2019 14:42:39 -
@@ -9,6 +9,7 @@ DPADD+= ${LIBCURSES} ${LIBUTIL}
 #
 #  REGEX   -- create regular expression functions.
 #  STARTUPFILE -- look for and handle initialization file.
+#  MGDEBUG -- debug mg internals to a log file.
 #
 CFLAGS+=-Wall -DREGEX

@@ -22,6 +23,11 @@ SRCS=autoexec.c basic.c bell.c buffer.c
 # More or less standalone extensions.
 #
 SRCS+= cmode.c cscope.c dired.c grep.c tags.c
+
+#
+# -DMGDEBUG source file.
+#
+#SRCS+=log.c

 afterinstall:
${INSTALL} -d -o root -g wheel ${DESTDIR}${DOCDIR}/mg
Index: kbd.c
===
RCS file: /cvs/src/usr.bin/mg/kbd.c,v
retrieving revision 1.30
diff -u -p -u -p -r1.30 kbd.c
--- kbd.c   26 Sep 2015 21:51:58 -  1.30
+++ kbd.c   7 Jun 2019 14:42:39 -
@@ -15,6 +15,10 @@
 #include "key.h"
 #include "macro.h"

+#ifdef  MGDEBUG
+#include "log.h"
+#endif
+
 #define METABIT 0x80

 #define PROMPTL 80
@@ -151,6 +155,11 @@ doin(void)
while ((funct = doscan(curmap, (key.k_chars[key.k_count++] =
getkey(TRUE)), )) == NULL)
/* nothing */;
+
+#ifdef  MGDEBUG
+   if (!mglog(funct))
+   ewprintf("Problem with logging");
+#endif

if (macrodef && macrocount < MAXMACRO)
macro[macrocount++].m_funct = funct;
Index: log.c
===
RCS file: log.c
diff -N log.c
--- /dev/null   1 Jan 1970 00:00:00 -
+++ log.c   7 Jun 2019 14:42:39 -
@@ -0,0 +1,121 @@
+/* $OpenBSD$   */
+
+/* 
+ * This file is in the public domain.

+ *
+ * Author: Mark Lumsden 
+ *
+ */
+
+/*
+ * Record a history of an mg session for temporal debugging.
+ * Sometimes pressing a key will set the scene for a bug only visible 
+ * dozens of keystrokes later. gdb has its limitations in this scenario.

+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "def.h"
+#include "log.h"
+#include "funmap.h"
+
+static charmglogpath[20];
+
+int
+mglog(PF funct)
+{
+   struct line *lp;
+   struct stat  sb;
+   char*curline;
+   FILE*fd;
+   int  i;
+
+   i = 0;
+
+   if(stat(mglogpath, ))
+   return (FALSE);
+
+   fd = fopen(mglogpath, "a");
+   if (fprintf(fd, "%s\n", function_name(funct)) == -1) {
+   fclose(fd);
+   return (FALSE);
+   }
+   lp = bfirstlp(curbp);
+
+   for(;;) {
+   i++;
+   curline = " ";
+   if (i == curw

mg(1): {beginning,end}-of-buffer numeric argument

2019-05-31 Thread Mark Lumsden
This diff gives the commands beginning-of-buffer and end-of-buffer the 
ability to take a numeric argument and move n/10th of the way from the 
top or bottom of the current buffer respectively.


Any comments/testers/oks?

Mark

Index: basic.c
===
RCS file: /cvs/src/usr.bin/mg/basic.c,v
retrieving revision 1.47
diff -u -p -u -p -r1.47 basic.c
--- basic.c 10 Oct 2015 09:13:14 -  1.47
+++ basic.c 31 May 2019 11:16:58 -
@@ -21,6 +21,8 @@

 #include "def.h"

+#define percint(n1, n2)((n1 * (int) n2) * 0.1)
+
 /*
  * Go to beginning of line.
  */
@@ -127,6 +129,12 @@ gotobob(int f, int n)
curwp->w_doto = 0;
curwp->w_rflag |= WFFULL;
curwp->w_dotline = 1;
+   if (f & FFOTHARG && n > 0) {
+   if (n > 9)
+   gotoeob(0, 0);
+   else
+   forwline(f, percint(curwp->w_bufp->b_lines, n) - 1);
+   }
return (TRUE);
 }

@@ -138,6 +146,7 @@ gotobob(int f, int n)
 int
 gotoeob(int f, int n)
 {
+   int  ln;
struct line *lp;

(void) setmark(f, n);
@@ -146,15 +155,22 @@ gotoeob(int f, int n)
curwp->w_dotline = curwp->w_bufp->b_lines;

lp = curwp->w_dotp;
-   n = curwp->w_ntrows - 3;
+   ln = curwp->w_ntrows - 3;

-   if (n < curwp->w_bufp->b_lines && n >= 3) {
-   while (n--)
+   if (ln < curwp->w_bufp->b_lines && ln >= 3) {
+   while (ln--)
curwp->w_dotp = lback(curwp->w_dotp);

curwp->w_linep = curwp->w_dotp;
curwp->w_dotp = lp;
}
+   if (f & FFOTHARG && n > 1) {
+   if (n > 9)
+   gotobob(0, 0);
+   else
+   backline(f, percint(curwp->w_bufp->b_lines, n));
+   }
+
curwp->w_rflag |= WFFULL;
return (TRUE);
 }
Index: mg.1
===
RCS file: /cvs/src/usr.bin/mg/mg.1,v
retrieving revision 1.112
diff -u -p -u -p -r1.112 mg.1
--- mg.126 Dec 2018 07:01:22 -  1.112
+++ mg.131 May 2019 11:16:58 -
@@ -405,6 +405,9 @@ Paragraphs are delimited by  or
 Move cursor backwards by the specified number of words.
 .It beginning-of-buffer
 Move cursor to the top of the buffer.
+A numeric argument 
+.Va n ,

+will move n/10th of the way from the top.
 .It beginning-of-line
 Move cursor to the beginning of the line.
 .It blink-and-insert
@@ -526,6 +529,9 @@ version string.
 Stop defining a keyboard macro.
 .It end-of-buffer
 Move cursor to the end of the buffer.
+A numeric argument
+.Va n ,
+will move n/10th of the way from the end.
 .It end-of-line
 Move cursor to the end of the line.
 .It enlarge-window



Re: ssh-keygen: interactive comment change

2019-05-22 Thread Mark Lumsden

On Wed, 22 May 2019, Mark Lumsden wrote:


Date: Wed, 22 May 2019 18:49:23 + (UTC)
From: Mark Lumsden 
To: tech@openbsd.org
Subject: ssh-keygen: interactive comment change

I used the -C command line option of ssh-keygen to change the comment of a 
public key and got confused with the output. For example, if the original 
comment was 'mark@home', this is what would happen trying to amend the 
comment to 'mark@work' via -C:


$ ssh-keygen -f test_rsa -c -C mark@work
Key now has comment 'mark@home'
The comment in your key file has been changed.
$

The line "Key now has comment 'mark@home'" suggested to me that the comment 
had been changed to 'mark@home'. But thats not really a change. However, the 
comment had actually changed in the .pub file. It looks like the wording has 
been designed to work without the -C option and _only_ the -c option:


$  ssh-keygen -f test_rsa -c
Key now has comment 'mark@home'
Enter new comment: mark@work
The comment in your key file has been changed.
$

Everything becomes clear when you run the command interactively via -c only.

The diff below attempts to make the wording make sense which ever way you try 
to change a comment on a .pub file:


$ ssh-keygen -f test_rsa -c
Old comment: mark@home
New comment: mark@work
Comment 'mark@work' applied
$

$ ssh-keygen -f test_rsa -c -C mark@work
Old comment: mark@home
Comment 'mark@work' applied
$

It also compares the old and new comments and informs if there is no change:

$ ssh-keygen -f test_rsa -c -C mark@home
Old comment: mark@home
No change to comment
$

$ ssh-keygen -f test_rsa -c
Old comment: mark@work
New comment: mark@work
No change to comment
$

ok?

Mark



Here is a better diff.

It doesn't say that the public key has been written, until it has 
actually been written.


If there is no change detected in the old and new comments, it doesn't try 
and write anything, just cleans up and exits.


Index: ssh-keygen.c
===
RCS file: /cvs/src/usr.bin/ssh/ssh-keygen.c,v
retrieving revision 1.329
diff -u -p -u -p -r1.329 ssh-keygen.c
--- ssh-keygen.c25 Mar 2019 16:19:44 -  1.329
+++ ssh-keygen.c22 May 2019 19:40:49 -
@@ -1466,15 +1466,15 @@ do_change_comment(struct passwd *pw, con
sshkey_free(private);
exit(1);
}
-   if (comment)
-   printf("Key now has comment '%s'\n", comment);
+   if (strlen(comment) > 0)
+   printf("Old comment: %s\n", comment);
else
-   printf("Key now has no comment\n");
+   printf("No existing comment\n");

if (identity_comment) {
strlcpy(new_comment, identity_comment, sizeof(new_comment));
} else {
-   printf("Enter new comment: ");
+   printf("New comment: ");
fflush(stdout);
if (!fgets(new_comment, sizeof(new_comment), stdin)) {
explicit_bzero(passphrase, strlen(passphrase));
@@ -1483,6 +1483,13 @@ do_change_comment(struct passwd *pw, con
}
new_comment[strcspn(new_comment, "\n")] = '\0';
}
+   if (strcmp(comment, new_comment) == 0) {
+   printf("No change to comment\n");
+   free(passphrase);
+   sshkey_free(private);
+   free(comment);
+   exit(0);
+   }

/* Save the file using the new passphrase. */
if ((r = sshkey_save_private(private, identity_file, passphrase,
@@ -1514,9 +1521,13 @@ do_change_comment(struct passwd *pw, con
fprintf(f, " %s\n", new_comment);
fclose(f);

+   if (strlen(new_comment) > 0)
+   printf("Comment '%s' applied\n", new_comment);
+   else
+   printf("Comment removed\n");
+
free(comment);

-   printf("The comment in your key file has been changed.\n");
exit(0);
 }



ssh-keygen: interactive comment change

2019-05-22 Thread Mark Lumsden
I used the -C command line option of ssh-keygen to change the comment 
of a public key and got confused with the output. For example, if the 
original comment was 'mark@home', this is what would happen trying to 
amend the comment to 'mark@work' via -C:


$ ssh-keygen -f test_rsa -c -C mark@work
Key now has comment 'mark@home'
The comment in your key file has been changed.
$

The line "Key now has comment 'mark@home'" suggested to me that the 
comment had been changed to 'mark@home'. But thats not really a change. 
However, the comment had actually changed in the .pub file. It looks like 
the wording has been designed to work without the -C option and _only_ the 
-c option:


$  ssh-keygen -f test_rsa -c
Key now has comment 'mark@home'
Enter new comment: mark@work
The comment in your key file has been changed.
$

Everything becomes clear when you run the command interactively via -c 
only.


The diff below attempts to make the wording make sense which ever way you 
try to change a comment on a .pub file:


$ ssh-keygen -f test_rsa -c
Old comment: mark@home
New comment: mark@work
Comment 'mark@work' applied
$

$ ssh-keygen -f test_rsa -c -C mark@work
Old comment: mark@home
Comment 'mark@work' applied
$

It also compares the old and new comments and informs if there is no 
change:


$ ssh-keygen -f test_rsa -c -C mark@home
Old comment: mark@home
No change to comment
$

$ ssh-keygen -f test_rsa -c
Old comment: mark@work
New comment: mark@work
No change to comment
$

ok?

Mark

Index: ssh-keygen.c
===
RCS file: /cvs/src/usr.bin/ssh/ssh-keygen.c,v
retrieving revision 1.329
diff -u -p -u -p -r1.329 ssh-keygen.c
--- ssh-keygen.c25 Mar 2019 16:19:44 -  1.329
+++ ssh-keygen.c22 May 2019 18:21:42 -
@@ -1466,15 +1466,15 @@ do_change_comment(struct passwd *pw, con
sshkey_free(private);
exit(1);
}
-   if (comment)
-   printf("Key now has comment '%s'\n", comment);
+   if (strlen(comment) > 0)
+   printf("Old comment: %s\n", comment);
else
-   printf("Key now has no comment\n");
+   printf("No existing comment\n");

if (identity_comment) {
strlcpy(new_comment, identity_comment, sizeof(new_comment));
} else {
-   printf("Enter new comment: ");
+   printf("New comment: ");
fflush(stdout);
if (!fgets(new_comment, sizeof(new_comment), stdin)) {
explicit_bzero(passphrase, strlen(passphrase));
@@ -1483,6 +1483,12 @@ do_change_comment(struct passwd *pw, con
}
new_comment[strcspn(new_comment, "\n")] = '\0';
}
+   if (strcmp(comment, new_comment) == 0)
+   printf("No change to comment\n");
+   else if (strlen(new_comment) > 0)
+   printf("Comment '%s' applied\n", new_comment);
+   else
+   printf("Comment removed\n");

/* Save the file using the new passphrase. */
if ((r = sshkey_save_private(private, identity_file, passphrase,
@@ -1516,7 +1522,6 @@ do_change_comment(struct passwd *pw, con

free(comment);

-   printf("The comment in your key file has been changed.\n");
exit(0);
 }



Re: mg: Delete region

2018-12-23 Thread Mark Lumsden

On Sun, 23 Dec 2018, Hiltjo Posthuma wrote:


Date: Sun, 23 Dec 2018 13:43:32 +0100
From: Hiltjo Posthuma 
To: Mark Lumsden 
Cc: Leonid Bobrov , tech@openbsd.org
Subject: Re: mg: Delete region

On Thu, Dec 20, 2018 at 06:44:15AM +, Mark Lumsden wrote:

hmm, you are correct. I'm trying to remember which machine I tested
on that made me come to that conclusion.

On Thu, 20 Dec 2018, Leonid Bobrov wrote:


Date: Thu, 20 Dec 2018 06:43:02 +0200
From: Leonid Bobrov 
To: Mark Lumsden , tech@openbsd.org
Subject: Re: mg: Delete region

I tried this in GNU Emacs and it didn't place the killed region into the
kill buffer. It only places it into the kill buffer if you pressed C-w





Hi,

Can this change get reverted upstream until it is properly tested (and OK'd),
please?

--
Kind regards,
Hiltjo



Its should be trivial to make it behave as emacs does. I should get time 
in about a week to have a look. Personally I don't think it needs reverted
since it is more useful having it behave as it does just now than 
previously. But if someone wants to do so they are free to do that.




Re: mg: Delete region

2018-12-19 Thread Mark Lumsden

hmm, you are correct. I'm trying to remember which machine I tested
on that made me come to that conclusion.

On Thu, 20 Dec 2018, Leonid Bobrov wrote:


Date: Thu, 20 Dec 2018 06:43:02 +0200
From: Leonid Bobrov 
To: Mark Lumsden , tech@openbsd.org
Subject: Re: mg: Delete region

I tried this in GNU Emacs and it didn't place the killed region into the
kill buffer. It only places it into the kill buffer if you pressed C-w





mg: Delete region

2018-12-17 Thread Mark Lumsden

Currently in mg, if the cursor is in a region and the 'delete' or
'backspace' keys are pressed mg will not behave any differently than
if the cursor wasn't in a region. The diff below makes mg behave
like emacs and kills the region and places it into the kill buffer.

ok?

Mark

Index: mg.1
===
RCS file: /cvs/src/usr.bin/mg/mg.1,v
retrieving revision 1.109
diff -u -p -u -p -r1.109 mg.1
--- mg.113 Dec 2018 14:59:16 -  1.109
+++ mg.117 Dec 2018 16:34:41 -
@@ -475,6 +475,8 @@ Delete backwards
 characters.
 Like delete-char, this actually does a kill if presented
 with an argument.
+If the cursor is in a region, the region is removed and placed
+in to the kill buffer.
 .It delete-blank-lines
 Delete blank lines around dot.
 If dot is sitting on a blank line, this command
@@ -486,6 +488,8 @@ Delete
 characters forward.
 If any argument is present, it kills rather than deletes,
 saving the result in the kill buffer.
+If the cursor is in a region, the region is removed and placed
+in to the kill buffer.
 .It delete-horizontal-space
 Delete any whitespace around the dot.
 .It delete-leading-space
Index: util.c
===
RCS file: /cvs/src/usr.bin/mg/util.c,v
retrieving revision 1.38
diff -u -p -u -p -r1.38 util.c
--- util.c  18 Nov 2015 18:21:06 -  1.38
+++ util.c  17 Dec 2018 16:34:41 -
@@ -411,7 +411,8 @@ indent(int f, int n)
  * Delete forward.  This is real easy, because the basic delete routine does
  * all of the work.  Watches for negative arguments, and does the right thing.
  * If any argument is present, it kills rather than deletes, to prevent loss
- * of text if typed with a big argument.  Normally bound to "C-D".
+ * of text if typed with a big argument.  Normally bound to "C-d".
+ * If the cursor is in a region, kill the region.
  */
 /* ARGSUSED */
 int
@@ -420,6 +421,9 @@ forwdel(int f, int n)
if (n < 0)
return (backdel(f | FFRAND, -n));

+   if (curwp->w_markp != NULL)
+   return(killregion(FFRAND, 1));
+
/* really a kill */
if (f & FFARG) {
if ((lastflag & CFKILL) == 0)
@@ -434,6 +438,7 @@ forwdel(int f, int n)
  * Delete backwards.  This is quite easy too, because it's all done with
  * other functions.  Just move the cursor back, and delete forwards.  Like
  * delete forward, this actually does a kill if presented with an argument.
+ * If the cursor is in a region, kill the region.
  */
 /* ARGSUSED */
 int
@@ -443,6 +448,9 @@ backdel(int f, int n)

if (n < 0)
return (forwdel(f | FFRAND, -n));
+
+   if (curwp->w_markp != NULL)
+   return (killregion(FFRAND, 1));

/* really a kill */
if (f & FFARG) {



mg: toggle-read-only-all

2018-11-27 Thread Mark Lumsden

Allow all non-ephemeral buffers to be toggled write/read-only. This
toggle works while mg is running, unlike the -R option which is only
during mg startup.

ok?

Index: buffer.c
===
RCS file: /cvs/src/usr.bin/mg/buffer.c,v
retrieving revision 1.104
diff -u -p -u -p -r1.104 buffer.c
--- buffer.c6 Aug 2017 04:39:45 -   1.104
+++ buffer.c27 Nov 2018 19:52:41 -
@@ -31,6 +31,28 @@ extern int globalwd;

 /* ARGSUSED */
 int
+togglereadonlyall(int f, int n)
+{
+   struct buffer *bp = NULL;
+   int len = 0;
+
+   allbro = !allbro;
+   for (bp = bheadp; bp != NULL; bp = bp->b_bufp) {
+   len = strlen(bp->b_bname);
+   if (bp->b_bname[0] != '*' && bp->b_bname[len - 1] != '*') {
+   if (allbro)
+   bp->b_flag |= BFREADONLY;
+   else
+   bp->b_flag &= ~BFREADONLY;
+   }
+   }
+   curwp->w_rflag |= WFMODE;
+
+   return (TRUE);
+}
+
+/* ARGSUSED */
+int
 togglereadonly(int f, int n)
 {
int s;
Index: def.h
===
RCS file: /cvs/src/usr.bin/mg/def.h,v
retrieving revision 1.156
diff -u -p -u -p -r1.156 def.h
--- def.h   29 Aug 2018 07:50:16 -  1.156
+++ def.h   27 Nov 2018 19:52:41 -
@@ -417,6 +417,7 @@ int  delwind(int, int);

 /* buffer.c */
 int togglereadonly(int, int);
+int togglereadonlyall(int, int);
 struct buffer   *bfind(const char *, int);
 int poptobuffer(int, int);
 int killbuffer(struct buffer *);
@@ -737,6 +738,7 @@ extern int   defb_flag;
 extern int  doaudiblebell;
 extern int  dovisiblebell;
 extern int  dblspace;
+extern int  allbro;
 extern char cinfo[];
 extern char*keystrings[];
 extern char pat[NPAT];
Index: funmap.c
===
RCS file: /cvs/src/usr.bin/mg/funmap.c,v
retrieving revision 1.54
diff -u -p -u -p -r1.54 funmap.c
--- funmap.c29 Aug 2018 07:50:16 -  1.54
+++ funmap.c27 Nov 2018 19:52:41 -
@@ -201,6 +201,7 @@ static struct funmap functnames[] = {
{usebuffer, "switch-to-buffer",},
{poptobuffer, "switch-to-buffer-other-window",},
{togglereadonly, "toggle-read-only" },
+   {togglereadonlyall, "toggle-read-only-all" },
{twiddle, "transpose-chars",},
{transposepara, "transpose-paragraphs",},
{transposeword, "transpose-words",},
Index: main.c
===
RCS file: /cvs/src/usr.bin/mg/main.c,v
retrieving revision 1.84
diff -u -p -u -p -r1.84 main.c
--- main.c  16 Sep 2016 17:17:40 -  1.84
+++ main.c  27 Nov 2018 19:52:41 -
@@ -28,6 +28,7 @@ intstartrow;  /* row to start 
*/
 int doaudiblebell; /* audible bell toggle  */
 int dovisiblebell; /* visible bell toggle  */
 int dblspace;  /* sentence end #spaces */
+int allbro;/* all buffs read-only  */
 struct buffer  *curbp; /* current buffer   */
 struct buffer  *bheadp;/* BUFFER list head */
 struct mgwin   *curwp; /* current window   */
@@ -65,6 +66,7 @@ main(int argc, char **argv)
switch (o) {
case 'R':
bro = 1;
+   allbro = 1;
break;
case 'n':
nobackups = 1;
Index: mg.1
===
RCS file: /cvs/src/usr.bin/mg/mg.1,v
retrieving revision 1.108
diff -u -p -u -p -r1.108 mg.1
--- mg.118 Nov 2018 07:57:28 -  1.108
+++ mg.127 Nov 2018 19:52:41 -
@@ -884,6 +884,10 @@ Prompt and switch to a new buffer in the
 Switch to buffer in another window.
 .It toggle-read-only
 Toggle the read-only flag on the current buffer.
+.It toggle-read-only-all
+Toggle the read-only flag on all non-ephemeral buffers.
+A simple toggle that switches a global read-only flag either on
+or off.
 .It transpose-chars
 Transpose the two characters in front of and under dot,
 then move forward one character.



mg and \n char

2018-11-15 Thread Mark Lumsden

Hi,

I'm trying to work out a way of progressing mg to be 8 bit clean.  Not
being 100% sure of the scope of the problem and solution, attached is
a diff that is trying to remove the implied or faked '\n' character
from mg's buffers.

I'm taking the approach of loading the '\n' char from disk to buffer,
instead of removing it at buffer load time (when opening a file) as mg
does at the moment. This diff only fixes 20% of the ramifications of
doing that, so if you apply the diff mg will be very buggy afterwards,
but this diff is only trying to discuss the approach of going 8 bit
clean and how to acheive that. If removing the implied '\n' character
this way is deemed suitable then I can carry on cleaning up the other
80% so that the main functionality of mg is not affected with not
having an implied \n or a faked \n but having a 'real' \n on a
new-line in a buffer.

One of the changes in having a \n at the end of a line is how mg works
with the length of a line. Some functions need to know the new length
(+1 char) but some others don't. For example, if you C-e to the end of
a line, currently mg leaves the cursor where a \n should be and says
the cursor is on X column. If you then M-x what-cursor-position, mg
fakes a \n character and tells you a \n is under the cursor.
With the attached diff, if you C-e to the end of a line, the function
called via C-e (gotoeol), puts the cursor on the length of the
displayed line, which is 1 less than the 'real' length of the line,
which now includes a \n char.  If you then M-x what-cursor-position,
mg will report the cursor is on a \n character because it _is_ on a \n
character.

I've introduced a new version of llength():

#define llength(lp)((lp)->l_used)  /* real line length */
#define dis_llength(lp)(llength(lp) - 1)   /* displayed line 
length */


However, is this approach the right way to progress 8 bit cleaness? I am
no sure, please feel free to express your opinion. Also, is anyone 
else working on this?


Mark

Index: basic.c
===
RCS file: /cvs/src/usr.bin/mg/basic.c,v
retrieving revision 1.47
diff -u -p -r1.47 basic.c
--- basic.c 10 Oct 2015 09:13:14 -  1.47
+++ basic.c 15 Nov 2018 08:00:03 -
@@ -59,7 +59,7 @@ backchar(int f, int n)
return (FALSE);
}
curwp->w_dotp = lp;
-   curwp->w_doto = llength(lp);
+   curwp->w_doto = dis_llength(lp);
curwp->w_rflag |= WFMOVE;
curwp->w_dotline--;
} else
@@ -78,7 +78,8 @@ gotoeol(int f, int n)
if (n == 0)
return (TRUE);

-   curwp->w_doto = llength(curwp->w_dotp);
+   /* need to check if line is end of buffer and no '\n'*/
+   curwp->w_doto = dis_llength(curwp->w_dotp);
return (TRUE);
 }

@@ -95,7 +96,7 @@ forwchar(int f, int n)
if (n < 0)
return (backchar(f, -n));
while (n--) {
-   if (curwp->w_doto == llength(curwp->w_dotp)) {
+   if (curwp->w_doto == dis_llength(curwp->w_dotp)) {
curwp->w_dotp = lforw(curwp->w_dotp);
if (curwp->w_dotp == curbp->b_headp) {
curwp->w_dotp = lback(curwp->w_dotp);
@@ -142,7 +143,7 @@ gotoeob(int f, int n)

(void) setmark(f, n);
curwp->w_dotp = blastlp(curbp);
-   curwp->w_doto = llength(curwp->w_dotp);
+   curwp->w_doto = llength(curwp->w_dotp);/* check no '\n'!! */
curwp->w_dotline = curwp->w_bufp->b_lines;

lp = curwp->w_dotp;
@@ -190,7 +191,8 @@ forwline(int f, int n)
dlp = lforw(dlp);
if (dlp == curbp->b_headp) {
curwp->w_dotp = lback(dlp);
-   curwp->w_doto = llength(curwp->w_dotp);
+   /*check if end of buffer and no '\n'*/
+   curwp->w_doto = dis_llength(curwp->w_dotp);
curwp->w_rflag |= WFMOVE;
if (!(f & FFRAND)) {
dobeep();
@@ -275,7 +277,9 @@ getgoal(struct line *dlp)

for (i = 0; i < llength(dlp); i++) {
c = lgetc(dlp, i);
-   if (c == '\t'
+   if (c == '\n')
+   ; /* check working */
+   else if (c == '\t'
 #ifdef NOTAB
&& !(curbp->b_flag & BFNOTAB)
 #endif
Index: def.h
===
RCS file: /cvs/src/usr.bin/mg/def.h,v
retrieving revision 1.156
diff -u -p -r1.156 def.h
--- def.h   29 Aug 2018 07:50:16 -  1.156
+++ def.h   15 Nov 2018 08:00:03 -
@@ -150,7 +150,8 @@ struct line {
 #define lback(lp)  ((lp)->l_bp)
 #define lgetc(lp, n)   (CHARMASK((lp)->l_text[(n)]))
 #define lputc(lp, n, c) ((lp)->l_text[(n)]=(c))

mg: fix undo transpose-paragraph

2018-11-13 Thread Mark Lumsden



Currently undoing transpose-paragraph doesn't work as expected.
This diff fixes that.

ok?

Index: paragraph.c
===
RCS file: /cvs/src/usr.bin/mg/paragraph.c,v
retrieving revision 1.45
diff -u -p -r1.45 paragraph.c
--- paragraph.c 6 Sep 2016 16:25:47 -   1.45
+++ paragraph.c 13 Nov 2018 21:20:48 -
@@ -338,6 +338,8 @@ transposepara(int f, int n)
if (n == 0)
return (TRUE);

+   undo_boundary_enable(FFRAND, 0);
+
/* find a paragraph, set mark, then goto the end */
gotobop(FFRAND, 1);
curwp->w_markp = curwp->w_dotp;
@@ -364,6 +366,8 @@ transposepara(int f, int n)
return (FALSE);
}
(void)yank(FFRAND, 1);
+
+   undo_boundary_enable(FFRAND, 1);

return (TRUE);
 }



Re: mg docs ownership

2016-09-11 Thread Mark Lumsden
> Maybe we should just not install it? Mark?

A couple of years ago when the tutorial started being installed there
were no dissenting voices, so unless there are objections, I'd carry
on doing that. And Martin's diff makes sense I think. 

Mark 



mg: region.c:preadin() - Also check for read() error

2016-09-08 Thread Mark Lumsden
Source Joachim Nilsson:

 Coverity Scan found this interesting buglet.  If read() fails the code,
 before this patch, would trigger a "Negative array index write".

ok?

Index: region.c
===
RCS file: /cvs/src/usr.bin/mg/region.c,v
retrieving revision 1.36
diff -u -p -u -p -r1.36 region.c
--- region.c8 Sep 2016 07:50:09 -   1.36
+++ region.c8 Sep 2016 07:56:14 -
@@ -650,7 +650,7 @@ preadin(int fd, struct buffer *bp)
int len;
char buf[BUFSIZ], *p, *q;
 
-   if ((len = read(fd, buf, BUFSIZ - 1)) == 0)
+   if ((len = read(fd, buf, BUFSIZ - 1)) <= 0)
return (FALSE);
 
buf[len] = '\0';



mg - Check pointer before calling showbuffer()

2016-09-06 Thread Mark Lumsden
Source Joachim Nilsson:

Found by Coverity Scan.  The popbuf() function iterated over a list to
find a wp pointer, then sent it to showbuffer() which immediately went
ahead and dereferenced it.  This patch simply adds a NULL pointer check
before calling showbuffer(), if NULL then just return NULL to callee.

The missing NULL check is actually referenced in a comment a few lines
earlier in the code. ok?

-lum

Index: buffer.c
===
RCS file: /cvs/src/usr.bin/mg/buffer.c,v
retrieving revision 1.101
diff -u -p -u -p -r1.101 buffer.c
--- buffer.c31 Aug 2016 12:22:28 -  1.101
+++ buffer.c6 Sep 2016 17:04:22 -
@@ -713,12 +713,16 @@ popbuf(struct buffer *bp, int flags)
 
while (wp != NULL && wp == curwp)
wp = wp->w_wndp;
-   } else
+   } else {
for (wp = wheadp; wp != NULL; wp = wp->w_wndp)
if (wp->w_bufp == bp) {
wp->w_rflag |= WFFULL | WFFRAME;
return (wp);
}
+   }
+   if (!wp)
+   return (NULL);
+
if (showbuffer(bp, wp, WFFULL) != TRUE)
return (NULL);
return (wp);



mg: goto end of para @ end of buffer problem

2016-09-05 Thread Mark Lumsden
Currently in mg, if you have a paragraph:

123
456

With the cursor on either the 4, 5 or 6 and no newline after the '6',
and then execute forward-paragraph (M-}), the cursor sits still and
does not move to the end of second line (after the 6), which is in
effect the end of parapraph. This diff fixes that behaviour. ok?

-lum

Index: paragraph.c
===
RCS file: /cvs/src/usr.bin/mg/paragraph.c,v
retrieving revision 1.44
diff -u -p -u -p -r1.44 paragraph.c
--- paragraph.c 14 Apr 2016 17:05:32 -  1.44
+++ paragraph.c 5 Sep 2016 14:34:45 -
@@ -108,13 +108,13 @@ do_gotoeop(int f, int n, int *i)
curwp->w_dotp = lforw(curwp->w_dotp);
curwp->w_dotline++;
 
-   /* do not continue after end of buffer */
-   if (lforw(curwp->w_dotp) == curbp->b_headp) {
-   gotoeol(FFRAND, 1);
-   curwp->w_rflag |= WFMOVE;
-   return (FALSE);
-   }
}
+   }
+   /* do not continue after end of buffer */
+   if (lforw(curwp->w_dotp) == curbp->b_headp) {
+   gotoeol(FFRAND, 1);
+   curwp->w_rflag |= WFMOVE;
+   return (FALSE);
}
 
/* force screen update */



mg(1) Initialize stack variables to zero before memmove()

2016-09-02 Thread Mark Lumsden
Source Joachim Nilsson:

Coverity Scan reported these two stack variables as uninitialized, in
particular the .r_lineno struct member was uninitialized.  This patch
clears the 'struct region' rather than setting .r_lineno because if
any more struct members are added in the future the clear will cover
them too.

I think Joachim's approach is sensible. ok?

-lum

Index: undo.c
===
RCS file: /cvs/src/usr.bin/mg/undo.c,v
retrieving revision 1.57
diff -u -p -u -p -r1.57 undo.c
--- undo.c  11 Dec 2015 20:21:23 -  1.57
+++ undo.c  2 Sep 2016 07:02:18 -
@@ -269,6 +269,8 @@ undo_add_insert(struct line *lp, int off
 
if (!undo_enable_flag)
return (TRUE);
+
+   memset(, 0, sizeof(reg));
reg.r_linep = lp;
reg.r_offset = offset;
reg.r_size = size;
@@ -315,6 +317,7 @@ undo_add_delete(struct line *lp, int off
if (!undo_enable_flag)
return (TRUE);
 
+   memset(, 0, sizeof(reg));
reg.r_linep = lp;
reg.r_offset = offset;
reg.r_size = size;



Re: mg - sentence-end-double-space

2016-04-12 Thread Mark Lumsden
Hi Ingo,

On Tue, Apr 12, 2016 at 08:39:07PM +0200, Ingo Schwarze wrote:
> Hi Mark,
> 
> Mark Lumsden wrote on Tue, Apr 12, 2016 at 06:47:40PM +:
> 
> > This diff allows a single space for sentence delimitation. 
> > ok/comments/objections?
> 
> No objection, but a comment.  Note that *using* the option is
> destructive.  Once you have replaced double spaces at the ends
> of sentences with single spaces, there is no algorithm short of
> computer linguistics that can take you back, because with that
> change, abbreviations become indistinguishable from full stops.
> 

You are correct though there is "undo".

> You might or might not want to mention that in the manual -
> depending on whether you consider it more important to prevent
> people from hurting themselves or to keep the manual concise.
>

I think conciseness is more important here.

Thanks for the comments.

mark



mg - sentence-end-double-space

2016-04-12 Thread Mark Lumsden
This diff allows a single space for sentence delimitation. 
ok/comments/objections? The default of a double space is left as is.

mark

Index: def.h
===
RCS file: /cvs/src/usr.bin/mg/def.h,v
retrieving revision 1.154
diff -u -p -u -p -r1.154 def.h
--- def.h   2 Jan 2016 10:39:19 -   1.154
+++ def.h   12 Apr 2016 18:01:57 -
@@ -593,6 +593,7 @@ int  fillword(int, int);
 int setfillcol(int, int);
 int markpara(int, int);
 int transposepara(int, int);
+int sentencespace(int, int);
 
 /* word.c X */
 int backword(int, int);
@@ -734,6 +735,7 @@ extern int   defb_nmodes;
 extern int  defb_flag;
 extern int  doaudiblebell;
 extern int  dovisiblebell;
+extern int  dblspace;
 extern char cinfo[];
 extern char*keystrings[];
 extern char pat[NPAT];
Index: funmap.c
===
RCS file: /cvs/src/usr.bin/mg/funmap.c,v
retrieving revision 1.52
diff -u -p -u -p -r1.52 funmap.c
--- funmap.c29 Dec 2015 19:44:32 -  1.52
+++ funmap.c12 Apr 2016 18:01:57 -
@@ -180,6 +180,7 @@ static struct funmap functnames[] = {
{backsearch, "search-backward",},
{forwsearch, "search-forward",},
{selfinsert, "self-insert-command",},
+   {sentencespace, "sentence-end-double-space",},
 #ifdef REGEX
{setcasefold, "set-case-fold-search",},
 #endif /* REGEX */
Index: main.c
===
RCS file: /cvs/src/usr.bin/mg/main.c,v
retrieving revision 1.81
diff -u -p -u -p -r1.81 main.c
--- main.c  24 Dec 2015 09:07:47 -  1.81
+++ main.c  12 Apr 2016 18:01:57 -
@@ -27,6 +27,7 @@ intcurgoal;   /* goal column  
*/
 int startrow;  /* row to start */
 int doaudiblebell; /* audible bell toggle  */
 int dovisiblebell; /* visible bell toggle  */
+int dblspace;  /* sentence end #spaces */
 struct buffer  *curbp; /* current buffer   */
 struct buffer  *bheadp;/* BUFFER list head */
 struct mgwin   *curwp; /* current window   */
@@ -109,6 +110,7 @@ main(int argc, char **argv)
edinit(bp); /* Buffers, windows.*/
ttykeymapinit();/* Symbols, bindings.   */
bellinit(); /* Audible and visible bell.*/
+   dblspace = 1;   /* two spaces for sentence end. */
 
/*
 * doing update() before reading files causes the error messages from
Index: mg.1
===
RCS file: /cvs/src/usr.bin/mg/mg.1,v
retrieving revision 1.103
diff -u -p -u -p -r1.103 mg.1
--- mg.117 Mar 2016 21:56:12 -  1.103
+++ mg.112 Apr 2016 18:01:58 -
@@ -838,6 +838,10 @@ If found, dot gets moved to just after t
 characters, if not found, print a message.
 .It self-insert-command
 Insert a character.
+.It sentence-end-double-space
+Toggle double or single spaces for end of sentences.
+Double is the default.
+Currently only affects fill-paragraph.
 .It set-case-fold-search
 Set case-fold searching, causing case not to matter
 in regular expression searches.
Index: paragraph.c
===
RCS file: /cvs/src/usr.bin/mg/paragraph.c,v
retrieving revision 1.43
diff -u -p -u -p -r1.43 paragraph.c
--- paragraph.c 12 Apr 2016 06:20:50 -  1.43
+++ paragraph.c 12 Apr 2016 18:01:58 -
@@ -208,12 +208,12 @@ fillpara(int f, int n)
 * behave the same way if a ')' is preceded by a
 * [.?!] and followed by a doublespace.
 */
-   if (!eopflag && ((eolflag ||
+   if (dblspace && (!eopflag && ((eolflag ||
curwp->w_doto == llength(curwp->w_dotp) ||
(c = lgetc(curwp->w_dotp, curwp->w_doto)) == ' '
|| c == '\t') && (ISEOSP(wbuf[wordlen - 1]) ||
(wbuf[wordlen - 1] == ')' && wordlen >= 2 &&
-   ISEOSP(wbuf[wordlen - 2]))) &&
+   ISEOSP(wbuf[wordlen - 2] &&
wordlen < MAXWORD - 1))
wbuf[wordlen++] = ' ';
 
@@ -480,5 +480,16 @@ setfillcol(int f, int n)
fillcol = nfill;
ewprintf("Fill column set to %d", fillcol);
}
+   return (TRUE);
+}
+
+int
+sentencespace(int f, int n)
+{
+   if (f & FFARG)
+   dblspace = n > 1;
+   else

Bug#812810: fill-paragraph: Leaves a space at the end of the paragraph

2016-04-10 Thread Mark Lumsden
This diff changes mg's behaviour to not put a space at the end of a
paragraph when using the fill-paragraph function as reported by Harald
Dunkel. ok/comments? 

 
Index: paragraph.c
===
RCS file: /cvs/src/usr.bin/mg/paragraph.c,v
retrieving revision 1.42
diff -u -p -u -p -r1.42 paragraph.c
--- paragraph.c 14 Dec 2015 03:25:59 -  1.42
+++ paragraph.c 3 Apr 2016 19:45:19 -
@@ -208,13 +208,13 @@ fillpara(int f, int n)
 * behave the same way if a ')' is preceded by a
 * [.?!] and followed by a doublespace.
 */
-   if ((eolflag ||
+   if (!eopflag && ((eolflag ||
curwp->w_doto == llength(curwp->w_dotp) ||
(c = lgetc(curwp->w_dotp, curwp->w_doto)) == ' '
|| c == '\t') && (ISEOSP(wbuf[wordlen - 1]) ||
(wbuf[wordlen - 1] == ')' && wordlen >= 2 &&
ISEOSP(wbuf[wordlen - 2]))) &&
-   wordlen < MAXWORD - 1)
+   wordlen < MAXWORD - 1))
wbuf[wordlen++] = ' ';
 
/* at a word break with a word waiting */



mg(1) dired-find-alternate-file

2015-12-30 Thread Mark Lumsden
By shuffling find-alternate-file around we have
dired-find-alternate-file as well. ok?

-lum

Index: def.h
===
RCS file: /cvs/src/usr.bin/mg/def.h,v
retrieving revision 1.153
diff -u -p -u -p -r1.153 def.h
--- def.h   29 Dec 2015 19:44:32 -  1.153
+++ def.h   30 Dec 2015 13:20:35 -
@@ -377,6 +377,7 @@ int  makebkfile(int, int);
 int writeout(FILE **, struct buffer *, char *);
 voidupmodes(struct buffer *);
 size_t  xbasename(char *, const char *, size_t);
+int do_filevisitalt(char *);
 
 /* line.c X */
 struct line*lalloc(int);
Index: dired.c
===
RCS file: /cvs/src/usr.bin/mg/dired.c,v
retrieving revision 1.81
diff -u -p -u -p -r1.81 dired.c
--- dired.c 11 Dec 2015 20:21:23 -  1.81
+++ dired.c 30 Dec 2015 13:20:35 -
@@ -51,6 +51,7 @@ static int d_forwline(int, int);
 static int  d_backline(int, int);
 static int  d_killbuffer_cmd(int, int);
 static int  d_refreshbuffer(int, int);
+static int  d_filevisitalt(int, int);
 static void reaper(int);
 static struct buffer   *refreshbuffer(struct buffer *);
 static int  createlist(struct buffer *);
@@ -120,7 +121,9 @@ static PF diredcz[] = {
d_create_directory  /* + */
 };
 
-static PF diredc[] = {
+static PF direda[] = {
+   d_filevisitalt, /* a */
+   rescan, /* b */
d_copy, /* c */
d_del,  /* d */
d_findfile, /* e */
@@ -184,7 +187,7 @@ static struct KEYMAPE (7) diredmap = {
CCHR('Z'), '+', diredcz, (KEYMAP *) & metamap
},
{
-   'c', 'g', diredc, NULL
+   'a', 'g', direda, NULL
},
{
'n', 'x', diredn, NULL
@@ -838,6 +841,17 @@ d_backline (int f, int n)
 {
backline(f | FFRAND, n);
return (d_warpdot(curwp->w_dotp, >w_doto));
+}
+
+int
+d_filevisitalt (int f, int n)
+{
+   char fname[NFILEN];
+
+   if (d_makename(curwp->w_dotp, fname, sizeof(fname)) == ABORT)
+   return (FALSE);
+
+   return(do_filevisitalt(fname));
 }
 
 /*
Index: file.c
===
RCS file: /cvs/src/usr.bin/mg/file.c,v
retrieving revision 1.99
diff -u -p -u -p -r1.99 file.c
--- file.c  29 Oct 2015 19:46:47 -  1.99
+++ file.c  30 Dec 2015 13:20:35 -
@@ -94,9 +94,7 @@ filevisit(int f, int n)
 int
 filevisitalt(int f, int n)
 {
-   struct buffer   *bp;
-   char fname[NFILEN], *bufp, *adjf;
-   int  status;
+   char fname[NFILEN], *bufp, *fn;
 
if (getbufcwd(fname, sizeof(fname)) != TRUE)
fname[0] = '\0';
@@ -107,11 +105,23 @@ filevisitalt(int f, int n)
else if (bufp[0] == '\0')
return (FALSE);
 
+   fn = fname;
+
+   return (do_filevisitalt(fn));
+}
+
+int
+do_filevisitalt(char *fn)
+{
+   struct buffer   *bp;
+   int  status;
+   char*adjf;
+
status = killbuffer(curbp);
if (status == ABORT || status == FALSE)
return (ABORT);
 
-   adjf = adjustname(fname, TRUE);
+   adjf = adjustname(fn, TRUE);
if (adjf == NULL)
return (FALSE);
if (fisdir(adjf) == TRUE)
Index: mg.1
===
RCS file: /cvs/src/usr.bin/mg/mg.1,v
retrieving revision 1.99
diff -u -p -u -p -r1.99 mg.1
--- mg.129 Dec 2015 19:44:32 -  1.99
+++ mg.130 Dec 2015 13:20:35 -
@@ -952,6 +952,8 @@ dired-next-line
 dired-shell-command
 .It +
 dired-create-directory
+.It a
+dired-find-alternate-file
 .It c
 dired-do-copy
 .It d and C-d
@@ -988,6 +990,9 @@ Copy the file listed on the current line
 Delete the files that have been flagged for deletion.
 .It dired-do-rename
 Rename the file listed on the current line of the dired buffer.
+.It dired-find-alternate-file
+Replace the current dired buffer with an alternate one as specified
+by the position of the cursor.
 .It dired-find-file
 Open the file on the current line of the dired buffer.
 If the cursor is on a directory it will be opened in dired mode.



mg(1) tranpose-words

2015-12-24 Thread Mark Lumsden
This diff adds transpose-words to mg. It behaves slightly differently
from emacs when it comes to muliple iterations. Take this text for 
example:

abc def ghi
jkl mno pqr

If the cursor is on the 'd', then you do C-u 3 M-t, in emacs the
result will be:

abc ghi
jkl mno def pqr

The attached diff gives this result in mg:

abc ghi jkl
mno def pqr

Which personally I think is better. Also in emacs if you have this
situation:

123 456 789

abc def ghi
jkl mno pqr

And the cursor is on 'a', then you do C-u 3 M-t, the result will be:

123 456 abc def ghi

789
jkl mno pqr

Which I find quite zany when compared to the first example. The
attached diff for mg does this:

123 456 abc

def ghi 789
jkl mno pqr

Which makes more sense to me but perhaps it is just as zany... What do
people think? 

Mark

Index: def.h
===
RCS file: /cvs/src/usr.bin/mg/def.h,v
retrieving revision 1.152
diff -u -p -u -p -r1.152 def.h
--- def.h   29 Oct 2015 19:46:47 -  1.152
+++ def.h   24 Dec 2015 09:27:00 -
@@ -602,6 +602,7 @@ int  capword(int, int);
 int delfword(int, int);
 int delbword(int, int);
 int inword(void);
+int transposeword(int, int);
 
 /* region.c X */
 int killregion(int, int);
Index: funmap.c
===
RCS file: /cvs/src/usr.bin/mg/funmap.c,v
retrieving revision 1.51
diff -u -p -u -p -r1.51 funmap.c
--- funmap.c26 Sep 2015 15:03:15 -  1.51
+++ funmap.c24 Dec 2015 09:27:00 -
@@ -201,6 +201,7 @@ static struct funmap functnames[] = {
{togglereadonly, "toggle-read-only" },
{twiddle, "transpose-chars",},
{transposepara, "transpose-paragraphs",},
+   {transposeword, "transpose-words",},
{undo, "undo",},
{undo_add_boundary, "undo-boundary",},
{undo_boundary_enable, "undo-boundary-toggle",},
Index: keymap.c
===
RCS file: /cvs/src/usr.bin/mg/keymap.c,v
retrieving revision 1.57
diff -u -p -u -p -r1.57 keymap.c
--- keymap.c26 Sep 2015 21:51:58 -  1.57
+++ keymap.c24 Dec 2015 09:27:00 -
@@ -282,7 +282,7 @@ static PF metal[] = {
fillpara,   /* q */
backsearch, /* r */
forwsearch, /* s */
-   rescan, /* t */
+   transposeword,  /* t */
upperword,  /* u */
backpage,   /* v */
copyregion, /* w */
Index: mg.1
===
RCS file: /cvs/src/usr.bin/mg/mg.1,v
retrieving revision 1.98
diff -u -p -u -p -r1.98 mg.1
--- mg.124 Dec 2015 09:07:47 -  1.98
+++ mg.124 Dec 2015 09:27:00 -
@@ -306,6 +306,8 @@ fill-paragraph
 search-backward
 .It M-s
 search-forward
+.It M-t
+transpose-words
 .It M-u
 upcase-word
 .It M-v
@@ -881,6 +883,12 @@ If multiple iterations are requested, th
 be moved
 .Va n
 paragraphs forward.
+.It transpose-words
+Transpose adjacent words.
+If multiple iterations are requested, the current word will
+be moved
+.Va n
+words forward.
 .It undo
 Undo the most recent action.
 If invoked again without an intervening command,
Index: word.c
===
RCS file: /cvs/src/usr.bin/mg/word.c,v
retrieving revision 1.17
diff -u -p -u -p -r1.17 word.c
--- word.c  19 Mar 2015 21:22:15 -  1.17
+++ word.c  24 Dec 2015 09:27:00 -
@@ -10,11 +10,15 @@
 
 #include 
 #include 
+#include 
 #include 
+#include 
+#include 
 
 #include "def.h"
 
 RSIZE  countfword(void);
+intgrabword(char **);
 
 /*
  * Move the cursor backward by "n" words. All of the details of motion are
@@ -61,6 +65,158 @@ forwword(int f, int n)
return (TRUE);
}
}
+   return (TRUE);
+}
+
+/*
+ * Transpose 2 words.
+ */
+int
+transposeword(int f, int n)
+{
+   struct line *tmp1_w_dotp = NULL;
+   struct line *tmp2_w_dotp = NULL;
+   int  tmp2_w_doto = 0;
+   int  tmp1_w_dotline = 0;
+   int  tmp2_w_dotline = 0;
+   int  tmp1_w_doto;
+   int  i; /* start-of-line space counter */
+   int  ret, s;
+   int  newline;
+   int  leave = 0;
+   int  tmp_len;
+   char*word1 = NULL;
+   char*word2 = NULL;
+   char*chr;
+
+   if (n == 0)
+   return (TRUE);
+
+   if ((s = checkdirty(curbp)) != TRUE)
+   return (s);
+   if (curbp->b_flag & BFREADONLY) {
+   dobeep();
+   ewprintf("Buffer is read-only");
+   return (FALSE);
+   }
+
+   undo_boundary_enable(FFRAND, 0);
+

mg - set read-only from command line

2015-12-23 Thread Mark Lumsden
If I am opening a lot of files into an editor but with the intention
of not changing the contents (or more usually only amending a couple
of files), a la:

> mg *

I like to open them all read-only, then change the ones I want to edit
to read-write as required, that way I know when I close them all I
know that any changes are there because I wanted to make them. Instead
of thinking 'did I really want that change' when I'm asked to save a
file I didn't want to edit, but edited it accidentally. 

This diff allows mg to open all command specified files read-only:

> mg -R *

ok?

Mark

Index: mg.1
===
RCS file: /cvs/src/usr.bin/mg/mg.1,v
retrieving revision 1.96
diff -u -p -r1.96 mg.1
--- mg.121 Dec 2015 09:04:52 -  1.96
+++ mg.123 Dec 2015 15:53:03 -
@@ -10,6 +10,7 @@
 .Sh SYNOPSIS
 .Nm mg
 .Op Fl n
+.Op Fl R
 .Op Fl f Ar mode
 .Op + Ns Ar number
 .Op Ar
@@ -40,6 +41,8 @@ arguments on the command line, including
 scratch buffer and all files.
 .It Fl n
 Turn off backup file generation.
+.It Fl R
+Files specified on the command line will be opened read-only.
 .El
 .Sh WINDOWS AND BUFFERS
 When a file is loaded into
Index: main.c
===
RCS file: /cvs/src/usr.bin/mg/main.c,v
retrieving revision 1.80
diff -u -p -r1.80 main.c
--- main.c  19 Nov 2015 19:30:44 -  1.80
+++ main.c  23 Dec 2015 15:53:03 -
@@ -53,14 +53,17 @@ main(int argc, char **argv)
char*cp, *init_fcn_name = NULL;
PF   init_fcn = NULL;
int  o, i, nfiles;
-   int  nobackups = 0;
+   int  nobackups = 0, bro = 0;
struct buffer   *bp = NULL;
 
if (pledge("stdio rpath wpath cpath fattr getpw tty proc exec", NULL) 
== -1)
err(1, "pledge");
 
-   while ((o = getopt(argc, argv, "nf:")) != -1)
+   while ((o = getopt(argc, argv, "Rnf:")) != -1)
switch (o) {
+   case 'R':
+   bro = 1;
+   break;
case 'n':
nobackups = 1;
break;
@@ -170,6 +173,8 @@ notnum:
init_fcn(FFOTHARG, 1);
nfiles++;
}
+   if (bro)
+   curbp->b_flag |= BFREADONLY;
}
}
}



mg(1) dired sort

2015-10-13 Thread Mark Lumsden
This diff allows dired mode to sort directory contents alphabetically
or by date order. It uses the same key as emacs: 's', though the
extended command name is 'dired-sort'. Comments/ok? 

-lum

Index: dired.c
===
RCS file: /cvs/src/usr.bin/mg/dired.c,v
retrieving revision 1.78
diff -u -p -u -p -r1.78 dired.c
--- dired.c 12 Oct 2015 19:08:39 -  1.78
+++ dired.c 13 Oct 2015 19:57:48 -
@@ -51,15 +51,20 @@ static int   d_forwline(int, int);
 static int  d_backline(int, int);
 static int  d_killbuffer_cmd(int, int);
 static int  d_refreshbuffer(int, int);
+static int  d_sort(int, int);
 static void reaper(int);
 static struct buffer   *refreshbuffer(struct buffer *);
 static int  createlist(struct buffer *);
 static void redelete(struct buffer *);
 static char *findfname(struct line *, char *);
+static void finddotlsal(struct buffer *);
 
 extern struct keymap_s helpmap, cXmap, metamap;
 
-const char DDELCHAR = 'D';
+const char  DDELCHAR = 'D';
+const int   LSALT = 4; /* 4 = -alt, 3 = -al)   */
+charlsargs[5] = "-al"; /* see LSALT above  */
+int lsarg_toggle = 0;  /* 's' has implications for dot */
 
 /*
  * Structure which holds a linked list of file names marked for
@@ -134,7 +139,7 @@ static PF diredn[] = {
d_backline, /* p */
d_killbuffer_cmd,   /* q */
d_rename,   /* r */
-   rescan, /* s */
+   d_sort, /* s */
rescan, /* t */
d_undel,/* u */
rescan, /* v */
@@ -212,6 +217,7 @@ dired_init(void)
funmap_add(d_rename, "dired-do-rename");
funmap_add(d_backpage, "dired-scroll-down");
funmap_add(d_forwpage, "dired-scroll-up");
+   funmap_add(d_sort, "dired-sort");
funmap_add(d_undel, "dired-unmark");
funmap_add(d_killbuffer_cmd, "quit-window");
maps_add((KEYMAP *), "dired");
@@ -750,7 +756,16 @@ refreshbuffer(struct buffer *bp)
if (ddel)
redelete(bp);   
 
-   /* find dot line */
+   /* If required, find suitable dot line if toggling sort order. */
+   if (lsarg_toggle && (strlen(lsargs) == LSALT)) {
+   tmp_w_dotline = 2;  /* 2nd line for -alt */
+   lsarg_toggle = 0;
+   } else if (lsarg_toggle) {
+   finddotlsal(bp);/* or after ".." if -al */
+   lsarg_toggle = 0;
+   curbp = bp;
+   return (bp);
+   }
bp->b_dotp = bfirstlp(bp);
if (tmp_w_dotline > bp->b_lines)
tmp_w_dotline = bp->b_lines - 1;
@@ -848,7 +863,6 @@ struct buffer *
 dired_(char *dname)
 {
struct buffer   *bp;
-   int  i;
size_t   len;
 
if ((dname = adjustname(dname, TRUE)) == NULL) {
@@ -881,26 +895,11 @@ dired_(char *dname)
bp = bfind(dname, TRUE);
bp->b_flag |= BFREADONLY | BFIGNDIRTY;
 
-   if ((d_exec(2, bp, NULL, "ls", "-al", dname, NULL)) != TRUE)
+   if ((d_exec(2, bp, NULL, "ls", lsargs, dname, NULL)) != TRUE)
return (NULL);
 
-   /* Find the line with ".." on it. */
-   bp->b_dotp = bfirstlp(bp);
-   bp->b_dotline = 1;
-   for (i = 0; i < bp->b_lines; i++) {
-   bp->b_dotp = lforw(bp->b_dotp);
-   bp->b_dotline++;
-   if (d_warpdot(bp->b_dotp, >b_doto) == FALSE)
-   continue;
-   if (strcmp(ltext(bp->b_dotp) + bp->b_doto, "..") == 0)
-   break;
-   }
+   finddotlsal(bp);
 
-   /* We want dot on the entry right after "..", if possible. */
-   if (++i < bp->b_lines - 2) {
-   bp->b_dotp = lforw(bp->b_dotp);
-   bp->b_dotline++;
-   }
d_warpdot(bp->b_dotp, >b_doto);
 
(void)strlcpy(bp->b_fname, dname, sizeof(bp->b_fname));
@@ -1035,4 +1034,46 @@ findfname(struct line *lp, char *fn)
return NULL;
fn = >l_text[start];
return fn;
+}
+
+static int
+d_sort(int f, int n)
+{
+   struct buffer   *bp;
+
+   if (strlen(lsargs) == LSALT)
+   (void)snprintf(lsargs, sizeof(lsargs), "-al");
+   else
+   (void)snprintf(lsargs, sizeof(lsargs), "-alt");
+
+   lsarg_toggle = 1;
+
+   if ((bp = refreshbuffer(curbp)) == NULL)
+   return (FALSE);
+   return (showbuffer(bp, curwp, WFFULL | WFMODE));
+}
+
+static void
+finddotlsal(struct buffer *bp)
+{
+   int i;
+
+   bp->b_dotp = bfirstlp(bp);
+   bp->b_dotline = 1;
+   for (i = 0; i < bp->b_lines; i++) {
+   bp->b_dotp = lforw(bp->b_dotp);
+   bp->b_dotline++;
+   if (d_warpdot(bp->b_dotp, >b_doto) == FALSE)
+   continue;
+

mg(1) make dired-flag-file-deletion file more accurate

2015-10-12 Thread Mark Lumsden
Instead of just seeing if a line in a dired buffer is longer than 0
before marking it for deletion, check if a filename has the potential
to be extracted from a line. ok? 

-lum

Index: dired.c
===
RCS file: /cvs/src/usr.bin/mg/dired.c,v
retrieving revision 1.78
diff -u -p -u -p -r1.78 dired.c
--- dired.c 12 Oct 2015 19:08:39 -  1.78
+++ dired.c 12 Oct 2015 19:34:50 -
@@ -286,7 +286,7 @@ d_del(int f, int n)
if (n < 0)
return (FALSE);
while (n--) {
-   if (llength(curwp->w_dotp) > 0) {
+   if (d_warpdot(curwp->w_dotp, >w_doto) == TRUE) {
lputc(curwp->w_dotp, 0, DDELCHAR);
curbp->b_flag |= BFDIREDDEL;
}



mg(1) Change onlywind() params

2015-10-09 Thread Mark Lumsden
Calling onlywind() in this way should use FFRAND and 1 as the
repective parameters. ok? 

-lum

Index: buffer.c
===
RCS file: /cvs/src/usr.bin/mg/buffer.c,v
retrieving revision 1.99
diff -u -p -u -p -r1.99 buffer.c
--- buffer.c26 Sep 2015 21:51:58 -  1.99
+++ buffer.c9 Oct 2015 09:39:30 -
@@ -408,7 +408,7 @@ listbuf_goto_buffer_helper(int f, int n,
curwp = wp;
 
if (only)
-   ret = (onlywind(f, n));
+   ret = (onlywind(FFRAND, 1));
else
ret = TRUE;
 
Index: theo.c
===
RCS file: /cvs/src/usr.bin/mg/theo.c,v
retrieving revision 1.146
diff -u -p -u -p -r1.146 theo.c
--- theo.c  19 Mar 2015 21:48:05 -  1.146
+++ theo.c  9 Oct 2015 09:39:30 -
@@ -78,7 +78,7 @@ theo(int f, int n)
 
curbp = bp;
curwp = wp;
-   onlywind(f, n);
+   onlywind(FFRAND, 1);
 
return (TRUE);
 }



mg(1) onlywind() line number anomaly

2015-10-08 Thread Mark Lumsden
If you open mg with only the *scratch* buffer loaded (no file names
given on command line), and press enter 5 times, take a note of the
line number in the status bar then open theo mode (M-x theo). Then
move back to the *scratch* buffer via switch-to-buffer (C-x b). You'll
notice the line number of the *scratch* buffer is now 1, though the
cursor is on line 5. theo mode is initally opened splitting the screen
in two, then onlywind() is called. The bug is in onlywind(). This diff
fixes this behavior. ok? 

-lum

Index: window.c
===
RCS file: /cvs/src/usr.bin/mg/window.c,v
retrieving revision 1.33
diff -u -p -u -p -r1.33 window.c
--- window.c25 Mar 2015 20:53:31 -  1.33
+++ window.c8 Oct 2015 19:49:34 -
@@ -167,6 +167,8 @@ onlywind(int f, int n)
wp->w_bufp->b_doto = wp->w_doto;
wp->w_bufp->b_markp = wp->w_markp;
wp->w_bufp->b_marko = wp->w_marko;
+   wp->w_bufp->b_dotline = wp->w_dotline;
+   wp->w_bufp->b_markline = wp->w_markline;
}
free(wp);
}
@@ -178,6 +180,8 @@ onlywind(int f, int n)
wp->w_bufp->b_doto = wp->w_doto;
wp->w_bufp->b_markp = wp->w_markp;
wp->w_bufp->b_marko = wp->w_marko;
+   wp->w_bufp->b_dotline = wp->w_dotline;
+   wp->w_bufp->b_markline = wp->w_markline;
}
free(wp);
}



mg(1) honour C-u 0

2015-10-07 Thread Mark Lumsden
Calling an mg command with zero iterations (C-u 0) seems non-sensical
but what should happen if you did? Currently some commands honour the
0 [ie. do nothing], others do not, they partially complete or complete
as if 1 had been passed. For example try and insert 0 characters via:

C-u 0 a

The function that inserts characters has an 'if' statement that
handles 0 being passed and returns before any characters are
inserted. Now try to move to the beginning of a line:

C-u 0 C-a

The case for zero iterations isn't handled and the cursor goes to the
beginning of the line. Now try tranposing 0 paragraphs:

C-u 0 M-x tranpose-paragraphs

The cursor moves to the end of the current paragraph and no
transposing is completed.

This diff makes functions that honour multiple* iterations but
currently do not honour zero iterations, honour 0 iterations.
Comments/oks? 

-lum

* Functions that do not honour multiple (or non-single) iterations are
not included, e.g: M-<. 
Also the tranpose-chars (C-t) function doesn't honour multiple
iterations, but probably should so it has been included in this diff. 

Index: basic.c
===
RCS file: /cvs/src/usr.bin/mg/basic.c,v
retrieving revision 1.46
diff -u -p -u -p -r1.46 basic.c
--- basic.c 26 Sep 2015 21:51:58 -  1.46
+++ basic.c 7 Oct 2015 14:19:24 -
@@ -28,6 +28,9 @@
 int
 gotobol(int f, int n)
 {
+   if (n == 0)
+   return (TRUE);
+
curwp->w_doto = 0;
return (TRUE);
 }
@@ -72,6 +75,9 @@ backchar(int f, int n)
 int
 gotoeol(int f, int n)
 {
+   if (n == 0)
+   return (TRUE);
+
curwp->w_doto = llength(curwp->w_dotp);
return (TRUE);
 }
Index: paragraph.c
===
RCS file: /cvs/src/usr.bin/mg/paragraph.c,v
retrieving revision 1.40
diff -u -p -u -p -r1.40 paragraph.c
--- paragraph.c 26 Sep 2015 15:03:15 -  1.40
+++ paragraph.c 7 Oct 2015 14:19:25 -
@@ -142,6 +142,9 @@ fillpara(int f, int n)
struct line *eopline;   /* pointer to line just past EOP
*/
char wbuf[MAXWORD]; /* buffer for current word  */
 
+   if (n == 0)
+   return (TRUE);
+
undo_boundary_enable(FFRAND, 0);
 
/* record the pointer to the line just past the EOP */
@@ -267,6 +270,9 @@ killpara(int f, int n)
 {
int lineno, status;
 
+   if (n == 0)
+   return (TRUE);
+
if (findpara() == FALSE)
return (TRUE);
 
@@ -298,6 +304,9 @@ markpara(int f, int n)
 {
int i = 0;
 
+   if (n == 0)
+   return (TRUE);
+
clearmark(FFARG, 0);
 
if (findpara() == FALSE)
@@ -325,6 +334,9 @@ transposepara(int f, int n)
 {
int i = 0, status;
charflg;
+
+   if (n == 0)
+   return (TRUE);
 
/* find a paragraph, set mark, then goto the end */
gotobop(FFRAND, 1);
Index: util.c
===
RCS file: /cvs/src/usr.bin/mg/util.c,v
retrieving revision 1.36
diff -u -p -u -p -r1.36 util.c
--- util.c  29 Sep 2015 03:19:24 -  1.36
+++ util.c  7 Oct 2015 14:19:25 -
@@ -117,6 +117,9 @@ twiddle(int f, int n)
struct line *dotp;
int  doto, cr;
 
+   if (n == 0)
+   return (TRUE);
+
dotp = curwp->w_dotp;
doto = curwp->w_doto;
 



mg(1) keep 'D' marked files across dired refreshes

2015-10-06 Thread Mark Lumsden
Hi,

Currently, in mg dired mode, if you mark a file as deleted, if the
dired buffer is refreshed (using 'dired-revert' for example) the
marking of files is lost. This diff fixes that by saving the marked
files before they are lost, then remarking them once the buffer is
refreshed. Comments/oks?

-lum

Index: def.h
===
RCS file: /cvs/src/usr.bin/mg/def.h,v
retrieving revision 1.150
diff -u -p -u -p -r1.150 def.h
--- def.h   29 Sep 2015 02:07:49 -  1.150
+++ def.h   6 Oct 2015 20:08:30 -
@@ -288,7 +288,8 @@ struct buffer {
 #define BFOVERWRITE 0x08   /* overwrite mode*/
 #define BFREADONLY  0x10   /* read only mode*/
 #define BFDIRTY 0x20   /* Buffer was modified elsewhere */
-#define BFIGNDIRTY  0x40   /* Ignore modifications */
+#define BFIGNDIRTY  0x40   /* Ignore modifications  */
+#define BFDIREDDEL  0x80   /* Dired has a deleted 'D' file  */
 /*
  * This structure holds information about recent actions for the Undo command.
  */
Index: dired.c
===
RCS file: /cvs/src/usr.bin/mg/dired.c,v
retrieving revision 1.77
diff -u -p -u -p -r1.77 dired.c
--- dired.c 28 Sep 2015 11:56:17 -  1.77
+++ dired.c 6 Oct 2015 20:08:30 -
@@ -53,9 +53,24 @@ static intd_killbuffer_cmd(int, int);
 static int  d_refreshbuffer(int, int);
 static void reaper(int);
 static struct buffer   *refreshbuffer(struct buffer *);
+static void createlist(struct buffer *);
+static void redelete(struct buffer *);
+static char *findfname(struct line *, char *);
 
 extern struct keymap_s helpmap, cXmap, metamap;
 
+const char DDELCHAR = 'D';
+
+/*
+ * Structure which holds a linked list of file names marked for
+ * deletion. Used to maintain dired buffer 'state' between refreshes.
+ */
+struct delentry {
+   SLIST_ENTRY(delentry) entry;
+   char   *fn;
+};
+SLIST_HEAD(slisthead, delentry) delhead = SLIST_HEAD_INITIALIZER(delhead);
+
 static PF dirednul[] = {
setmark,/* ^@ */
gotobol,/* ^A */
@@ -271,8 +286,10 @@ d_del(int f, int n)
if (n < 0)
return (FALSE);
while (n--) {
-   if (llength(curwp->w_dotp) > 0)
-   lputc(curwp->w_dotp, 0, 'D');
+   if (llength(curwp->w_dotp) > 0) {
+   lputc(curwp->w_dotp, 0, DDELCHAR);
+   curbp->b_flag |= BFDIREDDEL;
+   }
if (lforw(curwp->w_dotp) != curbp->b_headp) {
curwp->w_dotp = lforw(curwp->w_dotp);
curwp->w_dotline++;
@@ -412,6 +429,8 @@ d_expunge(int f, int n)
curwp->w_rflag |= WFFULL;
}
}
+   /* we have deleted all items successfully, remove del flag */
+   bp->b_flag &= ~BFDIREDDEL   
curwp->w_dotline = tmp;
d_warpdot(curwp->w_dotp, >w_doto);
return (TRUE);
@@ -692,26 +711,53 @@ d_refreshbuffer(int f, int n)
return (showbuffer(bp, curwp, WFFULL | WFMODE));
 }
 
+/*
+ * Kill then re-open the requested dired buffer.
+ * If required, take a note of any files marked for deletion. Then once
+ * the buffer has been re-opened, remark the same files as deleted.
+ */
 struct buffer *
 refreshbuffer(struct buffer *bp)
 {
-   char*tmp;
+   char*tmp_b_fname;
+   int  i, tmp_w_dotline;
 
-   tmp = strdup(bp->b_fname);
-   if (tmp == NULL) {
+   /* remember directory path to open later */
+   tmp_b_fname = strdup(bp->b_fname);
+   if (tmp_b_fname == NULL) {
dobeep();
ewprintf("Out of memory");
return (NULL);
}
+   tmp_w_dotline = curwp->w_dotline;
+
+   /* create a list of files for deletion */
+   if (bp->b_flag & BFDIREDDEL)
+   createlist(bp);
 
killbuffer(bp);
 
/* dired_() uses findbuffer() to create new buffer */
-   if ((bp = dired_(tmp)) == NULL) {
-   free(tmp);
+   if ((bp = dired_(tmp_b_fname)) == NULL) {
+   free(tmp_b_fname);
return (NULL);
}
-   free(tmp);
+   free(tmp_b_fname);
+
+   /* remark any previously deleted files with a 'D' */
+   redelete(bp);   
+
+   /* find dot line */
+   bp->b_dotp = bfirstlp(bp);
+   if (tmp_w_dotline > bp->b_lines)
+   tmp_w_dotline = bp->b_lines - 1;
+   for (i = 1; i < tmp_w_dotline; i++)
+   bp->b_dotp = lforw(bp->b_dotp);
+
+   bp->b_dotline = i;
+   bp->b_doto = 0;
+   d_warpdot(bp->b_dotp, >b_doto);
+
curbp = bp;
 
return (bp);
@@ -865,4 +911,118 @@ dired_(char *dname)
(void)fupdstat(bp);
bp->b_nmodes = 1;
  

mg(1) filevisit and dired mode

2015-09-25 Thread Mark Lumsden
hi,

If you find-file (C-x C-f) and select a directory instead of a file,
mg will eventually call dired but due to the current location of the
call to dired in mg, find-file calls showbuffer() multiple times.
Apart from being wastefull, doing this results in the cursor ending up
on the wrong line of the dired buffer, it lands on line 1 instead of
the line after "..". 

This diff checks to see if the requested path is a directory as soon
as find-file is called, and if so calls dired. This removes the
problems mention previously. 

Comments/ok?

mark

Index: file.c
===
RCS file: /cvs/src/usr.bin/mg/file.c,v
retrieving revision 1.97
diff -u -p -u -p -r1.97 file.c
--- file.c  25 Mar 2015 12:25:36 -  1.97
+++ file.c  25 Sep 2015 10:40:57 -
@@ -45,10 +45,10 @@ fileinsert(int f, int n)
 }
 
 /*
- * Select a file for editing.  Look around to see if you can find the file
- * in another buffer; if you can find it, just switch to the buffer.  If
- * you cannot find the file, create a new buffer, read in the text, and
- * switch to the new buffer.
+ * Select a file for editing.  If the file is a directory, invoke dired.
+ * Otherwise look around to see if you can find the file in another buffer;
+ * if you can find it, just switch to the buffer.  If you cannot find the
+ * file, create a new buffer, read in the text, and switch to the new buffer.
  */
 /* ARGSUSED */
 int
@@ -66,6 +66,12 @@ filevisit(int f, int n)
return (ABORT);
else if (bufp[0] == '\0')
return (FALSE);
+   if (fisdir(fname) == TRUE) {
+   if ((bp = dired_(bufp)) == FALSE)
+   return (FALSE);
+   curbp = bp;
+   return (showbuffer(bp, curwp, WFFULL | WFMODE));
+   }
adjf = adjustname(fname, TRUE);
if (adjf == NULL)
return (FALSE);



mg(1) transpose-paragraph

2015-09-24 Thread Mark Lumsden
While I am 'paragraph' mode, here is the useful 'transpose-paragraph'
command. Comments/ok?

mark

Index: def.h
===
RCS file: /cvs/src/usr.bin/mg/def.h,v
retrieving revision 1.148
diff -u -p -u -p -r1.148 def.h
--- def.h   24 Sep 2015 07:07:59 -  1.148
+++ def.h   24 Sep 2015 18:15:38 -
@@ -588,6 +588,7 @@ int  killpara(int, int);
 int fillword(int, int);
 int setfillcol(int, int);
 int markpara(int, int);
+int transposepara(int, int);
 
 /* word.c X */
 int backword(int, int);
Index: funmap.c
===
RCS file: /cvs/src/usr.bin/mg/funmap.c,v
retrieving revision 1.50
diff -u -p -u -p -r1.50 funmap.c
--- funmap.c24 Sep 2015 07:07:59 -  1.50
+++ funmap.c24 Sep 2015 18:15:38 -
@@ -200,6 +200,7 @@ static struct funmap functnames[] = {
{poptobuffer, "switch-to-buffer-other-window",},
{togglereadonly, "toggle-read-only" },
{twiddle, "transpose-chars",},
+   {transposepara, "transpose-paragraph",},
{undo, "undo",},
{undo_add_boundary, "undo-boundary",},
{undo_boundary_enable, "undo-boundary-toggle",},
Index: mg.1
===
RCS file: /cvs/src/usr.bin/mg/mg.1,v
retrieving revision 1.92
diff -u -p -u -p -r1.92 mg.1
--- mg.124 Sep 2015 07:07:59 -  1.92
+++ mg.124 Sep 2015 18:15:38 -
@@ -874,6 +874,10 @@ Toggle the read-only flag on the current
 Transpose the two characters in front of and under dot,
 then move forward one character.
 Treat newline characters the same as any other.
+.It transpose-paragraph
+Transpose adjacent paragraphs.
+If multiple iterations are requested, the current paragraph will
+be moved n paragraphs forward.
 .It undo
 Undo the most recent action.
 If invoked again without an intervening command,
Index: paragraph.c
===
RCS file: /cvs/src/usr.bin/mg/paragraph.c,v
retrieving revision 1.39
diff -u -p -u -p -r1.39 paragraph.c
--- paragraph.c 24 Sep 2015 07:20:12 -  1.39
+++ paragraph.c 24 Sep 2015 18:15:38 -
@@ -314,6 +314,50 @@ markpara(int f, int n)
return (TRUE);
 }
 
+
+/*
+ * Transpose the current paragraph with the following paragraph. If invoked
+ * multiple times, transpose to the n'th paragraph. If invoked between 
+ * paragraphs, move to the previous paragraph, then continue.
+ */
+/* ARGSUSED */
+int
+transposepara(int f, int n)
+{
+   int i = 0, status;
+   charflg;
+
+   /* find a paragraph, set mark, then goto the end */
+   gotobop(FFRAND, 1);
+   curwp->w_markp = curwp->w_dotp;
+   curwp->w_marko = curwp->w_doto;
+   (void)gotoeop(FFRAND, 1);
+
+   /* take a note of buffer flags - we may need them */
+   flg = curbp->b_flag;
+
+   /* clean out kill buffer then kill region */
+   kdelete();
+   if ((status = killregion(FFRAND, 1)) != TRUE)
+   return (status);
+
+   /* 
+* Now step through n paragraphs. If we reach the end of buffer,
+* stop and paste the killed region back, then display a message.
+*/
+   if (do_gotoeop(FFRAND, n, ) == FALSE) {
+   ewprintf("Cannot transpose paragraph, end of buffer reached.");
+   (void)gotobop(FFRAND, i);
+   (void)yank(FFRAND, 1);
+   curbp->b_flag = flg;
+   return (FALSE);
+   }
+   (void)yank(FFRAND, 1);
+
+   return (TRUE);
+}
+
+
 /*
  * Go down the buffer until we find a line with non-space characters.
  */



mg(1) dired-do-flagged-delete warpdot

2015-09-23 Thread Mark Lumsden
In dired mode, I noticed that if the cursor is on a file marked for
deletion when dired-do-flagged-delete (x) is called, the cursor is
placed on the left hand side of the window. This diff makes d_expunge
behave like other delete functions and calls d_warpdot to() place the
cursor on the first character of a filename. ok? 

mark

Index: dired.c
===
RCS file: /cvs/src/usr.bin/mg/dired.c,v
retrieving revision 1.74
diff -u -p -u -p -r1.74 dired.c
--- dired.c 23 Sep 2015 05:03:03 -  1.74
+++ dired.c 24 Sep 2015 00:42:55 -
@@ -413,6 +413,7 @@ d_expunge(int f, int n)
}
}
curwp->w_dotline = tmp;
+   d_warpdot(curwp->w_dotp, >w_doto);
return (TRUE);
 }
 



mg(1) - kill-paragraph tidy up

2015-09-21 Thread Mark Lumsden
Hi,

The kill-buffer command in mg doesn't behave quite as I would expect,
if you invoke it multiple times via C-u #, then follow with M-_ (undo)
or C-y (paste), only the last buffer killed (re)appears and not the
multiple paragraphs that I think should. This diff changes that
behaviour. 

Also, by fixing kill-paragraph I had worked out how to mark multiple
paragraphs in one go, so the mark-paragraph command was straight
forward to add in. This diff therefore is doing two things, fixing
kill-paragraph and introducing the mark-paragraph command. I can split
them out if required.  Comments/ok? 

-lum

Index: def.h
===
RCS file: /cvs/src/usr.bin/mg/def.h,v
retrieving revision 1.147
diff -u -p -u -p -r1.147 def.h
--- def.h   3 Jun 2015 23:40:01 -   1.147
+++ def.h   17 Sep 2015 18:44:39 -
@@ -587,6 +587,7 @@ int  fillpara(int, int);
 int killpara(int, int);
 int fillword(int, int);
 int setfillcol(int, int);
+int markpara(int, int);
 
 /* word.c X */
 int backword(int, int);
Index: funmap.c
===
RCS file: /cvs/src/usr.bin/mg/funmap.c,v
retrieving revision 1.49
diff -u -p -u -p -r1.49 funmap.c
--- funmap.c19 Mar 2015 21:22:15 -  1.49
+++ funmap.c17 Sep 2015 18:44:39 -
@@ -132,6 +132,7 @@ static struct funmap functnames[] = {
{localunbind, "local-unset-key",},
{makebkfile, "make-backup-files",},
{makedir, "make-directory",},
+   {markpara, "mark-paragraph",},
{markbuffer, "mark-whole-buffer",},
{do_meta, "meta-key-mode",},/* better name, anyone? */
{negative_argument, "negative-argument",},
Index: keymap.c
===
RCS file: /cvs/src/usr.bin/mg/keymap.c,v
retrieving revision 1.55
diff -u -p -u -p -r1.55 keymap.c
--- keymap.c19 Mar 2015 21:48:05 -  1.55
+++ keymap.c17 Sep 2015 18:44:39 -
@@ -268,7 +268,9 @@ static PF metasqf[] = {
capword,/* c */
delfword,   /* d */
rescan, /* e */
-   forwword/* f */
+   forwword,   /* f */
+   rescan, /* g */
+   markpara/* h */
 };
 
 static PF metal[] = {
@@ -333,7 +335,7 @@ struct KEYMAPE (8) metamap = {
'*', '>', metami, NULL
},
{
-   '[', 'f', metasqf, (KEYMAP *) 
+   '[', 'h', metasqf, (KEYMAP *) 
},
{
'l', '}', metal, NULL
Index: mg.1
===
RCS file: /cvs/src/usr.bin/mg/mg.1,v
retrieving revision 1.91
diff -u -p -u -p -r1.91 mg.1
--- mg.19 Sep 2015 19:03:13 -   1.91
+++ mg.117 Sep 2015 18:44:39 -
@@ -292,6 +292,8 @@ capitalize-word
 kill-word
 .It M-f
 forward-word
+.It M-h
+mark-paragraph
 .It M-l
 downcase-word
 .It M-m
@@ -672,6 +674,8 @@ Unbind a key mapping in the local (topmo
 Toggle generation of backup files.
 .It make-directory
 Prompt the user for a path or directory name which is then created.
+.It mark-paragraph
+Mark the current paragraph.
 .It mark-whole-buffer
 Marks whole buffer as a region by putting dot at the beginning and mark
 at the end of buffer.
Index: paragraph.c
===
RCS file: /cvs/src/usr.bin/mg/paragraph.c,v
retrieving revision 1.36
diff -u -p -u -p -r1.36 paragraph.c
--- paragraph.c 19 Mar 2015 21:22:15 -  1.36
+++ paragraph.c 17 Sep 2015 18:44:39 -
@@ -20,6 +20,9 @@ static intfillcol = 70;
 
 #define MAXWORD 256
 
+static int findpara(void);
+static int do_gotoeop(int, int, int *);
+
 /*
  * Move to start of paragraph.
  * Move backwards by line, checking from the 1st character forwards for the
@@ -70,7 +73,15 @@ gotobop(int f, int n)
 int
 gotoeop(int f, int n)
 {
-   int col, nospace;
+   int i;
+
+   return(do_gotoeop(f, n, ));
+}
+
+int
+do_gotoeop(int f, int n, int *i)
+{
+   int col, nospace, j = 0;
 
/* the other way... */
if (n < 0)
@@ -78,6 +89,7 @@ gotoeop(int f, int n)
 
/* for each one asked for */
while (n-- > 0) {
+   *i = ++j;
nospace = 0;
while (lforw(curwp->w_dotp) != curbp->b_headp) {
col = 0;
@@ -251,32 +263,82 @@ cleanup:
 int
 killpara(int f, int n)
 {
-   int status, end = FALSE;/* returned status of functions */
+   int lineno, status;
+
+   if (findpara() == FALSE)
+   return (TRUE);
+
+   /* goto beginning of para */
+   (void)gotobop(FFRAND, 1);
 
-   /* for each paragraph to delete */
-   while (n--) {
+   /* take a 

mg(1) startup file comments

2014-04-02 Thread Mark Lumsden
ok to indicate a comment in an mg startup file with the '#' char?

I can't see how this will break anybodys current startup files...

-lum

Index: extend.c
===
RCS file: /cvs/src/usr.bin/mg/extend.c,v
retrieving revision 1.54
diff -u -p -u -p -r1.54 extend.c
--- extend.c20 Mar 2014 07:47:29 -  1.54
+++ extend.c2 Apr 2014 18:35:21 -
@@ -730,8 +730,9 @@ excline(char *line)
f = 0;
n = 1;
funcp = skipwhite(line);
-   if (*funcp == '\0')
-   return (TRUE);  /* No error on blank lines */
+   /* No error on blank lines and skip comment lines.  */
+   if (*funcp == '\0' || *funcp == '#')
+   return (TRUE);
line = parsetoken(funcp);
if (*line != '\0') {
*line++ = '\0';
Index: mg.1
===
RCS file: /cvs/src/usr.bin/mg/mg.1,v
retrieving revision 1.87
diff -u -p -u -p -r1.87 mg.1
--- mg.127 Mar 2014 07:30:25 -  1.87
+++ mg.12 Apr 2014 18:35:21 -
@@ -1033,6 +1033,10 @@ set-default-mode fill
 set-fill-column 72
 auto-execute *.c c-mode
 .Ed
+.Pp
+Comments can be added to the startup files by placing
+.Dq #
+as the first character of a line.
 .Sh FILES
 .Bl -tag -width /usr/share/doc/mg/tutorial -compact
 .It Pa ~/.mg



mg(1) find-file - missing directory

2014-04-01 Thread Mark Lumsden
Currently, if you use find-file (C-x C-f) to find a file in a non-
existant directory, mg (and emacs - coincidentally) suggest you create
the directory manually with the make-directory command. This diff
offers to create the missing directory by pressing 'y'. If mg cannot
create the missing the directory for some reason, it behaves the same
as before and opens a read-write buffer. 

Another option would be having mg try and create the directory on the
fly (without having to press 'y') and then giving a message on its
success or failure. 

comments/oks?

-lum

Index: def.h
===
RCS file: /cvs/src/usr.bin/mg/def.h,v
retrieving revision 1.140
diff -u -p -u -p -r1.140 def.h
--- def.h   22 Mar 2014 11:05:37 -  1.140
+++ def.h   1 Apr 2014 06:18:55 -
@@ -336,7 +336,8 @@ int  changedir(int, int);
 int showcwdir(int, int);
 int getcwdir(char *, size_t);
 int makedir(int, int);
-int do_makedir(void);
+int do_makedir(char *);
+int ask_makedir(void);
 
 /* dired.c */
 struct buffer  *dired_(char *);
Index: dir.c
===
RCS file: /cvs/src/usr.bin/mg/dir.c,v
retrieving revision 1.26
diff -u -p -u -p -r1.26 dir.c
--- dir.c   31 Mar 2014 18:00:58 -  1.26
+++ dir.c   1 Apr 2014 06:18:55 -
@@ -84,18 +84,15 @@ getcwdir(char *buf, size_t len)
 int
 makedir(int f, int n)
 {
-   return (do_makedir());
+   return (ask_makedir());
 }
 
 int
-do_makedir(void)
+ask_makedir(void)
 {
 
-   struct stat  sb;
-   int  finished, ishere;
-   mode_t   dir_mode, mode, oumask;
char bufc[NFILEN];
-   char*slash, *path;
+   char*path;
 
if (getbufcwd(bufc, sizeof(bufc)) != TRUE)
return (ABORT);
@@ -104,6 +101,17 @@ do_makedir(void)
return (ABORT);
else if (path[0] == '\0')
return (FALSE);
+
+   return (do_makedir(path));
+}
+
+int
+do_makedir(char *path)
+{
+   struct stat  sb;
+   int  finished, ishere;
+   mode_t   dir_mode, mode, oumask;
+   char*slash;
 
if ((path = adjustname(path, TRUE)) == NULL)
return (FALSE);
Index: dired.c
===
RCS file: /cvs/src/usr.bin/mg/dired.c,v
retrieving revision 1.66
diff -u -p -u -p -r1.66 dired.c
--- dired.c 20 Mar 2014 07:47:29 -  1.66
+++ dired.c 1 Apr 2014 06:18:55 -
@@ -648,7 +648,7 @@ d_create_directory(int f, int n)
int ret;
struct buffer   *bp;
 
-   ret = do_makedir();
+   ret = ask_makedir();
if (ret != TRUE)
return(ret);
 
Index: file.c
===
RCS file: /cvs/src/usr.bin/mg/file.c,v
retrieving revision 1.93
diff -u -p -u -p -r1.93 file.c
--- file.c  31 Mar 2014 21:29:59 -  1.93
+++ file.c  1 Apr 2014 06:18:55 -
@@ -231,10 +231,10 @@ readin(char *fname)
(void)xdirname(dp, fname, sizeof(dp));
(void)strlcat(dp, /, sizeof(dp));
 
+   /* Missing directory; keep buffer read-write, like emacs */
if (stat(dp, statbuf) == -1  errno == ENOENT) {
-   /* not read-only; like emacs */
-   ewprintf(Use M-x make-directory RET RET to create the
-directory and its parents);
+   if (eyorn(Missing directory, create) == TRUE)
+   (void)do_makedir(dp);
} else if (access(dp, W_OK) == -1  errno == EACCES) {
ewprintf(File not found and directory
 write-protected);



mg(1) dired-unmark-backward

2013-12-19 Thread Mark Lumsden
Make 'dired-unmark-backward' behave the same as emacs.

Any objections?

-lum

Index: dired.c
===
RCS file: /cvs/src/usr.bin/mg/dired.c,v
retrieving revision 1.63
diff -u -p -u -p -r1.63 dired.c
--- dired.c 3 Jun 2013 05:10:59 -   1.63
+++ dired.c 19 Dec 2013 09:12:31 -
@@ -305,11 +305,11 @@ d_undelbak(int f, int n)
if (n  0)
return (d_undel(f, -n));
while (n--) {
-   if (llength(curwp-w_dotp)  0)
-   lputc(curwp-w_dotp, 0, ' ');
if (lback(curwp-w_dotp) != curbp-b_headp)
curwp-w_dotp = lback(curwp-w_dotp);
-   }
+   if (llength(curwp-w_dotp)  0)
+   lputc(curwp-w_dotp, 0, ' ');
+   }
curwp-w_rflag |= WFEDIT | WFMOVE;
return (d_warpdot(curwp-w_dotp, curwp-w_doto));
 }



mg(1) rename dired commands

2013-06-02 Thread Mark Lumsden
This diff renames the dired-* command names to be in line with emacs.
Any objections? 

mark

Index: dired.c
===
RCS file: /cvs/src/usr.bin/mg/dired.c,v
retrieving revision 1.59
diff -u -p -r1.59 dired.c
--- dired.c 30 May 2013 17:43:43 -  1.59
+++ dired.c 2 Jun 2013 08:07:53 -
@@ -183,20 +183,20 @@ void
 dired_init(void)
 {
funmap_add(dired, dired);
-   funmap_add(d_undelbak, dired-backup-unflag);
+   funmap_add(d_undelbak, dired-unmark-backward);
funmap_add(d_create_directory, dired-create-directory);
-   funmap_add(d_copy, dired-copy-file);
-   funmap_add(d_expunge, dired-do-deletions);
+   funmap_add(d_copy, dired-do-copy);
+   funmap_add(d_expunge, dired-do-flagged-delete);
funmap_add(d_findfile, dired-find-file);
funmap_add(d_ffotherwindow, dired-find-file-other-window);
-   funmap_add(d_del, dired-flag-file-deleted);
+   funmap_add(d_del, dired-flag-file-deletion);
funmap_add(d_forwline, dired-next-line);
funmap_add(d_otherwindow, dired-other-window);
funmap_add(d_backline, dired-previous-line);
-   funmap_add(d_rename, dired-rename-file);
+   funmap_add(d_rename, dired-do-rename);
funmap_add(d_backpage, dired-scroll-down);
funmap_add(d_forwpage, dired-scroll-up);
-   funmap_add(d_undel, dired-unflag);
+   funmap_add(d_undel, dired-unmark);
maps_add((KEYMAP *)diredmap, dired);
dobindkey(fundamental_map, dired, ^Xd);
 }
Index: mg.1
===
RCS file: /cvs/src/usr.bin/mg/mg.1,v
retrieving revision 1.81
diff -u -p -r1.81 mg.1
--- mg.11 Jun 2013 17:33:49 -   1.81
+++ mg.12 Jun 2013 08:07:53 -
@@ -936,9 +936,9 @@ dired-shell-command
 .It +
 dired-create-directory
 .It c
-dired-copy-file
+dired-do-copy
 .It d and C-d
-dired-flag-file-deleted
+dired-flag-file-deletion
 .It e, f and C-m
 dired-find-file
 .It n
@@ -948,11 +948,11 @@ dired-find-file-other-window
 .It p
 dired-previous-line
 .It r
-dired-rename-file
+dired-do-rename
 .It u
-dired-unflag
+dired-unmark
 .It x
-dired-do-deletions
+dired-do-flagged-delete
 .It C-v
 dired-scroll-down
 .It M-v
@@ -961,26 +961,25 @@ dired-scroll-up
 .Sh MG DIRED COMMANDS
 The following are a list of the commands specific to dired mode:
 .Bl -tag -width Ds
-.It dired-backup-unflag
-Remove the deletion flag from the file listed on the current line
-of the dired buffer, then move up one line.
-.It dired-copy-file
-Copy the file listed on the current line of the dired buffer.
 .It dired-create-directory
 Create a directory.
-.It dired-do-deletions
+.It dired-do-copy
+Copy the file listed on the current line of the dired buffer.
+.It dired-do-flagged-delete
 Delete the files that have been flagged for deletion.
+.It dired-do-rename
+Rename the file listed on the current line of the dired buffer.
 .It dired-find-file
 Open the file on the current line of the dired buffer.
 If the cursor is on a directory it will be opened in dired mode.
-.It dired-find-file-other-window
-Open the file on the current line of the dired buffer in a
-different window.
-.It dired-flag-file-deleted
+.It dired-flag-file-deletion
 Flag the file listed on the current line for deletion.
 This is indicated in the buffer by putting a D at the left margin.
 No files are actually deleted until the function dired-do-deletions
 is executed.
+.It dired-find-file-other-window
+Open the file on the current line of the dired buffer in a
+different window.
 .It dired-next-line
 Move the cursor to the next line.
 .It dired-other-window
@@ -988,14 +987,15 @@ This function works just like dired, exc
 dired buffer in another window.
 .It dired-previous-line
 Move the cursor to the previous line.
-.It dired-rename-file
-Rename the file listed on the current line of the dired buffer.
 .It dired-scroll-down
 Scroll down the dired buffer.
 .It dired-scroll-up
 Scroll up the dired buffer.
-.It dired-unflag
+.It dired-unmark
 Remove the deletion flag for the file on the current line.
+.It dired-unmark-backward
+Remove the deletion flag from the file listed on the current line
+of the dired buffer, then move up one line.
 .El
 .Sh CONFIGURATION FILES
 There are two configuration files,



mg(1) 'g' dired refresh buffer

2013-06-02 Thread Mark Lumsden
This diff uses 'g' to refresh the dired buffer.

mark

Index: dired.c
===
RCS file: /cvs/src/usr.bin/mg/dired.c,v
retrieving revision 1.62
diff -u -p -r1.62 dired.c
--- dired.c 2 Jun 2013 10:09:21 -   1.62
+++ dired.c 2 Jun 2013 11:23:33 -
@@ -45,6 +45,7 @@ static int d_backpage(int, int);
 static int  d_forwline(int, int);
 static int  d_backline(int, int);
 static int  d_killbuffer_cmd(int, int);
+static int  d_refreshbuffer(int, int);
 static void reaper(int);
 static struct buffer   *refreshbuffer(struct buffer *);
 
@@ -103,7 +104,8 @@ static PF diredc[] = {
d_copy, /* c */
d_del,  /* d */
d_findfile, /* e */
-   d_findfile  /* f */
+   d_findfile, /* f */
+   d_refreshbuffer /* g */
 };
 
 static PF diredn[] = {
@@ -166,7 +168,7 @@ static struct KEYMAPE (7 + NDIRED_XMAPS 
CCHR('Z'), '+', diredcz, (KEYMAP *)  metamap
},
{
-   'c', 'f', diredc, NULL
+   'c', 'g', diredc, NULL
},
{
'n', 'x', diredn, NULL
@@ -649,6 +651,17 @@ int
 d_killbuffer_cmd(int f, int n)
 {
return(killbuffer_cmd(FFRAND, 0));
+}
+
+int
+d_refreshbuffer(int f, int n)
+{
+   struct buffer *bp;
+
+   if ((bp = refreshbuffer(curbp)) == NULL)
+   return (FALSE);
+
+   return (showbuffer(bp, curwp, WFFULL | WFMODE));
 }
 
 struct buffer *
Index: mg.1
===
RCS file: /cvs/src/usr.bin/mg/mg.1,v
retrieving revision 1.83
diff -u -p -r1.83 mg.1
--- mg.12 Jun 2013 10:09:21 -   1.83
+++ mg.12 Jun 2013 11:23:33 -
@@ -941,6 +941,8 @@ dired-do-copy
 dired-flag-file-deletion
 .It e, f and C-m
 dired-find-file
+.It g
+dired-revert
 .It n
 dired-next-line
 .It o
@@ -989,6 +991,8 @@ This function works just like dired, exc
 dired buffer in another window.
 .It dired-previous-line
 Move the cursor to the previous line.
+.It dired-revert
+Refresh the dired buffer.
 .It dired-scroll-down
 Scroll down the dired buffer.
 .It dired-scroll-up



mg(1) 'q' for quit-window in dired mode

2013-06-01 Thread Mark Lumsden
This diff adds the key binding 'q' and function 'quit-window' to mg's
dired mode. Comments/oks? 

mark

Index: buffer.c
===
RCS file: /cvs/src/usr.bin/mg/buffer.c,v
retrieving revision 1.90
diff -u -p -r1.90 buffer.c
--- buffer.c17 Feb 2013 10:30:26 -  1.90
+++ buffer.c1 Jun 2013 15:03:07 -
@@ -124,10 +124,10 @@ poptobuffer(int f, int n)
 
 /*
  * Dispose of a buffer, by name.
- * Ask for the name. Look it up (don't get too
- * upset if it isn't there at all!). Clear the buffer (ask
+ * Ask for the name (unless called by dired mode). Look it up (don't
+ * get too upset if it isn't there at all!). Clear the buffer (ask
  * if the buffer has been changed). Then free the header
- * line and the buffer header. Bound to C-X k.
+ * line and the buffer header. Bound to C-x k.
  */
 /* ARGSUSED */
 int
@@ -136,7 +136,9 @@ killbuffer_cmd(int f, int n)
struct buffer *bp;
charbufn[NBUFN], *bufp;
 
-   if ((bufp = eread(Kill buffer: (default %s) , bufn, NBUFN,
+   if (f  FFRAND) /* dired mode 'q' */
+   bp = curbp;
+   else if ((bufp = eread(Kill buffer: (default %s) , bufn, NBUFN,
EFNUL | EFNEW | EFBUF, curbp-b_bname)) == NULL)
return (ABORT);
else if (bufp[0] == '\0')
Index: dired.c
===
RCS file: /cvs/src/usr.bin/mg/dired.c,v
retrieving revision 1.59
diff -u -p -r1.59 dired.c
--- dired.c 30 May 2013 17:43:43 -  1.59
+++ dired.c 1 Jun 2013 15:03:07 -
@@ -44,6 +44,7 @@ static int d_forwpage(int, int);
 static int  d_backpage(int, int);
 static int  d_forwline(int, int);
 static int  d_backline(int, int);
+static int  d_killbuffer_cmd(int, int);
 static void reaper(int);
 static struct buffer   *refreshbuffer(struct buffer *);
 
@@ -109,7 +110,7 @@ static PF diredn[] = {
d_forwline, /* n */
d_ffotherwindow,/* o */
d_backline, /* p */
-   rescan, /* q */
+   d_killbuffer_cmd,   /* q */
d_rename,   /* r */
rescan, /* s */
rescan, /* t */
@@ -197,6 +198,7 @@ dired_init(void)
funmap_add(d_backpage, dired-scroll-down);
funmap_add(d_forwpage, dired-scroll-up);
funmap_add(d_undel, dired-unflag);
+   funmap_add(d_killbuffer_cmd, quit-window);
maps_add((KEYMAP *)diredmap, dired);
dobindkey(fundamental_map, dired, ^Xd);
 }
@@ -640,6 +642,13 @@ d_create_directory(int f, int n)
return (FALSE);
 
return (showbuffer(bp, curwp, WFFULL | WFMODE));
+}
+
+/* ARGSUSED */
+int
+d_killbuffer_cmd(int f, int n)
+{
+   return(killbuffer_cmd(FFRAND, 0));
 }
 
 struct buffer *
Index: mg.1
===
RCS file: /cvs/src/usr.bin/mg/mg.1,v
retrieving revision 1.80
diff -u -p -r1.80 mg.1
--- mg.11 Jun 2013 14:47:07 -   1.80
+++ mg.11 Jun 2013 15:03:07 -
@@ -946,6 +946,8 @@ dired-next-line
 dired-find-file-other-window
 .It p
 dired-previous-line
+.It q
+dired-previous-line
 .It r
 dired-rename-file
 .It u
@@ -995,6 +997,8 @@ Scroll down the dired buffer.
 Scroll up the dired buffer.
 .It dired-unflag
 Remove the deletion flag for the file on the current line.
+.It quit-window
+Closes the current dired buffer.
 .El
 .Sh CONFIGURATION FILES
 There are two configuration files,



[m...@showcomplex.com: mg(1) 'q' for quit-window in dired mode]

2013-06-01 Thread Mark Lumsden
The man page has an error... it should read:

.It q
quit-window


- Forwarded message from Mark Lumsden m...@showcomplex.com -

Date: Sat, 1 Jun 2013 15:05:16 +
From: Mark Lumsden m...@showcomplex.com
To: tech@openbsd.org
Subject: mg(1) 'q' for quit-window in dired mode
User-Agent: Mutt/1.5.21 (2010-09-15)

This diff adds the key binding 'q' and function 'quit-window' to mg's
dired mode. Comments/oks? 

mark

Index: buffer.c
===
RCS file: /cvs/src/usr.bin/mg/buffer.c,v
retrieving revision 1.90
diff -u -p -r1.90 buffer.c
--- buffer.c17 Feb 2013 10:30:26 -  1.90
+++ buffer.c1 Jun 2013 15:03:07 -
@@ -124,10 +124,10 @@ poptobuffer(int f, int n)
 
 /*
  * Dispose of a buffer, by name.
- * Ask for the name. Look it up (don't get too
- * upset if it isn't there at all!). Clear the buffer (ask
+ * Ask for the name (unless called by dired mode). Look it up (don't
+ * get too upset if it isn't there at all!). Clear the buffer (ask
  * if the buffer has been changed). Then free the header
- * line and the buffer header. Bound to C-X k.
+ * line and the buffer header. Bound to C-x k.
  */
 /* ARGSUSED */
 int
@@ -136,7 +136,9 @@ killbuffer_cmd(int f, int n)
struct buffer *bp;
charbufn[NBUFN], *bufp;
 
-   if ((bufp = eread(Kill buffer: (default %s) , bufn, NBUFN,
+   if (f  FFRAND) /* dired mode 'q' */
+   bp = curbp;
+   else if ((bufp = eread(Kill buffer: (default %s) , bufn, NBUFN,
EFNUL | EFNEW | EFBUF, curbp-b_bname)) == NULL)
return (ABORT);
else if (bufp[0] == '\0')
Index: dired.c
===
RCS file: /cvs/src/usr.bin/mg/dired.c,v
retrieving revision 1.59
diff -u -p -r1.59 dired.c
--- dired.c 30 May 2013 17:43:43 -  1.59
+++ dired.c 1 Jun 2013 15:03:07 -
@@ -44,6 +44,7 @@ static int d_forwpage(int, int);
 static int  d_backpage(int, int);
 static int  d_forwline(int, int);
 static int  d_backline(int, int);
+static int  d_killbuffer_cmd(int, int);
 static void reaper(int);
 static struct buffer   *refreshbuffer(struct buffer *);
 
@@ -109,7 +110,7 @@ static PF diredn[] = {
d_forwline, /* n */
d_ffotherwindow,/* o */
d_backline, /* p */
-   rescan, /* q */
+   d_killbuffer_cmd,   /* q */
d_rename,   /* r */
rescan, /* s */
rescan, /* t */
@@ -197,6 +198,7 @@ dired_init(void)
funmap_add(d_backpage, dired-scroll-down);
funmap_add(d_forwpage, dired-scroll-up);
funmap_add(d_undel, dired-unflag);
+   funmap_add(d_killbuffer_cmd, quit-window);
maps_add((KEYMAP *)diredmap, dired);
dobindkey(fundamental_map, dired, ^Xd);
 }
@@ -640,6 +642,13 @@ d_create_directory(int f, int n)
return (FALSE);
 
return (showbuffer(bp, curwp, WFFULL | WFMODE));
+}
+
+/* ARGSUSED */
+int
+d_killbuffer_cmd(int f, int n)
+{
+   return(killbuffer_cmd(FFRAND, 0));
 }
 
 struct buffer *
Index: mg.1
===
RCS file: /cvs/src/usr.bin/mg/mg.1,v
retrieving revision 1.80
diff -u -p -r1.80 mg.1
--- mg.11 Jun 2013 14:47:07 -   1.80
+++ mg.11 Jun 2013 15:03:07 -
@@ -946,6 +946,8 @@ dired-next-line
 dired-find-file-other-window
 .It p
 dired-previous-line
+.It q
+dired-previous-line
 .It r
 dired-rename-file
 .It u
@@ -995,6 +997,8 @@ Scroll down the dired buffer.
 Scroll up the dired buffer.
 .It dired-unflag
 Remove the deletion flag for the file on the current line.
+.It quit-window
+Closes the current dired buffer.
 .El
 .Sh CONFIGURATION FILES
 There are two configuration files,


- End forwarded message -



mg(1) M-} forward para diff

2013-05-31 Thread Mark Lumsden
A while back, I committed a diff that fixed scrolling backwards by
 paragraph in mg. I thought I would give it a while before writing the
corresponding diff for going forwards, just to make sure there were no
problems with the first diff. 

So here it is. Before you compile this diff, (and if you are using mg)
put your cursor on the very first character of the first paragraph -
an 'A', then do M-} your cursor stops on the 2nd line. In emacs it
would stop on the 5th line. Currently mg stops moving forward when it
finds a new line with a space on the first character, this diff checks
the whole line before determinig if the line is a paragraph break or
not. 

ok?

mark

Index: paragraph.c
===
RCS file: /cvs/src/usr.bin/mg/paragraph.c,v
retrieving revision 1.24
diff -u -p -r1.24 paragraph.c
--- paragraph.c 19 May 2013 10:27:11 -  1.24
+++ paragraph.c 1 Jun 2013 05:40:02 -
@@ -63,37 +63,32 @@ gotobop(int f, int n)
 int
 gotoeop(int f, int n)
 {
+   int col;
+   int nospace = 0;
+
/* the other way... */
if (n  0)
return (gotobop(f, -n));
 
/* for each one asked for */
while (n--  0) {
-   /* Find the first word on/after the current line */
-   curwp-w_doto = 0;
-   while (forwchar(FFRAND, 1)  inword() == 0);
+   while (lforw(curwp-w_dotp) != curbp-b_headp) {
+   col = 0;
+   curwp-w_doto = 0;
 
-   curwp-w_doto = 0;
-   curwp-w_dotp = lforw(curwp-w_dotp);
+   while (col  llength(curwp-w_dotp) 
+   (isspace(lgetc(curwp-w_dotp, col
+   col++;
 
-   /* and scan forword until we hit a NLSP or ... */
-   while (curwp-w_dotp != curbp-b_headp) {
-   if (llength(curwp-w_dotp) 
-   lgetc(curwp-w_dotp, 0) != ' ' 
-   lgetc(curwp-w_dotp, 0) != '.' 
-   lgetc(curwp-w_dotp, 0) != '\t') {
-   curwp-w_dotp = lforw(curwp-w_dotp);
-   curwp-w_dotline++;
+   if (col = llength(curwp-w_dotp)) {
+   if (nospace)
+   break;
} else
-   break;
-   }
-   if (curwp-w_dotp == curbp-b_headp) {
-   /* beyond end of buffer, cleanup time */
-   curwp-w_dotp = lback(curwp-w_dotp);
-   curwp-w_doto = llength(curwp-w_dotp);
-   break;
-   } else
+   nospace = 1;
+
+   curwp-w_dotp = lforw(curwp-w_dotp);
curwp-w_dotline++;
+   }
}
/* force screen update */
curwp-w_rflag |= WFMOVE;



mg(1) visible/audible bell control

2013-05-30 Thread Mark Lumsden
This diff adds the capability to toggle on and off the system bell
within mg via the 'audible-bell' command. It also introduces the
'visible-bell' command: the modeline will flash instead.  However,
both can be used together, if so desired. Comments/oks? 

-lum

Index: Makefile
===
RCS file: /cvs/src/usr.bin/mg/Makefile,v
retrieving revision 1.27
diff -u -r1.27 Makefile
--- Makefile18 Jun 2012 07:13:26 -  1.27
+++ Makefile30 May 2013 18:33:42 -
@@ -15,7 +15,7 @@
 #
 CFLAGS+=-Wall -DFKEYS -DREGEX -DXKEYS
 
-SRCS=  autoexec.c basic.c buffer.c cinfo.c dir.c display.c \
+SRCS=  autoexec.c basic.c bell.c buffer.c cinfo.c dir.c display.c \
echo.c extend.c file.c fileio.c funmap.c help.c kbd.c keymap.c \
line.c macro.c main.c match.c modes.c paragraph.c random.c \
re_search.c region.c search.c spawn.c tty.c ttyio.c ttykbd.c \
Index: basic.c
===
RCS file: /cvs/src/usr.bin/mg/basic.c,v
retrieving revision 1.39
diff -u -r1.39 basic.c
--- basic.c 25 Mar 2013 11:41:44 -  1.39
+++ basic.c 30 May 2013 18:33:42 -
@@ -43,8 +43,10 @@
while (n--) {
if (curwp-w_doto == 0) {
if ((lp = lback(curwp-w_dotp)) == curbp-b_headp) {
-   if (!(f  FFRAND))
+   if (!(f  FFRAND)) {
+   dobeep();
ewprintf(Beginning of buffer);
+   }
return (FALSE);
}
curwp-w_dotp = lp;
@@ -85,8 +87,10 @@
curwp-w_dotp = lforw(curwp-w_dotp);
if (curwp-w_dotp == curbp-b_headp) {
curwp-w_dotp = lback(curwp-w_dotp);
-   if (!(f  FFRAND))
+   if (!(f  FFRAND)) {
+   dobeep();
ewprintf(End of buffer);
+   }
return (FALSE);
}
curwp-w_doto = 0;
@@ -283,7 +287,7 @@
lp = curwp-w_linep;
while (n--)
if ((lp = lforw(lp)) == curbp-b_headp) {
-   ttbeep();
+   dobeep();
ewprintf(End of buffer);
return(TRUE);
}
@@ -332,7 +336,7 @@
lp = lback(lp);
}
if (lp == curwp-w_linep) {
-   ttbeep();
+   dobeep();
ewprintf(Beginning of buffer);
}
curwp-w_linep = lp;
Index: bell.c
===
RCS file: bell.c
diff -N bell.c
--- /dev/null   1 Jan 1970 00:00:00 -
+++ bell.c  30 May 2013 18:33:42 -
@@ -0,0 +1,57 @@
+/* $OpenBSD$   */
+
+/*
+ * This file is in the public domain.
+ *
+ */
+/*
+ * Control how mg communicates with the user.
+ */
+
+#include def.h
+
+void
+bellinit(void)
+{
+   doaudiblebell = 1;
+   dovisiblebell = 0;
+   donebell = 0;
+}
+
+void
+dobeep(void)
+{
+   if (doaudiblebell) {
+   ttbeep();
+   }
+   if (dovisiblebell) {
+   sgarbf = TRUE;
+   update(CNONE);
+   usleep(5);
+   }
+   donebell = 1;
+}
+
+/* ARGSUSED */
+int
+toggleaudiblebell(int f, int n)
+{
+   if (f  FFARG)
+   doaudiblebell = n  0;
+   else
+   doaudiblebell = !doaudiblebell;
+
+   return (TRUE);
+}
+
+/* ARGSUSED */
+int
+togglevisiblebell(int f, int n)
+{
+   if (f  FFARG)
+   dovisiblebell = n  0;
+   else
+   dovisiblebell = !dovisiblebell;
+
+   return (TRUE);
+}
Index: def.h
===
RCS file: /cvs/src/usr.bin/mg/def.h,v
retrieving revision 1.137
diff -u -r1.137 def.h
--- def.h   30 May 2013 04:17:25 -  1.137
+++ def.h   30 May 2013 18:33:42 -
@@ -424,7 +424,7 @@
 intvtresize(int, int, int);
 void   vtinit(void);
 void   vttidy(void);
-void   update(void);
+void   update(int);
 intlinenotoggle(int, int);
 intcolnotoggle(int, int);
 
@@ -681,6 +681,12 @@
 int globalwdtoggle(int, int);
 int compile(int, int);
 
+/* bell.c */
+voidbellinit(void);
+int toggleaudiblebell(int, int);
+int togglevisiblebell(int, int);
+voiddobeep(void);
+
 /*
  * Externals.
  */
@@ -704,6 +710,9 @@
 extern int  tthue;
 extern int  defb_nmodes;
 extern int  defb_flag;
+extern int  doaudiblebell;
+extern int  

mg(1) dired opening ~/

2013-05-29 Thread Mark Lumsden
Currently dired mode doesn't use the adjustname() function early
enough when passed ~. For example typing 'M-x dired', then:

Dired: ~

Doesn't open your home directory. However, with this diff mg behaves
like emacs. 

ok?

mark

Index: dired.c
===
RCS file: /cvs/src/usr.bin/mg/dired.c,v
retrieving revision 1.56
diff -u -p -r1.56 dired.c
--- dired.c 29 May 2013 19:16:48 -  1.56
+++ dired.c 29 May 2013 19:38:33 -
@@ -754,11 +754,6 @@ dired_(char *dname)
int  i;
size_t   len;
 
-   if ((access(dname, R_OK | X_OK)) == -1) {
-   if (errno == EACCES)
-   ewprintf(Permission denied);
-   return (NULL);
-   }
if ((dname = adjustname(dname, FALSE)) == NULL) {
ewprintf(Bad directory name);
return (NULL);
@@ -768,6 +763,11 @@ dired_(char *dname)
if (dname[len - 1] != '/') {
dname[len++] = '/';
dname[len] = '\0';
+   }
+   if ((access(dname, R_OK | X_OK)) == -1) {
+   if (errno == EACCES)
+   ewprintf(Permission denied);
+   return (NULL);
}
if ((bp = findbuffer(dname)) == NULL) {
ewprintf(Could not create buffer);



mg(1) - use more adjustname() in dired

2013-05-29 Thread Mark Lumsden
The dired-copy-file and dired-rename-file commands do not use
adjustname() for the new path. Hence 'M-x dired-copy-file':

Dired: ~/filename

will not work. This diff fixes that behaviour. ok?

mark

Index: dired.c
===
RCS file: /cvs/src/usr.bin/mg/dired.c,v
retrieving revision 1.58
diff -u -p -r1.58 dired.c
--- dired.c 30 May 2013 04:27:18 -  1.58
+++ dired.c 30 May 2013 04:42:38 -
@@ -398,10 +398,11 @@ d_expunge(int f, int n)
 int
 d_copy(int f, int n)
 {
-   charfrname[NFILEN], toname[NFILEN], sname[NFILEN], *bufp;
-   int ret;
-   size_t  off;
-   struct buffer *bp;
+   char frname[NFILEN], toname[NFILEN], sname[NFILEN];
+   char*topath, *bufp;
+   int  ret;
+   size_t   off;
+   struct buffer   *bp;
 
if (d_makename(curwp-w_dotp, frname, sizeof(frname)) != FALSE) {
ewprintf(Not a file);
@@ -419,7 +420,9 @@ d_copy(int f, int n)
return (ABORT);
else if (bufp[0] == '\0')
return (FALSE);
-   ret = (copy(frname, toname) = 0) ? TRUE : FALSE;
+
+   topath = adjustname(toname, TRUE);
+   ret = (copy(frname, topath) = 0) ? TRUE : FALSE;
if (ret != TRUE)
return (ret);
if ((bp = refreshbuffer(curbp)) == NULL)
@@ -431,7 +434,8 @@ d_copy(int f, int n)
 int
 d_rename(int f, int n)
 {
-   char frname[NFILEN], toname[NFILEN], *bufp;
+   char frname[NFILEN], toname[NFILEN];
+   char*topath, *bufp;
int  ret;
size_t   off;
struct buffer   *bp;
@@ -453,7 +457,9 @@ d_rename(int f, int n)
return (ABORT);
else if (bufp[0] == '\0')
return (FALSE);
-   ret = (rename(frname, toname) = 0) ? TRUE : FALSE;
+
+   topath = adjustname(toname, TRUE);
+   ret = (rename(frname, topath) = 0) ? TRUE : FALSE;
if (ret != TRUE)
return (ret);
if ((bp = refreshbuffer(curbp)) == NULL)



mg(1) dired warpdot

2013-05-28 Thread Mark Lumsden
The mg dired commands:

dired-flag-file-deleted
dired-backup-unflag
dired-unflag

behave more like emacs when the cursor stays on the first character of
the file name. ok? 

mark

Index: dired.c
===
RCS file: /cvs/src/usr.bin/mg/dired.c,v
retrieving revision 1.54
diff -u -p -r1.54 dired.c
--- dired.c 28 May 2013 18:35:10 -  1.54
+++ dired.c 28 May 2013 19:09:15 -
@@ -275,8 +275,7 @@ d_del(int f, int n)
curwp-w_dotp = lforw(curwp-w_dotp);
}
curwp-w_rflag |= WFEDIT | WFMOVE;
-   curwp-w_doto = 0;
-   return (TRUE);
+   return (d_warpdot(curwp-w_dotp, curwp-w_doto));
 }
 
 /* ARGSUSED */
@@ -292,8 +291,7 @@ d_undel(int f, int n)
curwp-w_dotp = lforw(curwp-w_dotp);
}
curwp-w_rflag |= WFEDIT | WFMOVE;
-   curwp-w_doto = 0;
-   return (TRUE);
+   return (d_warpdot(curwp-w_dotp, curwp-w_doto));
 }
 
 /* ARGSUSED */
@@ -308,9 +306,8 @@ d_undelbak(int f, int n)
if (lback(curwp-w_dotp) != curbp-b_headp)
curwp-w_dotp = lback(curwp-w_dotp);
}
-   curwp-w_doto = 0;
curwp-w_rflag |= WFEDIT | WFMOVE;
-   return (TRUE);
+   return (d_warpdot(curwp-w_dotp, curwp-w_doto));
 }
 
 /* ARGSUSED */



mg(1) dired buffer refresh

2013-05-27 Thread Mark Lumsden
In mg dired mode, if you execute these commands:

dired-copy-file
dired-rename-file
dired-create-directory

The dired buffer is not refreshed with the updated action. This diff
fixes that. Comments/oks?

-lum

Index: dired.c
===
RCS file: /cvs/src/usr.bin/mg/dired.c,v
retrieving revision 1.52
diff -u -p -r1.52 dired.c
--- dired.c 3 Nov 2012 15:36:03 -   1.52
+++ dired.c 27 May 2013 13:35:09 -
@@ -44,6 +44,7 @@ static int d_backpage(int, int);
 static int  d_forwline(int, int);
 static int  d_backline(int, int);
 static void reaper(int);
+static struct buffer   *refreshbuffer(struct buffer *);
 
 extern struct keymap_s helpmap, cXmap, metamap;
 
@@ -422,7 +423,8 @@ d_copy(int f, int n)
ret = (copy(frname, toname) = 0) ? TRUE : FALSE;
if (ret != TRUE)
return (ret);
-   bp = dired_(curbp-b_fname);
+   if ((bp = refreshbuffer(curbp)) == NULL)
+   return (FALSE);
return (showbuffer(bp, curwp, WFFULL | WFMODE));
 }
 
@@ -455,7 +457,8 @@ d_rename(int f, int n)
ret = (rename(frname, toname) = 0) ? TRUE : FALSE;
if (ret != TRUE)
return (ret);
-   bp = dired_(curbp-b_fname);
+   if ((bp = refreshbuffer(curbp)) == NULL)
+   return (FALSE);
return (showbuffer(bp, curwp, WFFULL | WFMODE));
 }
 
@@ -638,8 +641,28 @@ d_create_directory(int f, int n)
tocreate);
return (FALSE);
}
-   bp = dired_(curbp-b_fname);
+   if ((bp = refreshbuffer(curbp)) == NULL)
+   return (FALSE);
return (showbuffer(bp, curwp, WFFULL | WFMODE));
+}
+
+struct buffer *
+refreshbuffer(struct buffer *bp)
+{
+   char*tmp;
+
+   tmp = strdup(bp-b_fname);
+   killbuffer(bp);
+
+   /* dired_() uses findbuffer() to create new buffer */
+   if ((bp = dired_(tmp)) == NULL) {
+   free(tmp);
+   return (NULL);
+   }
+   free(tmp);
+   curbp = bp;
+
+   return (bp);
 }
 
 static int



mg(1) dired buffer refresh

2013-05-27 Thread Mark Lumsden
In mg dired mode, if you execute these commands:

dired-copy-file
dired-rename-file
dired-create-directory

The dired buffer is not refreshed with the updated action. This diff
fixes that. Comments/oks?

-lum

Index: dired.c
===
RCS file: /cvs/src/usr.bin/mg/dired.c,v
retrieving revision 1.52
diff -u -p -r1.52 dired.c
--- dired.c 3 Nov 2012 15:36:03 -   1.52
+++ dired.c 27 May 2013 13:35:09 -
@@ -44,6 +44,7 @@ static int d_backpage(int, int);
 static int  d_forwline(int, int);
 static int  d_backline(int, int);
 static void reaper(int);
+static struct buffer   *refreshbuffer(struct buffer *);
 
 extern struct keymap_s helpmap, cXmap, metamap;
 
@@ -422,7 +423,8 @@ d_copy(int f, int n)
ret = (copy(frname, toname) = 0) ? TRUE : FALSE;
if (ret != TRUE)
return (ret);
-   bp = dired_(curbp-b_fname);
+   if ((bp = refreshbuffer(curbp)) == NULL)
+   return (FALSE);
return (showbuffer(bp, curwp, WFFULL | WFMODE));
 }
 
@@ -455,7 +457,8 @@ d_rename(int f, int n)
ret = (rename(frname, toname) = 0) ? TRUE : FALSE;
if (ret != TRUE)
return (ret);
-   bp = dired_(curbp-b_fname);
+   if ((bp = refreshbuffer(curbp)) == NULL)
+   return (FALSE);
return (showbuffer(bp, curwp, WFFULL | WFMODE));
 }
 
@@ -638,8 +641,28 @@ d_create_directory(int f, int n)
tocreate);
return (FALSE);
}
-   bp = dired_(curbp-b_fname);
+   if ((bp = refreshbuffer(curbp)) == NULL)
+   return (FALSE);
return (showbuffer(bp, curwp, WFFULL | WFMODE));
+}
+
+struct buffer *
+refreshbuffer(struct buffer *bp)
+{
+   char*tmp;
+
+   tmp = strdup(bp-b_fname);
+   killbuffer(bp);
+
+   /* dired_() uses findbuffer() to create new buffer */
+   if ((bp = dired_(tmp)) == NULL) {
+   free(tmp);
+   return (NULL);
+   }
+   free(tmp);
+   curbp = bp;
+
+   return (bp);
 }
 
 static int



mg(1) dired-create-directory

2013-05-27 Thread Mark Lumsden
dired-create-directory is missing from the function maps.

ok?

-lum

Index: dired.c
===
RCS file: /cvs/src/usr.bin/mg/dired.c,v
retrieving revision 1.52
diff -u -p -r1.52 dired.c
--- dired.c 3 Nov 2012 15:36:03 -   1.52
+++ dired.c 27 May 2013 13:48:01 -
@@ -182,6 +182,7 @@ dired_init(void)
 {
funmap_add(dired, dired);
funmap_add(d_undelbak, dired-backup-unflag);
+   funmap_add(d_create_directory, dired-create-directory);
funmap_add(d_copy, dired-copy-file);
funmap_add(d_expunge, dired-do-deletions);
funmap_add(d_findfile, dired-find-file);



mg.1 dired commands

2013-05-27 Thread Mark Lumsden
I realised the dired commands are not in the mg man page. ok?

-lum

Index: mg.1
===
RCS file: /cvs/src/usr.bin/mg/mg.1,v
retrieving revision 1.76
diff -u -p -r1.76 mg.1
--- mg.122 May 2013 19:23:45 -  1.76
+++ mg.127 May 2013 19:10:45 -
@@ -919,6 +919,43 @@ Unlike emacs, the
 kill buffer consists only
 of the most recent kill.
 It is not a ring.
+.Sh MG DIRED COMMANDS
+Following are a list of the commands specific to dired mode:
+.It dired-backup-unflag
+This function removes the deletion flag from the file listed on
+the current line of the dired buffer, then moves up one line.
+.It dired-create-directory
+Creates a directory.
+.It dired-copy-file
+Copy the file listed on the current line of the dired buffer.
+.It dired-do-deletions
+Deletes the files that have been flagged for deletion.
+.It dired-find-file
+Opens the file in the current line of the dired buffer.
+If the cursor is on a directory it will be opened in dired mode. 
+.It dired-find-file-other-window
+Opens the file on the current line of the dired buffer in a
+different window.
+.It dired-flag-file-deleted
+Flag the file listed on the current line for deletion.
+This is indicated in the buffer by putting a D at the left margin.
+No files are actually deleted until the function dired-do-deletions
+is executed.
+.It dired-next-line
+Moves the cursor to the next line.
+.It dired-other-window
+This function works just like dired, except that it puts the
+dired buffer in the other window.
+.It dired-previous-line
+Move the cursor to the previous line.
+.It dired-rename-file
+Renames the file listed on the current line of the dired buffer.
+.It dired-scroll-down
+Scroll down the dired buffer.
+.It dired-scroll-up
+Scroll up the dired buffer.
+.It dired-unflag
+Remove the deletion flag for the file on the current line.
 .El
 .Sh CONFIGURATION FILES
 There are two configuration files,



Re: mg(1): shell-command

2013-05-22 Thread Mark Lumsden
To make the shell-command-on-region and this command behave
like that requires another diff.

mark

On Wed, May 22, 2013 at 09:32:45AM +0200, Jasper Lievisse Adriaanse wrote:
 On Tue, May 21, 2013 at 07:54:31PM +, Mark Lumsden wrote:
  This diff modifies the shell-command-on-region function and gives us
  shell-command. It makes getting output from other commands into mg
  really easy. Comments/oks?
  
  -lum
 
 It seems Emacs doesn't split the window if the output from the command is only
 a single line (like 'date'), which is behaviour I quite like if you want to
 check something small.
 
  Index: def.h
  ===
  RCS file: /cvs/src/usr.bin/mg/def.h,v
  retrieving revision 1.135
  diff -u -p -r1.135 def.h
  --- def.h   25 Mar 2013 11:41:44 -  1.135
  +++ def.h   21 May 2013 19:46:38 -
  @@ -592,6 +592,7 @@ int  region_get_data(struct region *, c
   voidregion_put_data(const char *, int);
   int markbuffer(int, int);
   int piperegion(int, int);
  +int shellcommand(int, int);
   int pipeio(const char * const, char * const[], char * 
  const, int,
   struct buffer *);
   
  Index: funmap.c
  ===
  RCS file: /cvs/src/usr.bin/mg/funmap.c,v
  retrieving revision 1.45
  diff -u -p -r1.45 funmap.c
  --- funmap.c27 Dec 2012 18:51:52 -  1.45
  +++ funmap.c21 May 2013 19:46:38 -
  @@ -179,6 +179,7 @@ static struct funmap functnames[] = {
  {setfillcol, set-fill-column,},
  {setmark, set-mark-command,},
  {setprefix, set-prefix-string,},
  +   {shellcommand, shell-command,},
  {piperegion, shell-command-on-region,},
  {shrinkwind, shrink-window,},
   #ifdef NOTAB
  Index: keymap.c
  ===
  RCS file: /cvs/src/usr.bin/mg/keymap.c,v
  retrieving revision 1.50
  diff -u -p -r1.50 keymap.c
  --- keymap.c7 Jun 2012 15:15:04 -   1.50
  +++ keymap.c21 May 2013 19:46:38 -
  @@ -217,8 +217,9 @@ static PF metacV[] = {
  pagenext/* ^V */
   };
   
  -static PF metasp[] = {
  -   justone /* space */
  +static PF metaspex[] = {
  +   justone,/* space */
  +   shellcommand/* ! */
   };
   
   static PF metapct[] = {
  @@ -317,7 +318,7 @@ struct KEYMAPE (8 + IMAPEXT) metamap = {
  CCHR('V'), CCHR('V'), metacV, NULL
  },
  {
  -   ' ', ' ', metasp, NULL
  +   ' ', '!', metaspex, NULL
  },
  {
  '%', '%', metapct, NULL
  Index: mg.1
  ===
  RCS file: /cvs/src/usr.bin/mg/mg.1,v
  retrieving revision 1.75
  diff -u -p -r1.75 mg.1
  --- mg.128 Dec 2012 16:12:50 -  1.75
  +++ mg.121 May 2013 19:46:38 -
  @@ -268,6 +268,8 @@ suspend-emacs
   scroll-other-window
   .It M-SPC
   just-one-space
  +.It M-!
  +shell-command
   .It M-.
   find-tag
   .It M-*
  @@ -835,6 +837,8 @@ Used by auto-fill-mode.
   Sets the mark in the current window to the current dot location.
   .It set-prefix-string
   Sets the prefix string to be used by the 'prefix-region' command.
  +.It shell-command
  +Execute external command from mini-buffer.
   .It shell-command-on-region
   Provide the text in region to the shell command as input.
   .It shrink-window
  Index: region.c
  ===
  RCS file: /cvs/src/usr.bin/mg/region.c,v
  retrieving revision 1.32
  diff -u -p -r1.32 region.c
  --- region.c27 Dec 2012 18:49:59 -  1.32
  +++ region.c21 May 2013 19:46:38 -
  @@ -28,6 +28,7 @@ staticint iomux(int, char * const, int,
   static int preadin(int, struct buffer *);
   static voidpwriteout(int, char **, int *);
   static int setsize(struct region *, RSIZE);
  +static int shellcmdoutput(char * const[], char * const, int);
   
   /*
* Kill the region.  Ask getregion to figure out the bounds of the 
  region.
  @@ -406,9 +407,8 @@ int
   piperegion(int f, int n)
   {
  struct region region;
  -   struct buffer *bp;
  -   int len, ret;
  -   char *cmd, cmdbuf[NFILEN], *shellp, *text;
  +   int len;
  +   char *cmd, cmdbuf[NFILEN], *text;
  char *argv[] = {sh, -c, (char *) NULL, (char *) NULL};
   
  /* C-u M-| is not supported yet */
  @@ -436,6 +436,51 @@ piperegion(int f, int n)
  return (FALSE);
  }
   
  +   region_get_data(region, text, len);
  +
  +   return shellcmdoutput(argv, text, len);
  +}
  +
  +/*
  + * Get command from mini-buffer and execute externally.
  + */
  +/*ARGSUSED */
  +int
  +shellcommand(int f, int n)
  +{
  +
  +   int len;
  +   char *cmd

Re: mg(1): shell-command

2013-05-22 Thread Mark Lumsden
I am glad to say, 3 of you are on your toes today. 

I sent the wrong diff, and to be honest I wasn't sure if any
one would notice.

Gold Stars to you all


On Wed, May 22, 2013 at 09:07:56AM +, Florian Obser wrote:
 On Tue, May 21, 2013 at 07:54:31PM +, Mark Lumsden wrote:
  This diff modifies the shell-command-on-region function and gives us
  shell-command. It makes getting output from other commands into mg
  really easy. Comments/oks?
  
  -lum
  
  Index: def.h
  ===
  RCS file: /cvs/src/usr.bin/mg/def.h,v
  retrieving revision 1.135
  diff -u -p -r1.135 def.h
  --- def.h   25 Mar 2013 11:41:44 -  1.135
  +++ def.h   21 May 2013 19:46:38 -
  @@ -592,6 +592,7 @@ int  region_get_data(struct region *, c
   voidregion_put_data(const char *, int);
   int markbuffer(int, int);
   int piperegion(int, int);
  +int shellcommand(int, int);
   int pipeio(const char * const, char * const[], char * 
  const, int,
   struct buffer *);
   
  Index: funmap.c
  ===
  RCS file: /cvs/src/usr.bin/mg/funmap.c,v
  retrieving revision 1.45
  diff -u -p -r1.45 funmap.c
  --- funmap.c27 Dec 2012 18:51:52 -  1.45
  +++ funmap.c21 May 2013 19:46:38 -
  @@ -179,6 +179,7 @@ static struct funmap functnames[] = {
  {setfillcol, set-fill-column,},
  {setmark, set-mark-command,},
  {setprefix, set-prefix-string,},
  +   {shellcommand, shell-command,},
  {piperegion, shell-command-on-region,},
  {shrinkwind, shrink-window,},
   #ifdef NOTAB
  Index: keymap.c
  ===
  RCS file: /cvs/src/usr.bin/mg/keymap.c,v
  retrieving revision 1.50
  diff -u -p -r1.50 keymap.c
  --- keymap.c7 Jun 2012 15:15:04 -   1.50
  +++ keymap.c21 May 2013 19:46:38 -
  @@ -217,8 +217,9 @@ static PF metacV[] = {
  pagenext/* ^V */
   };
   
  -static PF metasp[] = {
  -   justone /* space */
  +static PF metaspex[] = {
  +   justone,/* space */
  +   shellcommand/* ! */
   };
   
   static PF metapct[] = {
  @@ -317,7 +318,7 @@ struct KEYMAPE (8 + IMAPEXT) metamap = {
  CCHR('V'), CCHR('V'), metacV, NULL
  },
  {
  -   ' ', ' ', metasp, NULL
  +   ' ', '!', metaspex, NULL
  },
  {
  '%', '%', metapct, NULL
  Index: mg.1
  ===
  RCS file: /cvs/src/usr.bin/mg/mg.1,v
  retrieving revision 1.75
  diff -u -p -r1.75 mg.1
  --- mg.128 Dec 2012 16:12:50 -  1.75
  +++ mg.121 May 2013 19:46:38 -
  @@ -268,6 +268,8 @@ suspend-emacs
   scroll-other-window
   .It M-SPC
   just-one-space
  +.It M-!
  +shell-command
   .It M-.
   find-tag
   .It M-*
  @@ -835,6 +837,8 @@ Used by auto-fill-mode.
   Sets the mark in the current window to the current dot location.
   .It set-prefix-string
   Sets the prefix string to be used by the 'prefix-region' command.
  +.It shell-command
  +Execute external command from mini-buffer.
   .It shell-command-on-region
   Provide the text in region to the shell command as input.
   .It shrink-window
  Index: region.c
  ===
  RCS file: /cvs/src/usr.bin/mg/region.c,v
  retrieving revision 1.32
  diff -u -p -r1.32 region.c
  --- region.c27 Dec 2012 18:49:59 -  1.32
  +++ region.c21 May 2013 19:46:38 -
  @@ -28,6 +28,7 @@ staticint iomux(int, char * const, int,
   static int preadin(int, struct buffer *);
   static voidpwriteout(int, char **, int *);
   static int setsize(struct region *, RSIZE);
  +static int shellcmdoutput(char * const[], char * const, int);
   
   /*
* Kill the region.  Ask getregion to figure out the bounds of the 
  region.
  @@ -406,9 +407,8 @@ int
   piperegion(int f, int n)
   {
  struct region region;
  -   struct buffer *bp;
  -   int len, ret;
  -   char *cmd, cmdbuf[NFILEN], *shellp, *text;
  +   int len;
  +   char *cmd, cmdbuf[NFILEN], *text;
  char *argv[] = {sh, -c, (char *) NULL, (char *) NULL};
   
  /* C-u M-| is not supported yet */
  @@ -436,6 +436,51 @@ piperegion(int f, int n)
  return (FALSE);
  }
   
  +   region_get_data(region, text, len);
  +
  +   return shellcmdoutput(argv, text, len);
  +}
  +
  +/*
  + * Get command from mini-buffer and execute externally.
  + */
  +/*ARGSUSED */
  +int
  +shellcommand(int f, int n)
  +{
  +
  +   int len;
  +   char *cmd, cmdbuf[NFILEN], *text;
 
 you don't need len and *text
 
  +   char *argv[] = {sh, -c, (char *) NULL, (char *) NULL

mg(1): shell-command

2013-05-21 Thread Mark Lumsden
This diff modifies the shell-command-on-region function and gives us
shell-command. It makes getting output from other commands into mg
really easy. Comments/oks?

-lum

Index: def.h
===
RCS file: /cvs/src/usr.bin/mg/def.h,v
retrieving revision 1.135
diff -u -p -r1.135 def.h
--- def.h   25 Mar 2013 11:41:44 -  1.135
+++ def.h   21 May 2013 19:46:38 -
@@ -592,6 +592,7 @@ int  region_get_data(struct region *, c
 voidregion_put_data(const char *, int);
 int markbuffer(int, int);
 int piperegion(int, int);
+int shellcommand(int, int);
 int pipeio(const char * const, char * const[], char * const, int,
 struct buffer *);
 
Index: funmap.c
===
RCS file: /cvs/src/usr.bin/mg/funmap.c,v
retrieving revision 1.45
diff -u -p -r1.45 funmap.c
--- funmap.c27 Dec 2012 18:51:52 -  1.45
+++ funmap.c21 May 2013 19:46:38 -
@@ -179,6 +179,7 @@ static struct funmap functnames[] = {
{setfillcol, set-fill-column,},
{setmark, set-mark-command,},
{setprefix, set-prefix-string,},
+   {shellcommand, shell-command,},
{piperegion, shell-command-on-region,},
{shrinkwind, shrink-window,},
 #ifdef NOTAB
Index: keymap.c
===
RCS file: /cvs/src/usr.bin/mg/keymap.c,v
retrieving revision 1.50
diff -u -p -r1.50 keymap.c
--- keymap.c7 Jun 2012 15:15:04 -   1.50
+++ keymap.c21 May 2013 19:46:38 -
@@ -217,8 +217,9 @@ static PF metacV[] = {
pagenext/* ^V */
 };
 
-static PF metasp[] = {
-   justone /* space */
+static PF metaspex[] = {
+   justone,/* space */
+   shellcommand/* ! */
 };
 
 static PF metapct[] = {
@@ -317,7 +318,7 @@ struct KEYMAPE (8 + IMAPEXT) metamap = {
CCHR('V'), CCHR('V'), metacV, NULL
},
{
-   ' ', ' ', metasp, NULL
+   ' ', '!', metaspex, NULL
},
{
'%', '%', metapct, NULL
Index: mg.1
===
RCS file: /cvs/src/usr.bin/mg/mg.1,v
retrieving revision 1.75
diff -u -p -r1.75 mg.1
--- mg.128 Dec 2012 16:12:50 -  1.75
+++ mg.121 May 2013 19:46:38 -
@@ -268,6 +268,8 @@ suspend-emacs
 scroll-other-window
 .It M-SPC
 just-one-space
+.It M-!
+shell-command
 .It M-.
 find-tag
 .It M-*
@@ -835,6 +837,8 @@ Used by auto-fill-mode.
 Sets the mark in the current window to the current dot location.
 .It set-prefix-string
 Sets the prefix string to be used by the 'prefix-region' command.
+.It shell-command
+Execute external command from mini-buffer.
 .It shell-command-on-region
 Provide the text in region to the shell command as input.
 .It shrink-window
Index: region.c
===
RCS file: /cvs/src/usr.bin/mg/region.c,v
retrieving revision 1.32
diff -u -p -r1.32 region.c
--- region.c27 Dec 2012 18:49:59 -  1.32
+++ region.c21 May 2013 19:46:38 -
@@ -28,6 +28,7 @@ staticint iomux(int, char * const, int,
 static int preadin(int, struct buffer *);
 static voidpwriteout(int, char **, int *);
 static int setsize(struct region *, RSIZE);
+static int shellcmdoutput(char * const[], char * const, int);
 
 /*
  * Kill the region.  Ask getregion to figure out the bounds of the region.
@@ -406,9 +407,8 @@ int
 piperegion(int f, int n)
 {
struct region region;
-   struct buffer *bp;
-   int len, ret;
-   char *cmd, cmdbuf[NFILEN], *shellp, *text;
+   int len;
+   char *cmd, cmdbuf[NFILEN], *text;
char *argv[] = {sh, -c, (char *) NULL, (char *) NULL};
 
/* C-u M-| is not supported yet */
@@ -436,6 +436,51 @@ piperegion(int f, int n)
return (FALSE);
}
 
+   region_get_data(region, text, len);
+
+   return shellcmdoutput(argv, text, len);
+}
+
+/*
+ * Get command from mini-buffer and execute externally.
+ */
+/*ARGSUSED */
+int
+shellcommand(int f, int n)
+{
+
+   int len;
+   char *cmd, cmdbuf[NFILEN], *text;
+   char *argv[] = {sh, -c, (char *) NULL, (char *) NULL};
+
+   if (n  1)
+   return (ABORT);
+
+   if ((cmd = eread(Shell command: , cmdbuf, sizeof(cmdbuf),
+   EFNEW | EFCR)) == NULL || (cmd[0] == '\0'))
+   return (ABORT);
+
+   argv[2] = cmd;
+
+   len = strlen(cmd);
+
+   if ((text = malloc(len + 1)) == NULL) {
+   ewprintf(Cannot allocate memory.);
+   return (FALSE);
+   }
+
+   return shellcmdoutput(argv, NULL, 0);
+}
+
+
+int
+shellcmdoutput(char* const argv[], char* const text, 

adduser default blowfish rounds

2013-05-13 Thread Mark Lumsden
Shouldn't the default rounds for blowfish in adduser.perl be the same
as login.conf? ok? 

mark

Index: adduser.perl
===
RCS file: /cvs/src/usr.sbin/adduser/adduser.perl,v
retrieving revision 1.58
diff -u -p -u -p -r1.58 adduser.perl
--- adduser.perl22 Sep 2011 10:59:23 -  1.58
+++ adduser.perl12 May 2013 20:09:47 -
@@ -973,12 +973,12 @@ sub salt {
 $salt = ;
 } elsif ($encryptionmethod =~ /^blowfish/ ) {
 ($encryptionmethod, $salt) = split(/\,/, $encryptionmethod);
-   $salt = 7 unless $salt; # default rounds if unspecified
+   $salt = 6 unless $salt; # default rounds if unspecified
 } else {
 warn $encryptionmethod encryption method invalid\n if ($verbose  0);
-   warn Falling back to blowfish,7...\n if ($verbose  0);
+   warn Falling back to blowfish,6...\n if ($verbose  0);
$encryptionmethod = blowfish;
-   $salt = 7;
+   $salt = 6;
 }

 warn Salt is: $salt\n if $verbose  1;



Re: adduser default blowfish rounds

2013-05-13 Thread Mark Lumsden
On Mon, May 13, 2013 at 08:24:43PM +0100, Stuart Henderson wrote:
 On 2013/05/13 18:35, Mark Lumsden wrote:
  Shouldn't the default rounds for blowfish in adduser.perl be the same
  as login.conf? ok? 
  
  mark
  
  Index: adduser.perl
  ===
  RCS file: /cvs/src/usr.sbin/adduser/adduser.perl,v
  retrieving revision 1.58
  diff -u -p -u -p -r1.58 adduser.perl
  --- adduser.perl22 Sep 2011 10:59:23 -  1.58
  +++ adduser.perl12 May 2013 20:09:47 -
  @@ -973,12 +973,12 @@ sub salt {
   $salt = ;
   } elsif ($encryptionmethod =~ /^blowfish/ ) {
   ($encryptionmethod, $salt) = split(/\,/, $encryptionmethod);
  -   $salt = 7 unless $salt; # default rounds if unspecified
  +   $salt = 6 unless $salt; # default rounds if unspecified
   } else {
   warn $encryptionmethod encryption method invalid\n if ($verbose 
   0);
  -   warn Falling back to blowfish,7...\n if ($verbose  0);
  +   warn Falling back to blowfish,6...\n if ($verbose  0);
  $encryptionmethod = blowfish;
  -   $salt = 7;
  +   $salt = 6;
   }
  
   warn Salt is: $salt\n if $verbose  1;
  
 
 The default number of rounds in login.conf was set to 6 in 2001 when the
 1.4GHz p3 xeon was a pretty decent cpu - this number needs to go up, not down.
 

I agree. tedu suggest 9 for the number of user rounds and 11 for
root back in 2010. Are these numbers reasonable on most archs?



mg(1) M-{} line number fix

2013-02-14 Thread Mark Lumsden
Fix forward-paragraph and backward-paragraph's handling of line
numbers. 

ok?

-lum

Index: paragraph.c
===
RCS file: /cvs/src/usr.bin/mg/paragraph.c,v
retrieving revision 1.22
diff -u -p -r1.22 paragraph.c
--- paragraph.c 29 Nov 2011 05:59:54 -  1.22
+++ paragraph.c 14 Feb 2013 20:35:18 -
@@ -41,9 +41,10 @@ gotobop(int f, int n)
if (llength(lback(curwp-w_dotp)) 
lgetc(curwp-w_dotp, 0) != ' ' 
lgetc(curwp-w_dotp, 0) != '.' 
-   lgetc(curwp-w_dotp, 0) != '\t')
+   lgetc(curwp-w_dotp, 0) != '\t') {
curwp-w_dotp = lback(curwp-w_dotp);
-   else {
+   curwp-w_dotline--;
+   } else {
if (llength(lback(curwp-w_dotp)) 
lgetc(curwp-w_dotp, 0) == '.') {
curwp-w_dotp = lforw(curwp-w_dotp);
@@ -56,6 +57,7 @@ gotobop(int f, int n)
lback(curwp-w_dotp);
curwp-w_doto =
llength(curwp-w_dotp);
+   curwp-w_dotline--;
}
}
break;
@@ -93,9 +95,10 @@ gotoeop(int f, int n)
if (llength(curwp-w_dotp) 
lgetc(curwp-w_dotp, 0) != ' ' 
lgetc(curwp-w_dotp, 0) != '.' 
-   lgetc(curwp-w_dotp, 0) != '\t')
+   lgetc(curwp-w_dotp, 0) != '\t') {
curwp-w_dotp = lforw(curwp-w_dotp);
-   else
+   curwp-w_dotline++;
+   } else
break;
}
if (curwp-w_dotp == curbp-b_headp) {
@@ -103,7 +106,8 @@ gotoeop(int f, int n)
curwp-w_dotp = lback(curwp-w_dotp);
curwp-w_doto = llength(curwp-w_dotp);
break;
-   }
+   } else
+   curwp-w_dotline++;
}
/* force screen update */
curwp-w_rflag |= WFMOVE;



Re: (Fwd) last(1) nit

2013-02-10 Thread Mark Lumsden
Printing just the file name (as opposed to the full path) is 
how NetBSD and linux behave. FreeBSD has the same behaviour as
OpenBSD. I'd follow the first 2. Any objections?

-lum

Might I suggest using basename()?

--- last.c.orig 2009-10-27 23:59:39.0 +
+++ last.c  2013-02-09 01:43:04.709416732 +
@@ -36,6 +36,7 @@
 #include ctype.h
 #include err.h
 #include fcntl.h
+#include libgen.h
 #include paths.h
 #include signal.h
 #include stdio.h
@@ -407,7 +408,7 @@
asctime(gmtime(total))+11);
}
ct = ctime(buf[0].ut_time);
-   printf(\nwtmp begins %10.10s %*.*s %4.4s\n, ct, timesize, timesize,
+   printf(\n%s begins %10.10s %*.*s %4.4s\n, basename(file),
ct, timesize, timesize,
ct + 11, ct + 20);
 }



lost user error message

2012-08-30 Thread Mark Lumsden
There is an check when closing mg via C-x C-c, that if a file name is
too long, the user should receive an error message Error: filename
too long!, however, currently that message gets lost due to that
check returning ABORT.  This diff changes the return value to UERROR
which allows the message to be shown. 

ok/comments?

-lum

Index: buffer.c
===
RCS file: /cvs/src/usr.bin/mg/buffer.c,v
retrieving revision 1.80
diff -u -p -r1.80 buffer.c
--- buffer.c30 Aug 2012 06:25:30 -  1.80
+++ buffer.c30 Aug 2012 20:59:10 -
@@ -459,7 +459,7 @@ anycb(int f)
bp-b_fname);
if (ret  0 || ret = sizeof(pbuf)) {
ewprintf(Error: filename too long!);
-   return (ABORT);
+   return (UERROR);
}
if ((f == TRUE || (save = eyorn(pbuf)) == TRUE) 
(save2 = buffsave(bp)) == TRUE) {
Index: def.h
===
RCS file: /cvs/src/usr.bin/mg/def.h,v
retrieving revision 1.124
diff -u -p -r1.124 def.h
--- def.h   14 Jun 2012 17:21:22 -  1.124
+++ def.h   30 Aug 2012 20:59:10 -
@@ -36,6 +36,7 @@ typedef int   (*PF)(int, int);/* generall
 #define FALSE  0   /* False, no, bad, etc.  */
 #define TRUE   1   /* True, yes, good, etc. */
 #define ABORT  2   /* Death, ^G, abort, etc.*/
+#define UERROR 3   /* User Error.   */
 
 #define KCLEAR 2   /* clear echo area   */
 
Index: main.c
===
RCS file: /cvs/src/usr.bin/mg/main.c,v
retrieving revision 1.68
diff -u -p -r1.68 main.c
--- main.c  30 Aug 2012 06:09:12 -  1.68
+++ main.c  30 Aug 2012 20:59:10 -
@@ -224,7 +224,7 @@ quit(int f, int n)
 
if ((s = anycb(FALSE)) == ABORT)
return (ABORT);
-   if (s == FIOERR)
+   if (s == FIOERR || s == UERROR)
return (FALSE);
if (s == FALSE
|| eyesno(Modified buffers exist; really exit) == TRUE) {



mg(1) - closing buffer behaviour

2012-08-29 Thread Mark Lumsden
If you C-x C-c out of emacs and there are unsaved buffers, emacs asks
if you want to save them (mg behaves the same). If there is a write
error (permissions or non-existant parent directory) emacs stops
exiting.  This allows the user to decide what to do with these
buffers. In mg, the contents of these buffers are lost while mg
continues to exit. 

This diff bring mg more into line with emacs. ok?

-lum

Index: buffer.c
===
RCS file: /cvs/src/usr.bin/mg/buffer.c,v
retrieving revision 1.78
diff -u -p -r1.78 buffer.c
--- buffer.c14 Mar 2012 13:56:35 -  1.78
+++ buffer.c28 Aug 2012 14:54:26 -
@@ -449,7 +449,7 @@ int
 anycb(int f)
 {
struct buffer   *bp;
-   int  s = FALSE, save = FALSE, ret;
+   int  s = FALSE, save = FALSE, save2 = FALSE, ret;
char pbuf[NFILEN + 11];
 
for (bp = bheadp; bp != NULL; bp = bp-b_bufp) {
@@ -462,11 +462,14 @@ anycb(int f)
return (ABORT);
}
if ((f == TRUE || (save = eyorn(pbuf)) == TRUE) 
-   buffsave(bp) == TRUE) {
+   (save2 = buffsave(bp)) == TRUE) {
bp-b_flag = ~BFCHG;
upmodes(bp);
-   } else
+   } else {
+   if (save2 == FIOERR)
+   return (save2);
s = TRUE;
+   }
if (save == ABORT)
return (save);
save = TRUE;
Index: file.c
===
RCS file: /cvs/src/usr.bin/mg/file.c,v
retrieving revision 1.82
diff -u -p -r1.82 file.c
--- file.c  28 Aug 2012 11:37:49 -  1.82
+++ file.c  28 Aug 2012 14:54:26 -
@@ -662,8 +662,23 @@ makebkfile(int f, int n)
 int
 writeout(FILE ** ffp, struct buffer *bp, char *fn)
 {
+   struct stat statbuf;
int  s;
+   char*dp;
 
+   dp = dirname(fn);
+
+   if (stat(fn, statbuf) == -1  errno == ENOENT) {
+   if (access(dp, W_OK)  errno == EACCES) {
+   ewprintf(Directory %s%s write-protected, dp,
+   (dp[0] == '/'  dp[1] == '\0') ?  : /);
+   return (FIOERR);
+   } else if (errno == ENOENT) {
+ewprintf(%s%s: no such directory, dp,
+(dp[0] == '/'  dp[1] == '\0') ?  : /);
+   return (FIOERR);
+   }
+}
/* open writes message */
if ((s = ffwopen(ffp, fn, bp)) != FIOSUC)
return (FALSE);
Index: main.c
===
RCS file: /cvs/src/usr.bin/mg/main.c,v
retrieving revision 1.67
diff -u -p -r1.67 main.c
--- main.c  29 May 2012 06:08:48 -  1.67
+++ main.c  28 Aug 2012 14:54:26 -
@@ -224,6 +224,8 @@ quit(int f, int n)
 
if ((s = anycb(FALSE)) == ABORT)
return (ABORT);
+   if (s == FIOERR)
+   return (FALSE);
if (s == FALSE
|| eyesno(Modified buffers exist; really exit) == TRUE) {
vttidy();



Re: tinyscheme + mg

2012-06-28 Thread Mark Lumsden
 Here is an updated diff for mg with tinyscheme integration. It's based on
 tedu's original diff with various tweaks and changes. For those worried about
 mg being too bloated, rest assured, it's still small and lean and a big part
 smaller than vi ;-)
 It's not fully possible to turn mg into your mail client, but I'd like to 
 commit
 this diff and work on it futher in tree (not the mail-client thing, that would
 bloat mg and that's far from desired).
 
 Includes some fixes by lum@ and Sunil Nimmagadda too.
 
 Diff is also at http://crappydiffs.org/tinyschemg.diff


I would appreciate some feedback on the inclusion of this diff in mg
since I am unlikely to use tinyscheme myself but can see why others
would like it added. Are there are strong feelings about it either
way? 

-lum



Re: tinyscheme + mg

2012-06-28 Thread Mark Lumsden
 I'm all for adding support for scripting into mg, though I would be tempted
 to rip out all nonessential functionality first (ng? ;) and add it back via
 the scripting language. I would think the goal should be to make mg
 significantly *smaller* any such change
 

Could you clarify what you mean by non-essential functionality?

mark



Re: tinyscheme + mg

2012-06-28 Thread Mark Lumsden
  I'd be a lot happier voicing an opinion in support of something like this
  if I also saw diffs and interest in *using* them
  to extend functionality later or replace some things easier to do with
  scheme to make the code simpler - something kjell was alluding to.
 
 I think we can work towards that, but there's a bit of chicken and egg
 problem here.  I'm not inclined to do a lot of work if the answer in
 two months is going to be oh, sorry, perl would have been cooler.
 The diff will only get larger from here.
 
  A promise of this is bigger and bloated now but will be really cool in the
  future isn't so good if the people putting it in
  see getting scheme integration in as the goal - otherwise, congrats, you've
 
 Integration is one of the goals.  I can't predict what extensions you
 may want to write.  I mean, mg already reads a .mg file.  If we knew
 what people were going to put in their .mg files, we could just hard
 code it in the program and cut out the startup file bloat.
 
 That said, some concrete examples would help, both to make sure we're
 building something useful and to demonstrate that it is useful. Why do
 people still use emacs and not mg? For text editing not usenet
 browsing or whatever.
 

+1 to somebody providing concrete examples.



mg - end-of-buffer diff

2012-06-15 Thread Mark Lumsden
Currently, if you are at the start of a buffer that is longer than the
window and press M-, you will move to the end of the buffer. There is
a difference between mg and emacs' behaviour though. In emacs, your
cursor will be placed at the bottom of the window (minus 3 lines)
which means most of the window above is displaying buffer contents,
while mg places the cursor in the middle of the window only allowing
half the screen to display buffer contents. This diff makes mg behave
the same as emacs. 

ok?

-lum

Index: basic.c
===
RCS file: /cvs/src/usr.bin/mg/basic.c,v
retrieving revision 1.36
diff -u -p -r1.36 basic.c
--- basic.c 8 Jun 2012 21:21:57 -   1.36
+++ basic.c 16 Jun 2012 03:03:54 -
@@ -115,17 +115,30 @@ gotobob(int f, int n)
 }
 
 /*
- * Go to the end of the buffer.
- * Setting WFFULL is conservative, but
- * almost always the case.
+ * Go to the end of the buffer. Leave dot 3 lines from the bottom of the
+ * window if buffer length is longer than window length; same as emacs.
+ * Setting WFFULL is conservative, but almost always the case.
  */
 int
 gotoeob(int f, int n)
 {
+   struct line *lp;
+   
(void) setmark(f, n);
curwp-w_dotp = blastlp(curbp);
curwp-w_doto = llength(curwp-w_dotp);
curwp-w_dotline = curwp-w_bufp-b_lines;
+
+   lp = curwp-w_dotp;
+   n = curwp-w_ntrows - 3;
+
+   if (n  curwp-w_bufp-b_lines  n = 3) {
+   while (n--)
+   curwp-w_dotp = lback(curwp-w_dotp);
+
+   curwp-w_linep = curwp-w_dotp;
+   curwp-w_dotp = lp;
+   }
curwp-w_rflag |= WFFULL;
return (TRUE);
 }



mg - another ~file bug

2012-06-14 Thread Mark Lumsden
Currently, in mg, if you try to open a file that doesn't exist and has
a name longer than LOGIN_NAME_MAX and also has a tilde at the front
e.g. 

  $ mg ~01234567890123456789012345678901

you will receive a msg:

Login name too long

Since the filename cannot be a user name (it is too long), mg should
open up a new buffer with the file name as the buffer name. This diff
makes mg behave like that which also mimics the behaviour of emacs. 

As you can see I have put all the relevant code in a function, the
fix concerns the lines following:

+   if (ulen = sizeof(user)) {

ok?

-lum

Index: fileio.c
===
RCS file: /cvs/src/usr.bin/mg/fileio.c,v
retrieving revision 1.91
diff -u -p -r1.91 fileio.c
--- fileio.c14 Jun 2012 17:21:22 -  1.91
+++ fileio.c14 Jun 2012 17:56:42 -
@@ -24,6 +24,7 @@
 
 static char *bkuplocation(const char *);
 static int   bkupleavetmp(const char *);
+char   *expandtilde(const char *);
 
 static char *bkupdir;
 static int   leavetmp = 0; /* 1 = leave any '~' files in tmp dir */  
@@ -281,13 +282,9 @@ fbackupfile(const char *fn)
 char *
 adjustname(const char *fn, int slashslash)
 {
-   struct stat  statbuf; 
static char  fnb[MAXPATHLEN];
const char  *cp, *ep = NULL;
-   char user[LOGIN_NAME_MAX], path[MAXPATHLEN];
-   size_t   ulen, plen;
-
-   path[0] = '\0';
+   char*path;
 
if (slashslash == TRUE) {
cp = fn + strlen(fn) - 1;
@@ -302,50 +299,8 @@ adjustname(const char *fn, int slashslas
ep = NULL;
}
}
-
-   /* 
-* Next, expand file names beginning with '~', if appropriate:
-*   1, if ./~fn exists, continue without expanding tilde.
-*   2, otherwise, if username 'fn' exists, expand tilde with home
-*  directory path.
-*   3, otherwise, continue and create new buffer called ~fn.
-*/
-   if (fn[0] == '~'  stat(fn, statbuf) != 0) {
-   struct passwd *pw;
-
-   cp = strchr(fn, '/');
-   if (cp == NULL)
-   cp = fn + strlen(fn); /* point to the NUL byte */
-   ulen = cp - fn[1];
-   if (ulen = sizeof(user)) {
-   ewprintf(Login name too long);
-   return (NULL);
-   }
-   if (ulen == 0) /* ~/ or ~ */
-   (void)strlcpy(user, getlogin(), sizeof(user));
-   else { /* ~user/ or ~user */
-   memcpy(user, fn[1], ulen);
-   user[ulen] = '\0';
-   }
-   pw = getpwnam(user);
-   if (pw != NULL) {
-   plen = strlcpy(path, pw-pw_dir, sizeof(path));
-   if (plen == 0 || path[plen - 1] != '/') {
-   if (strlcat(path, /, sizeof(path)) =
-   sizeof(path)) {
-   ewprintf(Path too long);
-   return (NULL);
-   }
-   }
-   fn = cp;
-   if (*fn == '/')
-   fn++;
-   }
-   }
-   if (strlcat(path, fn, sizeof(path)) = sizeof(path)) {
-   ewprintf(Path too long);
+   if ((path = expandtilde(fn)) == NULL)
return (NULL);
-   }
 
if (realpath(path, fnb) == NULL)
(void)strlcpy(fnb, path, sizeof(fnb));
@@ -730,4 +685,64 @@ bkupleavetmp(const char *fn)
return (TRUE);
 
return (FALSE);
+}
+
+/* 
+ * Expand file names beginning with '~' if appropriate:
+ *   1, if ./~fn exists, continue without expanding tilde.
+ *   2, else, if username 'fn' exists, expand tilde with home directory path.
+ *   3, otherwise, continue and create new buffer called ~fn.
+ */
+char *
+expandtilde(const char *fn)
+{
+   struct passwd   *pw;
+   struct stat  statbuf;
+   const char  *cp;
+   char user[LOGIN_NAME_MAX], path[NFILEN], *ret;
+   size_t   ulen, plen;
+
+   path[0] = '\0';
+
+if (fn[0] != '~' || stat(fn, statbuf) == 0) {
+   if ((ret = strndup(fn, NFILEN)) == NULL)
+   return (NULL);
+   return(ret);
+   }
+   cp = strchr(fn, '/');
+   if (cp == NULL)
+   cp = fn + strlen(fn); /* point to the NUL byte */
+   ulen = cp - fn[1];
+   if (ulen = sizeof(user)) {
+   if ((ret = strndup(fn, NFILEN)) == NULL)
+   return (NULL);
+   return(ret);
+   }
+   if (ulen == 0) /* ~/ or ~ */
+   (void)strlcpy(user, getlogin(), sizeof(user));
+   else { /* ~user/ or ~user */
+   memcpy(user, 

mg - save backup files to homedir (diff v3)

2012-06-13 Thread Mark Lumsden
If you use mg as the editor with mutt, any backup files mutt creates
are kept in /tmp. However, with backup-to-home-directory enabled all
backup files are moved to ~/.mg.d. Personally, I'd rather not move
these backups but keep them in the /tmp dir. 

This modified diff allows backup files that are located in the /tmp
directory to stay there, while allowing all other backups to go to the
~/.mg.d directory. Arguably, this could just be made the default
behaviour (with backup-to-home-directory enabled), however I wrote the
diff with an added an option so am sending the diff with it in.  Also,
since this option is not exactly the same as an emacs command I have
chosen a non emacs command name:

leave-tmpdir-backups

Of course, by default nothing is changed in mg. Backups are still
kept in the current directory.

Comments/ok?

-lum

Index: def.h
===
RCS file: /cvs/src/usr.bin/mg/def.h,v
retrieving revision 1.123
diff -u -p -r1.123 def.h
--- def.h   7 Jun 2012 15:15:04 -   1.123
+++ def.h   13 Jun 2012 12:33:06 -
@@ -446,6 +446,8 @@ struct list *make_file_list(char *);
 int fisdir(const char *);
 int fchecktime(struct buffer *);
 int fupdstat(struct buffer *);
+int backuptohomedir(int, int);
+int  toggleleavetmp(int, int);
 
 /* kbd.c X */
 int do_meta(int, int);
Index: fileio.c
===
RCS file: /cvs/src/usr.bin/mg/fileio.c,v
retrieving revision 1.90
diff -u -p -r1.90 fileio.c
--- fileio.c11 Jun 2012 18:30:03 -  1.90
+++ fileio.c13 Jun 2012 12:33:06 -
@@ -22,6 +22,12 @@
 
 #include kbd.h
 
+static char *bkuplocation(const char *);
+static int   bkupleavetmp(const char *);
+
+static char *bkupdir;
+static int   leavetmp = 0; /* 1 = leave any '~' files in tmp dir */  
+
 /*
  * Open a file for reading.
  */
@@ -203,23 +209,28 @@ fbackupfile(const char *fn)
int  from, to, serrno;
ssize_t  nread;
char buf[BUFSIZ];
-   char*nname, *tname;
+   char*nname, *tname, *bkpth;
 
if (stat(fn, sb) == -1) {
ewprintf(Can't stat %s : %s, fn, strerror(errno));
return (FALSE);
}
 
-   if (asprintf(nname, %s~, fn) == -1) {
+   if ((bkpth = bkuplocation(fn)) == NULL)
+   return (FALSE);
+
+   if (asprintf(nname, %s~, bkpth) == -1) {
ewprintf(Can't allocate backup file name : %s, 
strerror(errno));
+   free(bkpth);
return (ABORT);
}
-
-   if (asprintf(tname, %s.XX, fn) == -1) {
+   if (asprintf(tname, %s.XX, bkpth) == -1) {
ewprintf(Can't allocate temp file name : %s, strerror(errno));
+   free(bkpth);
free(nname);
return (ABORT);
}
+   free(bkpth);
 
if ((from = open(fn, O_RDONLY)) == -1) {
free(nname);
@@ -610,4 +621,113 @@ fchecktime(struct buffer *bp)
 
return (TRUE);

+}
+
+/*
+ * Location of backup file. This function creates the correct path.
+ */
+static char *
+bkuplocation(const char *fn)
+{
+   struct stat sb;
+   char *ret;
+
+   if (bkupdir != NULL  (stat(bkupdir, sb) == 0) 
+   S_ISDIR(sb.st_mode)  !bkupleavetmp(fn)) {
+   char fname[NFILEN];
+   const char *c;
+   int i = 0, len;
+
+   c = fn;
+   len = strlen(bkupdir);
+
+   while (*c != '\0') {
+   /* Make sure we don't go over combined:
+   * strlen(bkupdir + '/' + fname + '\0')
+   */
+   if (i = NFILEN - len - 1)
+   return (NULL);
+   if (*c == '/') {
+   fname[i] = '!';
+   } else if (*c == '!') {
+   if (i = NFILEN - len - 2)
+   return (NULL);
+   fname[i++] = '!';
+   fname[i] = '!';
+   } else
+   fname[i] = *c;
+   i++;
+   c++;
+   }
+   fname[i] = '\0';
+   if (asprintf(ret, %s/%s, bkupdir, fname) == -1)
+   return (NULL);
+
+   } else if ((ret = strndup(fn, NFILEN)) == NULL)
+   return (NULL);
+
+   return (ret);
+}
+
+int
+backuptohomedir(int f, int n)
+{
+   const char  *c = ~/.mg.d;
+   char*p;
+
+   if (bkupdir == NULL) {
+   p = adjustname(c, TRUE);
+   bkupdir = strndup(p, NFILEN);
+   if (bkupdir == NULL)
+   return(FALSE);
+
+   if 

Re: mg - save backup files to homedir (diff v2)

2012-06-09 Thread Mark Lumsden
 So perhaps it is better for mg to behave more like emacs when it comes
 to saving backup files in a single directory. Especially if a user has
 two files open with the same name and are working on them
 simultaneously.  In this diff I've added the path to the backup file
 name. Like emacs, it changes any '/' to '!'.


Here is a slightly modified diff; add NUL termination to backup path.

Are there objections to this going in?

-lum


Index: def.h
===
RCS file: /cvs/src/usr.bin/mg/def.h,v
retrieving revision 1.123
diff -u -p -r1.123 def.h
--- def.h   7 Jun 2012 15:15:04 -   1.123
+++ def.h   9 Jun 2012 20:22:10 -
@@ -446,6 +446,7 @@ struct list *make_file_list(char *);
 int fisdir(const char *);
 int fchecktime(struct buffer *);
 int fupdstat(struct buffer *);
+int backuptohomedir(int, int);
 
 /* kbd.c X */
 int do_meta(int, int);
Index: fileio.c
===
RCS file: /cvs/src/usr.bin/mg/fileio.c,v
retrieving revision 1.89
diff -u -p -r1.89 fileio.c
--- fileio.c25 May 2012 04:56:58 -  1.89
+++ fileio.c9 Jun 2012 20:22:10 -
@@ -22,6 +22,10 @@
 
 #include kbd.h
 
+static char *bkuplocation(const char *);
+
+static char *bkupdir;
+
 /*
  * Open a file for reading.
  */
@@ -189,6 +193,51 @@ ffgetline(FILE *ffp, char *buf, int nbuf
 }
 
 /*
+ * Location of backup file. This function creates the correct path.
+ */
+static char *
+bkuplocation(const char *fn)
+{
+   struct stat sb;
+   char *ret;
+
+   if (bkupdir != NULL  (stat(bkupdir, sb) == 0) 
+   S_ISDIR(sb.st_mode)) {
+   char fname[NFILEN];
+   const char *c;
+   int i = 0, len;
+
+   c = fn;
+   len = strlen(bkupdir);
+
+   while (*c != '\0') {
+   /* Make sure we don't go over combined:
+* strlen(bkupdir + '/' + fname + '\0')
+*/
+   if (i = NFILEN - len - 1)
+   return (NULL);
+   if (*c == '/') {
+   fname[i] = '!';
+   } else if (*c == '!') {
+   if (i = NFILEN - len - 2)
+   return (NULL);
+   fname[i++] = '!';
+   fname[i] = '!';
+   } else
+   fname[i] = *c;
+   i++;
+   c++;
+   }
+   fname[i] = '\0';
+   if (asprintf(ret, %s/%s, bkupdir, fname) == -1)
+   return (NULL);
+   } else if ((ret = strndup(fn, NFILEN)) == NULL)
+   return (NULL);
+
+   return (ret);
+}
+
+/*
  * Make a backup copy of fname.  On Unix the backup has the same
  * name as the original file, with a ~ on the end; this seems to
  * be newest of the new-speak. The error handling is all in file.c.
@@ -203,23 +252,29 @@ fbackupfile(const char *fn)
int  from, to, serrno;
ssize_t  nread;
char buf[BUFSIZ];
-   char*nname, *tname;
+   char*nname, *tname, *bkpth;
 
if (stat(fn, sb) == -1) {
ewprintf(Can't stat %s : %s, fn, strerror(errno));
return (FALSE);
}
 
-   if (asprintf(nname, %s~, fn) == -1) {
+   if ((bkpth = bkuplocation(fn)) == NULL)
+   return (FALSE);
+
+   if (asprintf(nname, %s~, bkpth) == -1) {
ewprintf(Can't allocate temp file name : %s, strerror(errno));
+   free(bkpth);
return (ABORT);
}
 
-   if (asprintf(tname, %s.XX, fn) == -1) {
+   if (asprintf(tname, %s.XX, bkpth) == -1) {
ewprintf(Can't allocate temp file name : %s, strerror(errno));
+   free(bkpth);
free(nname);
return (ABORT);
}
+   free(bkpth);
 
if ((from = open(fn, O_RDONLY)) == -1) {
free(nname);
@@ -610,4 +665,28 @@ fchecktime(struct buffer *bp)
 
return (TRUE);

+}
+
+int
+backuptohomedir(int f, int n)
+{
+   const char  *c = ~/.mg.d;
+   char*p;
+
+   if (bkupdir == NULL) {
+   p = adjustname(c, TRUE);
+   bkupdir = strndup(p, NFILEN);
+   if (bkupdir == NULL)
+   return(FALSE);
+
+   if (mkdir(bkupdir, 0700) == -1  errno != EEXIST) {
+   free(bkupdir);
+   bkupdir = NULL;
+   }
+   } else {
+   free(bkupdir);
+   bkupdir = NULL;
+   }
+
+   return (TRUE);
 }
Index: funmap.c

mg - Another corner-case scrolling fix

2012-06-08 Thread Mark Lumsden
Bit difficult to explain this one. If you have a file open that is 3
or 4 times longer than the length of the viewable window and are at
the bottom of the buffer then scroll up to the top using M-v, your
cursor should remain at the bottom left of the window once you reach
the top of the buffer. 

mg behaves like this since the last couple of scrolling diffs I've
committed. However, and as an example, if you start with the window
viewing the top of a buffer and press C-v twice, then C-p four times
then M-v twice to scroll back to the top, you will find your cursor is
NOT at the bottom left of the window. tut tut. This diff makes the
cursor stay at the bottom left, like emacs.

ok?

-lum

Index: basic.c
===
RCS file: /cvs/src/usr.bin/mg/basic.c,v
retrieving revision 1.35
diff -u -p -r1.35 basic.c
--- basic.c 8 Jun 2012 05:10:50 -   1.35
+++ basic.c 8 Jun 2012 15:09:22 -
@@ -334,6 +334,8 @@ backpage(int f, int n)
 
/* Move the dot the slow way, for line nos */
while (curwp-w_dotp != lp2) {
+if (curwp-w_dotline = curwp-w_ntrows)
+return (TRUE);
curwp-w_dotp = lback(curwp-w_dotp);
curwp-w_dotline--;
}



Re: mg - corner-case backward scrolling

2012-06-07 Thread Mark Lumsden
 There is a corner case when the screen buffer is only 1 line long
 where the loop that looks for the current dot line goes through the
 whole buffer until it finds the correct line. This means the line
 number decrement is way over what it should be. This diff accounts
 for that corner case. ok?


This version uses the existing function backline() that already moves
the cursor and linep by one line. This keeps the backpage() function
for paging backwards. 

-lum

Index: basic.c
===
RCS file: /cvs/src/usr.bin/mg/basic.c,v
retrieving revision 1.34
diff -u -p -r1.34 basic.c
--- basic.c 1 Jun 2012 11:22:06 -   1.34
+++ basic.c 7 Jun 2012 15:25:34 -
@@ -309,7 +309,7 @@ backpage(int f, int n)
if (!(f  FFARG)) {
n = curwp-w_ntrows - 2;/* Default scroll.   */
if (n = 0) /* Don't blow up if the  */
-   n = 1;  /* window is tiny.   */
+   return(backline(f, 1)); /* window is tiny.   */
} else if (n  0)
return (forwpage(f | FFRAND, -n));



mg - save backup files to homedir (diff v2)

2012-06-07 Thread Mark Lumsden
[note: I've modifed this diff from the first version with comments
from eric@ and Sunil Nimmagadda.] 

I find the backup files mg creates scattered around a pain but then
again I don't want to switch backups off since they can be useful.
Also, I don't feel the need to implement something in mg as fancy as
emacs's backup functionality ie. moving backup files, versioning,
deleting old backup versions etc 

With this diff I've only added the emacs functionality of moving the
backup files to a single directory instead of having them scattered
around everywhere. 

There are some drawbacks to having the backups in one directory of
course, only one backup version is maintained for files of the same
name but which originate in different directories (But that is
enough for me)

Since the functionality isn't trying to mimic emacs exactly, the
command name I've chosen isn't trying to reuse one of emacs'. 

backup-to-home-directory

This is open to suggestions of course.

The backup directory name ~/.mg.d stems from emacs's ~/.emacs.d.

Any comments?

-lum

Index: def.h
===
RCS file: /cvs/src/usr.bin/mg/def.h,v
retrieving revision 1.123
diff -u -p -r1.123 def.h
--- def.h   7 Jun 2012 15:15:04 -   1.123
+++ def.h   7 Jun 2012 17:38:26 -
@@ -446,6 +446,7 @@ struct list *make_file_list(char *);
 int fisdir(const char *);
 int fchecktime(struct buffer *);
 int fupdstat(struct buffer *);
+int backuptohomedir(int, int);
 
 /* kbd.c X */
 int do_meta(int, int);
Index: fileio.c
===
RCS file: /cvs/src/usr.bin/mg/fileio.c,v
retrieving revision 1.89
diff -u -p -r1.89 fileio.c
--- fileio.c25 May 2012 04:56:58 -  1.89
+++ fileio.c7 Jun 2012 17:38:26 -
@@ -22,6 +22,10 @@
 
 #include kbd.h
 
+static char *bkuplocation(const char *);
+
+static char *bkupdir;
+
 /*
  * Open a file for reading.
  */
@@ -189,6 +193,26 @@ ffgetline(FILE *ffp, char *buf, int nbuf
 }
 
 /*
+ * Location of backup file. This function creates the correct path.
+ */
+static char *
+bkuplocation(const char *fn)
+{
+   struct stat sb;
+   char *fname, *c;
+
+   if (bkupdir != NULL  (stat(bkupdir, sb) == 0) 
+   S_ISDIR(sb.st_mode)) {
+   c = strrchr(fn, '/');
+   if (asprintf(fname, %s%s, bkupdir, c) == -1)
+   return (NULL);
+   } else if ((fname = strndup(fn, NFILEN)) == NULL)
+   return (NULL);
+
+   return (fname);
+}
+
+/*
  * Make a backup copy of fname.  On Unix the backup has the same
  * name as the original file, with a ~ on the end; this seems to
  * be newest of the new-speak. The error handling is all in file.c.
@@ -203,23 +227,27 @@ fbackupfile(const char *fn)
int  from, to, serrno;
ssize_t  nread;
char buf[BUFSIZ];
-   char*nname, *tname;
+   char*nname, *tname, *bkpth;
 
if (stat(fn, sb) == -1) {
ewprintf(Can't stat %s : %s, fn, strerror(errno));
return (FALSE);
}
 
-   if (asprintf(nname, %s~, fn) == -1) {
+   if ((bkpth = bkuplocation(fn)) == NULL)
+   return (FALSE);
+
+   if (asprintf(nname, %s~, bkpth) == -1) {
ewprintf(Can't allocate temp file name : %s, strerror(errno));
return (ABORT);
}
 
-   if (asprintf(tname, %s.XX, fn) == -1) {
+   if (asprintf(tname, %s.XX, bkpth) == -1) {
ewprintf(Can't allocate temp file name : %s, strerror(errno));
free(nname);
return (ABORT);
}
+   free(bkpth);
 
if ((from = open(fn, O_RDONLY)) == -1) {
free(nname);
@@ -610,4 +638,28 @@ fchecktime(struct buffer *bp)
 
return (TRUE);

+}
+
+int
+backuptohomedir(int f, int n)
+{
+   const char  *c = ~/.mg.d;
+   char*p;
+
+   if (bkupdir == NULL) {
+   p = adjustname(c, TRUE);
+   bkupdir = strndup(p, NFILEN);
+   if (bkupdir == NULL)
+   return(FALSE);
+
+   if (mkdir(bkupdir, 0700) == -1  errno != EEXIST) {
+   free(bkupdir);
+   bkupdir = NULL;
+   }
+   } else {
+   free(bkupdir);
+   bkupdir = NULL;
+   }
+
+   return (TRUE);
 }
Index: funmap.c
===
RCS file: /cvs/src/usr.bin/mg/funmap.c,v
retrieving revision 1.39
diff -u -p -r1.39 funmap.c
--- funmap.c7 Jun 2012 15:15:04 -   1.39
+++ funmap.c7 Jun 2012 17:38:26 -
@@ -25,6 +25,7 @@ static struct funmap functnames[] = {
{fillmode, auto-fill-mode,},
{indentmode, auto-indent-mode,},
{backtoindent, 

mg - corner-case backward scrolling

2012-06-05 Thread Mark Lumsden
There is a corner case when the screen buffer is only 1 line long
where the loop that looks for the current dot line goes through the
whole buffer until it finds the correct line. This means the line
number decrement is way over what it should be. This diff accounts
for that corner case. ok?

-lum 

Index: basic.c
===
RCS file: /cvs/src/usr.bin/mg/basic.c,v
retrieving revision 1.34
diff -u -p -r1.34 basic.c
--- basic.c 1 Jun 2012 11:22:06 -   1.34
+++ basic.c 5 Jun 2012 21:01:38 -
@@ -305,11 +305,12 @@ int
 backpage(int f, int n)
 {
struct line  *lp, *lp2;
+   int i = 0;
 
if (!(f  FFARG)) {
n = curwp-w_ntrows - 2;/* Default scroll.   */
if (n = 0) /* Don't blow up if the  */
-   n = 1;  /* window is tiny.   */
+   i = n = 1;  /* window is tiny.   */
} else if (n  0)
return (forwpage(f | FFRAND, -n));
 
@@ -332,10 +333,15 @@ backpage(int f, int n)
 
 lp2 = lforw(lp2);
 
-   /* Move the dot the slow way, for line nos */
-   while (curwp-w_dotp != lp2) {
-   curwp-w_dotp = lback(curwp-w_dotp);
-   curwp-w_dotline--;
+   if (i == 1) {
+curwp-w_dotp = lback(curwp-w_dotp);
+curwp-w_dotline--;
+   } else {
+   /* Move the dot the slow way, for line nos */
+   while (curwp-w_dotp != lp2) {
+   curwp-w_dotp = lback(curwp-w_dotp);
+   curwp-w_dotline--;
+   }
}
curwp-w_doto = 0;
return (TRUE);



Re: cscope support in mg

2012-06-01 Thread Mark Lumsden
 Here is an updated diff with following changes...
 
 Manpage update.
 Remove conditional compilation of cscope functionality.
 Fixed a memory leak in csexists function.
 Treat current word at cursor as default input for cscope commands.
 
 Comments?

I like it. I'm using your previous diffs (ctags/shell-command-on-region
etc..) to develope mg, so I'm keen for it to go in. I recall others
being interested in this, do they have anything to say? Or are there 
any objectors?

mark



mg - scrolling back diff

2012-05-31 Thread Mark Lumsden
Currently, mg's cursor jumps from top to bottom of the screen as you
scroll upwards, I find this behaviour confusing at times. This diff
makes mg's scroll back the same as emacs. 

Comments/ok?

mark

Index: basic.c
===
RCS file: /cvs/src/usr.bin/mg/basic.c,v
retrieving revision 1.32
diff -u -p -r1.32 basic.c
--- basic.c 30 May 2012 06:13:32 -  1.32
+++ basic.c 31 May 2012 06:57:11 -
@@ -301,7 +301,7 @@ forwpage(int f, int n)
 int
 backpage(int f, int n)
 {
-   struct line  *lp;
+   struct line  *lp, *lp2;
 
if (!(f  FFARG)) {
n = curwp-w_ntrows - 2;/* Default scroll.   */
@@ -309,18 +309,24 @@ backpage(int f, int n)
n = 1;  /* window is tiny.   */
} else if (n  0)
return (forwpage(f | FFRAND, -n));
-   lp = curwp-w_linep;
+
+   lp = lp2 = curwp-w_linep;
+
while (n--  lback(lp) != curbp-b_headp) {
lp = lback(lp);
}
curwp-w_linep = lp;
curwp-w_rflag |= WFFULL;
+
/* if in current window, don't move dot */
for (n = curwp-w_ntrows; n--  lp != curbp-b_headp; lp = lforw(lp))
if (lp == curwp-w_dotp)
return (TRUE);
+
+lp2 = lforw(lp2);
+
/* Move the dot the slow way, for line nos */
-   while (curwp-w_dotp != curwp-w_linep) {
+   while (curwp-w_dotp != lp2) {
curwp-w_dotp = lback(curwp-w_dotp);
curwp-w_dotline--;
}



mg - more emacs scroll compatibility

2012-05-31 Thread Mark Lumsden
Show a message and beep when you reach either end of a buffer. 

ok?

-lum

Index: basic.c
===
RCS file: /cvs/src/usr.bin/mg/basic.c,v
retrieving revision 1.33
diff -u -p -r1.33 basic.c
--- basic.c 31 May 2012 10:55:53 -  1.33
+++ basic.c 31 May 2012 14:54:24 -
@@ -269,8 +269,11 @@ forwpage(int f, int n)
 
lp = curwp-w_linep;
while (n--)
-   if ((lp = lforw(lp)) == curbp-b_headp)
+   if ((lp = lforw(lp)) == curbp-b_headp) {
+   ttbeep();
+   ewprintf(End of buffer);
return(TRUE);
+   }
 
curwp-w_linep = lp;
curwp-w_rflag |= WFFULL;
@@ -314,6 +317,10 @@ backpage(int f, int n)
 
while (n--  lback(lp) != curbp-b_headp) {
lp = lback(lp);
+   }
+   if (lp == curwp-w_linep) {
+   ttbeep();
+   ewprintf(Beginning of buffer);
}
curwp-w_linep = lp;
curwp-w_rflag |= WFFULL;



mg - remove *init* buffer

2012-05-28 Thread Mark Lumsden
After a recent commit (http://marc.info/?l=openbsd-techm=133787310204563w=2)
I realised the *init* buffer could be removed since we went back and updated
modes after scratch was created.

There is a side effect to this diff; theo mode now works from the command
line:

$ mg -f theo

[it had been broken for a while]

Comments/ok

-lum

Index: main.c
===
RCS file: /cvs/src/usr.bin/mg/main.c,v
retrieving revision 1.65
diff -u -p -r1.65 main.c
--- main.c  25 May 2012 05:05:48 -  1.65
+++ main.c  28 May 2012 14:09:51 -
@@ -23,7 +23,7 @@ struct mgwin  *curwp; /* current windo
 struct mgwin   *wheadp;/* MGWIN listhead   */
 charpat[NPAT]; /* pattern  */
 
-static void edinit(PF);
+static void edinit(struct buffer *);
 static __dead void usage(void);
 
 extern char*__progname;
@@ -40,11 +40,11 @@ usage()
 int
 main(int argc, char **argv)
 {
-   char*cp, *init_fcn_name = NULL;
-   PF   init_fcn = NULL;
-   int  o, i, nfiles;
-   int  nobackups = 0;
-   struct buffer *bp;
+   char*cp, *init_fcn_name = NULL;
+   PF   init_fcn = NULL;
+   int  o, i, nfiles;
+   int  nobackups = 0;
+   struct buffer   *bp = NULL;
 
while ((o = getopt(argc, argv, nf:)) != -1)
switch (o) {
@@ -88,7 +88,7 @@ main(int argc, char **argv)
 
vtinit();   /* Virtual terminal.*/
dirinit();  /* Get current directory.   */
-   edinit(init_fcn);   /* Buffers, windows.*/
+   edinit(bp); /* Buffers, windows.*/
ttykeymapinit();/* Symbols, bindings.   */
 
/*
@@ -98,13 +98,6 @@ main(int argc, char **argv)
 */
update();
 
-   /*
-* Create scratch buffer now, killing old *init* buffer.
-* This causes *scratch* to be created and made curbp.
-*/
-   if ((bp = bfind(*init*, FALSE)) != NULL)
-   killbuffer(bp);
-
/* user startup file. */
if ((cp = startupfile(NULL)) != NULL)
(void)load(cp);
@@ -194,26 +187,23 @@ notnum:
 }
 
 /*
- * Initialize default buffer and window.
- * Initially, buffer is named *init*. This is changed later
- * to *scratch* after the startup files are read.
+ * Initialize default buffer and window. Default buffer is called *scratch*.
  */
 static void
-edinit(PF init_fcn)
+edinit(struct buffer *bp)
 {
-   struct buffer   *bp;
struct mgwin*wp;
 
bheadp = NULL;
-   bp = bfind(*init*, TRUE); /* Text buffer.  */
+   bp = bfind(*scratch*, TRUE);  /* Text buffer.  */
if (bp == NULL)
panic(edinit);
 
wp = new_window(bp);
if (wp == NULL)
-   panic(Out of memory);
+   panic(edinit: Out of memory);
 
-   curbp = bp; /* Current ones. */
+   curbp = bp; /* Current buffer.   */
wheadp = wp;
curwp = wp;
wp-w_wndp = NULL;  /* Initialize window.*/



mg end of buffer page down diff

2012-05-25 Thread Mark Lumsden
When you page down a document and get to the last page, mg doesn't
stop, it keeps going until the last line is at the top of the window.
This diff makes mg stop paging down when the end of the text is
visible. 

Comments/ok?

-lum
ps some whitespace for readability added. 

Index: basic.c
===
RCS file: /cvs/src/usr.bin/mg/basic.c,v
retrieving revision 1.30
diff -u -p -r1.30 basic.c
--- basic.c 4 Jun 2009 02:23:37 -   1.30
+++ basic.c 25 May 2012 07:40:33 -
@@ -266,16 +266,20 @@ forwpage(int f, int n)
n = 1;  /* if tiny window.   */
} else if (n  0)
return (backpage(f | FFRAND, -n));
+
lp = curwp-w_linep;
-   while (n--  lforw(lp) != curbp-b_headp) {
-   lp = lforw(lp);
-   }
+   while (n--)
+   if ((lp = lforw(lp)) == curbp-b_headp)
+   return(TRUE);
+
curwp-w_linep = lp;
curwp-w_rflag |= WFFULL;
+
/* if in current window, don't move dot */
-   for (n = curwp-w_ntrows; n--  lp != curbp-b_headp; lp = lforw(lp))
+   for (n = curwp-w_ntrows; n--; lp = lforw(lp))
if (lp == curwp-w_dotp)
return (TRUE);
+
/* Advance the dot the slow way, for line nos */
while (curwp-w_dotp != curwp-w_linep) {
curwp-w_dotp = lforw(curwp-w_dotp);



mg history and window relocation

2012-05-25 Thread Mark Lumsden
Move the windows section in the tutorial to a more sensible place
(next to buffers) and move the mg history into the README file which
seems a more sensible place as well.

ok?

-lum

Index: README
===
RCS file: /cvs/src/usr.bin/mg/README,v
retrieving revision 1.9
diff -u -p -r1.9 README
--- README  11 Apr 2012 17:51:10 -  1.9
+++ README  25 May 2012 10:30:31 -
@@ -40,8 +40,16 @@ People who have worked on previous versi
 
rtech!da...@sun.com Dave Brower
 
-Currently maintained in the OpenBSD src tree, with contributions from
-many others.
+Early release history:
+
+* Nov 16, 1986: First release to mod.sources
+* Mar 3, 1987: First Release (mg1a) via comp.sources.unix
+* May 26, 1988: Second release: (mg2a) via comp.sources.misc
+* Jan 26, 1992: Linux port released by Charles Hedrick. This version
+  later makes its way onto tsx-11, Infomagic, and various other Linux
+  repositories.
+* Feb 25, 2000: First import into the OpenBSD tree, where it is
+  currently maintained.
 
 --
 
Index: tutorial
===
RCS file: /cvs/src/usr.bin/mg/tutorial,v
retrieving revision 1.9
diff -u -p -r1.9 tutorial
--- tutorial7 May 2012 13:52:58 -   1.9
+++ tutorial25 May 2012 10:30:32 -
@@ -118,20 +118,6 @@ screen when you type C-g indicating that
 
 In general, when in doubt, use C-g to get out of trouble.
 
-Windows

-
-The mg editor can support several windows at the same time, each one displaying
-different text. To split a screen into two horizontal windows use C-x 2 to do
-this. To return to one window, use C-x 1 to close the other windows and only
-keep the current window.
-
- Use C-x 2 to split the screen into two windows. 
-
- Use C-x o to move from one window to the other. You can scroll up and down
-   in each window using the cursor keys or C-n and C-p keys.
-
- Use C-x 1 to restore back to one window.
 
 Inserting/Deleting Text
 ---
@@ -267,6 +253,21 @@ in the bottom of your screen. In general
 often. When you save a file, mg saves a backup of the file with a tilde (~)
 character at the end.
 
+Windows
+---
+
+The mg editor can support several windows at the same time, each one displaying
+different text. To split a screen into two horizontal windows use C-x 2 to do
+this. To return to one window, use C-x 1 to close the other windows and only
+keep the current window.
+
+ Use C-x 2 to split the screen into two windows. 
+
+ Use C-x o to move from one window to the other. You can scroll up and down
+   in each window using the cursor keys or C-n and C-p keys.
+
+ Use C-x 1 to restore back to one window.
+
 Buffers
 ---
 
@@ -334,31 +335,11 @@ information available via the mg(1) man 
 improvement, please don't hesitate to drop a message or (better still) submit
 a diff to tech@openbsd.org.
 
-History

-
-mg is a public-domain text editor. It was originally based on MicroEMACS, but
-has since moved to more closely resemble GNU Emacs while still maintaining a
-small memory footprint and fast speed. 
-
-* Nov 16, 1986: First release to mod.sources
-* Mar 3, 1987: First Release (mg1a) via comp.sources.unix
-* May 26, 1988: Second release: (mg2a) via comp.sources.misc
-* Jan 26, 1992: Linux port released by Charles Hedrick. This version
-  later makes its way onto tsx-11, Infomagic, and various other Linux
-  repositories. 
-* Feb 25, 2000: First import into the OpenBSD tree, where it is
-  currently maintained
-
-The mg editor was originally named MicroGNUEmacs. The name was changed at
-the request of Richard Stallman, as this software is entirely unrelated to
-the GNU project. 
-
 Author Info
 ---
 
 Original Author of this document: Mayukh Bose, 
-Date last updated: 2012-01-17
+Date last updated: 2012-05-25
 
 Copyright
 -



  1   2   >