aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Brumlow <mbrumlow@roblox.com>2020-03-19 23:19:36 -0700
committerMike Brumlow <mbrumlow@roblox.com>2020-03-19 23:19:36 -0700
commit68f413b03336cff2ef0ec8c0f5bd8ec642c102d9 (patch)
tree772b4d86e50b3f2526d06cebd68e18f35b773aaf
parentd02be51ae5c75844134858b683de528997048ec5 (diff)
This commit fixes the newlines when copied and pasted.
This commit fixes up the newlines that were inserted for wrapping using the same approach as term.el does. It does so by adding a property to the '\n' chars that were inserted as a result of wrapping the terminal. When killing a region text will be passed through the filter-buffer-substring-function vterm--remove-fake-newlines removing the wrapped new lines by looking for the 'vterm-line-wrap property and removing the char that corresponds. If this change set is not up to project standards please work with me to correct any issues you find.
-rw-r--r--vterm-module.c39
-rw-r--r--vterm-module.h2
-rw-r--r--vterm.el19
3 files changed, 58 insertions, 2 deletions
diff --git a/vterm-module.c b/vterm-module.c
index 73330e6..79f3df2 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,15 @@ 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, buffer, length, &lastCell);
+ insert(env, text);
+ }
+
}
emacs_value text = render_text(env, term, buffer, length, &lastCell);
insert(env, text);
@@ -657,6 +669,25 @@ 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, char *buffer,
+ int len, VTermScreenCell *cell) {
+
+ 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 +1160,8 @@ 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 +1179,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"));
diff --git a/vterm-module.h b/vterm-module.h
index 5be8b49..b5e7ebe 100644
--- a/vterm-module.h
+++ b/vterm-module.h
@@ -90,6 +90,8 @@ 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, char *string,
+ int len, VTermScreenCell *cell);
static emacs_value color_to_rgb_string(emacs_env *env, Term *term,
VTermColor *color);
diff --git a/vterm.el b/vterm.el
index b44300e..0daaf42 100644
--- a/vterm.el
+++ b/vterm.el
@@ -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