aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md19
-rw-r--r--elisp.c5
-rw-r--r--elisp.h2
-rw-r--r--vterm-module.c62
-rw-r--r--vterm-module.h5
-rw-r--r--vterm.el13
6 files changed, 97 insertions, 9 deletions
diff --git a/README.md b/README.md
index 9ab5e0a..4f84f1f 100644
--- a/README.md
+++ b/README.md
@@ -94,6 +94,25 @@ color you like:
- vterm-color-cyan
- vterm-color-white
+## Directory tracking
+
+For `zsh` put this in your `.zshrc`:
+
+```zsh
+function chpwd() {
+ echo -e "\e]51;$(pwd)\e\\"
+}
+```
+
+For bash there's no real change directory hook, so you have to rewrite the cd
+command (please als have a look the answers [here](https://unix.stackexchange.com/q/170279)):
+
+```bash
+cd() {
+ builtin cd "$@" || return
+ [ "$OLDPWD" = "$PWD" ] || echo -e "\e]51;$(pwd)\e\\"
+}
+```
## Related packages
diff --git a/elisp.c b/elisp.c
index beaf5d6..4f2f106 100644
--- a/elisp.c
+++ b/elisp.c
@@ -112,10 +112,15 @@ emacs_value vterm_get_color(emacs_env *env, int index) {
emacs_value idx = env->make_integer(env, index);
return env->funcall(env, Fvterm_get_color, 1, (emacs_value[]){idx});
}
+
void set_title(emacs_env *env, emacs_value string) {
env->funcall(env, Fvterm_set_title, 1, (emacs_value[]){string});
}
+void set_directory(emacs_env *env, emacs_value string) {
+ env->funcall(env, Fvterm_set_directory, 1, (emacs_value[]){string});
+}
+
void vterm_invalidate(emacs_env *env) {
env->funcall(env, Fvterm_invalidate, 0, NULL);
}
diff --git a/elisp.h b/elisp.h
index 6bb149c..5420728 100644
--- a/elisp.h
+++ b/elisp.h
@@ -45,6 +45,7 @@ emacs_value Fvterm_flush_output;
emacs_value Fget_buffer_window;
emacs_value Fselected_window;
emacs_value Fvterm_set_title;
+emacs_value Fvterm_set_directory;
emacs_value Fvterm_invalidate;
emacs_value Feq;
emacs_value Fvterm_get_color;
@@ -74,6 +75,7 @@ void forward_char(emacs_env *env, emacs_value n);
emacs_value get_buffer_window(emacs_env *env);
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);
diff --git a/vterm-module.c b/vterm-module.c
index 4ec78dc..21ace5f 100644
--- a/vterm-module.c
+++ b/vterm-module.c
@@ -376,6 +376,7 @@ static void term_redraw_cursor(Term *term, emacs_env *env) {
static void term_redraw(Term *term, emacs_env *env) {
term_redraw_cursor(term, env);
+
if (term->is_invalidated) {
long bufline_before = env->extract_integer(env, buffer_line_number(env));
refresh_scrollback(term, env);
@@ -384,10 +385,17 @@ static void term_redraw(Term *term, emacs_env *env) {
env->extract_integer(env, buffer_line_number(env)) - bufline_before;
adjust_topline(term, env, line_added);
}
- if (term->is_title_changed) {
+
+ if (term->title_changed) {
set_title(env, env->make_string(env, term->title, strlen(term->title)));
- term->is_title_changed = false;
+ term->title_changed = false;
+ }
+
+ if (term->directory_changed) {
+ set_directory(env, env->make_string(env, term->directory, strlen(term->directory)));
+ term->directory_changed = false;
}
+
term->is_invalidated = false;
}
@@ -417,6 +425,7 @@ static bool is_key(unsigned char *key, size_t len, char *key_description) {
return (len == strlen(key_description) &&
memcmp(key, key_description, len) == 0);
}
+
static void term_set_title(Term *term, char *title) {
size_t len = strlen(title);
if (term->title) {
@@ -425,7 +434,7 @@ static void term_set_title(Term *term, char *title) {
term->title = malloc(sizeof(char) * (len + 1));
strncpy(term->title, title, len);
term->title[len] = 0;
- term->is_title_changed = true;
+ term->title_changed = true;
return;
}
@@ -621,6 +630,11 @@ void term_finalize(void *object) {
term->title = NULL;
}
+ if (term->directory) {
+ free(term->directory);
+ term->directory = NULL;
+ }
+
if (term->pty_fd > 0) {
close(term->pty_fd);
}
@@ -630,6 +644,37 @@ void term_finalize(void *object) {
free(term);
}
+static int osc_callback(const char *command, size_t cmdlen, void *user)
+{
+ Term *term = (Term *) user;
+ char buffer[cmdlen + 1];
+
+ buffer[cmdlen] = '\0';
+ memcpy(buffer, command, cmdlen);
+
+ if (term->directory != NULL) {
+ free(term->directory);
+ term->directory = NULL;
+ }
+
+ if (cmdlen > 3 && buffer[0] == '5' && buffer[1] == '1' && buffer[2] == ';') {
+ term->directory = malloc(cmdlen - 3 + 1);
+ strcpy(term->directory, &buffer[3]);
+ term->directory_changed = true;
+ return 1;
+ }
+ return 0;
+}
+
+static VTermParserCallbacks parser_callbacks = {
+ .text = NULL,
+ .control = NULL,
+ .escape = NULL,
+ .csi = NULL,
+ .osc = &osc_callback,
+ .dcs = NULL,
+};
+
emacs_value Fvterm_new(emacs_env *env, ptrdiff_t nargs, emacs_value args[],
void *data) {
Term *term = malloc(sizeof(Term));
@@ -642,6 +687,10 @@ emacs_value Fvterm_new(emacs_env *env, ptrdiff_t nargs, emacs_value args[],
vterm_set_utf8(term->vt, 1);
term->vts = vterm_obtain_screen(term->vt);
+
+ VTermState *state = vterm_obtain_state(term->vt);
+ vterm_state_set_unrecognised_fallbacks(state, &parser_callbacks, term);
+
vterm_screen_reset(term->vts, 1);
vterm_screen_set_callbacks(term->vts, &vterm_screen_callbacks, term);
vterm_screen_set_damage_merge(term->vts, VTERM_DAMAGE_SCROLL);
@@ -657,7 +706,10 @@ emacs_value Fvterm_new(emacs_env *env, ptrdiff_t nargs, emacs_value args[],
term->pty_fd = -1;
term->title = NULL;
- term->is_title_changed = false;
+ term->title_changed = false;
+
+ term->directory = NULL;
+ term->directory_changed = false;
return env->make_user_ptr(env, term_finalize, term);
}
@@ -796,6 +848,8 @@ int emacs_module_init(struct emacs_runtime *ert) {
Fvterm_set_title =
env->make_global_ref(env, env->intern(env, "vterm--set-title"));
+ Fvterm_set_directory =
+ env->make_global_ref(env, env->intern(env, "vterm--set-directory"));
Fvterm_invalidate =
env->make_global_ref(env, env->intern(env, "vterm--invalidate"));
Feq = env->make_global_ref(env, env->intern(env, "eq"));
diff --git a/vterm-module.h b/vterm-module.h
index ca0bcb5..6a6e792 100644
--- a/vterm-module.h
+++ b/vterm-module.h
@@ -56,7 +56,10 @@ typedef struct Term {
Cursor cursor;
char *title;
- bool is_title_changed;
+ bool title_changed;
+
+ char *directory;
+ bool directory_changed;
int width, height;
diff --git a/vterm.el b/vterm.el
index 6160a88..b09abcc 100644
--- a/vterm.el
+++ b/vterm.el
@@ -529,20 +529,25 @@ Feeds the size change to the virtual terminal."
"Run the `vterm--set-title-hook' with TITLE as argument."
(run-hook-with-args 'vterm-set-title-functions title))
+(defun vterm--set-directory (path)
+ "Set `default-directory' to PATH."
+ (when (file-directory-p path)
+ (setq default-directory path)))
+
(defun vterm--get-color(index)
"Get color by index from `vterm-color-palette'.
Argument INDEX index of color."
(cond
- ((and (>= index 0)(< index 8 ))
+ ((and (>= index 0)(< index 8))
(face-foreground
(elt vterm-color-palette index)
nil 'default))
- ((and (>= index 8 )(< index 16 ))
+ ((and (>= index 8 )(< index 16))
(face-background
(elt vterm-color-palette (% index 8))
nil 'default))
- ( (= index -1) ;-1 foreground
- (face-foreground 'vterm-color-default nil 'default))
+ ((= index -1) ;-1 foreground
+ (face-foreground 'vterm-color-default nil 'default))
(t ;-2 background
(face-background 'vterm-color-default nil 'default))))