aboutsummaryrefslogtreecommitdiff
path: root/vterm-module.c
diff options
context:
space:
mode:
authorjixiuf <jixiuf@qq.com>2022-04-16 17:46:16 +0800
committerjixiuf <jixiuf@qq.com>2022-04-16 17:46:16 +0800
commit17f80c2259512db55003d78c894c308aaa2283e2 (patch)
tree788db079aa6fcb68728a3d9dce7d60f1fb9f5256 /vterm-module.c
parentc8ddfed84eeb3236ae14dec2aa0bf64eb41d5c40 (diff)
trim trailing whitespace
Diffstat (limited to 'vterm-module.c')
-rw-r--r--vterm-module.c120
1 files changed, 79 insertions, 41 deletions
diff --git a/vterm-module.c b/vterm-module.c
index 72a1e21..efe700a 100644
--- a/vterm-module.c
+++ b/vterm-module.c
@@ -201,18 +201,12 @@ static LineInfo *get_lineinfo(Term *term, int row) {
}
static bool is_eol(Term *term, int end_col, int row, int col) {
/* This cell is EOL if this and every cell to the right is black */
- if (row >= 0) {
- VTermPos pos = {.row = row, .col = col};
- return vterm_screen_is_eol(term->vts, pos);
- }
-
- ScrollbackLine *sbrow = term->sb_buffer[-row - 1];
- int c;
- for (c = col; c < end_col && c < sbrow->cols;) {
- if (sbrow->cells[c].chars[0]) {
+ VTermScreenCell cell;
+ for (int c = col; c < end_col; c++) {
+ fetch_cell(term, row, c, &cell);
+ if (!(!cell.chars[0] || (cell.width == 1 && cell.chars[0] == ' '))) {
return 0;
}
- c += sbrow->cells[c].width;
}
return 1;
}
@@ -232,8 +226,8 @@ static int is_end_of_prompt(Term *term, int end_col, int row, int col) {
}
return 0;
}
-
-static void goto_col(Term *term, emacs_env *env, int row, int end_col) {
+static void goto_col(Term *term, emacs_env *env, int row, int end_col,
+ bool insert_beyond_eol) {
int col = 0;
size_t offset = 0;
size_t beyond_eol = 0;
@@ -248,6 +242,9 @@ static void goto_col(Term *term, emacs_env *env, int row, int end_col) {
if (cell.chars[0]) {
if (cell.width > 1) {
offset += cell.width - 1;
+ } else if (is_eol(term, term->width, row, col)) {
+ beyond_eol += cell.width;
+ offset += cell.width;
}
} else {
if (is_eol(term, term->width, row, col)) {
@@ -257,11 +254,15 @@ static void goto_col(Term *term, emacs_env *env, int row, int end_col) {
}
col += cell.width;
}
-
- forward_char(env, env->make_integer(env, end_col - offset));
- emacs_value space = env->make_string(env, " ", 1);
- for (int i = 0; i < beyond_eol; i += 1)
- insert(env, space);
+ int n = end_col - offset;
+ if (!insert_beyond_eol)
+ n += beyond_eol;
+ forward_char(env, env->make_integer(env, n));
+ if (insert_beyond_eol) {
+ emacs_value space = env->make_string(env, " ", 1);
+ for (int i = 0; i < beyond_eol; i += 1)
+ insert(env, space);
+ }
}
static void refresh_lines(Term *term, emacs_env *env, int start_row,
@@ -273,53 +274,88 @@ static void refresh_lines(Term *term, emacs_env *env, int start_row,
#define PUSH_BUFFER(c) \
do { \
- if (length == capacity) { \
+ if (length + spacelength == capacity) { \
capacity += end_col * 4; \
buffer = realloc(buffer, capacity * sizeof(char)); \
} \
- buffer[length] = (c); \
- length++; \
+ if (c == ' ') { \
+ buffer[length + spacelength] = ' '; \
+ spacelength++; \
+ } else { \
+ /* only increase the line length if the last character is not \
+ * whitespace*/ \
+ buffer[length + spacelength] = (c); \
+ length += 1 + spacelength; \
+ spacelength = 0; \
+ } \
} while (0)
int capacity = ((end_row - start_row + 1) * end_col) * 4;
int length = 0;
+ int spacelength = 0; // count of trailing whitespace
char *buffer = malloc(capacity * sizeof(char));
VTermScreenCell cell;
VTermScreenCell lastCell;
fetch_cell(term, start_row, 0, &lastCell);
for (i = start_row; i < end_row; i++) {
-
+ spacelength = 0;
int newline = 0;
- int isprompt = 0;
+ int isprompt = 0; // is end of prompt
for (j = 0; j < end_col; j++) {
fetch_cell(term, i, j, &cell);
- if (isprompt && length > 0) {
- emacs_value text = render_text(env, term, buffer, length, &lastCell);
- insert(env, render_prompt(env, text));
- length = 0;
+ // This cell is EOL if this and every cell to the right is black
+ bool eol = is_eol(term, end_col, i, j);
+ if (isprompt) { // previous cell is prompt
+ if (length > 0) { // if the prompt char is not whitespace
+ emacs_value text = render_text(env, term, buffer, length, &lastCell);
+ insert(env, render_prompt(env, text));
+ memmove(buffer, buffer + length, spacelength);
+ length = 0;
+ } else if (spacelength > 0 && !eol) {
+ // if the prompt char is whitespace and the cell is not at the end of
+ // line, then render the whitespace as prompt
+ emacs_value text =
+ render_text(env, term, buffer, length + spacelength, &lastCell);
+ insert(env, render_prompt(env, text));
+ length = 0;
+ spacelength = 0;
+ } else if (eol) {
+ // trim trailing whitespace at end of line
+ // and the prompt would be rendered after break
+ spacelength = 0;
+ PUSH_BUFFER('\n');
+ newline = 1;
+ break;
+ }
}
isprompt = is_end_of_prompt(term, end_col, i, j);
- if (isprompt && length > 0) {
- insert(env, render_text(env, term, buffer, length, &lastCell));
+ if (isprompt && length + spacelength > 0) {
+ insert(env,
+ render_text(env, term, buffer, length + spacelength, &lastCell));
length = 0;
+ spacelength = 0;
}
if (!compare_cells(&cell, &lastCell)) {
+ // maybe the trailing whitespace should be rendered togther?
emacs_value text = render_text(env, term, buffer, length, &lastCell);
insert(env, text);
+ // move the trailing whitespace to the start of buffer
+ memmove(buffer, buffer + length, spacelength);
length = 0;
}
-
lastCell = cell;
+
+ if (eol) {
+ // trim trailing whitespace at end of line
+ spacelength = 0;
+ PUSH_BUFFER('\n');
+ newline = 1;
+ break;
+ }
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 */
- PUSH_BUFFER('\n');
- newline = 1;
- break;
- }
PUSH_BUFFER(' ');
} else {
for (int k = 0; k < VTERM_MAX_CHARS_PER_CELL && cell.chars[k]; ++k) {
@@ -335,11 +371,13 @@ static void refresh_lines(Term *term, emacs_env *env, int start_row,
int w = cell.width - 1;
j = j + w;
}
- }
- if (isprompt && length > 0) {
- emacs_value text = render_text(env, term, buffer, length, &lastCell);
+ } // end of range of columns
+ if (isprompt && length + spacelength > 0) {
+ emacs_value text =
+ render_text(env, term, buffer, length + spacelength, &lastCell);
insert(env, render_prompt(env, text));
length = 0;
+ spacelength = 0;
isprompt = 0;
}
@@ -347,6 +385,7 @@ static void refresh_lines(Term *term, emacs_env *env, int start_row,
emacs_value text = render_text(env, term, buffer, length, &lastCell);
insert(env, text);
length = 0;
+ spacelength = 0;
text = render_fake_newline(env, term);
insert(env, text);
}
@@ -486,7 +525,7 @@ static void adjust_topline(Term *term, emacs_env *env) {
*/
goto_line(env, pos.row - term->height);
- goto_col(term, env, pos.row, pos.col);
+ goto_col(term, env, pos.row, pos.col, true);
emacs_value windows = get_buffer_window_list(env);
emacs_value swindow = selected_window(env);
@@ -1393,7 +1432,7 @@ emacs_value Fvterm_reset_cursor_point(emacs_env *env, ptrdiff_t nargs,
Term *term = env->get_user_ptr(env, args[0]);
int line = row_to_linenr(term, term->cursor.row);
goto_line(env, line);
- goto_col(term, env, term->cursor.row, term->cursor.col);
+ goto_col(term, env, term->cursor.row, term->cursor.col, false);
return point(env);
}
@@ -1512,6 +1551,5 @@ int emacs_module_init(struct emacs_runtime *ert) {
bind_function(env, "vterm--get-icrnl", fun);
provide(env, "vterm-module");
-
return 0;
}