diff options
| -rw-r--r-- | README.md | 17 | ||||
| -rw-r--r-- | elisp.c | 31 | ||||
| -rw-r--r-- | elisp.h | 5 | ||||
| -rw-r--r-- | vterm-module.c | 62 | ||||
| -rw-r--r-- | vterm-module.h | 12 | ||||
| -rw-r--r-- | vterm.el | 51 |
6 files changed, 178 insertions, 0 deletions
@@ -33,6 +33,23 @@ And add this to your `init.el` M-x vterm-create ``` +# Customization + +## Colors + +Set the `:foreground` and `:background` attributes of the following faces to a +color you like: + +- vterm +- vterm-color-black +- vterm-color-red +- vterm-color-green +- vterm-color-yellow +- vterm-color-blue +- vterm-color-magenta +- vterm-color-cyan +- vterm-color-white + # Limitations - No support for scrolling (But you can use tmux/screen to emulate scrolling) @@ -54,6 +54,27 @@ emacs_value color_to_rgb_string(emacs_env *env, VTermColor color) { return env->make_string(env, buffer, 7); }; +uint8_t hex_to_byte(char *hex) { return strtoul(hex, NULL, 16); } + +VTermColor rgb_string_to_color(emacs_env *env, emacs_value string) { + VTermColor color; + ptrdiff_t len = 8; + char buffer[len]; + char hex[3]; + env->copy_string_contents(env, string, buffer, &len); + hex[0] = buffer[1]; + hex[1] = buffer[2]; + color.red = hex_to_byte(hex); + hex[0] = buffer[3]; + hex[1] = buffer[4]; + color.green = hex_to_byte(hex); + hex[0] = buffer[5]; + hex[1] = buffer[6]; + color.blue = hex_to_byte(hex); + + return color; +}; + void erase_buffer(emacs_env *env) { env->funcall(env, Ferase_buffer, 0, NULL); } void insert(emacs_env *env, emacs_value string) { @@ -69,3 +90,13 @@ void toggle_cursor(emacs_env *env, bool visible) { emacs_value Qvisible = visible ? Qt : Qnil; env->funcall(env, Fset, 2, (emacs_value[]){Qcursor_type, Qvisible}); } + +emacs_value get_hex_color_fg(emacs_env *env, emacs_value face) { + return env->funcall(env, Fvterm_face_color_hex, 2, + (emacs_value[]){face, Qforeground}); +} + +emacs_value get_hex_color_bg(emacs_env *env, emacs_value face) { + return env->funcall(env, Fvterm_face_color_hex, 2, + (emacs_value[]){face, Qbackground}); +} @@ -28,6 +28,7 @@ emacs_value Finsert; emacs_value Fgoto_char; emacs_value Fput_text_property; emacs_value Fset; +emacs_value Fvterm_face_color_hex; // Utils void bind_function(emacs_env *env, const char *name, emacs_value Sfun); @@ -39,9 +40,13 @@ void put_text_property(emacs_env *env, emacs_value string, emacs_value property, emacs_value value); void byte_to_hex(uint8_t byte, char *hex); emacs_value color_to_rgb_string(emacs_env *env, VTermColor color); +uint8_t hex_to_byte(char *hex); +VTermColor rgb_string_to_color(emacs_env *env, emacs_value string); void erase_buffer(emacs_env *env); void insert(emacs_env *env, emacs_value string); void goto_char(emacs_env *env, int pos); void toggle_cursor(emacs_env *env, bool visible); +emacs_value get_hex_color_fg(emacs_env *env, emacs_value face); +emacs_value get_hex_color_bg(emacs_env *env, emacs_value face); #endif /* ELISP_H */ diff --git a/vterm-module.c b/vterm-module.c index 4f59cd5..55e0ee9 100644 --- a/vterm-module.c +++ b/vterm-module.c @@ -136,6 +136,54 @@ static void term_redraw(struct Term *term, emacs_env *env) { term_put_caret(term, env, pos.row, pos.col, -offset); } +static void term_setup_colors(struct Term *term, emacs_env *env) { + VTermState *state = vterm_obtain_state(term->vt); + VTermColor fg = rgb_string_to_color(env, get_hex_color_fg(env, Qterm)); + VTermColor bg = rgb_string_to_color(env, get_hex_color_bg(env, Qterm)); + + vterm_state_set_default_colors(state, &fg, &bg); + + fg = rgb_string_to_color(env, get_hex_color_fg(env, Qterm_color_black)); + vterm_state_set_palette_color(state, 0, &fg); + bg = rgb_string_to_color(env, get_hex_color_bg(env, Qterm_color_black)); + vterm_state_set_palette_color(state, 8, &bg); + + fg = rgb_string_to_color(env, get_hex_color_fg(env, Qterm_color_red)); + vterm_state_set_palette_color(state, 1, &fg); + bg = rgb_string_to_color(env, get_hex_color_bg(env, Qterm_color_red)); + vterm_state_set_palette_color(state, 9, &bg); + + fg = rgb_string_to_color(env, get_hex_color_fg(env, Qterm_color_green)); + vterm_state_set_palette_color(state, 2, &fg); + bg = rgb_string_to_color(env, get_hex_color_bg(env, Qterm_color_green)); + vterm_state_set_palette_color(state, 10, &bg); + + fg = rgb_string_to_color(env, get_hex_color_fg(env, Qterm_color_yellow)); + vterm_state_set_palette_color(state, 3, &fg); + bg = rgb_string_to_color(env, get_hex_color_bg(env, Qterm_color_yellow)); + vterm_state_set_palette_color(state, 11, &bg); + + fg = rgb_string_to_color(env, get_hex_color_fg(env, Qterm_color_blue)); + vterm_state_set_palette_color(state, 4, &fg); + bg = rgb_string_to_color(env, get_hex_color_bg(env, Qterm_color_blue)); + vterm_state_set_palette_color(state, 12, &bg); + + fg = rgb_string_to_color(env, get_hex_color_fg(env, Qterm_color_magenta)); + vterm_state_set_palette_color(state, 5, &fg); + bg = rgb_string_to_color(env, get_hex_color_bg(env, Qterm_color_magenta)); + vterm_state_set_palette_color(state, 13, &bg); + + fg = rgb_string_to_color(env, get_hex_color_fg(env, Qterm_color_cyan)); + vterm_state_set_palette_color(state, 6, &fg); + bg = rgb_string_to_color(env, get_hex_color_bg(env, Qterm_color_cyan)); + vterm_state_set_palette_color(state, 14, &bg); + + fg = rgb_string_to_color(env, get_hex_color_fg(env, Qterm_color_white)); + vterm_state_set_palette_color(state, 7, &fg); + bg = rgb_string_to_color(env, get_hex_color_bg(env, Qterm_color_white)); + vterm_state_set_palette_color(state, 15, &bg); +} + static void term_flush_output(struct Term *term) { size_t bufflen = vterm_output_get_buffer_current(term->vt); if (bufflen) { @@ -293,6 +341,8 @@ static emacs_value Fvterm_new(emacs_env *env, ptrdiff_t nargs, term->vt = vterm_new(rows, cols); vterm_set_utf8(term->vt, 1); + term_setup_colors(term, env); + VTermScreen *screen = vterm_obtain_screen(term->vt); vterm_screen_reset(screen, 1); @@ -424,6 +474,18 @@ int emacs_module_init(struct emacs_runtime *ert) { Fgoto_char = env->intern(env, "goto-char"); Fput_text_property = env->intern(env, "put-text-property"); Fset = env->intern(env, "set"); + Fvterm_face_color_hex = env->intern(env, "vterm-face-color-hex"); + + // Faces + Qterm = env->intern(env, "vterm"); + Qterm_color_black = env->intern(env, "vterm-color-black"); + Qterm_color_red = env->intern(env, "vterm-color-red"); + Qterm_color_green = env->intern(env, "vterm-color-green"); + Qterm_color_yellow = env->intern(env, "vterm-color-yellow"); + Qterm_color_blue = env->intern(env, "vterm-color-blue"); + Qterm_color_magenta = env->intern(env, "vterm-color-magenta"); + Qterm_color_cyan = env->intern(env, "vterm-color-cyan"); + Qterm_color_white = env->intern(env, "vterm-color-white"); // Exported functions emacs_value fun; diff --git a/vterm-module.h b/vterm-module.h index 11c9531..b971592 100644 --- a/vterm-module.h +++ b/vterm-module.h @@ -15,6 +15,17 @@ struct Term { pthread_t thread; }; +// Faces +emacs_value Qterm; +emacs_value Qterm_color_black; +emacs_value Qterm_color_red; +emacs_value Qterm_color_green; +emacs_value Qterm_color_yellow; +emacs_value Qterm_color_blue; +emacs_value Qterm_color_magenta; +emacs_value Qterm_color_cyan; +emacs_value Qterm_color_white; + 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, char *string, int len, @@ -23,6 +34,7 @@ static emacs_value render_text(emacs_env *env, char *string, int len, static int set_term_prop_cb(VTermProp prop, VTermValue *val, void *user_data); static void term_redraw(struct Term *term, emacs_env *env); +static void term_setup_colors(struct Term *term, emacs_env *env); static void term_flush_output(struct Term *term); static void term_process_key(struct Term *term, unsigned char *key, size_t len, VTermModifier modifier); @@ -10,6 +10,7 @@ (require 'vterm-module) (require 'subr-x) (require 'cl-lib) +(require 'color) (defvar vterm-term nil "Pointer to struct Term.") @@ -24,6 +25,52 @@ If you use a keybinding with a prefix-key that prefix-key cannot be send to the terminal.") + +(defface vterm + '((t :inherit default)) + "Default face to use in Term mode." + :group 'vterm) + +(defface vterm-color-black + '((t :foreground "black" :background "black")) + "Face used to render black color code." + :group 'vterm) + +(defface vterm-color-red + '((t :foreground "red3" :background "red3")) + "Face used to render red color code." + :group 'vterm) + +(defface vterm-color-green + '((t :foreground "green3" :background "green3")) + "Face used to render green color code." + :group 'vterm) + +(defface vterm-color-yellow + '((t :foreground "yellow3" :background "yellow3")) + "Face used to render yellow color code." + :group 'vterm) + +(defface vterm-color-blue + '((t :foreground "blue2" :background "blue2")) + "Face used to render blue color code." + :group 'vterm) + +(defface vterm-color-magenta + '((t :foreground "magenta3" :background "magenta3")) + "Face used to render magenta color code." + :group 'vterm) + +(defface vterm-color-cyan + '((t :foreground "cyan3" :background "cyan3")) + "Face used to render cyan color code." + :group 'vterm) + +(defface vterm-color-white + '((t :foreground "white" :background "white")) + "Face used to render white color code." + :group 'vterm) + (define-derived-mode vterm-mode fundamental-mode "VTerm" "Mayor mode for vterm buffer." (buffer-disable-undo) @@ -102,5 +149,9 @@ be send to the terminal.") (when (eq major-mode 'vterm-mode) (vterm-set-size vterm-term (window-body-height) (window-body-width))))))) +(defun vterm-face-color-hex (face attr) + "Return the color of the FACE's ATTR as a hex string." + (apply #'color-rgb-to-hex (color-name-to-rgb (face-attribute face attr nil 'default)))) + (provide 'vterm) ;;; vterm.el ends here |
