From e96c53f5035c841b20937b65142498bd8e161a40 Mon Sep 17 00:00:00 2001 From: Illia Ostapyshyn Date: Sat, 23 Sep 2023 00:32:10 +0200 Subject: Differentiate foreground and background colors Allow using different background and foreground colors for same ANSI index, analogously to how term-mode does it. Remove magical indices for underlined cells with default foreground and inverse-video cells with default background. Instead, pass relevant info to lisp function to handle these cases at higher level. * elisp.c, elisp.h (Fapply): New binding. (vterm_get_color): Add new argument for optional attributes. * vterm-module.c (cell_rgb_color): Pass relevant attributes to vterm_get_color. * vterm.el (vterm--get-color): Use foreground or background color of the face depending on received attributes. * README.md: Update documentation --- README.md | 4 +++- elisp.c | 5 +++-- elisp.h | 3 ++- vterm-module.c | 21 +++++++++++++++------ vterm.el | 40 +++++++++++++++++++++------------------- 5 files changed, 44 insertions(+), 29 deletions(-) diff --git a/README.md b/README.md index e3b93bc..b1b5a65 100644 --- a/README.md +++ b/README.md @@ -529,7 +529,9 @@ is a global minor mode in Emacs, you can use `M-x blink-cursor-mode` to toggle. ## Colors -Customize the following faces to your liking. +Customize the following faces to your liking. It is possible to specify +different colors for foreground and background via the `:foreground` and +`:background` attributes. - vterm-color-black - vterm-color-red diff --git a/elisp.c b/elisp.c index 12d48d0..bf08fbd 100644 --- a/elisp.c +++ b/elisp.c @@ -42,6 +42,7 @@ emacs_value Frecenter; emacs_value Fset_window_point; emacs_value Fwindow_body_height; emacs_value Fpoint; +emacs_value Fapply; emacs_value Fput_text_property; emacs_value Fadd_text_properties; @@ -182,9 +183,9 @@ void set_cursor_blink(emacs_env *env, bool blink) { (emacs_value[]){env->make_integer(env, blink)}); } -emacs_value vterm_get_color(emacs_env *env, int index) { +emacs_value vterm_get_color(emacs_env *env, int index, emacs_value args) { emacs_value idx = env->make_integer(env, index); - return env->funcall(env, Fvterm_get_color, 1, (emacs_value[]){idx}); + return env->funcall(env, Fapply, 3, (emacs_value[]){ Fvterm_get_color, idx, args }); } void set_title(emacs_env *env, emacs_value string) { diff --git a/elisp.h b/elisp.h index 22d7e60..ba5e5fe 100644 --- a/elisp.h +++ b/elisp.h @@ -29,6 +29,7 @@ extern emacs_value Qrear_nonsticky; extern emacs_value Qvterm_prompt; // Emacs functions +extern emacs_value Fapply; extern emacs_value Fblink_cursor_mode; extern emacs_value Fsymbol_value; extern emacs_value Flength; @@ -91,7 +92,7 @@ emacs_value selected_window(emacs_env *env); void set_title(emacs_env *env, emacs_value string); void set_directory(emacs_env *env, emacs_value string); void vterm_invalidate(emacs_env *env); -emacs_value vterm_get_color(emacs_env *env, int index); +emacs_value vterm_get_color(emacs_env *env, int index, emacs_value args); emacs_value vterm_eval(emacs_env *env, emacs_value string); emacs_value vterm_set_selection(emacs_env *env, emacs_value selection_target, emacs_value selection_data); diff --git a/vterm-module.c b/vterm-module.c index b599a37..f6ab477 100644 --- a/vterm-module.c +++ b/vterm-module.c @@ -845,18 +845,26 @@ static emacs_value cell_rgb_color(emacs_env *env, Term *term, VTermScreenCell *cell, bool is_foreground) { VTermColor *color = is_foreground ? &cell->fg : &cell->bg; + int props_len = 0; + emacs_value props[3]; + if (is_foreground) + props[props_len++] = Qforeground; + if (cell->attrs.underline) + props[props_len++] = Qunderline; + if (cell->attrs.reverse) + props[props_len++] = Qreverse; + + emacs_value args = list(env, props, props_len); + /** NOTE: -10 is used as index offset for special indexes, * see C-h f vterm--get-color RET */ - if (VTERM_COLOR_IS_DEFAULT_FG(color)) { - return vterm_get_color(env, -1 + (cell->attrs.underline ? -10 : 0)); - } - if (VTERM_COLOR_IS_DEFAULT_BG(color)) { - return vterm_get_color(env, -2 + (cell->attrs.reverse ? -10 : 0)); + if (VTERM_COLOR_IS_DEFAULT_FG(color) || VTERM_COLOR_IS_DEFAULT_BG(color)) { + return vterm_get_color(env, -1, args); } if (VTERM_COLOR_IS_INDEXED(color)) { if (color->indexed.idx < 16) { - return vterm_get_color(env, color->indexed.idx); + return vterm_get_color(env, color->indexed.idx, args); } else { VTermState *state = vterm_obtain_state(term->vt); vterm_state_get_palette_color(state, color->indexed.idx, color); @@ -1451,6 +1459,7 @@ int emacs_module_init(struct emacs_runtime *ert) { Qcursor_type = env->make_global_ref(env, env->intern(env, "cursor-type")); // Functions + Fapply = env->make_global_ref(env, env->intern(env, "apply")); Fblink_cursor_mode = env->make_global_ref(env, env->intern(env, "blink-cursor-mode")); Fsymbol_value = env->make_global_ref(env, env->intern(env, "symbol-value")); diff --git a/vterm.el b/vterm.el index 8c56e08..ebb5b2a 100644 --- a/vterm.el +++ b/vterm.el @@ -1654,25 +1654,27 @@ If N is negative backward-line from end of buffer." (when raw-pwd (vterm--get-directory raw-pwd))))) -(defun vterm--get-color (index) - "Get color by index from `vterm-color-palette'. -Argument INDEX index of the terminal color. -Special values for INDEX are: --11 foreground for cells with underline attribute, foreground of -the `vterm-color-underline' face is used in this case. --12 background for cells with inverse video attribute, background -of the `vterm-color-inverse-video' face is used in this case." - (cond - ((and (>= index 0) (< index 16)) - (face-foreground - (elt vterm-color-palette index) - nil 'default)) - ((= index -11) - (face-foreground 'vterm-color-underline nil 'default)) - ((= index -12) - (face-background 'vterm-color-inverse-video nil 'default)) - (t - nil))) +(defun vterm--get-color (index &rest args) + "Get color by INDEX from `vterm-color-palette'. + +Special INDEX of -1 is used to represent default colors. ARGS +may optionally contain `:underline' or `:inverse-video' for cells +with underline or inverse video attribute. If ARGS contains +`:foreground', use foreground color of the respective face +instead of background." + (let ((foreground (member :foreground args)) + (underline (member :underline args)) + (inverse-video (member :inverse-video args))) + (funcall (if foreground #'face-foreground #'face-background) + (cond + ((and (>= index 0) (< index 16)) + (elt vterm-color-palette index)) + ((and (= index -1) foreground underline) + 'vterm-color-underline) + ((and (= index -1) (not foreground) inverse-video) + 'vterm-color-inverse-video) + (t 'default)) + nil 'default))) (defun vterm--eval (str) "Check if string STR is `vterm-eval-cmds' and execute command. -- cgit v1.0