To: vim_dev@googlegroups.com Subject: Patch 8.2.2675 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.2.2675 Problem: Directory change in a terminal window shell is not followed. Solution: Add the 'autoshelldir' option. (closes #6290) Files: runtime/doc/options.txt, runtime/doc/quickref.txt, runtime/optwin.vim, src/charset.c, src/feature.h, src/option.h, src/optiondefs.h, src/terminal.c, src/testdir/check.vim, src/testdir/test_terminal3.vim *** ../vim-8.2.2674/runtime/doc/options.txt 2021-03-04 21:55:54.601235264 +0100 --- runtime/doc/options.txt 2021-03-29 20:38:32.031640025 +0200 *************** *** 749,754 **** --- 749,763 ---- 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 *** ../vim-8.2.2674/runtime/doc/quickref.txt 2021-01-31 17:02:06.258490157 +0100 --- runtime/doc/quickref.txt 2021-03-29 20:39:10.695540234 +0200 *************** *** 605,610 **** --- 605,611 ---- '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 *** ../vim-8.2.2674/runtime/optwin.vim 2020-09-20 21:31:59.634692878 +0200 --- runtime/optwin.vim 2021-03-29 20:35:13.384153457 +0200 *************** *** 266,271 **** --- 266,273 ---- call AddOption("autochdir", gettext("change to directory of file in buffer")) call BinOptionG("acd", &acd) endif + call AddOption("autoshelldir", gettext("change to pwd of shell in terminal buffer")) + call BinOptionG("asd", &asd) call AddOption("wrapscan", gettext("search commands wrap around the end of the buffer")) call BinOptionG("ws", &ws) call AddOption("incsearch", gettext("show match for partly typed search command")) *** ../vim-8.2.2674/src/charset.c 2021-02-15 20:37:58.453374547 +0100 --- src/charset.c 2021-03-29 20:35:13.384153457 +0200 *************** *** 2005,2011 **** return c - '0'; } ! #if defined(FEAT_TERMRESPONSE) || defined(FEAT_GUI_GTK) || defined(PROTO) /* * Convert two hex characters to a byte. * Return -1 if one of the characters is not hex. --- 2005,2012 ---- return c - '0'; } ! #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. *** ../vim-8.2.2674/src/feature.h 2020-12-18 19:49:52.341571870 +0100 --- src/feature.h 2021-03-29 20:35:13.384153457 +0200 *************** *** 1148,1153 **** --- 1148,1159 ---- #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) *** ../vim-8.2.2674/src/option.h 2021-02-15 20:37:58.457374538 +0100 --- src/option.h 2021-03-29 20:35:13.384153457 +0200 *************** *** 383,388 **** --- 383,391 ---- #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' *** ../vim-8.2.2674/src/optiondefs.h 2021-02-15 20:37:58.457374538 +0100 --- src/optiondefs.h 2021-03-29 20:35:13.384153457 +0200 *************** *** 372,377 **** --- 372,386 ---- {(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}, *** ../vim-8.2.2674/src/terminal.c 2021-02-23 17:47:20.078181103 +0100 --- src/terminal.c 2021-03-29 20:45:42.646551274 +0200 *************** *** 4293,4298 **** --- 4293,4365 ---- } /* + * 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,4312 **** : term->tl_job->jv_channel; garray_T *gap = &term->tl_osc_buf; ! // We recognize only OSC 5 1 ; {command} if (command != 51) return 0; --- 4373,4385 ---- : term->tl_job->jv_channel; garray_T *gap = &term->tl_osc_buf; ! // 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; *** ../vim-8.2.2674/src/testdir/check.vim 2021-03-20 12:49:12.078222904 +0100 --- src/testdir/check.vim 2021-03-29 20:35:13.384153457 +0200 *************** *** 92,97 **** --- 92,105 ---- 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() *** ../vim-8.2.2674/src/testdir/test_terminal3.vim 2021-02-20 19:21:31.955986987 +0100 --- src/testdir/test_terminal3.vim 2021-03-29 20:46:24.430447428 +0200 *************** *** 475,480 **** --- 475,509 ---- 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'\") + "call term_sendkeys(buf, "cd ".tmpfolder."\") + 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 *** ../vim-8.2.2674/src/version.c 2021-03-29 20:10:23.152204702 +0200 --- src/version.c 2021-03-29 20:46:45.218395670 +0200 *************** *** 752,753 **** --- 752,755 ---- { /* Add new patch number below this line */ + /**/ + 2675, /**/ -- hundred-and-one symptoms of being an internet addict: 34. You laugh at people with a 10 Mbit connection. /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// \\\ \\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///