summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/charset.c3
-rw-r--r--src/feature.h6
-rw-r--r--src/option.h3
-rw-r--r--src/optiondefs.h9
-rw-r--r--src/terminal.c75
-rw-r--r--src/testdir/check.vim8
-rw-r--r--src/testdir/test_terminal3.vim29
-rw-r--r--src/version.c2
8 files changed, 133 insertions, 2 deletions
diff --git a/src/charset.c b/src/charset.c
index d06a273643..db0c146f88 100644
--- a/src/charset.c
+++ b/src/charset.c
@@ -2005,7 +2005,8 @@ hex2nr(int c)
return c - '0';
}
-#if defined(FEAT_TERMRESPONSE) || defined(FEAT_GUI_GTK) || defined(PROTO)
+#if defined(FEAT_TERMRESPONSE) || defined(FEAT_GUI_GTK) \
+ || defined(PROTO) || defined(FEAT_AUTOSHELLDIR)
/*
* Convert two hex characters to a byte.
* Return -1 if one of the characters is not hex.
diff --git a/src/feature.h b/src/feature.h
index 5f6f800c22..4df73d1cb4 100644
--- a/src/feature.h
+++ b/src/feature.h
@@ -1148,6 +1148,12 @@
#endif
/*
+ * +autoshelldir 'autoshelldir' option.
+ */
+#if defined(FEAT_TERMINAL)
+# define FEAT_AUTOSHELLDIR
+#endif
+/*
* +textprop and +popupwin Text PROPerties and POPUP windows
*/
#if defined(FEAT_EVAL) && defined(FEAT_SYN_HL)
diff --git a/src/option.h b/src/option.h
index 349268c3d4..0b1183fecf 100644
--- a/src/option.h
+++ b/src/option.h
@@ -383,6 +383,9 @@ EXTERN char_u *p_ambw; // 'ambiwidth'
#ifdef FEAT_AUTOCHDIR
EXTERN int p_acd; // 'autochdir'
#endif
+#ifdef FEAT_AUTOSHELLDIR
+EXTERN int p_asd; // 'autoshelldir'
+#endif
EXTERN int p_ai; // 'autoindent'
EXTERN int p_bin; // 'binary'
EXTERN int p_bomb; // 'bomb'
diff --git a/src/optiondefs.h b/src/optiondefs.h
index dcd195d7ef..42f355c287 100644
--- a/src/optiondefs.h
+++ b/src/optiondefs.h
@@ -372,6 +372,15 @@ static struct vimoption options[] =
{(char_u *)0L, (char_u *)0L}
#endif
SCTX_INIT},
+ {"autoshelldir", "asd", P_BOOL|P_VI_DEF,
+#ifdef FEAT_AUTOSHELLDIR
+ (char_u *)&p_asd, PV_NONE,
+ {(char_u *)FALSE, (char_u *)0L}
+#else
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)0L, (char_u *)0L}
+#endif
+ SCTX_INIT},
{"autoindent", "ai", P_BOOL|P_VI_DEF,
(char_u *)&p_ai, PV_AI,
{(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
diff --git a/src/terminal.c b/src/terminal.c
index 4c43ea7482..6f07055ebc 100644
--- a/src/terminal.c
+++ b/src/terminal.c
@@ -4293,6 +4293,73 @@ handle_call_command(term_T *term, channel_T *channel, listitem_T *item)
}
/*
+ * URL decoding (also know as Percent-encoding).
+ *
+ * Note this function currently is only used for decoding shell's
+ * OSC 7 escape sequence which we can assume all bytes are valid
+ * UTF-8 bytes. Thus we don't need to deal with invalid UTF-8
+ * encoding bytes like 0xfe, 0xff.
+ */
+ static size_t
+url_decode(const char *src, const size_t len, char_u *dst)
+{
+ size_t i = 0, j = 0;
+
+ while (i < len)
+ {
+ if (src[i] == '%' && i + 2 < len)
+ {
+ dst[j] = hexhex2nr((char_u *)&src[i + 1]);
+ j++;
+ i += 3;
+ }
+ else
+ {
+ dst[j] = src[i];
+ i++;
+ j++;
+ }
+ }
+ dst[j] = '\0';
+ return j;
+}
+
+/*
+ * Sync terminal buffer's cwd with shell's pwd with the help of OSC 7.
+ *
+ * The OSC 7 sequence has the format of
+ * "\033]7;file://HOSTNAME/CURRENT/DIR\033\\"
+ * and what VTerm provides via VTermStringFragment is
+ * "file://HOSTNAME/CURRENT/DIR"
+ */
+ static void
+sync_shell_dir(VTermStringFragment *frag)
+{
+ int offset = 7; // len of "file://" is 7
+ char *pos = (char *)frag->str + offset;
+ char_u *new_dir;
+
+ // remove HOSTNAME to get PWD
+ while (*pos != '/' && offset < frag->len)
+ {
+ offset += 1;
+ pos += 1;
+ }
+
+ if (offset >= frag->len)
+ {
+ semsg(_(e_failed_to_extract_pwd_from_str_check_your_shell_config),
+ frag->str);
+ return;
+ }
+
+ new_dir = alloc(frag->len - offset + 1);
+ url_decode(pos, frag->len-offset, new_dir);
+ changedir_func(new_dir, TRUE, CDSCOPE_WINDOW);
+ vim_free(new_dir);
+}
+
+/*
* Called by libvterm when it cannot recognize an OSC sequence.
* We recognize a terminal API command.
*/
@@ -4306,7 +4373,13 @@ parse_osc(int command, VTermStringFragment frag, void *user)
: term->tl_job->jv_channel;
garray_T *gap = &term->tl_osc_buf;
- // We recognize only OSC 5 1 ; {command}
+ // We recognize only OSC 5 1 ; {command} and OSC 7 ; {command}
+ if (p_asd && command == 7)
+ {
+ sync_shell_dir(&frag);
+ return 1;
+ }
+
if (command != 51)
return 0;
diff --git a/src/testdir/check.vim b/src/testdir/check.vim
index 6190399e5d..4c5f3eef5d 100644
--- a/src/testdir/check.vim
+++ b/src/testdir/check.vim
@@ -92,6 +92,14 @@ func CheckLinux()
endif
endfunc
+" Command to check for not running on a BSD system.
+command CheckNotBSD call CheckNotBSD()
+func CheckNotBSD()
+ if has('bsd')
+ throw 'Skipped: does not work on BSD'
+ endif
+endfunc
+
" Command to check that making screendumps is supported.
" Caller must source screendump.vim
command CheckScreendump call CheckScreendump()
diff --git a/src/testdir/test_terminal3.vim b/src/testdir/test_terminal3.vim
index 037d935582..ab926b686a 100644
--- a/src/testdir/test_terminal3.vim
+++ b/src/testdir/test_terminal3.vim
@@ -475,6 +475,35 @@ func Test_term_mouse()
call delete('Xbuf')
endfunc
+" Test for sync buffer cwd with shell's pwd
+func Test_terminal_sync_shell_dir()
+ CheckUnix
+ " The test always use sh (see src/testdir/unix.vim).
+ " However, BSD's sh doesn't seem to play well with OSC 7 escape sequence.
+ CheckNotBSD
+
+ set asd
+ " , is
+ " 1. a valid character for directory names
+ " 2. a reserved character in url-encoding
+ let chars = ",a"
+ " "," is url-encoded as '%2C'
+ let chars_url = "%2Ca"
+ let tmpfolder = fnamemodify(tempname(),':h').'/'.chars
+ let tmpfolder_url = fnamemodify(tempname(),':h').'/'.chars_url
+ call mkdir(tmpfolder, "p")
+ let buf = Run_shell_in_terminal({})
+ call term_sendkeys(buf, "echo -ne $'\\e\]7;file://".tmpfolder_url."\\a'\<CR>")
+ "call term_sendkeys(buf, "cd ".tmpfolder."\<CR>")
+ call TermWait(buf)
+ if has("mac")
+ let expected = "/private".tmpfolder
+ else
+ let expected = tmpfolder
+ endif
+ call assert_equal(expected, getcwd(winnr()))
+endfunc
+
" Test for modeless selection in a terminal
func Test_term_modeless_selection()
CheckUnix
diff --git a/src/version.c b/src/version.c
index da20571e26..bc47c43909 100644
--- a/src/version.c
+++ b/src/version.c
@@ -751,6 +751,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 2675,
+/**/
2674,
/**/
2673,