aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2022-04-28 19:03:39 -0700
committerKaz Kylheku <kaz@kylheku.com>2022-04-28 19:03:39 -0700
commit1a99270e6d3e6a519b33b4deef749bdd55ccce1c (patch)
treedbb1b8cd5e3e54d7207aa2b98d5eb25ce5f043d2
parentc0ad4a51358674829361d9954067faa948818c5b (diff)
downloadpw-1a99270e6d3e6a519b33b4deef749bdd55ccce1c.tar.gz
pw-1a99270e6d3e6a519b33b4deef749bdd55ccce1c.tar.bz2
pw-1a99270e6d3e6a519b33b4deef749bdd55ccce1c.zip
Implement Ctrl-Z suspend.
-rw-r--r--pw.114
-rw-r--r--pw.c33
2 files changed, 39 insertions, 8 deletions
diff --git a/pw.1 b/pw.1
index 5c0240e..7fe38a4 100644
--- a/pw.1
+++ b/pw.1
@@ -217,6 +217,18 @@ recall using the up and down arrow keys or
and
.BR Ctrl-N .
+.IP \fBCtrl-Z\fI
+Suspends
+.IR pw ,
+and indeed the entire surrounding process group, to the background
+to gain shell access. This requires a job control shell.
+When
+.IR pw
+is foregrounded again, it will refresh the display in a new text area below the
+cursor, avoiding overwriting anything in the terminal. Thus suspending and then
+immediately foregrounding provides a way to save a snapshot of the window into
+the terminal sessions history.
+
.SH COLON COMMANDS
First, some general remarks. Display refresh doesn't pause during the editing
@@ -365,8 +377,6 @@ The intervals and number of lines cannot be dynamically adjusted.
There is no support for unwrapping long lines, which would be useful for
copy and paste.
-Ctrl-Z suspend is missing.
-
During the
.B :!
command's execution, the TTY settings are not restored.
diff --git a/pw.c b/pw.c
index f3c4c34..eb4c425 100644
--- a/pw.c
+++ b/pw.c
@@ -13,6 +13,7 @@
#include <sys/time.h>
#include <fcntl.h>
#include <errno.h>
+#include <signal.h>
#include <regex.h>
#define ctrl(ch) ((ch) & 0x1f)
@@ -396,6 +397,18 @@ static void execute(char *cmd, unsigned *pstat)
fflush(stdout);
}
+static void ttyset(int fd, struct termios *tty)
+{
+ if (tcsetattr(fd, TCSANOW, tty) < 0)
+ panic("unable to set TTY parameters");
+}
+
+static void ttyget(int fd, struct termios *tty)
+{
+ if (tcgetattr(fd, tty) < 0)
+ panic("unable to get TTY parameters");
+}
+
int main(int argc, char **argv)
{
char *line = 0;
@@ -471,8 +484,7 @@ int main(int argc, char **argv)
columns = ws.ws_col;
}
- if (tcgetattr(ttyfd, &tty_saved) < 0)
- panic("unable to get TTY parameters");
+ ttyget(ttyfd, &tty_saved);
tty_new = tty_saved;
@@ -483,8 +495,7 @@ int main(int argc, char **argv)
tty_new.c_cc[VMIN] = 1;
tty_new.c_cc[VTIME] = 0;
- if (tcsetattr(ttyfd, TCSANOW, &tty_new) < 0)
- panic("unable to set TTY parameters");
+ ttyset(ttyfd, &tty_new);
setvbuf(tty, NULL, _IONBF, 0);
@@ -614,6 +625,17 @@ int main(int argc, char **argv)
if ((pe[0].revents)) {
int ch = getc(tty);
+ if (ch == ctrl('z')) {
+ ttyset(ttyfd, &tty_saved);
+ kill(0, SIGTSTP);
+ ttyset(ttyfd, &tty_new);
+ for (int i = 0; i < nlines; i++)
+ puts("");
+ redraw(circbuf, nlines, hpos, columns, stat, curcmd);
+ stat &= ~stat_dirty;
+ continue;
+ }
+
fakecmd:
switch (kbd_state) {
case kbd_result:
@@ -847,7 +869,6 @@ int main(int argc, char **argv)
}
}
- if (tcsetattr(ttyfd, TCSANOW, &tty_saved) < 0)
- panic("unable to restore TTY parameters");
+ ttyset(ttyfd, &tty_saved);
return exit_status;
}