aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2022-05-13 23:05:26 -0700
committerKaz Kylheku <kaz@kylheku.com>2022-05-13 23:05:26 -0700
commit3a13f268eb32f4d6d2c27562dc885eb05431f41b (patch)
tree2bbb397a3c44a1a25fbf578363c7b9cfbe1802f5
parentb5eb74343f9b096b83ab03d30b3467302ecf1ec5 (diff)
downloadpw-3a13f268eb32f4d6d2c27562dc885eb05431f41b.tar.gz
pw-3a13f268eb32f4d6d2c27562dc885eb05431f41b.tar.bz2
pw-3a13f268eb32f4d6d2c27562dc885eb05431f41b.zip
Tighten the command syntax.
Commands are now separated from their argument by exactly one space, which may only be omitted for an argument which does not begin with a letter. Thus :gfoo no longer pushes a regular expression foo onto the grep stack, but is the unrecognized command gfoo. The command :g foo specifies the regular expression " foo".
-rw-r--r--pw.135
-rw-r--r--pw.c19
2 files changed, 40 insertions, 14 deletions
diff --git a/pw.1 b/pw.1
index 6729e47..b818c0e 100644
--- a/pw.1
+++ b/pw.1
@@ -578,13 +578,27 @@ direction.
.SH COLON COMMANDS
-First, some general remarks. Display refresh doesn't pause during the editing
-of a colon command. If that is required, the suspend command must be used.
-The space between the command and the argument may be omitted. After a command
-is executed, a result message appears in its place. This message persists over
-the poll interval period. The longer the poll interval
-.RB ( -i " option),
-the longer the result message persists.
+First, some general remarks.
+
+The capture of snaphots, driving display refresh, doesn't pause during the
+editing of a colon command. If that is desired, the suspend command must
+be used first.
+
+The name of a colon command consists of lower-case letters. Currently, no
+command has a name more than one letter long. The command may be followed
+by an argument, which is separated from the command by exactly one space.
+If the argument does not begin with a lower-case letter, then the space
+may be omitted. If the command is followed by no characters at all, or
+exactly one space, then its argument is effectively the empty string;
+by convention, this is understood as there being no argument.
+
+When a command is executed, a message appears in its place, diagnosing
+an error situation or confirming a successful result. When such a message
+appears, it persists until a command is issued. If the command is Enter,
+it has only the effect of dismissing the message and restoring the usual
+status line, and not the usual effect of resuming
+.I pw
+out of suspended capture mode.
Colon commands are saved in a history which may be navigated for
recall using the up and down arrow keys or
@@ -592,6 +606,8 @@ recall using the up and down arrow keys or
and
.BR Ctrl-N .
+The commands are:
+
.IP "\fB:w\fP \fIfilename\fP"
Write the currently displayed lines into the specified file.
@@ -636,8 +652,9 @@ is disabled and the
.B GREP
status line disappears. If the optional
.B !
-modifier is included in the command, then it pops the entire stack,
-forgetting all the patterns and disabling grep mode.
+modifier is added to the command, then it pops the entire stack,
+forgetting all the patterns and disabling grep mode. The modifier
+is not an argument and may not be separated from the command.
.IP "\fB:i\fP \fIreal\fP"
Set the poll interval to the number of seconds specified by
diff --git a/pw.c b/pw.c
index aaaeea0..1a1e5ea 100644
--- a/pw.c
+++ b/pw.c
@@ -801,9 +801,15 @@ static execode execute(pwstate *pw, char *cmd, char *resbuf,
size_t size, int count)
{
execode res = exec_failed;
- char *arg = cmd + 2 + strspn(cmd + 2, " \t");
+ char cmdbuf[16];
+ int cmdlen = 0;
+ int ntok = sscanf(cmd + 1, "%15[a-z]%n", cmdbuf, &cmdlen);
+ char *arg = cmd + 1 + cmdlen;
- if (cmd[0] == ':') switch (cmd[1]) {
+ if (*arg == ' ')
+ arg++;
+
+ if (cmd[0] == ':' && ntok == 1 && cmdlen == 1) switch (cmd[1]) {
case 'w': case 'a':
if (arg[0] == 0) {
snprintf(resbuf, size, "file name required!");
@@ -989,7 +995,7 @@ static execode execute(pwstate *pw, char *cmd, char *resbuf,
rflg = gr->flags;
fputs(((gr->flags & REG_EXTENDED)) ? ":E\n" : ":B\n", f);
}
- fputs(gr->inv ? ":v" : ":g", f);
+ fputs(gr->inv ? ":v " : ":g ", f);
fputs(gr->pat, f);
putc('\n', f);
}
@@ -1027,9 +1033,9 @@ static execode execute(pwstate *pw, char *cmd, char *resbuf,
res = exec_ok;
break;
default:
- snprintf(resbuf, size, "bad command");
+ goto badcmd;
break;
- } else {
+ } else if (cmd[0] == '?' || cmd[0] == '/') {
int trig = count > 0 ? count - 1 : count;
if (trig < pw->maxlines && trig < maxtrig)
@@ -1082,6 +1088,9 @@ static execode execute(pwstate *pw, char *cmd, char *resbuf,
}
}
}
+ } else {
+badcmd:
+ snprintf(resbuf, size, "unrecognized command");
}
return res;