diff options
| -rw-r--r-- | elisp.c | 9 | ||||
| -rw-r--r-- | elisp.h | 5 | ||||
| -rw-r--r-- | vterm-module.c | 36 | ||||
| -rw-r--r-- | vterm-module.h | 1 | ||||
| -rw-r--r-- | vterm.el | 19 |
5 files changed, 67 insertions, 3 deletions
@@ -49,6 +49,15 @@ void put_text_property(emacs_env *env, emacs_value string, emacs_value property, (emacs_value[]){start, end, property, value, string}); } +void add_text_properties(emacs_env *env, emacs_value string, + emacs_value property) { + emacs_value start = env->make_integer(env, 0); + emacs_value end = length(env, string); + + env->funcall(env, Fadd_text_properties, 4, + (emacs_value[]){start, end, property, string}); +} + void erase_buffer(emacs_env *env) { env->funcall(env, Ferase_buffer, 0, NULL); } void insert(emacs_env *env, emacs_value string) { @@ -24,6 +24,8 @@ emacs_value Qbar; emacs_value Qhbar; emacs_value Qcursor_type; emacs_value Qemacs_major_version; +emacs_value Qvterm_line_wrap; +emacs_value Qrear_nonsticky; // Emacs functions emacs_value Fsymbol_value; @@ -43,6 +45,7 @@ emacs_value Fwindow_body_height; emacs_value Fpoint; emacs_value Fput_text_property; +emacs_value Fadd_text_properties; emacs_value Fset; emacs_value Fvterm_flush_output; emacs_value Fget_buffer_window_list; @@ -64,6 +67,8 @@ emacs_value list(emacs_env *env, emacs_value elements[], ptrdiff_t len); emacs_value nth(emacs_env *env, int idx, emacs_value list); void put_text_property(emacs_env *env, emacs_value string, emacs_value property, emacs_value value); +void add_text_properties(emacs_env *env, emacs_value string, + emacs_value property); void erase_buffer(emacs_env *env); void insert(emacs_env *env, emacs_value string); void goto_char(emacs_env *env, int pos); diff --git a/vterm-module.c b/vterm-module.c index 73330e6..a635427 100644 --- a/vterm-module.c +++ b/vterm-module.c @@ -257,6 +257,8 @@ static void refresh_lines(Term *term, emacs_env *env, int start_row, int offset = 0; for (i = start_row; i < end_row; i++) { + + int newline = 0; for (j = 0; j < end_col; j++) { fetch_cell(term, i, j, &cell); @@ -270,6 +272,9 @@ static void refresh_lines(Term *term, emacs_env *env, int start_row, if (cell.chars[0] == 0) { if (is_eol(term, end_col, i, j)) { /* This cell is EOL if this and every cell to the right is black */ + buffer[length] = '\n'; + length++; + newline = 1; break; } buffer[length] = ' '; @@ -290,8 +295,13 @@ static void refresh_lines(Term *term, emacs_env *env, int start_row, } } - buffer[length] = '\n'; - length++; + if (!newline) { + emacs_value text = render_text(env, term, buffer, length, &lastCell); + insert(env, text); + length = 0; + text = render_fake_newline(env, term); + insert(env, text); + } } emacs_value text = render_text(env, term, buffer, length, &lastCell); insert(env, text); @@ -657,6 +667,21 @@ static emacs_value render_text(emacs_env *env, Term *term, char *buffer, return text; } +static emacs_value render_fake_newline(emacs_env *env, Term *term) { + + emacs_value text; + text = env->make_string(env, "\n", 1); + + emacs_value properties; + + properties = + list(env, (emacs_value[]){Qvterm_line_wrap, Qt, Qrear_nonsticky, Qt}, 4); + + add_text_properties(env, text, properties); + + return text; +} + static emacs_value color_to_rgb_string(emacs_env *env, Term *term, VTermColor *color) { if (VTERM_COLOR_IS_DEFAULT_FG(color)) { @@ -1129,6 +1154,10 @@ int emacs_module_init(struct emacs_runtime *ert) { Qextend = env->make_global_ref(env, env->intern(env, ":extend")); Qemacs_major_version = env->make_global_ref(env, env->intern(env, "emacs-major-version")); + Qvterm_line_wrap = + env->make_global_ref(env, env->intern(env, "vterm-line-wrap")); + Qrear_nonsticky = + env->make_global_ref(env, env->intern(env, "rear-nonsticky")); Qface = env->make_global_ref(env, env->intern(env, "font-lock-face")); Qbox = env->make_global_ref(env, env->intern(env, "box")); @@ -1146,6 +1175,8 @@ int emacs_module_init(struct emacs_runtime *ert) { Fgoto_char = env->make_global_ref(env, env->intern(env, "goto-char")); Fput_text_property = env->make_global_ref(env, env->intern(env, "put-text-property")); + Fadd_text_properties = + env->make_global_ref(env, env->intern(env, "add-text-properties")); Fset = env->make_global_ref(env, env->intern(env, "set")); Fvterm_flush_output = env->make_global_ref(env, env->intern(env, "vterm--flush-output")); @@ -1212,7 +1243,6 @@ int emacs_module_init(struct emacs_runtime *ert) { "Reset cursor postion.", NULL); bind_function(env, "vterm--reset-point", fun); - fun = env->make_function(env, 1, 1, Fvterm_get_icrnl, "Gets the icrnl state of the pty", NULL); bind_function(env, "vterm--get-icrnl", fun); diff --git a/vterm-module.h b/vterm-module.h index 5be8b49..752d744 100644 --- a/vterm-module.h +++ b/vterm-module.h @@ -90,6 +90,7 @@ static bool compare_cells(VTermScreenCell *a, VTermScreenCell *b); static bool is_key(unsigned char *key, size_t len, char *key_description); static emacs_value render_text(emacs_env *env, Term *term, char *string, int len, VTermScreenCell *cell); +static emacs_value render_fake_newline(emacs_env *env, Term *term); static emacs_value color_to_rgb_string(emacs_env *env, Term *term, VTermColor *color); @@ -264,6 +264,9 @@ If nil, never delay") (setq-local hscroll-margin 0) (setq-local hscroll-step 1) (setq-local truncate-lines t) + (add-function :filter-return + (local 'filter-buffer-substring-function) + #'vterm--filter-buffer-substring) (setq vterm--process (make-process :name "vterm" @@ -876,5 +879,21 @@ Effectively toggle between the two positions." (goto-char prompt-pt) (beginning-of-line))))) +(defun vterm--remove-fake-newlines () + (goto-char (point-min)) + (let (fake-newline) + (while (setq fake-newline (next-single-property-change (point) + 'vterm-line-wrap)) + (goto-char fake-newline) + (cl-assert (eq ?\n (char-after))) + (let ((inhibit-read-only t)) + (delete-char 1))))) + +(defun vterm--filter-buffer-substring (content) + (with-temp-buffer + (insert content) + (vterm--remove-fake-newlines) + (buffer-string))) + (provide 'vterm) ;;; vterm.el ends here |
