aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLukas Fürmetz <fuermetz@mailbox.org>2017-08-17 14:34:46 +0200
committerLukas Fürmetz <fuermetz@mailbox.org>2017-08-23 15:47:37 +0200
commit163dd21864c6c5bb93452dab00806bf612128a10 (patch)
treec22e0e387415f28af93c0c28965011c120cdfe0a
parentf4cff20bd59112fe36e341c551f8f87673cc8c45 (diff)
Asynchronous communication
-rw-r--r--vterm-module.c31
-rw-r--r--vterm-module.h8
-rw-r--r--vterm.el26
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,
diff --git a/vterm.el b/vterm.el
index 7e43b18..6c828a2 100644
--- a/vterm.el
+++ b/vterm.el
@@ -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)