mirror of
https://github.com/vim/vim.git
synced 2025-09-24 03:44:06 -04:00
patch 8.2.2675: directory change in a terminal window shell is not followed
Problem: Directory change in a terminal window shell is not followed. Solution: Add the 'autoshelldir' option. (closes #6290)
This commit is contained in:
@@ -749,6 +749,15 @@ A jump table for the options with a short description can be found at |Q_op|.
|
||||
or selected.
|
||||
Note: When this option is on some plugins may not work.
|
||||
|
||||
*'autoshelldir'* *'asd'* *'noautoshelldir'* *'noasd'*
|
||||
'autoshelldir' 'asd' boolean (default off)
|
||||
global
|
||||
When on, Vim will change the current working directory whenever you
|
||||
change the directory of the shell running in a terminal window. You
|
||||
need proper setting-up, so whenever the shell's pwd changes an OSC 7
|
||||
escape sequence will be emitted. For example, on Linux, you can source
|
||||
/etc/profile.d/vte.sh in your shell profile if you use bash or zsh.
|
||||
|
||||
*'arabic'* *'arab'* *'noarabic'* *'noarab'*
|
||||
'arabic' 'arab' boolean (default off)
|
||||
local to window
|
||||
|
@@ -605,6 +605,7 @@ Short explanation of each option: *option-list*
|
||||
'ambiwidth' 'ambw' what to do with Unicode chars of ambiguous width
|
||||
'antialias' 'anti' Mac OS X: use smooth, antialiased fonts
|
||||
'autochdir' 'acd' change directory to the file in the current window
|
||||
'autoshelldir' 'asd' change directory to the shell's current directory
|
||||
'arabic' 'arab' for Arabic as a default second language
|
||||
'arabicshape' 'arshape' do shaping for Arabic characters
|
||||
'autoindent' 'ai' take indent for new line from previous line
|
||||
|
@@ -266,6 +266,8 @@ if exists("+autochdir")
|
||||
call <SID>AddOption("autochdir", gettext("change to directory of file in buffer"))
|
||||
call <SID>BinOptionG("acd", &acd)
|
||||
endif
|
||||
call <SID>AddOption("autoshelldir", gettext("change to pwd of shell in terminal buffer"))
|
||||
call <SID>BinOptionG("asd", &asd)
|
||||
call <SID>AddOption("wrapscan", gettext("search commands wrap around the end of the buffer"))
|
||||
call <SID>BinOptionG("ws", &ws)
|
||||
call <SID>AddOption("incsearch", gettext("show match for partly typed search command"))
|
||||
|
@@ -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.
|
||||
|
@@ -1147,6 +1147,12 @@
|
||||
# define FEAT_SYN_HL
|
||||
#endif
|
||||
|
||||
/*
|
||||
* +autoshelldir 'autoshelldir' option.
|
||||
*/
|
||||
#if defined(FEAT_TERMINAL)
|
||||
# define FEAT_AUTOSHELLDIR
|
||||
#endif
|
||||
/*
|
||||
* +textprop and +popupwin Text PROPerties and POPUP windows
|
||||
*/
|
||||
|
@@ -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'
|
||||
|
@@ -370,6 +370,15 @@ static struct vimoption options[] =
|
||||
#else
|
||||
(char_u *)NULL, PV_NONE,
|
||||
{(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,
|
||||
|
@@ -4292,6 +4292,73 @@ handle_call_command(term_T *term, channel_T *channel, listitem_T *item)
|
||||
ch_log(channel, "Calling function %s failed", func);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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;
|
||||
|
||||
|
@@ -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()
|
||||
|
@@ -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
|
||||
|
@@ -750,6 +750,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
2675,
|
||||
/**/
|
||||
2674,
|
||||
/**/
|
||||
|
Reference in New Issue
Block a user