runtime: decouple Open and Launch commands and gx mapping from netrw Commit: https://github.com/vim/vim/commit/c729d6d154e097b439ff264b9736604824f4a5f4 Author: Luca Saccarola <github.e4...@aleeas.com> Date: Sat Jan 25 16:07:12 2025 +0100
runtime: decouple Open and Launch commands and gx mapping from netrw closes: https://github.com/vim/vim/issues/16494 fixes: #https://github.com/vim/vim/issues/16486 Signed-off-by: Christian Brabandt <c...@256bit.org> diff --git a/runtime/autoload/dist/vim9.vim b/runtime/autoload/dist/vim9.vim index 2277f2453..a2b1451b0 100644 --- a/runtime/autoload/dist/vim9.vim +++ b/runtime/autoload/dist/vim9.vim @@ -2,19 +2,128 @@ vim9script # Vim runtime support library # -# Maintainer: The Vim Project <https://github.com/vim/vim> -# Last Change: 2023 Oct 25 +# Maintainer: The Vim Project <https://github.com/vim/vim> +# Last Change: 2025 Jan 24 export def IsSafeExecutable(filetype: string, executable: string): bool - if empty(exepath(executable)) - return v:false + if empty(exepath(executable)) + return v:false + endif + var cwd = getcwd() + return get(g:, filetype .. '_exec', get(g:, 'plugin_exec', 0)) + && (fnamemodify(exepath(executable), ':p:h') !=# cwd + || (split($PATH, has('win32') ? ';' : ':')->index(cwd) != -1 + && cwd != '.')) +enddef + +def Redir(): string + if get(g:, 'netrw_suppress_gx_mesg', true) + if &srr =~# "%s" + return printf(&srr, has("win32") ? "nul" : "/dev/null") + elseif &srr =~# '>&\?$' + return &srr .. (has("win32") ? "nul" : "/dev/null") + else + return &srr .. (has("win32") ? "> nul" : "> /dev/null") endif - var cwd = getcwd() - return get(g:, filetype .. '_exec', get(g:, 'plugin_exec', 0)) - && (fnamemodify(exepath(executable), ':p:h') !=# cwd - || (split($PATH, has('win32') ? ';' : ':')->index(cwd) != -1 - && cwd != '.')) + endif + return '' +enddef + +if has('unix') + if has('win32unix') + # Cygwin provides cygstart + if executable('cygstart') + export def Launch(args: string) + execute 'silent ! cygstart --hide' args Redir() | redraw! + enddef + elseif !empty($MSYSTEM) && executable('start') + # MSYS2/Git Bash comes by default without cygstart; see + # https://www.msys2.org/wiki/How-does-MSYS2-differ-from-Cygwin + # Instead it provides /usr/bin/start script running `cmd.exe //c start` + # Adding "" //b` sets void title, hides cmd window and blocks path conversion + # of /b to \ " by MSYS2; see https://www.msys2.org/docs/filesystem-paths/ + export def Launch(args: string) + execute 'silent !start "" //b' args Redir() | redraw! + enddef + else + # imitate /usr/bin/start script for other environments and hope for the best + export def Launch(args: string) + execute 'silent !cmd //c start "" //b' args Redir() | redraw! + enddef + endif + elseif exists('$WSL_DISTRO_NAME') # use cmd.exe to start GUI apps in WSL + export def Launch(args: string) + execute 'silent !' .. + ((args =~? ' <+\.(exe|com|bat|cmd)>') ? + $'cmd.exe /c start /b {args} {Redir()}' : + $'nohup {args} {Redir()} &') + | redraw! + enddef + else + export def Launch(args: string) + execute ':silent ! nohup' args Redir() (has('gui_running') ? '' : '&') | redraw! + enddef + endif +elseif has('win32') + export def Launch(args: string) + execute 'silent !' .. (&shell =~? '\<cmd\.exe\>' ? '' : 'cmd.exe /c') + 'start "" /b' args Redir() | redraw! + enddef +else + export def Launch(dummy: string) + echom 'No common launcher found' + enddef +endif + +var os_viewer = null_string +# Git Bash +if has('win32unix') + # (cyg)start suffices + os_viewer = '' +# Windows / WSL +elseif executable('explorer.exe') + os_viewer = 'explorer.exe' +# Linux / BSD +elseif executable('xdg-open') + os_viewer = 'xdg-open' +# MacOS +elseif executable('open') + os_viewer = 'open' +endif + +def Viewer(): string + # g:Openprg could be a string of program + its arguments, test if first + # argument is executable + var user_viewer = get(g:, "Openprg", get(g:, "netrw_browsex_viewer", "")) + + # Take care of an off-by-one check for "for" too + if executable(trim(user_viewer)) + return user_viewer + endif + + var args = split(user_viewer, '\s\+\zs') + var viewer = get(args, 0, '') + + for arg in args[1 :] + if executable(trim(viewer)) + return user_viewer + endif + + viewer ..= arg + endfor + + if os_viewer == null + echoerr "No program to open this path found. See :help Open for more information." + endif + + return os_viewer +enddef + +export def Open(file: string) + Launch($"{Viewer()} {shellescape(file, 1)}") enddef # Uncomment this line to check for compilation errors early # defcompile + +# vim: ts=8 sts=2 sw=2 et diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index 2348cdddb..094b650c7 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -1,4 +1,4 @@ -*eval.txt* For Vim version 9.1. Last change: 2025 Jan 02 +*eval.txt* For Vim version 9.1. Last change: 2025 Jan 25 VIM REFERENCE MANUAL by Bram Moolenaar @@ -4907,5 +4907,40 @@ executable. It takes the following arguments: filetype string executable string + *dist#vim9#Open()* *:Open* + *g:Openprg* +dist#vim9#Open(file: string) ~ + +Opens `path` with the system default handler (macOS `open`, Windows +`explorer.exe`, Linux `xdg-open`, 窶ヲ). If the variable |g:Openprg| exists the +string specified in the variable is used instead. + +NOTE: Escaping of the path is automatically applied. + +Usage: >vim + :call dist#vim9#Open(<path>) + :Open <path> +< + + *dist#vim9#Launch()* *:Launch* +dist#vim9#Launch(file: string) ~ + +Launches <args> with the appropriate system programs. Intended for launching +GUI programs within Vim. + +NOTE: escaping of <args> is left to the user + +Examples: >vim + vim9script + + import autoload 'dist/vim9.vim' + # Execute 'makeprg' into another xterm window + vim9.Launch('xterm ' .. expandcmd(&makeprg)) +< + +Usage: >vim + :call dist#vim9#Launch(<args>) + :Launch <app> <args>. +< vim:tw=78:ts=8:noet:ft=help:norl: diff --git a/runtime/doc/index.txt b/runtime/doc/index.txt index 079f9ea39..06a24e046 100644 --- a/runtime/doc/index.txt +++ b/runtime/doc/index.txt @@ -803,8 +803,6 @@ tag char note action in Normal mode ~ |gu| gu{motion} 2 make Nmove text lowercase |gv| gv reselect the previous Visual area |gw| gw{motion} 2 format Nmove text and keep cursor -|netrw-gx| gx execute application for file name under the - cursor (only with |netrw| plugin) |g@| g@{motion} call 'operatorfunc' |g~| g~{motion} 2 swap case for Nmove text |g<Down>| g<Down> 1 same as "gj" diff --git a/runtime/doc/tags b/runtime/doc/tags index 0b9253203..e667a33d5 100644 --- a/runtime/doc/tags +++ b/runtime/doc/tags @@ -2133,7 +2133,7 @@ $quote eval.txt /*$quote* :LP pi_logipat.txt /*:LP* :LPE pi_logipat.txt /*:LPE* :LPF pi_logipat.txt /*:LPF* -:Launch pi_netrw.txt /*:Launch* +:Launch eval.txt /*:Launch* :Lexplore pi_netrw.txt /*:Lexplore* :Lfilter quickfix.txt /*:Lfilter* :LogiPat pi_logipat.txt /*:LogiPat* @@ -2151,7 +2151,7 @@ $quote eval.txt /*$quote* :Ntree pi_netrw.txt /*:Ntree* :Nw pi_netrw.txt /*:Nw* :Nwrite pi_netrw.txt /*:Nwrite* -:Open pi_netrw.txt /*:Open* +:Open eval.txt /*:Open* :Over terminal.txt /*:Over* :P various.txt /*:P* :Pexplore pi_netrw.txt /*:Pexplore* @@ -6879,6 +6879,8 @@ disable-menus gui.txt /*disable-menus* discard editing.txt /*discard* dist#vim eval.txt /*dist#vim* dist#vim9 eval.txt /*dist#vim9* +dist#vim9#Launch() eval.txt /*dist#vim9#Launch()* +dist#vim9#Open() eval.txt /*dist#vim9#Open()* distribute-script usr_51.txt /*distribute-script* distributed-plugins usr_05.txt /*distributed-plugins* distribution intro.txt /*distribution* @@ -7527,6 +7529,7 @@ g:NetrwTopLvlMenu pi_netrw.txt /*g:NetrwTopLvlMenu* g:Netrw_UserMaps pi_netrw.txt /*g:Netrw_UserMaps* g:Netrw_corehandler pi_netrw.txt /*g:Netrw_corehandler* g:Netrw_funcref pi_netrw.txt /*g:Netrw_funcref* +g:Openprg eval.txt /*g:Openprg* g:actual_curbuf options.txt /*g:actual_curbuf* g:actual_curwin options.txt /*g:actual_curwin* g:ada#Comment ft_ada.txt /*g:ada#Comment* @@ -7630,8 +7633,6 @@ g:netrw_altv pi_netrw.txt /*g:netrw_altv* g:netrw_banner pi_netrw.txt /*g:netrw_banner* g:netrw_bannerbackslash pi_netrw.txt /*g:netrw_bannerbackslash* g:netrw_browse_split pi_netrw.txt /*g:netrw_browse_split* -g:netrw_browsex_support_remote pi_netrw.txt /*g:netrw_browsex_support_remote* -g:netrw_browsex_viewer pi_netrw.txt /*g:netrw_browsex_viewer* g:netrw_bufsettings pi_netrw.txt /*g:netrw_bufsettings* g:netrw_chgperm pi_netrw.txt /*g:netrw_chgperm* g:netrw_chgwin pi_netrw.txt /*g:netrw_chgwin* @@ -7660,7 +7661,6 @@ g:netrw_ftp_timelist_cmd pi_netrw.txt /*g:netrw_ftp_timelist_cmd* g:netrw_ftpextracmd pi_netrw.txt /*g:netrw_ftpextracmd* g:netrw_ftpmode pi_netrw.txt /*g:netrw_ftpmode* g:netrw_glob_escape pi_netrw.txt /*g:netrw_glob_escape* -g:netrw_gx pi_netrw.txt /*g:netrw_gx* g:netrw_hide pi_netrw.txt /*g:netrw_hide* g:netrw_home pi_netrw.txt /*g:netrw_home* g:netrw_http_cmd pi_netrw.txt /*g:netrw_http_cmd* @@ -7686,7 +7686,6 @@ g:netrw_menu pi_netrw.txt /*g:netrw_menu* g:netrw_mkdir_cmd pi_netrw.txt /*g:netrw_mkdir_cmd* g:netrw_mousemaps pi_netrw.txt /*g:netrw_mousemaps* g:netrw_nobeval pi_netrw.txt /*g:netrw_nobeval* -g:netrw_nogx pi_netrw.txt /*g:netrw_nogx* g:netrw_preview pi_netrw.txt /*g:netrw_preview* g:netrw_rcp_cmd pi_netrw.txt /*g:netrw_rcp_cmd* g:netrw_remote_mkdir pi_netrw.txt /*g:netrw_remote_mkdir* @@ -9031,8 +9030,6 @@ netrw-gitignore pi_netrw.txt /*netrw-gitignore* netrw-gn pi_netrw.txt /*netrw-gn* netrw-gp pi_netrw.txt /*netrw-gp* netrw-grep pi_netrw.txt /*netrw-grep* -netrw-gx pi_netrw.txt /*netrw-gx* -netrw-handler pi_netrw.txt /*netrw-handler* netrw-help pi_netrw.txt /*netrw-help* netrw-hexplore pi_netrw.txt /*netrw-hexplore* netrw-hide pi_netrw.txt /*netrw-hide* @@ -9161,7 +9158,6 @@ netrw-vexplore pi_netrw.txt /*netrw-vexplore* netrw-windows-netrc pi_netrw.txt /*netrw-windows-netrc* netrw-windows-s pi_netrw.txt /*netrw-windows-s* netrw-write pi_netrw.txt /*netrw-write* -netrw-x pi_netrw.txt /*netrw-x* netrw-xfer pi_netrw.txt /*netrw-xfer* netrw.txt pi_netrw.txt /*netrw.txt* netrw.vim pi_netrw.txt /*netrw.vim* diff --git a/runtime/doc/version9.txt b/runtime/doc/version9.txt index 2f2ab5ae0..f77499aeb 100644 --- a/runtime/doc/version9.txt +++ b/runtime/doc/version9.txt @@ -1,4 +1,4 @@ -*version9.txt* For Vim version 9.1. Last change: 2025 Jan 23 +*version9.txt* For Vim version 9.1. Last change: 2025 Jan 25 VIM REFERENCE MANUAL by Bram Moolenaar @@ -41626,6 +41626,8 @@ Changed~ - |v:stacktrace| The stack trace of the exception most recently caught and not finished - New option value "nosort" for 'completeopt' +- add |dist#vim9#Launch()| and |dist#vim9#Open()| to the |vim-script-library| + and decouple it from |netrw| *added-9.2* Added ~ diff --git a/runtime/pack/dist/opt/netrw/doc/netrw.txt b/runtime/pack/dist/opt/netrw/doc/netrw.txt index cd5777ec9..4afe53819 100644 --- a/runtime/pack/dist/opt/netrw/doc/netrw.txt +++ b/runtime/pack/dist/opt/netrw/doc/netrw.txt @@ -403,9 +403,6 @@ settings are described below, in |netrw-browser-options|, and in *g:netrw_menu* =0 disable netrw's menu =1 (default) netrw's menu enabled - *g:netrw_nogx* if this variable exists, then the "gx" map will not - be available (see |netrw-gx|) - *g:netrw_uid* (ftp) user-id, retained on a per-vim-session basis *s:netrw_passwd* (ftp) password, retained on a per-vim-session basis @@ -1113,7 +1110,7 @@ QUICK REFERENCE: MAPS *netrw-browse-maps* {{{2 U Change to subsequently-visited directory |netrw-U| v Enter the file/directory under the cursor in a new |netrw-v| browser window. A vertical split is used. - x View file with an associated program |netrw-x| + x View file with an associated program. (see |:Open|) X Execute filename under cursor via |system()| |netrw-X| % Open a new file in netrw's current directory |netrw-%| @@ -1466,106 +1463,6 @@ With either form of the command, netrw will first ask for confirmation that the removal is in fact what you want to do. If netrw doesn't have permission to remove a file, it will issue an error message. -CUSTOMIZING BROWSING WITH A SPECIAL HANDLER *netrw-x* *netrw-handler* {{{2 - -Certain files, such as html, gif, jpeg, (word/office) doc, etc, files, are -best seen with a special handler (ie. a tool provided with your computer's -operating system). Netrw allows one to invoke such special handlers by: - - * hitting gx with the cursor atop the file path or alternatively x - in a netrw buffer; the former can be disabled by defining the - |g:netrw_nogx| variable - * when in command line, typing :Open <path>, see |:Open| below. - -One may also use visual mode (see |visual-start|) to select the text that the -special handler will use. Normally gx checks for a close-by URL or file name -to pick up the text under the cursor; one may change what |expand()| uses via the -|g:netrw_gx| variable (options include "<cword>", "<cWORD>"). Note that -expand("<cfile>") depends on the |'isfname'| setting. Alternatively, one may -select the text to be used by gx by making a visual selection (see -|visual-block|) and then pressing gx. - -The selection function can be adapted for each filetype by adding a function -`Netrw_get_URL_<filetype>`, where <filetype> is given by the 'filetype'. -The function should return the URL or file name to be used by gx, and will -fall back to the default behavior if it returns an empty string. -For example, special handlers for links Markdown and HTML are - -" make gx work on concealed links regardless of exact cursor position: > - - function Netrw_get_URL_markdown() - " markdown URL such as [link text](http://ya.ru 'yandex search') - try - let save_view = winsaveview() - if searchpair('\[.\{-}\](', '', ')\zs', 'cbW', '', line('.')) > 0 - return matchstr(getline('.')[col('.')-1:], - \ '\[.\{-}\](\zs' .. g:netrw_regex_url .. '\ze\(\s\+.\{-}\)\?)') - endif - return '' - finally - call winrestview(save_view) - endtry - endfunction - - function Netrw_get_URL_html() - " HTML URL such as <a href='http://www.python.org'>Python is here</a> - " <a href="http://www.python.org"/> - try - let save_view = winsaveview() - if searchpair('<a\s\+href=', '', '\%(</a>\|/>\)\zs', 'cbW', '', line('.')) > 0 - return matchstr(getline('.')[col('.') - 1 : ], - \ 'href=["'.."'"..']\?\zs\S\{-}\ze["'.."'"..']\?/\?>') - endif - return '' - finally - call winrestview(save_view) - endtry - endfunction -< -Other than a file path, the text under the cursor may be a URL. Netrw uses -by default the following regular expression to determine if the text under the -cursor is a URL: -> - :let g:netrw_regex_url = '\%(\%(http\|ftp\|irc\)s\?\|file\)://\S\{-}' -< -Associated setting variables: - |g:netrw_gx| control how gx picks up the text under the cursor - |g:netrw_nogx| prevent gx map while editing - |g:netrw_suppress_gx_mesg| controls gx's suppression of browser messages - -OPENING FILES AND LAUNCHING APPS *netrw-gx* *:Open* *:Launch* {{{2 - -Netrw determines which special handler by the following method: - - * if |g:netrw_browsex_viewer| exists, then it will be used to attempt to - view files. - If the viewer you wish to use does not support handling of a remote URL - directory, set |g:netrw_browsex_support_remote| to 0. - * otherwise: - - * for Windows : explorer.exe is used - * for Mac OS X : open is used. - * for Linux : xdg-open is used. - -To open a path (or URL) <path> by the appropriate handler, type > - - :Open <path> -< -No escaping, neither for the shell nor for Vim's command-line, is needed. - -To launch a specific application <app> <args>, often <args> being <path> > - - :Launch <app> <args>. - -Since <args> can be arbitrarily complex, in particular contain many file -paths, the escaping is left to the user. - -If you disabled the netrw plugin by setting g:loaded_netrwPlugin (see -|netrw-noload|), then you can use > - - :call netrw#Launch('<app> <args>') - :call netrw#Open('<path>') -< *netrw-curdir* DELETING BOOKMARKS *netrw-mB* {{{2 @@ -2585,14 +2482,6 @@ your browsing preferences. (see also: |netrw-settings|) |netrw-C| |netrw-cr| |netrw-ctrl-r| - *g:netrw_browsex_viewer* specify user's preference for a viewer: > - "kfmclient exec" - "gnome-open" -< - *g:netrw_browsex_support_remote* - specify if the specified viewer supports a - remote URL. (see |netrw-handler|). - *g:netrw_chgperm* Unix/Linux: "chmod PERM FILENAME" Windows: "cacls FILENAME /e /p PERM" Used to change access permission for a file. @@ -2615,12 +2504,11 @@ your browsing preferences. (see also: |netrw-settings|) *g:Netrw_corehandler* Allows one to specify something additional to do when handling <core> files via netrw's - browser's "x" command (see |netrw-x|). If - present, g:Netrw_corehandler specifies - either one or more function references - (see |Funcref|). (the capital g:Netrw... - is required its holding a function reference) - + browser's "x" command. If present, + g:Netrw_corehandler specifies either one or + more function references (see |Funcref|). + (the capital g:Netrw... is required its + holding a function reference) *g:netrw_ctags* ="ctags" The default external program used to create @@ -2769,11 +2657,6 @@ your browsing preferences. (see also: |netrw-settings|) These characters in directory names are escaped before applying glob() - *g:netrw_gx* ="<cfile>" - This option controls how gx (|netrw-gx|) picks - up the text under the cursor. See |expand()| - for possibilities. - *g:netrw_hide* Controlled by the "a" map (see |netrw-a|) =0 : show all =1 : show not-hidden files diff --git a/runtime/pack/dist/opt/netrw/plugin/netrwPlugin.vim b/runtime/pack/dist/opt/netrw/plugin/netrwPlugin.vim index 8d10c0015..388a7f2ba 100644 --- a/runtime/pack/dist/opt/netrw/plugin/netrwPlugin.vim +++ b/runtime/pack/dist/opt/netrw/plugin/netrwPlugin.vim @@ -20,12 +20,6 @@ let g:loaded_netrwPlugin = "v175" let s:keepcpo = &cpo set cpo&vim -" Commands Launch/URL: {{{ - -command -complete=shellcmd -nargs=1 Launch call netrw#Launch(trim(<q-args>)) -command -complete=file -nargs=1 Open call netrw#Open(trim(<q-args>)) - -" }}} " Local Browsing Autocmds: {{{ augroup FileExplorer @@ -85,21 +79,6 @@ command! -bang NetrwClean call netrw#Clean(<bang>0) " }}} " Maps: {{{ -if !exists("g:netrw_nogx") - if maparg('gx','n') == "" - if !hasmapto('<Plug>NetrwBrowseX') - nmap <unique> gx <Plug>NetrwBrowseX - endif - nno <silent> <Plug>NetrwBrowseX :call netrw#BrowseX(netrw#GX(),netrw#CheckIfRemote(netrw#GX()))<cr> - endif - if maparg('gx','x') == "" - if !hasmapto('<Plug>NetrwBrowseXVis') - xmap <unique> gx <Plug>NetrwBrowseXVis - endif - xno <silent> <Plug>NetrwBrowseXVis :<c-u>call netrw#BrowseXVis()<cr> - endif -endif - if exists("g:netrw_usetab") && g:netrw_usetab if maparg('<c-tab>','n') == "" nmap <unique> <c-tab> <Plug>NetrwShrink diff --git a/runtime/plugin/openPlugin.vim b/runtime/plugin/openPlugin.vim new file mode 100644 index 000000000..103b33cd6 --- /dev/null +++ b/runtime/plugin/openPlugin.vim @@ -0,0 +1,24 @@ +vim9script + +# Vim runtime support library +# +# Maintainer: The Vim Project <https://github.com/vim/vim> +# Last Change: 2025 Jan 24 + +import autoload 'dist/vim9.vim' + +command -complete=shellcmd -nargs=1 Launch vim9.Launch(trim(<q-args>)) +command -complete=file -nargs=1 Open vim9.Open(trim(<q-args>)) + +const no_gx = get(g:, "nogx", get(g:, "netrw_nogx", false)) +if !no_gx + if maparg('gx', 'n') == "" + const file = get(g:, 'netrw_gx', '<cfile>') + nnoremap <unique> gx <scriptcmd>vim9.Open(expand(file))<CR> + endif + if maparg('gx', 'x') == "" + xnoremap <unique> gx <scriptcmd>vim9.Open(getregion(getpos('v'), getpos('.'), { type: mode() })->join())<CR> + endif +endif + +# vim: ts=8 sts=2 sw=2 et -- -- You received this message from the "vim_dev" maillist. Do not top-post! Type your reply below the text you are replying to. For more information, visit http://www.vim.org/maillist.php --- You received this message because you are subscribed to the Google Groups "vim_dev" group. To unsubscribe from this group and stop receiving emails from it, send an email to vim_dev+unsubscr...@googlegroups.com. To view this discussion visit https://groups.google.com/d/msgid/vim_dev/E1tbhsG-000mNB-4l%40256bit.org.