mirror of
https://github.com/vim/vim.git
synced 2025-09-25 03:54:15 -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.
|
or selected.
|
||||||
Note: When this option is on some plugins may not work.
|
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'* *'noarabic'* *'noarab'*
|
||||||
'arabic' 'arab' boolean (default off)
|
'arabic' 'arab' boolean (default off)
|
||||||
local to window
|
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
|
'ambiwidth' 'ambw' what to do with Unicode chars of ambiguous width
|
||||||
'antialias' 'anti' Mac OS X: use smooth, antialiased fonts
|
'antialias' 'anti' Mac OS X: use smooth, antialiased fonts
|
||||||
'autochdir' 'acd' change directory to the file in the current window
|
'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
|
'arabic' 'arab' for Arabic as a default second language
|
||||||
'arabicshape' 'arshape' do shaping for Arabic characters
|
'arabicshape' 'arshape' do shaping for Arabic characters
|
||||||
'autoindent' 'ai' take indent for new line from previous line
|
'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>AddOption("autochdir", gettext("change to directory of file in buffer"))
|
||||||
call <SID>BinOptionG("acd", &acd)
|
call <SID>BinOptionG("acd", &acd)
|
||||||
endif
|
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>AddOption("wrapscan", gettext("search commands wrap around the end of the buffer"))
|
||||||
call <SID>BinOptionG("ws", &ws)
|
call <SID>BinOptionG("ws", &ws)
|
||||||
call <SID>AddOption("incsearch", gettext("show match for partly typed search command"))
|
call <SID>AddOption("incsearch", gettext("show match for partly typed search command"))
|
||||||
|
@@ -2005,7 +2005,8 @@ hex2nr(int c)
|
|||||||
return c - '0';
|
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.
|
* Convert two hex characters to a byte.
|
||||||
* Return -1 if one of the characters is not hex.
|
* Return -1 if one of the characters is not hex.
|
||||||
|
@@ -1147,6 +1147,12 @@
|
|||||||
# define FEAT_SYN_HL
|
# define FEAT_SYN_HL
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* +autoshelldir 'autoshelldir' option.
|
||||||
|
*/
|
||||||
|
#if defined(FEAT_TERMINAL)
|
||||||
|
# define FEAT_AUTOSHELLDIR
|
||||||
|
#endif
|
||||||
/*
|
/*
|
||||||
* +textprop and +popupwin Text PROPerties and POPUP windows
|
* +textprop and +popupwin Text PROPerties and POPUP windows
|
||||||
*/
|
*/
|
||||||
|
@@ -383,6 +383,9 @@ EXTERN char_u *p_ambw; // 'ambiwidth'
|
|||||||
#ifdef FEAT_AUTOCHDIR
|
#ifdef FEAT_AUTOCHDIR
|
||||||
EXTERN int p_acd; // 'autochdir'
|
EXTERN int p_acd; // 'autochdir'
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef FEAT_AUTOSHELLDIR
|
||||||
|
EXTERN int p_asd; // 'autoshelldir'
|
||||||
|
#endif
|
||||||
EXTERN int p_ai; // 'autoindent'
|
EXTERN int p_ai; // 'autoindent'
|
||||||
EXTERN int p_bin; // 'binary'
|
EXTERN int p_bin; // 'binary'
|
||||||
EXTERN int p_bomb; // 'bomb'
|
EXTERN int p_bomb; // 'bomb'
|
||||||
|
@@ -370,6 +370,15 @@ static struct vimoption options[] =
|
|||||||
#else
|
#else
|
||||||
(char_u *)NULL, PV_NONE,
|
(char_u *)NULL, PV_NONE,
|
||||||
{(char_u *)0L, (char_u *)0L}
|
{(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
|
#endif
|
||||||
SCTX_INIT},
|
SCTX_INIT},
|
||||||
{"autoindent", "ai", P_BOOL|P_VI_DEF,
|
{"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);
|
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.
|
* Called by libvterm when it cannot recognize an OSC sequence.
|
||||||
* We recognize a terminal API command.
|
* We recognize a terminal API command.
|
||||||
@@ -4306,7 +4373,13 @@ parse_osc(int command, VTermStringFragment frag, void *user)
|
|||||||
: term->tl_job->jv_channel;
|
: term->tl_job->jv_channel;
|
||||||
garray_T *gap = &term->tl_osc_buf;
|
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)
|
if (command != 51)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@@ -92,6 +92,14 @@ func CheckLinux()
|
|||||||
endif
|
endif
|
||||||
endfunc
|
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.
|
" Command to check that making screendumps is supported.
|
||||||
" Caller must source screendump.vim
|
" Caller must source screendump.vim
|
||||||
command CheckScreendump call CheckScreendump()
|
command CheckScreendump call CheckScreendump()
|
||||||
|
@@ -475,6 +475,35 @@ func Test_term_mouse()
|
|||||||
call delete('Xbuf')
|
call delete('Xbuf')
|
||||||
endfunc
|
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
|
" Test for modeless selection in a terminal
|
||||||
func Test_term_modeless_selection()
|
func Test_term_modeless_selection()
|
||||||
CheckUnix
|
CheckUnix
|
||||||
|
@@ -750,6 +750,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
2675,
|
||||||
/**/
|
/**/
|
||||||
2674,
|
2674,
|
||||||
/**/
|
/**/
|
||||||
|
Reference in New Issue
Block a user