diff options
| -rw-r--r-- | vterm-module.c | 73 | ||||
| -rw-r--r-- | vterm-module.h | 27 | ||||
| -rw-r--r-- | vterm.el | 26 |
3 files changed, 83 insertions, 43 deletions
diff --git a/vterm-module.c b/vterm-module.c index 7d44293..edf8237 100644 --- a/vterm-module.c +++ b/vterm-module.c @@ -2,9 +2,11 @@ #include "elisp.h" #include "utf8.h" #include <assert.h> +#include <fcntl.h> #include <limits.h> #include <stdio.h> #include <string.h> +#include <termios.h> #include <unistd.h> #include <vterm.h> @@ -528,13 +530,24 @@ static void term_flush_output(Term *term, emacs_env *env) { static void term_process_key(Term *term, unsigned char *key, size_t len, VTermModifier modifier) { if (is_key(key, len, "<return>")) { - vterm_keyboard_key(term->vt, VTERM_KEY_ENTER, modifier); + if (term->pty_fd > 0) { + struct termios keys; + tcgetattr(term->pty_fd, &keys); + if (keys.c_iflag & ICRNL) + vterm_keyboard_unichar(term->vt, 10, modifier); + else + vterm_keyboard_unichar(term->vt, 13, modifier); + } else { + vterm_keyboard_key(term->vt, VTERM_KEY_ENTER, modifier); + } } else if (is_key(key, len, "<start_paste>")) { vterm_keyboard_start_paste(term->vt); } else if (is_key(key, len, "<end_paste>")) { vterm_keyboard_end_paste(term->vt); } else if (is_key(key, len, "<tab>")) { vterm_keyboard_key(term->vt, VTERM_KEY_TAB, modifier); + } else if (is_key(key, len, "<backtab>") || is_key(key, len, "<iso-lefttab>")) { + vterm_keyboard_key(term->vt, VTERM_KEY_TAB, VTERM_MOD_SHIFT); } else if (is_key(key, len, "<backspace>")) { vterm_keyboard_key(term->vt, VTERM_KEY_BACKSPACE, modifier); } else if (is_key(key, len, "<escape>")) { @@ -593,17 +606,7 @@ static void term_process_key(Term *term, unsigned char *key, size_t len, } } -static void term_put_caret(Term *term, emacs_env *env, int row, int col, - int offset) { - int rows, cols; - vterm_get_size(term->vt, &rows, &cols); - // row * (cols + 1) because of newline character - // col + 1 because (goto-char 1) sets point to first position - int point = ((row + term->sb_current) * (cols + 1)) + col + 1 + offset; - goto_char(env, point); -} - -static void term_finalize(void *object) { +void term_finalize(void *object) { Term *term = (Term *)object; for (int i = 0; i < term->sb_current; i++) { free(term->sb_buffer[i]); @@ -613,13 +616,17 @@ static void term_finalize(void *object) { term->title = NULL; } + if (term->pty_fd > 0) { + close(term->pty_fd); + } + free(term->sb_buffer); vterm_free(term->vt); free(term); } -static emacs_value Fvterm_new(emacs_env *env, ptrdiff_t nargs, - emacs_value args[], void *data) { +emacs_value Fvterm_new(emacs_env *env, ptrdiff_t nargs, emacs_value args[], + void *data) { Term *term = malloc(sizeof(Term)); int rows = env->extract_integer(env, args[0]); @@ -642,6 +649,7 @@ static emacs_value Fvterm_new(emacs_env *env, ptrdiff_t nargs, term->invalid_end = rows; term->width = cols; term->height = rows; + term->pty_fd = -1; term->title = NULL; term->is_title_changed = false; @@ -649,8 +657,8 @@ static emacs_value Fvterm_new(emacs_env *env, ptrdiff_t nargs, return env->make_user_ptr(env, term_finalize, term); } -static emacs_value Fvterm_update(emacs_env *env, ptrdiff_t nargs, - emacs_value args[], void *data) { +emacs_value Fvterm_update(emacs_env *env, ptrdiff_t nargs, emacs_value args[], + void *data) { Term *term = env->get_user_ptr(env, args[0]); // Process keys @@ -679,14 +687,15 @@ static emacs_value Fvterm_update(emacs_env *env, ptrdiff_t nargs, return env->make_integer(env, 0); } -static emacs_value Fvterm_redraw(emacs_env *env, ptrdiff_t nargs, - emacs_value args[], void *data) { +emacs_value Fvterm_redraw(emacs_env *env, ptrdiff_t nargs, emacs_value args[], + void *data) { Term *term = env->get_user_ptr(env, args[0]); term_redraw(term, env); return env->make_integer(env, 0); } -static emacs_value Fvterm_write_input(emacs_env *env, ptrdiff_t nargs, - emacs_value args[], void *data) { + +emacs_value Fvterm_write_input(emacs_env *env, ptrdiff_t nargs, + emacs_value args[], void *data) { Term *term = env->get_user_ptr(env, args[0]); ptrdiff_t len = string_bytes(env, args[1]); char bytes[len]; @@ -699,8 +708,8 @@ static emacs_value Fvterm_write_input(emacs_env *env, ptrdiff_t nargs, return env->make_integer(env, 0); } -static emacs_value Fvterm_set_size(emacs_env *env, ptrdiff_t nargs, - emacs_value args[], void *data) { +emacs_value Fvterm_set_size(emacs_env *env, ptrdiff_t nargs, emacs_value args[], + void *data) { Term *term = env->get_user_ptr(env, args[0]); int rows = env->extract_integer(env, args[1]); int cols = env->extract_integer(env, args[2]); @@ -714,6 +723,22 @@ static emacs_value Fvterm_set_size(emacs_env *env, ptrdiff_t nargs, return Qnil; } + +emacs_value Fvterm_set_pty_name(emacs_env *env, ptrdiff_t nargs, + emacs_value args[], void *data) { + Term *term = env->get_user_ptr(env, args[0]); + + if (nargs > 1) { + ptrdiff_t len = string_bytes(env, args[1]); + char filename[len]; + + env->copy_string_contents(env, args[1], filename, &len); + + term->pty_fd = open(filename, O_RDONLY); + } + return Qnil; +} + int emacs_module_init(struct emacs_runtime *ert) { emacs_env *env = ert->get_environment(ert); @@ -794,6 +819,10 @@ int emacs_module_init(struct emacs_runtime *ert) { "Sets the size of the terminal.", NULL); bind_function(env, "vterm--set-size", fun); + fun = env->make_function(env, 2, 2, Fvterm_set_pty_name, + "Sets the name of the pty.", NULL); + bind_function(env, "vterm--set-pty-name", fun); + provide(env, "vterm-module"); return 0; diff --git a/vterm-module.h b/vterm-module.h index 356a6dd..ca0bcb5 100644 --- a/vterm-module.h +++ b/vterm-module.h @@ -59,6 +59,8 @@ typedef struct Term { bool is_title_changed; int width, height; + + int pty_fd; } Term; static bool compare_cells(VTermScreenCell *a, VTermScreenCell *b); @@ -74,18 +76,23 @@ static void term_redraw(Term *term, emacs_env *env); static void term_flush_output(Term *term, emacs_env *env); static void term_process_key(Term *term, unsigned char *key, size_t len, VTermModifier modifier); -static void term_put_caret(Term *term, emacs_env *env, int row, int col, - int offset); static void invalidate_terminal(Term *term, int start_row, int end_row); static void refresh_size(Term *term); -static void term_finalize(void *object); - -static emacs_value Fvterm_new(emacs_env *env, ptrdiff_t nargs, - emacs_value args[], void *data); -static emacs_value Fvterm_update(emacs_env *env, ptrdiff_t nargs, - emacs_value args[], void *data); -static emacs_value Fvterm_redraw(emacs_env *env, ptrdiff_t nargs, - emacs_value args[], void *data); +void term_finalize(void *object); + +emacs_value Fvterm_new(emacs_env *env, ptrdiff_t nargs, emacs_value args[], + void *data); +emacs_value Fvterm_update(emacs_env *env, ptrdiff_t nargs, emacs_value args[], + void *data); +emacs_value Fvterm_redraw(emacs_env *env, ptrdiff_t nargs, emacs_value args[], + void *data); +emacs_value Fvterm_write_input(emacs_env *env, ptrdiff_t nargs, + emacs_value args[], void *data); +emacs_value Fvterm_set_size(emacs_env *env, ptrdiff_t nargs, emacs_value args[], + void *data); +emacs_value Fvterm_set_pty_name(emacs_env *env, ptrdiff_t nargs, + emacs_value args[], void *data); + int emacs_module_init(struct emacs_runtime *ert); #endif /* VTERM_MODULE_H */ @@ -232,20 +232,22 @@ If nil, never delay") :name "vterm" :buffer (current-buffer) :command `("/bin/sh" "-c" - ,(format "stty -nl sane iutf8 rows %d columns %d >/dev/null && exec %s" + ,(format "stty -nl sane iutf8 erase ^? rows %d columns %d >/dev/null && exec %s" (window-body-height) (window-body-width) vterm-shell)) :coding 'no-conversion :connection-type 'pty :filter #'vterm--filter - :sentinel (when vterm-exit-functions #'vterm--sentinel))))) + :sentinel (when vterm-exit-functions #'vterm--sentinel)))) + (vterm--set-pty-name vterm--term (process-tty-name vterm--process))) ;; Keybindings (define-key vterm-mode-map [tab] #'vterm--self-insert) +(define-key vterm-mode-map [backtab] #'vterm--self-insert) (define-key vterm-mode-map [backspace] #'vterm--self-insert) (define-key vterm-mode-map [M-backspace] #'vterm--self-insert) -(define-key vterm-mode-map [return] #'vterm-send-return) +(define-key vterm-mode-map [return] #'vterm--self-insert) (define-key vterm-mode-map [left] #'vterm--self-insert) (define-key vterm-mode-map [right] #'vterm--self-insert) (define-key vterm-mode-map [up] #'vterm--self-insert) @@ -274,6 +276,15 @@ If nil, never delay") unless (member key vterm-keymap-exceptions) collect key)))) +(defun vterm-event-basic-type (event) + "Same as `event-basic-type', except the downcasing of EVENT." + (if (consp event) + (setq event (car event))) + (if (symbolp event) + (car (get event 'event-symbol-elements)) + (let* ((base (logand event (1- ?\A-\^@)))) + (if (< base 32) (logior base 64) base)))) + (defun vterm--self-insert () "Sends invoking key to libvterm." (interactive) @@ -282,7 +293,7 @@ If nil, never delay") (shift (memq 'shift modifiers)) (meta (memq 'meta modifiers)) (ctrl (memq 'control modifiers))) - (when-let ((key (key-description (vector (event-basic-type last-input-event))))) + (when-let ((key (key-description (vector (vterm-event-basic-type last-input-event))))) (vterm-send-key key shift meta ctrl))))) (defun vterm-send-key (key &optional shift meta ctrl) @@ -290,8 +301,6 @@ If nil, never delay") (when vterm--term (let ((inhibit-redisplay t) (inhibit-read-only t)) - (when (and shift (not meta) (not ctrl)) - (setq key (upcase key))) (vterm--update vterm--term key shift meta ctrl)))) (defun vterm-send-ctrl-c () @@ -304,11 +313,6 @@ If nil, never delay") (interactive) (vterm-send-key "_" nil nil t)) -(defun vterm-send-return () - "Sends C-m to the libvterm." - (interactive) - (process-send-string vterm--process "\C-m")) - (defun vterm-yank () "Implementation of `yank' (paste) in vterm." (interactive) |
