From 39ccac7354243d00ded31c34603e70ac2f4fe1a2 Mon Sep 17 00:00:00 2001 From: "Michael D. Lowis" Date: Tue, 18 Jul 2017 11:15:15 -0400 Subject: [PATCH] move pty logic to pty.c and added shortcuts for ^c ^d and ^z --- Makefile | 3 ++- inc/edit.h | 9 +++++++ lib/pty.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ tide.c | 64 +++++++----------------------------------------- 4 files changed, 91 insertions(+), 56 deletions(-) create mode 100644 lib/pty.c diff --git a/Makefile b/Makefile index 2507e71..6793735 100644 --- a/Makefile +++ b/Makefile @@ -14,7 +14,8 @@ LIBEDIT_OBJS = \ lib/win.o \ lib/colors.o \ lib/config.o \ - lib/event.o + lib/event.o \ + lib/pty.o TEST_BINS = \ tests/tide \ diff --git a/inc/edit.h b/inc/edit.h index 36081f8..d37e0df 100644 --- a/inc/edit.h +++ b/inc/edit.h @@ -228,6 +228,15 @@ void exec_job(char** cmd, char* data, size_t ndata, View* dest); void exec_cmd(char** cmd, char* text, char** out, char** err); int exec_spawn(char** cmd, int* in, int* out); +/* Pseudo-Terminal Handling + *****************************************************************************/ +bool pty_active(void); +void pty_spawn(char** argv); +void pty_send(char* cmd); +void pty_send_intr(void); +void pty_send_eof(void); +void pty_send_susp(void); + /* Configuration Data *****************************************************************************/ enum { /* Configuration Variables */ diff --git a/lib/pty.c b/lib/pty.c new file mode 100644 index 0000000..1a2ae27 --- /dev/null +++ b/lib/pty.c @@ -0,0 +1,71 @@ +#define _XOPEN_SOURCE 700 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef __MACH__ + #include +#else + #include +#endif + +static int PtyFD = -1; + +static void update(int fd, void* data); + +bool pty_active(void) { return (PtyFD >= 0);} +void pty_send_intr(void) { (void)write(PtyFD, "\x03", 1); } +void pty_send_eof(void) { (void)write(PtyFD, "\x04", 1); } +void pty_send_susp(void) { (void)write(PtyFD, "\x1A", 1); } + +void pty_spawn(char** argv) { + assert(!pty_active()); + struct termios tio; + pid_t pid; + putenv("TERM=dumb"); + switch ( (pid = forkpty(&PtyFD, NULL, NULL, NULL)) ) { + case -1: // Failed + die("forkpty() :"); + break; + + case 0: // Child Process + if (execvp(argv[0], argv) < 0) + die("execvp('%s', ...) :", argv[0]); + exit(EXIT_FAILURE); + break; + + default: // Parent Process + tcgetattr(PtyFD, &tio); + tio.c_lflag &= ~(ECHO | ECHONL); + tio.c_cc[ VMIN ] = 1; + tio.c_cc[ VTIME ] = 0; + tcsetattr(PtyFD, TCSANOW, &tio); + break; + } + event_watchfd(PtyFD, INPUT, update, NULL); +} + +void pty_send(char* str) { + if (write(PtyFD, str, strlen(str)-1) < 0) + PtyFD = -1; +} + +static void update(int fd, void* data) { + /* Read from command if we have one */ + long n = 0, i = 0; + static char cmdbuf[8192]; + if ((n = read(PtyFD, cmdbuf, sizeof(cmdbuf))) < 0) + PtyFD = -1; + while (i < n) { + Rune rune = 0; + size_t length = 0; + while (!utf8decode(&rune, &length, cmdbuf[i++])); + view_insert(win_view(EDIT), false, rune); + } + win_buf(EDIT)->outpoint = win_view(EDIT)->selection.end; +} diff --git a/tide.c b/tide.c index 47466df..10f1ec0 100644 --- a/tide.c +++ b/tide.c @@ -1,4 +1,3 @@ -#define _XOPEN_SOURCE 700 #include #include #include @@ -7,12 +6,6 @@ #include #include #include -#include -#ifdef __MACH__ - #include -#else - #include -#endif typedef struct { char* tag; @@ -22,7 +15,6 @@ typedef struct { } action; } Tag; -static int CmdFD = -1; static Tag Builtins[]; static int SearchDir = DOWN; static char* SearchTerm = NULL; @@ -492,6 +484,12 @@ static KeyBinding Bindings[] = { { ModCtrl, 'n', new_win }, { ModOneOrMore, '\n', newline }, { ModCtrl, ' ', complete }, + + /* Pseudo-terminal control shortcuts */ + { ModCtrl|ModShift, 'c', pty_send_intr }, + { ModCtrl|ModShift, 'd', pty_send_eof }, + { ModCtrl|ModShift, 'z', pty_send_susp }, + { 0, 0, 0 } }; @@ -548,62 +546,19 @@ bool update_needed(void) { } static void oninput(Rune rune) { - view_insert(win_view(FOCUSED), (CmdFD == -1), rune); + view_insert(win_view(FOCUSED), !pty_active(), rune); if (win_getregion() == EDIT) { size_t point = win_buf(EDIT)->outpoint; size_t pos = win_view(EDIT)->selection.end; if ((rune == '\n' || rune == RUNE_CRLF) && pos > point) { Sel range = { .beg = point, .end = pos }; char* str = view_getstr(win_view(EDIT), &range); - if (write(CmdFD, str, strlen(str)-1) < 0) - CmdFD = -1; + pty_send(str); free(str); } } } -int pty_spawn(char** argv) { - int fd; - struct termios tio; - pid_t pid; - putenv("TERM=dumb"); - switch ( (pid = forkpty(&fd, NULL, NULL, NULL)) ) { - case -1: // Failed - die("forkpty() :"); - break; - - case 0: // Child Process - if (execvp(argv[0], argv) < 0) - die("execvp('%s', ...) :", argv[0]); - exit(EXIT_FAILURE); - break; - - default: // Parent Process - tcgetattr(fd, &tio); - tio.c_lflag &= ~(ECHO | ECHONL); - tio.c_cc[ VMIN ] = 1; - tio.c_cc[ VTIME ] = 0; - tcsetattr(fd, TCSANOW, &tio); - break; - } - return fd; -} - -void pty_update(int fd, void* data) { - /* Read from command if we have one */ - long n = 0, i = 0; - static char cmdbuf[8192]; - if ((n = read(CmdFD, cmdbuf, sizeof(cmdbuf))) < 0) - CmdFD = -1; - while (i < n) { - Rune rune = 0; - size_t length = 0; - while (!utf8decode(&rune, &length, cmdbuf[i++])); - view_insert(win_view(EDIT), false, rune); - } - win_buf(EDIT)->outpoint = win_view(EDIT)->selection.end; -} - void edit_relative(char* path) { char *currdir = NULL, *currpath = NULL, *relpath = NULL; char* origdir = getcurrdir(); @@ -659,8 +614,7 @@ void edit_command(char** cmd) { config_set_int(TabWidth, 8); win_setlinenums(false); win_setruler(0); - CmdFD = pty_spawn(*cmd ? cmd : shellcmd); - event_watchfd(CmdFD, INPUT, pty_update, NULL); + pty_spawn(*cmd ? cmd : shellcmd); } #ifndef TEST -- 2.49.0