diff options
| author | Lukas Fürmetz <fuermetz@mailbox.org> | 2017-08-17 14:34:46 +0200 |
|---|---|---|
| committer | Lukas Fürmetz <fuermetz@mailbox.org> | 2017-08-23 15:47:37 +0200 |
| commit | 163dd21864c6c5bb93452dab00806bf612128a10 (patch) | |
| tree | c22e0e387415f28af93c0c28965011c120cdfe0a | |
| parent | f4cff20bd59112fe36e341c551f8f87673cc8c45 (diff) | |
Asynchronous communication
| -rw-r--r-- | vterm-module.c | 31 | ||||
| -rw-r--r-- | vterm-module.h | 8 | ||||
| -rw-r--r-- | vterm.el | 26 |
3 files changed, 47 insertions, 18 deletions
diff --git a/vterm-module.c b/vterm-module.c index b44fd54..a6beae1 100644 --- a/vterm-module.c +++ b/vterm-module.c @@ -5,10 +5,12 @@ #else # include <pty.h> #endif +#include <pthread.h> #include <signal.h> #include <stdio.h> #include <string.h> #include <sys/ioctl.h> +#include <sys/select.h> #include <sys/wait.h> #include <termios.h> #include <unistd.h> @@ -16,7 +18,8 @@ #define MAX(x, y) (((x) > (y)) ? (x) : (y)) -static size_t codepoint_to_utf8(const uint32_t codepoint, unsigned char buffer[4]) { +static size_t codepoint_to_utf8(const uint32_t codepoint, + unsigned char buffer[4]) { if (codepoint <= 0x7F) { buffer[0] = codepoint; return 1; @@ -323,6 +326,7 @@ static void term_finalize(void *term) { static emacs_value Fvterm_new(emacs_env *env, ptrdiff_t nargs, emacs_value args[], void *data) { struct Term *term = malloc(sizeof(struct Term)); + int rows = env->extract_integer(env, args[0]); int cols = env->extract_integer(env, args[1]); @@ -365,7 +369,6 @@ static emacs_value Fvterm_new(emacs_env *env, ptrdiff_t nargs, termios.c_cc[VTIME] = 0; term->pid = forkpty(&term->masterfd, NULL, &termios, &size); - fcntl(term->masterfd, F_SETFL, fcntl(term->masterfd, F_GETFL) | O_NONBLOCK); if (term->pid == 0) { @@ -382,10 +385,30 @@ static emacs_value Fvterm_new(emacs_env *env, ptrdiff_t nargs, VTermScreen *screen = vterm_obtain_screen(term->vt); vterm_screen_reset(screen, 1); + pthread_t thread; + pthread_create(&thread, NULL, &event_loop, term); + return env->make_user_ptr(env, term_finalize, term); } -static void process_key(struct Term *term, unsigned char *key, size_t len, VTermModifier modifier) { +static void *event_loop(void *arg) { + struct Term *term = arg; + fd_set rfds; + + while (1) { + FD_ZERO(&rfds); + FD_SET(term->masterfd, &rfds); + if (select(term->masterfd + 1, &rfds, NULL, NULL, NULL) == 1) { + kill(getpid(), SIGUSR1); + usleep(20); + } + } + + return NULL; +} + +static void process_key(struct Term *term, unsigned char *key, size_t len, + VTermModifier modifier) { if (len == 8 && memcmp(key, "<return>", len) == 0) { vterm_keyboard_key(term->vt, VTERM_KEY_ENTER, modifier); } else if (len == 11 && memcmp(key, "<backspace>", len) == 0) { @@ -437,7 +460,7 @@ static emacs_value Fvterm_update(emacs_env *env, ptrdiff_t nargs, if ((len = read(term->masterfd, bytes, 4096)) > 0) { vterm_input_write(term->vt, bytes, len); vterm_redraw(term->vt, env); - }; + } return env->make_integer(env, 0); } diff --git a/vterm-module.h b/vterm-module.h index 305b354..f6df00c 100644 --- a/vterm-module.h +++ b/vterm-module.h @@ -1,5 +1,6 @@ #include <emacs-module.h> #include <inttypes.h> +#include <semaphore.h> #include <stdbool.h> #include <vterm.h> @@ -11,7 +12,8 @@ struct Term { pid_t pid; }; -static size_t codepoint_to_utf8(const uint32_t codepoint, unsigned char buffer[4]); +static size_t codepoint_to_utf8(const uint32_t codepoint, + unsigned char buffer[4]); static bool utf8_to_codepoint(const unsigned char buffer[4], const size_t len, uint32_t *codepoint); static void bind_function(emacs_env *env, const char *name, emacs_value Sfun); @@ -36,7 +38,9 @@ static void vterm_flush_output(struct Term *term); static void term_finalize(void *term); static emacs_value Fvterm_new(emacs_env *env, ptrdiff_t nargs, emacs_value args[], void *data); -static void process_key(struct Term *term, unsigned char *key, size_t len, VTermModifier modifier); +static void *event_loop(void *arg); +static void process_key(struct Term *term, unsigned char *key, size_t len, + VTermModifier modifier); static emacs_value Fvterm_update(emacs_env *env, ptrdiff_t nargs, emacs_value args[], void *data); static emacs_value Fvterm_kill(emacs_env *env, ptrdiff_t nargs, @@ -15,9 +15,8 @@ "Pointer to struct Term.") (make-variable-buffer-local 'vterm-term) -(defvar vterm-timer nil - "Timer to update the term.") -(make-variable-buffer-local 'vterm-timer) +(defvar vterm-buffers nil + "List of active vterm-buffers.") (defvar vterm-keymap-exceptions '("C-x" "C-u" "C-g" "C-h" "M-x" "M-o") "Exceptions for vterm-keymap. @@ -64,24 +63,27 @@ be send to the terminal.") "Create a new vterm." (interactive) (let ((buffer (generate-new-buffer "vterm"))) + (add-to-list 'vterm-buffers buffer) (pop-to-buffer buffer) - (vterm-mode) - (setq vterm-timer (run-with-timer 0 .1 #'vterm-run-timer buffer)))) + (vterm-mode))) -(defun vterm-run-timer (buffer) +(defun vterm-event () "Update the vterm BUFFER." (interactive) (let ((inhibit-redisplay t) (inhibit-read-only t)) - (with-current-buffer buffer - (unless (vterm-update vterm-term) - (cancel-timer vterm-timer) - (insert "\nProcess exited!\n\n"))))) + (mapc (lambda (buffer) + (with-current-buffer buffer + (unless (vterm-update vterm-term) + (insert "\nProcess exited!\n\n")))) + vterm-buffers))) + +(define-key special-event-map [sigusr1] #'vterm-event) (defun vterm-kill-buffer-hook () - "Cancel the timer and the vterm." + "Kill the corresponding process of vterm." (when (eq major-mode 'vterm-mode) - (cancel-timer vterm-timer) + (setq vterm-buffers (remove (current-buffer) vterm-buffers)) (vterm-kill vterm-term))) (defun vterm-window-size-change (frame) |
