blob: 3cf9082aa6e5e8cc0a98b84e7b0f99f635a7abcc [file] [log] [blame]
Bram Moolenaar482aaeb2005-09-29 18:26:07 +00001" netrwPlugin.vim: Handles file transfer and remote directory listing across a network
Bram Moolenaardd2a3cd2007-05-05 17:10:09 +00002" PLUGIN SECTION
Christian Brabandtf9ca1392024-02-19 20:37:11 +01003" Maintainer: This runtime file is looking for a new maintainer.
Konfekt3d7e5672024-10-27 22:16:49 +01004" Date: Sep 09, 2021
Nir Lichtman1e34b952024-05-08 19:19:34 +02005" Last Change:
6" 2024 May 08 by Vim Project: cleanup legacy Win9X checks
Konfekt3d7e5672024-10-27 22:16:49 +01007" 2024 Oct 27 by Vim Project: cleanup gx mapping
Christian Brabandtf9ca1392024-02-19 20:37:11 +01008" Former Maintainer: Charles E Campbell
Bram Moolenaar482aaeb2005-09-29 18:26:07 +00009" GetLatestVimScripts: 1075 1 :AutoInstall: netrw.vim
Bram Moolenaar89a9c152021-08-29 21:55:35 +020010" Copyright: Copyright (C) 1999-2021 Charles E. Campbell {{{1
Bram Moolenaar482aaeb2005-09-29 18:26:07 +000011" Permission is hereby granted to use and distribute this code,
12" with or without modifications, provided that this copyright
13" notice is copied with it. Like anything else that's free,
14" netrw.vim, netrwPlugin.vim, and netrwSettings.vim are provided
15" *as is* and comes with no warranty of any kind, either
16" expressed or implied. By using this plugin, you agree that
17" in no event will the copyright holder be liable for any damages
18" resulting from the use of this software.
19"
20" But be doers of the Word, and not only hearers, deluding your own selves {{{1
21" (James 1:22 RSV)
22" =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
Bram Moolenaar482aaeb2005-09-29 18:26:07 +000023" Load Once: {{{1
Bram Moolenaardd2a3cd2007-05-05 17:10:09 +000024if &cp || exists("g:loaded_netrwPlugin")
Bram Moolenaar482aaeb2005-09-29 18:26:07 +000025 finish
26endif
Bram Moolenaarb7398fe2023-05-14 18:50:25 +010027let g:loaded_netrwPlugin = "v173"
Bram Moolenaar5c736222010-01-06 20:54:52 +010028let s:keepcpo = &cpo
Bram Moolenaar482aaeb2005-09-29 18:26:07 +000029set cpo&vim
Bram Moolenaar8d043172014-01-23 14:24:41 +010030"DechoRemOn
Bram Moolenaar482aaeb2005-09-29 18:26:07 +000031
32" ---------------------------------------------------------------------
33" Public Interface: {{{1
34
Konfekt3d7e5672024-10-27 22:16:49 +010035" Commands Launch/URL {{{2
36" surpress output of command; use bang for GUI applications
37
38" set up redirection (avoids browser messages)
Christian Brabandt7c967762024-10-28 07:03:24 +010039" by default if not set, g:netrw_suppress_gx_mesg is true
40if get(g:, 'netrw_suppress_gx_mesg', 1)
Konfekt3d7e5672024-10-27 22:16:49 +010041 if &srr =~# "%s"
42 let s:redir = printf(&srr, has("win32") ? "nul" : "/dev/null")
43 else
44 let s:redir= &srr .. (has("win32") ? "nul" : "/dev/null")
45 endif
46else
47 let s:redir= ""
48endif
49
50if has('unix')
51 if has('win32unix')
52 " If cygstart provided, then assume Cygwin and use cygstart --hide; see man cygstart.
53 if executable('cygstart')
54 command -complete=shellcmd -nargs=1 -bang Launch
55 \ exe 'silent ! cygstart --hide' trim(<q-args>) s:redir | redraw!
56 elseif !empty($MSYSTEM) && executable('start')
57 " MSYS2/Git Bash comes by default without cygstart; see
58 " https://www.msys2.org/wiki/How-does-MSYS2-differ-from-Cygwin
59 " Instead it provides /usr/bin/start script running `cmd.exe //c start`
60 " Adding "" //b` sets void title, hides cmd window and blocks path conversion
61 " of /b to \b\ " by MSYS2; see https://www.msys2.org/docs/filesystem-paths/
62 command -complete=shellcmd -nargs=1 -bang Launch
63 \ exe 'silent !start "" //b' trim(<q-args>) s:redir | redraw!
64 else
65 " imitate /usr/bin/start script for other environments and hope for the best
66 command -complete=shellcmd -nargs=1 -bang Launch
67 \ exe 'silent !cmd //c start "" //b' trim(<q-args>) s:redir | redraw!
68 endif
69 elseif exists('$WSL_DISTRO_NAME') " use cmd.exe to start GUI apps in WSL
70 command -complete=shellcmd -nargs=1 -bang Launch execute ':silent !'..
71 \ ((<q-args> =~? '\v<\f+\.(exe|com|bat|cmd)>') ?
72 \ 'cmd.exe /c start "" /b' trim(<q-args>) :
73 \ 'nohup ' trim(<q-args>) s:redir '&')
74 \ | redraw!
75 else
76 command -complete=shellcmd -nargs=1 -bang Launch
77 \ exe ':silent ! nohup' trim(<q-args>) s:redir '&' | redraw!
78 endif
79elseif has('win32')
80 command -complete=shellcmd -nargs=1 -bang Launch
81 \ exe 'silent !'.. (&shell =~? '\<cmd\.exe\>' ? '' : 'cmd.exe /c')
82 \ 'start /b ' trim(<q-args>) s:redir | redraw!
83endif
84if exists(':Launch') == 2
85 " Git Bash
86 if has('win32unix')
87 " start suffices
88 let s:cmd = ''
89 " Windows / WSL
90 elseif executable('explorer.exe')
91 let s:cmd = 'explorer.exe'
92 " Linux / BSD
93 elseif executable('xdg-open')
94 let s:cmd = 'xdg-open'
95 " MacOS
96 elseif executable('open')
97 let s:cmd = 'open'
98 else
Christian Brabandt7c967762024-10-28 07:03:24 +010099 let s:cmd = ''
Konfekt3d7e5672024-10-27 22:16:49 +0100100 endif
101 function s:Open(cmd, file)
102 if empty(a:cmd) && !exists('g:netrw_browsex_viewer')
103 echoerr "No program to open this path found. See :help Open for more information."
104 else
105 Launch cmd shellescape(a:file, 1)
106 endif
107 endfunction
108 command -complete=file -nargs=1 Open call s:Open(s:cmd, <q-args>)
109endif
110
111if !exists('g:netrw_regex_url')
112 let g:netrw_regex_url = '\%(\%(http\|ftp\|irc\)s\?\|file\)://\S\{-}'
113endif
114
115" " }}}
Bram Moolenaar8d043172014-01-23 14:24:41 +0100116" Local Browsing Autocmds: {{{2
Bram Moolenaar482aaeb2005-09-29 18:26:07 +0000117augroup FileExplorer
118 au!
Bram Moolenaara6878372014-03-22 21:02:50 +0100119 au BufLeave * if &ft != "netrw"|let w:netrw_prvfile= expand("%:p")|endif
Bram Moolenaar8d043172014-01-23 14:24:41 +0100120 au BufEnter * sil call s:LocalBrowse(expand("<amatch>"))
121 au VimEnter * sil call s:VimEnter(expand("<amatch>"))
Nir Lichtman1e34b952024-05-08 19:19:34 +0200122 if has("win32")
Bram Moolenaar8d043172014-01-23 14:24:41 +0100123 au BufEnter .* sil call s:LocalBrowse(expand("<amatch>"))
Bram Moolenaardd2a3cd2007-05-05 17:10:09 +0000124 endif
Bram Moolenaar482aaeb2005-09-29 18:26:07 +0000125augroup END
126
127" Network Browsing Reading Writing: {{{2
128augroup Network
129 au!
Bram Moolenaar85850f32019-07-19 22:05:51 +0200130 au BufReadCmd file://* call netrw#FileUrlEdit(expand("<amatch>"))
131 au BufReadCmd ftp://*,rcp://*,scp://*,http://*,https://*,dav://*,davs://*,rsync://*,sftp://* exe "sil doau BufReadPre ".fnameescape(expand("<amatch>"))|call netrw#Nread(2,expand("<amatch>"))|exe "sil doau BufReadPost ".fnameescape(expand("<amatch>"))
Bram Moolenaar8feef4f2015-01-07 16:57:10 +0100132 au FileReadCmd ftp://*,rcp://*,scp://*,http://*,file://*,https://*,dav://*,davs://*,rsync://*,sftp://* exe "sil doau FileReadPre ".fnameescape(expand("<amatch>"))|call netrw#Nread(1,expand("<amatch>"))|exe "sil doau FileReadPost ".fnameescape(expand("<amatch>"))
133 au BufWriteCmd ftp://*,rcp://*,scp://*,http://*,file://*,dav://*,davs://*,rsync://*,sftp://* exe "sil doau BufWritePre ".fnameescape(expand("<amatch>"))|exe 'Nwrite '.fnameescape(expand("<amatch>"))|exe "sil doau BufWritePost ".fnameescape(expand("<amatch>"))
134 au FileWriteCmd ftp://*,rcp://*,scp://*,http://*,file://*,dav://*,davs://*,rsync://*,sftp://* exe "sil doau FileWritePre ".fnameescape(expand("<amatch>"))|exe "'[,']".'Nwrite '.fnameescape(expand("<amatch>"))|exe "sil doau FileWritePost ".fnameescape(expand("<amatch>"))
Bram Moolenaar589edb32019-09-20 14:38:13 +0200135 try
Bram Moolenaar8feef4f2015-01-07 16:57:10 +0100136 au SourceCmd ftp://*,rcp://*,scp://*,http://*,file://*,https://*,dav://*,davs://*,rsync://*,sftp://* exe 'Nsource '.fnameescape(expand("<amatch>"))
Bram Moolenaar589edb32019-09-20 14:38:13 +0200137 catch /^Vim\%((\a\+)\)\=:E216/
Bram Moolenaar8feef4f2015-01-07 16:57:10 +0100138 au SourcePre ftp://*,rcp://*,scp://*,http://*,file://*,https://*,dav://*,davs://*,rsync://*,sftp://* exe 'Nsource '.fnameescape(expand("<amatch>"))
Bram Moolenaardd2a3cd2007-05-05 17:10:09 +0000139 endtry
Bram Moolenaar482aaeb2005-09-29 18:26:07 +0000140augroup END
141
142" Commands: :Nread, :Nwrite, :NetUserPass {{{2
Bram Moolenaare0fa3742016-02-20 15:47:01 +0100143com! -count=1 -nargs=* Nread let s:svpos= winsaveview()<bar>call netrw#NetRead(<count>,<f-args>)<bar>call winrestview(s:svpos)
144com! -range=% -nargs=* Nwrite let s:svpos= winsaveview()<bar><line1>,<line2>call netrw#NetWrite(<f-args>)<bar>call winrestview(s:svpos)
Bram Moolenaar482aaeb2005-09-29 18:26:07 +0000145com! -nargs=* NetUserPass call NetUserPass(<f-args>)
Bram Moolenaare0fa3742016-02-20 15:47:01 +0100146com! -nargs=* Nsource let s:svpos= winsaveview()<bar>call netrw#NetSource(<f-args>)<bar>call winrestview(s:svpos)
Bram Moolenaar85850f32019-07-19 22:05:51 +0200147com! -nargs=? Ntree call netrw#SetTreetop(1,<q-args>)
Bram Moolenaar482aaeb2005-09-29 18:26:07 +0000148
Bram Moolenaar8d043172014-01-23 14:24:41 +0100149" Commands: :Explore, :Sexplore, Hexplore, Vexplore, Lexplore {{{2
Bram Moolenaardd2a3cd2007-05-05 17:10:09 +0000150com! -nargs=* -bar -bang -count=0 -complete=dir Explore call netrw#Explore(<count>,0,0+<bang>0,<q-args>)
151com! -nargs=* -bar -bang -count=0 -complete=dir Sexplore call netrw#Explore(<count>,1,0+<bang>0,<q-args>)
152com! -nargs=* -bar -bang -count=0 -complete=dir Hexplore call netrw#Explore(<count>,1,2+<bang>0,<q-args>)
153com! -nargs=* -bar -bang -count=0 -complete=dir Vexplore call netrw#Explore(<count>,1,4+<bang>0,<q-args>)
154com! -nargs=* -bar -count=0 -complete=dir Texplore call netrw#Explore(<count>,0,6 ,<q-args>)
155com! -nargs=* -bar -bang Nexplore call netrw#Explore(-1,0,0,<q-args>)
156com! -nargs=* -bar -bang Pexplore call netrw#Explore(-2,0,0,<q-args>)
Bram Moolenaar8feef4f2015-01-07 16:57:10 +0100157com! -nargs=* -bar -bang -count=0 -complete=dir Lexplore call netrw#Lexplore(<count>,<bang>0,<q-args>)
Bram Moolenaar482aaeb2005-09-29 18:26:07 +0000158
159" Commands: NetrwSettings {{{2
Bram Moolenaarf2330482008-06-24 20:19:36 +0000160com! -nargs=0 NetrwSettings call netrwSettings#NetrwSettings()
Bram Moolenaara6878372014-03-22 21:02:50 +0100161com! -bang NetrwClean call netrw#Clean(<bang>0)
Bram Moolenaar482aaeb2005-09-29 18:26:07 +0000162
Bram Moolenaarb8a7b562006-02-01 21:47:16 +0000163" Maps:
Bram Moolenaar8feef4f2015-01-07 16:57:10 +0100164if !exists("g:netrw_nogx")
165 if maparg('gx','n') == ""
166 if !hasmapto('<Plug>NetrwBrowseX')
167 nmap <unique> gx <Plug>NetrwBrowseX
168 endif
Bram Moolenaar5ef1c6a2019-11-10 22:09:11 +0100169 nno <silent> <Plug>NetrwBrowseX :call netrw#BrowseX(netrw#GX(),netrw#CheckIfRemote(netrw#GX()))<cr>
Bram Moolenaardd2a3cd2007-05-05 17:10:09 +0000170 endif
Bram Moolenaar89a9c152021-08-29 21:55:35 +0200171 if maparg('gx','x') == ""
Bram Moolenaar8feef4f2015-01-07 16:57:10 +0100172 if !hasmapto('<Plug>NetrwBrowseXVis')
Bram Moolenaar89a9c152021-08-29 21:55:35 +0200173 xmap <unique> gx <Plug>NetrwBrowseXVis
Bram Moolenaar8feef4f2015-01-07 16:57:10 +0100174 endif
Bram Moolenaar89a9c152021-08-29 21:55:35 +0200175 xno <silent> <Plug>NetrwBrowseXVis :<c-u>call netrw#BrowseXVis()<cr>
Bram Moolenaar8feef4f2015-01-07 16:57:10 +0100176 endif
Bram Moolenaarb8a7b562006-02-01 21:47:16 +0000177endif
Bram Moolenaara0f849e2015-10-30 14:37:44 +0100178if exists("g:netrw_usetab") && g:netrw_usetab
179 if maparg('<c-tab>','n') == ""
180 nmap <unique> <c-tab> <Plug>NetrwShrink
181 endif
182 nno <silent> <Plug>NetrwShrink :call netrw#Shrink()<cr>
183endif
Bram Moolenaarb8a7b562006-02-01 21:47:16 +0000184
Bram Moolenaar482aaeb2005-09-29 18:26:07 +0000185" ---------------------------------------------------------------------
Bram Moolenaar8d043172014-01-23 14:24:41 +0100186" LocalBrowse: invokes netrw#LocalBrowseCheck() on directory buffers {{{2
Bram Moolenaar482aaeb2005-09-29 18:26:07 +0000187fun! s:LocalBrowse(dirname)
Bram Moolenaar8d043172014-01-23 14:24:41 +0100188 " Unfortunate interaction -- only DechoMsg debugging calls can be safely used here.
189 " Otherwise, the BufEnter event gets triggered when attempts to write to
Bram Moolenaar482aaeb2005-09-29 18:26:07 +0000190 " the DBG buffer are made.
Bram Moolenaar589edb32019-09-20 14:38:13 +0200191
Bram Moolenaare6ae6222013-05-21 21:01:10 +0200192 if !exists("s:vimentered")
Bram Moolenaar8d043172014-01-23 14:24:41 +0100193 " If s:vimentered doesn't exist, then the VimEnter event hasn't fired. It will,
194 " and so s:VimEnter() will then be calling this routine, but this time with s:vimentered defined.
195" call Dfunc("s:LocalBrowse(dirname<".a:dirname.">) (s:vimentered doesn't exist)")
196" call Dret("s:LocalBrowse")
Bram Moolenaare6ae6222013-05-21 21:01:10 +0200197 return
198 endif
Bram Moolenaar8d043172014-01-23 14:24:41 +0100199
200" call Dfunc("s:LocalBrowse(dirname<".a:dirname.">) (s:vimentered=".s:vimentered.")")
201
Bram Moolenaardd2a3cd2007-05-05 17:10:09 +0000202 if has("amiga")
203 " The check against '' is made for the Amiga, where the empty
204 " string is the current directory and not checking would break
205 " things such as the help command.
Bram Moolenaar8d043172014-01-23 14:24:41 +0100206" call Decho("(LocalBrowse) dirname<".a:dirname."> (isdirectory, amiga)")
Bram Moolenaardd2a3cd2007-05-05 17:10:09 +0000207 if a:dirname != '' && isdirectory(a:dirname)
Bram Moolenaaradc21822011-04-01 18:03:16 +0200208 sil! call netrw#LocalBrowseCheck(a:dirname)
Bram Moolenaar8feef4f2015-01-07 16:57:10 +0100209 if exists("w:netrw_bannercnt") && line('.') < w:netrw_bannercnt
Bram Moolenaara6878372014-03-22 21:02:50 +0100210 exe w:netrw_bannercnt
211 endif
Bram Moolenaardd2a3cd2007-05-05 17:10:09 +0000212 endif
Bram Moolenaar8d043172014-01-23 14:24:41 +0100213
Bram Moolenaardd2a3cd2007-05-05 17:10:09 +0000214 elseif isdirectory(a:dirname)
Bram Moolenaara6878372014-03-22 21:02:50 +0100215" call Decho("(LocalBrowse) dirname<".a:dirname."> ft=".&ft." (isdirectory, not amiga)")
216" call Dredir("LocalBrowse ft last set: ","verbose set ft")
Bram Moolenaar89a9c152021-08-29 21:55:35 +0200217 " Jul 13, 2021: for whatever reason, preceding the following call with
218 " a sil! causes an unbalanced if-endif vim error
219 call netrw#LocalBrowseCheck(a:dirname)
Bram Moolenaar8feef4f2015-01-07 16:57:10 +0100220 if exists("w:netrw_bannercnt") && line('.') < w:netrw_bannercnt
Bram Moolenaara6878372014-03-22 21:02:50 +0100221 exe w:netrw_bannercnt
222 endif
Bram Moolenaar8d043172014-01-23 14:24:41 +0100223
224 else
225 " not a directory, ignore it
226" call Decho("(LocalBrowse) dirname<".a:dirname."> not a directory, ignoring...")
Bram Moolenaar482aaeb2005-09-29 18:26:07 +0000227 endif
Bram Moolenaar8d043172014-01-23 14:24:41 +0100228
229" call Dret("s:LocalBrowse")
Bram Moolenaar482aaeb2005-09-29 18:26:07 +0000230endfun
231
232" ---------------------------------------------------------------------
Bram Moolenaar8d043172014-01-23 14:24:41 +0100233" s:VimEnter: after all vim startup stuff is done, this function is called. {{{2
234" Its purpose: to look over all windows and run s:LocalBrowse() on
235" them, which checks if they're directories and will create a directory
236" listing when appropriate.
237" It also sets s:vimentered, letting s:LocalBrowse() know that s:VimEnter()
238" has already been called.
Bram Moolenaar00a927d2010-05-14 23:24:24 +0200239fun! s:VimEnter(dirname)
Bram Moolenaar8d043172014-01-23 14:24:41 +0100240" call Dfunc("s:VimEnter(dirname<".a:dirname.">) expand(%)<".expand("%").">")
Bram Moolenaar89a9c152021-08-29 21:55:35 +0200241 if has('nvim') || v:version < 802
242 " Johann Hรถchtl: reported that the call range... line causes an E488: Trailing characters
243 " error with neovim. I suspect its because neovim hasn't updated with recent
244 " vim patches. As is, this code will have problems with popup terminals
245 " instantiated before the VimEnter event runs.
246 " Ingo Karkat : E488 also in Vim 8.1.1602
Bram Moolenaare6ae6222013-05-21 21:01:10 +0200247 let curwin = winnr()
248 let s:vimentered = 1
Bram Moolenaar8d043172014-01-23 14:24:41 +0100249 windo call s:LocalBrowse(expand("%:p"))
Bram Moolenaar477db062010-07-28 18:17:41 +0200250 exe curwin."wincmd w"
Bram Moolenaar89a9c152021-08-29 21:55:35 +0200251 else
252 " the following complicated expression comes courtesy of lacygoill; largely does the same thing as the windo and
253 " wincmd which are commented out, but avoids some side effects. Allows popup terminal before VimEnter.
254 let s:vimentered = 1
255 call range(1, winnr('$'))->map({_, v -> win_execute(win_getid(v), 'call expand("%:p")->s:LocalBrowse()')})
256 endif
Bram Moolenaar8d043172014-01-23 14:24:41 +0100257" call Dret("s:VimEnter")
Bram Moolenaar00a927d2010-05-14 23:24:24 +0200258endfun
259
260" ---------------------------------------------------------------------
Bram Moolenaar482aaeb2005-09-29 18:26:07 +0000261" NetrwStatusLine: {{{1
262fun! NetrwStatusLine()
Bram Moolenaaraf48b092006-03-14 22:51:38 +0000263" let g:stlmsg= "Xbufnr=".w:netrw_explore_bufnr." bufnr=".bufnr("%")." Xline#".w:netrw_explore_line." line#".line(".")
264 if !exists("w:netrw_explore_bufnr") || w:netrw_explore_bufnr != bufnr("%") || !exists("w:netrw_explore_line") || w:netrw_explore_line != line(".") || !exists("w:netrw_explore_list")
Bram Moolenaar482aaeb2005-09-29 18:26:07 +0000265 let &stl= s:netrw_explore_stl
266 if exists("w:netrw_explore_bufnr")|unlet w:netrw_explore_bufnr|endif
267 if exists("w:netrw_explore_line")|unlet w:netrw_explore_line|endif
268 return ""
269 else
270 return "Match ".w:netrw_explore_mtchcnt." of ".w:netrw_explore_listlen
271 endif
272endfun
273
274" ------------------------------------------------------------------------
275" NetUserPass: set username and password for subsequent ftp transfer {{{1
276" Usage: :call NetUserPass() -- will prompt for userid and password
277" :call NetUserPass("uid") -- will prompt for password
278" :call NetUserPass("uid","password") -- sets global userid and password
279fun! NetUserPass(...)
280
281 " get/set userid
282 if a:0 == 0
283" call Dfunc("NetUserPass(a:0<".a:0.">)")
284 if !exists("g:netrw_uid") || g:netrw_uid == ""
285 " via prompt
286 let g:netrw_uid= input('Enter username: ')
287 endif
288 else " from command line
289" call Dfunc("NetUserPass(a:1<".a:1.">) {")
290 let g:netrw_uid= a:1
291 endif
292
293 " get password
294 if a:0 <= 1 " via prompt
295" call Decho("a:0=".a:0." case <=1:")
296 let g:netrw_passwd= inputsecret("Enter Password: ")
297 else " from command line
298" call Decho("a:0=".a:0." case >1: a:2<".a:2.">")
299 let g:netrw_passwd=a:2
300 endif
301" call Dret("NetUserPass")
302endfun
303
304" ------------------------------------------------------------------------
Bram Moolenaar482aaeb2005-09-29 18:26:07 +0000305" Modelines And Restoration: {{{1
306let &cpo= s:keepcpo
307unlet s:keepcpo
308" vim:ts=8 fdm=marker