neovim

Neovim text editor
git clone https://git.dasho.dev/neovim.git
Log | Files | Refs | README

netrw.vim (394918B)


      1 " Creator:    Charles E Campbell
      2 " Previous Maintainer: Luca Saccarola <github.e41mv@aleeas.com>
      3 " Maintainer: This runtime file is looking for a new maintainer.
      4 " Last Change:
      5 " 2025 Aug 07 by Vim Project (use correct "=~#" for netrw_stylesize option #17901)
      6 " 2025 Aug 07 by Vim Project (netrw#BrowseX() distinguishes remote files #17794)
      7 " 2025 Aug 22 by Vim Project netrw#Explore handle terminal correctly #18069
      8 " 2025 Sep 05 by Vim Project ensure netrw#fs#Dirname() returns trailing slash #18199
      9 " 2025 Sep 11 by Vim Project only keep cursor position in tree mode #18275
     10 " 2025 Sep 17 by Vim Project tighten the regex to handle remote compressed archives #18318
     11 " 2025 Sep 18 by Vim Project 'equalalways' not always respected #18358
     12 " 2025 Oct 01 by Vim Project fix navigate to parent folder #18464
     13 " 2025 Oct 26 by Vim Project fix parsing of remote user names #18611
     14 " 2025 Oct 27 by Vim Project align comment after #18611
     15 " 2025 Nov 01 by Vim Project fix NetrwChgPerm #18674
     16 " 2025 Nov 13 by Vim Project don't wipe unnamed buffers #18740
     17 " 2025 Nov 18 by Vim Project use UNC paths when using scp and Windows paths #18764
     18 " 2025 Nov 28 by Vim Project fix undefined variable in *NetrwMenu #18829
     19 " 2025 Dec 26 by Vim Project fix use of g:netrw_cygwin #19015
     20 " 2026 Jan 19 by Vim Project do not create swapfiles #18854
     21 " Copyright:  Copyright (C) 2016 Charles E. Campbell {{{1
     22 "             Permission is hereby granted to use and distribute this code,
     23 "             with or without modifications, provided that this copyright
     24 "             notice is copied with it. Like anything else that's free,
     25 "             netrw.vim, netrwPlugin.vim, and netrwSettings.vim are provided
     26 "             *as is* and come with no warranty of any kind, either
     27 "             expressed or implied. By using this plugin, you agree that
     28 "             in no event will the copyright holder be liable for any damages
     29 "             resulting from the use of this software.
     30 "
     31 " Note: the code here was started in 1999 under a much earlier version of vim.  The directory browsing
     32 "       code was written using vim v6, which did not have Lists (Lists were first offered with vim-v7).
     33 
     34 " Load Once: {{{1
     35 if &cp || exists("g:loaded_netrw")
     36    finish
     37 endif
     38 
     39 let g:loaded_netrw = "v184"
     40 
     41 if !has("patch-9.1.1054") && !has('nvim')
     42    echoerr 'netrw needs Vim v9.1.1054'
     43    finish
     44 endif
     45 
     46 let s:keepcpo= &cpo
     47 setl cpo&vim
     48 
     49 "  Netrw Variables: {{{1
     50 
     51 " s:NetrwInit: initializes variables if they haven't been defined {{{2
     52 
     53 function s:NetrwInit(name, default)
     54    if !exists(a:name)
     55        let {a:name} = a:default
     56    endif
     57 endfunction
     58 
     59 "  Netrw Constants: {{{2
     60 call s:NetrwInit("g:netrw_dirhistcnt",0)
     61 if !exists("s:LONGLIST")
     62  call s:NetrwInit("s:THINLIST",0)
     63  call s:NetrwInit("s:LONGLIST",1)
     64  call s:NetrwInit("s:WIDELIST",2)
     65  call s:NetrwInit("s:TREELIST",3)
     66  call s:NetrwInit("s:MAXLIST" ,4)
     67 endif
     68 
     69 " Default option values: {{{2
     70 call s:NetrwInit("g:netrw_localcopycmdopt","")
     71 call s:NetrwInit("g:netrw_localcopydircmdopt","")
     72 call s:NetrwInit("g:netrw_localmkdiropt","")
     73 call s:NetrwInit("g:netrw_localmovecmdopt","")
     74 
     75 " Default values for netrw's global protocol variables {{{2
     76 
     77 if !exists("g:netrw_dav_cmd")
     78  if executable("cadaver")
     79    let g:netrw_dav_cmd   = "cadaver"
     80  elseif executable("curl")
     81    let g:netrw_dav_cmd   = "curl"
     82  else
     83    let g:netrw_dav_cmd   = ""
     84  endif
     85 endif
     86 if !exists("g:netrw_fetch_cmd")
     87  if executable("fetch")
     88    let g:netrw_fetch_cmd = "fetch -o"
     89  else
     90    let g:netrw_fetch_cmd = ""
     91  endif
     92 endif
     93 if !exists("g:netrw_file_cmd")
     94  if executable("elinks")
     95    call s:NetrwInit("g:netrw_file_cmd","elinks")
     96  elseif executable("links")
     97    call s:NetrwInit("g:netrw_file_cmd","links")
     98  endif
     99 endif
    100 if !exists("g:netrw_ftp_cmd")
    101  let g:netrw_ftp_cmd   = "ftp"
    102 endif
    103 let s:netrw_ftp_cmd= g:netrw_ftp_cmd
    104 if !exists("g:netrw_ftp_options")
    105  let g:netrw_ftp_options= "-i -n"
    106 endif
    107 if !exists("g:netrw_http_cmd")
    108  if executable("wget")
    109    let g:netrw_http_cmd  = "wget"
    110    call s:NetrwInit("g:netrw_http_xcmd","-q -O")
    111  elseif executable("curl")
    112    let g:netrw_http_cmd  = "curl"
    113    call s:NetrwInit("g:netrw_http_xcmd","-L -o")
    114  elseif executable("elinks")
    115    let g:netrw_http_cmd = "elinks"
    116    call s:NetrwInit("g:netrw_http_xcmd","-source >")
    117  elseif executable("fetch")
    118    let g:netrw_http_cmd  = "fetch"
    119    call s:NetrwInit("g:netrw_http_xcmd","-o")
    120  elseif executable("links")
    121    let g:netrw_http_cmd = "links"
    122    call s:NetrwInit("g:netrw_http_xcmd","-http.extra-header ".shellescape("Accept-Encoding: identity", 1)." -source >")
    123  else
    124    let g:netrw_http_cmd  = ""
    125  endif
    126 endif
    127 call s:NetrwInit("g:netrw_http_put_cmd","curl -T")
    128 call s:NetrwInit("g:netrw_keepj","keepj")
    129 call s:NetrwInit("g:netrw_rcp_cmd"  , "rcp")
    130 call s:NetrwInit("g:netrw_rsync_cmd", "rsync")
    131 call s:NetrwInit("g:netrw_rsync_sep", "/")
    132 if !exists("g:netrw_scp_cmd")
    133  if executable("scp")
    134    call s:NetrwInit("g:netrw_scp_cmd" , "scp -q")
    135  elseif executable("pscp")
    136    call s:NetrwInit("g:netrw_scp_cmd", 'pscp -q')
    137  else
    138    call s:NetrwInit("g:netrw_scp_cmd" , "scp -q")
    139  endif
    140 endif
    141 call s:NetrwInit("g:netrw_sftp_cmd" , "sftp")
    142 call s:NetrwInit("g:netrw_ssh_cmd"  , "ssh")
    143 
    144 if has("win32")
    145      \ && exists("g:netrw_use_nt_rcp")
    146      \ && g:netrw_use_nt_rcp
    147      \ && executable( $SystemRoot .'/system32/rcp.exe')
    148  let s:netrw_has_nt_rcp = 1
    149  let s:netrw_rcpmode    = '-b'
    150 else
    151  let s:netrw_has_nt_rcp = 0
    152  let s:netrw_rcpmode    = ''
    153 endif
    154 
    155 " Default values for netrw's global variables {{{2
    156 " Cygwin Detection ------- {{{3
    157 if !exists("g:netrw_cygwin")
    158  if has("win32unix") && &shell =~ '\%(\<bash\>\|\<zsh\>\)\%(\.exe\)\=$'
    159    let g:netrw_cygwin= 1
    160  else
    161    let g:netrw_cygwin= 0
    162  endif
    163 endif
    164 " Default values - a-c ---------- {{{3
    165 call s:NetrwInit("g:netrw_alto"        , &sb)
    166 call s:NetrwInit("g:netrw_altv"        , &spr)
    167 call s:NetrwInit("g:netrw_banner"      , 1)
    168 call s:NetrwInit("g:netrw_browse_split", 0)
    169 call s:NetrwInit("g:netrw_bufsettings" , "noma nomod nonu nobl nowrap ro nornu")
    170 call s:NetrwInit("g:netrw_chgwin"      , -1)
    171 call s:NetrwInit("g:netrw_clipboard"   , 1)
    172 call s:NetrwInit("g:netrw_compress"    , "gzip")
    173 call s:NetrwInit("g:netrw_ctags"       , "ctags")
    174 call s:NetrwInit("g:netrw_cursor"      , 2)
    175 let s:netrw_usercul = &cursorline
    176 let s:netrw_usercuc = &cursorcolumn
    177 call s:NetrwInit("g:netrw_cygdrive","/cygdrive")
    178 " Default values - d-g ---------- {{{3
    179 call s:NetrwInit("s:didstarstar",0)
    180 call s:NetrwInit("g:netrw_dirhistcnt"      , 0)
    181 let s:xz_opt = has('unix') ? "XZ_OPT=-T0" :
    182      \ (has("win32") && &shell =~? '\vcmd(\.exe)?$' ?
    183      \ "setx XZ_OPT=-T0 &&" : "")
    184 call s:NetrwInit("g:netrw_decompress", {
    185            \ '.lz4': 'lz4 -d',
    186            \ '.lzo': 'lzop -d',
    187            \ '.lz': 'lzip -dk',
    188            \ '.7z': '7za x',
    189            \ '.001': '7za x',
    190            \ '.zip': 'unzip',
    191            \ '.bz': 'bunzip2 -k',
    192            \ '.bz2': 'bunzip2 -k',
    193            \ '.gz': 'gunzip -k',
    194            \ '.lzma': 'unlzma -T0 -k',
    195            \ '.xz': 'unxz -T0 -k',
    196            \ '.zst': 'zstd -T0 -d',
    197            \ '.Z': 'uncompress -k',
    198            \ '.tar': 'tar -xvf',
    199            \ '.tar.bz': 'tar -xvjf',
    200            \ '.tar.bz2': 'tar -xvjf',
    201            \ '.tbz': 'tar -xvjf',
    202            \ '.tbz2': 'tar -xvjf',
    203            \ '.tar.gz': 'tar -xvzf',
    204            \ '.tgz': 'tar -xvzf',
    205            \ '.tar.lzma': s:xz_opt .. ' tar -xvf --lzma',
    206            \ '.tlz': s:xz_opt .. ' tar -xvf --lzma',
    207            \ '.tar.xz': s:xz_opt .. ' tar -xvfJ',
    208            \ '.txz': s:xz_opt .. ' tar -xvfJ',
    209            \ '.tar.zst': s:xz_opt .. ' tar -xvf --use-compress-program=unzstd',
    210            \ '.tzst': s:xz_opt .. ' tar -xvf --use-compress-program=unzstd',
    211            \ '.rar': (executable("unrar")?"unrar x -ad":"rar x -ad"),
    212            \ })
    213 unlet s:xz_opt
    214 call s:NetrwInit("g:netrw_dirhistmax"       , 10)
    215 call s:NetrwInit("g:netrw_fastbrowse"       , 1)
    216 call s:NetrwInit("g:netrw_ftp_browse_reject", '^total\s\+\d\+$\|^Trying\s\+\d\+.*$\|^KERBEROS_V\d rejected\|^Security extensions not\|No such file\|: connect to address [0-9a-fA-F:]*: No route to host$')
    217 if !exists("g:netrw_ftp_list_cmd")
    218  if has("unix") || g:netrw_cygwin
    219    let g:netrw_ftp_list_cmd     = "ls -lF"
    220    let g:netrw_ftp_timelist_cmd = "ls -tlF"
    221    let g:netrw_ftp_sizelist_cmd = "ls -slF"
    222  else
    223    let g:netrw_ftp_list_cmd     = "dir"
    224    let g:netrw_ftp_timelist_cmd = "dir"
    225    let g:netrw_ftp_sizelist_cmd = "dir"
    226  endif
    227 endif
    228 call s:NetrwInit("g:netrw_ftpmode",'binary')
    229 " Default values - h-lh ---------- {{{3
    230 call s:NetrwInit("g:netrw_hide",1)
    231 if !exists("g:netrw_ignorenetrc")
    232  if &shell =~ '\c\<\%(cmd\|4nt\)\.exe$'
    233    let g:netrw_ignorenetrc= 1
    234  else
    235    let g:netrw_ignorenetrc= 0
    236  endif
    237 endif
    238 call s:NetrwInit("g:netrw_keepdir",1)
    239 if !exists("g:netrw_list_cmd")
    240  if g:netrw_scp_cmd =~ '^pscp' && executable("pscp")
    241    if exists("g:netrw_list_cmd_options")
    242      let g:netrw_list_cmd= g:netrw_scp_cmd." -ls USEPORT HOSTNAME: ".g:netrw_list_cmd_options
    243    else
    244      let g:netrw_list_cmd= g:netrw_scp_cmd." -ls USEPORT HOSTNAME:"
    245    endif
    246  elseif executable(g:netrw_ssh_cmd)
    247    " provide a scp-based default listing command
    248    if exists("g:netrw_list_cmd_options")
    249      let g:netrw_list_cmd= g:netrw_ssh_cmd." USEPORT HOSTNAME ls -FLa ".g:netrw_list_cmd_options
    250    else
    251      let g:netrw_list_cmd= g:netrw_ssh_cmd." USEPORT HOSTNAME ls -FLa"
    252    endif
    253  else
    254    let g:netrw_list_cmd= ""
    255  endif
    256 endif
    257 call s:NetrwInit("g:netrw_list_hide","")
    258 " Default values - lh-lz ---------- {{{3
    259 if !exists("g:netrw_localcmdshell")
    260  let g:netrw_localcmdshell= ""
    261 endif
    262 
    263 if !exists("g:netrw_localcopycmd")
    264    let g:netrw_localcopycmd = 'cp'
    265    let g:netrw_localcopycmdopt = ''
    266 
    267    if has("win32") && !g:netrw_cygwin
    268        let g:netrw_localcopycmd   = expand("$COMSPEC", v:true)
    269        let g:netrw_localcopycmdopt = '/c copy'
    270    endif
    271 endif
    272 
    273 if !exists("g:netrw_localcopydircmd")
    274    let g:netrw_localcopydircmd = 'cp'
    275    let g:netrw_localcopydircmdopt = '-R'
    276 
    277    if has("win32") && !g:netrw_cygwin
    278        let g:netrw_localcopydircmd   = "cp"
    279        call s:NetrwInit("g:netrw_localcopydircmdopt", "-R")
    280    endif
    281 endif
    282 
    283 if has("win32")
    284  if g:netrw_cygwin
    285    call s:NetrwInit("g:netrw_localmkdir","mkdir")
    286  else
    287    call s:NetrwInit("g:netrw_localmkdir",expand("$COMSPEC", v:true))
    288    call s:NetrwInit("g:netrw_localmkdiropt"," /c mkdir")
    289  endif
    290 else
    291  call s:NetrwInit("g:netrw_localmkdir","mkdir")
    292 endif
    293 call s:NetrwInit("g:netrw_remote_mkdir","mkdir")
    294 
    295 if !exists("g:netrw_localmovecmd")
    296  if has("win32")
    297    if g:netrw_cygwin
    298      let g:netrw_localmovecmd= "mv"
    299    else
    300      let g:netrw_localmovecmd   = expand("$COMSPEC", v:true)
    301      call s:NetrwInit("g:netrw_localmovecmdopt"," /c move")
    302    endif
    303  elseif has("unix") || has("macunix")
    304    let g:netrw_localmovecmd= "mv"
    305  else
    306    let g:netrw_localmovecmd= ""
    307  endif
    308 endif
    309 
    310 call s:NetrwInit("g:netrw_liststyle"  , s:THINLIST)
    311 " sanity checks
    312 if g:netrw_liststyle < 0 || g:netrw_liststyle >= s:MAXLIST
    313  let g:netrw_liststyle= s:THINLIST
    314 endif
    315 if g:netrw_liststyle == s:LONGLIST && g:netrw_scp_cmd !~ '^pscp'
    316  let g:netrw_list_cmd= g:netrw_list_cmd." -l"
    317 endif
    318 " Default values - m-r ---------- {{{3
    319 call s:NetrwInit("g:netrw_markfileesc"   , '*./[\~')
    320 call s:NetrwInit("g:netrw_maxfilenamelen", 32)
    321 call s:NetrwInit("g:netrw_menu"          , 1)
    322 call s:NetrwInit("g:netrw_mkdir_cmd"     , g:netrw_ssh_cmd." USEPORT HOSTNAME mkdir")
    323 call s:NetrwInit("g:netrw_mousemaps"     , (exists("+mouse") && &mouse =~# '[anh]'))
    324 call s:NetrwInit("g:netrw_retmap"        , 0)
    325 if has("unix") || g:netrw_cygwin
    326  call s:NetrwInit("g:netrw_chgperm"       , "chmod PERM FILENAME")
    327 elseif has("win32")
    328  call s:NetrwInit("g:netrw_chgperm"       , "cacls FILENAME /e /p PERM")
    329 else
    330  call s:NetrwInit("g:netrw_chgperm"       , "chmod PERM FILENAME")
    331 endif
    332 call s:NetrwInit("g:netrw_preview"       , 0)
    333 call s:NetrwInit("g:netrw_scpport"       , "-P")
    334 call s:NetrwInit("g:netrw_servername"    , "NETRWSERVER")
    335 call s:NetrwInit("g:netrw_sshport"       , "-p")
    336 call s:NetrwInit("g:netrw_rename_cmd"    , g:netrw_ssh_cmd." USEPORT HOSTNAME mv")
    337 call s:NetrwInit("g:netrw_rm_cmd"        , g:netrw_ssh_cmd." USEPORT HOSTNAME rm")
    338 call s:NetrwInit("g:netrw_rmdir_cmd"     , g:netrw_ssh_cmd." USEPORT HOSTNAME rmdir")
    339 call s:NetrwInit("g:netrw_rmf_cmd"       , g:netrw_ssh_cmd." USEPORT HOSTNAME rm -f ")
    340 " Default values - q-s ---------- {{{3
    341 call s:NetrwInit("g:netrw_quickhelp",0)
    342 let s:QuickHelp= ["-:go up dir  D:delete  R:rename  s:sort-by  x:special",
    343      \              "(create new)  %:file  d:directory",
    344      \              "(windows split&open) o:horz  v:vert  p:preview",
    345      \              "i:style  qf:file info  O:obtain  r:reverse",
    346      \              "(marks)  mf:mark file  mt:set target  mm:move  mc:copy",
    347      \              "(bookmarks)  mb:make  mB:delete  qb:list  gb:go to",
    348      \              "(history)  qb:list  u:go up  U:go down",
    349      \              "(targets)  mt:target Tb:use bookmark  Th:use history"]
    350 " g:netrw_sepchr: picking a character that doesn't appear in filenames that can be used to separate priority from filename
    351 call s:NetrwInit("g:netrw_sepchr"        , (&enc == "euc-jp")? "\<Char-0x01>" : "\<Char-0xff>")
    352 if !exists("g:netrw_keepj") || g:netrw_keepj == "keepj"
    353  call s:NetrwInit("s:netrw_silentxfer"    , (exists("g:netrw_silent") && g:netrw_silent != 0)? "sil keepj " : "keepj ")
    354 else
    355  call s:NetrwInit("s:netrw_silentxfer"    , (exists("g:netrw_silent") && g:netrw_silent != 0)? "sil " : " ")
    356 endif
    357 call s:NetrwInit("g:netrw_sort_by"       , "name") " alternatives: date                                      , size
    358 call s:NetrwInit("g:netrw_sort_options"  , "")
    359 call s:NetrwInit("g:netrw_sort_direction", "normal") " alternative: reverse  (z y x ...)
    360 if !exists("g:netrw_sort_sequence")
    361    let g:netrw_sort_sequence = !empty(&suffixes)
    362                \ ? printf('[\/]$,*,\%(%s\)[*@]\=$', &suffixes->split(',')->map('escape(v:val, ".*$~")')->join('\|'))
    363                \ : '[\/]$,*'
    364 endif
    365 call s:NetrwInit("g:netrw_special_syntax"   , 0)
    366 call s:NetrwInit("g:netrw_ssh_browse_reject", '^total\s\+\d\+$')
    367 call s:NetrwInit("g:netrw_use_noswf"        , 1)
    368 call s:NetrwInit("g:netrw_sizestyle"        ,"b")
    369 " Default values - t-w ---------- {{{3
    370 call s:NetrwInit("g:netrw_timefmt","%c")
    371 if !exists("g:netrw_xstrlen")
    372  if exists("g:Align_xstrlen")
    373    let g:netrw_xstrlen= g:Align_xstrlen
    374  elseif exists("g:drawit_xstrlen")
    375    let g:netrw_xstrlen= g:drawit_xstrlen
    376  elseif &enc == "latin1" || !has("multi_byte")
    377    let g:netrw_xstrlen= 0
    378  else
    379    let g:netrw_xstrlen= 1
    380  endif
    381 endif
    382 call s:NetrwInit("g:NetrwTopLvlMenu","Netrw.")
    383 call s:NetrwInit("g:netrw_winsize",50)
    384 call s:NetrwInit("g:netrw_wiw",1)
    385 if g:netrw_winsize > 100|let g:netrw_winsize= 100|endif
    386 " Default values for netrw's script variables: {{{2
    387 call s:NetrwInit("g:netrw_fname_escape",' ?&;%')
    388 if has("win32")
    389  call s:NetrwInit("g:netrw_glob_escape",'*?`{[]$')
    390 else
    391  call s:NetrwInit("g:netrw_glob_escape",'*[]?`{~$\')
    392 endif
    393 call s:NetrwInit("g:netrw_menu_escape",'.&? \')
    394 call s:NetrwInit("g:netrw_tmpfile_escape",' &;')
    395 call s:NetrwInit("s:netrw_map_escape","<|\n\r\\\<C-V>\"")
    396 if has("gui_running") && (&enc == 'utf-8' || &enc == 'utf-16' || &enc == 'ucs-4')
    397  let s:treedepthstring= "│ "
    398 else
    399  let s:treedepthstring= "| "
    400 endif
    401 call s:NetrwInit("s:netrw_posn", {})
    402 
    403 " BufEnter event ignored by decho when following variable is true
    404 "  Has a side effect that doau BufReadPost doesn't work, so
    405 "  files read by network transfer aren't appropriately highlighted.
    406 
    407 "  Netrw Initialization: {{{1
    408 
    409 au WinEnter * if &ft == "netrw" | call s:NetrwInsureWinVars() | endif
    410 
    411 if g:netrw_keepj =~# "keepj"
    412  com! -nargs=*  NetrwKeepj      keepj <args>
    413 else
    414  let g:netrw_keepj= ""
    415  com! -nargs=*  NetrwKeepj      <args>
    416 endif
    417 
    418 "  Netrw Utility Functions: {{{1
    419 " netrw#Explore: launch the local browser in the directory of the current file {{{2
    420 "          indx:  == -1: Nexplore
    421 "                 == -2: Pexplore
    422 "                 ==  +: this is overloaded:
    423 "                      * If Nexplore/Pexplore is in use, then this refers to the
    424 "                        indx'th item in the w:netrw_explore_list[] of items which
    425 "                        matched the */pattern **/pattern *//pattern **//pattern
    426 "                      * If Hexplore or Vexplore, then this will override
    427 "                        g:netrw_winsize to specify the qty of rows or columns the
    428 "                        newly split window should have.
    429 "          dosplit==0: the window will be split iff the current file has been modified and hidden not set
    430 "          dosplit==1: the window will be split before running the local browser
    431 "          style == 0: Explore     style == 1: Explore!
    432 "                == 2: Hexplore    style == 3: Hexplore!
    433 "                == 4: Vexplore    style == 5: Vexplore!
    434 "                == 6: Texplore
    435 function netrw#Explore(indx,dosplit,style,...)
    436  if !exists("b:netrw_curdir")
    437    let b:netrw_curdir= getcwd()
    438  endif
    439 
    440  " record current file for Rexplore's benefit
    441  if &ft != "netrw"
    442    let w:netrw_rexfile= expand("%:p")
    443  endif
    444 
    445  " record current directory
    446  let curdir     = simplify(b:netrw_curdir)
    447  if !g:netrw_cygwin && has("win32")
    448    let curdir= substitute(curdir,'\','/','g')
    449  endif
    450  let curfiledir = substitute(expand("%:p"),'^\(.*[/\\]\)[^/\\]*$','\1','e')
    451  if &buftype == "terminal"
    452      let curfiledir = curdir
    453  endif
    454 
    455  " using completion, directories with spaces in their names (thanks, Bill Gates, for a truly dumb idea)
    456  " will end up with backslashes here.  Solution: strip off backslashes that precede white space and
    457  " try Explore again.
    458  if a:0 > 0
    459    if a:1 =~ "\\\s" && !filereadable(s:NetrwFile(a:1)) && !isdirectory(s:NetrwFile(a:1))
    460      let a1 = substitute(a:1, '\\\(\s\)', '\1', 'g')
    461      if a1 != a:1
    462        call netrw#Explore(a:indx, a:dosplit, a:style, a1)
    463        return
    464      endif
    465    endif
    466  endif
    467 
    468  " save registers
    469  if !has('nvim') && has("clipboard") && g:netrw_clipboard
    470    sil! let keepregstar = @*
    471    sil! let keepregplus = @+
    472  endif
    473  sil! let keepregslash= @/
    474 
    475  " if   dosplit
    476  " -or- buffer is not a terminal AND file has been modified AND file not hidden when abandoned
    477  " -or- Texplore used
    478  if a:dosplit || (&buftype != "terminal" && &modified && &hidden == 0 && &bufhidden != "hide") || a:style == 6
    479    call s:SaveWinVars()
    480    let winsz= g:netrw_winsize
    481    if a:indx > 0
    482      let winsz= a:indx
    483    endif
    484 
    485    if a:style == 0      " Explore, Sexplore
    486      let winsz= (winsz > 0)? (winsz*winheight(0))/100 : -winsz
    487      if winsz == 0|let winsz= ""|endif
    488      exe "noswapfile ".(g:netrw_alto ? "below " : "above ").winsz."wincmd s"
    489 
    490    elseif a:style == 1  " Explore!, Sexplore!
    491      let winsz= (winsz > 0)? (winsz*winwidth(0))/100 : -winsz
    492      if winsz == 0|let winsz= ""|endif
    493      exe "keepalt noswapfile ".(g:netrw_altv ? "rightbelow " : "leftabove ").winsz."wincmd v"
    494 
    495    elseif a:style == 2  " Hexplore
    496      let winsz= (winsz > 0)? (winsz*winheight(0))/100 : -winsz
    497      if winsz == 0|let winsz= ""|endif
    498      exe "keepalt noswapfile ".(g:netrw_alto ? "below " : "above ").winsz."wincmd s"
    499 
    500    elseif a:style == 3  " Hexplore!
    501      let winsz= (winsz > 0)? (winsz*winheight(0))/100 : -winsz
    502      if winsz == 0|let winsz= ""|endif
    503      exe "keepalt noswapfile ".(!g:netrw_alto ? "below " : "above ").winsz."wincmd s"
    504 
    505    elseif a:style == 4  " Vexplore
    506      let winsz= (winsz > 0)? (winsz*winwidth(0))/100 : -winsz
    507      if winsz == 0|let winsz= ""|endif
    508      exe "keepalt noswapfile ".(g:netrw_altv ? "rightbelow " : "leftabove ").winsz."wincmd v"
    509 
    510    elseif a:style == 5  " Vexplore!
    511      let winsz= (winsz > 0)? (winsz*winwidth(0))/100 : -winsz
    512      if winsz == 0|let winsz= ""|endif
    513      exe "keepalt noswapfile ".(!g:netrw_altv ? "rightbelow " : "leftabove ").winsz."wincmd v"
    514 
    515    elseif a:style == 6  " Texplore
    516      call s:SaveBufVars()
    517      exe "keepalt tabnew ".fnameescape(curdir)
    518      call s:RestoreBufVars()
    519    endif
    520    call s:RestoreWinVars()
    521  endif
    522  NetrwKeepj norm! 0
    523 
    524  if a:0 > 0
    525    if a:1 =~ '^\~' && (has("unix") || g:netrw_cygwin)
    526      let dirname= simplify(substitute(a:1,'\~',expand("$HOME"),''))
    527    elseif a:1 == '.'
    528      let dirname= simplify(exists("b:netrw_curdir")? b:netrw_curdir : getcwd())
    529      if dirname !~ '/$'
    530        let dirname= dirname."/"
    531      endif
    532    elseif a:1 =~ '\$'
    533      let dirname= simplify(expand(a:1))
    534    elseif a:1 !~ '^\*\{1,2}/' && a:1 !~ '^\a\{3,}://'
    535      let dirname= simplify(a:1)
    536    else
    537      let dirname= a:1
    538    endif
    539  else
    540    " clear explore
    541    call s:NetrwClearExplore()
    542    return
    543  endif
    544 
    545  if dirname =~ '\.\./\=$'
    546    let dirname= simplify(fnamemodify(dirname,':p:h'))
    547  elseif dirname =~ '\.\.' || dirname == '.'
    548    let dirname= simplify(fnamemodify(dirname,':p'))
    549  endif
    550 
    551  if dirname =~ '^\*//'
    552    " starpat=1: Explore *//pattern   (current directory only search for files containing pattern)
    553    let pattern= substitute(dirname,'^\*//\(.*\)$','\1','')
    554    let starpat= 1
    555    if &hls | let keepregslash= s:ExplorePatHls(pattern) | endif
    556 
    557  elseif dirname =~ '^\*\*//'
    558    " starpat=2: Explore **//pattern  (recursive descent search for files containing pattern)
    559    let pattern= substitute(dirname,'^\*\*//','','')
    560    let starpat= 2
    561 
    562  elseif dirname =~ '/\*\*/'
    563    " handle .../**/.../filepat
    564    let prefixdir= substitute(dirname,'^\(.\{-}\)\*\*.*$','\1','')
    565    if prefixdir =~ '^/' || (prefixdir =~ '^\a:/' && has("win32"))
    566      let b:netrw_curdir = prefixdir
    567    else
    568      let b:netrw_curdir= getcwd().'/'.prefixdir
    569    endif
    570    let dirname= substitute(dirname,'^.\{-}\(\*\*/.*\)$','\1','')
    571    let starpat= 4
    572 
    573  elseif dirname =~ '^\*/'
    574    " case starpat=3: Explore */filepat   (search in current directory for filenames matching filepat)
    575    let starpat= 3
    576 
    577  elseif dirname=~ '^\*\*/'
    578    " starpat=4: Explore **/filepat  (recursive descent search for filenames matching filepat)
    579    let starpat= 4
    580 
    581  else
    582    let starpat= 0
    583  endif
    584 
    585  if starpat == 0 && a:indx >= 0
    586    " [Explore Hexplore Vexplore Sexplore] [dirname]
    587    if dirname == ""
    588      let dirname= curfiledir
    589    endif
    590    if dirname =~# '^scp://' || dirname =~ '^ftp://'
    591      call netrw#Nread(2,dirname)
    592    else
    593      if dirname == ""
    594        let dirname= getcwd()
    595      elseif has("win32") && !g:netrw_cygwin
    596        " Windows : check for a drive specifier, or else for a remote share name ('\\Foo' or '//Foo',
    597        " depending on whether backslashes have been converted to forward slashes by earlier code).
    598        if dirname !~ '^[a-zA-Z]:' && dirname !~ '^\\\\\w\+' && dirname !~ '^//\w\+'
    599          let dirname= b:netrw_curdir."/".dirname
    600        endif
    601      elseif dirname !~ '^/'
    602        let dirname= b:netrw_curdir."/".dirname
    603      endif
    604      call netrw#LocalBrowseCheck(dirname)
    605    endif
    606    if exists("w:netrw_bannercnt")
    607      " done to handle P08-Ingelrest. :Explore will _Always_ go to the line just after the banner.
    608      " If one wants to return the same place in the netrw window, use :Rex instead.
    609      exe w:netrw_bannercnt
    610    endif
    611 
    612 
    613  " starpat=1: Explore *//pattern  (current directory only search for files containing pattern)
    614  " starpat=2: Explore **//pattern (recursive descent search for files containing pattern)
    615  " starpat=3: Explore */filepat   (search in current directory for filenames matching filepat)
    616  " starpat=4: Explore **/filepat  (recursive descent search for filenames matching filepat)
    617  elseif a:indx <= 0
    618    " Nexplore, Pexplore, Explore: handle starpat
    619    if !mapcheck("<s-up>","n") && !mapcheck("<s-down>","n") && exists("b:netrw_curdir")
    620      let s:didstarstar= 1
    621      nnoremap <buffer> <silent> <s-up>   :Pexplore<cr>
    622      nnoremap <buffer> <silent> <s-down> :Nexplore<cr>
    623    endif
    624 
    625    if has("path_extra")
    626      if !exists("w:netrw_explore_indx")
    627        let w:netrw_explore_indx= 0
    628      endif
    629 
    630      let indx = a:indx
    631 
    632      if indx == -1
    633        " Nexplore
    634        if !exists("w:netrw_explore_list") " sanity check
    635          call netrw#msg#Notify('WARNING', 'using Nexplore or <s-down> improperly; see help for netrw-starstar')
    636          if !has('nvim') && has("clipboard") && g:netrw_clipboard
    637            if @* != keepregstar | sil! let @* = keepregstar | endif
    638            if @+ != keepregplus | sil! let @+ = keepregplus | endif
    639          endif
    640          sil! let @/ = keepregslash
    641          return
    642        endif
    643        let indx= w:netrw_explore_indx
    644        if indx < 0                        | let indx= 0                           | endif
    645        if indx >= w:netrw_explore_listlen | let indx= w:netrw_explore_listlen - 1 | endif
    646        let curfile= w:netrw_explore_list[indx]
    647        while indx < w:netrw_explore_listlen && curfile == w:netrw_explore_list[indx]
    648          let indx= indx + 1
    649        endwhile
    650        if indx >= w:netrw_explore_listlen | let indx= w:netrw_explore_listlen - 1 | endif
    651 
    652      elseif indx == -2
    653        " Pexplore
    654        if !exists("w:netrw_explore_list") " sanity check
    655          call netrw#msg#Notify('WARNING', 'using Pexplore or <s-up> improperly; see help for netrw-starstar')
    656          if !has('nvim') && has("clipboard") && g:netrw_clipboard
    657            if @* != keepregstar | sil! let @* = keepregstar | endif
    658            if @+ != keepregplus | sil! let @+ = keepregplus | endif
    659          endif
    660          sil! let @/ = keepregslash
    661          return
    662        endif
    663        let indx= w:netrw_explore_indx
    664        if indx < 0                        | let indx= 0                           | endif
    665        if indx >= w:netrw_explore_listlen | let indx= w:netrw_explore_listlen - 1 | endif
    666        let curfile= w:netrw_explore_list[indx]
    667        while indx >= 0 && curfile == w:netrw_explore_list[indx]
    668          let indx= indx - 1
    669        endwhile
    670        if indx < 0                        | let indx= 0                           | endif
    671 
    672      else
    673        " Explore -- initialize
    674        " build list of files to Explore with Nexplore/Pexplore
    675        NetrwKeepj keepalt call s:NetrwClearExplore()
    676        let w:netrw_explore_indx= 0
    677        if !exists("b:netrw_curdir")
    678          let b:netrw_curdir= getcwd()
    679        endif
    680 
    681        " switch on starpat to build the w:netrw_explore_list of files
    682        if starpat == 1
    683          " starpat=1: Explore *//pattern  (current directory only search for files containing pattern)
    684          try
    685            exe "NetrwKeepj noautocmd vimgrep /".pattern."/gj ".fnameescape(b:netrw_curdir)."/*"
    686          catch /^Vim\%((\a\+)\)\=:E480/
    687            call netrw#msg#Notify('WARNING', printf("no match with pattern<%s>", pattern))
    688            return
    689          endtry
    690          let w:netrw_explore_list = s:NetrwExploreListUniq(map(getqflist(),'bufname(v:val.bufnr)'))
    691          if &hls | let keepregslash= s:ExplorePatHls(pattern) | endif
    692 
    693        elseif starpat == 2
    694          " starpat=2: Explore **//pattern (recursive descent search for files containing pattern)
    695          try
    696            exe "sil NetrwKeepj noautocmd keepalt vimgrep /".pattern."/gj "."**/*"
    697          catch /^Vim\%((\a\+)\)\=:E480/
    698            call netrw#msg#Notify('WARNING', printf('no files matched pattern<%s>', pattern))
    699            if &hls | let keepregslash= s:ExplorePatHls(pattern) | endif
    700            if !has('nvim') && has("clipboard") && g:netrw_clipboard
    701              if @* != keepregstar | sil! let @* = keepregstar | endif
    702              if @+ != keepregplus | sil! let @+ = keepregplus | endif
    703            endif
    704            sil! let @/ = keepregslash
    705            return
    706          endtry
    707          let s:netrw_curdir       = b:netrw_curdir
    708          let w:netrw_explore_list = getqflist()
    709          let w:netrw_explore_list = s:NetrwExploreListUniq(map(w:netrw_explore_list,'s:netrw_curdir."/".bufname(v:val.bufnr)'))
    710          if &hls | let keepregslash= s:ExplorePatHls(pattern) | endif
    711 
    712        elseif starpat == 3
    713          " starpat=3: Explore */filepat   (search in current directory for filenames matching filepat)
    714          let filepat= substitute(dirname,'^\*/','','')
    715          let filepat= substitute(filepat,'^[%#<]','\\&','')
    716          let w:netrw_explore_list= s:NetrwExploreListUniq(split(expand(b:netrw_curdir."/".filepat),'\n'))
    717          if &hls | let keepregslash= s:ExplorePatHls(filepat) | endif
    718 
    719        elseif starpat == 4
    720          " starpat=4: Explore **/filepat  (recursive descent search for filenames matching filepat)
    721          let w:netrw_explore_list= s:NetrwExploreListUniq(split(expand(b:netrw_curdir."/".dirname),'\n'))
    722          if &hls | let keepregslash= s:ExplorePatHls(dirname) | endif
    723        endif " switch on starpat to build w:netrw_explore_list
    724 
    725        let w:netrw_explore_listlen = len(w:netrw_explore_list)
    726 
    727        if w:netrw_explore_listlen == 0 || (w:netrw_explore_listlen == 1 && w:netrw_explore_list[0] =~ '\*\*\/')
    728          call netrw#msg#Notify('WARNING', 'no files matched')
    729          if !has('nvim') && has("clipboard") && g:netrw_clipboard
    730            if @* != keepregstar | sil! let @* = keepregstar | endif
    731            if @+ != keepregplus | sil! let @+ = keepregplus | endif
    732          endif
    733          sil! let @/ = keepregslash
    734          return
    735        endif
    736      endif  " if indx ... endif
    737 
    738      " NetrwStatusLine support - for exploring support
    739      let w:netrw_explore_indx= indx
    740 
    741      " wrap the indx around, but issue a note
    742      if indx >= w:netrw_explore_listlen || indx < 0
    743        let indx                = (indx < 0)? ( w:netrw_explore_listlen - 1 ) : 0
    744        let w:netrw_explore_indx= indx
    745        call netrw#msg#Notify('NOTE', 'no more files match Explore pattern')
    746      endif
    747 
    748      exe "let dirfile= w:netrw_explore_list[".indx."]"
    749      let newdir= substitute(dirfile,'/[^/]*$','','e')
    750 
    751      call netrw#LocalBrowseCheck(newdir)
    752      if !exists("w:netrw_liststyle")
    753        let w:netrw_liststyle= g:netrw_liststyle
    754      endif
    755      if w:netrw_liststyle == s:THINLIST || w:netrw_liststyle == s:LONGLIST
    756        keepalt NetrwKeepj call search('^'.substitute(dirfile,"^.*/","","").'\>',"W")
    757      else
    758        keepalt NetrwKeepj call search('\<'.substitute(dirfile,"^.*/","","").'\>',"w")
    759      endif
    760      let w:netrw_explore_mtchcnt = indx + 1
    761      let w:netrw_explore_bufnr   = bufnr("%")
    762      let w:netrw_explore_line    = line(".")
    763      keepalt NetrwKeepj call s:SetupNetrwStatusLine('%f %h%m%r%=%9*%{NetrwStatusLine()}')
    764 
    765    else
    766      call netrw#msg#Notify('WARNING', 'your vim needs the +path_extra feature for Exploring with **!')
    767      if !has('nvim') && has("clipboard") && g:netrw_clipboard
    768        if @* != keepregstar | sil! let @* = keepregstar | endif
    769        if @+ != keepregplus | sil! let @+ = keepregplus | endif
    770      endif
    771      sil! let @/ = keepregslash
    772      return
    773    endif
    774 
    775  else
    776    if exists("w:netrw_liststyle") && w:netrw_liststyle == s:TREELIST && dirname =~ '/'
    777      sil! unlet w:netrw_treedict
    778      sil! unlet w:netrw_treetop
    779    endif
    780    let newdir= dirname
    781    if !exists("b:netrw_curdir")
    782      NetrwKeepj call netrw#LocalBrowseCheck(getcwd())
    783    else
    784      NetrwKeepj call netrw#LocalBrowseCheck(s:NetrwBrowseChgDir(1,newdir,0))
    785    endif
    786  endif
    787 
    788  " visual display of **/ **// */ Exploration files
    789  if exists("w:netrw_explore_indx") && exists("b:netrw_curdir")
    790    if !exists("s:explore_prvdir") || s:explore_prvdir != b:netrw_curdir
    791      " only update match list when current directory isn't the same as before
    792      let s:explore_prvdir = b:netrw_curdir
    793      let s:explore_match  = ""
    794      let dirlen           = strlen(b:netrw_curdir)
    795      if b:netrw_curdir !~ '/$'
    796        let dirlen= dirlen + 1
    797      endif
    798      let prvfname= ""
    799      for fname in w:netrw_explore_list
    800        if fname =~ '^'.b:netrw_curdir
    801          if s:explore_match == ""
    802            let s:explore_match= '\<'.escape(strpart(fname,dirlen),g:netrw_markfileesc).'\>'
    803          else
    804            let s:explore_match= s:explore_match.'\|\<'.escape(strpart(fname,dirlen),g:netrw_markfileesc).'\>'
    805          endif
    806        elseif fname !~ '^/' && fname != prvfname
    807          if s:explore_match == ""
    808            let s:explore_match= '\<'.escape(fname,g:netrw_markfileesc).'\>'
    809          else
    810            let s:explore_match= s:explore_match.'\|\<'.escape(fname,g:netrw_markfileesc).'\>'
    811          endif
    812        endif
    813        let prvfname= fname
    814      endfor
    815      if has("syntax") && exists("g:syntax_on") && g:syntax_on
    816        exe "2match netrwMarkFile /".s:explore_match."/"
    817      endif
    818    endif
    819    echo "<s-up>==Pexplore  <s-down>==Nexplore"
    820  else
    821    2match none
    822    if exists("s:explore_match")  | unlet s:explore_match  | endif
    823    if exists("s:explore_prvdir") | unlet s:explore_prvdir | endif
    824  endif
    825 
    826  " since Explore may be used to initialize netrw's browser,
    827  " there's no danger of a late FocusGained event on initialization.
    828  " Consequently, set s:netrw_events to 2.
    829  let s:netrw_events= 2
    830  if !has('nvim') && has("clipboard") && g:netrw_clipboard
    831    if @* != keepregstar | sil! let @* = keepregstar | endif
    832    if @+ != keepregplus | sil! let @+ = keepregplus | endif
    833  endif
    834  sil! let @/ = keepregslash
    835 endfunction
    836 
    837 " netrw#Lexplore: toggle Explorer window, keeping it on the left of the current tab {{{2
    838 "   Uses  g:netrw_chgwin  : specifies the window where Lexplore files are to be opened
    839 "         t:netrw_lexposn : winsaveview() output (used on Lexplore window)
    840 "         t:netrw_lexbufnr: the buffer number of the Lexplore buffer  (internal to this function)
    841 "         s:lexplore_win  : window number of Lexplore window (serves to indicate which window is a Lexplore window)
    842 "         w:lexplore_buf  : buffer number of Lexplore window (serves to indicate which window is a Lexplore window)
    843 function netrw#Lexplore(count,rightside,...)
    844  let curwin= winnr()
    845 
    846  if a:0 > 0 && a:1 != ""
    847    " if a netrw window is already on the left-side of the tab
    848    " and a directory has been specified, explore with that
    849    " directory.
    850    let a1 = expand(a:1)
    851    exe "1wincmd w"
    852    if &ft == "netrw"
    853      exe "Explore ".fnameescape(a1)
    854      exe curwin."wincmd w"
    855      let s:lexplore_win= curwin
    856      let w:lexplore_buf= bufnr("%")
    857      if exists("t:netrw_lexposn")
    858        unlet t:netrw_lexposn
    859      endif
    860      return
    861    endif
    862    exe curwin."wincmd w"
    863  else
    864    let a1= ""
    865  endif
    866 
    867  if exists("t:netrw_lexbufnr")
    868    " check if t:netrw_lexbufnr refers to a netrw window
    869    let lexwinnr = bufwinnr(t:netrw_lexbufnr)
    870  else
    871    let lexwinnr= 0
    872  endif
    873 
    874  if lexwinnr > 0
    875    " close down netrw explorer window
    876    exe lexwinnr."wincmd w"
    877    let g:netrw_winsize = -winwidth(0)
    878    let t:netrw_lexposn = winsaveview()
    879    close
    880    if lexwinnr < curwin
    881      let curwin= curwin - 1
    882    endif
    883    if lexwinnr != curwin
    884      exe curwin."wincmd w"
    885    endif
    886    unlet t:netrw_lexbufnr
    887 
    888  else
    889    " open netrw explorer window
    890    exe "1wincmd w"
    891    let keep_altv    = g:netrw_altv
    892    let g:netrw_altv = 0
    893    if a:count != 0
    894      let netrw_winsize   = g:netrw_winsize
    895      let g:netrw_winsize = a:count
    896    endif
    897    let curfile= expand("%")
    898    exe (a:rightside? "botright" : "topleft")." vertical ".((g:netrw_winsize > 0)? (g:netrw_winsize*winwidth(0))/100 : -g:netrw_winsize) . " new"
    899    if a:0 > 0 && a1 != ""
    900      call netrw#Explore(0,0,0,a1)
    901      exe "Explore ".fnameescape(a1)
    902    elseif curfile =~ '^\a\{3,}://'
    903      call netrw#Explore(0,0,0,substitute(curfile,'[^/\\]*$','',''))
    904    else
    905      call netrw#Explore(0,0,0,".")
    906    endif
    907    if a:count != 0
    908      let g:netrw_winsize = netrw_winsize
    909    endif
    910    setlocal winfixwidth
    911    let g:netrw_altv     = keep_altv
    912    let t:netrw_lexbufnr = bufnr("%")
    913    " done to prevent build-up of hidden buffers due to quitting and re-invocation of :Lexplore.
    914    " Since the intended use of :Lexplore is to have an always-present explorer window, the extra
    915    " effort to prevent mis-use of :Lex is warranted.
    916    set bh=wipe
    917    if exists("t:netrw_lexposn")
    918      call winrestview(t:netrw_lexposn)
    919      unlet t:netrw_lexposn
    920    endif
    921  endif
    922 
    923  " set up default window for editing via <cr>
    924  if exists("g:netrw_chgwin") && g:netrw_chgwin == -1
    925    if a:rightside
    926      let g:netrw_chgwin= 1
    927    else
    928      let g:netrw_chgwin= 2
    929    endif
    930  endif
    931 
    932 endfunction
    933 
    934 " netrw#MakeTgt: make a target out of the directory name provided {{{2
    935 function netrw#MakeTgt(dname)
    936  " simplify the target (eg. /abc/def/../ghi -> /abc/ghi)
    937  let svpos               = winsaveview()
    938  let s:netrwmftgt_islocal= (a:dname !~ '^\a\{3,}://')
    939  if s:netrwmftgt_islocal
    940    let netrwmftgt= simplify(a:dname)
    941  else
    942    let netrwmftgt= a:dname
    943  endif
    944  if exists("s:netrwmftgt") && netrwmftgt == s:netrwmftgt
    945    " re-selected target, so just clear it
    946    unlet s:netrwmftgt s:netrwmftgt_islocal
    947  else
    948    let s:netrwmftgt= netrwmftgt
    949  endif
    950  if g:netrw_fastbrowse <= 1
    951    call s:NetrwRefresh((b:netrw_curdir !~ '\a\{3,}://'),b:netrw_curdir)
    952  endif
    953  call winrestview(svpos)
    954 endfunction
    955 
    956 " netrw#Obtain: {{{2
    957 "   netrw#Obtain(islocal,fname[,tgtdirectory])
    958 "     islocal=0  obtain from remote source
    959 "            =1  obtain from local source
    960 "     fname  :   a filename or a list of filenames
    961 "     tgtdir :   optional place where files are to go  (not present, uses getcwd())
    962 function netrw#Obtain(islocal,fname,...)
    963  " NetrwStatusLine support - for obtaining support
    964 
    965  if type(a:fname) == 1
    966    let fnamelist= [ a:fname ]
    967  elseif type(a:fname) == 3
    968    let fnamelist= a:fname
    969  else
    970    call netrw#msg#Notify('ERROR', 'attempting to use NetrwObtain on something not a filename or a list')
    971    return
    972  endif
    973  if a:0 > 0
    974    let tgtdir= a:1
    975  else
    976    let tgtdir= getcwd()
    977  endif
    978 
    979  if exists("b:netrw_islocal") && b:netrw_islocal
    980    " obtain a file from local b:netrw_curdir to (local) tgtdir
    981    if exists("b:netrw_curdir") && getcwd() != b:netrw_curdir
    982      let topath = netrw#fs#ComposePath(tgtdir,"")
    983      if has("win32")
    984        " transfer files one at time
    985        for fname in fnamelist
    986          call system(g:netrw_localcopycmd.g:netrw_localcopycmdopt." ".netrw#os#Escape(fname)." ".netrw#os#Escape(topath))
    987          if v:shell_error != 0
    988            call netrw#msg#Notify('WARNING', printf('consider setting g:netrw_localcopycmd<%s> to something that works', g:netrw_localcopycmd))
    989            return
    990          endif
    991        endfor
    992      else
    993        " transfer files with one command
    994        let filelist= join(map(deepcopy(fnamelist),"netrw#os#Escape(v:val)"))
    995        call system(g:netrw_localcopycmd.g:netrw_localcopycmdopt." ".filelist." ".netrw#os#Escape(topath))
    996        if v:shell_error != 0
    997          call netrw#msg#Notify('WARNING', printf('consider setting g:netrw_localcopycmd<%s> to something that works', g:netrw_localcopycmd))
    998          return
    999        endif
   1000      endif
   1001    elseif !exists("b:netrw_curdir")
   1002      call netrw#msg#Notify('ERROR', "local browsing directory doesn't exist!")
   1003    else
   1004      call netrw#msg#Notify('WARNING', 'local browsing directory and current directory are identical')
   1005    endif
   1006 
   1007  else
   1008    " obtain files from remote b:netrw_curdir to local tgtdir
   1009    if type(a:fname) == 1
   1010      call s:SetupNetrwStatusLine('%f %h%m%r%=%9*Obtaining '.a:fname)
   1011    endif
   1012    call s:NetrwMethod(b:netrw_curdir)
   1013    if !s:NetrwValidateHostname(g:netrw_machine)
   1014        call netrw#msg#Notify('ERROR', 'Rejecting invalid hostname: <%s>', g:netrw_machine)
   1015        return
   1016    endif
   1017 
   1018    if b:netrw_method == 4
   1019      " obtain file using scp
   1020      if exists("g:netrw_port") && g:netrw_port != ""
   1021        let useport= " ".g:netrw_scpport." ".g:netrw_port
   1022      else
   1023        let useport= ""
   1024      endif
   1025      if b:netrw_fname =~ '/'
   1026        let path= substitute(b:netrw_fname,'^\(.*/\).\{-}$','\1','')
   1027      else
   1028        let path= ""
   1029      endif
   1030      let filelist= join(map(deepcopy(fnamelist),'escape(netrw#os#Escape(g:netrw_machine.":".path.v:val,1)," ")'))
   1031      call netrw#os#Execute(s:netrw_silentxfer."!".g:netrw_scp_cmd.netrw#os#Escape(useport,1)." ".filelist." ".netrw#os#Escape(tgtdir,1))
   1032 
   1033    elseif b:netrw_method == 2
   1034      " obtain file using ftp + .netrc
   1035      call s:SaveBufVars()|sil NetrwKeepj new|call s:RestoreBufVars()
   1036      let tmpbufnr= bufnr("%")
   1037      setl ff=unix
   1038      if exists("g:netrw_ftpmode") && g:netrw_ftpmode != ""
   1039        NetrwKeepj put =g:netrw_ftpmode
   1040      endif
   1041 
   1042      if exists("b:netrw_fname") && b:netrw_fname != ""
   1043        call setline(line("$")+1,'cd "'.b:netrw_fname.'"')
   1044      endif
   1045 
   1046      if exists("g:netrw_ftpextracmd")
   1047        NetrwKeepj put =g:netrw_ftpextracmd
   1048      endif
   1049      for fname in fnamelist
   1050        call setline(line("$")+1,'get "'.fname.'"')
   1051      endfor
   1052      if exists("g:netrw_port") && g:netrw_port != ""
   1053        call netrw#os#Execute(s:netrw_silentxfer."%!".s:netrw_ftp_cmd." -i ".netrw#os#Escape(g:netrw_machine,1)." ".netrw#os#Escape(g:netrw_port,1))
   1054      else
   1055        call netrw#os#Execute(s:netrw_silentxfer."%!".s:netrw_ftp_cmd." -i ".netrw#os#Escape(g:netrw_machine,1))
   1056      endif
   1057      " If the result of the ftp operation isn't blank, show an error message (tnx to Doug Claar)
   1058      if getline(1) !~ "^$" && getline(1) !~ '^Trying '
   1059        let debugkeep= &debug
   1060        setl debug=msg
   1061        call netrw#msg#Notify('ERROR', getline(1))
   1062        let &debug= debugkeep
   1063      endif
   1064 
   1065    elseif b:netrw_method == 3
   1066      " obtain with ftp + machine, id, passwd, and fname (ie. no .netrc)
   1067      call s:SaveBufVars()|sil NetrwKeepj new|call s:RestoreBufVars()
   1068      let tmpbufnr= bufnr("%")
   1069      setl ff=unix
   1070 
   1071      if exists("g:netrw_port") && g:netrw_port != ""
   1072        NetrwKeepj put ='open '.g:netrw_machine.' '.g:netrw_port
   1073      else
   1074        NetrwKeepj put ='open '.g:netrw_machine
   1075      endif
   1076 
   1077      if exists("g:netrw_uid") && g:netrw_uid != ""
   1078        if exists("g:netrw_ftp") && g:netrw_ftp == 1
   1079          NetrwKeepj put =g:netrw_uid
   1080          if exists("s:netrw_passwd") && s:netrw_passwd != ""
   1081            NetrwKeepj put ='\"'.s:netrw_passwd.'\"'
   1082          endif
   1083        elseif exists("s:netrw_passwd")
   1084          NetrwKeepj put ='user \"'.g:netrw_uid.'\" \"'.s:netrw_passwd.'\"'
   1085        endif
   1086      endif
   1087 
   1088      if exists("g:netrw_ftpmode") && g:netrw_ftpmode != ""
   1089        NetrwKeepj put =g:netrw_ftpmode
   1090      endif
   1091 
   1092      if exists("b:netrw_fname") && b:netrw_fname != ""
   1093        NetrwKeepj call setline(line("$")+1,'cd "'.b:netrw_fname.'"')
   1094      endif
   1095 
   1096      if exists("g:netrw_ftpextracmd")
   1097        NetrwKeepj put =g:netrw_ftpextracmd
   1098      endif
   1099 
   1100      if exists("g:netrw_ftpextracmd")
   1101        NetrwKeepj put =g:netrw_ftpextracmd
   1102      endif
   1103      for fname in fnamelist
   1104        NetrwKeepj call setline(line("$")+1,'get "'.fname.'"')
   1105      endfor
   1106 
   1107      " perform ftp:
   1108      " -i       : turns off interactive prompting from ftp
   1109      " -n  unix : DON'T use <.netrc>, even though it exists
   1110      " -n  win32: quit being obnoxious about password
   1111      "  Note: using "_dd to delete to the black hole register; avoids messing up @@
   1112      NetrwKeepj norm! 1G"_dd
   1113      call netrw#os#Execute(s:netrw_silentxfer."%!".s:netrw_ftp_cmd." ".g:netrw_ftp_options)
   1114      " If the result of the ftp operation isn't blank, show an error message (tnx to Doug Claar)
   1115      if getline(1) !~ "^$"
   1116          call netrw#msg#Notify('ERROR', getline(1))
   1117      endif
   1118 
   1119    elseif b:netrw_method == 9
   1120      " obtain file using sftp
   1121      if a:fname =~ '/'
   1122        let localfile= substitute(a:fname,'^.*/','','')
   1123      else
   1124        let localfile= a:fname
   1125      endif
   1126      call netrw#os#Execute(s:netrw_silentxfer."!".g:netrw_sftp_cmd." ".netrw#os#Escape(g:netrw_machine.":".b:netrw_fname,1).netrw#os#Escape(localfile)." ".netrw#os#Escape(tgtdir))
   1127 
   1128    elseif !exists("b:netrw_method") || b:netrw_method < 0
   1129      " probably a badly formed url; protocol not recognized
   1130      return
   1131 
   1132    else
   1133      " protocol recognized but not supported for Obtain (yet?)
   1134        call netrw#msg#Notify('ERROR', 'current protocol not supported for obtaining file')
   1135      return
   1136    endif
   1137 
   1138    " restore status line
   1139    if type(a:fname) == 1 && exists("s:netrw_users_stl")
   1140      NetrwKeepj call s:SetupNetrwStatusLine(s:netrw_users_stl)
   1141    endif
   1142 
   1143  endif
   1144 
   1145  " cleanup
   1146  if exists("tmpbufnr")
   1147    if bufnr("%") != tmpbufnr
   1148      exe tmpbufnr."bw!"
   1149    else
   1150      q!
   1151    endif
   1152  endif
   1153 
   1154 endfunction
   1155 
   1156 " netrw#Nread: save position, call netrw#NetRead(), and restore position {{{2
   1157 function netrw#Nread(mode,fname)
   1158  let svpos= winsaveview()
   1159  call netrw#NetRead(a:mode,a:fname)
   1160  call winrestview(svpos)
   1161 
   1162  if exists("w:netrw_liststyle") && w:netrw_liststyle != s:TREELIST
   1163    if exists("w:netrw_bannercnt")
   1164      " start with cursor just after the banner
   1165      exe w:netrw_bannercnt
   1166    endif
   1167  endif
   1168 endfunction
   1169 
   1170 " s:NetrwOptionsSave: save options prior to setting to "netrw-buffer-standard" form {{{2
   1171 "             Options get restored by s:NetrwOptionsRestore()
   1172 "
   1173 "             Option handling:
   1174 "              * save user's options                                     (s:NetrwOptionsSave)
   1175 "              * set netrw-safe options                                  (s:NetrwOptionsSafe)
   1176 "                - change an option only when user option != safe option (s:netrwSetSafeSetting)
   1177 "              * restore user's options                                  (s:netrwOPtionsRestore)
   1178 "                - restore a user option when != safe option             (s:NetrwRestoreSetting)
   1179 "             vt: (variable type) normally its either "w:" or "s:"
   1180 function s:NetrwOptionsSave(vt)
   1181 
   1182  if !exists("{a:vt}netrw_optionsave")
   1183    let {a:vt}netrw_optionsave= 1
   1184  else
   1185    return
   1186  endif
   1187 
   1188  " Save current settings and current directory
   1189  let s:yykeep          = @@
   1190  if exists("&l:acd")|let {a:vt}netrw_acdkeep  = &l:acd|endif
   1191  let {a:vt}netrw_aikeep    = &l:ai
   1192  let {a:vt}netrw_awkeep    = &l:aw
   1193  let {a:vt}netrw_bhkeep    = &l:bh
   1194  let {a:vt}netrw_blkeep    = &l:bl
   1195  let {a:vt}netrw_btkeep    = &l:bt
   1196  let {a:vt}netrw_bombkeep  = &l:bomb
   1197  let {a:vt}netrw_cedit     = &cedit
   1198  let {a:vt}netrw_cikeep    = &l:ci
   1199  let {a:vt}netrw_cinkeep   = &l:cin
   1200  let {a:vt}netrw_cinokeep  = &l:cino
   1201  let {a:vt}netrw_comkeep   = &l:com
   1202  let {a:vt}netrw_cpokeep   = &l:cpo
   1203  let {a:vt}netrw_cuckeep   = &l:cuc
   1204  let {a:vt}netrw_culkeep   = &l:cul
   1205  let {a:vt}netrw_diffkeep  = &l:diff
   1206  let {a:vt}netrw_fenkeep   = &l:fen
   1207  if !exists("g:netrw_ffkeep") || g:netrw_ffkeep
   1208    let {a:vt}netrw_ffkeep    = &l:ff
   1209  endif
   1210  let {a:vt}netrw_fokeep    = &l:fo           " formatoptions
   1211  let {a:vt}netrw_gdkeep    = &l:gd           " gdefault
   1212  let {a:vt}netrw_gokeep    = &go             " guioptions
   1213  let {a:vt}netrw_hidkeep   = &l:hidden
   1214  let {a:vt}netrw_imkeep    = &l:im
   1215  let {a:vt}netrw_iskkeep   = &l:isk
   1216  let {a:vt}netrw_lines     = &lines
   1217  let {a:vt}netrw_lskeep    = &l:ls
   1218  let {a:vt}netrw_makeep    = &l:ma
   1219  let {a:vt}netrw_magickeep = &l:magic
   1220  let {a:vt}netrw_modkeep   = &l:mod
   1221  let {a:vt}netrw_nukeep    = &l:nu
   1222  let {a:vt}netrw_rnukeep   = &l:rnu
   1223  let {a:vt}netrw_repkeep   = &l:report
   1224  let {a:vt}netrw_rokeep    = &l:ro
   1225  let {a:vt}netrw_selkeep   = &l:sel
   1226  let {a:vt}netrw_spellkeep = &l:spell
   1227  if !g:netrw_use_noswf
   1228    let {a:vt}netrw_swfkeep  = &l:swf
   1229  endif
   1230  let {a:vt}netrw_tskeep    = &l:ts
   1231  let {a:vt}netrw_twkeep    = &l:tw           " textwidth
   1232  let {a:vt}netrw_wigkeep   = &l:wig          " wildignore
   1233  let {a:vt}netrw_wrapkeep  = &l:wrap
   1234  let {a:vt}netrw_writekeep = &l:write
   1235 
   1236  " save a few selected netrw-related variables
   1237  if g:netrw_keepdir
   1238    let {a:vt}netrw_dirkeep  = getcwd()
   1239  endif
   1240  if !has('nvim') && has("clipboard") && g:netrw_clipboard
   1241    sil! let {a:vt}netrw_starkeep = @*
   1242    sil! let {a:vt}netrw_pluskeep = @+
   1243  endif
   1244  sil! let {a:vt}netrw_slashkeep= @/
   1245 
   1246 endfunction
   1247 
   1248 " s:NetrwOptionsSafe: sets options to help netrw do its job {{{2
   1249 "                     Use  s:NetrwSaveOptions() to save user settings
   1250 "                     Use  s:NetrwOptionsRestore() to restore user settings
   1251 function s:NetrwOptionsSafe(islocal)
   1252  if exists("+acd") | call s:NetrwSetSafeSetting("&l:acd",0)|endif
   1253  call s:NetrwSetSafeSetting("&l:ai",0)
   1254  call s:NetrwSetSafeSetting("&l:aw",0)
   1255  call s:NetrwSetSafeSetting("&l:bl",0)
   1256  call s:NetrwSetSafeSetting("&l:bomb",0)
   1257  if a:islocal
   1258    call s:NetrwSetSafeSetting("&l:bt","nofile")
   1259  else
   1260    call s:NetrwSetSafeSetting("&l:bt","acwrite")
   1261  endif
   1262  call s:NetrwSetSafeSetting("&l:ci",0)
   1263  call s:NetrwSetSafeSetting("&l:cin",0)
   1264  if g:netrw_fastbrowse > a:islocal
   1265    call s:NetrwSetSafeSetting("&l:bh","hide")
   1266  else
   1267    call s:NetrwSetSafeSetting("&l:bh","delete")
   1268  endif
   1269  call s:NetrwSetSafeSetting("&l:cino","")
   1270  call s:NetrwSetSafeSetting("&l:com","")
   1271  if &cpo =~ 'a' | call s:NetrwSetSafeSetting("&cpo",substitute(&cpo,'a','','g')) | endif
   1272  if &cpo =~ 'A' | call s:NetrwSetSafeSetting("&cpo",substitute(&cpo,'A','','g')) | endif
   1273  setl fo=nroql2
   1274  if &go =~ 'a' | set go-=a | endif
   1275  if &go =~ 'A' | set go-=A | endif
   1276  if &go =~ 'P' | set go-=P | endif
   1277  call s:NetrwSetSafeSetting("&l:hid",0)
   1278  call s:NetrwSetSafeSetting("&l:im",0)
   1279  setl isk+=@ isk+=* isk+=/
   1280  call s:NetrwSetSafeSetting("&l:magic",1)
   1281  if g:netrw_use_noswf
   1282    call s:NetrwSetSafeSetting("swf",0)
   1283  endif
   1284  call s:NetrwSetSafeSetting("&l:report",10000)
   1285  call s:NetrwSetSafeSetting("&l:sel","inclusive")
   1286  call s:NetrwSetSafeSetting("&l:spell",0)
   1287  call s:NetrwSetSafeSetting("&l:tw",0)
   1288  call s:NetrwSetSafeSetting("&l:wig","")
   1289  setl cedit&
   1290 
   1291  " set up cuc and cul based on g:netrw_cursor and listing style
   1292  " COMBAK -- cuc cul related
   1293  call s:NetrwCursor(0)
   1294 
   1295  " allow the user to override safe options
   1296  if &ft == "netrw"
   1297    keepalt NetrwKeepj doau FileType netrw
   1298  endif
   1299 
   1300 endfunction
   1301 
   1302 " s:NetrwOptionsRestore: restore options (based on prior s:NetrwOptionsSave) {{{2
   1303 function s:NetrwOptionsRestore(vt)
   1304  if !exists("{a:vt}netrw_optionsave")
   1305    " filereadable() returns zero for remote files (e.g. scp://user@localhost//etc/fstab)
   1306    " Note: @ may not be in 'isfname', so '^\w\+://\f\+/' may not match
   1307    if filereadable(expand("%")) || expand("%") =~# '^\w\+://\f\+'
   1308      filetype detect
   1309    else
   1310      setl ft=netrw
   1311    endif
   1312    return
   1313  endif
   1314  unlet {a:vt}netrw_optionsave
   1315 
   1316  if exists("+acd")
   1317    if exists("{a:vt}netrw_acdkeep")
   1318      let curdir = getcwd()
   1319      let &l:acd = {a:vt}netrw_acdkeep
   1320      unlet {a:vt}netrw_acdkeep
   1321      if &l:acd
   1322        call s:NetrwLcd(curdir)
   1323      endif
   1324    endif
   1325  endif
   1326  call s:NetrwRestoreSetting(a:vt."netrw_aikeep","&l:ai")
   1327  call s:NetrwRestoreSetting(a:vt."netrw_awkeep","&l:aw")
   1328  call s:NetrwRestoreSetting(a:vt."netrw_blkeep","&l:bl")
   1329  call s:NetrwRestoreSetting(a:vt."netrw_btkeep","&l:bt")
   1330  call s:NetrwRestoreSetting(a:vt."netrw_bombkeep","&l:bomb")
   1331  call s:NetrwRestoreSetting(a:vt."netrw_cedit","&cedit")
   1332  call s:NetrwRestoreSetting(a:vt."netrw_cikeep","&l:ci")
   1333  call s:NetrwRestoreSetting(a:vt."netrw_cinkeep","&l:cin")
   1334  call s:NetrwRestoreSetting(a:vt."netrw_cinokeep","&l:cino")
   1335  call s:NetrwRestoreSetting(a:vt."netrw_comkeep","&l:com")
   1336  call s:NetrwRestoreSetting(a:vt."netrw_cpokeep","&l:cpo")
   1337  call s:NetrwRestoreSetting(a:vt."netrw_diffkeep","&l:diff")
   1338  call s:NetrwRestoreSetting(a:vt."netrw_fenkeep","&l:fen")
   1339  if exists("g:netrw_ffkeep") && g:netrw_ffkeep
   1340    call s:NetrwRestoreSetting(a:vt."netrw_ffkeep")","&l:ff")
   1341  endif
   1342  call s:NetrwRestoreSetting(a:vt."netrw_fokeep"   ,"&l:fo")
   1343  call s:NetrwRestoreSetting(a:vt."netrw_gdkeep"   ,"&l:gd")
   1344  call s:NetrwRestoreSetting(a:vt."netrw_gokeep"   ,"&go")
   1345  call s:NetrwRestoreSetting(a:vt."netrw_hidkeep"  ,"&l:hidden")
   1346  call s:NetrwRestoreSetting(a:vt."netrw_imkeep"   ,"&l:im")
   1347  call s:NetrwRestoreSetting(a:vt."netrw_iskkeep"  ,"&l:isk")
   1348  call s:NetrwRestoreSetting(a:vt."netrw_lines"    ,"&lines")
   1349  call s:NetrwRestoreSetting(a:vt."netrw_lskeep"   ,"&l:ls")
   1350  call s:NetrwRestoreSetting(a:vt."netrw_makeep"   ,"&l:ma")
   1351  call s:NetrwRestoreSetting(a:vt."netrw_magickeep","&l:magic")
   1352  call s:NetrwRestoreSetting(a:vt."netrw_modkeep"  ,"&l:mod")
   1353  call s:NetrwRestoreSetting(a:vt."netrw_nukeep"   ,"&l:nu")
   1354  call s:NetrwRestoreSetting(a:vt."netrw_rnukeep"  ,"&l:rnu")
   1355  call s:NetrwRestoreSetting(a:vt."netrw_repkeep"  ,"&l:report")
   1356  call s:NetrwRestoreSetting(a:vt."netrw_rokeep"   ,"&l:ro")
   1357  call s:NetrwRestoreSetting(a:vt."netrw_selkeep"  ,"&l:sel")
   1358  call s:NetrwRestoreSetting(a:vt."netrw_spellkeep","&l:spell")
   1359  call s:NetrwRestoreSetting(a:vt."netrw_twkeep"   ,"&l:tw")
   1360  call s:NetrwRestoreSetting(a:vt."netrw_wigkeep"  ,"&l:wig")
   1361  call s:NetrwRestoreSetting(a:vt."netrw_wrapkeep" ,"&l:wrap")
   1362  call s:NetrwRestoreSetting(a:vt."netrw_writekeep","&l:write")
   1363  call s:NetrwRestoreSetting("s:yykeep","@@")
   1364  " former problem: start with liststyle=0; press <i> : result, following line resets l:ts.
   1365  " Fixed; in s:PerformListing, when w:netrw_liststyle is s:LONGLIST, will use a printf to pad filename with spaces
   1366  "        rather than by appending a tab which previously was using "&ts" to set the desired spacing.  (Sep 28, 2018)
   1367  call s:NetrwRestoreSetting(a:vt."netrw_tskeep","&l:ts")
   1368 
   1369  if exists("{a:vt}netrw_swfkeep")
   1370    if &directory == ""
   1371      " user hasn't specified a swapfile directory;
   1372      " netrw will temporarily set the swapfile directory
   1373      " to the current directory as returned by getcwd().
   1374      let &l:directory= getcwd()
   1375      sil! let &l:swf = {a:vt}netrw_swfkeep
   1376      setl directory=
   1377      unlet {a:vt}netrw_swfkeep
   1378    elseif &l:swf != {a:vt}netrw_swfkeep
   1379      if !g:netrw_use_noswf
   1380        " following line causes a Press ENTER in windows -- can't seem to work around it!!!
   1381        sil! let &l:swf= {a:vt}netrw_swfkeep
   1382      endif
   1383      unlet {a:vt}netrw_swfkeep
   1384    endif
   1385  endif
   1386  if exists("{a:vt}netrw_dirkeep") && isdirectory(s:NetrwFile({a:vt}netrw_dirkeep)) && g:netrw_keepdir
   1387    let dirkeep = substitute({a:vt}netrw_dirkeep,'\\','/','g')
   1388    if exists("{a:vt}netrw_dirkeep")
   1389      call s:NetrwLcd(dirkeep)
   1390      unlet {a:vt}netrw_dirkeep
   1391    endif
   1392  endif
   1393  if !has('nvim') && has("clipboard") && g:netrw_clipboard
   1394    call s:NetrwRestoreSetting(a:vt."netrw_starkeep","@*")
   1395    call s:NetrwRestoreSetting(a:vt."netrw_pluskeep","@+")
   1396  endif
   1397  call s:NetrwRestoreSetting(a:vt."netrw_slashkeep","@/")
   1398 
   1399  " Moved the filetype detect here from NetrwGetFile() because remote files
   1400  " were having their filetype detect-generated settings overwritten by
   1401  " NetrwOptionRestore.
   1402  if &ft != "netrw"
   1403    filetype detect
   1404  endif
   1405 endfunction
   1406 
   1407 " s:NetrwSetSafeSetting: sets an option to a safe setting {{{2
   1408 "                        but only when the options' value and the safe setting differ
   1409 "                        Doing this means that netrw will not come up as having changed a
   1410 "                        setting last when it really didn't actually change it.
   1411 "
   1412 "                        Called from s:NetrwOptionsSafe
   1413 "                          ex. call s:NetrwSetSafeSetting("&l:sel","inclusive")
   1414 function s:NetrwSetSafeSetting(setting,safesetting)
   1415 
   1416  if a:setting =~ '^&'
   1417    exe "let settingval= ".a:setting
   1418 
   1419    if settingval != a:safesetting
   1420      if type(a:safesetting) == 0
   1421        exe "let ".a:setting."=".a:safesetting
   1422      elseif type(a:safesetting) == 1
   1423        exe "let ".a:setting."= '".a:safesetting."'"
   1424      else
   1425        call netrw#msg#Notify('ERROR', printf("(s:NetrwRestoreSetting) doesn't know how to restore %s with a safesetting of type#%s", a:setting, type(a:safesetting)))
   1426      endif
   1427    endif
   1428  endif
   1429 
   1430 endfunction
   1431 
   1432 " s:NetrwRestoreSetting: restores specified setting using associated keepvar, {{{2
   1433 "                        but only if the setting value differs from the associated keepvar.
   1434 "                        Doing this means that netrw will not come up as having changed a
   1435 "                        setting last when it really didn't actually change it.
   1436 "
   1437 "                        Used by s:NetrwOptionsRestore() to restore each netrw-sensitive setting
   1438 "                        keepvars are set up by s:NetrwOptionsSave
   1439 function s:NetrwRestoreSetting(keepvar,setting)
   1440 
   1441  " typically called from s:NetrwOptionsRestore
   1442  "   call s:NetrwRestoreSettings(keep-option-variable-name,'associated-option')
   1443  "   ex. call s:NetrwRestoreSetting(a:vt."netrw_selkeep","&l:sel")
   1444  "  Restores option (but only if different) from a:keepvar
   1445  if exists(a:keepvar)
   1446    exe "let keepvarval= ".a:keepvar
   1447    exe "let setting= ".a:setting
   1448 
   1449 
   1450    if setting != keepvarval
   1451      if type(a:setting) == 0
   1452        exe "let ".a:setting."= ".keepvarval
   1453      elseif type(a:setting) == 1
   1454        exe "let ".a:setting."= '".substitute(keepvarval,"'","''","g")."'"
   1455      else
   1456        call netrw#msg#Notify('ERROR', printf("(s:NetrwRestoreSetting) doesn't know how to restore %s with a setting of type#%s", a:keepvar, type(a:setting)))
   1457      endif
   1458    endif
   1459 
   1460    exe "unlet ".a:keepvar
   1461  endif
   1462 
   1463 endfunction
   1464 
   1465 " NetrwStatusLine: {{{2
   1466 
   1467 function NetrwStatusLine()
   1468    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")
   1469        let &stl= s:netrw_explore_stl
   1470        unlet! w:netrw_explore_bufnr w:netrw_explore_line
   1471        return ""
   1472    else
   1473        return "Match ".w:netrw_explore_mtchcnt." of ".w:netrw_explore_listlen
   1474    endif
   1475 endfunction
   1476 
   1477 "  Netrw Transfer Functions: {{{1
   1478 
   1479 " netrw#NetRead: responsible for reading a file over the net {{{2
   1480 "   mode: =0 read remote file and insert before current line
   1481 "         =1 read remote file and insert after current line
   1482 "         =2 replace with remote file
   1483 "         =3 obtain file, but leave in temporary format
   1484 function netrw#NetRead(mode,...)
   1485 
   1486    " NetRead: save options {{{3
   1487    call s:NetrwOptionsSave("w:")
   1488    call s:NetrwOptionsSafe(0)
   1489    call s:RestoreCursorline()
   1490    " NetrwSafeOptions sets a buffer up for a netrw listing, which includes buflisting off.
   1491    " However, this setting is not wanted for a remote editing session.  The buffer should be "nofile", still.
   1492    setl bl
   1493 
   1494    " NetRead: interpret mode into a readcmd {{{3
   1495    if     a:mode == 0 " read remote file before current line
   1496        let readcmd = "0r"
   1497    elseif a:mode == 1 " read file after current line
   1498        let readcmd = "r"
   1499    elseif a:mode == 2 " replace with remote file
   1500        let readcmd = "%r"
   1501    elseif a:mode == 3 " skip read of file (leave as temporary)
   1502        let readcmd = "t"
   1503    else
   1504        exe a:mode
   1505        let readcmd = "r"
   1506    endif
   1507    let ichoice = (a:0 == 0)? 0 : 1
   1508 
   1509    " NetRead: get temporary filename {{{3
   1510    let tmpfile= s:GetTempfile("")
   1511    if tmpfile == ""
   1512        return
   1513    endif
   1514 
   1515    while ichoice <= a:0
   1516 
   1517        " attempt to repeat with previous host-file-etc
   1518        if exists("b:netrw_lastfile") && a:0 == 0
   1519            let choice = b:netrw_lastfile
   1520            let ichoice= ichoice + 1
   1521 
   1522        else
   1523            exe "let choice= a:" . ichoice
   1524 
   1525            if match(choice,"?") == 0
   1526                " give help
   1527                echomsg 'NetRead Usage:'
   1528                echomsg ':Nread machine:path                         uses rcp'
   1529                echomsg ':Nread "machine path"                       uses ftp   with <.netrc>'
   1530                echomsg ':Nread "machine id password path"           uses ftp'
   1531                echomsg ':Nread dav://machine[:port]/path            uses cadaver'
   1532                echomsg ':Nread fetch://machine/path                 uses fetch'
   1533                echomsg ':Nread ftp://[user@]machine[:port]/path     uses ftp   autodetects <.netrc>'
   1534                echomsg ':Nread http://[user@]machine/path           uses http  wget'
   1535                echomsg ':Nread file:///path                         uses elinks'
   1536                echomsg ':Nread https://[user@]machine/path          uses http  wget'
   1537                echomsg ':Nread rcp://[user@]machine/path            uses rcp'
   1538                echomsg ':Nread rsync://machine[:port]/path          uses rsync'
   1539                echomsg ':Nread scp://[user@]machine[[:#]port]/path  uses scp'
   1540                echomsg ':Nread sftp://[user@]machine[[:#]port]/path uses sftp'
   1541                sleep 4
   1542                break
   1543 
   1544            elseif match(choice,'^"') != -1
   1545                " Reconstruct Choice if choice starts with '"'
   1546                if match(choice,'"$') != -1
   1547                    " case "..."
   1548                    let choice= strpart(choice,1,strlen(choice)-2)
   1549                else
   1550                    "  case "... ... ..."
   1551                    let choice      = strpart(choice,1,strlen(choice)-1)
   1552                    let wholechoice = ""
   1553 
   1554                    while match(choice,'"$') == -1
   1555                        let wholechoice = wholechoice . " " . choice
   1556                        let ichoice     = ichoice + 1
   1557                        if ichoice > a:0
   1558                            call netrw#msg#Notify('ERROR', printf('Unbalanced string in filename "%s"', wholechoice))
   1559                            return
   1560                        endif
   1561                        let choice= a:{ichoice}
   1562                    endwhile
   1563                    let choice= strpart(wholechoice,1,strlen(wholechoice)-1) . " " . strpart(choice,0,strlen(choice)-1)
   1564                endif
   1565            endif
   1566        endif
   1567 
   1568        let ichoice= ichoice + 1
   1569 
   1570        " NetRead: Determine method of read (ftp, rcp, etc) {{{3
   1571        call s:NetrwMethod(choice)
   1572        if !exists("b:netrw_method") || b:netrw_method < 0
   1573            return
   1574        endif
   1575        if !s:NetrwValidateHostname(g:netrw_machine)
   1576            call netrw#msg#Notify('ERROR', printf('Rejecting invalid hostname: <%s>', g:netrw_machine))
   1577            return
   1578        endif
   1579        let tmpfile= s:GetTempfile(b:netrw_fname) " apply correct suffix
   1580 
   1581        " Check whether or not NetrwBrowse() should be handling this request
   1582        if choice =~ "^.*[\/]$" && b:netrw_method != 5 && choice !~ '^https\=://'
   1583            NetrwKeepj call s:NetrwBrowse(0,choice)
   1584            return
   1585        endif
   1586 
   1587        " ============
   1588        " NetRead: Perform Protocol-Based Read {{{3
   1589        " ===========================
   1590        if exists("g:netrw_silent") && g:netrw_silent == 0 && &ch >= 1
   1591            echo "(netrw) Processing your read request..."
   1592        endif
   1593 
   1594        ".........................................
   1595        " NetRead: (rcp)  NetRead Method #1 {{{3
   1596        if  b:netrw_method == 1 " read with rcp
   1597            " ER: nothing done with g:netrw_uid yet?
   1598            " ER: on Win2K" rcp machine[.user]:file tmpfile
   1599            " ER: when machine contains '.' adding .user is required (use $USERNAME)
   1600            " ER: the tmpfile is full path: rcp sees C:\... as host C
   1601            if s:netrw_has_nt_rcp == 1
   1602                if exists("g:netrw_uid") && ( g:netrw_uid != "" )
   1603                    let uid_machine = g:netrw_machine .'.'. g:netrw_uid
   1604                else
   1605                    " Any way needed it machine contains a '.'
   1606                    let uid_machine = g:netrw_machine .'.'. $USERNAME
   1607                endif
   1608            else
   1609                if exists("g:netrw_uid") && ( g:netrw_uid != "" )
   1610                    let uid_machine = g:netrw_uid .'@'. g:netrw_machine
   1611                else
   1612                    let uid_machine = g:netrw_machine
   1613                endif
   1614            endif
   1615            call netrw#os#Execute(s:netrw_silentxfer."!".g:netrw_rcp_cmd." ".s:netrw_rcpmode." ".netrw#os#Escape(uid_machine.":".b:netrw_fname,1)." ".netrw#os#Escape(tmpfile,1))
   1616            let result           = s:NetrwGetFile(readcmd, tmpfile, b:netrw_method)
   1617            let b:netrw_lastfile = choice
   1618 
   1619            ".........................................
   1620        " NetRead: (ftp + <.netrc>)  NetRead Method #2 {{{3
   1621        elseif b:netrw_method  == 2          " read with ftp + <.netrc>
   1622            let netrw_fname= b:netrw_fname
   1623            NetrwKeepj call s:SaveBufVars()|new|NetrwKeepj call s:RestoreBufVars()
   1624            let filtbuf= bufnr("%")
   1625            setl ff=unix
   1626            NetrwKeepj put =g:netrw_ftpmode
   1627            if exists("g:netrw_ftpextracmd")
   1628                NetrwKeepj put =g:netrw_ftpextracmd
   1629            endif
   1630            call setline(line("$")+1,'get "'.netrw_fname.'" '.tmpfile)
   1631            if exists("g:netrw_port") && g:netrw_port != ""
   1632                call netrw#os#Execute(s:netrw_silentxfer."%!".s:netrw_ftp_cmd." -i ".netrw#os#Escape(g:netrw_machine,1)." ".netrw#os#Escape(g:netrw_port,1))
   1633            else
   1634                call netrw#os#Execute(s:netrw_silentxfer."%!".s:netrw_ftp_cmd." -i ".netrw#os#Escape(g:netrw_machine,1))
   1635            endif
   1636            " If the result of the ftp operation isn't blank, show an error message (tnx to Doug Claar)
   1637            if getline(1) !~ "^$" && getline(1) !~ '^Trying '
   1638                let debugkeep = &debug
   1639                setl debug=msg
   1640                call netrw#msg#Notify('ERROR', getline(1))
   1641                let &debug    = debugkeep
   1642            endif
   1643            call s:SaveBufVars()
   1644            keepj bd!
   1645            if bufname("%") == "" && getline("$") == "" && line('$') == 1
   1646                " needed when one sources a file in a nolbl setting window via ftp
   1647                q!
   1648            endif
   1649            call s:RestoreBufVars()
   1650            let result           = s:NetrwGetFile(readcmd, tmpfile, b:netrw_method)
   1651            let b:netrw_lastfile = choice
   1652 
   1653            ".........................................
   1654        " NetRead: (ftp + machine,id,passwd,filename)  NetRead Method #3 {{{3
   1655        elseif b:netrw_method == 3           " read with ftp + machine, id, passwd, and fname
   1656            " Construct execution string (four lines) which will be passed through filter
   1657            let netrw_fname= escape(b:netrw_fname,g:netrw_fname_escape)
   1658            NetrwKeepj call s:SaveBufVars()|new|NetrwKeepj call s:RestoreBufVars()
   1659            let filtbuf= bufnr("%")
   1660            setl ff=unix
   1661            if exists("g:netrw_port") && g:netrw_port != ""
   1662                NetrwKeepj put ='open '.g:netrw_machine.' '.g:netrw_port
   1663            else
   1664                NetrwKeepj put ='open '.g:netrw_machine
   1665            endif
   1666 
   1667            if exists("g:netrw_uid") && g:netrw_uid != ""
   1668                if exists("g:netrw_ftp") && g:netrw_ftp == 1
   1669                    NetrwKeepj put =g:netrw_uid
   1670                    if exists("s:netrw_passwd")
   1671                        NetrwKeepj put ='\"'.s:netrw_passwd.'\"'
   1672                    endif
   1673                elseif exists("s:netrw_passwd")
   1674                    NetrwKeepj put ='user \"'.g:netrw_uid.'\" \"'.s:netrw_passwd.'\"'
   1675                endif
   1676            endif
   1677 
   1678            if exists("g:netrw_ftpmode") && g:netrw_ftpmode != ""
   1679                NetrwKeepj put =g:netrw_ftpmode
   1680            endif
   1681            if exists("g:netrw_ftpextracmd")
   1682                NetrwKeepj put =g:netrw_ftpextracmd
   1683            endif
   1684            NetrwKeepj put ='get \"'.netrw_fname.'\" '.tmpfile
   1685 
   1686            " perform ftp:
   1687            " -i       : turns off interactive prompting from ftp
   1688            " -n  unix : DON'T use <.netrc>, even though it exists
   1689            " -n  win32: quit being obnoxious about password
   1690            NetrwKeepj norm! 1G"_dd
   1691            call netrw#os#Execute(s:netrw_silentxfer."%!".s:netrw_ftp_cmd." ".g:netrw_ftp_options)
   1692            " If the result of the ftp operation isn't blank, show an error message (tnx to Doug Claar)
   1693            if getline(1) !~ "^$"
   1694                call netrw#msg#Notify('ERROR', getline(1))
   1695            endif
   1696            call s:SaveBufVars()|keepj bd!|call s:RestoreBufVars()
   1697            let result           = s:NetrwGetFile(readcmd, tmpfile, b:netrw_method)
   1698            let b:netrw_lastfile = choice
   1699 
   1700            ".........................................
   1701        " NetRead: (scp) NetRead Method #4 {{{3
   1702        elseif     b:netrw_method  == 4      " read with scp
   1703            if exists("g:netrw_port") && g:netrw_port != ""
   1704                let useport= " ".g:netrw_scpport." ".g:netrw_port
   1705            else
   1706                let useport= ""
   1707            endif
   1708            " Using UNC notation in windows to get a unix like path.
   1709            " This is workaround to avoid mis-handle windows local-path:
   1710            if g:netrw_scp_cmd =~ '^scp' && has("win32")
   1711                let tmpfile_get = substitute(tr(tmpfile, '\', '/'), '^\(\a\):[/\\]\(.*\)$', '//' .. $COMPUTERNAME .. '/\1$/\2', '')
   1712            else
   1713                let tmpfile_get = tmpfile
   1714            endif
   1715            call netrw#os#Execute(s:netrw_silentxfer."!".g:netrw_scp_cmd.useport." ".escape(netrw#os#Escape(g:netrw_machine.":".b:netrw_fname,1),' ')." ".netrw#os#Escape(tmpfile_get,1))
   1716            let result           = s:NetrwGetFile(readcmd, tmpfile, b:netrw_method)
   1717            let b:netrw_lastfile = choice
   1718 
   1719            ".........................................
   1720        " NetRead: (http) NetRead Method #5 (wget) {{{3
   1721        elseif     b:netrw_method  == 5
   1722            if g:netrw_http_cmd == ""
   1723                call netrw#msg#Notify('ERROR', 'neither the wget nor the fetch command is available')
   1724                return
   1725            endif
   1726 
   1727            if match(b:netrw_fname,"#") == -1 || exists("g:netrw_http_xcmd")
   1728                " using g:netrw_http_cmd (usually elinks, links, curl, wget, or fetch)
   1729                if exists("g:netrw_http_xcmd")
   1730                    call netrw#os#Execute(s:netrw_silentxfer."!".g:netrw_http_cmd." ".netrw#os#Escape(b:netrw_http."://".g:netrw_machine.b:netrw_fname,1)." ".g:netrw_http_xcmd." ".netrw#os#Escape(tmpfile,1))
   1731                else
   1732                    call netrw#os#Execute(s:netrw_silentxfer."!".g:netrw_http_cmd." ".netrw#os#Escape(tmpfile,1)." ".netrw#os#Escape(b:netrw_http."://".g:netrw_machine.b:netrw_fname,1))
   1733                endif
   1734                let result = s:NetrwGetFile(readcmd, tmpfile, b:netrw_method)
   1735 
   1736            else
   1737                " wget/curl/fetch plus a jump to an in-page marker (ie. http://abc/def.html#aMarker)
   1738                let netrw_html= substitute(b:netrw_fname,"#.*$","","")
   1739                let netrw_tag = substitute(b:netrw_fname,"^.*#","","")
   1740                call netrw#os#Execute(s:netrw_silentxfer."!".g:netrw_http_cmd." ".netrw#os#Escape(tmpfile,1)." ".netrw#os#Escape(b:netrw_http."://".g:netrw_machine.netrw_html,1))
   1741                let result = s:NetrwGetFile(readcmd, tmpfile, b:netrw_method)
   1742                exe 'NetrwKeepj norm! 1G/<\s*a\s*name=\s*"'.netrw_tag.'"/'."\<CR>"
   1743            endif
   1744            let b:netrw_lastfile = choice
   1745            setl ro nomod
   1746 
   1747            ".........................................
   1748        " NetRead: (dav) NetRead Method #6 {{{3
   1749        elseif     b:netrw_method  == 6
   1750 
   1751            if !executable(g:netrw_dav_cmd)
   1752                call netrw#msg#Notify('ERROR', printf('%s is not executable', g:netrw_dav_cmd))
   1753                return
   1754            endif
   1755            if g:netrw_dav_cmd =~ "curl"
   1756                call netrw#os#Execute(s:netrw_silentxfer."!".g:netrw_dav_cmd." ".netrw#os#Escape("dav://".g:netrw_machine.b:netrw_fname,1)." ".netrw#os#Escape(tmpfile,1))
   1757            else
   1758                " Construct execution string (four lines) which will be passed through filter
   1759                let netrw_fname= escape(b:netrw_fname,g:netrw_fname_escape)
   1760                new
   1761                setl ff=unix
   1762                if exists("g:netrw_port") && g:netrw_port != ""
   1763                    NetrwKeepj put ='open '.g:netrw_machine.' '.g:netrw_port
   1764                else
   1765                    NetrwKeepj put ='open '.g:netrw_machine
   1766                endif
   1767                if exists("g:netrw_uid") && exists("s:netrw_passwd") && g:netrw_uid != ""
   1768                    NetrwKeepj put ='user '.g:netrw_uid.' '.s:netrw_passwd
   1769                endif
   1770                NetrwKeepj put ='get '.netrw_fname.' '.tmpfile
   1771                NetrwKeepj put ='quit'
   1772 
   1773                " perform cadaver operation:
   1774                NetrwKeepj norm! 1G"_dd
   1775                call netrw#os#Execute(s:netrw_silentxfer."%!".g:netrw_dav_cmd)
   1776                keepj bd!
   1777            endif
   1778            let result           = s:NetrwGetFile(readcmd, tmpfile, b:netrw_method)
   1779            let b:netrw_lastfile = choice
   1780 
   1781            ".........................................
   1782        " NetRead: (rsync) NetRead Method #7 {{{3
   1783        elseif     b:netrw_method  == 7
   1784            call netrw#os#Execute(s:netrw_silentxfer."!".g:netrw_rsync_cmd." ".netrw#os#Escape(g:netrw_machine.g:netrw_rsync_sep.b:netrw_fname,1)." ".netrw#os#Escape(tmpfile,1))
   1785            let result           = s:NetrwGetFile(readcmd,tmpfile, b:netrw_method)
   1786            let b:netrw_lastfile = choice
   1787 
   1788            ".........................................
   1789        " NetRead: (fetch) NetRead Method #8 {{{3
   1790        "    fetch://[user@]host[:http]/path
   1791        elseif     b:netrw_method  == 8
   1792            if g:netrw_fetch_cmd == ""
   1793                call netrw#msg#Notify('ERROR', "fetch command not available")
   1794                return
   1795            endif
   1796            if exists("g:netrw_option") && g:netrw_option =~ ":https\="
   1797                let netrw_option= "http"
   1798            else
   1799                let netrw_option= "ftp"
   1800            endif
   1801 
   1802            if exists("g:netrw_uid") && g:netrw_uid != "" && exists("s:netrw_passwd") && s:netrw_passwd != ""
   1803                call netrw#os#Execute(s:netrw_silentxfer."!".g:netrw_fetch_cmd." ".netrw#os#Escape(tmpfile,1)." ".netrw#os#Escape(netrw_option."://".g:netrw_uid.':'.s:netrw_passwd.'@'.g:netrw_machine."/".b:netrw_fname,1))
   1804            else
   1805                call netrw#os#Execute(s:netrw_silentxfer."!".g:netrw_fetch_cmd." ".netrw#os#Escape(tmpfile,1)." ".netrw#os#Escape(netrw_option."://".g:netrw_machine."/".b:netrw_fname,1))
   1806            endif
   1807 
   1808            let result          = s:NetrwGetFile(readcmd,tmpfile, b:netrw_method)
   1809            let b:netrw_lastfile = choice
   1810            setl ro nomod
   1811 
   1812            ".........................................
   1813        " NetRead: (sftp) NetRead Method #9 {{{3
   1814        elseif     b:netrw_method  == 9
   1815            call netrw#os#Execute(s:netrw_silentxfer."!".g:netrw_sftp_cmd." ".netrw#os#Escape(g:netrw_machine.":".b:netrw_fname,1)." ".tmpfile)
   1816            let result          = s:NetrwGetFile(readcmd, tmpfile, b:netrw_method)
   1817            let b:netrw_lastfile = choice
   1818 
   1819            ".........................................
   1820        " NetRead: (file) NetRead Method #10 {{{3
   1821        elseif      b:netrw_method == 10 && exists("g:netrw_file_cmd")
   1822            call netrw#os#Execute(s:netrw_silentxfer."!".g:netrw_file_cmd." ".netrw#os#Escape(b:netrw_fname,1)." ".tmpfile)
   1823            let result           = s:NetrwGetFile(readcmd, tmpfile, b:netrw_method)
   1824            let b:netrw_lastfile = choice
   1825 
   1826            ".........................................
   1827        " NetRead: Complain {{{3
   1828        else
   1829            call netrw#msg#Notify('WARNING', printf('unable to comply with your request<%s>', choice))
   1830        endif
   1831    endwhile
   1832 
   1833    " NetRead: cleanup {{{3
   1834    if exists("b:netrw_method")
   1835        unlet b:netrw_method
   1836        unlet b:netrw_fname
   1837    endif
   1838    if s:FileReadable(tmpfile) && tmpfile !~ '.tar.bz2$' && tmpfile !~ '.tar.gz$' && tmpfile !~ '.zip' && tmpfile !~ '.tar' && readcmd != 't' && tmpfile !~ '.tar.xz$' && tmpfile !~ '.txz'
   1839        call netrw#fs#Remove(tmpfile)
   1840    endif
   1841    NetrwKeepj call s:NetrwOptionsRestore("w:")
   1842 
   1843 endfunction
   1844 
   1845 " netrw#NetWrite: responsible for writing a file over the net {{{2
   1846 function netrw#NetWrite(...) range
   1847 
   1848    " NetWrite: option handling {{{3
   1849    let mod= 0
   1850    call s:NetrwOptionsSave("w:")
   1851    call s:NetrwOptionsSafe(0)
   1852 
   1853    " NetWrite: Get Temporary Filename {{{3
   1854    let tmpfile= s:GetTempfile("")
   1855    if tmpfile == ""
   1856        return
   1857    endif
   1858 
   1859    if a:0 == 0
   1860        let ichoice = 0
   1861    else
   1862        let ichoice = 1
   1863    endif
   1864 
   1865    let curbufname= expand("%")
   1866    if &binary
   1867        " For binary writes, always write entire file.
   1868        " (line numbers don't really make sense for that).
   1869        " Also supports the writing of tar and zip files.
   1870        exe "sil NetrwKeepj w! ".fnameescape(v:cmdarg)." ".fnameescape(tmpfile)
   1871    elseif g:netrw_cygwin
   1872        " write (selected portion of) file to temporary
   1873        let cygtmpfile= substitute(tmpfile,g:netrw_cygdrive.'/\(.\)','\1:','')
   1874        exe "sil NetrwKeepj ".a:firstline."," . a:lastline . "w! ".fnameescape(v:cmdarg)." ".fnameescape(cygtmpfile)
   1875    else
   1876        " write (selected portion of) file to temporary
   1877        exe "sil NetrwKeepj ".a:firstline."," . a:lastline . "w! ".fnameescape(v:cmdarg)." ".fnameescape(tmpfile)
   1878    endif
   1879 
   1880    if curbufname == ""
   1881        " when the file is [No Name], and one attempts to Nwrite it, the buffer takes
   1882        " on the temporary file's name.  Deletion of the temporary file during
   1883        " cleanup then causes an error message.
   1884        0file!
   1885    endif
   1886 
   1887    " NetWrite: while choice loop: {{{3
   1888    while ichoice <= a:0
   1889 
   1890        " Process arguments: {{{4
   1891        " attempt to repeat with previous host-file-etc
   1892        if exists("b:netrw_lastfile") && a:0 == 0
   1893            let choice = b:netrw_lastfile
   1894            let ichoice= ichoice + 1
   1895        else
   1896            exe "let choice= a:" . ichoice
   1897 
   1898            " Reconstruct Choice when choice starts with '"'
   1899            if match(choice,"?") == 0
   1900                echomsg 'NetWrite Usage:"'
   1901                echomsg ':Nwrite machine:path                        uses rcp'
   1902                echomsg ':Nwrite "machine path"                      uses ftp with <.netrc>'
   1903                echomsg ':Nwrite "machine id password path"          uses ftp'
   1904                echomsg ':Nwrite dav://[user@]machine/path           uses cadaver'
   1905                echomsg ':Nwrite fetch://[user@]machine/path         uses fetch'
   1906                echomsg ':Nwrite ftp://machine[#port]/path           uses ftp  (autodetects <.netrc>)'
   1907                echomsg ':Nwrite rcp://machine/path                  uses rcp'
   1908                echomsg ':Nwrite rsync://[user@]machine/path         uses rsync'
   1909                echomsg ':Nwrite scp://[user@]machine[[:#]port]/path uses scp'
   1910                echomsg ':Nwrite sftp://[user@]machine/path          uses sftp'
   1911                sleep 4
   1912                break
   1913 
   1914            elseif match(choice,"^\"") != -1
   1915                if match(choice,"\"$") != -1
   1916                    " case "..."
   1917                    let choice=strpart(choice,1,strlen(choice)-2)
   1918                else
   1919                    "  case "... ... ..."
   1920                    let choice      = strpart(choice,1,strlen(choice)-1)
   1921                    let wholechoice = ""
   1922 
   1923                    while match(choice,"\"$") == -1
   1924                        let wholechoice= wholechoice . " " . choice
   1925                        let ichoice    = ichoice + 1
   1926                        if choice > a:0
   1927                            call netrw#msg#Notify('ERROR', printf('Unbalanced string in filename "%s"', wholechoice))
   1928                            return
   1929                        endif
   1930                        let choice= a:{ichoice}
   1931                    endwhile
   1932                    let choice= strpart(wholechoice,1,strlen(wholechoice)-1) . " " . strpart(choice,0,strlen(choice)-1)
   1933                endif
   1934            endif
   1935        endif
   1936        let ichoice= ichoice + 1
   1937 
   1938        " Determine method of write (ftp, rcp, etc) {{{4
   1939        NetrwKeepj call s:NetrwMethod(choice)
   1940        if !exists("b:netrw_method") || b:netrw_method < 0
   1941            return
   1942        endif
   1943        if !s:NetrwValidateHostname(g:netrw_machine)
   1944            call netrw#msg#Notify('ERROR', printf('Rejecting invalid hostname: <%s>', g:netrw_machine))
   1945            return
   1946        endif
   1947 
   1948        " =============
   1949        " NetWrite: Perform Protocol-Based Write {{{3
   1950        " ============================
   1951        if exists("g:netrw_silent") && g:netrw_silent == 0 && &ch >= 1
   1952            echo "(netrw) Processing your write request..."
   1953        endif
   1954 
   1955        ".........................................
   1956        " NetWrite: (rcp) NetWrite Method #1 {{{3
   1957        if  b:netrw_method == 1
   1958            if s:netrw_has_nt_rcp == 1
   1959                if exists("g:netrw_uid") &&  ( g:netrw_uid != "" )
   1960                    let uid_machine = g:netrw_machine .'.'. g:netrw_uid
   1961                else
   1962                    let uid_machine = g:netrw_machine .'.'. $USERNAME
   1963                endif
   1964            else
   1965                if exists("g:netrw_uid") &&  ( g:netrw_uid != "" )
   1966                    let uid_machine = g:netrw_uid .'@'. g:netrw_machine
   1967                else
   1968                    let uid_machine = g:netrw_machine
   1969                endif
   1970            endif
   1971            call netrw#os#Execute(s:netrw_silentxfer."!".g:netrw_rcp_cmd." ".s:netrw_rcpmode." ".netrw#os#Escape(tmpfile,1)." ".netrw#os#Escape(uid_machine.":".b:netrw_fname,1))
   1972            let b:netrw_lastfile = choice
   1973 
   1974            ".........................................
   1975        " NetWrite: (ftp + <.netrc>) NetWrite Method #2 {{{3
   1976        elseif b:netrw_method == 2
   1977            let netrw_fname = b:netrw_fname
   1978 
   1979            " formerly just a "new...bd!", that changed the window sizes when equalalways.  Using enew workaround instead
   1980            let bhkeep      = &l:bh
   1981            let curbuf      = bufnr("%")
   1982            setl bh=hide
   1983            keepj keepalt enew
   1984 
   1985            setl ff=unix
   1986            NetrwKeepj put =g:netrw_ftpmode
   1987            if exists("g:netrw_ftpextracmd")
   1988                NetrwKeepj put =g:netrw_ftpextracmd
   1989            endif
   1990            NetrwKeepj call setline(line("$")+1,'put "'.tmpfile.'" "'.netrw_fname.'"')
   1991            if exists("g:netrw_port") && g:netrw_port != ""
   1992                call netrw#os#Execute(s:netrw_silentxfer."%!".s:netrw_ftp_cmd." -i ".netrw#os#Escape(g:netrw_machine,1)." ".netrw#os#Escape(g:netrw_port,1))
   1993            else
   1994                call netrw#os#Execute(s:netrw_silentxfer."%!".s:netrw_ftp_cmd." -i ".netrw#os#Escape(g:netrw_machine,1))
   1995            endif
   1996            " If the result of the ftp operation isn't blank, show an error message (tnx to Doug Claar)
   1997            if getline(1) !~ "^$"
   1998                call netrw#msg#Notify('ERROR', getline(1))
   1999                let mod=1
   2000            endif
   2001 
   2002            " remove enew buffer (quietly)
   2003            let filtbuf= bufnr("%")
   2004            exe curbuf."b!"
   2005            let &l:bh            = bhkeep
   2006            exe filtbuf."bw!"
   2007 
   2008            let b:netrw_lastfile = choice
   2009 
   2010            ".........................................
   2011        " NetWrite: (ftp + machine, id, passwd, filename) NetWrite Method #3 {{{3
   2012        elseif b:netrw_method == 3
   2013            " Construct execution string (three or more lines) which will be passed through filter
   2014            let netrw_fname = b:netrw_fname
   2015            let bhkeep      = &l:bh
   2016 
   2017            " formerly just a "new...bd!", that changed the window sizes when equalalways.  Using enew workaround instead
   2018            let curbuf      = bufnr("%")
   2019            setl bh=hide
   2020            keepj keepalt enew
   2021            setl ff=unix
   2022 
   2023            if exists("g:netrw_port") && g:netrw_port != ""
   2024                NetrwKeepj put ='open '.g:netrw_machine.' '.g:netrw_port
   2025            else
   2026                NetrwKeepj put ='open '.g:netrw_machine
   2027            endif
   2028            if exists("g:netrw_uid") && g:netrw_uid != ""
   2029                if exists("g:netrw_ftp") && g:netrw_ftp == 1
   2030                    NetrwKeepj put =g:netrw_uid
   2031                    if exists("s:netrw_passwd") && s:netrw_passwd != ""
   2032                        NetrwKeepj put ='\"'.s:netrw_passwd.'\"'
   2033                    endif
   2034                elseif exists("s:netrw_passwd") && s:netrw_passwd != ""
   2035                    NetrwKeepj put ='user \"'.g:netrw_uid.'\" \"'.s:netrw_passwd.'\"'
   2036                endif
   2037            endif
   2038            NetrwKeepj put =g:netrw_ftpmode
   2039            if exists("g:netrw_ftpextracmd")
   2040                NetrwKeepj put =g:netrw_ftpextracmd
   2041            endif
   2042            NetrwKeepj put ='put \"'.tmpfile.'\" \"'.netrw_fname.'\"'
   2043            " save choice/id/password for future use
   2044            let b:netrw_lastfile = choice
   2045 
   2046            " perform ftp:
   2047            " -i       : turns off interactive prompting from ftp
   2048            " -n  unix : DON'T use <.netrc>, even though it exists
   2049            " -n  win32: quit being obnoxious about password
   2050            NetrwKeepj norm! 1G"_dd
   2051            call netrw#os#Execute(s:netrw_silentxfer."%!".s:netrw_ftp_cmd." ".g:netrw_ftp_options)
   2052            " If the result of the ftp operation isn't blank, show an error message (tnx to Doug Claar)
   2053            if getline(1) !~ "^$"
   2054                call netrw#msg#Notify('ERROR', getline(1))
   2055                let mod=1
   2056            endif
   2057 
   2058            " remove enew buffer (quietly)
   2059            let filtbuf= bufnr("%")
   2060            exe curbuf."b!"
   2061            let &l:bh= bhkeep
   2062            exe filtbuf."bw!"
   2063 
   2064            ".........................................
   2065        " NetWrite: (scp) NetWrite Method #4 {{{3
   2066        elseif     b:netrw_method == 4
   2067            if exists("g:netrw_port") && g:netrw_port != ""
   2068                let useport= " ".g:netrw_scpport." ".fnameescape(g:netrw_port)
   2069            else
   2070                let useport= ""
   2071            endif
   2072            call netrw#os#Execute(s:netrw_silentxfer."!".g:netrw_scp_cmd.useport." ".netrw#os#Escape(tmpfile,1)." ".netrw#os#Escape(g:netrw_machine.":".b:netrw_fname,1))
   2073            let b:netrw_lastfile = choice
   2074 
   2075            ".........................................
   2076        " NetWrite: (http) NetWrite Method #5 {{{3
   2077        elseif     b:netrw_method == 5
   2078            let curl= substitute(g:netrw_http_put_cmd,'\s\+.*$',"","")
   2079            if executable(curl)
   2080                let url= g:netrw_choice
   2081                call netrw#os#Execute(s:netrw_silentxfer."!".g:netrw_http_put_cmd." ".netrw#os#Escape(tmpfile,1)." ".netrw#os#Escape(url,1) )
   2082            else
   2083                call netrw#msg#Notify('ERROR', printf("can't write to http using <%s>", g:netrw_http_put_cmd))
   2084            endif
   2085 
   2086            ".........................................
   2087        " NetWrite: (dav) NetWrite Method #6 (cadaver) {{{3
   2088        elseif     b:netrw_method == 6
   2089 
   2090            " Construct execution string (four lines) which will be passed through filter
   2091            let netrw_fname = escape(b:netrw_fname,g:netrw_fname_escape)
   2092            let bhkeep      = &l:bh
   2093 
   2094            " formerly just a "new...bd!", that changed the window sizes when equalalways.  Using enew workaround instead
   2095            let curbuf      = bufnr("%")
   2096            setl bh=hide
   2097            keepj keepalt enew
   2098 
   2099            setl ff=unix
   2100            if exists("g:netrw_port") && g:netrw_port != ""
   2101                NetrwKeepj put ='open '.g:netrw_machine.' '.g:netrw_port
   2102            else
   2103                NetrwKeepj put ='open '.g:netrw_machine
   2104            endif
   2105            if exists("g:netrw_uid") && exists("s:netrw_passwd") && g:netrw_uid != ""
   2106                NetrwKeepj put ='user '.g:netrw_uid.' '.s:netrw_passwd
   2107            endif
   2108            NetrwKeepj put ='put '.tmpfile.' '.netrw_fname
   2109 
   2110            " perform cadaver operation:
   2111            NetrwKeepj norm! 1G"_dd
   2112            call netrw#os#Execute(s:netrw_silentxfer."%!".g:netrw_dav_cmd)
   2113 
   2114            " remove enew buffer (quietly)
   2115            let filtbuf= bufnr("%")
   2116            exe curbuf."b!"
   2117            let &l:bh            = bhkeep
   2118            exe filtbuf."bw!"
   2119 
   2120            let b:netrw_lastfile = choice
   2121 
   2122            ".........................................
   2123        " NetWrite: (rsync) NetWrite Method #7 {{{3
   2124        elseif     b:netrw_method == 7
   2125            call netrw#os#Execute(s:netrw_silentxfer."!".g:netrw_rsync_cmd." ".netrw#os#Escape(tmpfile,1)." ".netrw#os#Escape(g:netrw_machine.g:netrw_rsync_sep.b:netrw_fname,1))
   2126            let b:netrw_lastfile = choice
   2127 
   2128            ".........................................
   2129        " NetWrite: (sftp) NetWrite Method #9 {{{3
   2130        elseif     b:netrw_method == 9
   2131            let netrw_fname= escape(b:netrw_fname,g:netrw_fname_escape)
   2132            if exists("g:netrw_uid") &&  ( g:netrw_uid != "" )
   2133                let uid_machine = g:netrw_uid .'@'. g:netrw_machine
   2134            else
   2135                let uid_machine = g:netrw_machine
   2136            endif
   2137 
   2138            " formerly just a "new...bd!", that changed the window sizes when equalalways.  Using enew workaround instead
   2139            let bhkeep = &l:bh
   2140            let curbuf = bufnr("%")
   2141            setl bh=hide
   2142            keepj keepalt enew
   2143 
   2144            setl ff=unix
   2145            call setline(1,'put "'.escape(tmpfile,'\').'" '.netrw_fname)
   2146            let sftpcmd= substitute(g:netrw_sftp_cmd,"%TEMPFILE%",escape(tmpfile,'\'),"g")
   2147            call netrw#os#Execute(s:netrw_silentxfer."%!".sftpcmd.' '.netrw#os#Escape(uid_machine,1))
   2148            let filtbuf= bufnr("%")
   2149            exe curbuf."b!"
   2150            let &l:bh            = bhkeep
   2151            exe filtbuf."bw!"
   2152            let b:netrw_lastfile = choice
   2153 
   2154            ".........................................
   2155        " NetWrite: Complain {{{3
   2156        else
   2157            call netrw#msg#Notify('WARNING', printf('unable to comply with your request<%s>', choice))
   2158            let leavemod= 1
   2159        endif
   2160    endwhile
   2161 
   2162    " NetWrite: Cleanup: {{{3
   2163    if s:FileReadable(tmpfile)
   2164        call netrw#fs#Remove(tmpfile)
   2165    endif
   2166    call s:NetrwOptionsRestore("w:")
   2167 
   2168    if a:firstline == 1 && a:lastline == line("$")
   2169        " restore modifiability; usually equivalent to set nomod
   2170        let &l:mod= mod
   2171    elseif !exists("leavemod")
   2172        " indicate that the buffer has not been modified since last written
   2173        setl nomod
   2174    endif
   2175 
   2176 endfunction
   2177 
   2178 " netrw#NetSource: source a remotely hosted Vim script {{{2
   2179 " uses NetRead to get a copy of the file into a temporarily file,
   2180 "              then sources that file,
   2181 "              then removes that file.
   2182 function netrw#NetSource(...)
   2183    if a:0 > 0 && a:1 == '?'
   2184        " give help
   2185        echomsg 'NetSource Usage:'
   2186        echomsg ':Nsource dav://machine[:port]/path            uses cadaver'
   2187        echomsg ':Nsource fetch://machine/path                 uses fetch'
   2188        echomsg ':Nsource ftp://[user@]machine[:port]/path     uses ftp   autodetects <.netrc>'
   2189        echomsg ':Nsource http[s]://[user@]machine/path        uses http  wget'
   2190        echomsg ':Nsource rcp://[user@]machine/path            uses rcp'
   2191        echomsg ':Nsource rsync://machine[:port]/path          uses rsync'
   2192        echomsg ':Nsource scp://[user@]machine[[:#]port]/path  uses scp'
   2193        echomsg ':Nsource sftp://[user@]machine[[:#]port]/path uses sftp'
   2194        sleep 4
   2195    else
   2196        let i= 1
   2197        while i <= a:0
   2198            call netrw#NetRead(3,a:{i})
   2199            if s:FileReadable(s:netrw_tmpfile)
   2200                exe "so ".fnameescape(s:netrw_tmpfile)
   2201                if delete(s:netrw_tmpfile)
   2202                    call netrw#msg#Notify('ERROR', 'unable to delete directory <%s>', s:netrw_tmpfile)
   2203                endif
   2204                unlet s:netrw_tmpfile
   2205            else
   2206                call netrw#msg#Notify('ERROR', printf('unable to source <%s>!', a:{i}))
   2207            endif
   2208            let i= i + 1
   2209        endwhile
   2210    endif
   2211 endfunction
   2212 
   2213 " netrw#SetTreetop: resets the tree top to the current directory/specified directory {{{2
   2214 "                   (implements the :Ntree command)
   2215 function netrw#SetTreetop(iscmd,...)
   2216 
   2217    " iscmd==0: netrw#SetTreetop called using gn mapping
   2218    " iscmd==1: netrw#SetTreetop called using :Ntree from the command line
   2219    " clear out the current tree
   2220    if exists("w:netrw_treetop")
   2221        let inittreetop= w:netrw_treetop
   2222        unlet w:netrw_treetop
   2223    endif
   2224    if exists("w:netrw_treedict")
   2225        unlet w:netrw_treedict
   2226    endif
   2227 
   2228    if (a:iscmd == 0 || a:1 == "") && exists("inittreetop")
   2229        let treedir         = s:NetrwTreePath(inittreetop)
   2230    else
   2231        if isdirectory(s:NetrwFile(a:1))
   2232            let treedir         = a:1
   2233            let s:netrw_treetop = treedir
   2234        elseif exists("b:netrw_curdir") && (isdirectory(s:NetrwFile(b:netrw_curdir."/".a:1)) || a:1 =~ '^\a\{3,}://')
   2235            let treedir         = b:netrw_curdir."/".a:1
   2236            let s:netrw_treetop = treedir
   2237        else
   2238            " normally the cursor is left in the message window.
   2239            " However, here this results in the directory being listed in the message window, which is not wanted.
   2240            let netrwbuf= bufnr("%")
   2241            call netrw#msg#Notify('ERROR', printf("sorry, %s doesn't seem to be a directory!", a:1))
   2242            exe bufwinnr(netrwbuf)."wincmd w"
   2243            let treedir         = "."
   2244            let s:netrw_treetop = getcwd()
   2245        endif
   2246    endif
   2247 
   2248    " determine if treedir is remote or local
   2249    let islocal= expand("%") !~ '^\a\{3,}://'
   2250 
   2251    " browse the resulting directory
   2252    if islocal
   2253        call netrw#LocalBrowseCheck(s:NetrwBrowseChgDir(islocal,treedir,0))
   2254    else
   2255        call s:NetrwBrowse(islocal,s:NetrwBrowseChgDir(islocal,treedir,0))
   2256    endif
   2257 
   2258 endfunction
   2259 
   2260 " s:NetrwGetFile: Function to read temporary file "tfile" with command "readcmd". {{{2
   2261 "    readcmd == %r : replace buffer with newly read file
   2262 "            == 0r : read file at top of buffer
   2263 "            == r  : read file after current line
   2264 "            == t  : leave file in temporary form (ie. don't read into buffer)
   2265 function s:NetrwGetFile(readcmd, tfile, method)
   2266 
   2267    " readcmd=='t': simply do nothing
   2268    if a:readcmd == 't'
   2269        return
   2270    endif
   2271 
   2272    " get name of remote filename (ie. url and all)
   2273    let rfile= bufname("%")
   2274 
   2275    if exists("*NetReadFixup")
   2276        " for the use of NetReadFixup (not otherwise used internally)
   2277        let line2= line("$")
   2278    endif
   2279 
   2280    if a:readcmd[0] == '%'
   2281        " get file into buffer
   2282 
   2283        " rename the current buffer to the temp file (ie. tfile)
   2284        if g:netrw_cygwin
   2285            let tfile= substitute(a:tfile,g:netrw_cygdrive.'/\(.\)','\1:','')
   2286        else
   2287            let tfile= a:tfile
   2288        endif
   2289        call s:NetrwBufRename(tfile)
   2290 
   2291        " edit temporary file (ie. read the temporary file in)
   2292        if     rfile =~ '\.zip$'
   2293            call zip#Browse(tfile)
   2294        elseif rfile =~ '\.tar$'
   2295            call tar#Browse(tfile)
   2296        elseif rfile =~ '\.tar\.gz$'
   2297            call tar#Browse(tfile)
   2298        elseif rfile =~ '\.tar\.bz2$'
   2299            call tar#Browse(tfile)
   2300        elseif rfile =~ '\.tar\.xz$'
   2301            call tar#Browse(tfile)
   2302        elseif rfile =~ '\.txz$'
   2303            call tar#Browse(tfile)
   2304        else
   2305            NetrwKeepj e!
   2306        endif
   2307 
   2308        " rename buffer back to remote filename
   2309        call s:NetrwBufRename(rfile)
   2310 
   2311        " Jan 19, 2022: COMBAK -- bram problem with https://github.com/vim/vim/pull/9554.diff filetype
   2312        " Detect filetype of local version of remote file.
   2313        " Note that isk must not include a "/" for scripts.vim
   2314        " to process this detection correctly.
   2315        "   setl ft=
   2316        let iskkeep= &isk
   2317        setl isk-=/
   2318        filetype detect
   2319        let &l:isk= iskkeep
   2320        let line1 = 1
   2321        let line2 = line("$")
   2322 
   2323    elseif !&ma
   2324        " attempting to read a file after the current line in the file, but the buffer is not modifiable
   2325        call netrw#msg#Notify('WARNING', printf('attempt to read<%s> into a non-modifiable buffer!', a:tfile))
   2326        return
   2327 
   2328    elseif s:FileReadable(a:tfile)
   2329        " read file after current line
   2330        let curline = line(".")
   2331        let lastline= line("$")
   2332        exe "NetrwKeepj ".a:readcmd." ".fnameescape(v:cmdarg)." ".fnameescape(a:tfile)
   2333        let line1= curline + 1
   2334        let line2= line("$") - lastline + 1
   2335 
   2336    else
   2337        " not readable
   2338        call netrw#msg#Notify('WARNING', printf('file <%s> not readable', a:tfile))
   2339        return
   2340    endif
   2341 
   2342    " User-provided (ie. optional) fix-it-up command
   2343    if exists("*NetReadFixup")
   2344        NetrwKeepj call NetReadFixup(a:method, line1, line2)
   2345    endif
   2346 
   2347    if has("gui") && has("menu") && has("gui_running") && &go =~# 'm' && g:netrw_menu
   2348        " update the Buffers menu
   2349        NetrwKeepj call s:UpdateBuffersMenu()
   2350    endif
   2351 
   2352 
   2353    " make sure file is being displayed
   2354    "  redraw!
   2355 
   2356 endfunction
   2357 
   2358 " s:NetrwMethod:  determine method of transfer {{{2
   2359 " Input:
   2360 "   choice = url   [protocol:]//[userid@]hostname[:port]/[path-to-file]
   2361 " Output:
   2362 "  b:netrw_method= 1: rcp
   2363 "                  2: ftp + <.netrc>
   2364 "                  3: ftp + machine, id, password, and [path]filename
   2365 "                  4: scp
   2366 "                  5: http[s] (wget)
   2367 "                  6: dav
   2368 "                  7: rsync
   2369 "                  8: fetch
   2370 "                  9: sftp
   2371 "                 10: file
   2372 "  g:netrw_machine= hostname
   2373 "  b:netrw_fname  = filename
   2374 "  g:netrw_port   = optional port number (for ftp)
   2375 "  g:netrw_choice = copy of input url (choice)
   2376 function s:NetrwMethod(choice)
   2377 
   2378    " sanity check: choice should have at least three slashes in it
   2379    if strlen(substitute(a:choice,'[^/]','','g')) < 3
   2380        call netrw#msg#Notify('ERROR', 'not a netrw-style url; netrw uses protocol://[user@]hostname[:port]/[path])')
   2381        let b:netrw_method = -1
   2382        return
   2383    endif
   2384 
   2385    " record current g:netrw_machine, if any
   2386    " curmachine used if protocol == ftp and no .netrc
   2387    if exists("g:netrw_machine")
   2388        let curmachine= g:netrw_machine
   2389    else
   2390        let curmachine= "N O T A HOST"
   2391    endif
   2392    if exists("g:netrw_port")
   2393        let netrw_port= g:netrw_port
   2394    endif
   2395 
   2396    " insure that netrw_ftp_cmd starts off every method determination
   2397    " with the current g:netrw_ftp_cmd
   2398    let s:netrw_ftp_cmd= g:netrw_ftp_cmd
   2399 
   2400    " initialization
   2401    let b:netrw_method  = 0
   2402    let g:netrw_machine = ""
   2403    let b:netrw_fname   = ""
   2404    let g:netrw_port    = ""
   2405    let g:netrw_choice  = a:choice
   2406 
   2407    " Patterns:
   2408    " mipf     : a:machine a:id password filename      Use ftp
   2409    " mf      : a:machine filename                     Use ftp + <.netrc> or g:netrw_uid s:netrw_passwd
   2410    " ftpurm   : ftp://[user@]host[[#:]port]/filename  Use ftp + <.netrc> or g:netrw_uid s:netrw_passwd
   2411    " rcpurm   : rcp://[user@]host/filename            Use rcp
   2412    " rcphf    : [user@]host:filename                  Use rcp
   2413    " scpurm   : scp://[user@]host[[#:]port]/filename  Use scp
   2414    " httpurm  : http[s]://[user@]host/filename        Use wget
   2415    " davurm   : dav[s]://host[:port]/path             Use cadaver/curl
   2416    " rsyncurm : rsync://host[:port]/path              Use rsync
   2417    " fetchurm : fetch://[user@]host[:http]/filename   Use fetch (defaults to ftp, override for http)
   2418    " sftpurm  : sftp://[user@]host/filename  Use scp
   2419    " fileurm  : file://[user@]host/filename           Use elinks or links
   2420    let mipf     = '^\(\S\+\)\s\+\(\S\+\)\s\+\(\S\+\)\s\+\(\S\+\)$'
   2421    let mf       = '^\(\S\+\)\s\+\(\S\+\)$'
   2422    let ftpurm   = '^ftp://\(\([^/]*\)@\)\=\([^/#:]\{-}\)\([#:]\d\+\)\=/\(.*\)$'
   2423    let rcpurm   = '^rcp://\%(\([^/]*\)@\)\=\([^/]\{-}\)/\(.*\)$'
   2424    let rcphf    = '^\(\(\h\w*\)@\)\=\(\h\w*\):\([^@]\+\)$'
   2425    let scpurm   = '^scp://\([^/#:]\+\)\%([#:]\(\d\+\)\)\=/\(.*\)$'
   2426    let httpurm  = '^https\=://\([^/]\{-}\)\(/.*\)\=$'
   2427    let davurm   = '^davs\=://\([^/]\+\)/\(.*/\)\([-_.~[:alnum:]]\+\)$'
   2428    let rsyncurm = '^rsync://\([^/]\{-}\)/\(.*\)\=$'
   2429    let fetchurm = '^fetch://\(\([^/]*\)@\)\=\([^/#:]\{-}\)\(:http\)\=/\(.*\)$'
   2430    let sftpurm  = '^sftp://\([^/]\{-}\)/\(.*\)\=$'
   2431    let fileurm  = '^file\=://\(.*\)$'
   2432 
   2433    " Determine Method
   2434    " Method#1: rcp://user@hostname/...path-to-file {{{3
   2435    if match(a:choice,rcpurm) == 0
   2436        let b:netrw_method  = 1
   2437        let userid          = substitute(a:choice,rcpurm,'\1',"")
   2438        let g:netrw_machine = substitute(a:choice,rcpurm,'\2',"")
   2439        let b:netrw_fname   = substitute(a:choice,rcpurm,'\3',"")
   2440        if userid != ""
   2441            let g:netrw_uid= userid
   2442        endif
   2443 
   2444    " Method#4: scp://user@hostname/...path-to-file {{{3
   2445    elseif match(a:choice,scpurm) == 0
   2446        let b:netrw_method  = 4
   2447        let g:netrw_machine = substitute(a:choice,scpurm,'\1',"")
   2448        let g:netrw_port    = substitute(a:choice,scpurm,'\2',"")
   2449        let b:netrw_fname   = substitute(a:choice,scpurm,'\3',"")
   2450 
   2451    " Method#5: http[s]://user@hostname/...path-to-file {{{3
   2452    elseif match(a:choice,httpurm) == 0
   2453        let b:netrw_method = 5
   2454        let g:netrw_machine= substitute(a:choice,httpurm,'\1',"")
   2455        let b:netrw_fname  = substitute(a:choice,httpurm,'\2',"")
   2456        let b:netrw_http   = (a:choice =~ '^https:')? "https" : "http"
   2457 
   2458    " Method#6: dav://hostname[:port]/..path-to-file.. {{{3
   2459    elseif match(a:choice,davurm) == 0
   2460        let b:netrw_method= 6
   2461        if a:choice =~ 'davs:'
   2462            let g:netrw_machine= 'https://'.substitute(a:choice,davurm,'\1/\2',"")
   2463        else
   2464            let g:netrw_machine= 'http://'.substitute(a:choice,davurm,'\1/\2',"")
   2465        endif
   2466        let b:netrw_fname  = substitute(a:choice,davurm,'\3',"")
   2467 
   2468    " Method#7: rsync://user@hostname/...path-to-file {{{3
   2469    elseif match(a:choice,rsyncurm) == 0
   2470        let b:netrw_method = 7
   2471        let g:netrw_machine= substitute(a:choice,rsyncurm,'\1',"")
   2472        let b:netrw_fname  = substitute(a:choice,rsyncurm,'\2',"")
   2473 
   2474    " Methods 2,3: ftp://[user@]hostname[[:#]port]/...path-to-file {{{3
   2475    elseif match(a:choice,ftpurm) == 0
   2476        let userid         = substitute(a:choice,ftpurm,'\2',"")
   2477        let g:netrw_machine= substitute(a:choice,ftpurm,'\3',"")
   2478        let g:netrw_port   = substitute(a:choice,ftpurm,'\4',"")
   2479        let b:netrw_fname  = substitute(a:choice,ftpurm,'\5',"")
   2480        if userid != ""
   2481            let g:netrw_uid= userid
   2482        endif
   2483 
   2484        if curmachine != g:netrw_machine
   2485            if exists("s:netrw_hup[".g:netrw_machine."]")
   2486                call netrw#NetUserPass("ftp:".g:netrw_machine)
   2487            elseif exists("s:netrw_passwd")
   2488                " if there's a change in hostname, require password re-entry
   2489                unlet s:netrw_passwd
   2490            endif
   2491            if exists("netrw_port")
   2492                unlet netrw_port
   2493            endif
   2494        endif
   2495 
   2496        if exists("g:netrw_uid") && exists("s:netrw_passwd")
   2497            let b:netrw_method = 3
   2498        else
   2499            let host= substitute(g:netrw_machine,'\..*$','','')
   2500            if exists("s:netrw_hup[host]")
   2501                call netrw#NetUserPass("ftp:".host)
   2502 
   2503            elseif has("win32") && s:netrw_ftp_cmd =~# '-[sS]:'
   2504                if g:netrw_ftp_cmd =~# '-[sS]:\S*MACHINE\>'
   2505                    let s:netrw_ftp_cmd= substitute(g:netrw_ftp_cmd,'\<MACHINE\>',g:netrw_machine,'')
   2506                endif
   2507                let b:netrw_method= 2
   2508            elseif s:FileReadable(expand("$HOME/.netrc")) && !g:netrw_ignorenetrc
   2509                let b:netrw_method= 2
   2510            else
   2511                if !exists("g:netrw_uid") || g:netrw_uid == ""
   2512                    call netrw#NetUserPass()
   2513                elseif !exists("s:netrw_passwd") || s:netrw_passwd == ""
   2514                    call netrw#NetUserPass(g:netrw_uid)
   2515                    " else just use current g:netrw_uid and s:netrw_passwd
   2516                endif
   2517                let b:netrw_method= 3
   2518            endif
   2519        endif
   2520 
   2521    " Method#8: fetch {{{3
   2522    elseif match(a:choice,fetchurm) == 0
   2523        let b:netrw_method = 8
   2524        let g:netrw_userid = substitute(a:choice,fetchurm,'\2',"")
   2525        let g:netrw_machine= substitute(a:choice,fetchurm,'\3',"")
   2526        let b:netrw_option = substitute(a:choice,fetchurm,'\4',"")
   2527        let b:netrw_fname  = substitute(a:choice,fetchurm,'\5',"")
   2528 
   2529    " Method#3: Issue an ftp : "machine id password [path/]filename" {{{3
   2530    elseif match(a:choice,mipf) == 0
   2531        let b:netrw_method  = 3
   2532        let g:netrw_machine = substitute(a:choice,mipf,'\1',"")
   2533        let g:netrw_uid     = substitute(a:choice,mipf,'\2',"")
   2534        let s:netrw_passwd  = substitute(a:choice,mipf,'\3',"")
   2535        let b:netrw_fname   = substitute(a:choice,mipf,'\4',"")
   2536        call netrw#NetUserPass(g:netrw_machine,g:netrw_uid,s:netrw_passwd)
   2537 
   2538    " Method#3: Issue an ftp: "hostname [path/]filename" {{{3
   2539    elseif match(a:choice,mf) == 0
   2540        if exists("g:netrw_uid") && exists("s:netrw_passwd")
   2541            let b:netrw_method  = 3
   2542            let g:netrw_machine = substitute(a:choice,mf,'\1',"")
   2543            let b:netrw_fname   = substitute(a:choice,mf,'\2',"")
   2544 
   2545        elseif s:FileReadable(expand("$HOME/.netrc"))
   2546            let b:netrw_method  = 2
   2547            let g:netrw_machine = substitute(a:choice,mf,'\1',"")
   2548            let b:netrw_fname   = substitute(a:choice,mf,'\2',"")
   2549        endif
   2550 
   2551    " Method#9: sftp://user@hostname/...path-to-file {{{3
   2552    elseif match(a:choice,sftpurm) == 0
   2553        let b:netrw_method = 9
   2554        let g:netrw_machine= substitute(a:choice,sftpurm,'\1',"")
   2555        let b:netrw_fname  = substitute(a:choice,sftpurm,'\2',"")
   2556 
   2557    " Method#1: Issue an rcp: hostname:filename"  (this one should be last) {{{3
   2558    elseif match(a:choice,rcphf) == 0
   2559        let b:netrw_method  = 1
   2560        let userid          = substitute(a:choice,rcphf,'\2',"")
   2561        let g:netrw_machine = substitute(a:choice,rcphf,'\3',"")
   2562        let b:netrw_fname   = substitute(a:choice,rcphf,'\4',"")
   2563        if userid != ""
   2564            let g:netrw_uid= userid
   2565        endif
   2566 
   2567    " Method#10: file://user@hostname/...path-to-file {{{3
   2568    elseif match(a:choice,fileurm) == 0 && exists("g:netrw_file_cmd")
   2569        let b:netrw_method = 10
   2570        let b:netrw_fname  = substitute(a:choice,fileurm,'\1',"")
   2571 
   2572    " Cannot Determine Method {{{3
   2573    else
   2574        call netrw#msg#Notify('WARNING', 'cannot determine method (format: protocol://[user@]hostname[:port]/[path])')
   2575        let b:netrw_method  = -1
   2576    endif
   2577    "}}}3
   2578 
   2579    if g:netrw_port != ""
   2580        " remove any leading [:#] from port number
   2581        let g:netrw_port = substitute(g:netrw_port,'[#:]\+','','')
   2582    elseif exists("netrw_port")
   2583        " retain port number as implicit for subsequent ftp operations
   2584        let g:netrw_port= netrw_port
   2585    endif
   2586 
   2587 endfunction
   2588 
   2589 " s:NetrwValidateHostname:  Validate that the hostname is valid {{{2
   2590 " Input:
   2591 "   hostname
   2592 " Output:
   2593 "  true if g:netrw_machine is valid according to RFC1123 #Section 2
   2594 function s:NetrwValidateHostname(hostname)
   2595    " RFC1123#section-2 mandates, a valid hostname starts with letters or digits
   2596    " so reject everyhing else
   2597    return a:hostname =~? '^[a-z0-9]'
   2598 endfunction
   2599 
   2600 " NetUserPass: set username and password for subsequent ftp transfer {{{2
   2601 "   Usage:  :call netrw#NetUserPass()                        -- will prompt for userid and password
   2602 "           :call netrw#NetUserPass("uid")                   -- will prompt for password
   2603 "           :call netrw#NetUserPass("uid","password")        -- sets global userid and password
   2604 "           :call netrw#NetUserPass("ftp:host")              -- looks up userid and password using hup dictionary
   2605 "           :call netrw#NetUserPass("host","uid","password") -- sets hup dictionary with host, userid, password
   2606 function netrw#NetUserPass(...)
   2607 
   2608 
   2609    if !exists('s:netrw_hup')
   2610        let s:netrw_hup= {}
   2611    endif
   2612 
   2613    if a:0 == 0
   2614        " case: no input arguments
   2615 
   2616        " change host and username if not previously entered; get new password
   2617        if !exists("g:netrw_machine")
   2618            let g:netrw_machine= input('Enter hostname: ')
   2619        endif
   2620        if !exists("g:netrw_uid") || g:netrw_uid == ""
   2621            " get username (user-id) via prompt
   2622            let g:netrw_uid= input('Enter username: ')
   2623        endif
   2624        " get password via prompting
   2625        let s:netrw_passwd= inputsecret("Enter Password: ")
   2626 
   2627        " set up hup database
   2628        let host = substitute(g:netrw_machine,'\..*$','','')
   2629        if !exists('s:netrw_hup[host]')
   2630            let s:netrw_hup[host]= {}
   2631        endif
   2632        let s:netrw_hup[host].uid    = g:netrw_uid
   2633        let s:netrw_hup[host].passwd = s:netrw_passwd
   2634 
   2635    elseif a:0 == 1
   2636        " case: one input argument
   2637 
   2638        if a:1 =~ '^ftp:'
   2639            " get host from ftp:... url
   2640            " access userid and password from hup (host-user-passwd) dictionary
   2641            let host = substitute(a:1,'^ftp:','','')
   2642            let host = substitute(host,'\..*','','')
   2643            if exists("s:netrw_hup[host]")
   2644                let g:netrw_uid    = s:netrw_hup[host].uid
   2645                let s:netrw_passwd = s:netrw_hup[host].passwd
   2646            else
   2647                let g:netrw_uid    = input("Enter UserId: ")
   2648                let s:netrw_passwd = inputsecret("Enter Password: ")
   2649            endif
   2650 
   2651        else
   2652            " case: one input argument, not an url.  Using it as a new user-id.
   2653            if exists("g:netrw_machine")
   2654                if g:netrw_machine =~ '[0-9.]\+'
   2655                    let host= g:netrw_machine
   2656                else
   2657                    let host= substitute(g:netrw_machine,'\..*$','','')
   2658                endif
   2659            else
   2660                let g:netrw_machine= input('Enter hostname: ')
   2661            endif
   2662            let g:netrw_uid = a:1
   2663            if exists("g:netrw_passwd")
   2664                " ask for password if one not previously entered
   2665                let s:netrw_passwd= g:netrw_passwd
   2666            else
   2667                let s:netrw_passwd = inputsecret("Enter Password: ")
   2668            endif
   2669        endif
   2670 
   2671        if exists("host")
   2672            if !exists('s:netrw_hup[host]')
   2673                let s:netrw_hup[host]= {}
   2674            endif
   2675            let s:netrw_hup[host].uid    = g:netrw_uid
   2676            let s:netrw_hup[host].passwd = s:netrw_passwd
   2677        endif
   2678 
   2679    elseif a:0 == 2
   2680        let g:netrw_uid    = a:1
   2681        let s:netrw_passwd = a:2
   2682 
   2683    elseif a:0 == 3
   2684        " enter hostname, user-id, and password into the hup dictionary
   2685        let host = substitute(a:1,'^\a\+:','','')
   2686        let host = substitute(host,'\..*$','','')
   2687        if !exists('s:netrw_hup[host]')
   2688            let s:netrw_hup[host]= {}
   2689        endif
   2690        let s:netrw_hup[host].uid    = a:2
   2691        let s:netrw_hup[host].passwd = a:3
   2692        let g:netrw_uid              = s:netrw_hup[host].uid
   2693        let s:netrw_passwd           = s:netrw_hup[host].passwd
   2694    endif
   2695 
   2696 endfunction
   2697 
   2698 "  Shared Browsing Support:    {{{1
   2699 
   2700 " s:ExplorePatHls: converts an Explore pattern into a regular expression search pattern {{{2
   2701 function s:ExplorePatHls(pattern)
   2702    let repat= substitute(a:pattern,'^**/\{1,2}','','')
   2703    let repat= escape(repat,'][.\')
   2704    let repat= '\<'.substitute(repat,'\*','\\(\\S\\+ \\)*\\S\\+','g').'\>'
   2705    return repat
   2706 endfunction
   2707 
   2708 "  s:NetrwBookHistHandler: {{{2
   2709 "    0: (user: <mb>)   bookmark current directory
   2710 "    1: (user: <gb>)   change to the bookmarked directory
   2711 "    2: (user: <qb>)   list bookmarks
   2712 "    3: (browsing)     records current directory history
   2713 "    4: (user: <u>)    go up   (previous) directory, using history
   2714 "    5: (user: <U>)    go down (next)     directory, using history
   2715 "    6: (user: <mB>)   delete bookmark
   2716 function s:NetrwBookHistHandler(chg,curdir)
   2717    if !exists("g:netrw_dirhistmax") || g:netrw_dirhistmax <= 0
   2718        return
   2719    endif
   2720 
   2721    let ykeep    = @@
   2722    let curbufnr = bufnr("%")
   2723 
   2724    if a:chg == 0
   2725        " bookmark the current directory
   2726        if exists("s:netrwmarkfilelist_{curbufnr}")
   2727            call s:NetrwBookmark(0)
   2728            echo "bookmarked marked files"
   2729        else
   2730            call s:MakeBookmark(a:curdir)
   2731            echo "bookmarked the current directory"
   2732        endif
   2733 
   2734        try
   2735            call s:NetrwBookHistSave()
   2736        catch
   2737        endtry
   2738 
   2739    elseif a:chg == 1
   2740        " change to the bookmarked directory
   2741        if exists("g:netrw_bookmarklist[v:count-1]")
   2742            exe "NetrwKeepj e ".fnameescape(g:netrw_bookmarklist[v:count-1])
   2743        else
   2744            echomsg "Sorry, bookmark#".v:count." doesn't exist!"
   2745        endif
   2746 
   2747    elseif a:chg == 2
   2748        "   redraw!
   2749        let didwork= 0
   2750        " list user's bookmarks
   2751        if exists("g:netrw_bookmarklist")
   2752            let cnt= 1
   2753            for bmd in g:netrw_bookmarklist
   2754                echo printf("Netrw Bookmark#%-2d: %s",cnt,g:netrw_bookmarklist[cnt-1])
   2755                let didwork = 1
   2756                let cnt     = cnt + 1
   2757            endfor
   2758        endif
   2759 
   2760        " list directory history
   2761        " Note: history is saved only when PerformListing is done;
   2762        "       ie. when netrw can re-use a netrw buffer, the current directory is not saved in the history.
   2763        let cnt     = g:netrw_dirhistcnt
   2764        let first   = 1
   2765        let histcnt = 0
   2766        if g:netrw_dirhistmax > 0
   2767            while ( first || cnt != g:netrw_dirhistcnt )
   2768                if exists("g:netrw_dirhist_{cnt}")
   2769                    echo printf("Netrw  History#%-2d: %s",histcnt,g:netrw_dirhist_{cnt})
   2770                    let didwork= 1
   2771                endif
   2772                let histcnt = histcnt + 1
   2773                let first   = 0
   2774                let cnt     = ( cnt - 1 ) % g:netrw_dirhistmax
   2775                if cnt < 0
   2776                    let cnt= cnt + g:netrw_dirhistmax
   2777                endif
   2778            endwhile
   2779        else
   2780            let g:netrw_dirhistcnt= 0
   2781        endif
   2782        if didwork
   2783            call inputsave()|call input("Press <cr> to continue")|call inputrestore()
   2784        endif
   2785 
   2786    elseif a:chg == 3
   2787        " saves most recently visited directories (when they differ)
   2788        if !exists("g:netrw_dirhistcnt") || !exists("g:netrw_dirhist_{g:netrw_dirhistcnt}") || g:netrw_dirhist_{g:netrw_dirhistcnt} != a:curdir
   2789            if g:netrw_dirhistmax > 0
   2790                let g:netrw_dirhistcnt                   = ( g:netrw_dirhistcnt + 1 ) % g:netrw_dirhistmax
   2791                let g:netrw_dirhist_{g:netrw_dirhistcnt} = a:curdir
   2792            endif
   2793        endif
   2794 
   2795    elseif a:chg == 4
   2796        " u: change to the previous directory stored on the history list
   2797        if g:netrw_dirhistmax > 0
   2798            let g:netrw_dirhistcnt= ( g:netrw_dirhistcnt - v:count1 ) % g:netrw_dirhistmax
   2799            if g:netrw_dirhistcnt < 0
   2800                let g:netrw_dirhistcnt= g:netrw_dirhistcnt + g:netrw_dirhistmax
   2801            endif
   2802        else
   2803            let g:netrw_dirhistcnt= 0
   2804        endif
   2805        if exists("g:netrw_dirhist_{g:netrw_dirhistcnt}")
   2806            if exists("w:netrw_liststyle") && w:netrw_liststyle == s:TREELIST && exists("b:netrw_curdir")
   2807                setl ma noro
   2808                sil! NetrwKeepj %d _
   2809                setl nomod
   2810            endif
   2811            exe "NetrwKeepj e! ".fnameescape(g:netrw_dirhist_{g:netrw_dirhistcnt})
   2812        else
   2813            if g:netrw_dirhistmax > 0
   2814                let g:netrw_dirhistcnt= ( g:netrw_dirhistcnt + v:count1 ) % g:netrw_dirhistmax
   2815            else
   2816                let g:netrw_dirhistcnt= 0
   2817            endif
   2818            echo "Sorry, no predecessor directory exists yet"
   2819        endif
   2820 
   2821    elseif a:chg == 5
   2822        " U: change to the subsequent directory stored on the history list
   2823        if g:netrw_dirhistmax > 0
   2824            let g:netrw_dirhistcnt= ( g:netrw_dirhistcnt + 1 ) % g:netrw_dirhistmax
   2825            if exists("g:netrw_dirhist_{g:netrw_dirhistcnt}")
   2826                if exists("w:netrw_liststyle") && w:netrw_liststyle == s:TREELIST && exists("b:netrw_curdir")
   2827                    setl ma noro
   2828                    sil! NetrwKeepj %d _
   2829                    setl nomod
   2830                endif
   2831                exe "NetrwKeepj e! ".fnameescape(g:netrw_dirhist_{g:netrw_dirhistcnt})
   2832            else
   2833                let g:netrw_dirhistcnt= ( g:netrw_dirhistcnt - 1 ) % g:netrw_dirhistmax
   2834                if g:netrw_dirhistcnt < 0
   2835                    let g:netrw_dirhistcnt= g:netrw_dirhistcnt + g:netrw_dirhistmax
   2836                endif
   2837                echo "Sorry, no successor directory exists yet"
   2838            endif
   2839        else
   2840            let g:netrw_dirhistcnt= 0
   2841            echo "Sorry, no successor directory exists yet (g:netrw_dirhistmax is ".g:netrw_dirhistmax.")"
   2842        endif
   2843 
   2844    elseif a:chg == 6
   2845        if exists("s:netrwmarkfilelist_{curbufnr}")
   2846            call s:NetrwBookmark(1)
   2847            echo "removed marked files from bookmarks"
   2848        else
   2849            " delete the v:count'th bookmark
   2850            let iremove = v:count
   2851            let dremove = g:netrw_bookmarklist[iremove - 1]
   2852            call s:MergeBookmarks()
   2853            NetrwKeepj call remove(g:netrw_bookmarklist,iremove-1)
   2854            echo "removed ".dremove." from g:netrw_bookmarklist"
   2855        endif
   2856 
   2857        try
   2858            call s:NetrwBookHistSave()
   2859        catch
   2860        endtry
   2861    endif
   2862    call s:NetrwBookmarkMenu()
   2863    call s:NetrwTgtMenu()
   2864    let @@= ykeep
   2865 endfunction
   2866 
   2867 " s:NetrwBookHistRead: this function reads bookmarks and history {{{2
   2868 "  Will source the history file (.netrwhist) only if the g:netrw_disthistmax is > 0.
   2869 "                      Sister function: s:NetrwBookHistSave()
   2870 function s:NetrwBookHistRead()
   2871    if !exists("g:netrw_dirhistmax") || g:netrw_dirhistmax <= 0
   2872        return
   2873    endif
   2874    let ykeep= @@
   2875 
   2876    " read bookmarks
   2877    if !exists("s:netrw_initbookhist")
   2878        let home    = s:NetrwHome()
   2879        let savefile= home."/.netrwbook"
   2880        if filereadable(s:NetrwFile(savefile))
   2881            exe "keepalt NetrwKeepj so ".savefile
   2882        endif
   2883 
   2884        " read history
   2885        if g:netrw_dirhistmax > 0
   2886            let savefile= home."/.netrwhist"
   2887            if filereadable(s:NetrwFile(savefile))
   2888                exe "keepalt NetrwKeepj so ".savefile
   2889            endif
   2890            let s:netrw_initbookhist= 1
   2891            au VimLeave * call s:NetrwBookHistSave()
   2892        endif
   2893    endif
   2894 
   2895    let @@= ykeep
   2896 endfunction
   2897 
   2898 " s:NetrwBookHistSave: this function saves bookmarks and history to files {{{2
   2899 "                      Sister function: s:NetrwBookHistRead()
   2900 "                      I used to do this via viminfo but that appears to
   2901 "                      be unreliable for long-term storage
   2902 "                      If g:netrw_dirhistmax is <= 0, no history or bookmarks
   2903 "                      will be saved.
   2904 "                      (s:NetrwBookHistHandler(3,...) used to record history)
   2905 function s:NetrwBookHistSave()
   2906    if !exists("g:netrw_dirhistmax") || g:netrw_dirhistmax <= 0
   2907        return
   2908    endif
   2909 
   2910    let savefile= s:NetrwHome()."/.netrwhist"
   2911    1split
   2912 
   2913    " setting up a new buffer which will become .netrwhist
   2914    call s:NetrwEnew()
   2915    if g:netrw_use_noswf
   2916        setl cino= com= cpo-=a cpo-=A fo=nroql2 tw=0 report=10000 noswf
   2917    else
   2918        setl cino= com= cpo-=a cpo-=A fo=nroql2 tw=0 report=10000
   2919    endif
   2920    setl nocin noai noci magic nospell nohid wig= noaw
   2921    setl ma noro write
   2922    if exists("+acd") | setl noacd | endif
   2923    sil! NetrwKeepj keepalt %d _
   2924 
   2925    " rename enew'd file: .netrwhist -- no attempt to merge
   2926    " record dirhistmax and current dirhistcnt
   2927    " save history
   2928    sil! keepalt file .netrwhist
   2929    call setline(1,"let g:netrw_dirhistmax  =".g:netrw_dirhistmax)
   2930    call setline(2,"let g:netrw_dirhistcnt =".g:netrw_dirhistcnt)
   2931    if g:netrw_dirhistmax > 0
   2932        let lastline = line("$")
   2933        let cnt      = g:netrw_dirhistcnt
   2934        let first    = 1
   2935        while ( first || cnt != g:netrw_dirhistcnt )
   2936            let lastline= lastline + 1
   2937            if exists("g:netrw_dirhist_{cnt}")
   2938                call setline(lastline,'let g:netrw_dirhist_'.cnt."='".g:netrw_dirhist_{cnt}."'")
   2939            endif
   2940            let first   = 0
   2941            let cnt     = ( cnt - 1 ) % g:netrw_dirhistmax
   2942            if cnt < 0
   2943                let cnt= cnt + g:netrw_dirhistmax
   2944            endif
   2945        endwhile
   2946        exe "sil! w! ".savefile
   2947    endif
   2948 
   2949    " save bookmarks
   2950    sil NetrwKeepj %d _
   2951    if exists("g:netrw_bookmarklist") && g:netrw_bookmarklist != []
   2952        " merge and write .netrwbook
   2953        let savefile= s:NetrwHome()."/.netrwbook"
   2954 
   2955        if filereadable(s:NetrwFile(savefile))
   2956            let booklist= deepcopy(g:netrw_bookmarklist)
   2957            exe "sil NetrwKeepj keepalt so ".savefile
   2958            for bdm in booklist
   2959                if index(g:netrw_bookmarklist,bdm) == -1
   2960                    call add(g:netrw_bookmarklist,bdm)
   2961                endif
   2962            endfor
   2963            call sort(g:netrw_bookmarklist)
   2964        endif
   2965 
   2966        " construct and save .netrwbook
   2967        call setline(1,"let g:netrw_bookmarklist= ".string(g:netrw_bookmarklist))
   2968        exe "sil! w! ".savefile
   2969    endif
   2970 
   2971    " cleanup -- remove buffer used to construct history
   2972    let bgone= bufnr("%")
   2973    q!
   2974    exe "keepalt ".bgone."bwipe!"
   2975 
   2976 endfunction
   2977 
   2978 " s:NetrwBrowse: This function uses the command in g:netrw_list_cmd to provide a {{{2
   2979 "  list of the contents of a local or remote directory.  It is assumed that the
   2980 "  g:netrw_list_cmd has a string, USEPORT HOSTNAME, that needs to be substituted
   2981 "  with the requested remote hostname first.
   2982 "    Often called via:  Explore/e dirname/etc -> netrw#LocalBrowseCheck() -> s:NetrwBrowse()
   2983 function s:NetrwBrowse(islocal,dirname)
   2984    if !exists("w:netrw_liststyle")|let w:netrw_liststyle= g:netrw_liststyle|endif
   2985 
   2986    " save alternate-file's filename if w:netrw_rexlocal doesn't exist
   2987    " This is useful when one edits a local file, then :e ., then :Rex
   2988    if a:islocal && !exists("w:netrw_rexfile") && bufname("#") != ""
   2989        let w:netrw_rexfile= bufname("#")
   2990    endif
   2991 
   2992    " s:NetrwBrowse : initialize history {{{3
   2993    if !exists("s:netrw_initbookhist")
   2994        NetrwKeepj call s:NetrwBookHistRead()
   2995    endif
   2996 
   2997    " s:NetrwBrowse : simplify the dirname (especially for ".."s in dirnames) {{{3
   2998    if a:dirname !~ '^\a\{3,}://'
   2999        let dirname= simplify(a:dirname)
   3000    else
   3001        let dirname= a:dirname
   3002    endif
   3003 
   3004    " repoint t:netrw_lexbufnr if appropriate
   3005    if exists("t:netrw_lexbufnr") && bufnr("%") == t:netrw_lexbufnr
   3006        let repointlexbufnr= 1
   3007    endif
   3008 
   3009    " s:NetrwBrowse : sanity checks: {{{3
   3010    if exists("s:netrw_skipbrowse")
   3011        unlet s:netrw_skipbrowse
   3012        return
   3013    endif
   3014    if !exists("*shellescape")
   3015        call netrw#msg#Notify('ERROR', "netrw can't run -- your vim is missing shellescape()")
   3016        return
   3017    endif
   3018    if !exists("*fnameescape")
   3019        call netrw#msg#Notify('ERROR', "netrw can't run -- your vim is missing fnameescape()")
   3020        return
   3021    endif
   3022 
   3023    " s:NetrwBrowse : save options: {{{3
   3024    call s:NetrwOptionsSave("w:")
   3025 
   3026    " s:NetrwBrowse : re-instate any marked files {{{3
   3027    if has("syntax") && exists("g:syntax_on") && g:syntax_on
   3028        if exists("s:netrwmarkfilelist_{bufnr('%')}")
   3029            exe "2match netrwMarkFile /".s:netrwmarkfilemtch_{bufnr("%")}."/"
   3030        endif
   3031    endif
   3032 
   3033    if a:islocal && exists("w:netrw_acdkeep") && w:netrw_acdkeep
   3034        " s:NetrwBrowse : set up "safe" options for local directory/file {{{3
   3035        if s:NetrwLcd(dirname)
   3036            return
   3037        endif
   3038 
   3039    elseif !a:islocal && dirname !~ '[\/]$' && dirname !~ '^"'
   3040        " s:NetrwBrowse :  remote regular file handler {{{3
   3041        if bufname(dirname) != ""
   3042            exe "NetrwKeepj b ".bufname(dirname)
   3043        else
   3044            " attempt transfer of remote regular file
   3045 
   3046            " remove any filetype indicator from end of dirname, except for the
   3047            " "this is a directory" indicator (/).
   3048            " There shouldn't be one of those here, anyway.
   3049            let path= substitute(dirname,'[*=@|]\r\=$','','e')
   3050            call s:RemotePathAnalysis(dirname)
   3051 
   3052            " s:NetrwBrowse : remote-read the requested file into current buffer {{{3
   3053            call s:NetrwEnew(dirname)
   3054            call s:NetrwOptionsSafe(a:islocal)
   3055            setl ma noro
   3056            let b:netrw_curdir = dirname
   3057            let url            = s:method."://".((s:user == "")? "" : s:user."@").s:machine.(s:port ? ":".s:port : "")."/".s:path
   3058            call s:NetrwBufRename(url)
   3059            exe "sil! NetrwKeepj keepalt doau BufReadPre ".fnameescape(s:fname)
   3060            sil call netrw#NetRead(2,url)
   3061            " netrw.vim and tar.vim have already handled decompression of the tarball; avoiding gzip.vim error
   3062            if s:path =~ '\.bz2$'
   3063                exe "sil NetrwKeepj keepalt doau BufReadPost ".fnameescape(substitute(s:fname,'\.bz2$','',''))
   3064            elseif s:path =~ '\.gz$'
   3065                exe "sil NetrwKeepj keepalt doau BufReadPost ".fnameescape(substitute(s:fname,'\.gz$','',''))
   3066            elseif s:path =~ '\.xz$'
   3067                exe "sil NetrwKeepj keepalt doau BufReadPost ".fnameescape(substitute(s:fname,'\.xz$','',''))
   3068            else
   3069                exe "sil NetrwKeepj keepalt doau BufReadPost ".fnameescape(s:fname)
   3070            endif
   3071        endif
   3072 
   3073        " s:NetrwBrowse : save certain window-oriented variables into buffer-oriented variables {{{3
   3074        call s:SetBufWinVars()
   3075        call s:NetrwOptionsRestore("w:")
   3076        setl ma nomod noro
   3077        return
   3078    endif
   3079 
   3080    " use buffer-oriented WinVars if buffer variables exist but associated window variables don't {{{3
   3081    call s:UseBufWinVars()
   3082 
   3083    " set up some variables {{{3
   3084    let b:netrw_browser_active = 1
   3085    let dirname                = dirname
   3086    let s:last_sort_by         = g:netrw_sort_by
   3087 
   3088    " set up menu {{{3
   3089    NetrwKeepj call s:NetrwMenu(1)
   3090 
   3091    " get/set-up buffer {{{3
   3092    let svpos  = winsaveview()
   3093 
   3094    " NetrwGetBuffer might change buffers but s:rexposn_X was set for the
   3095    " previous buffer
   3096    let prevbufnr = bufnr('%')
   3097    let reusing= s:NetrwGetBuffer(a:islocal,dirname)
   3098    if exists("s:rexposn_".prevbufnr) && exists("w:netrw_liststyle") && w:netrw_liststyle == s:TREELIST
   3099        let s:rexposn_{bufnr('%')} = s:rexposn_{prevbufnr}
   3100    endif
   3101 
   3102    " maintain markfile highlighting
   3103    if has("syntax") && exists("g:syntax_on") && g:syntax_on
   3104        if exists("s:netrwmarkfilemtch_{bufnr('%')}") && s:netrwmarkfilemtch_{bufnr("%")} != ""
   3105            exe "2match netrwMarkFile /".s:netrwmarkfilemtch_{bufnr("%")}."/"
   3106        else
   3107            2match none
   3108        endif
   3109    endif
   3110    if reusing && line("$") > 1
   3111        call s:NetrwOptionsRestore("w:")
   3112        setl noma nomod nowrap
   3113        return
   3114    endif
   3115 
   3116    " set b:netrw_curdir to the new directory name {{{3
   3117    let b:netrw_curdir= dirname
   3118    if b:netrw_curdir =~ '[/\\]$'
   3119        let b:netrw_curdir= substitute(b:netrw_curdir,'[/\\]$','','e')
   3120    endif
   3121    if b:netrw_curdir =~ '\a:$' && has("win32")
   3122        let b:netrw_curdir= b:netrw_curdir."/"
   3123    endif
   3124    if b:netrw_curdir == ''
   3125        if has("amiga")
   3126            " On the Amiga, the empty string connotes the current directory
   3127            let b:netrw_curdir= getcwd()
   3128        else
   3129            " under unix, when the root directory is encountered, the result
   3130            " from the preceding substitute is an empty string.
   3131            let b:netrw_curdir= '/'
   3132        endif
   3133    endif
   3134    if !a:islocal && b:netrw_curdir !~ '/$'
   3135        let b:netrw_curdir= b:netrw_curdir.'/'
   3136    endif
   3137 
   3138    " ------------
   3139    " (local only) {{{3
   3140    " ------------
   3141    if a:islocal
   3142        " Set up ShellCmdPost handling.  Append current buffer to browselist
   3143        call s:LocalFastBrowser()
   3144 
   3145        " handle g:netrw_keepdir: set vim's current directory to netrw's notion of the current directory {{{3
   3146        if !g:netrw_keepdir
   3147            if !exists("&l:acd") || !&l:acd
   3148                if s:NetrwLcd(b:netrw_curdir)
   3149                    return
   3150                endif
   3151            endif
   3152        endif
   3153 
   3154    " --------------------------------
   3155    " remote handling: {{{3
   3156    " --------------------------------
   3157    else
   3158 
   3159        " analyze dirname and g:netrw_list_cmd {{{3
   3160        if dirname =~# "^NetrwTreeListing\>"
   3161            let dirname= b:netrw_curdir
   3162        elseif exists("w:netrw_liststyle") && w:netrw_liststyle == s:TREELIST && exists("b:netrw_curdir")
   3163            let dirname= substitute(b:netrw_curdir,'\\','/','g')
   3164            if dirname !~ '/$'
   3165                let dirname= dirname.'/'
   3166            endif
   3167            let b:netrw_curdir = dirname
   3168        else
   3169            let dirname = substitute(dirname,'\\','/','g')
   3170        endif
   3171 
   3172        let dirpat  = '^\(\w\{-}\)://\(\w\+@\)\=\([^/]\+\)/\(.*\)$'
   3173        if dirname !~ dirpat
   3174            call netrw#msg#Notify('ERROR', printf("netrw doesn't understand your dirname<%s>", dirname))
   3175            NetrwKeepj call s:NetrwOptionsRestore("w:")
   3176            setl noma nomod nowrap
   3177            return
   3178        endif
   3179        let b:netrw_curdir= dirname
   3180    endif  " (additional remote handling)
   3181 
   3182    " -------------------------------
   3183    " Perform Directory Listing: {{{3
   3184    " -------------------------------
   3185    NetrwKeepj call s:NetrwMaps(a:islocal)
   3186    NetrwKeepj call s:NetrwCommands(a:islocal)
   3187    NetrwKeepj call s:PerformListing(a:islocal)
   3188 
   3189    " restore option(s)
   3190    call s:NetrwOptionsRestore("w:")
   3191 
   3192    " If there is a rexposn: restore position with rexposn
   3193    " Otherwise            : set rexposn
   3194    if exists("s:rexposn_".bufnr("%"))
   3195        NetrwKeepj call winrestview(s:rexposn_{bufnr('%')})
   3196        if exists("w:netrw_bannercnt") && line(".") < w:netrw_bannercnt
   3197            NetrwKeepj exe w:netrw_bannercnt
   3198        endif
   3199    else
   3200        NetrwKeepj call s:SetRexDir(a:islocal,b:netrw_curdir)
   3201    endif
   3202 
   3203    " repoint t:netrw_lexbufnr if appropriate
   3204    if exists("repointlexbufnr")
   3205        let t:netrw_lexbufnr= bufnr("%")
   3206    endif
   3207 
   3208    " restore position
   3209    if reusing
   3210        call winrestview(svpos)
   3211    endif
   3212 
   3213    " The s:LocalBrowseRefresh() function is called by an autocmd
   3214    " installed by s:LocalFastBrowser() when g:netrw_fastbrowse <= 1 (ie. slow or medium speed).
   3215    " However, s:NetrwBrowse() causes the FocusGained event to fire the first time.
   3216    return
   3217 endfunction
   3218 
   3219 " s:NetrwFile: because of g:netrw_keepdir, isdirectory(), type(), etc may or {{{2
   3220 " may not apply correctly; ie. netrw's idea of the current directory may
   3221 " differ from vim's.  This function insures that netrw's idea of the current
   3222 " directory is used.
   3223 " Returns a path to the file specified by a:fname
   3224 function s:NetrwFile(fname)
   3225 
   3226    " clean up any leading treedepthstring
   3227    if exists("w:netrw_liststyle") && w:netrw_liststyle == s:TREELIST
   3228        let fname= substitute(a:fname,'^'.s:treedepthstring.'\+','','')
   3229    else
   3230        let fname= a:fname
   3231    endif
   3232 
   3233    if g:netrw_keepdir
   3234        " vim's idea of the current directory possibly may differ from netrw's
   3235        if !exists("b:netrw_curdir")
   3236            let b:netrw_curdir= getcwd()
   3237        endif
   3238 
   3239        if !g:netrw_cygwin && has("win32")
   3240            if fname =~ '^\' || fname =~ '^\a:\'
   3241                " windows, but full path given
   3242                let ret= fname
   3243            else
   3244                " windows, relative path given
   3245                let ret= netrw#fs#ComposePath(b:netrw_curdir,fname)
   3246            endif
   3247 
   3248        elseif fname =~ '^/'
   3249            " not windows, full path given
   3250            let ret= fname
   3251        else
   3252            " not windows, relative path given
   3253            let ret= netrw#fs#ComposePath(b:netrw_curdir,fname)
   3254        endif
   3255    else
   3256        " vim and netrw agree on the current directory
   3257        let ret= fname
   3258    endif
   3259 
   3260    return ret
   3261 endfunction
   3262 
   3263 " s:NetrwFileInfo: supports qf (query for file information) {{{2
   3264 function s:NetrwFileInfo(islocal,fname)
   3265    let ykeep= @@
   3266    if a:islocal
   3267        let lsopt= "-lsad"
   3268        if g:netrw_sizestyle =~# 'H'
   3269            let lsopt= "-lsadh"
   3270        elseif g:netrw_sizestyle =~# 'h'
   3271            let lsopt= "-lsadh --si"
   3272        endif
   3273        if (has("unix") || has("macunix")) && executable("/bin/ls")
   3274 
   3275            if getline(".") == "../"
   3276                echo system("/bin/ls ".lsopt." ".netrw#os#Escape(".."))
   3277 
   3278            elseif w:netrw_liststyle == s:TREELIST && getline(".") !~ '^'.s:treedepthstring
   3279                echo system("/bin/ls ".lsopt." ".netrw#os#Escape(b:netrw_curdir))
   3280 
   3281            elseif exists("b:netrw_curdir")
   3282                echo system("/bin/ls ".lsopt." ".netrw#os#Escape(netrw#fs#ComposePath(b:netrw_curdir,a:fname)))
   3283 
   3284            else
   3285                echo system("/bin/ls ".lsopt." ".netrw#os#Escape(s:NetrwFile(a:fname)))
   3286            endif
   3287        else
   3288            " use vim functions to return information about file below cursor
   3289            if !isdirectory(s:NetrwFile(a:fname)) && !filereadable(s:NetrwFile(a:fname)) && a:fname =~ '[*@/]'
   3290                let fname= substitute(a:fname,".$","","")
   3291            else
   3292                let fname= a:fname
   3293            endif
   3294            let t  = getftime(s:NetrwFile(fname))
   3295            let sz = getfsize(s:NetrwFile(fname))
   3296            if g:netrw_sizestyle =~# "[hH]"
   3297                let sz= s:NetrwHumanReadable(sz)
   3298            endif
   3299            echo a:fname.":  ".sz."  ".strftime(g:netrw_timefmt,getftime(s:NetrwFile(fname)))
   3300        endif
   3301    else
   3302        echo "sorry, \"qf\" not supported yet for remote files"
   3303    endif
   3304    let @@= ykeep
   3305 endfunction
   3306 
   3307 " s:NetrwGetBuffer: [get a new|find an old netrw] buffer for a netrw listing {{{2
   3308 "   returns 0=cleared buffer
   3309 "           1=re-used buffer (buffer not cleared)
   3310 "  Nov 09, 2020: tst952 shows that when user does :set hidden that NetrwGetBuffer will come up with a [No Name] buffer (hid fix)
   3311 function s:NetrwGetBuffer(islocal,dirname)
   3312    let dirname= a:dirname
   3313 
   3314    " re-use buffer if possible {{{3
   3315    if !exists("s:netrwbuf")
   3316        let s:netrwbuf= {}
   3317    endif
   3318 
   3319    if exists("w:netrw_liststyle") && w:netrw_liststyle == s:TREELIST
   3320        let bufnum = -1
   3321 
   3322        if !empty(s:netrwbuf) && has_key(s:netrwbuf,netrw#fs#AbsPath(dirname))
   3323            if has_key(s:netrwbuf,"NetrwTreeListing")
   3324                let bufnum= s:netrwbuf["NetrwTreeListing"]
   3325            else
   3326                let bufnum= s:netrwbuf[netrw#fs#AbsPath(dirname)]
   3327            endif
   3328            if !bufexists(bufnum)
   3329                call remove(s:netrwbuf,"NetrwTreeListing")
   3330                let bufnum= -1
   3331            endif
   3332        elseif bufnr("NetrwTreeListing") != -1
   3333            let bufnum= bufnr("NetrwTreeListing")
   3334        else
   3335            let bufnum= -1
   3336        endif
   3337 
   3338    elseif has_key(s:netrwbuf,netrw#fs#AbsPath(dirname))
   3339        let bufnum= s:netrwbuf[netrw#fs#AbsPath(dirname)]
   3340        if !bufexists(bufnum)
   3341            call remove(s:netrwbuf,netrw#fs#AbsPath(dirname))
   3342            let bufnum= -1
   3343        endif
   3344 
   3345    else
   3346        let bufnum= -1
   3347    endif
   3348 
   3349    " highjack the current buffer
   3350    "   IF the buffer already has the desired name
   3351    "   AND it is empty
   3352    let curbuf = bufname("%")
   3353    if curbuf == '.'
   3354        let curbuf = getcwd()
   3355    endif
   3356    if dirname == curbuf && line("$") == 1 && getline("%") == ""
   3357        return 0
   3358    else  " DEBUG
   3359    endif
   3360    " Aug 14, 2021: was thinking about looking for a [No Name] buffer here and using it, but that might cause problems
   3361 
   3362    " get enew buffer and name it -or- re-use buffer {{{3
   3363    if bufnum < 0      " get enew buffer and name it
   3364        call s:NetrwEnew(dirname)
   3365        " name the buffer
   3366        if exists("w:netrw_liststyle") && w:netrw_liststyle == s:TREELIST
   3367            " Got enew buffer; transform into a NetrwTreeListing
   3368            let w:netrw_treebufnr = bufnr("%")
   3369            call s:NetrwBufRename("NetrwTreeListing")
   3370            if g:netrw_use_noswf
   3371                setl nobl bt=nofile noswf
   3372            else
   3373                setl nobl bt=nofile
   3374            endif
   3375            nnoremap <silent> <buffer> [[       :sil call <SID>TreeListMove('[[')<cr>
   3376            nnoremap <silent> <buffer> ]]       :sil call <SID>TreeListMove(']]')<cr>
   3377            nnoremap <silent> <buffer> []       :sil call <SID>TreeListMove('[]')<cr>
   3378            nnoremap <silent> <buffer> ][       :sil call <SID>TreeListMove('][')<cr>
   3379        else
   3380            call s:NetrwBufRename(dirname)
   3381            " enter the new buffer into the s:netrwbuf dictionary
   3382            let s:netrwbuf[netrw#fs#AbsPath(dirname)]= bufnr("%")
   3383        endif
   3384 
   3385    else " Re-use the buffer
   3386        " ignore all events
   3387        let eikeep= &ei
   3388        setl ei=all
   3389 
   3390        if &ft == "netrw"
   3391            exe "sil! NetrwKeepj noswapfile b ".bufnum
   3392        else
   3393            call s:NetrwEditBuf(bufnum)
   3394        endif
   3395        if bufname("%") == '.'
   3396            call s:NetrwBufRename(getcwd())
   3397        endif
   3398 
   3399        " restore ei
   3400        let &ei= eikeep
   3401 
   3402        if line("$") <= 1 && getline(1) == ""
   3403            " empty buffer
   3404            NetrwKeepj call s:NetrwListSettings(a:islocal)
   3405            return 0
   3406 
   3407        elseif g:netrw_fastbrowse == 0 || (a:islocal && g:netrw_fastbrowse == 1)
   3408            NetrwKeepj call s:NetrwListSettings(a:islocal)
   3409            sil NetrwKeepj %d _
   3410            return 0
   3411 
   3412        elseif exists("w:netrw_liststyle") && w:netrw_liststyle == s:TREELIST
   3413            setl ma
   3414            sil NetrwKeepj %d _
   3415            NetrwKeepj call s:NetrwListSettings(a:islocal)
   3416            return 0
   3417 
   3418        else
   3419            return 1
   3420        endif
   3421    endif
   3422 
   3423    " do netrw settings: make this buffer not-a-file, modifiable, not line-numbered, etc {{{3
   3424    "     fastbrowse  Local  Remote   Hiding a buffer implies it may be re-used (fast)
   3425    "  slow   0         D      D      Deleting a buffer implies it will not be re-used (slow)
   3426    "  med    1         D      H
   3427    "  fast   2         H      H
   3428    let fname= expand("%")
   3429    NetrwKeepj call s:NetrwListSettings(a:islocal)
   3430    call s:NetrwBufRename(fname)
   3431 
   3432    " delete all lines from buffer {{{3
   3433    sil! keepalt NetrwKeepj %d _
   3434 
   3435    return 0
   3436 endfunction
   3437 
   3438 "  s:NetrwGetWord: it gets the directory/file named under the cursor {{{2
   3439 function s:NetrwGetWord()
   3440    let keepsol= &l:sol
   3441    setl nosol
   3442 
   3443    call s:UseBufWinVars()
   3444 
   3445    " insure that w:netrw_liststyle is set up
   3446    if !exists("w:netrw_liststyle")
   3447        if exists("g:netrw_liststyle")
   3448            let w:netrw_liststyle= g:netrw_liststyle
   3449        else
   3450            let w:netrw_liststyle= s:THINLIST
   3451        endif
   3452    endif
   3453 
   3454    if exists("w:netrw_bannercnt") && line(".") < w:netrw_bannercnt
   3455        " Active Banner support
   3456        NetrwKeepj norm! 0
   3457        let dirname= "./"
   3458        let curline= getline('.')
   3459 
   3460        if curline =~# '"\s*Sorted by\s'
   3461            NetrwKeepj norm! "_s
   3462            let s:netrw_skipbrowse= 1
   3463            echo 'Pressing "s" also works'
   3464 
   3465        elseif curline =~# '"\s*Sort sequence:'
   3466            let s:netrw_skipbrowse= 1
   3467            echo 'Press "S" to edit sorting sequence'
   3468 
   3469        elseif curline =~# '"\s*Quick Help:'
   3470            NetrwKeepj norm! ?
   3471            let s:netrw_skipbrowse= 1
   3472 
   3473        elseif curline =~# '"\s*\%(Hiding\|Showing\):'
   3474            NetrwKeepj norm! a
   3475            let s:netrw_skipbrowse= 1
   3476            echo 'Pressing "a" also works'
   3477 
   3478        elseif line("$") > w:netrw_bannercnt
   3479            exe 'sil NetrwKeepj '.w:netrw_bannercnt
   3480        endif
   3481 
   3482    elseif w:netrw_liststyle == s:THINLIST
   3483        NetrwKeepj norm! 0
   3484        let dirname= substitute(getline('.'),'\t -->.*$','','')
   3485 
   3486    elseif w:netrw_liststyle == s:LONGLIST
   3487        NetrwKeepj norm! 0
   3488        let dirname= substitute(getline('.'),'^\(\%(\S\+ \)*\S\+\).\{-}$','\1','e')
   3489 
   3490    elseif exists("w:netrw_liststyle") && w:netrw_liststyle == s:TREELIST
   3491        let dirname= substitute(getline('.'),'^\('.s:treedepthstring.'\)*','','e')
   3492        let dirname= substitute(dirname,'\t -->.*$','','')
   3493 
   3494    else
   3495        let dirname= getline('.')
   3496 
   3497        if !exists("b:netrw_cpf")
   3498            let b:netrw_cpf= 0
   3499            exe 'sil NetrwKeepj '.w:netrw_bannercnt.',$g/^./if virtcol("$") > b:netrw_cpf|let b:netrw_cpf= virtcol("$")|endif'
   3500            call histdel("/",-1)
   3501        endif
   3502 
   3503        let filestart = (virtcol(".")/b:netrw_cpf)*b:netrw_cpf
   3504        if filestart == 0
   3505            NetrwKeepj norm! 0ma
   3506        else
   3507            call cursor(line("."),filestart+1)
   3508            NetrwKeepj norm! ma
   3509        endif
   3510 
   3511        let dict={}
   3512        " save the unnamed register and register 0-9 and a
   3513        let dict.a=[getreg('a'), getregtype('a')]
   3514        for i in range(0, 9)
   3515            let dict[i] = [getreg(i), getregtype(i)]
   3516        endfor
   3517        let dict.unnamed = [getreg(''), getregtype('')]
   3518 
   3519        let eofname= filestart + b:netrw_cpf + 1
   3520        if eofname <= col("$")
   3521            call cursor(line("."),filestart+b:netrw_cpf+1)
   3522            NetrwKeepj norm! "ay`a
   3523        else
   3524            NetrwKeepj norm! "ay$
   3525        endif
   3526 
   3527        let dirname = @a
   3528        call s:RestoreRegister(dict)
   3529 
   3530        let dirname= substitute(dirname,'\s\+$','','e')
   3531    endif
   3532 
   3533    " symlinks are indicated by a trailing "@".  Remove it before further processing.
   3534    let dirname= substitute(dirname,"@$","","")
   3535 
   3536    " executables are indicated by a trailing "*".  Remove it before further processing.
   3537    let dirname= substitute(dirname,"\*$","","")
   3538 
   3539    let &l:sol= keepsol
   3540 
   3541    return dirname
   3542 endfunction
   3543 
   3544 " s:NetrwListSettings: make standard settings for making a netrw listing {{{2
   3545 "                      g:netrw_bufsettings will be used after the listing is produced.
   3546 "                      Called by s:NetrwGetBuffer()
   3547 function s:NetrwListSettings(islocal)
   3548    let fname= bufname("%")
   3549    "              nobl noma nomod nonu noma nowrap ro   nornu  (std g:netrw_bufsettings)
   3550    setl bt=nofile nobl ma         nonu      nowrap noro nornu
   3551    call s:NetrwBufRename(fname)
   3552    if g:netrw_use_noswf
   3553        setl noswf
   3554    endif
   3555    exe "setl ts=".(g:netrw_maxfilenamelen+1)
   3556    setl isk+=.,~,-
   3557    if g:netrw_fastbrowse > a:islocal
   3558        setl bh=hide
   3559    else
   3560        setl bh=delete
   3561    endif
   3562 endfunction
   3563 
   3564 "  s:NetrwListStyle: change list style (thin - long - wide - tree) {{{2
   3565 "  islocal=0: remote browsing
   3566 "         =1: local browsing
   3567 function s:NetrwListStyle(islocal)
   3568    let ykeep             = @@
   3569    let fname             = s:NetrwGetWord()
   3570    if !exists("w:netrw_liststyle")|let w:netrw_liststyle= g:netrw_liststyle|endif
   3571    let svpos            = winsaveview()
   3572    let w:netrw_liststyle = (w:netrw_liststyle + 1) % s:MAXLIST
   3573 
   3574    " repoint t:netrw_lexbufnr if appropriate
   3575    if exists("t:netrw_lexbufnr") && bufnr("%") == t:netrw_lexbufnr
   3576        let repointlexbufnr= 1
   3577    endif
   3578 
   3579    if w:netrw_liststyle == s:THINLIST
   3580        " use one column listing
   3581        let g:netrw_list_cmd = substitute(g:netrw_list_cmd,' -l','','ge')
   3582 
   3583    elseif w:netrw_liststyle == s:LONGLIST
   3584        " use long list
   3585        let g:netrw_list_cmd = g:netrw_list_cmd." -l"
   3586 
   3587    elseif w:netrw_liststyle == s:WIDELIST
   3588        " give wide list
   3589        let g:netrw_list_cmd = substitute(g:netrw_list_cmd,' -l','','ge')
   3590 
   3591    elseif exists("w:netrw_liststyle") && w:netrw_liststyle == s:TREELIST
   3592        let g:netrw_list_cmd = substitute(g:netrw_list_cmd,' -l','','ge')
   3593 
   3594    else
   3595        call netrw#msg#Notify('WARNING', printf('bad value for g:netrw_liststyle (=%s)', w:netrw_liststyle))
   3596        let g:netrw_liststyle = s:THINLIST
   3597        let w:netrw_liststyle = g:netrw_liststyle
   3598        let g:netrw_list_cmd  = substitute(g:netrw_list_cmd,' -l','','ge')
   3599    endif
   3600    setl ma noro
   3601 
   3602    " clear buffer - this will cause NetrwBrowse/LocalBrowseCheck to do a refresh
   3603    sil! NetrwKeepj %d _
   3604    " following prevents tree listing buffer from being marked "modified"
   3605    setl nomod
   3606 
   3607    " refresh the listing
   3608    NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./',0))
   3609    NetrwKeepj call s:NetrwCursor(0)
   3610 
   3611    " repoint t:netrw_lexbufnr if appropriate
   3612    if exists("repointlexbufnr")
   3613        let t:netrw_lexbufnr= bufnr("%")
   3614    endif
   3615 
   3616    " restore position; keep cursor on the filename
   3617    NetrwKeepj call winrestview(svpos)
   3618    let @@= ykeep
   3619 
   3620 endfunction
   3621 
   3622 " s:NetrwBannerCtrl: toggles the display of the banner {{{2
   3623 function s:NetrwBannerCtrl(islocal)
   3624    let ykeep= @@
   3625    " toggle the banner (enable/suppress)
   3626    let g:netrw_banner= !g:netrw_banner
   3627 
   3628    " refresh the listing
   3629    let svpos= winsaveview()
   3630    call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./',0))
   3631 
   3632    " keep cursor on the filename
   3633    if g:netrw_banner && exists("w:netrw_bannercnt") && line(".") >= w:netrw_bannercnt
   3634        let fname= s:NetrwGetWord()
   3635        sil NetrwKeepj $
   3636        let result= search('\%(^\%(|\+\s\)\=\|\s\{2,}\)\zs'.escape(fname,'.\[]*$^').'\%(\s\{2,}\|$\)','bc')
   3637        if result <= 0 && exists("w:netrw_bannercnt")
   3638            exe "NetrwKeepj ".w:netrw_bannercnt
   3639        endif
   3640    endif
   3641    let @@= ykeep
   3642 endfunction
   3643 
   3644 " s:NetrwBookmark: supports :NetrwMB[!] [file]s                 {{{2
   3645 "
   3646 "  No bang: enters files/directories into Netrw's bookmark system
   3647 "   No argument and in netrw buffer:
   3648 "     if there are marked files: bookmark marked files
   3649 "     otherwise                : bookmark file/directory under cursor
   3650 "   No argument and not in netrw buffer: bookmarks current open file
   3651 "   Has arguments: globs them individually and bookmarks them
   3652 "
   3653 "  With bang: deletes files/directories from Netrw's bookmark system
   3654 function s:NetrwBookmark(del,...)
   3655    if a:0 == 0
   3656        if &ft == "netrw"
   3657            let curbufnr = bufnr("%")
   3658 
   3659            if exists("s:netrwmarkfilelist_{curbufnr}")
   3660                " for every filename in the marked list
   3661                let svpos  = winsaveview()
   3662                let islocal= expand("%") !~ '^\a\{3,}://'
   3663                for fname in s:netrwmarkfilelist_{curbufnr}
   3664                    if a:del|call s:DeleteBookmark(fname)|else|call s:MakeBookmark(fname)|endif
   3665                endfor
   3666                let curdir  = exists("b:netrw_curdir")? b:netrw_curdir : getcwd()
   3667                call s:NetrwUnmarkList(curbufnr,curdir)
   3668                NetrwKeepj call s:NetrwRefresh(islocal,s:NetrwBrowseChgDir(islocal,'./',0))
   3669                NetrwKeepj call winrestview(svpos)
   3670            else
   3671                let fname= s:NetrwGetWord()
   3672                if a:del|call s:DeleteBookmark(fname)|else|call s:MakeBookmark(fname)|endif
   3673            endif
   3674 
   3675        else
   3676            " bookmark currently open file
   3677            let fname= expand("%")
   3678            if a:del|call s:DeleteBookmark(fname)|else|call s:MakeBookmark(fname)|endif
   3679        endif
   3680 
   3681    else
   3682        " bookmark specified files
   3683        "  attempts to infer if working remote or local
   3684        "  by deciding if the current file begins with an url
   3685        "  Globbing cannot be done remotely.
   3686        let islocal= expand("%") !~ '^\a\{3,}://'
   3687        let i = 1
   3688        while i <= a:0
   3689            if islocal
   3690                let mbfiles = glob(fnameescape(a:{i}), 0, 1, 1)
   3691            else
   3692                let mbfiles = [a:{i}]
   3693            endif
   3694            for mbfile in mbfiles
   3695                if a:del
   3696                    call s:DeleteBookmark(mbfile)
   3697                else
   3698                    call s:MakeBookmark(mbfile)
   3699                endif
   3700            endfor
   3701            let i= i + 1
   3702        endwhile
   3703    endif
   3704 
   3705    " update the menu
   3706    call s:NetrwBookmarkMenu()
   3707 endfunction
   3708 
   3709 " s:NetrwBookmarkMenu: Uses menu priorities {{{2
   3710 "                      .2.[cnt] for bookmarks, and
   3711 "                      .3.[cnt] for history
   3712 "                      (see s:NetrwMenu())
   3713 function s:NetrwBookmarkMenu()
   3714    if !exists("s:netrw_menucnt")
   3715        return
   3716    endif
   3717 
   3718    " the following test assures that gvim is running, has menus available, and has menus enabled.
   3719    if has("gui") && has("menu") && has("gui_running") && &go =~# 'm' && g:netrw_menu
   3720        if exists("g:NetrwTopLvlMenu")
   3721            exe 'sil! unmenu '.g:NetrwTopLvlMenu.'Bookmarks'
   3722            exe 'sil! unmenu '.g:NetrwTopLvlMenu.'Bookmarks\ and\ History.Bookmark\ Delete'
   3723        endif
   3724        if !exists("s:netrw_initbookhist")
   3725            call s:NetrwBookHistRead()
   3726        endif
   3727 
   3728        " show bookmarked places
   3729        if exists("g:netrw_bookmarklist") && g:netrw_bookmarklist != [] && g:netrw_dirhistmax > 0
   3730            let cnt= 1
   3731            for bmd in g:netrw_bookmarklist
   3732                let bmd= escape(bmd,g:netrw_menu_escape)
   3733 
   3734                " show bookmarks for goto menu
   3735                exe 'sil! menu '.g:NetrwMenuPriority.".2.".cnt." ".g:NetrwTopLvlMenu.'Bookmarks.'.bmd.'    :e '.bmd."\<cr>"
   3736 
   3737                " show bookmarks for deletion menu
   3738                exe 'sil! menu '.g:NetrwMenuPriority.".8.2.".cnt." ".g:NetrwTopLvlMenu.'Bookmarks\ and\ History.Bookmark\ Delete.'.bmd.'   '.cnt."mB"
   3739                let cnt= cnt + 1
   3740            endfor
   3741 
   3742        endif
   3743 
   3744        " show directory browsing history
   3745        if g:netrw_dirhistmax > 0
   3746            let cnt     = g:netrw_dirhistcnt
   3747            let first   = 1
   3748            let histcnt = 0
   3749            while ( first || cnt != g:netrw_dirhistcnt )
   3750                let histcnt  = histcnt + 1
   3751                let priority = g:netrw_dirhistcnt + histcnt
   3752                if exists("g:netrw_dirhist_{cnt}")
   3753                    let histdir= escape(g:netrw_dirhist_{cnt},g:netrw_menu_escape)
   3754                    exe 'sil! menu '.g:NetrwMenuPriority.".3.".priority." ".g:NetrwTopLvlMenu.'History.'.histdir.'    :e '.histdir."\<cr>"
   3755                endif
   3756                let first = 0
   3757                let cnt   = ( cnt - 1 ) % g:netrw_dirhistmax
   3758                if cnt < 0
   3759                    let cnt= cnt + g:netrw_dirhistmax
   3760                endif
   3761            endwhile
   3762        endif
   3763 
   3764    endif
   3765 endfunction
   3766 
   3767 "  s:NetrwBrowseChgDir: constructs a new directory based on the current {{{2
   3768 "                       directory and a new directory name.  Also, if the
   3769 "                       "new directory name" is actually a file,
   3770 "                       NetrwBrowseChgDir() edits the file.
   3771 "    cursor=0: newdir is relative to b:netrw_curdir
   3772 "          =1: newdir is relative to the path to the word under the cursor in
   3773 "              tree view
   3774 function s:NetrwBrowseChgDir(islocal, newdir, cursor, ...)
   3775    let ykeep= @@
   3776    if !exists("b:netrw_curdir")
   3777        let @@= ykeep
   3778        return
   3779    endif
   3780 
   3781    " NetrwBrowseChgDir; save options and initialize {{{3
   3782    call s:SavePosn(s:netrw_posn)
   3783    NetrwKeepj call s:NetrwOptionsSave("s:")
   3784    NetrwKeepj call s:NetrwOptionsSafe(a:islocal)
   3785 
   3786    let newdir = a:newdir
   3787    let dirname = b:netrw_curdir
   3788 
   3789    if a:cursor && w:netrw_liststyle == s:TREELIST
   3790        " dirname is the path to the word under the cursor
   3791        let dirname = s:NetrwTreePath(w:netrw_treetop)
   3792        " If the word under the cursor is a directory (except for ../), NetrwTreePath
   3793        " returns the full path, including the word under the cursor, remove it
   3794        if newdir != "../"
   3795            let dirname = fnamemodify(dirname, ":h")
   3796        endif
   3797    endif
   3798 
   3799    if has("win32")
   3800        let dirname = substitute(dirname, '\\', '/', 'ge')
   3801    endif
   3802 
   3803    let dolockout = 0
   3804    let dorestore = 1
   3805 
   3806    " ignore <cr>s when done in the banner
   3807    if g:netrw_banner
   3808        if exists("w:netrw_bannercnt") && line(".") < w:netrw_bannercnt && line("$") >= w:netrw_bannercnt
   3809            if getline(".") =~# 'Quick Help'
   3810                let g:netrw_quickhelp= (g:netrw_quickhelp + 1)%len(s:QuickHelp)
   3811                setl ma noro nowrap
   3812                NetrwKeepj call setline(line('.'),'"   Quick Help: <F1>:help  '.s:QuickHelp[g:netrw_quickhelp])
   3813                setl noma nomod nowrap
   3814                NetrwKeepj call s:NetrwOptionsRestore("s:")
   3815            endif
   3816        endif
   3817    endif
   3818 
   3819    " set up o/s-dependent directory recognition pattern
   3820    let dirpat = has("amiga") ? '[\/:]$' : '[\/]$'
   3821 
   3822    if newdir !~ dirpat && !(a:islocal && isdirectory(s:NetrwFile(netrw#fs#ComposePath(dirname, newdir))))
   3823        " ------------------------------
   3824        " NetrwBrowseChgDir: edit a file {{{3
   3825        " ------------------------------
   3826 
   3827        " save position for benefit of Rexplore
   3828        let s:rexposn_{bufnr("%")}= winsaveview()
   3829 
   3830        let dirname = isabsolutepath(newdir)
   3831                    \ ? netrw#fs#AbsPath(newdir)
   3832                    \ : netrw#fs#ComposePath(dirname, newdir)
   3833 
   3834        " this lets netrw#BrowseX avoid the edit
   3835        if a:0 < 1
   3836            NetrwKeepj call s:NetrwOptionsRestore("s:")
   3837            let curdir= b:netrw_curdir
   3838            if !exists("s:didsplit")
   3839                if type(g:netrw_browse_split) == 3
   3840                    " open file in server
   3841                    " Note that g:netrw_browse_split is a List: [servername,tabnr,winnr]
   3842                    call s:NetrwServerEdit(a:islocal,dirname)
   3843                    return
   3844 
   3845                elseif g:netrw_browse_split == 1
   3846                    " horizontally splitting the window first
   3847                    let winsz= (g:netrw_winsize > 0)? (g:netrw_winsize*winheight(0))/100 : -g:netrw_winsize
   3848                    exe "keepalt ".(g:netrw_alto? "bel " : "abo ").winsz."wincmd s"
   3849                    if !&ea
   3850                        keepalt wincmd _
   3851                    else
   3852                        exe "keepalt wincmd ="
   3853                    endif
   3854                    call s:SetRexDir(a:islocal,curdir)
   3855 
   3856                elseif g:netrw_browse_split == 2
   3857                    " vertically splitting the window first
   3858                    let winsz= (g:netrw_winsize > 0)? (g:netrw_winsize*winwidth(0))/100 : -g:netrw_winsize
   3859                    exe "keepalt ".(g:netrw_alto? "top " : "bot ")."vert ".winsz."wincmd s"
   3860                    if !&ea
   3861                        keepalt wincmd |
   3862                    else
   3863                        exe "keepalt wincmd ="
   3864                    endif
   3865                    call s:SetRexDir(a:islocal,curdir)
   3866 
   3867                elseif g:netrw_browse_split == 3
   3868                    " open file in new tab
   3869                    keepalt tabnew
   3870                    if !exists("b:netrw_curdir")
   3871                        let b:netrw_curdir= getcwd()
   3872                    endif
   3873                    call s:SetRexDir(a:islocal,curdir)
   3874 
   3875                elseif g:netrw_browse_split == 4
   3876                    " act like "P" (ie. open previous window)
   3877                    if s:NetrwPrevWinOpen(2) == 3
   3878                        let @@= ykeep
   3879                        return
   3880                    endif
   3881                    call s:SetRexDir(a:islocal,curdir)
   3882 
   3883                else
   3884                    " handling a file, didn't split, so remove menu
   3885                    call s:NetrwMenu(0)
   3886                    " optional change to window
   3887                    if g:netrw_chgwin >= 1
   3888                        if winnr("$")+1 == g:netrw_chgwin
   3889                            " if g:netrw_chgwin is set to one more than the last window, then
   3890                            " vertically split the last window to make that window available.
   3891                            let curwin= winnr()
   3892                            exe "NetrwKeepj keepalt ".winnr("$")."wincmd w"
   3893                            vs
   3894                            exe "NetrwKeepj keepalt ".g:netrw_chgwin."wincmd ".curwin
   3895                        endif
   3896                        exe "NetrwKeepj keepalt ".g:netrw_chgwin."wincmd w"
   3897                    endif
   3898                    call s:SetRexDir(a:islocal,curdir)
   3899                endif
   3900 
   3901            endif
   3902 
   3903            " the point where netrw actually edits the (local) file
   3904            " if its local only: LocalBrowseCheck() doesn't edit a file, but NetrwBrowse() will
   3905            " use keepalt to support  :e #  to return to a directory listing
   3906            if !&mod
   3907                " if e the new file would fail due to &mod, then don't change any of the flags
   3908                let dolockout= 1
   3909            endif
   3910 
   3911            if a:islocal
   3912                " some like c-^ to return to the last edited file
   3913                " others like c-^ to return to the netrw buffer
   3914                " Apr 30, 2020: used to have e! here.  That can cause loss of a modified file,
   3915                " so emit error E37 instead.
   3916                call s:NetrwEditFile("e","",dirname)
   3917                call s:NetrwCursor(1)
   3918                if &hidden || &bufhidden == "hide"
   3919                    " file came from vim's hidden storage.  Don't "restore" options with it.
   3920                    let dorestore= 0
   3921                endif
   3922            endif
   3923 
   3924            " handle g:Netrw_funcref -- call external-to-netrw functions
   3925            "   This code will handle g:Netrw_funcref as an individual function reference
   3926            "   or as a list of function references.  It will ignore anything that's not
   3927            "   a function reference.  See  :help Funcref  for information about function references.
   3928            if exists("g:Netrw_funcref")
   3929                if type(g:Netrw_funcref) == 2
   3930                    NetrwKeepj call g:Netrw_funcref()
   3931                elseif type(g:Netrw_funcref) == 3
   3932                    for Fncref in g:Netrw_funcref
   3933                        if type(Fncref) == 2
   3934                            NetrwKeepj call Fncref()
   3935                        endif
   3936                    endfor
   3937                endif
   3938            endif
   3939        endif
   3940 
   3941    elseif newdir =~ '^/'
   3942        " ----------------------------------------------------
   3943        " NetrwBrowseChgDir: just go to the new directory spec {{{3
   3944        " ----------------------------------------------------
   3945        let dirname = newdir
   3946        NetrwKeepj call s:SetRexDir(a:islocal,dirname)
   3947        NetrwKeepj call s:NetrwOptionsRestore("s:")
   3948        norm! m`
   3949 
   3950    elseif newdir == './'
   3951        " ---------------------------------------------
   3952        " NetrwBrowseChgDir: refresh the directory list {{{3
   3953        " ---------------------------------------------
   3954        NetrwKeepj call s:SetRexDir(a:islocal,dirname)
   3955        norm! m`
   3956 
   3957    elseif newdir == '../'
   3958        " --------------------------------------
   3959        " NetrwBrowseChgDir: go up one directory {{{3
   3960        " --------------------------------------
   3961 
   3962        " The following regexps expect '/' as path separator
   3963        let dirname = substitute(netrw#fs#AbsPath(dirname), '\\', '/', 'ge') . '/'
   3964 
   3965        if w:netrw_liststyle == s:TREELIST && exists("w:netrw_treedict")
   3966            " force a refresh
   3967            setl noro ma
   3968            NetrwKeepj %d _
   3969        endif
   3970 
   3971        if has("amiga")
   3972            " amiga
   3973            if a:islocal
   3974                let dirname= substitute(dirname,'^\(.*[/:]\)\([^/]\+$\)','\1','')
   3975                let dirname= substitute(dirname,'/$','','')
   3976            else
   3977                let dirname= substitute(dirname,'^\(.*[/:]\)\([^/]\+/$\)','\1','')
   3978            endif
   3979 
   3980        elseif !g:netrw_cygwin && has("win32")
   3981            " windows
   3982            if a:islocal
   3983                let dirname= substitute(dirname,'^\(.*\)/\([^/]\+\)/$','\1','')
   3984                if dirname == ""
   3985                    let dirname= '/'
   3986                endif
   3987            else
   3988                let dirname= substitute(dirname,'^\(\a\{3,}://.\{-}/\{1,2}\)\(.\{-}\)\([^/]\+\)/$','\1\2','')
   3989            endif
   3990            if dirname =~ '^\a:$'
   3991                let dirname= dirname.'/'
   3992            endif
   3993 
   3994        else
   3995            " unix or cygwin
   3996            if a:islocal
   3997                let dirname= substitute(dirname,'^\(.*\)/\([^/]\+\)/$','\1','')
   3998                if dirname == ""
   3999                    let dirname= '/'
   4000                endif
   4001            else
   4002                let dirname= substitute(dirname,'^\(\a\{3,}://.\{-}/\{1,2}\)\(.\{-}\)\([^/]\+\)/$','\1\2','')
   4003            endif
   4004        endif
   4005        NetrwKeepj call s:SetRexDir(a:islocal,dirname)
   4006        norm! m`
   4007 
   4008    elseif exists("w:netrw_liststyle") && w:netrw_liststyle == s:TREELIST && exists("w:netrw_treedict")
   4009        " --------------------------------------
   4010        " NetrwBrowseChgDir: Handle Tree Listing {{{3
   4011        " --------------------------------------
   4012        " force a refresh (for TREELIST, NetrwTreeDir() will force the refresh)
   4013        setl noro ma
   4014        if !(exists("w:netrw_liststyle") && w:netrw_liststyle == s:TREELIST && exists("b:netrw_curdir"))
   4015            NetrwKeepj %d _
   4016        endif
   4017        let treedir      = s:NetrwTreeDir(a:islocal)
   4018        let s:treecurpos = winsaveview()
   4019        let haskey       = 0
   4020 
   4021        " search treedict for tree dir as-is
   4022        if has_key(w:netrw_treedict,treedir)
   4023            let haskey= 1
   4024        else
   4025        endif
   4026 
   4027        " search treedict for treedir with a [/@] appended
   4028        if !haskey && treedir !~ '[/@]$'
   4029            if has_key(w:netrw_treedict,treedir."/")
   4030                let treedir= treedir."/"
   4031                let haskey = 1
   4032            else
   4033            endif
   4034        endif
   4035 
   4036        " search treedict for treedir with any trailing / elided
   4037        if !haskey && treedir =~ '/$'
   4038            let treedir= substitute(treedir,'/$','','')
   4039            if has_key(w:netrw_treedict,treedir)
   4040                let haskey = 1
   4041            else
   4042            endif
   4043        endif
   4044 
   4045        if haskey
   4046            " close tree listing for selected subdirectory
   4047            call remove(w:netrw_treedict,treedir)
   4048            let dirname= w:netrw_treetop
   4049        else
   4050            " go down one directory
   4051            let dirname= substitute(treedir,'/*$','/','')
   4052        endif
   4053        NetrwKeepj call s:SetRexDir(a:islocal,dirname)
   4054        let s:treeforceredraw = 1
   4055 
   4056    else
   4057        " ----------------------------------------
   4058        " NetrwBrowseChgDir: Go down one directory {{{3
   4059        " ----------------------------------------
   4060        let dirname    = netrw#fs#ComposePath(dirname,newdir)
   4061        NetrwKeepj call s:SetRexDir(a:islocal,dirname)
   4062        norm! m`
   4063    endif
   4064 
   4065    " --------------------------------------
   4066    " NetrwBrowseChgDir: Restore and Cleanup {{{3
   4067    " --------------------------------------
   4068    if dorestore
   4069        " dorestore is zero'd when a local file was hidden or bufhidden;
   4070        " in such a case, we want to keep whatever settings it may have.
   4071        NetrwKeepj call s:NetrwOptionsRestore("s:")
   4072    endif
   4073    if dolockout && dorestore
   4074        if filewritable(dirname)
   4075            setl ma noro nomod
   4076        else
   4077            setl ma ro nomod
   4078        endif
   4079    endif
   4080    call s:RestorePosn(s:netrw_posn)
   4081    let @@= ykeep
   4082 
   4083    return dirname
   4084 endfunction
   4085 
   4086 " s:NetrwBrowseUpDir: implements the "-" mappings {{{2
   4087 "    for thin, long, and wide: cursor placed just after banner
   4088 "    for tree, keeps cursor on current filename
   4089 function s:NetrwBrowseUpDir(islocal)
   4090    if exists("w:netrw_bannercnt") && line(".") < w:netrw_bannercnt-1
   4091        " this test needed because occasionally this function seems to be incorrectly called
   4092        " when multiple leftmouse clicks are taken when atop the one line help in the banner.
   4093        " I'm allowing the very bottom line to permit a "-" exit so that one may escape empty
   4094        " directories.
   4095        return
   4096    endif
   4097 
   4098    norm! 0
   4099    if exists("w:netrw_liststyle") && w:netrw_liststyle == s:TREELIST && exists("w:netrw_treedict")
   4100        let curline= getline(".")
   4101        let swwline= winline() - 1
   4102        if exists("w:netrw_treetop")
   4103            let b:netrw_curdir= w:netrw_treetop
   4104        elseif exists("b:netrw_curdir")
   4105            let w:netrw_treetop= b:netrw_curdir
   4106        else
   4107            let w:netrw_treetop= getcwd()
   4108            let b:netrw_curdir = w:netrw_treetop
   4109        endif
   4110        let curfile = getline(".")
   4111        let curpath = s:NetrwTreePath(w:netrw_treetop)
   4112        if a:islocal
   4113            call netrw#LocalBrowseCheck(s:NetrwBrowseChgDir(1,'../',0))
   4114        else
   4115            call s:NetrwBrowse(0,s:NetrwBrowseChgDir(0,'../',0))
   4116        endif
   4117        if w:netrw_treetop == '/'
   4118            keepj call search('^\M'.curfile,"w")
   4119        elseif curfile == '../'
   4120            keepj call search('^\M'.curfile,"wb")
   4121        else
   4122            while 1
   4123                keepj call search('^\M'.s:treedepthstring.curfile,"wb")
   4124                let treepath= s:NetrwTreePath(w:netrw_treetop)
   4125                if treepath == curpath
   4126                    break
   4127                endif
   4128            endwhile
   4129        endif
   4130 
   4131    else
   4132        call s:SavePosn(s:netrw_posn)
   4133        if exists("b:netrw_curdir")
   4134            let curdir= b:netrw_curdir
   4135        else
   4136            let curdir= expand(getcwd())
   4137        endif
   4138        if a:islocal
   4139            call netrw#LocalBrowseCheck(s:NetrwBrowseChgDir(1,'../',0))
   4140        else
   4141            call s:NetrwBrowse(0,s:NetrwBrowseChgDir(0,'../',0))
   4142        endif
   4143        call s:RestorePosn(s:netrw_posn)
   4144        let curdir= substitute(curdir,'^.*[\/]','','')
   4145        let curdir= '\<'. escape(curdir, '~'). '/'
   4146        call search(curdir,'wc')
   4147    endif
   4148 endfunction
   4149 
   4150 " netrw#BrowseX:  (implements "x") executes a special "viewer" script or program for the {{{2
   4151 "                 given filename; typically this means given their extension.
   4152 function netrw#BrowseX(fname)
   4153    " special core dump handler
   4154    if a:fname =~ '/core\(\.\d\+\)\=$' && exists("g:Netrw_corehandler")
   4155        if type(g:Netrw_corehandler) == v:t_func
   4156            " g:Netrw_corehandler is a function reference (see :help Funcref)
   4157            call g:Netrw_corehandler(s:NetrwFile(a:fname))
   4158        elseif type(g:Netrw_corehandler) == v:t_list
   4159            " g:Netrw_corehandler is a List of function references (see :help Funcref)
   4160            for Fncref in g:Netrw_corehandler
   4161                if type(Fncref) == v:t_func
   4162                    call Fncref(a:fname)
   4163                endif
   4164            endfor
   4165        endif
   4166        return
   4167    endif
   4168 
   4169    let fname = a:fname
   4170    " special ~ handler for local
   4171    if fname =~ '^\~' && expand("$HOME") != ""
   4172        let fname = substitute(fname, '^\~', expand("$HOME"), '')
   4173    endif
   4174 
   4175    if fname =~ '^[a-z]\+://'
   4176        " open a remote file
   4177        call netrw#os#Open(fname)
   4178    else
   4179        call netrw#os#Open(s:NetrwFile(fname))
   4180    endif
   4181 endfunction
   4182 
   4183 " s:NetrwBufRename: renames a buffer without the side effect of retaining an unlisted buffer having the old name {{{2
   4184 "                   Using the file command on a "[No Name]" buffer does not seem to cause the old "[No Name]" buffer
   4185 "                   to become an unlisted buffer, so in that case don't bwipe it.
   4186 function s:NetrwBufRename(newname)
   4187    let oldbufname= bufname(bufnr("%"))
   4188 
   4189    if oldbufname != a:newname
   4190        let b:junk= 1
   4191        exe 'sil! keepj keepalt file '.fnameescape(a:newname)
   4192        let oldbufnr= bufnr(oldbufname)
   4193        if oldbufname != "" && oldbufnr != -1 && oldbufnr != bufnr("%")
   4194            exe "bwipe! ".oldbufnr
   4195        endif
   4196    endif
   4197 
   4198 endfunction
   4199 
   4200 " netrw#CheckIfRemote: returns 1 if current file looks like an url, 0 else {{{2
   4201 function netrw#CheckIfRemote(...)
   4202    if a:0 > 0
   4203        let curfile= a:1
   4204    else
   4205        let curfile= expand("%")
   4206    endif
   4207    " Ignore terminal buffers
   4208    if &buftype ==# 'terminal'
   4209        return 0
   4210    endif
   4211    if curfile =~ '^\a\{3,}://'
   4212        return 1
   4213    else
   4214        return 0
   4215    endif
   4216 endfunction
   4217 
   4218 " s:NetrwChgPerm: (implements "gp") change file permission {{{2
   4219 function s:NetrwChgPerm(islocal,curdir)
   4220    let ykeep  = @@
   4221    call inputsave()
   4222    let newperm= input("Enter new permission: ")
   4223    call inputrestore()
   4224    let fullpath = fnamemodify(netrw#fs#PathJoin(a:curdir, expand("<cfile>")), ':p')
   4225    let chgperm= substitute(g:netrw_chgperm,'\<FILENAME\>',netrw#os#Escape(fullpath),'')
   4226    let chgperm= substitute(chgperm,'\<PERM\>',netrw#os#Escape(newperm),'')
   4227    call system(chgperm)
   4228    if v:shell_error != 0
   4229        NetrwKeepj call netrw#msg#Notify('WARNING', printf('changing permission on file<%s> seems to have failed', fullpath))
   4230    endif
   4231    if a:islocal
   4232        NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./',0))
   4233    endif
   4234    let @@= ykeep
   4235 endfunction
   4236 
   4237 " s:NetrwClearExplore: clear explore variables (if any) {{{2
   4238 function s:NetrwClearExplore()
   4239    2match none
   4240    if exists("s:explore_match")        |unlet s:explore_match        |endif
   4241    if exists("s:explore_indx")         |unlet s:explore_indx         |endif
   4242    if exists("s:netrw_explore_prvdir") |unlet s:netrw_explore_prvdir |endif
   4243    if exists("s:dirstarstar")          |unlet s:dirstarstar          |endif
   4244    if exists("s:explore_prvdir")       |unlet s:explore_prvdir       |endif
   4245    if exists("w:netrw_explore_indx")   |unlet w:netrw_explore_indx   |endif
   4246    if exists("w:netrw_explore_listlen")|unlet w:netrw_explore_listlen|endif
   4247    if exists("w:netrw_explore_list")   |unlet w:netrw_explore_list   |endif
   4248    if exists("w:netrw_explore_bufnr")  |unlet w:netrw_explore_bufnr  |endif
   4249    "   redraw!
   4250 endfunction
   4251 
   4252 " s:NetrwEditBuf: decides whether or not to use keepalt to edit a buffer {{{2
   4253 function s:NetrwEditBuf(bufnum)
   4254    if exists("g:netrw_altfile") && g:netrw_altfile && &ft == "netrw"
   4255        exe "sil! NetrwKeepj keepalt noswapfile b ".fnameescape(a:bufnum)
   4256    else
   4257        exe "sil! NetrwKeepj noswapfile b ".fnameescape(a:bufnum)
   4258    endif
   4259 endfunction
   4260 
   4261 " s:NetrwEditFile: decides whether or not to use keepalt to edit a file {{{2
   4262 "    NetrwKeepj [keepalt] <OPT> <CMD> <FILENAME>
   4263 function s:NetrwEditFile(cmd,opt,fname)
   4264    if exists("g:netrw_altfile") && g:netrw_altfile && &ft == "netrw"
   4265        exe "NetrwKeepj noswapfile keepalt ".a:opt." ".a:cmd." ".fnameescape(a:fname)
   4266    else
   4267        if a:cmd =~# 'e\%[new]!' && !&hidden && getbufvar(bufname('%'), '&modified', 0)
   4268            call setbufvar(bufname('%'), '&bufhidden', 'hide')
   4269        endif
   4270        exe "NetrwKeepj noswapfile ".a:opt." ".a:cmd." ".fnameescape(a:fname)
   4271    endif
   4272 endfunction
   4273 
   4274 " s:NetrwExploreListUniq: {{{2
   4275 function s:NetrwExploreListUniq(explist)
   4276    " this assumes that the list is already sorted
   4277    let newexplist= []
   4278    for member in a:explist
   4279        if !exists("uniqmember") || member != uniqmember
   4280            let uniqmember = member
   4281            let newexplist = newexplist + [ member ]
   4282        endif
   4283    endfor
   4284    return newexplist
   4285 endfunction
   4286 
   4287 " s:NetrwForceChgDir: (gd support) Force treatment as a directory {{{2
   4288 function s:NetrwForceChgDir(islocal,newdir)
   4289    let ykeep= @@
   4290    if a:newdir !~ '/$'
   4291        " ok, looks like force is needed to get directory-style treatment
   4292        if a:newdir =~ '@$'
   4293            let newdir= substitute(a:newdir,'@$','/','')
   4294        elseif a:newdir =~ '[*=|\\]$'
   4295            let newdir= substitute(a:newdir,'.$','/','')
   4296        else
   4297            let newdir= a:newdir.'/'
   4298        endif
   4299    else
   4300        " should already be getting treatment as a directory
   4301        let newdir= a:newdir
   4302    endif
   4303    let newdir= s:NetrwBrowseChgDir(a:islocal,newdir,0)
   4304    call s:NetrwBrowse(a:islocal,newdir)
   4305    let @@= ykeep
   4306 endfunction
   4307 
   4308 " s:NetrwForceFile: (gf support) Force treatment as a file {{{2
   4309 function s:NetrwForceFile(islocal,newfile)
   4310    if a:newfile =~ '[/@*=|\\]$'
   4311        let newfile= substitute(a:newfile,'.$','','')
   4312    else
   4313        let newfile= a:newfile
   4314    endif
   4315    if a:islocal
   4316        call s:NetrwBrowseChgDir(a:islocal,newfile,0)
   4317    else
   4318        call s:NetrwBrowse(a:islocal,s:NetrwBrowseChgDir(a:islocal,newfile,0))
   4319    endif
   4320 endfunction
   4321 
   4322 " s:NetrwHide: this function is invoked by the "a" map for browsing {{{2
   4323 "          and switches the hiding mode.  The actual hiding is done by
   4324 "          s:NetrwListHide().
   4325 "             g:netrw_hide= 0: show all
   4326 "                           1: show not-hidden files
   4327 "                           2: show hidden files only
   4328 function s:NetrwHide(islocal)
   4329    let ykeep= @@
   4330    let svpos= winsaveview()
   4331 
   4332    if exists("s:netrwmarkfilelist_{bufnr('%')}")
   4333 
   4334        " hide the files in the markfile list
   4335        for fname in s:netrwmarkfilelist_{bufnr("%")}
   4336            if match(g:netrw_list_hide,'\<'.fname.'\>') != -1
   4337                " remove fname from hiding list
   4338                let g:netrw_list_hide= substitute(g:netrw_list_hide,'..\<'.escape(fname,g:netrw_fname_escape).'\>..','','')
   4339                let g:netrw_list_hide= substitute(g:netrw_list_hide,',,',',','g')
   4340                let g:netrw_list_hide= substitute(g:netrw_list_hide,'^,\|,$','','')
   4341            else
   4342                " append fname to hiding list
   4343                if exists("g:netrw_list_hide") && g:netrw_list_hide != ""
   4344                    let g:netrw_list_hide= g:netrw_list_hide.',\<'.escape(fname,g:netrw_fname_escape).'\>'
   4345                else
   4346                    let g:netrw_list_hide= '\<'.escape(fname,g:netrw_fname_escape).'\>'
   4347                endif
   4348            endif
   4349        endfor
   4350        NetrwKeepj call s:NetrwUnmarkList(bufnr("%"),b:netrw_curdir)
   4351        let g:netrw_hide= 1
   4352 
   4353    else
   4354 
   4355        " switch between show-all/show-not-hidden/show-hidden
   4356        let g:netrw_hide=(g:netrw_hide+1)%3
   4357        exe "NetrwKeepj norm! 0"
   4358        if g:netrw_hide && g:netrw_list_hide == ""
   4359            call netrw#msg#Notify('WARNING', 'your hiding list is empty!')
   4360            let @@= ykeep
   4361            return
   4362        endif
   4363    endif
   4364 
   4365    NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./',0))
   4366    NetrwKeepj call winrestview(svpos)
   4367    let @@= ykeep
   4368 endfunction
   4369 
   4370 " s:NetrwHideEdit: allows user to edit the file/directory hiding list {{{2
   4371 function s:NetrwHideEdit(islocal)
   4372    let ykeep= @@
   4373    " save current cursor position
   4374    let svpos= winsaveview()
   4375 
   4376    " get new hiding list from user
   4377    call inputsave()
   4378    let newhide= input("Edit Hiding List: ",g:netrw_list_hide)
   4379    call inputrestore()
   4380    let g:netrw_list_hide= newhide
   4381 
   4382    " refresh the listing
   4383    sil NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,"./",0))
   4384 
   4385    " restore cursor position
   4386    call winrestview(svpos)
   4387    let @@= ykeep
   4388 endfunction
   4389 
   4390 " s:NetrwHidden: invoked by "gh" {{{2
   4391 function s:NetrwHidden(islocal)
   4392    let ykeep= @@
   4393    "  save current position
   4394    let svpos  = winsaveview()
   4395 
   4396    if g:netrw_list_hide =~ '\(^\|,\)\\(^\\|\\s\\s\\)\\zs\\.\\S\\+'
   4397        " remove .file pattern from hiding list
   4398        let g:netrw_list_hide= substitute(g:netrw_list_hide,'\(^\|,\)\\(^\\|\\s\\s\\)\\zs\\.\\S\\+','','')
   4399    elseif strdisplaywidth(g:netrw_list_hide) >= 1
   4400        let g:netrw_list_hide= g:netrw_list_hide . ',\(^\|\s\s\)\zs\.\S\+'
   4401    else
   4402        let g:netrw_list_hide= '\(^\|\s\s\)\zs\.\S\+'
   4403    endif
   4404    if g:netrw_list_hide =~ '^,'
   4405        let g:netrw_list_hide= strpart(g:netrw_list_hide,1)
   4406    endif
   4407 
   4408    " refresh screen and return to saved position
   4409    NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./',0))
   4410    NetrwKeepj call winrestview(svpos)
   4411    let @@= ykeep
   4412 endfunction
   4413 
   4414 "  s:NetrwHome: this function determines a "home" for saving bookmarks and history {{{2
   4415 function s:NetrwHome()
   4416    if has('nvim')
   4417        let home = netrw#fs#PathJoin(stdpath('state'), 'netrw')
   4418    elseif exists('g:netrw_home')
   4419        let home = expand(g:netrw_home)
   4420    elseif exists('$MYVIMDIR')
   4421        let home = expand('$MYVIMDIR')->substitute('/$', '', '')
   4422    else
   4423        " Pick the first redable directory in 'runtimepath'
   4424        for path in split(&rtp, ',')
   4425            if isdirectory(s:NetrwFile(path)) && filewritable(s:NetrwFile(path))
   4426                let home = path
   4427                break
   4428            endif
   4429        endfor
   4430 
   4431        if empty(path)
   4432            " just pick the first directory
   4433            let home = substitute(&rtp, ',.*$', '', '')
   4434        endif
   4435    endif
   4436 
   4437    " insure that the home directory exists
   4438    if g:netrw_dirhistmax > 0 && !isdirectory(s:NetrwFile(home))
   4439        if exists("g:netrw_mkdir")
   4440            call system(g:netrw_mkdir." ".s:ShellEscape(s:NetrwFile(home)))
   4441        else
   4442            call mkdir(home)
   4443        endif
   4444    endif
   4445 
   4446    " Normalize directory if on Windows
   4447    if has("win32")
   4448        let home = substitute(home, '/', '\\', 'g')
   4449    endif
   4450 
   4451    let g:netrw_home = home
   4452    return home
   4453 endfunction
   4454 
   4455 " s:NetrwLeftmouse: handles the <leftmouse> when in a netrw browsing window {{{2
   4456 function s:NetrwLeftmouse(islocal)
   4457    if exists("s:netrwdrag")
   4458        return
   4459    endif
   4460    if &ft != "netrw"
   4461        return
   4462    endif
   4463 
   4464    let ykeep= @@
   4465    " check if the status bar was clicked on instead of a file/directory name
   4466    while getchar(0) != 0
   4467        "clear the input stream
   4468    endwhile
   4469    call feedkeys("\<LeftMouse>")
   4470    let c          = getchar()
   4471    let mouse_lnum = v:mouse_lnum
   4472    let wlastline  = line('w$')
   4473    let lastline   = line('$')
   4474    if mouse_lnum >= wlastline + 1 || v:mouse_win != winnr()
   4475        " appears to be a status bar leftmouse click
   4476        let @@= ykeep
   4477        return
   4478    endif
   4479    " Dec 04, 2013: following test prevents leftmouse selection/deselection of directories and files in treelist mode
   4480    " Windows are separated by vertical separator bars - but the mouse seems to be doing what it should when dragging that bar
   4481    " without this test when its disabled.
   4482    " May 26, 2014: edit file, :Lex, resize window -- causes refresh.  Reinstated a modified test.  See if problems develop.
   4483    if v:mouse_col > virtcol('.')
   4484        let @@= ykeep
   4485        return
   4486    endif
   4487 
   4488    if a:islocal
   4489        if exists("b:netrw_curdir")
   4490            NetrwKeepj call netrw#LocalBrowseCheck(s:NetrwBrowseChgDir(1,s:NetrwGetWord(),1))
   4491        endif
   4492    else
   4493        if exists("b:netrw_curdir")
   4494            NetrwKeepj call s:NetrwBrowse(0,s:NetrwBrowseChgDir(0,s:NetrwGetWord(),1))
   4495        endif
   4496    endif
   4497    let @@= ykeep
   4498 endfunction
   4499 
   4500 " s:NetrwCLeftmouse: used to select a file/directory for a target {{{2
   4501 function s:NetrwCLeftmouse(islocal)
   4502    if &ft != "netrw"
   4503        return
   4504    endif
   4505    call s:NetrwMarkFileTgt(a:islocal)
   4506 endfunction
   4507 
   4508 " s:NetrwServerEdit: edit file in a server gvim, usually NETRWSERVER  (implements <c-r>){{{2
   4509 "   a:islocal=0 : <c-r> not used, remote
   4510 "   a:islocal=1 : <c-r> not used, local
   4511 "   a:islocal=2 : <c-r>     used, remote
   4512 "   a:islocal=3 : <c-r>     used, local
   4513 function s:NetrwServerEdit(islocal,fname)
   4514    let islocal = a:islocal%2      " =0: remote           =1: local
   4515    let ctrlr   = a:islocal >= 2   " =0: <c-r> not used   =1: <c-r> used
   4516 
   4517    if (islocal && isdirectory(s:NetrwFile(a:fname))) || (!islocal && a:fname =~ '/$')
   4518        " handle directories in the local window -- not in the remote vim server
   4519        " user must have closed the NETRWSERVER window.  Treat as normal editing from netrw.
   4520        let g:netrw_browse_split= 0
   4521        if exists("s:netrw_browse_split") && exists("s:netrw_browse_split_".winnr())
   4522            let g:netrw_browse_split= s:netrw_browse_split_{winnr()}
   4523            unlet s:netrw_browse_split_{winnr()}
   4524        endif
   4525        call s:NetrwBrowse(islocal,s:NetrwBrowseChgDir(islocal,a:fname,0))
   4526        return
   4527    endif
   4528 
   4529    if has("clientserver") && executable("gvim")
   4530 
   4531        if exists("g:netrw_browse_split") && type(g:netrw_browse_split) == 3
   4532            let srvrname = g:netrw_browse_split[0]
   4533            let tabnum   = g:netrw_browse_split[1]
   4534            let winnum   = g:netrw_browse_split[2]
   4535 
   4536            if serverlist() !~ '\<'.srvrname.'\>'
   4537                if !ctrlr
   4538                    " user must have closed the server window and the user did not use <c-r>, but
   4539                    " used something like <cr>.
   4540                    if exists("g:netrw_browse_split")
   4541                        unlet g:netrw_browse_split
   4542                    endif
   4543                    let g:netrw_browse_split= 0
   4544                    if exists("s:netrw_browse_split_".winnr())
   4545                        let g:netrw_browse_split= s:netrw_browse_split_{winnr()}
   4546                    endif
   4547                    call s:NetrwBrowseChgDir(islocal,a:fname,0)
   4548                    return
   4549 
   4550                elseif has("win32") && executable("start")
   4551                    " start up remote netrw server under windows
   4552                    call system("start gvim --servername ".srvrname)
   4553 
   4554                else
   4555                    " start up remote netrw server under linux
   4556                    call system("gvim --servername ".srvrname)
   4557                endif
   4558            endif
   4559 
   4560            call remote_send(srvrname,":tabn ".tabnum."\<cr>")
   4561            call remote_send(srvrname,":".winnum."wincmd w\<cr>")
   4562            call remote_send(srvrname,":e ".fnameescape(s:NetrwFile(a:fname))."\<cr>")
   4563        else
   4564 
   4565            if serverlist() !~ '\<'.g:netrw_servername.'\>'
   4566 
   4567                if !ctrlr
   4568                    if exists("g:netrw_browse_split")
   4569                        unlet g:netrw_browse_split
   4570                    endif
   4571                    let g:netrw_browse_split= 0
   4572                    call s:NetrwBrowse(islocal,s:NetrwBrowseChgDir(islocal,a:fname,0))
   4573                    return
   4574 
   4575                else
   4576                    if has("win32") && executable("start")
   4577                        " start up remote netrw server under windows
   4578                        call system("start gvim --servername ".g:netrw_servername)
   4579                    else
   4580                        " start up remote netrw server under linux
   4581                        call system("gvim --servername ".g:netrw_servername)
   4582                    endif
   4583                endif
   4584            endif
   4585 
   4586            while 1
   4587                try
   4588                    call remote_send(g:netrw_servername,":e ".fnameescape(s:NetrwFile(a:fname))."\<cr>")
   4589                    break
   4590                catch /^Vim\%((\a\+)\)\=:E241/
   4591                    sleep 200m
   4592                endtry
   4593            endwhile
   4594 
   4595            if exists("g:netrw_browse_split")
   4596                if type(g:netrw_browse_split) != 3
   4597                    let s:netrw_browse_split_{winnr()}= g:netrw_browse_split
   4598                endif
   4599                unlet g:netrw_browse_split
   4600            endif
   4601            let g:netrw_browse_split= [g:netrw_servername,1,1]
   4602        endif
   4603 
   4604    else
   4605        call netrw#msg#Notify('ERROR', 'you need a gui-capable vim and client-server to use <ctrl-r>')
   4606    endif
   4607 
   4608 endfunction
   4609 
   4610 " s:NetrwSLeftmouse: marks the file under the cursor.  May be dragged to select additional files {{{2
   4611 function s:NetrwSLeftmouse(islocal)
   4612    if &ft != "netrw"
   4613        return
   4614    endif
   4615 
   4616    let s:ngw= s:NetrwGetWord()
   4617    call s:NetrwMarkFile(a:islocal,s:ngw)
   4618 
   4619 endfunction
   4620 
   4621 " s:NetrwSLeftdrag: invoked via a shift-leftmouse and dragging {{{2
   4622 "                   Used to mark multiple files.
   4623 function s:NetrwSLeftdrag(islocal)
   4624    if !exists("s:netrwdrag")
   4625        let s:netrwdrag = winnr()
   4626        if a:islocal
   4627            nno <silent> <s-leftrelease> <leftmouse>:<c-u>call <SID>NetrwSLeftrelease(1)<cr>
   4628        else
   4629            nno <silent> <s-leftrelease> <leftmouse>:<c-u>call <SID>NetrwSLeftrelease(0)<cr>
   4630        endif
   4631    endif
   4632    let ngw = s:NetrwGetWord()
   4633    if !exists("s:ngw") || s:ngw != ngw
   4634        call s:NetrwMarkFile(a:islocal,ngw)
   4635    endif
   4636    let s:ngw= ngw
   4637 endfunction
   4638 
   4639 " s:NetrwSLeftrelease: terminates shift-leftmouse dragging {{{2
   4640 function s:NetrwSLeftrelease(islocal)
   4641    if exists("s:netrwdrag")
   4642        nunmap <s-leftrelease>
   4643        let ngw = s:NetrwGetWord()
   4644        if !exists("s:ngw") || s:ngw != ngw
   4645            call s:NetrwMarkFile(a:islocal,ngw)
   4646        endif
   4647        if exists("s:ngw")
   4648            unlet s:ngw
   4649        endif
   4650        unlet s:netrwdrag
   4651    endif
   4652 endfunction
   4653 
   4654 " s:NetrwListHide: uses [range]g~...~d to delete files that match       {{{2
   4655 "                  comma-separated patterns given in g:netrw_list_hide
   4656 function s:NetrwListHide()
   4657    let ykeep= @@
   4658 
   4659    " find a character not in the "hide" string to use as a separator for :g and :v commands
   4660    " How-it-works: take the hiding command, convert it into a range.
   4661    " Duplicate characters don't matter.
   4662    " Remove all such characters from the '/~@#...890' string.
   4663    " Use the first character left as a separator character.
   4664    let listhide= g:netrw_list_hide
   4665    let sep     = strpart(substitute('~@#$%^&*{};:,<.>?|1234567890','['.escape(listhide,'-]^\').']','','ge'),1,1)
   4666 
   4667    while listhide != ""
   4668        if listhide =~ ','
   4669            let hide     = substitute(listhide,',.*$','','e')
   4670            let listhide = substitute(listhide,'^.\{-},\(.*\)$','\1','e')
   4671        else
   4672            let hide     = listhide
   4673            let listhide = ""
   4674        endif
   4675        if g:netrw_sort_by =~ '^[ts]'
   4676            if hide =~ '^\^'
   4677                let hide= substitute(hide,'^\^','^\(\\d\\+/\)','')
   4678            elseif hide =~ '^\\(\^'
   4679                let hide= substitute(hide,'^\\(\^','\\(^\\(\\d\\+/\\)','')
   4680            endif
   4681        endif
   4682 
   4683        " Prune the list by hiding any files which match
   4684        if g:netrw_hide == 1
   4685            exe 'sil! NetrwKeepj '.w:netrw_bannercnt.',$g'.sep.hide.sep.'d'
   4686        elseif g:netrw_hide == 2
   4687            exe 'sil! NetrwKeepj '.w:netrw_bannercnt.',$g'.sep.hide.sep.'s@^@ /-KEEP-/ @'
   4688        endif
   4689    endwhile
   4690 
   4691    if g:netrw_hide == 2
   4692        exe 'sil! NetrwKeepj '.w:netrw_bannercnt.',$v@^ /-KEEP-/ @d'
   4693        exe 'sil! NetrwKeepj '.w:netrw_bannercnt.',$s@^\%( /-KEEP-/ \)\+@@e'
   4694    endif
   4695 
   4696    " remove any blank lines that have somehow remained.
   4697    " This seems to happen under Windows.
   4698    exe 'sil! NetrwKeepj 1,$g@^\s*$@d'
   4699 
   4700    let @@= ykeep
   4701 endfunction
   4702 
   4703 " s:NetrwMakeDir: this function makes a directory (both local and remote) {{{2
   4704 "                 implements the "d" mapping.
   4705 function s:NetrwMakeDir(usrhost)
   4706 
   4707    let ykeep= @@
   4708    " get name of new directory from user.  A bare <CR> will skip.
   4709    " if its currently a directory, also request will be skipped, but with
   4710    " a message.
   4711    call inputsave()
   4712    let newdirname= input("Please give directory name: ")
   4713    call inputrestore()
   4714 
   4715    if newdirname == ""
   4716        let @@= ykeep
   4717        return
   4718    endif
   4719 
   4720    if a:usrhost == ""
   4721 
   4722        " Local mkdir:
   4723        " sanity checks
   4724        let fullnewdir= b:netrw_curdir.'/'.newdirname
   4725        if isdirectory(s:NetrwFile(fullnewdir))
   4726            call netrw#msg#Notify('WARNING', printf('<%s> is already a directory!', newdirname))
   4727            let @@= ykeep
   4728            return
   4729        endif
   4730        if s:FileReadable(fullnewdir)
   4731            call netrw#msg#Notify('WARNING', printf('<%s> is already a file!', newdirname))
   4732            let @@= ykeep
   4733            return
   4734        endif
   4735 
   4736        " requested new local directory is neither a pre-existing file or
   4737        " directory, so make it!
   4738        if exists("*mkdir")
   4739            if has("unix")
   4740                call mkdir(fullnewdir,"p",xor(0777, system("umask")))
   4741            else
   4742                call mkdir(fullnewdir,"p")
   4743            endif
   4744        else
   4745            let netrw_origdir= netrw#fs#Cwd(1)
   4746            if s:NetrwLcd(b:netrw_curdir)
   4747                return
   4748            endif
   4749            call netrw#os#Execute("sil! !".g:netrw_localmkdir.g:netrw_localmkdiropt.' '.netrw#os#Escape(newdirname,1))
   4750            if v:shell_error != 0
   4751                let @@= ykeep
   4752                call netrw#msg#Notify('ERROR', printf('consider setting g:netrw_localmkdir<%s> to something that works', g:netrw_localmkdir))
   4753                return
   4754            endif
   4755            if !g:netrw_keepdir
   4756                if s:NetrwLcd(netrw_origdir)
   4757                    return
   4758                endif
   4759            endif
   4760        endif
   4761 
   4762        if v:shell_error == 0
   4763            " refresh listing
   4764            let svpos= winsaveview()
   4765            call s:NetrwRefresh(1,s:NetrwBrowseChgDir(1,'./',0))
   4766            call winrestview(svpos)
   4767        else
   4768            call netrw#msg#Notify('ERROR', printf('unable to make directory<%s>', newdirname))
   4769        endif
   4770 
   4771    elseif !exists("b:netrw_method") || b:netrw_method == 4
   4772        " Remote mkdir:  using ssh
   4773        let mkdircmd  = s:MakeSshCmd(g:netrw_mkdir_cmd)
   4774        let newdirname= substitute(b:netrw_curdir,'^\%(.\{-}/\)\{3}\(.*\)$','\1','').newdirname
   4775        call netrw#os#Execute("sil! !".mkdircmd." ".netrw#os#Escape(newdirname,1))
   4776        if v:shell_error == 0
   4777            " refresh listing
   4778            let svpos= winsaveview()
   4779            NetrwKeepj call s:NetrwRefresh(0,s:NetrwBrowseChgDir(0,'./',0))
   4780            NetrwKeepj call winrestview(svpos)
   4781        else
   4782            call netrw#msg#Notify('ERROR', printf('unable to make directory<%s>', newdirname))
   4783        endif
   4784 
   4785    elseif b:netrw_method == 2
   4786        " Remote mkdir:  using ftp+.netrc
   4787        let svpos= winsaveview()
   4788        if exists("b:netrw_fname")
   4789            let remotepath= b:netrw_fname
   4790        else
   4791            let remotepath= ""
   4792        endif
   4793        call s:NetrwRemoteFtpCmd(remotepath,g:netrw_remote_mkdir.' "'.newdirname.'"')
   4794        NetrwKeepj call s:NetrwRefresh(0,s:NetrwBrowseChgDir(0,'./',0))
   4795        NetrwKeepj call winrestview(svpos)
   4796 
   4797    elseif b:netrw_method == 3
   4798        " Remote mkdir: using ftp + machine, id, passwd, and fname (ie. no .netrc)
   4799        let svpos= winsaveview()
   4800        if exists("b:netrw_fname")
   4801            let remotepath= b:netrw_fname
   4802        else
   4803            let remotepath= ""
   4804        endif
   4805        call s:NetrwRemoteFtpCmd(remotepath,g:netrw_remote_mkdir.' "'.newdirname.'"')
   4806        NetrwKeepj call s:NetrwRefresh(0,s:NetrwBrowseChgDir(0,'./',0))
   4807        NetrwKeepj call winrestview(svpos)
   4808    endif
   4809 
   4810    let @@= ykeep
   4811 endfunction
   4812 
   4813 " s:TreeSqueezeDir: allows a shift-cr (gvim only) to squeeze the current tree-listing directory {{{2
   4814 function s:TreeSqueezeDir(islocal)
   4815    if exists("w:netrw_liststyle") && w:netrw_liststyle == s:TREELIST && exists("w:netrw_treedict")
   4816        " its a tree-listing style
   4817        let curdepth = substitute(getline('.'),'^\(\%('.s:treedepthstring.'\)*\)[^'.s:treedepthstring.'].\{-}$','\1','e')
   4818        let stopline = (exists("w:netrw_bannercnt")? (w:netrw_bannercnt + 1) : 1)
   4819        let depth    = strchars(substitute(curdepth,' ','','g'))
   4820        let srch     = -1
   4821        if depth >= 2
   4822            NetrwKeepj norm! 0
   4823            let curdepthm1= substitute(curdepth,'^'.s:treedepthstring,'','')
   4824            let srch      = search('^'.curdepthm1.'\%('.s:treedepthstring.'\)\@!','bW',stopline)
   4825        elseif depth == 1
   4826            NetrwKeepj norm! 0
   4827            let treedepthchr= substitute(s:treedepthstring,' ','','')
   4828            let srch        = search('^[^'.treedepthchr.']','bW',stopline)
   4829        endif
   4830        if srch > 0
   4831            call s:NetrwBrowse(a:islocal,s:NetrwBrowseChgDir(a:islocal,s:NetrwGetWord(),1))
   4832            exe srch
   4833        endif
   4834    endif
   4835 endfunction
   4836 
   4837 " s:NetrwMaps: {{{2
   4838 function s:NetrwMaps(islocal)
   4839 
   4840    " mouse <Plug> maps: {{{3
   4841    if g:netrw_mousemaps && g:netrw_retmap
   4842        if !hasmapto("<Plug>NetrwReturn")
   4843            if maparg("<2-leftmouse>","n") == "" || maparg("<2-leftmouse>","n") =~ '^-$'
   4844                nmap <unique> <silent> <2-leftmouse>       <Plug>NetrwReturn
   4845            elseif maparg("<c-leftmouse>","n") == ""
   4846                nmap <unique> <silent> <c-leftmouse>       <Plug>NetrwReturn
   4847            endif
   4848        endif
   4849        nno <silent> <Plug>NetrwReturn       :Rexplore<cr>
   4850    endif
   4851 
   4852    " generate default <Plug> maps {{{3
   4853    if !hasmapto('<Plug>NetrwHide')              |nmap <buffer> <silent> <nowait> a       <Plug>NetrwHide_a|endif
   4854    if !hasmapto('<Plug>NetrwBrowseUpDir')       |nmap <buffer> <silent> <nowait> -       <Plug>NetrwBrowseUpDir|endif
   4855    if !hasmapto('<Plug>NetrwOpenFile')          |nmap <buffer> <silent> <nowait> %       <Plug>NetrwOpenFile|endif
   4856    if !hasmapto('<Plug>NetrwBadd_cb')           |nmap <buffer> <silent> <nowait> cb      <Plug>NetrwBadd_cb|endif
   4857    if !hasmapto('<Plug>NetrwBadd_cB')           |nmap <buffer> <silent> <nowait> cB      <Plug>NetrwBadd_cB|endif
   4858    if !hasmapto('<Plug>NetrwLcd')               |nmap <buffer> <silent> <nowait> cd      <Plug>NetrwLcd|endif
   4859    if !hasmapto('<Plug>NetrwSetChgwin')         |nmap <buffer> <silent> <nowait> C       <Plug>NetrwSetChgwin|endif
   4860    if !hasmapto('<Plug>NetrwRefresh')           |nmap <buffer> <silent> <nowait> <c-l>   <Plug>NetrwRefresh|endif
   4861    if !hasmapto('<Plug>NetrwLocalBrowseCheck')  |nmap <buffer> <silent> <nowait> <cr>    <Plug>NetrwLocalBrowseCheck|endif
   4862    if !hasmapto('<Plug>NetrwServerEdit')        |nmap <buffer> <silent> <nowait> <c-r>   <Plug>NetrwServerEdit|endif
   4863    if !hasmapto('<Plug>NetrwMakeDir')           |nmap <buffer> <silent> <nowait> d       <Plug>NetrwMakeDir|endif
   4864    if !hasmapto('<Plug>NetrwBookHistHandler_gb')|nmap <buffer> <silent> <nowait> gb      <Plug>NetrwBookHistHandler_gb|endif
   4865 
   4866    if a:islocal
   4867        " local normal-mode maps {{{3
   4868        nnoremap <buffer> <silent> <Plug>NetrwHide_a                 :<c-u>call <SID>NetrwHide(1)<cr>
   4869        nnoremap <buffer> <silent> <Plug>NetrwBrowseUpDir            :<c-u>call <SID>NetrwBrowseUpDir(1)<cr>
   4870        nnoremap <buffer> <silent> <Plug>NetrwOpenFile               :<c-u>call <SID>NetrwOpenFile(1)<cr>
   4871        nnoremap <buffer> <silent> <Plug>NetrwBadd_cb                :<c-u>call <SID>NetrwBadd(1,0)<cr>
   4872        nnoremap <buffer> <silent> <Plug>NetrwBadd_cB                :<c-u>call <SID>NetrwBadd(1,1)<cr>
   4873        nnoremap <buffer> <silent> <Plug>NetrwLcd                    :<c-u>call <SID>NetrwLcd(b:netrw_curdir)<cr>
   4874        nnoremap <buffer> <silent> <Plug>NetrwSetChgwin              :<c-u>call <SID>NetrwSetChgwin()<cr>
   4875        nnoremap <buffer> <silent> <Plug>NetrwLocalBrowseCheck       :<c-u>call netrw#LocalBrowseCheck(<SID>NetrwBrowseChgDir(1,<SID>NetrwGetWord(),1))<cr>
   4876        nnoremap <buffer> <silent> <Plug>NetrwServerEdit             :<c-u>call <SID>NetrwServerEdit(3,<SID>NetrwGetWord())<cr>
   4877        nnoremap <buffer> <silent> <Plug>NetrwMakeDir                :<c-u>call <SID>NetrwMakeDir("")<cr>
   4878        nnoremap <buffer> <silent> <Plug>NetrwBookHistHandler_gb     :<c-u>call <SID>NetrwBookHistHandler(1,b:netrw_curdir)<cr>
   4879        " ---------------------------------------------------------------------
   4880        nnoremap <buffer> <silent> <nowait> gd       :<c-u>call <SID>NetrwForceChgDir(1,<SID>NetrwGetWord())<cr>
   4881        nnoremap <buffer> <silent> <nowait> gf       :<c-u>call <SID>NetrwForceFile(1,<SID>NetrwGetWord())<cr>
   4882        nnoremap <buffer> <silent> <nowait> gh       :<c-u>call <SID>NetrwHidden(1)<cr>
   4883        nnoremap <buffer> <silent> <nowait> gn       :<c-u>call netrw#SetTreetop(0,<SID>NetrwGetWord())<cr>
   4884        nnoremap <buffer> <silent> <nowait> gp       :<c-u>call <SID>NetrwChgPerm(1,b:netrw_curdir)<cr>
   4885        nnoremap <buffer> <silent> <nowait> I        :<c-u>call <SID>NetrwBannerCtrl(1)<cr>
   4886        nnoremap <buffer> <silent> <nowait> i        :<c-u>call <SID>NetrwListStyle(1)<cr>
   4887        nnoremap <buffer> <silent> <nowait> ma       :<c-u>call <SID>NetrwMarkFileArgList(1,0)<cr>
   4888        nnoremap <buffer> <silent> <nowait> mA       :<c-u>call <SID>NetrwMarkFileArgList(1,1)<cr>
   4889        nnoremap <buffer> <silent> <nowait> mb       :<c-u>call <SID>NetrwBookHistHandler(0,b:netrw_curdir)<cr>
   4890        nnoremap <buffer> <silent> <nowait> mB       :<c-u>call <SID>NetrwBookHistHandler(6,b:netrw_curdir)<cr>
   4891        nnoremap <buffer> <silent> <nowait> mc       :<c-u>call <SID>NetrwMarkFileCopy(1)<cr>
   4892        nnoremap <buffer> <silent> <nowait> md       :<c-u>call <SID>NetrwMarkFileDiff(1)<cr>
   4893        nnoremap <buffer> <silent> <nowait> me       :<c-u>call <SID>NetrwMarkFileEdit(1)<cr>
   4894        nnoremap <buffer> <silent> <nowait> mf       :<c-u>call <SID>NetrwMarkFile(1,<SID>NetrwGetWord())<cr>
   4895        nnoremap <buffer> <silent> <nowait> mF       :<c-u>call <SID>NetrwUnmarkList(bufnr("%"),b:netrw_curdir)<cr>
   4896        nnoremap <buffer> <silent> <nowait> mg       :<c-u>call <SID>NetrwMarkFileGrep(1)<cr>
   4897        nnoremap <buffer> <silent> <nowait> mh       :<c-u>call <SID>NetrwMarkHideSfx(1)<cr>
   4898        nnoremap <buffer> <silent> <nowait> mm       :<c-u>call <SID>NetrwMarkFileMove(1)<cr>
   4899        nnoremap <buffer> <silent> <nowait> mr       :<c-u>call <SID>NetrwMarkFileRegexp(1)<cr>
   4900        nnoremap <buffer> <silent> <nowait> ms       :<c-u>call <SID>NetrwMarkFileSource(1)<cr>
   4901        nnoremap <buffer> <silent> <nowait> mT       :<c-u>call <SID>NetrwMarkFileTag(1)<cr>
   4902        nnoremap <buffer> <silent> <nowait> mt       :<c-u>call <SID>NetrwMarkFileTgt(1)<cr>
   4903        nnoremap <buffer> <silent> <nowait> mu       :<c-u>call <SID>NetrwUnMarkFile(1)<cr>
   4904        nnoremap <buffer> <silent> <nowait> mv       :<c-u>call <SID>NetrwMarkFileVimCmd(1)<cr>
   4905        nnoremap <buffer> <silent> <nowait> mx       :<c-u>call <SID>NetrwMarkFileExe(1,0)<cr>
   4906        nnoremap <buffer> <silent> <nowait> mX       :<c-u>call <SID>NetrwMarkFileExe(1,1)<cr>
   4907        nnoremap <buffer> <silent> <nowait> mz       :<c-u>call <SID>NetrwMarkFileCompress(1)<cr>
   4908        nnoremap <buffer> <silent> <nowait> O        :<c-u>call <SID>NetrwObtain(1)<cr>
   4909        nnoremap <buffer> <silent> <nowait> o        :call <SID>NetrwSplit(3)<cr>
   4910        nnoremap <buffer> <silent> <nowait> p        :<c-u>call <SID>NetrwPreview(<SID>NetrwBrowseChgDir(1,<SID>NetrwGetWord(),1,1))<cr>
   4911        nnoremap <buffer> <silent> <nowait> P        :<c-u>call <SID>NetrwPrevWinOpen(1)<cr>
   4912        nnoremap <buffer> <silent> <nowait> qb       :<c-u>call <SID>NetrwBookHistHandler(2,b:netrw_curdir)<cr>
   4913        nnoremap <buffer> <silent> <nowait> qf       :<c-u>call <SID>NetrwFileInfo(1,<SID>NetrwGetWord())<cr>
   4914        nnoremap <buffer> <silent> <nowait> qF       :<c-u>call <SID>NetrwMarkFileQFEL(1,getqflist())<cr>
   4915        nnoremap <buffer> <silent> <nowait> qL       :<c-u>call <SID>NetrwMarkFileQFEL(1,getloclist(v:count))<cr>
   4916        nnoremap <buffer> <silent> <nowait> s        :call <SID>NetrwSortStyle(1)<cr>
   4917        nnoremap <buffer> <silent> <nowait> S        :<c-u>call <SID>NetSortSequence(1)<cr>
   4918        nnoremap <buffer> <silent> <nowait> Tb       :<c-u>call <SID>NetrwSetTgt(1,'b',v:count1)<cr>
   4919        nnoremap <buffer> <silent> <nowait> t        :call <SID>NetrwSplit(4)<cr>
   4920        nnoremap <buffer> <silent> <nowait> Th       :<c-u>call <SID>NetrwSetTgt(1,'h',v:count)<cr>
   4921        nnoremap <buffer> <silent> <nowait> u        :<c-u>call <SID>NetrwBookHistHandler(4,expand("%"))<cr>
   4922        nnoremap <buffer> <silent> <nowait> U        :<c-u>call <SID>NetrwBookHistHandler(5,expand("%"))<cr>
   4923        nnoremap <buffer> <silent> <nowait> v        :call <SID>NetrwSplit(5)<cr>
   4924        nnoremap <buffer> <silent> <nowait> x        :<c-u>call netrw#BrowseX(<SID>NetrwBrowseChgDir(1,<SID>NetrwGetWord(),1,0))"<cr>
   4925        nnoremap <buffer> <silent> <nowait> X        :<c-u>call <SID>NetrwLocalExecute(expand("<cword>"))"<cr>
   4926 
   4927        nnoremap <buffer> <silent> <nowait> r        :<c-u>let g:netrw_sort_direction= (g:netrw_sort_direction =~# 'n')? 'r' : 'n'<bar>exe "norm! 0"<bar>call <SID>NetrwRefresh(1,<SID>NetrwBrowseChgDir(1,'./',0))<cr>
   4928        if !hasmapto('<Plug>NetrwHideEdit')
   4929            nmap <buffer> <unique> <c-h> <Plug>NetrwHideEdit
   4930        endif
   4931        nnoremap <buffer> <silent> <Plug>NetrwHideEdit               :call <SID>NetrwHideEdit(1)<cr>
   4932        if !hasmapto('<Plug>NetrwRefresh')
   4933            nmap <buffer> <unique> <c-l> <Plug>NetrwRefresh
   4934        endif
   4935        nnoremap <buffer> <silent> <Plug>NetrwRefresh                <c-l>:call <SID>NetrwRefresh(1,<SID>NetrwBrowseChgDir(1,(exists("w:netrw_liststyle") && exists("w:netrw_treetop") && w:netrw_liststyle == 3)? w:netrw_treetop : './',0))<cr>
   4936        if s:didstarstar || !mapcheck("<s-down>","n")
   4937            nnoremap <buffer> <silent> <s-down> :Nexplore<cr>
   4938        endif
   4939        if s:didstarstar || !mapcheck("<s-up>","n")
   4940            nnoremap <buffer> <silent> <s-up>   :Pexplore<cr>
   4941        endif
   4942        if !hasmapto('<Plug>NetrwTreeSqueeze')
   4943            nmap <buffer> <silent> <nowait> <s-cr>                      <Plug>NetrwTreeSqueeze
   4944        endif
   4945        nnoremap <buffer> <silent> <Plug>NetrwTreeSqueeze            :call <SID>TreeSqueezeDir(1)<cr>
   4946        let mapsafecurdir = escape(b:netrw_curdir, s:netrw_map_escape)
   4947        if g:netrw_mousemaps == 1
   4948            nmap <buffer>                       <leftmouse>             <Plug>NetrwLeftmouse
   4949            nmap <buffer>                       <c-leftmouse>           <Plug>NetrwCLeftmouse
   4950            nmap <buffer>                       <middlemouse>           <Plug>NetrwMiddlemouse
   4951            nmap <buffer>                       <s-leftmouse>           <Plug>NetrwSLeftmouse
   4952            nmap <buffer>                       <s-leftdrag>            <Plug>NetrwSLeftdrag
   4953            nmap <buffer>                       <2-leftmouse>           <Plug>Netrw2Leftmouse
   4954            imap <buffer>                       <leftmouse>             <Plug>ILeftmouse
   4955            imap <buffer>                       <middlemouse>           <Plug>IMiddlemouse
   4956            nno  <buffer> <silent>              <Plug>NetrwLeftmouse    :exec "norm! \<lt>leftmouse>"<bar>call <SID>NetrwLeftmouse(1)<cr>
   4957            nno  <buffer> <silent>              <Plug>NetrwCLeftmouse   :exec "norm! \<lt>leftmouse>"<bar>call <SID>NetrwCLeftmouse(1)<cr>
   4958            nno  <buffer> <silent>              <Plug>NetrwMiddlemouse  :exec "norm! \<lt>leftmouse>"<bar>call <SID>NetrwPrevWinOpen(1)<cr>
   4959            nno  <buffer> <silent>              <Plug>NetrwSLeftmouse   :exec "norm! \<lt>leftmouse>"<bar>call <SID>NetrwSLeftmouse(1)<cr>
   4960            nno  <buffer> <silent>              <Plug>NetrwSLeftdrag    :exec "norm! \<lt>leftmouse>"<bar>call <SID>NetrwSLeftdrag(1)<cr>
   4961            nmap <buffer> <silent>              <Plug>Netrw2Leftmouse   -
   4962                exe 'nnoremap <buffer> <silent> <rightmouse>  :exec "norm! \<lt>leftmouse>"<bar>call <SID>NetrwLocalRm("'.mapsafecurdir.'")<cr>'
   4963            exe 'vnoremap <buffer> <silent> <rightmouse>  :exec "norm! \<lt>leftmouse>"<bar>call <SID>NetrwLocalRm("'.mapsafecurdir.'")<cr>'
   4964        endif
   4965        exe 'nnoremap <buffer> <silent> <nowait> <del>       :call <SID>NetrwLocalRm("'.mapsafecurdir.'")<cr>'
   4966        exe 'nnoremap <buffer> <silent> <nowait> D           :call <SID>NetrwLocalRm("'.mapsafecurdir.'")<cr>'
   4967        exe 'nnoremap <buffer> <silent> <nowait> R           :call <SID>NetrwLocalRename("'.mapsafecurdir.'")<cr>'
   4968        exe 'nnoremap <buffer> <silent> <nowait> d           :call <SID>NetrwMakeDir("")<cr>'
   4969        exe 'vnoremap <buffer> <silent> <nowait> <del>       :call <SID>NetrwLocalRm("'.mapsafecurdir.'")<cr>'
   4970        exe 'vnoremap <buffer> <silent> <nowait> D           :call <SID>NetrwLocalRm("'.mapsafecurdir.'")<cr>'
   4971        exe 'vnoremap <buffer> <silent> <nowait> R           :call <SID>NetrwLocalRename("'.mapsafecurdir.'")<cr>'
   4972        nnoremap <buffer> <F1>                       :he netrw-quickhelp<cr>
   4973 
   4974        " support user-specified maps
   4975        call netrw#UserMaps(1)
   4976 
   4977    else
   4978        " remote normal-mode maps {{{3
   4979        call s:RemotePathAnalysis(b:netrw_curdir)
   4980        nnoremap <buffer> <silent> <Plug>NetrwHide_a                 :<c-u>call <SID>NetrwHide(0)<cr>
   4981        nnoremap <buffer> <silent> <Plug>NetrwBrowseUpDir            :<c-u>call <SID>NetrwBrowseUpDir(0)<cr>
   4982        nnoremap <buffer> <silent> <Plug>NetrwOpenFile               :<c-u>call <SID>NetrwOpenFile(0)<cr>
   4983        nnoremap <buffer> <silent> <Plug>NetrwBadd_cb                :<c-u>call <SID>NetrwBadd(0,0)<cr>
   4984        nnoremap <buffer> <silent> <Plug>NetrwBadd_cB                :<c-u>call <SID>NetrwBadd(0,1)<cr>
   4985        nnoremap <buffer> <silent> <Plug>NetrwLcd                    :<c-u>call <SID>NetrwLcd(b:netrw_curdir)<cr>
   4986        nnoremap <buffer> <silent> <Plug>NetrwSetChgwin              :<c-u>call <SID>NetrwSetChgwin()<cr>
   4987        nnoremap <buffer> <silent> <Plug>NetrwRefresh                :<c-u>call <SID>NetrwRefresh(0,<SID>NetrwBrowseChgDir(0,'./',0))<cr>
   4988        nnoremap <buffer> <silent> <Plug>NetrwLocalBrowseCheck       :<c-u>call <SID>NetrwBrowse(0,<SID>NetrwBrowseChgDir(0,<SID>NetrwGetWord(),1))<cr>
   4989        nnoremap <buffer> <silent> <Plug>NetrwServerEdit             :<c-u>call <SID>NetrwServerEdit(2,<SID>NetrwGetWord())<cr>
   4990        nnoremap <buffer> <silent> <Plug>NetrwBookHistHandler_gb     :<c-u>call <SID>NetrwBookHistHandler(1,b:netrw_curdir)<cr>
   4991        " ---------------------------------------------------------------------
   4992        nnoremap <buffer> <silent> <nowait> gd       :<c-u>call <SID>NetrwForceChgDir(0,<SID>NetrwGetWord())<cr>
   4993        nnoremap <buffer> <silent> <nowait> gf       :<c-u>call <SID>NetrwForceFile(0,<SID>NetrwGetWord())<cr>
   4994        nnoremap <buffer> <silent> <nowait> gh       :<c-u>call <SID>NetrwHidden(0)<cr>
   4995        nnoremap <buffer> <silent> <nowait> gp       :<c-u>call <SID>NetrwChgPerm(0,b:netrw_curdir)<cr>
   4996        nnoremap <buffer> <silent> <nowait> I        :<c-u>call <SID>NetrwBannerCtrl(1)<cr>
   4997        nnoremap <buffer> <silent> <nowait> i        :<c-u>call <SID>NetrwListStyle(0)<cr>
   4998        nnoremap <buffer> <silent> <nowait> ma       :<c-u>call <SID>NetrwMarkFileArgList(0,0)<cr>
   4999        nnoremap <buffer> <silent> <nowait> mA       :<c-u>call <SID>NetrwMarkFileArgList(0,1)<cr>
   5000        nnoremap <buffer> <silent> <nowait> mb       :<c-u>call <SID>NetrwBookHistHandler(0,b:netrw_curdir)<cr>
   5001        nnoremap <buffer> <silent> <nowait> mB       :<c-u>call <SID>NetrwBookHistHandler(6,b:netrw_curdir)<cr>
   5002        nnoremap <buffer> <silent> <nowait> mc       :<c-u>call <SID>NetrwMarkFileCopy(0)<cr>
   5003        nnoremap <buffer> <silent> <nowait> md       :<c-u>call <SID>NetrwMarkFileDiff(0)<cr>
   5004        nnoremap <buffer> <silent> <nowait> me       :<c-u>call <SID>NetrwMarkFileEdit(0)<cr>
   5005        nnoremap <buffer> <silent> <nowait> mf       :<c-u>call <SID>NetrwMarkFile(0,<SID>NetrwGetWord())<cr>
   5006        nnoremap <buffer> <silent> <nowait> mF       :<c-u>call <SID>NetrwUnmarkList(bufnr("%"),b:netrw_curdir)<cr>
   5007        nnoremap <buffer> <silent> <nowait> mg       :<c-u>call <SID>NetrwMarkFileGrep(0)<cr>
   5008        nnoremap <buffer> <silent> <nowait> mh       :<c-u>call <SID>NetrwMarkHideSfx(0)<cr>
   5009        nnoremap <buffer> <silent> <nowait> mm       :<c-u>call <SID>NetrwMarkFileMove(0)<cr>
   5010        nnoremap <buffer> <silent> <nowait> mr       :<c-u>call <SID>NetrwMarkFileRegexp(0)<cr>
   5011        nnoremap <buffer> <silent> <nowait> ms       :<c-u>call <SID>NetrwMarkFileSource(0)<cr>
   5012        nnoremap <buffer> <silent> <nowait> mT       :<c-u>call <SID>NetrwMarkFileTag(0)<cr>
   5013        nnoremap <buffer> <silent> <nowait> mt       :<c-u>call <SID>NetrwMarkFileTgt(0)<cr>
   5014        nnoremap <buffer> <silent> <nowait> mu       :<c-u>call <SID>NetrwUnMarkFile(0)<cr>
   5015        nnoremap <buffer> <silent> <nowait> mv       :<c-u>call <SID>NetrwMarkFileVimCmd(0)<cr>
   5016        nnoremap <buffer> <silent> <nowait> mx       :<c-u>call <SID>NetrwMarkFileExe(0,0)<cr>
   5017        nnoremap <buffer> <silent> <nowait> mX       :<c-u>call <SID>NetrwMarkFileExe(0,1)<cr>
   5018        nnoremap <buffer> <silent> <nowait> mz       :<c-u>call <SID>NetrwMarkFileCompress(0)<cr>
   5019        nnoremap <buffer> <silent> <nowait> O        :<c-u>call <SID>NetrwObtain(0)<cr>
   5020        nnoremap <buffer> <silent> <nowait> o        :call <SID>NetrwSplit(0)<cr>
   5021        nnoremap <buffer> <silent> <nowait> p        :<c-u>call <SID>NetrwPreview(<SID>NetrwBrowseChgDir(1,<SID>NetrwGetWord(),1,1))<cr>
   5022        nnoremap <buffer> <silent> <nowait> P        :<c-u>call <SID>NetrwPrevWinOpen(0)<cr>
   5023        nnoremap <buffer> <silent> <nowait> qb       :<c-u>call <SID>NetrwBookHistHandler(2,b:netrw_curdir)<cr>
   5024        nnoremap <buffer> <silent> <nowait> qf       :<c-u>call <SID>NetrwFileInfo(0,<SID>NetrwGetWord())<cr>
   5025        nnoremap <buffer> <silent> <nowait> qF       :<c-u>call <SID>NetrwMarkFileQFEL(0,getqflist())<cr>
   5026        nnoremap <buffer> <silent> <nowait> qL       :<c-u>call <SID>NetrwMarkFileQFEL(0,getloclist(v:count))<cr>
   5027        nnoremap <buffer> <silent> <nowait> r        :<c-u>let g:netrw_sort_direction= (g:netrw_sort_direction =~# 'n')? 'r' : 'n'<bar>exe "norm! 0"<bar>call <SID>NetrwBrowse(0,<SID>NetrwBrowseChgDir(0,'./',0))<cr>
   5028        nnoremap <buffer> <silent> <nowait> s        :call <SID>NetrwSortStyle(0)<cr>
   5029        nnoremap <buffer> <silent> <nowait> S        :<c-u>call <SID>NetSortSequence(0)<cr>
   5030        nnoremap <buffer> <silent> <nowait> Tb       :<c-u>call <SID>NetrwSetTgt(0,'b',v:count1)<cr>
   5031        nnoremap <buffer> <silent> <nowait> t        :call <SID>NetrwSplit(1)<cr>
   5032        nnoremap <buffer> <silent> <nowait> Th       :<c-u>call <SID>NetrwSetTgt(0,'h',v:count)<cr>
   5033        nnoremap <buffer> <silent> <nowait> u        :<c-u>call <SID>NetrwBookHistHandler(4,b:netrw_curdir)<cr>
   5034        nnoremap <buffer> <silent> <nowait> U        :<c-u>call <SID>NetrwBookHistHandler(5,b:netrw_curdir)<cr>
   5035        nnoremap <buffer> <silent> <nowait> v        :call <SID>NetrwSplit(2)<cr>
   5036        if !hasmapto('<Plug>NetrwHideEdit')
   5037            nmap <buffer> <c-h> <Plug>NetrwHideEdit
   5038        endif
   5039        nnoremap <buffer> <silent> <Plug>NetrwHideEdit       :call <SID>NetrwHideEdit(0)<cr>
   5040        if !hasmapto('<Plug>NetrwRefresh')
   5041            nmap <buffer> <c-l> <Plug>NetrwRefresh
   5042        endif
   5043        if !hasmapto('<Plug>NetrwTreeSqueeze')
   5044            nmap <buffer> <silent> <nowait> <s-cr>      <Plug>NetrwTreeSqueeze
   5045        endif
   5046        nnoremap <buffer> <silent> <Plug>NetrwTreeSqueeze    :call <SID>TreeSqueezeDir(0)<cr>
   5047 
   5048        let mapsafepath     = escape(s:path, s:netrw_map_escape)
   5049        let mapsafeusermach = escape(((s:user == "")? "" : s:user."@").s:machine, s:netrw_map_escape)
   5050 
   5051        nnoremap <buffer> <silent> <Plug>NetrwRefresh        :call <SID>NetrwRefresh(0,<SID>NetrwBrowseChgDir(0,'./',0))<cr>
   5052        if g:netrw_mousemaps == 1
   5053            nmap <buffer> <leftmouse>           <Plug>NetrwLeftmouse
   5054            nno  <buffer> <silent>              <Plug>NetrwLeftmouse    :exec "norm! \<lt>leftmouse>"<bar>call <SID>NetrwLeftmouse(0)<cr>
   5055            nmap <buffer> <c-leftmouse>         <Plug>NetrwCLeftmouse
   5056            nno  <buffer> <silent>              <Plug>NetrwCLeftmouse   :exec "norm! \<lt>leftmouse>"<bar>call <SID>NetrwCLeftmouse(0)<cr>
   5057            nmap <buffer> <s-leftmouse>         <Plug>NetrwSLeftmouse
   5058            nno  <buffer> <silent>              <Plug>NetrwSLeftmouse   :exec "norm! \<lt>leftmouse>"<bar>call <SID>NetrwSLeftmouse(0)<cr>
   5059            nmap <buffer> <s-leftdrag>          <Plug>NetrwSLeftdrag
   5060            nno  <buffer> <silent>              <Plug>NetrwSLeftdrag    :exec "norm! \<lt>leftmouse>"<bar>call <SID>NetrwSLeftdrag(0)<cr>
   5061            nmap <middlemouse>                  <Plug>NetrwMiddlemouse
   5062            nno  <buffer> <silent>              <middlemouse>           <Plug>NetrwMiddlemouse :exec "norm! \<lt>leftmouse>"<bar>call <SID>NetrwPrevWinOpen(0)<cr>
   5063            nmap <buffer> <2-leftmouse>         <Plug>Netrw2Leftmouse
   5064            nmap <buffer> <silent>              <Plug>Netrw2Leftmouse   -
   5065                imap <buffer> <leftmouse>           <Plug>ILeftmouse
   5066            imap <buffer> <middlemouse>         <Plug>IMiddlemouse
   5067            imap <buffer> <s-leftmouse>         <Plug>ISLeftmouse
   5068            exe 'nnoremap <buffer> <silent> <rightmouse> :exec "norm! \<lt>leftmouse>"<bar>call <SID>NetrwRemoteRm("'.mapsafeusermach.'","'.mapsafepath.'")<cr>'
   5069            exe 'vnoremap <buffer> <silent> <rightmouse> :exec "norm! \<lt>leftmouse>"<bar>call <SID>NetrwRemoteRm("'.mapsafeusermach.'","'.mapsafepath.'")<cr>'
   5070        endif
   5071        exe 'nnoremap <buffer> <silent> <nowait> <del>       :call <SID>NetrwRemoteRm("'.mapsafeusermach.'","'.mapsafepath.'")<cr>'
   5072        exe 'nnoremap <buffer> <silent> <nowait> d           :call <SID>NetrwMakeDir("'.mapsafeusermach.'")<cr>'
   5073        exe 'nnoremap <buffer> <silent> <nowait> D           :call <SID>NetrwRemoteRm("'.mapsafeusermach.'","'.mapsafepath.'")<cr>'
   5074        exe 'nnoremap <buffer> <silent> <nowait> R           :call <SID>NetrwRemoteRename("'.mapsafeusermach.'","'.mapsafepath.'")<cr>'
   5075        exe 'vnoremap <buffer> <silent> <nowait> <del>       :call <SID>NetrwRemoteRm("'.mapsafeusermach.'","'.mapsafepath.'")<cr>'
   5076        exe 'vnoremap <buffer> <silent> <nowait> D           :call <SID>NetrwRemoteRm("'.mapsafeusermach.'","'.mapsafepath.'")<cr>'
   5077        exe 'vnoremap <buffer> <silent> <nowait> R           :call <SID>NetrwRemoteRename("'.mapsafeusermach.'","'.mapsafepath.'")<cr>'
   5078        nnoremap <buffer> <F1>                       :he netrw-quickhelp<cr>
   5079 
   5080        " support user-specified maps
   5081        call netrw#UserMaps(0)
   5082    endif " }}}3
   5083 endfunction
   5084 
   5085 " s:NetrwCommands: set up commands                              {{{2
   5086 "  If -buffer, the command is only available from within netrw buffers
   5087 "  Otherwise, the command is available from any window, so long as netrw
   5088 "  has been used at least once in the session.
   5089 function s:NetrwCommands(islocal)
   5090 
   5091    com! -nargs=* -complete=file -bang    NetrwMB call s:NetrwBookmark(<bang>0,<f-args>)
   5092    com! -nargs=*                         NetrwC  call s:NetrwSetChgwin(<q-args>)
   5093    com! Rexplore if exists("w:netrw_rexlocal")|call s:NetrwRexplore(w:netrw_rexlocal,exists("w:netrw_rexdir")? w:netrw_rexdir : ".")|else|call netrw#msg#Notify('WARNING', "win#".winnr()." not a former netrw window")|endif
   5094    if a:islocal
   5095        com! -buffer -nargs=+ -complete=file MF      call s:NetrwMarkFiles(1,<f-args>)
   5096    else
   5097        com! -buffer -nargs=+ -complete=file MF      call s:NetrwMarkFiles(0,<f-args>)
   5098    endif
   5099    com! -buffer -nargs=? -complete=file  MT      call s:NetrwMarkTarget(<q-args>)
   5100 
   5101 endfunction
   5102 
   5103 " s:NetrwMarkFiles: apply s:NetrwMarkFile() to named file(s) {{{2
   5104 "                   glob()ing only works with local files
   5105 function s:NetrwMarkFiles(islocal,...)
   5106    let curdir = s:NetrwGetCurdir(a:islocal)
   5107    let i      = 1
   5108    while i <= a:0
   5109        if a:islocal
   5110            let mffiles= glob(a:{i}, 0, 1, 1)
   5111        else
   5112            let mffiles= [a:{i}]
   5113        endif
   5114        for mffile in mffiles
   5115            call s:NetrwMarkFile(a:islocal,mffile)
   5116        endfor
   5117        let i= i + 1
   5118    endwhile
   5119 endfunction
   5120 
   5121 " s:NetrwMarkTarget: implements :MT (mark target) {{{2
   5122 function s:NetrwMarkTarget(...)
   5123    if a:0 == 0 || (a:0 == 1 && a:1 == "")
   5124        let curdir = s:NetrwGetCurdir(1)
   5125        let tgt    = b:netrw_curdir
   5126    else
   5127        let curdir = s:NetrwGetCurdir((a:1 =~ '^\a\{3,}://')? 0 : 1)
   5128        let tgt    = a:1
   5129    endif
   5130    let s:netrwmftgt         = tgt
   5131    let s:netrwmftgt_islocal = tgt !~ '^\a\{3,}://'
   5132    let curislocal           = b:netrw_curdir !~ '^\a\{3,}://'
   5133    let svpos                = winsaveview()
   5134    call s:NetrwRefresh(curislocal,s:NetrwBrowseChgDir(curislocal,'./',0))
   5135    call winrestview(svpos)
   5136 endfunction
   5137 
   5138 " s:NetrwMarkFile: (invoked by mf) This function is used to both {{{2
   5139 "                  mark and unmark files.  If a markfile list exists,
   5140 "                  then the rename and delete functions will use it instead
   5141 "                  of whatever may happen to be under the cursor at that
   5142 "                  moment.  When the mouse and gui are available,
   5143 "                  shift-leftmouse may also be used to mark files.
   5144 "
   5145 "  Creates two lists
   5146 "    s:netrwmarkfilelist    -- holds complete paths to all marked files
   5147 "    s:netrwmarkfilelist_#  -- holds list of marked files in current-buffer's directory (#==bufnr())
   5148 "
   5149 "  Creates a marked file match string
   5150 "    s:netrwmarfilemtch_#   -- used with 2match to display marked files
   5151 "
   5152 "  Creates a buffer version of islocal
   5153 "    b:netrw_islocal
   5154 function s:NetrwMarkFile(islocal,fname)
   5155 
   5156    " sanity check
   5157    if empty(a:fname)
   5158        return
   5159    endif
   5160    let curdir = s:NetrwGetCurdir(a:islocal)
   5161 
   5162    let ykeep   = @@
   5163    let curbufnr= bufnr("%")
   5164    let leader= '\%(^\|\s\)\zs'
   5165    if a:fname =~ '\a$'
   5166        let trailer = '\>[@=|\/\*]\=\ze\%(  \|\t\|$\)'
   5167    else
   5168        let trailer = '[@=|\/\*]\=\ze\%(  \|\t\|$\)'
   5169    endif
   5170 
   5171    if exists("s:netrwmarkfilelist_".curbufnr)
   5172        " markfile list pre-exists
   5173        let b:netrw_islocal= a:islocal
   5174 
   5175        if index(s:netrwmarkfilelist_{curbufnr},a:fname) == -1
   5176            " append filename to buffer's markfilelist
   5177            call add(s:netrwmarkfilelist_{curbufnr},a:fname)
   5178            let s:netrwmarkfilemtch_{curbufnr}= s:netrwmarkfilemtch_{curbufnr}.'\|'.leader.escape(a:fname,g:netrw_markfileesc).trailer
   5179 
   5180        else
   5181            " remove filename from buffer's markfilelist
   5182            call filter(s:netrwmarkfilelist_{curbufnr},'v:val != a:fname')
   5183            if s:netrwmarkfilelist_{curbufnr} == []
   5184                " local markfilelist is empty; remove it entirely
   5185                call s:NetrwUnmarkList(curbufnr,curdir)
   5186            else
   5187                " rebuild match list to display markings correctly
   5188                let s:netrwmarkfilemtch_{curbufnr}= ""
   5189                let first                         = 1
   5190                for fname in s:netrwmarkfilelist_{curbufnr}
   5191                    if first
   5192                        let s:netrwmarkfilemtch_{curbufnr}= s:netrwmarkfilemtch_{curbufnr}.leader.escape(fname,g:netrw_markfileesc).trailer
   5193                    else
   5194                        let s:netrwmarkfilemtch_{curbufnr}= s:netrwmarkfilemtch_{curbufnr}.'\|'.leader.escape(fname,g:netrw_markfileesc).trailer
   5195                    endif
   5196                    let first= 0
   5197                endfor
   5198            endif
   5199        endif
   5200 
   5201    else
   5202        " initialize new markfilelist
   5203 
   5204        let s:netrwmarkfilelist_{curbufnr}= []
   5205        call add(s:netrwmarkfilelist_{curbufnr},substitute(a:fname,'[|@]$','',''))
   5206 
   5207        " build initial markfile matching pattern
   5208        if a:fname =~ '/$'
   5209            let s:netrwmarkfilemtch_{curbufnr}= leader.escape(a:fname,g:netrw_markfileesc)
   5210        else
   5211            let s:netrwmarkfilemtch_{curbufnr}= leader.escape(a:fname,g:netrw_markfileesc).trailer
   5212        endif
   5213    endif
   5214 
   5215    " handle global markfilelist
   5216    if exists("s:netrwmarkfilelist")
   5217        let dname= netrw#fs#ComposePath(b:netrw_curdir,a:fname)
   5218        if index(s:netrwmarkfilelist,dname) == -1
   5219            " append new filename to global markfilelist
   5220            call add(s:netrwmarkfilelist,netrw#fs#ComposePath(b:netrw_curdir,a:fname))
   5221        else
   5222            " remove new filename from global markfilelist
   5223            call filter(s:netrwmarkfilelist,'v:val != "'.dname.'"')
   5224            if s:netrwmarkfilelist == []
   5225                unlet s:netrwmarkfilelist
   5226            endif
   5227        endif
   5228    else
   5229        " initialize new global-directory markfilelist
   5230        let s:netrwmarkfilelist= []
   5231        call add(s:netrwmarkfilelist,netrw#fs#ComposePath(b:netrw_curdir,a:fname))
   5232    endif
   5233 
   5234    " set up 2match'ing to netrwmarkfilemtch_# list
   5235    if has("syntax") && exists("g:syntax_on") && g:syntax_on
   5236        if exists("s:netrwmarkfilemtch_{curbufnr}") && s:netrwmarkfilemtch_{curbufnr} != ""
   5237            if exists("g:did_drchip_netrwlist_syntax")
   5238                exe "2match netrwMarkFile /".s:netrwmarkfilemtch_{curbufnr}."/"
   5239            endif
   5240        else
   5241            2match none
   5242        endif
   5243    endif
   5244    let @@= ykeep
   5245 endfunction
   5246 
   5247 " s:NetrwMarkFileArgList: ma: move the marked file list to the argument list (tomflist=0) {{{2
   5248 "                         mA: move the argument list to marked file list     (tomflist=1)
   5249 "                            Uses the global marked file list
   5250 function s:NetrwMarkFileArgList(islocal,tomflist)
   5251    let svpos    = winsaveview()
   5252    let curdir   = s:NetrwGetCurdir(a:islocal)
   5253    let curbufnr = bufnr("%")
   5254 
   5255    if a:tomflist
   5256        " mA: move argument list to marked file list
   5257        while argc()
   5258            let fname= argv(0)
   5259            exe "argdel ".fnameescape(fname)
   5260            call s:NetrwMarkFile(a:islocal,fname)
   5261        endwhile
   5262 
   5263    else
   5264        " ma: move marked file list to argument list
   5265        if exists("s:netrwmarkfilelist")
   5266 
   5267            " for every filename in the marked list
   5268            for fname in s:netrwmarkfilelist
   5269                exe "argadd ".fnameescape(fname)
   5270            endfor      " for every file in the marked list
   5271 
   5272            " unmark list and refresh
   5273            call s:NetrwUnmarkList(curbufnr,curdir)
   5274            NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./',0))
   5275            NetrwKeepj call winrestview(svpos)
   5276        endif
   5277    endif
   5278 endfunction
   5279 
   5280 " s:NetrwMarkFileCompress: (invoked by mz) This function is used to {{{2
   5281 "                          compress/decompress files using the programs
   5282 "                          in g:netrw_compress and g:netrw_uncompress,
   5283 "                          using g:netrw_compress_suffix to know which to
   5284 "                          do.  By default:
   5285 "                            g:netrw_compress        = "gzip"
   5286 "                            g:netrw_decompress      = { ".gz" : "gunzip" , ".bz2" : "bunzip2" , ".zip" : "unzip" , ".tar" : "tar -xf", ".xz" : "unxz"}
   5287 function s:NetrwMarkFileCompress(islocal)
   5288    let svpos    = winsaveview()
   5289    let curdir   = s:NetrwGetCurdir(a:islocal)
   5290    let curbufnr = bufnr("%")
   5291 
   5292    " sanity check
   5293    if !exists("s:netrwmarkfilelist_{curbufnr}") || empty(s:netrwmarkfilelist_{curbufnr})
   5294        call netrw#msg#Notify('ERROR', 'there are no marked files in this window (:help netrw-mf)')
   5295        return
   5296    endif
   5297 
   5298    if exists("s:netrwmarkfilelist_{curbufnr}") && exists("g:netrw_compress") && exists("g:netrw_decompress")
   5299 
   5300        " for every filename in the marked list
   5301        for fname in s:netrwmarkfilelist_{curbufnr}
   5302            let sfx= substitute(fname,'^.\{-}\(\.[[:alnum:]]\+\)$','\1','')
   5303            if exists("g:netrw_decompress['".sfx."']")
   5304                " fname has a suffix indicating that its compressed; apply associated decompression routine
   5305                let exe= g:netrw_decompress[sfx]
   5306                let exe= netrw#fs#WinPath(exe)
   5307                if a:islocal
   5308                    if g:netrw_keepdir
   5309                        let fname= netrw#os#Escape(netrw#fs#ComposePath(curdir,fname))
   5310                    endif
   5311                    call system(exe." ".fname)
   5312                    if v:shell_error
   5313                        call netrw#msg#Notify('WARNING', printf('unable to apply<%s> to file<%s>', exe, fname))
   5314                    endif
   5315                else
   5316                    let fname= netrw#os#Escape(b:netrw_curdir.fname,1)
   5317                    NetrwKeepj call s:RemoteSystem(exe." ".fname)
   5318                endif
   5319 
   5320            endif
   5321            unlet sfx
   5322 
   5323            if exists("exe")
   5324                unlet exe
   5325            elseif a:islocal
   5326                " fname not a compressed file, so compress it
   5327                call system(netrw#fs#WinPath(g:netrw_compress)." ".netrw#os#Escape(netrw#fs#ComposePath(b:netrw_curdir,fname)))
   5328                if v:shell_error
   5329                    call netrw#msg#Notify('WARNING', printf('consider setting g:netrw_compress<%s> to something that works', g:netrw_compress))
   5330                endif
   5331            else
   5332                " fname not a compressed file, so compress it
   5333                NetrwKeepj call s:RemoteSystem(netrw#fs#WinPath(g:netrw_compress)." ".netrw#os#Escape(fname))
   5334            endif
   5335        endfor       " for every file in the marked list
   5336 
   5337        call s:NetrwUnmarkList(curbufnr,curdir)
   5338        NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./',0))
   5339        NetrwKeepj call winrestview(svpos)
   5340    endif
   5341 endfunction
   5342 
   5343 " s:NetrwMarkFileCopy: (invoked by mc) copy marked files to target {{{2
   5344 "                      If no marked files, then set up directory as the
   5345 "                      target.  Currently does not support copying entire
   5346 "                      directories.  Uses the local-buffer marked file list.
   5347 "                      Returns 1=success  (used by NetrwMarkFileMove())
   5348 "                              0=failure
   5349 function s:NetrwMarkFileCopy(islocal,...)
   5350 
   5351    let curdir   = s:NetrwGetCurdir(a:islocal)
   5352    let curbufnr = bufnr("%")
   5353    if b:netrw_curdir !~ '/$'
   5354        if !exists("b:netrw_curdir")
   5355            let b:netrw_curdir= curdir
   5356        endif
   5357        let b:netrw_curdir= b:netrw_curdir."/"
   5358    endif
   5359 
   5360    " sanity check
   5361    if !exists("s:netrwmarkfilelist_{curbufnr}") || empty(s:netrwmarkfilelist_{curbufnr})
   5362        call netrw#msg#Notify('ERROR', 'there are no marked files in this window (:help netrw-mf)')
   5363        return
   5364    endif
   5365 
   5366    if !exists("s:netrwmftgt")
   5367        call netrw#msg#Notify('ERROR', 'your marked file target is empty! (:help netrw-mt)')
   5368        return 0
   5369    endif
   5370 
   5371    if a:islocal &&  s:netrwmftgt_islocal
   5372        " Copy marked files, local directory to local directory
   5373        if !executable(g:netrw_localcopycmd)
   5374            call netrw#msg#Notify('ERROR', printf('g:netrw_localcopycmd<%s> not executable on your system, aborting', g:netrw_localcopycmd))
   5375            return
   5376        endif
   5377 
   5378        " copy marked files while within the same directory (ie. allow renaming)
   5379        if simplify(s:netrwmftgt) ==# simplify(b:netrw_curdir)
   5380            if len(s:netrwmarkfilelist_{bufnr('%')}) == 1
   5381                " only one marked file
   5382                let args    = netrw#os#Escape(b:netrw_curdir.s:netrwmarkfilelist_{bufnr('%')}[0])
   5383                let oldname = s:netrwmarkfilelist_{bufnr('%')}[0]
   5384            elseif a:0 == 1
   5385                " this happens when the next case was used to recursively call s:NetrwMarkFileCopy()
   5386                let args    = netrw#os#Escape(b:netrw_curdir.a:1)
   5387                let oldname = a:1
   5388            else
   5389                " copy multiple marked files inside the same directory
   5390                let s:recursive= 1
   5391                for oldname in s:netrwmarkfilelist_{bufnr("%")}
   5392                    let ret= s:NetrwMarkFileCopy(a:islocal,oldname)
   5393                    if ret == 0
   5394                        break
   5395                    endif
   5396                endfor
   5397                unlet s:recursive
   5398                call s:NetrwUnmarkList(curbufnr,curdir)
   5399                return ret
   5400            endif
   5401 
   5402            call inputsave()
   5403            let newname= input(printf("Copy %s to: ", oldname), oldname, 'file')
   5404            call inputrestore()
   5405 
   5406            if empty(newname)
   5407                return 0
   5408            endif
   5409 
   5410            let args = netrw#os#Escape(oldname)
   5411            let tgt = netrw#os#Escape(s:netrwmftgt.'/'.newname)
   5412        else
   5413            let args = join(map(deepcopy(s:netrwmarkfilelist_{bufnr('%')}),"netrw#os#Escape(b:netrw_curdir.\"/\".v:val)"))
   5414            let tgt = netrw#os#Escape(s:netrwmftgt)
   5415        endif
   5416 
   5417        if !g:netrw_cygwin && has("win32")
   5418            let args = substitute(args,'/','\\','g')
   5419            let tgt = substitute(tgt, '/','\\','g')
   5420        endif
   5421 
   5422        if args =~ "'" |let args= substitute(args,"'\\(.*\\)'",'\1','')|endif
   5423        if tgt  =~ "'" |let tgt = substitute(tgt ,"'\\(.*\\)'",'\1','')|endif
   5424        if args =~ '//'|let args= substitute(args,'//','/','g')|endif
   5425        if tgt  =~ '//'|let tgt = substitute(tgt ,'//','/','g')|endif
   5426 
   5427        let copycmd = g:netrw_localcopycmd
   5428        let copycmdopt = g:netrw_localcopycmdopt
   5429 
   5430        if isdirectory(s:NetrwFile(args))
   5431            let copycmd = g:netrw_localcopydircmd
   5432            let copycmdopt = g:netrw_localcopydircmdopt
   5433            if has('win32') && !g:netrw_cygwin
   5434                " window's xcopy doesn't copy a directory to a target properly.  Instead, it copies a directory's
   5435                " contents to a target.  One must append the source directory name to the target to get xcopy to
   5436                " do the right thing.
   5437                let tgt= tgt.'\'.substitute(a:1,'^.*[\\/]','','')
   5438            endif
   5439        endif
   5440 
   5441        call system(printf("%s %s '%s' '%s'", copycmd, copycmdopt, args, tgt))
   5442        if v:shell_error != 0
   5443            if exists("b:netrw_curdir") && b:netrw_curdir != getcwd() && g:netrw_keepdir
   5444                call netrw#msg#Notify('ERROR', printf("copy failed; perhaps due to vim's current directory<%s> not matching netrw's (%s) (see :help netrw-cd)", getcwd(), b:netrw_curdir))
   5445            else
   5446                call netrw#msg#Notify('ERROR', printf("tried using g:netrw_localcopycmd<%s>; it doesn't work!", g:netrw_localcopycmd))
   5447            endif
   5448            return 0
   5449        endif
   5450 
   5451    elseif  a:islocal && !s:netrwmftgt_islocal
   5452        " Copy marked files, local directory to remote directory
   5453        NetrwKeepj call s:NetrwUpload(s:netrwmarkfilelist_{bufnr('%')},s:netrwmftgt)
   5454 
   5455    elseif !a:islocal &&  s:netrwmftgt_islocal
   5456        " Copy marked files, remote directory to local directory
   5457        NetrwKeepj call netrw#Obtain(a:islocal,s:netrwmarkfilelist_{bufnr('%')},s:netrwmftgt)
   5458 
   5459    elseif !a:islocal && !s:netrwmftgt_islocal
   5460        " Copy marked files, remote directory to remote directory
   5461        let curdir = getcwd()
   5462        let tmpdir = s:GetTempfile("")
   5463        if tmpdir !~ '/'
   5464            let tmpdir= curdir."/".tmpdir
   5465        endif
   5466        if exists("*mkdir")
   5467            call mkdir(tmpdir)
   5468        else
   5469            call netrw#os#Execute("sil! !".g:netrw_localmkdir.g:netrw_localmkdiropt.' '.netrw#os#Escape(tmpdir,1))
   5470            if v:shell_error != 0
   5471                call netrw#msg#Notify('WARNING', printf("consider setting g:netrw_localmkdir<%s> to something that works", g:netrw_localmkdir))
   5472                return
   5473            endif
   5474        endif
   5475        if isdirectory(s:NetrwFile(tmpdir))
   5476            if s:NetrwLcd(tmpdir)
   5477                return
   5478            endif
   5479            NetrwKeepj call netrw#Obtain(a:islocal,s:netrwmarkfilelist_{bufnr('%')},tmpdir)
   5480            let localfiles= map(deepcopy(s:netrwmarkfilelist_{bufnr('%')}),'substitute(v:val,"^.*/","","")')
   5481            NetrwKeepj call s:NetrwUpload(localfiles,s:netrwmftgt)
   5482            if getcwd() == tmpdir
   5483                for fname in s:netrwmarkfilelist_{bufnr('%')}
   5484                    call netrw#fs#Remove(fname)
   5485                endfor
   5486                if s:NetrwLcd(curdir)
   5487                    return
   5488                endif
   5489                if delete(tmpdir,"d")
   5490                    call netrw#msg#Notify('ERROR', printf('unable to delete directory <%s>!', tmpdir))
   5491                endif
   5492            else
   5493                if s:NetrwLcd(curdir)
   5494                    return
   5495                endif
   5496            endif
   5497        endif
   5498    endif
   5499 
   5500    " -------
   5501    " cleanup
   5502    " -------
   5503    " remove markings from local buffer
   5504    call s:NetrwUnmarkList(curbufnr,curdir)                   " remove markings from local buffer
   5505    if exists("s:recursive")
   5506    else
   5507    endif
   5508    " see s:LocalFastBrowser() for g:netrw_fastbrowse interpretation (refreshing done for both slow and medium)
   5509    if g:netrw_fastbrowse <= 1
   5510        NetrwKeepj call s:LocalBrowseRefresh()
   5511    else
   5512        " refresh local and targets for fast browsing
   5513        if !exists("s:recursive")
   5514            " remove markings from local buffer
   5515            NetrwKeepj call s:NetrwUnmarkList(curbufnr,curdir)
   5516        endif
   5517 
   5518        " refresh buffers
   5519        if s:netrwmftgt_islocal
   5520            NetrwKeepj call s:NetrwRefreshDir(s:netrwmftgt_islocal,s:netrwmftgt)
   5521        endif
   5522        if a:islocal && s:netrwmftgt != curdir
   5523            NetrwKeepj call s:NetrwRefreshDir(a:islocal,curdir)
   5524        endif
   5525    endif
   5526 
   5527    return 1
   5528 endfunction
   5529 
   5530 " s:NetrwMarkFileDiff: (invoked by md) This function is used to {{{2
   5531 "                      invoke vim's diff mode on the marked files.
   5532 "                      Either two or three files can be so handled.
   5533 "                      Uses the global marked file list.
   5534 function s:NetrwMarkFileDiff(islocal)
   5535    let curbufnr= bufnr("%")
   5536 
   5537    " sanity check
   5538    if !exists("s:netrwmarkfilelist_{curbufnr}") || empty(s:netrwmarkfilelist_{curbufnr})
   5539        call netrw#msg#Notify('ERROR', 'there are no marked files in this window (:help netrw-mf)')
   5540        return
   5541    endif
   5542    let curdir= s:NetrwGetCurdir(a:islocal)
   5543 
   5544    if exists("s:netrwmarkfilelist_{".curbufnr."}")
   5545        let cnt    = 0
   5546        for fname in s:netrwmarkfilelist
   5547            let cnt= cnt + 1
   5548            if cnt == 1
   5549                exe "NetrwKeepj e ".fnameescape(fname)
   5550                diffthis
   5551            elseif cnt == 2 || cnt == 3
   5552                below vsplit
   5553                exe "NetrwKeepj e ".fnameescape(fname)
   5554                diffthis
   5555            else
   5556                break
   5557            endif
   5558        endfor
   5559        call s:NetrwUnmarkList(curbufnr,curdir)
   5560    endif
   5561 
   5562 endfunction
   5563 
   5564 " s:NetrwMarkFileEdit: (invoked by me) put marked files on arg list and start editing them {{{2
   5565 "                       Uses global markfilelist
   5566 function s:NetrwMarkFileEdit(islocal)
   5567 
   5568    let curdir   = s:NetrwGetCurdir(a:islocal)
   5569    let curbufnr = bufnr("%")
   5570 
   5571    " sanity check
   5572    if !exists("s:netrwmarkfilelist_{curbufnr}") || empty(s:netrwmarkfilelist_{curbufnr})
   5573        call netrw#msg#Notify('ERROR', 'there are no marked files in this window (:help netrw-mf)')
   5574        return
   5575    endif
   5576 
   5577    if exists("s:netrwmarkfilelist_{curbufnr}")
   5578        call s:SetRexDir(a:islocal,curdir)
   5579        let flist= join(map(deepcopy(s:netrwmarkfilelist), "fnameescape(v:val)"))
   5580        " unmark markedfile list
   5581        "   call s:NetrwUnmarkList(curbufnr,curdir)
   5582        call s:NetrwUnmarkAll()
   5583        exe "sil args ".flist
   5584    endif
   5585    echo "(use :bn, :bp to navigate files; :Rex to return)"
   5586 
   5587 endfunction
   5588 
   5589 " s:NetrwMarkFileQFEL: convert a quickfix-error or location list into a marked file list {{{2
   5590 function s:NetrwMarkFileQFEL(islocal,qfel)
   5591    call s:NetrwUnmarkAll()
   5592    let curbufnr= bufnr("%")
   5593 
   5594    if !empty(a:qfel)
   5595        for entry in a:qfel
   5596            let bufnmbr= entry["bufnr"]
   5597            if !exists("s:netrwmarkfilelist_{curbufnr}")
   5598                call s:NetrwMarkFile(a:islocal,bufname(bufnmbr))
   5599            elseif index(s:netrwmarkfilelist_{curbufnr},bufname(bufnmbr)) == -1
   5600                " s:NetrwMarkFile will remove duplicate entries from the marked file list.
   5601                " So, this test lets two or more hits on the same pattern to be ignored.
   5602                call s:NetrwMarkFile(a:islocal,bufname(bufnmbr))
   5603            else
   5604            endif
   5605        endfor
   5606        echo "(use me to edit marked files)"
   5607    else
   5608        call netrw#msg#Notify('WARNING', "can't convert quickfix error list; its empty!")
   5609    endif
   5610 
   5611 endfunction
   5612 
   5613 " s:NetrwMarkFileExe: (invoked by mx and mX) execute arbitrary system command on marked files {{{2
   5614 "                     mx enbloc=0: Uses the local marked-file list, applies command to each file individually
   5615 "                     mX enbloc=1: Uses the global marked-file list, applies command to entire list
   5616 function s:NetrwMarkFileExe(islocal,enbloc)
   5617    let svpos    = winsaveview()
   5618    let curdir   = s:NetrwGetCurdir(a:islocal)
   5619    let curbufnr = bufnr("%")
   5620 
   5621    if a:enbloc == 0
   5622        " individually apply command to files, one at a time
   5623        " sanity check
   5624        if !exists("s:netrwmarkfilelist_{curbufnr}") || empty(s:netrwmarkfilelist_{curbufnr})
   5625            call netrw#msg#Notify('ERROR', 'there are no marked files in this window (:help netrw-mf)')
   5626            return
   5627        endif
   5628 
   5629        if exists("s:netrwmarkfilelist_{curbufnr}")
   5630            " get the command
   5631            call inputsave()
   5632            let cmd= input("Enter command: ","","file")
   5633            call inputrestore()
   5634            if cmd == ""
   5635                return
   5636            endif
   5637 
   5638            " apply command to marked files, individually.  Substitute: filename -> %
   5639            " If no %, then append a space and the filename to the command
   5640            for fname in s:netrwmarkfilelist_{curbufnr}
   5641                if a:islocal
   5642                    if g:netrw_keepdir
   5643                        let fname= netrw#os#Escape(netrw#fs#WinPath(netrw#fs#ComposePath(curdir,fname)))
   5644                    endif
   5645                else
   5646                    let fname= netrw#os#Escape(netrw#fs#WinPath(b:netrw_curdir.fname))
   5647                endif
   5648                if cmd =~ '%'
   5649                    let xcmd= substitute(cmd,'%',fname,'g')
   5650                else
   5651                    let xcmd= cmd.' '.fname
   5652                endif
   5653                if a:islocal
   5654                    let ret= system(xcmd)
   5655                else
   5656                    let ret= s:RemoteSystem(xcmd)
   5657                endif
   5658                if v:shell_error < 0
   5659                    call netrw#msg#Notify('ERROR', printf('command<%s> failed, aborting', xcmd))
   5660                    break
   5661                else
   5662                    if ret !=# ''
   5663                        echo "\n"
   5664                        " skip trailing new line
   5665                        echo ret[0:-2]
   5666                    else
   5667                        echo ret
   5668                    endif
   5669                endif
   5670            endfor
   5671 
   5672            " unmark marked file list
   5673            call s:NetrwUnmarkList(curbufnr,curdir)
   5674 
   5675            " refresh the listing
   5676            NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./',0))
   5677            NetrwKeepj call winrestview(svpos)
   5678        else
   5679            call netrw#msg#Notify('ERROR', 'no files marked!')
   5680        endif
   5681 
   5682    else " apply command to global list of files, en bloc
   5683 
   5684        call inputsave()
   5685        let cmd= input("Enter command: ","","file")
   5686        call inputrestore()
   5687        if cmd == ""
   5688            return
   5689        endif
   5690        if cmd =~ '%'
   5691            let cmd= substitute(cmd,'%',join(map(s:netrwmarkfilelist,'netrw#os#Escape(v:val)'),' '),'g')
   5692        else
   5693            let cmd= cmd.' '.join(map(s:netrwmarkfilelist,'netrw#os#Escape(v:val)'),' ')
   5694        endif
   5695        if a:islocal
   5696            call system(cmd)
   5697            if v:shell_error < 0
   5698                call netrw#msg#Notify('ERROR', printf('command<%s> failed, aborting',xcmd))
   5699            endif
   5700        else
   5701            let ret= s:RemoteSystem(cmd)
   5702        endif
   5703        call s:NetrwUnmarkAll()
   5704 
   5705        " refresh the listing
   5706        NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./',0))
   5707        NetrwKeepj call winrestview(svpos)
   5708 
   5709    endif
   5710 endfunction
   5711 
   5712 " s:NetrwMarkHideSfx: (invoked by mh) (un)hide files having same suffix
   5713 "                  as the marked file(s) (toggles suffix presence)
   5714 "                  Uses the local marked file list.
   5715 function s:NetrwMarkHideSfx(islocal)
   5716    let svpos    = winsaveview()
   5717    let curbufnr = bufnr("%")
   5718 
   5719    " s:netrwmarkfilelist_{curbufnr}: the List of marked files
   5720    if exists("s:netrwmarkfilelist_{curbufnr}")
   5721 
   5722        for fname in s:netrwmarkfilelist_{curbufnr}
   5723            " construct suffix pattern
   5724            if fname =~ '\.'
   5725                let sfxpat= "^.*".substitute(fname,'^.*\(\.[^. ]\+\)$','\1','')
   5726            else
   5727                let sfxpat= '^\%(\%(\.\)\@!.\)*$'
   5728            endif
   5729            " determine if its in the hiding list or not
   5730            let inhidelist= 0
   5731            if g:netrw_list_hide != ""
   5732                let itemnum = 0
   5733                let hidelist= split(g:netrw_list_hide,',')
   5734                for hidepat in hidelist
   5735                    if sfxpat == hidepat
   5736                        let inhidelist= 1
   5737                        break
   5738                    endif
   5739                    let itemnum= itemnum + 1
   5740                endfor
   5741            endif
   5742            if inhidelist
   5743                " remove sfxpat from list
   5744                call remove(hidelist,itemnum)
   5745                let g:netrw_list_hide= join(hidelist,",")
   5746            elseif g:netrw_list_hide != ""
   5747                " append sfxpat to non-empty list
   5748                let g:netrw_list_hide= g:netrw_list_hide.",".sfxpat
   5749            else
   5750                " set hiding list to sfxpat
   5751                let g:netrw_list_hide= sfxpat
   5752            endif
   5753        endfor
   5754 
   5755        " refresh the listing
   5756        NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./',0))
   5757        NetrwKeepj call winrestview(svpos)
   5758    else
   5759        call netrw#msg#Notify('ERROR', 'no files marked!')
   5760    endif
   5761 endfunction
   5762 
   5763 " s:NetrwMarkFileVimCmd: (invoked by mv) execute arbitrary vim command on marked files, one at a time {{{2
   5764 "                     Uses the local marked-file list.
   5765 function s:NetrwMarkFileVimCmd(islocal)
   5766    let svpos    = winsaveview()
   5767    let curdir   = s:NetrwGetCurdir(a:islocal)
   5768    let curbufnr = bufnr("%")
   5769 
   5770    " sanity check
   5771    if !exists("s:netrwmarkfilelist_{curbufnr}") || empty(s:netrwmarkfilelist_{curbufnr})
   5772        call netrw#msg#Notify('ERROR', 'there are no marked files in this window (:help netrw-mf)')
   5773        return
   5774    endif
   5775 
   5776    if exists("s:netrwmarkfilelist_{curbufnr}")
   5777        " get the command
   5778        call inputsave()
   5779        let cmd= input("Enter vim command: ","","file")
   5780        call inputrestore()
   5781        if cmd == ""
   5782            return
   5783        endif
   5784 
   5785        " apply command to marked files.  Substitute: filename -> %
   5786        " If no %, then append a space and the filename to the command
   5787        for fname in s:netrwmarkfilelist_{curbufnr}
   5788            if a:islocal
   5789                1split
   5790                exe "sil! NetrwKeepj keepalt e ".fnameescape(fname)
   5791                exe cmd
   5792                exe "sil! keepalt wq!"
   5793            else
   5794                echo "sorry, \"mv\" not supported yet for remote files"
   5795            endif
   5796        endfor
   5797 
   5798        " unmark marked file list
   5799        call s:NetrwUnmarkList(curbufnr,curdir)
   5800 
   5801        " refresh the listing
   5802        NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./',0))
   5803        NetrwKeepj call winrestview(svpos)
   5804    else
   5805        call netrw#msg#Notify('ERROR', 'no files marked!')
   5806    endif
   5807 endfunction
   5808 
   5809 " s:NetrwMarkFileGrep: (invoked by mg) This function applies vimgrep to marked files {{{2
   5810 "                     Uses the global markfilelist
   5811 function s:NetrwMarkFileGrep(islocal)
   5812    let svpos    = winsaveview()
   5813    let curbufnr = bufnr("%")
   5814    let curdir   = s:NetrwGetCurdir(a:islocal)
   5815 
   5816    if exists("s:netrwmarkfilelist")
   5817        let netrwmarkfilelist= join(map(deepcopy(s:netrwmarkfilelist), "fnameescape(v:val)"))
   5818        call s:NetrwUnmarkAll()
   5819    else
   5820        let netrwmarkfilelist= "*"
   5821    endif
   5822 
   5823    " ask user for pattern
   5824    call inputsave()
   5825    let pat= input("Enter pattern: ","")
   5826    call inputrestore()
   5827    let patbang = ""
   5828    if pat =~ '^!'
   5829        let patbang = "!"
   5830        let pat     = strpart(pat,2)
   5831    endif
   5832    if pat =~ '^\i'
   5833        let pat    = escape(pat,'/')
   5834        let pat    = '/'.pat.'/'
   5835    else
   5836        let nonisi = pat[0]
   5837    endif
   5838 
   5839    " use vimgrep for both local and remote
   5840    try
   5841        exe "NetrwKeepj noautocmd vimgrep".patbang." ".pat." ".netrwmarkfilelist
   5842    catch /^Vim\%((\a\+)\)\=:E480/
   5843        call netrw#msg#Notify('WARNING', printf('no match with pattern<%s>', pat))
   5844        return
   5845    endtry
   5846    echo "(use :cn, :cp to navigate, :Rex to return)"
   5847 
   5848    2match none
   5849    NetrwKeepj call winrestview(svpos)
   5850 
   5851    if exists("nonisi")
   5852        " original, user-supplied pattern did not begin with a character from isident
   5853        if pat =~# nonisi.'j$\|'.nonisi.'gj$\|'.nonisi.'jg$'
   5854            call s:NetrwMarkFileQFEL(a:islocal,getqflist())
   5855        endif
   5856    endif
   5857 
   5858 endfunction
   5859 
   5860 " s:NetrwMarkFileMove: (invoked by mm) execute arbitrary command on marked files, one at a time {{{2
   5861 "                      uses the global marked file list
   5862 "                      s:netrwmfloc= 0: target directory is remote
   5863 "                                  = 1: target directory is local
   5864 function s:NetrwMarkFileMove(islocal)
   5865    let curdir   = s:NetrwGetCurdir(a:islocal)
   5866    let curbufnr = bufnr("%")
   5867 
   5868    " sanity check
   5869    if !exists("s:netrwmarkfilelist_{curbufnr}") || empty(s:netrwmarkfilelist_{curbufnr})
   5870        call netrw#msg#Notify('ERROR', 'there are no marked files in this window (:help netrw-mf)')
   5871        return
   5872    endif
   5873 
   5874    if !exists("s:netrwmftgt")
   5875        call netrw#msg#Notify('ERROR', 'your marked file target is empty! (:help netrw-mt)')
   5876        return 0
   5877    endif
   5878 
   5879    if      a:islocal &&  s:netrwmftgt_islocal
   5880        " move: local -> local
   5881        if !executable(g:netrw_localmovecmd)
   5882            call netrw#msg#Notify('ERROR', printf('g:netrw_localmovecmd<%s> not executable on your system, aborting', g:netrw_localmovecmd))
   5883            return
   5884        endif
   5885        let tgt = netrw#os#Escape(s:netrwmftgt)
   5886        if !g:netrw_cygwin && has("win32")
   5887            let tgt= substitute(tgt, '/','\\','g')
   5888            if g:netrw_localmovecmd =~ '\s'
   5889                let movecmd     = substitute(g:netrw_localmovecmd,'\s.*$','','')
   5890                let movecmdargs = substitute(g:netrw_localmovecmd,'^.\{-}\(\s.*\)$','\1','')
   5891                let movecmd     = netrw#fs#WinPath(movecmd).movecmdargs
   5892            else
   5893                let movecmd = netrw#fs#WinPath(g:netrw_localmovecmd)
   5894            endif
   5895        else
   5896            let movecmd = netrw#fs#WinPath(g:netrw_localmovecmd)
   5897        endif
   5898        for fname in s:netrwmarkfilelist_{bufnr("%")}
   5899            if g:netrw_keepdir
   5900                " Jul 19, 2022: fixing file move when g:netrw_keepdir is 1
   5901                let fname= b:netrw_curdir."/".fname
   5902            endif
   5903            if !g:netrw_cygwin && has("win32")
   5904                let fname= substitute(fname,'/','\\','g')
   5905            endif
   5906            let ret= system(movecmd.g:netrw_localmovecmdopt." ".netrw#os#Escape(fname)." ".tgt)
   5907            if v:shell_error != 0
   5908                if exists("b:netrw_curdir") && b:netrw_curdir != getcwd() && !g:netrw_keepdir
   5909                    call netrw#msg#Notify('ERROR', printf("move failed; perhaps due to vim's current directory<%s> not matching netrw's (%s) (see :help netrw-cd)", getcwd(), b:netrw_curdir))
   5910                else
   5911                    call netrw#msg#Notify('ERROR', printf("tried using g:netrw_localmovecmd<%s>; it doesn't work!", g:netrw_localmovecmd))
   5912                endif
   5913                break
   5914            endif
   5915        endfor
   5916 
   5917    elseif  a:islocal && !s:netrwmftgt_islocal
   5918        " move: local -> remote
   5919        let mflist= s:netrwmarkfilelist_{bufnr("%")}
   5920        NetrwKeepj call s:NetrwMarkFileCopy(a:islocal)
   5921        for fname in mflist
   5922            let barefname = substitute(fname,'^\(.*/\)\(.\{-}\)$','\2','')
   5923            let ok        = s:NetrwLocalRmFile(b:netrw_curdir,barefname,1)
   5924        endfor
   5925        unlet mflist
   5926 
   5927    elseif !a:islocal &&  s:netrwmftgt_islocal
   5928        " move: remote -> local
   5929        let mflist= s:netrwmarkfilelist_{bufnr("%")}
   5930        NetrwKeepj call s:NetrwMarkFileCopy(a:islocal)
   5931        for fname in mflist
   5932            let barefname = substitute(fname,'^\(.*/\)\(.\{-}\)$','\2','')
   5933            let ok        = s:NetrwRemoteRmFile(b:netrw_curdir,barefname,1)
   5934        endfor
   5935        unlet mflist
   5936 
   5937    elseif !a:islocal && !s:netrwmftgt_islocal
   5938        " move: remote -> remote
   5939        let mflist= s:netrwmarkfilelist_{bufnr("%")}
   5940        NetrwKeepj call s:NetrwMarkFileCopy(a:islocal)
   5941        for fname in mflist
   5942            let barefname = substitute(fname,'^\(.*/\)\(.\{-}\)$','\2','')
   5943            let ok        = s:NetrwRemoteRmFile(b:netrw_curdir,barefname,1)
   5944        endfor
   5945        unlet mflist
   5946    endif
   5947 
   5948    " -------
   5949    " cleanup
   5950    " -------
   5951 
   5952    " remove markings from local buffer
   5953    call s:NetrwUnmarkList(curbufnr,curdir)                   " remove markings from local buffer
   5954 
   5955    " refresh buffers
   5956    if !s:netrwmftgt_islocal
   5957        NetrwKeepj call s:NetrwRefreshDir(s:netrwmftgt_islocal,s:netrwmftgt)
   5958    endif
   5959    if a:islocal
   5960        NetrwKeepj call s:NetrwRefreshDir(a:islocal,b:netrw_curdir)
   5961    endif
   5962    if g:netrw_fastbrowse <= 1
   5963        NetrwKeepj call s:LocalBrowseRefresh()
   5964    endif
   5965 
   5966 endfunction
   5967 
   5968 " s:NetrwMarkFileRegexp: (invoked by mr) This function is used to mark {{{2
   5969 "                        files when given a regexp (for which a prompt is
   5970 "                        issued) (matches to name of files).
   5971 function s:NetrwMarkFileRegexp(islocal)
   5972 
   5973    " get the regular expression
   5974    call inputsave()
   5975    let regexp= input("Enter regexp: ","","file")
   5976    call inputrestore()
   5977 
   5978    if a:islocal
   5979        let curdir= s:NetrwGetCurdir(a:islocal)
   5980        " get the matching list of files using local glob()
   5981        let dirname = escape(b:netrw_curdir,g:netrw_glob_escape)
   5982        let filelist= glob(netrw#fs#ComposePath(dirname,regexp),0,1,1)
   5983 
   5984        " mark the list of files
   5985        for fname in filelist
   5986            if fname =~ '^'.fnameescape(curdir)
   5987                NetrwKeepj call s:NetrwMarkFile(a:islocal,substitute(fname,'^'.fnameescape(curdir).'/','',''))
   5988            else
   5989                NetrwKeepj call s:NetrwMarkFile(a:islocal,substitute(fname,'^.*/','',''))
   5990            endif
   5991        endfor
   5992 
   5993    else
   5994 
   5995        " convert displayed listing into a filelist
   5996        let eikeep = &ei
   5997        let areg   = @a
   5998        sil NetrwKeepj %y a
   5999        setl ei=all ma
   6000        1split
   6001        NetrwKeepj call s:NetrwEnew()
   6002        NetrwKeepj call s:NetrwOptionsSafe(a:islocal)
   6003        sil NetrwKeepj norm! "ap
   6004        NetrwKeepj 2
   6005        let bannercnt= search('^" =====','W')
   6006        exe "sil NetrwKeepj 1,".bannercnt."d"
   6007        setl bt=nofile
   6008        if     g:netrw_liststyle == s:LONGLIST
   6009            sil NetrwKeepj %s/\s\{2,}\S.*$//e
   6010            call histdel("/",-1)
   6011        elseif g:netrw_liststyle == s:WIDELIST
   6012            sil NetrwKeepj %s/\s\{2,}/\r/ge
   6013            call histdel("/",-1)
   6014        elseif g:netrw_liststyle == s:TREELIST
   6015            exe 'sil NetrwKeepj %s/^'.s:treedepthstring.' //e'
   6016            sil! NetrwKeepj g/^ .*$/d
   6017            call histdel("/",-1)
   6018            call histdel("/",-1)
   6019        endif
   6020        " convert regexp into the more usual glob-style format
   6021        let regexp= substitute(regexp,'\*','.*','g')
   6022        exe "sil! NetrwKeepj v/".escape(regexp,'/')."/d"
   6023        call histdel("/",-1)
   6024        let filelist= getline(1,line("$"))
   6025        q!
   6026        for filename in filelist
   6027            NetrwKeepj call s:NetrwMarkFile(a:islocal,substitute(filename,'^.*/','',''))
   6028        endfor
   6029        unlet filelist
   6030        let @a  = areg
   6031        let &ei = eikeep
   6032    endif
   6033    echo "  (use me to edit marked files)"
   6034 
   6035 endfunction
   6036 
   6037 " s:NetrwMarkFileSource: (invoked by ms) This function sources marked files {{{2
   6038 "                        Uses the local marked file list.
   6039 function s:NetrwMarkFileSource(islocal)
   6040    let curbufnr= bufnr("%")
   6041 
   6042    " sanity check
   6043    if !exists("s:netrwmarkfilelist_{curbufnr}") || empty(s:netrwmarkfilelist_{curbufnr})
   6044        call netrw#msg#Notify('ERROR', 'there are no marked files in this window (:help netrw-mf)')
   6045        return
   6046    endif
   6047    let curdir= s:NetrwGetCurdir(a:islocal)
   6048 
   6049    if exists("s:netrwmarkfilelist_{curbufnr}")
   6050        let netrwmarkfilelist = s:netrwmarkfilelist_{bufnr("%")}
   6051        call s:NetrwUnmarkList(curbufnr,curdir)
   6052        for fname in netrwmarkfilelist
   6053            if a:islocal
   6054                if g:netrw_keepdir
   6055                    let fname= netrw#fs#ComposePath(curdir,fname)
   6056                endif
   6057            else
   6058                let fname= curdir.fname
   6059            endif
   6060            " the autocmds will handle sourcing both local and remote files
   6061            exe "so ".fnameescape(fname)
   6062        endfor
   6063        2match none
   6064    endif
   6065 endfunction
   6066 
   6067 " s:NetrwMarkFileTag: (invoked by mT) This function applies g:netrw_ctags to marked files {{{2
   6068 "                     Uses the global markfilelist
   6069 function s:NetrwMarkFileTag(islocal)
   6070    let svpos    = winsaveview()
   6071    let curdir   = s:NetrwGetCurdir(a:islocal)
   6072    let curbufnr = bufnr("%")
   6073 
   6074    " sanity check
   6075    if !exists("s:netrwmarkfilelist_{curbufnr}") || empty(s:netrwmarkfilelist_{curbufnr})
   6076        call netrw#msg#Notify('ERROR', 'there are no marked files in this window (:help netrw-mf)')
   6077        return
   6078    endif
   6079 
   6080    if exists("s:netrwmarkfilelist")
   6081        let netrwmarkfilelist= join(map(deepcopy(s:netrwmarkfilelist), "netrw#os#Escape(v:val,".!a:islocal.")"))
   6082        call s:NetrwUnmarkAll()
   6083 
   6084        if a:islocal
   6085 
   6086            call system(g:netrw_ctags." ".netrwmarkfilelist)
   6087            if v:shell_error
   6088                call netrw#msg#Notify('ERROR', printf('g:netrw_ctags<%s> is not executable!', g:netrw_ctags))
   6089            endif
   6090 
   6091        else
   6092            let cmd   = s:RemoteSystem(g:netrw_ctags." ".netrwmarkfilelist)
   6093            call netrw#Obtain(a:islocal,"tags")
   6094            let curdir= b:netrw_curdir
   6095            1split
   6096            NetrwKeepj e tags
   6097            let path= substitute(curdir,'^\(.*\)/[^/]*$','\1/','')
   6098            exe 'NetrwKeepj %s/\t\(\S\+\)\t/\t'.escape(path,"/\n\r\\").'\1\t/e'
   6099            call histdel("/",-1)
   6100            wq!
   6101        endif
   6102        2match none
   6103        call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./',0))
   6104        call winrestview(svpos)
   6105    endif
   6106 endfunction
   6107 
   6108 " s:NetrwMarkFileTgt:  (invoked by mt) This function sets up a marked file target {{{2
   6109 "   Sets up two variables,
   6110 "     s:netrwmftgt         : holds the target directory
   6111 "     s:netrwmftgt_islocal : 0=target directory is remote
   6112 "                            1=target directory is local
   6113 function s:NetrwMarkFileTgt(islocal)
   6114    let svpos  = winsaveview()
   6115    let curdir = s:NetrwGetCurdir(a:islocal)
   6116    let hadtgt = exists("s:netrwmftgt")
   6117    if !exists("w:netrw_bannercnt")
   6118        let w:netrw_bannercnt= b:netrw_bannercnt
   6119    endif
   6120 
   6121    " set up target
   6122    if line(".") < w:netrw_bannercnt
   6123        " if cursor in banner region, use b:netrw_curdir for the target unless its already the target
   6124        if exists("s:netrwmftgt") && exists("s:netrwmftgt_islocal") && s:netrwmftgt == b:netrw_curdir
   6125            unlet s:netrwmftgt s:netrwmftgt_islocal
   6126            if g:netrw_fastbrowse <= 1
   6127                call s:LocalBrowseRefresh()
   6128            endif
   6129            call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./',0))
   6130            call winrestview(svpos)
   6131            return
   6132        else
   6133            let s:netrwmftgt= b:netrw_curdir
   6134        endif
   6135 
   6136    else
   6137        " get word under cursor.
   6138        "  * If directory, use it for the target.
   6139        "  * If file, use b:netrw_curdir for the target
   6140        let curword= s:NetrwGetWord()
   6141        let tgtdir = netrw#fs#ComposePath(curdir,curword)
   6142        if a:islocal && isdirectory(s:NetrwFile(tgtdir))
   6143            let s:netrwmftgt = tgtdir
   6144        elseif !a:islocal && tgtdir =~ '/$'
   6145            let s:netrwmftgt = tgtdir
   6146        else
   6147            let s:netrwmftgt = curdir
   6148        endif
   6149    endif
   6150    if a:islocal
   6151        " simplify the target (eg. /abc/def/../ghi -> /abc/ghi)
   6152        let s:netrwmftgt= simplify(s:netrwmftgt)
   6153    endif
   6154    if g:netrw_cygwin
   6155        let s:netrwmftgt= substitute(system("cygpath ".netrw#os#Escape(s:netrwmftgt)),'\n$','','')
   6156        let s:netrwmftgt= substitute(s:netrwmftgt,'\n$','','')
   6157    endif
   6158    let s:netrwmftgt_islocal= a:islocal
   6159 
   6160    " need to do refresh so that the banner will be updated
   6161    "  s:LocalBrowseRefresh handles all local-browsing buffers when not fast browsing
   6162    if g:netrw_fastbrowse <= 1
   6163        call s:LocalBrowseRefresh()
   6164    endif
   6165    "  call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./',0))
   6166    if exists("w:netrw_liststyle") && w:netrw_liststyle == s:TREELIST
   6167        call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,w:netrw_treetop,0))
   6168    else
   6169        call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./',0))
   6170    endif
   6171    call winrestview(svpos)
   6172    if !hadtgt
   6173        sil! NetrwKeepj norm! j
   6174    endif
   6175 endfunction
   6176 
   6177 " s:NetrwGetCurdir: gets current directory and sets up b:netrw_curdir if necessary {{{2
   6178 function s:NetrwGetCurdir(islocal)
   6179 
   6180    if exists("w:netrw_liststyle") && w:netrw_liststyle == s:TREELIST
   6181        let b:netrw_curdir = s:NetrwTreePath(w:netrw_treetop)
   6182    elseif !exists("b:netrw_curdir")
   6183        let b:netrw_curdir= getcwd()
   6184    endif
   6185 
   6186    if b:netrw_curdir !~ '\<\a\{3,}://'
   6187        let curdir= b:netrw_curdir
   6188        if g:netrw_keepdir == 0
   6189            call s:NetrwLcd(curdir)
   6190        endif
   6191    endif
   6192 
   6193    return b:netrw_curdir
   6194 endfunction
   6195 
   6196 " s:NetrwOpenFile: query user for a filename and open it {{{2
   6197 function s:NetrwOpenFile(islocal)
   6198    call inputsave()
   6199    let fname = input("Enter filename: ")
   6200    call inputrestore()
   6201 
   6202    if empty(fname)
   6203        return
   6204    endif
   6205 
   6206    " save position for benefit of Rexplore
   6207    let s:rexposn_{bufnr("%")}= winsaveview()
   6208 
   6209    execute "NetrwKeepj e " . fnameescape(!isabsolutepath(fname)
   6210                \ ? netrw#fs#ComposePath(b:netrw_curdir, fname)
   6211                \ : fname)
   6212 endfunction
   6213 
   6214 " netrw#Shrink: shrinks/expands a netrw or Lexplorer window {{{2
   6215 "               For the mapping to this function be made via
   6216 "               netrwPlugin, you'll need to have had
   6217 "               g:netrw_usetab set to non-zero.
   6218 function netrw#Shrink()
   6219    let curwin  = winnr()
   6220    let wiwkeep = &wiw
   6221    set wiw=1
   6222 
   6223    if &ft == "netrw"
   6224        if winwidth(0) > g:netrw_wiw
   6225            let t:netrw_winwidth= winwidth(0)
   6226            exe "vert resize ".g:netrw_wiw
   6227            wincmd l
   6228            if winnr() == curwin
   6229                wincmd h
   6230            endif
   6231        else
   6232            exe "vert resize ".t:netrw_winwidth
   6233        endif
   6234 
   6235    elseif exists("t:netrw_lexbufnr")
   6236        exe bufwinnr(t:netrw_lexbufnr)."wincmd w"
   6237        if     winwidth(bufwinnr(t:netrw_lexbufnr)) >  g:netrw_wiw
   6238            let t:netrw_winwidth= winwidth(0)
   6239            exe "vert resize ".g:netrw_wiw
   6240            wincmd l
   6241            if winnr() == curwin
   6242                wincmd h
   6243            endif
   6244        elseif winwidth(bufwinnr(t:netrw_lexbufnr)) >= 0
   6245            exe "vert resize ".t:netrw_winwidth
   6246        else
   6247            call netrw#Lexplore(0,0)
   6248        endif
   6249 
   6250    else
   6251        call netrw#Lexplore(0,0)
   6252    endif
   6253    let wiw= wiwkeep
   6254 
   6255 endfunction
   6256 
   6257 " s:NetSortSequence: allows user to edit the sorting sequence {{{2
   6258 function s:NetSortSequence(islocal)
   6259    let ykeep= @@
   6260    let svpos= winsaveview()
   6261    call inputsave()
   6262    let newsortseq= input("Edit Sorting Sequence: ",g:netrw_sort_sequence)
   6263    call inputrestore()
   6264 
   6265    " refresh the listing
   6266    let g:netrw_sort_sequence= newsortseq
   6267    NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./',0))
   6268    NetrwKeepj call winrestview(svpos)
   6269    let @@= ykeep
   6270 endfunction
   6271 
   6272 " s:NetrwUnmarkList: delete local marked file list and remove their contents from the global marked-file list {{{2
   6273 "   User access provided by the <mF> mapping. (see :help netrw-mF)
   6274 "   Used by many MarkFile functions.
   6275 function s:NetrwUnmarkList(curbufnr,curdir)
   6276 
   6277    "  remove all files in local marked-file list from global list
   6278    if exists("s:netrwmarkfilelist")
   6279        for mfile in s:netrwmarkfilelist_{a:curbufnr}
   6280            let dfile = netrw#fs#ComposePath(a:curdir,mfile)       " prepend directory to mfile
   6281            let idx   = index(s:netrwmarkfilelist,dfile)    " get index in list of dfile
   6282            call remove(s:netrwmarkfilelist,idx)            " remove from global list
   6283        endfor
   6284        if s:netrwmarkfilelist == []
   6285            unlet s:netrwmarkfilelist
   6286        endif
   6287 
   6288        " getting rid of the local marked-file lists is easy
   6289        unlet s:netrwmarkfilelist_{a:curbufnr}
   6290    endif
   6291    if exists("s:netrwmarkfilemtch_{a:curbufnr}")
   6292        unlet s:netrwmarkfilemtch_{a:curbufnr}
   6293    endif
   6294    2match none
   6295 endfunction
   6296 
   6297 " s:NetrwUnmarkAll: remove the global marked file list and all local ones {{{2
   6298 function s:NetrwUnmarkAll()
   6299    if exists("s:netrwmarkfilelist")
   6300        unlet s:netrwmarkfilelist
   6301    endif
   6302    sil call s:NetrwUnmarkAll2()
   6303    2match none
   6304 endfunction
   6305 
   6306 " s:NetrwUnmarkAll2: unmark all files from all buffers {{{2
   6307 function s:NetrwUnmarkAll2()
   6308    redir => netrwmarkfilelist_let
   6309    let
   6310    redir END
   6311    let netrwmarkfilelist_list= split(netrwmarkfilelist_let,'\n')          " convert let string into a let list
   6312    call filter(netrwmarkfilelist_list,"v:val =~ '^s:netrwmarkfilelist_'") " retain only those vars that start as s:netrwmarkfilelist_
   6313    call map(netrwmarkfilelist_list,"substitute(v:val,'\\s.*$','','')")    " remove what the entries are equal to
   6314    for flist in netrwmarkfilelist_list
   6315        let curbufnr= substitute(flist,'s:netrwmarkfilelist_','','')
   6316        unlet s:netrwmarkfilelist_{curbufnr}
   6317        unlet s:netrwmarkfilemtch_{curbufnr}
   6318    endfor
   6319 endfunction
   6320 
   6321 " s:NetrwUnMarkFile: called via mu map; unmarks *all* marked files, both global and buffer-local {{{2
   6322 "
   6323 " Marked files are in two types of lists:
   6324 "    s:netrwmarkfilelist    -- holds complete paths to all marked files
   6325 "    s:netrwmarkfilelist_#  -- holds list of marked files in current-buffer's directory (#==bufnr())
   6326 "
   6327 " Marked files suitable for use with 2match are in:
   6328 "    s:netrwmarkfilemtch_#   -- used with 2match to display marked files
   6329 function s:NetrwUnMarkFile(islocal)
   6330    let svpos    = winsaveview()
   6331    let curbufnr = bufnr("%")
   6332 
   6333    " unmark marked file list
   6334    " (although I expect s:NetrwUpload() to do it, I'm just making sure)
   6335    if exists("s:netrwmarkfilelist")
   6336        unlet s:netrwmarkfilelist
   6337    endif
   6338 
   6339    let ibuf= 1
   6340    while ibuf < bufnr("$")
   6341        if exists("s:netrwmarkfilelist_".ibuf)
   6342            unlet s:netrwmarkfilelist_{ibuf}
   6343            unlet s:netrwmarkfilemtch_{ibuf}
   6344        endif
   6345        let ibuf = ibuf + 1
   6346    endwhile
   6347    2match none
   6348 
   6349    "  call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./',0))
   6350    call winrestview(svpos)
   6351 endfunction
   6352 
   6353 " s:NetrwMenu: generates the menu for gvim and netrw {{{2
   6354 function s:NetrwMenu(domenu)
   6355 
   6356    if !exists("g:NetrwMenuPriority")
   6357        let g:NetrwMenuPriority= 80
   6358    endif
   6359 
   6360    if has("menu") && has("gui_running") && &go =~# 'm' && g:netrw_menu
   6361 
   6362        if !exists("s:netrw_menu_enabled") && a:domenu
   6363            let s:netrw_menu_enabled= 1
   6364            exe 'sil! menu '.g:NetrwMenuPriority.'.1      '.g:NetrwTopLvlMenu.'Help<tab><F1>    <F1>'
   6365            exe 'sil! menu '.g:NetrwMenuPriority.'.5      '.g:NetrwTopLvlMenu.'-Sep1-   :'
   6366            exe 'sil! menu '.g:NetrwMenuPriority.'.6      '.g:NetrwTopLvlMenu.'Go\ Up\ Directory<tab>-  -'
   6367            exe 'sil! menu '.g:NetrwMenuPriority.'.7      '.g:NetrwTopLvlMenu.'Apply\ Special\ Viewer<tab>x     x'
   6368            if g:netrw_dirhistmax > 0
   6369                exe 'sil! menu '.g:NetrwMenuPriority.'.8.1   '.g:NetrwTopLvlMenu.'Bookmarks\ and\ History.Bookmark\ Current\ Directory<tab>mb      mb'
   6370                exe 'sil! menu '.g:NetrwMenuPriority.'.8.4   '.g:NetrwTopLvlMenu.'Bookmarks\ and\ History.Goto\ Prev\ Dir\ (History)<tab>u u'
   6371                exe 'sil! menu '.g:NetrwMenuPriority.'.8.5   '.g:NetrwTopLvlMenu.'Bookmarks\ and\ History.Goto\ Next\ Dir\ (History)<tab>U U'
   6372                exe 'sil! menu '.g:NetrwMenuPriority.'.8.6   '.g:NetrwTopLvlMenu.'Bookmarks\ and\ History.List<tab>qb      qb'
   6373            else
   6374                exe 'sil! menu '.g:NetrwMenuPriority.'.8     '.g:NetrwTopLvlMenu.'Bookmarks\ and\ History  :echo "(disabled)"'."\<cr>"
   6375            endif
   6376            exe 'sil! menu '.g:NetrwMenuPriority.'.9.1    '.g:NetrwTopLvlMenu.'Browsing\ Control.Horizontal\ Split<tab>o        o'
   6377            exe 'sil! menu '.g:NetrwMenuPriority.'.9.2    '.g:NetrwTopLvlMenu.'Browsing\ Control.Vertical\ Split<tab>v  v'
   6378            exe 'sil! menu '.g:NetrwMenuPriority.'.9.3    '.g:NetrwTopLvlMenu.'Browsing\ Control.New\ Tab<tab>t t'
   6379            exe 'sil! menu '.g:NetrwMenuPriority.'.9.4    '.g:NetrwTopLvlMenu.'Browsing\ Control.Preview<tab>p  p'
   6380            exe 'sil! menu '.g:NetrwMenuPriority.'.9.5    '.g:NetrwTopLvlMenu.'Browsing\ Control.Edit\ File\ Hiding\ List<tab><ctrl-h>'."       \<c-h>'"
   6381            exe 'sil! menu '.g:NetrwMenuPriority.'.9.6    '.g:NetrwTopLvlMenu.'Browsing\ Control.Edit\ Sorting\ Sequence<tab>S  S'
   6382            exe 'sil! menu '.g:NetrwMenuPriority.'.9.7    '.g:NetrwTopLvlMenu.'Browsing\ Control.Quick\ Hide/Unhide\ Dot\ Files<tab>'."gh       gh"
   6383            exe 'sil! menu '.g:NetrwMenuPriority.'.9.8    '.g:NetrwTopLvlMenu.'Browsing\ Control.Refresh\ Listing<tab>'."<ctrl-l>       \<c-l>"
   6384            exe 'sil! menu '.g:NetrwMenuPriority.'.9.9    '.g:NetrwTopLvlMenu.'Browsing\ Control.Settings/Options<tab>:NetrwSettings    '.":NetrwSettings\<cr>"
   6385            exe 'sil! menu '.g:NetrwMenuPriority.'.10     '.g:NetrwTopLvlMenu.'Delete\ File/Directory<tab>D     D'
   6386            exe 'sil! menu '.g:NetrwMenuPriority.'.11.1   '.g:NetrwTopLvlMenu.'Edit\ File/Dir.Create\ New\ File<tab>%   %'
   6387            exe 'sil! menu '.g:NetrwMenuPriority.'.11.1   '.g:NetrwTopLvlMenu.'Edit\ File/Dir.In\ Current\ Window<tab><cr>      '."\<cr>"
   6388            exe 'sil! menu '.g:NetrwMenuPriority.'.11.2   '.g:NetrwTopLvlMenu.'Edit\ File/Dir.Preview\ File/Directory<tab>p     p'
   6389            exe 'sil! menu '.g:NetrwMenuPriority.'.11.3   '.g:NetrwTopLvlMenu.'Edit\ File/Dir.In\ Previous\ Window<tab>P        P'
   6390            exe 'sil! menu '.g:NetrwMenuPriority.'.11.4   '.g:NetrwTopLvlMenu.'Edit\ File/Dir.In\ New\ Window<tab>o     o'
   6391            exe 'sil! menu '.g:NetrwMenuPriority.'.11.5   '.g:NetrwTopLvlMenu.'Edit\ File/Dir.In\ New\ Tab<tab>t        t'
   6392            exe 'sil! menu '.g:NetrwMenuPriority.'.11.5   '.g:NetrwTopLvlMenu.'Edit\ File/Dir.In\ New\ Vertical\ Window<tab>v   v'
   6393            exe 'sil! menu '.g:NetrwMenuPriority.'.12.1   '.g:NetrwTopLvlMenu.'Explore.Directory\ Name  :Explore '
   6394            exe 'sil! menu '.g:NetrwMenuPriority.'.12.2   '.g:NetrwTopLvlMenu.'Explore.Filenames\ Matching\ Pattern\ (curdir\ only)<tab>:Explore\ */    :Explore */'
   6395            exe 'sil! menu '.g:NetrwMenuPriority.'.12.2   '.g:NetrwTopLvlMenu.'Explore.Filenames\ Matching\ Pattern\ (+subdirs)<tab>:Explore\ **/       :Explore **/'
   6396            exe 'sil! menu '.g:NetrwMenuPriority.'.12.3   '.g:NetrwTopLvlMenu.'Explore.Files\ Containing\ String\ Pattern\ (curdir\ only)<tab>:Explore\ *//     :Explore *//'
   6397            exe 'sil! menu '.g:NetrwMenuPriority.'.12.4   '.g:NetrwTopLvlMenu.'Explore.Files\ Containing\ String\ Pattern\ (+subdirs)<tab>:Explore\ **//        :Explore **//'
   6398            exe 'sil! menu '.g:NetrwMenuPriority.'.12.4   '.g:NetrwTopLvlMenu.'Explore.Next\ Match<tab>:Nexplore        :Nexplore<cr>'
   6399            exe 'sil! menu '.g:NetrwMenuPriority.'.12.4   '.g:NetrwTopLvlMenu.'Explore.Prev\ Match<tab>:Pexplore        :Pexplore<cr>'
   6400            exe 'sil! menu '.g:NetrwMenuPriority.'.13     '.g:NetrwTopLvlMenu.'Make\ Subdirectory<tab>d d'
   6401            exe 'sil! menu '.g:NetrwMenuPriority.'.14.1   '.g:NetrwTopLvlMenu.'Marked\ Files.Mark\ File<tab>mf  mf'
   6402            exe 'sil! menu '.g:NetrwMenuPriority.'.14.2   '.g:NetrwTopLvlMenu.'Marked\ Files.Mark\ Files\ by\ Regexp<tab>mr     mr'
   6403            exe 'sil! menu '.g:NetrwMenuPriority.'.14.3   '.g:NetrwTopLvlMenu.'Marked\ Files.Hide-Show-List\ Control<tab>a      a'
   6404            exe 'sil! menu '.g:NetrwMenuPriority.'.14.4   '.g:NetrwTopLvlMenu.'Marked\ Files.Copy\ To\ Target<tab>mc    mc'
   6405            exe 'sil! menu '.g:NetrwMenuPriority.'.14.5   '.g:NetrwTopLvlMenu.'Marked\ Files.Delete<tab>D       D'
   6406            exe 'sil! menu '.g:NetrwMenuPriority.'.14.6   '.g:NetrwTopLvlMenu.'Marked\ Files.Diff<tab>md        md'
   6407            exe 'sil! menu '.g:NetrwMenuPriority.'.14.7   '.g:NetrwTopLvlMenu.'Marked\ Files.Edit<tab>me        me'
   6408            exe 'sil! menu '.g:NetrwMenuPriority.'.14.8   '.g:NetrwTopLvlMenu.'Marked\ Files.Exe\ Cmd<tab>mx    mx'
   6409            exe 'sil! menu '.g:NetrwMenuPriority.'.14.9   '.g:NetrwTopLvlMenu.'Marked\ Files.Move\ To\ Target<tab>mm    mm'
   6410            exe 'sil! menu '.g:NetrwMenuPriority.'.14.10  '.g:NetrwTopLvlMenu.'Marked\ Files.Obtain<tab>O       O'
   6411            exe 'sil! menu '.g:NetrwMenuPriority.'.14.11  '.g:NetrwTopLvlMenu.'Marked\ Files.Print<tab>mp       mp'
   6412            exe 'sil! menu '.g:NetrwMenuPriority.'.14.12  '.g:NetrwTopLvlMenu.'Marked\ Files.Replace<tab>R      R'
   6413            exe 'sil! menu '.g:NetrwMenuPriority.'.14.13  '.g:NetrwTopLvlMenu.'Marked\ Files.Set\ Target<tab>mt mt'
   6414            exe 'sil! menu '.g:NetrwMenuPriority.'.14.14  '.g:NetrwTopLvlMenu.'Marked\ Files.Tag<tab>mT mT'
   6415            exe 'sil! menu '.g:NetrwMenuPriority.'.14.15  '.g:NetrwTopLvlMenu.'Marked\ Files.Zip/Unzip/Compress/Uncompress<tab>mz       mz'
   6416            exe 'sil! menu '.g:NetrwMenuPriority.'.15     '.g:NetrwTopLvlMenu.'Obtain\ File<tab>O       O'
   6417            exe 'sil! menu '.g:NetrwMenuPriority.'.16.1.1 '.g:NetrwTopLvlMenu.'Style.Listing.thin<tab>i :let w:netrw_liststyle=0<cr><c-L>'
   6418            exe 'sil! menu '.g:NetrwMenuPriority.'.16.1.1 '.g:NetrwTopLvlMenu.'Style.Listing.long<tab>i :let w:netrw_liststyle=1<cr><c-L>'
   6419            exe 'sil! menu '.g:NetrwMenuPriority.'.16.1.1 '.g:NetrwTopLvlMenu.'Style.Listing.wide<tab>i :let w:netrw_liststyle=2<cr><c-L>'
   6420            exe 'sil! menu '.g:NetrwMenuPriority.'.16.1.1 '.g:NetrwTopLvlMenu.'Style.Listing.tree<tab>i :let w:netrw_liststyle=3<cr><c-L>'
   6421            exe 'sil! menu '.g:NetrwMenuPriority.'.16.2.1 '.g:NetrwTopLvlMenu.'Style.Normal-Hide-Show.Show\ All<tab>a   :let g:netrw_hide=0<cr><c-L>'
   6422            exe 'sil! menu '.g:NetrwMenuPriority.'.16.2.3 '.g:NetrwTopLvlMenu.'Style.Normal-Hide-Show.Normal<tab>a      :let g:netrw_hide=1<cr><c-L>'
   6423            exe 'sil! menu '.g:NetrwMenuPriority.'.16.2.2 '.g:NetrwTopLvlMenu.'Style.Normal-Hide-Show.Hidden\ Only<tab>a        :let g:netrw_hide=2<cr><c-L>'
   6424            exe 'sil! menu '.g:NetrwMenuPriority.'.16.3   '.g:NetrwTopLvlMenu.'Style.Reverse\ Sorting\ Order<tab>'."r   r"
   6425            exe 'sil! menu '.g:NetrwMenuPriority.'.16.4.1 '.g:NetrwTopLvlMenu.'Style.Sorting\ Method.Name<tab>s       :let g:netrw_sort_by="name"<cr><c-L>'
   6426            exe 'sil! menu '.g:NetrwMenuPriority.'.16.4.2 '.g:NetrwTopLvlMenu.'Style.Sorting\ Method.Time<tab>s       :let g:netrw_sort_by="time"<cr><c-L>'
   6427            exe 'sil! menu '.g:NetrwMenuPriority.'.16.4.3 '.g:NetrwTopLvlMenu.'Style.Sorting\ Method.Size<tab>s       :let g:netrw_sort_by="size"<cr><c-L>'
   6428            exe 'sil! menu '.g:NetrwMenuPriority.'.16.4.3 '.g:NetrwTopLvlMenu.'Style.Sorting\ Method.Exten<tab>s      :let g:netrw_sort_by="exten"<cr><c-L>'
   6429            exe 'sil! menu '.g:NetrwMenuPriority.'.17     '.g:NetrwTopLvlMenu.'Rename\ File/Directory<tab>R     R'
   6430            exe 'sil! menu '.g:NetrwMenuPriority.'.18     '.g:NetrwTopLvlMenu.'Set\ Current\ Directory<tab>c    c'
   6431            let s:netrw_menucnt= 28
   6432            call s:NetrwBookmarkMenu() " provide some history!  uses priorities 2,3, reserves 4, 8.2.x
   6433            call s:NetrwTgtMenu()      " let bookmarks and history be easy targets
   6434 
   6435        elseif !a:domenu
   6436            let s:netrwcnt = 0
   6437            let curwin     = winnr()
   6438            windo if getline(2) =~# "Netrw" | let s:netrwcnt= s:netrwcnt + 1 | endif
   6439            exe curwin."wincmd w"
   6440 
   6441            if s:netrwcnt <= 1
   6442                exe 'sil! unmenu '.g:NetrwTopLvlMenu
   6443                sil! unlet s:netrw_menu_enabled
   6444            endif
   6445        endif
   6446    return
   6447  endif
   6448 
   6449 endfunction
   6450 
   6451 " s:NetrwObtain: obtain file under cursor or from markfile list {{{2
   6452 "                Used by the O maps (as <SID>NetrwObtain())
   6453 function s:NetrwObtain(islocal)
   6454 
   6455    let ykeep= @@
   6456    if exists("s:netrwmarkfilelist_{bufnr('%')}")
   6457        let islocal= s:netrwmarkfilelist_{bufnr('%')}[1] !~ '^\a\{3,}://'
   6458        call netrw#Obtain(islocal,s:netrwmarkfilelist_{bufnr('%')})
   6459        call s:NetrwUnmarkList(bufnr('%'),b:netrw_curdir)
   6460    else
   6461        call netrw#Obtain(a:islocal,s:NetrwGetWord())
   6462    endif
   6463    let @@= ykeep
   6464 
   6465 endfunction
   6466 
   6467 " s:NetrwPrevWinOpen: open file/directory in previous window.  {{{2
   6468 "   If there's only one window, then the window will first be split.
   6469 "   Returns:
   6470 "     choice = 0 : didn't have to choose
   6471 "     choice = 1 : saved modified file in window first
   6472 "     choice = 2 : didn't save modified file, opened window
   6473 "     choice = 3 : cancel open
   6474 function s:NetrwPrevWinOpen(islocal)
   6475    let ykeep= @@
   6476    " grab a copy of the b:netrw_curdir to pass it along to newly split windows
   6477    let curdir = b:netrw_curdir
   6478 
   6479    " get last window number and the word currently under the cursor
   6480    let origwin   = winnr()
   6481    let lastwinnr = winnr("$")
   6482    let curword      = s:NetrwGetWord()
   6483    let choice       = 0
   6484    let s:prevwinopen= 1  " lets s:NetrwTreeDir() know that NetrwPrevWinOpen called it (s:NetrwTreeDir() will unlet s:prevwinopen)
   6485    let s:treedir = s:NetrwTreeDir(a:islocal)
   6486    let curdir    = s:treedir
   6487 
   6488    let didsplit = 0
   6489    if lastwinnr == 1
   6490        " if only one window, open a new one first
   6491        " g:netrw_preview=0: preview window shown in a horizontally split window
   6492        " g:netrw_preview=1: preview window shown in a vertically   split window
   6493        if g:netrw_preview
   6494            " vertically split preview window
   6495            let winsz= (g:netrw_winsize > 0)? (g:netrw_winsize*winwidth(0))/100 : -g:netrw_winsize
   6496            exe (g:netrw_alto? "top " : "bot ")."vert ".winsz."wincmd s"
   6497        else
   6498            " horizontally split preview window
   6499            let winsz= (g:netrw_winsize > 0)? (g:netrw_winsize*winheight(0))/100 : -g:netrw_winsize
   6500            exe (g:netrw_alto? "bel " : "abo ").winsz."wincmd s"
   6501        endif
   6502        let didsplit = 1
   6503 
   6504    else
   6505        NetrwKeepj call s:SaveBufVars()
   6506        let eikeep= &ei
   6507        setl ei=all
   6508        wincmd p
   6509 
   6510        if exists("s:lexplore_win") && s:lexplore_win == winnr()
   6511            " whoops -- user trying to open file in the Lexplore window.
   6512            " Use Lexplore's opening-file window instead.
   6513            "    exe g:netrw_chgwin."wincmd w"
   6514            wincmd p
   6515            call s:NetrwBrowse(0,s:NetrwBrowseChgDir(0,s:NetrwGetWord(),1))
   6516        endif
   6517 
   6518        " prevwinnr: the window number of the "prev" window
   6519        " prevbufnr: the buffer number of the buffer in the "prev" window
   6520        " bnrcnt   : the qty of windows open on the "prev" buffer
   6521        let prevwinnr   = winnr()
   6522        let prevbufnr   = bufnr("%")
   6523        let prevbufname = bufname("%")
   6524        let prevmod     = &mod
   6525        let bnrcnt      = 0
   6526        NetrwKeepj call s:RestoreBufVars()
   6527 
   6528        " if the previous window's buffer has been changed (ie. its modified flag is set),
   6529        " and it doesn't appear in any other extant window, then ask the
   6530        " user if s/he wants to abandon modifications therein.
   6531        if prevmod
   6532            windo if winbufnr(0) == prevbufnr | let bnrcnt=bnrcnt+1 | endif
   6533            exe prevwinnr."wincmd w"
   6534 
   6535            if bnrcnt == 1 && &hidden == 0
   6536                " only one copy of the modified buffer in a window, and
   6537                " hidden not set, so overwriting will lose the modified file.  Ask first...
   6538                let choice = confirm("Save modified buffer<".prevbufname."> first?","&Yes\n&No\n&Cancel")
   6539                let &ei= eikeep
   6540 
   6541                if choice == 1
   6542                    " Yes -- write file & then browse
   6543                    let v:errmsg= ""
   6544                    sil w
   6545                    if v:errmsg != ""
   6546                        call netrw#msg#Notify('ERROR', printf('unable to write <%s>!', (exists("prevbufname") ? prevbufname : 'n/a')))
   6547                        exe origwin."wincmd w"
   6548                        let &ei = eikeep
   6549                        let @@  = ykeep
   6550                        return choice
   6551                    endif
   6552 
   6553                elseif choice == 2
   6554                    " No -- don't worry about changed file, just browse anyway
   6555                    echomsg "**note** changes to ".prevbufname." abandoned"
   6556 
   6557                else
   6558                    " Cancel -- don't do this
   6559                    exe origwin."wincmd w"
   6560                    let &ei= eikeep
   6561                    let @@ = ykeep
   6562                    return choice
   6563                endif
   6564            endif
   6565        endif
   6566        let &ei= eikeep
   6567    endif
   6568 
   6569    " restore b:netrw_curdir (window split/enew may have lost it)
   6570    let b:netrw_curdir= curdir
   6571    if a:islocal < 2
   6572        if a:islocal
   6573            call netrw#LocalBrowseCheck(s:NetrwBrowseChgDir(a:islocal,curword,0))
   6574        else
   6575            call s:NetrwBrowse(a:islocal,s:NetrwBrowseChgDir(a:islocal,curword,0))
   6576        endif
   6577    endif
   6578    let @@= ykeep
   6579    return choice
   6580 endfunction
   6581 
   6582 " s:NetrwUpload: load fname to tgt (used by NetrwMarkFileCopy()) {{{2
   6583 "                Always assumed to be local -> remote
   6584 "                call s:NetrwUpload(filename, target)
   6585 "                call s:NetrwUpload(filename, target, fromdirectory)
   6586 function s:NetrwUpload(fname,tgt,...)
   6587 
   6588    if a:tgt =~ '^\a\{3,}://'
   6589        let tgtdir= substitute(a:tgt,'^\a\{3,}://[^/]\+/\(.\{-}\)$','\1','')
   6590    else
   6591        let tgtdir= substitute(a:tgt,'^\(.*\)/[^/]*$','\1','')
   6592    endif
   6593 
   6594    if a:0 > 0
   6595        let fromdir= a:1
   6596    else
   6597        let fromdir= getcwd()
   6598    endif
   6599 
   6600    if type(a:fname) == 1
   6601        " handle uploading a single file using NetWrite
   6602        1split
   6603        exe "NetrwKeepj e ".fnameescape(s:NetrwFile(a:fname))
   6604        if a:tgt =~ '/$'
   6605            let wfname= substitute(a:fname,'^.*/','','')
   6606            exe "w! ".fnameescape(a:tgt.wfname)
   6607        else
   6608            exe "w ".fnameescape(a:tgt)
   6609        endif
   6610        q!
   6611 
   6612    elseif type(a:fname) == 3
   6613        " handle uploading a list of files via scp
   6614        let curdir= getcwd()
   6615        if a:tgt =~ '^scp:'
   6616            if s:NetrwLcd(fromdir)
   6617                return
   6618            endif
   6619            let filelist= deepcopy(s:netrwmarkfilelist_{bufnr('%')})
   6620            let args    = join(map(filelist,"netrw#os#Escape(v:val, 1)"))
   6621            if exists("g:netrw_port") && g:netrw_port != ""
   6622                let useport= " ".g:netrw_scpport." ".g:netrw_port
   6623            else
   6624                let useport= ""
   6625            endif
   6626            let machine = substitute(a:tgt,'^scp://\([^/:]\+\).*$','\1','')
   6627            let tgt     = substitute(a:tgt,'^scp://[^/]\+/\(.*\)$','\1','')
   6628            call netrw#os#Execute(s:netrw_silentxfer."!".g:netrw_scp_cmd.netrw#os#Escape(useport,1)." ".args." ".netrw#os#Escape(machine.":".tgt,1))
   6629            if s:NetrwLcd(curdir)
   6630                return
   6631            endif
   6632 
   6633        elseif a:tgt =~ '^ftp:'
   6634            call s:NetrwMethod(a:tgt)
   6635            if !s:NetrwValidateHostname(g:netrw_machine)
   6636                call netrw#msg#Notify('ERROR', printf('Rejecting invalid hostname: <%s>', g:netrw_machine))
   6637                return
   6638            endif
   6639 
   6640            if b:netrw_method == 2
   6641                " handle uploading a list of files via ftp+.netrc
   6642                let netrw_fname = b:netrw_fname
   6643                sil NetrwKeepj new
   6644 
   6645                NetrwKeepj put =g:netrw_ftpmode
   6646 
   6647                if exists("g:netrw_ftpextracmd")
   6648                    NetrwKeepj put =g:netrw_ftpextracmd
   6649                endif
   6650 
   6651                NetrwKeepj call setline(line("$")+1,'lcd "'.fromdir.'"')
   6652 
   6653                if tgtdir == ""
   6654                    let tgtdir= '/'
   6655                endif
   6656                NetrwKeepj call setline(line("$")+1,'cd "'.tgtdir.'"')
   6657 
   6658                for fname in a:fname
   6659                    NetrwKeepj call setline(line("$")+1,'put "'.s:NetrwFile(fname).'"')
   6660                endfor
   6661 
   6662                if exists("g:netrw_port") && g:netrw_port != ""
   6663                    call netrw#os#Execute(s:netrw_silentxfer."%!".s:netrw_ftp_cmd." -i ".netrw#os#Escape(g:netrw_machine,1)." ".netrw#os#Escape(g:netrw_port,1))
   6664                else
   6665                    call netrw#os#Execute(s:netrw_silentxfer."%!".s:netrw_ftp_cmd." -i ".netrw#os#Escape(g:netrw_machine,1))
   6666                endif
   6667                " If the result of the ftp operation isn't blank, show an error message (tnx to Doug Claar)
   6668                sil NetrwKeepj g/Local directory now/d
   6669                call histdel("/",-1)
   6670                if getline(1) !~ "^$" && getline(1) !~ '^Trying '
   6671                    call netrw#msg#Notify('ERROR', getline(1))
   6672                else
   6673                    bw!|q
   6674                endif
   6675 
   6676            elseif b:netrw_method == 3
   6677                " upload with ftp + machine, id, passwd, and fname (ie. no .netrc)
   6678                let netrw_fname= b:netrw_fname
   6679                NetrwKeepj call s:SaveBufVars()|sil NetrwKeepj new|NetrwKeepj call s:RestoreBufVars()
   6680                let tmpbufnr= bufnr("%")
   6681                setl ff=unix
   6682 
   6683                if exists("g:netrw_port") && g:netrw_port != ""
   6684                    NetrwKeepj put ='open '.g:netrw_machine.' '.g:netrw_port
   6685                else
   6686                    NetrwKeepj put ='open '.g:netrw_machine
   6687                endif
   6688 
   6689                if exists("g:netrw_uid") && g:netrw_uid != ""
   6690                    if exists("g:netrw_ftp") && g:netrw_ftp == 1
   6691                        NetrwKeepj put =g:netrw_uid
   6692                        if exists("s:netrw_passwd")
   6693                            NetrwKeepj call setline(line("$")+1,'"'.s:netrw_passwd.'"')
   6694                        endif
   6695                    elseif exists("s:netrw_passwd")
   6696                        NetrwKeepj put ='user \"'.g:netrw_uid.'\" \"'.s:netrw_passwd.'\"'
   6697                    endif
   6698                endif
   6699 
   6700                NetrwKeepj call setline(line("$")+1,'lcd "'.fromdir.'"')
   6701 
   6702                if exists("b:netrw_fname") && b:netrw_fname != ""
   6703                    NetrwKeepj call setline(line("$")+1,'cd "'.b:netrw_fname.'"')
   6704                endif
   6705 
   6706                if exists("g:netrw_ftpextracmd")
   6707                    NetrwKeepj put =g:netrw_ftpextracmd
   6708                endif
   6709 
   6710                for fname in a:fname
   6711                    NetrwKeepj call setline(line("$")+1,'put "'.fname.'"')
   6712                endfor
   6713 
   6714                " perform ftp:
   6715                " -i       : turns off interactive prompting from ftp
   6716                " -n  unix : DON'T use <.netrc>, even though it exists
   6717                " -n  win32: quit being obnoxious about password
   6718                NetrwKeepj norm! 1G"_dd
   6719                call netrw#os#Execute(s:netrw_silentxfer."%!".s:netrw_ftp_cmd." ".g:netrw_ftp_options)
   6720                " If the result of the ftp operation isn't blank, show an error message (tnx to Doug Claar)
   6721                sil NetrwKeepj g/Local directory now/d
   6722                call histdel("/",-1)
   6723                if getline(1) !~ "^$" && getline(1) !~ '^Trying '
   6724                    let debugkeep= &debug
   6725                    setl debug=msg
   6726                    call netrw#msg#Notify('ERROR', getline(1))
   6727                    let &debug = debugkeep
   6728                    let mod    = 1
   6729                else
   6730                    bw!|q
   6731                endif
   6732            elseif !exists("b:netrw_method") || b:netrw_method < 0
   6733                return
   6734            endif
   6735        else
   6736            call netrw#msg#Notify('ERROR', printf("can't obtain files with protocol from<%s>", a:tgt))
   6737        endif
   6738    endif
   6739 
   6740 endfunction
   6741 
   6742 " s:NetrwPreview: supports netrw's "p" map {{{2
   6743 function s:NetrwPreview(path) range
   6744    let ykeep= @@
   6745    NetrwKeepj call s:NetrwOptionsSave("s:")
   6746    if a:path !~ '^\*\{1,2}/' && a:path !~ '^\a\{3,}://'
   6747        NetrwKeepj call s:NetrwOptionsSafe(1)
   6748    else
   6749        NetrwKeepj call s:NetrwOptionsSafe(0)
   6750    endif
   6751    if has("quickfix")
   6752        if !isdirectory(s:NetrwFile(a:path))
   6753            if g:netrw_preview
   6754                " vertical split
   6755                let pvhkeep = &pvh
   6756                let winsz   = (g:netrw_winsize > 0)? (g:netrw_winsize*winwidth(0))/100 : -g:netrw_winsize
   6757                let &pvh    = winwidth(0) - winsz
   6758            else
   6759                " horizontal split
   6760                let pvhkeep = &pvh
   6761                let winsz   = (g:netrw_winsize > 0)? (g:netrw_winsize*winheight(0))/100 : -g:netrw_winsize
   6762                let &pvh    = winheight(0) - winsz
   6763            endif
   6764            " g:netrw_preview   g:netrw_alto
   6765            "    1 : vert        1: top       -- preview window is vertically   split off and on the left
   6766            "    1 : vert        0: bot       -- preview window is vertically   split off and on the right
   6767            "    0 :             1: top       -- preview window is horizontally split off and on the top
   6768            "    0 :             0: bot       -- preview window is horizontally split off and on the bottom
   6769            "
   6770            " Note that the file being previewed is already known to not be a directory, hence we can avoid doing a LocalBrowseCheck() check via
   6771            " the BufEnter event set up in netrwPlugin.vim
   6772            let eikeep = &ei
   6773            set ei=BufEnter
   6774            exe (g:netrw_alto? "top " : "bot ").(g:netrw_preview? "vert " : "")."pedit ".fnameescape(a:path)
   6775            let &ei= eikeep
   6776            if exists("pvhkeep")
   6777                let &pvh= pvhkeep
   6778            endif
   6779        else
   6780            call netrw#msg#Notify('WARNING', printf('sorry, cannot preview a directory such as <%s>', a:path))
   6781        endif
   6782    else
   6783        call netrw#msg#Notify('WARNING', 'sorry, to preview your vim needs the quickfix feature compiled in')
   6784    endif
   6785    NetrwKeepj call s:NetrwOptionsRestore("s:")
   6786    let @@= ykeep
   6787 endfunction
   6788 
   6789 " s:NetrwRefresh: {{{2
   6790 function s:NetrwRefresh(islocal,dirname)
   6791    " at the current time (Mar 19, 2007) all calls to NetrwRefresh() call NetrwBrowseChgDir() first.
   6792    setl ma noro
   6793    let ykeep      = @@
   6794    if exists("w:netrw_liststyle") && w:netrw_liststyle == s:TREELIST
   6795        if !exists("w:netrw_treetop")
   6796            if exists("b:netrw_curdir")
   6797                let w:netrw_treetop= b:netrw_curdir
   6798            else
   6799                let w:netrw_treetop= getcwd()
   6800            endif
   6801        endif
   6802        NetrwKeepj call s:NetrwRefreshTreeDict(w:netrw_treetop)
   6803    endif
   6804 
   6805    " save the cursor position before refresh.
   6806    let screenposn = winsaveview()
   6807 
   6808    sil! NetrwKeepj %d _
   6809    if a:islocal
   6810        NetrwKeepj call netrw#LocalBrowseCheck(a:dirname)
   6811    else
   6812        NetrwKeepj call s:NetrwBrowse(a:islocal,a:dirname)
   6813    endif
   6814 
   6815    " restore position
   6816    NetrwKeepj call winrestview(screenposn)
   6817 
   6818    " restore file marks
   6819    if has("syntax") && exists("g:syntax_on") && g:syntax_on
   6820        if exists("s:netrwmarkfilemtch_{bufnr('%')}") && s:netrwmarkfilemtch_{bufnr("%")} != ""
   6821            exe "2match netrwMarkFile /".s:netrwmarkfilemtch_{bufnr("%")}."/"
   6822        else
   6823            2match none
   6824        endif
   6825    endif
   6826 
   6827    "  restore
   6828    let @@= ykeep
   6829 endfunction
   6830 
   6831 " s:NetrwRefreshDir: refreshes a directory by name {{{2
   6832 "                    Called by NetrwMarkFileCopy()
   6833 "                    Interfaces to s:NetrwRefresh() and s:LocalBrowseRefresh()
   6834 function s:NetrwRefreshDir(islocal,dirname)
   6835    if g:netrw_fastbrowse == 0
   6836        " slowest mode (keep buffers refreshed, local or remote)
   6837        let tgtwin= bufwinnr(a:dirname)
   6838 
   6839        if tgtwin > 0
   6840            " tgtwin is being displayed, so refresh it
   6841            let curwin= winnr()
   6842            exe tgtwin."wincmd w"
   6843            NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./',0))
   6844            exe curwin."wincmd w"
   6845 
   6846        elseif bufnr(a:dirname) > 0
   6847            let bn= bufnr(a:dirname)
   6848            exe "sil keepj bd ".bn
   6849        endif
   6850 
   6851    elseif g:netrw_fastbrowse <= 1
   6852        NetrwKeepj call s:LocalBrowseRefresh()
   6853    endif
   6854 endfunction
   6855 
   6856 " s:NetrwSetChgwin: set g:netrw_chgwin; a <cr> will use the specified
   6857 " window number to do its editing in.
   6858 " Supports   [count]C  where the count, if present, is used to specify
   6859 " a window to use for editing via the <cr> mapping.
   6860 function s:NetrwSetChgwin(...)
   6861    if a:0 > 0
   6862        if a:1 == ""    " :NetrwC win#
   6863            let g:netrw_chgwin= winnr()
   6864        else              " :NetrwC
   6865            let g:netrw_chgwin= a:1
   6866        endif
   6867    elseif v:count > 0 " [count]C
   6868        let g:netrw_chgwin= v:count
   6869    else               " C
   6870        let g:netrw_chgwin= winnr()
   6871    endif
   6872    echo "editing window now set to window#".g:netrw_chgwin
   6873 endfunction
   6874 
   6875 " s:NetrwSetSort: sets up the sort based on the g:netrw_sort_sequence {{{2
   6876 "          What this function does is to compute a priority for the patterns
   6877 "          in the g:netrw_sort_sequence.  It applies a substitute to any
   6878 "          "files" that satisfy each pattern, putting the priority / in
   6879 "          front.  An "*" pattern handles the default priority.
   6880 function s:NetrwSetSort()
   6881    let ykeep= @@
   6882    if w:netrw_liststyle == s:LONGLIST
   6883        let seqlist  = substitute(g:netrw_sort_sequence,'\$','\\%(\t\\|\$\\)','ge')
   6884    else
   6885        let seqlist  = g:netrw_sort_sequence
   6886    endif
   6887    " sanity check -- insure that * appears somewhere
   6888    if seqlist == ""
   6889        let seqlist= '*'
   6890    elseif seqlist !~ '\*'
   6891        let seqlist= seqlist.',*'
   6892    endif
   6893    let priority = 1
   6894    while seqlist != ""
   6895        if seqlist =~ ','
   6896            let seq     = substitute(seqlist,',.*$','','e')
   6897            let seqlist = substitute(seqlist,'^.\{-},\(.*\)$','\1','e')
   6898        else
   6899            let seq     = seqlist
   6900            let seqlist = ""
   6901        endif
   6902        if priority < 10
   6903            let spriority= "00".priority.g:netrw_sepchr
   6904        elseif priority < 100
   6905            let spriority= "0".priority.g:netrw_sepchr
   6906        else
   6907            let spriority= priority.g:netrw_sepchr
   6908        endif
   6909 
   6910        " sanity check
   6911        if w:netrw_bannercnt > line("$")
   6912            " apparently no files were left after a Hiding pattern was used
   6913            return
   6914        endif
   6915        if seq == '*'
   6916            let starpriority= spriority
   6917        else
   6918            exe 'sil NetrwKeepj '.w:netrw_bannercnt.',$g/'.seq.'/s/^/'.spriority.'/'
   6919            call histdel("/",-1)
   6920            " sometimes multiple sorting patterns will match the same file or directory.
   6921            " The following substitute is intended to remove the excess matches.
   6922            exe 'sil NetrwKeepj '.w:netrw_bannercnt.',$g/^\d\{3}'.g:netrw_sepchr.'\d\{3}\//s/^\d\{3}'.g:netrw_sepchr.'\(\d\{3}\/\).\@=/\1/e'
   6923            NetrwKeepj call histdel("/",-1)
   6924        endif
   6925        let priority = priority + 1
   6926    endwhile
   6927    if exists("starpriority")
   6928        exe 'sil NetrwKeepj '.w:netrw_bannercnt.',$v/^\d\{3}'.g:netrw_sepchr.'/s/^/'.starpriority.'/e'
   6929        NetrwKeepj call histdel("/",-1)
   6930    endif
   6931 
   6932    " Following line associated with priority -- items that satisfy a priority
   6933    " pattern get prefixed by ###/ which permits easy sorting by priority.
   6934    " Sometimes files can satisfy multiple priority patterns -- only the latest
   6935    " priority pattern needs to be retained.  So, at this point, these excess
   6936    " priority prefixes need to be removed, but not directories that happen to
   6937    " be just digits themselves.
   6938    exe 'sil NetrwKeepj '.w:netrw_bannercnt.',$s/^\(\d\{3}'.g:netrw_sepchr.'\)\%(\d\{3}'.g:netrw_sepchr.'\)\+\ze./\1/e'
   6939    NetrwKeepj call histdel("/",-1)
   6940    let @@= ykeep
   6941 
   6942 endfunction
   6943 
   6944 " s:NetrwSetTgt: sets the target to the specified choice index {{{2
   6945 "    Implements [count]Tb  (bookhist<b>)
   6946 "               [count]Th  (bookhist<h>)
   6947 "               See :help netrw-qb for how to make the choice.
   6948 function s:NetrwSetTgt(islocal,bookhist,choice)
   6949 
   6950    if     a:bookhist == 'b'
   6951        " supports choosing a bookmark as a target using a qb-generated list
   6952        let choice= a:choice - 1
   6953        if exists("g:netrw_bookmarklist[".choice."]")
   6954            call netrw#MakeTgt(g:netrw_bookmarklist[choice])
   6955        else
   6956            echomsg "Sorry, bookmark#".a:choice." doesn't exist!"
   6957        endif
   6958 
   6959    elseif a:bookhist == 'h'
   6960        " supports choosing a history stack entry as a target using a qb-generated list
   6961        let choice= (a:choice % g:netrw_dirhistmax) + 1
   6962        if exists("g:netrw_dirhist_".choice)
   6963            let histentry = g:netrw_dirhist_{choice}
   6964            call netrw#MakeTgt(histentry)
   6965        else
   6966            echomsg "Sorry, history#".a:choice." not available!"
   6967        endif
   6968    endif
   6969 
   6970    " refresh the display
   6971    if !exists("b:netrw_curdir")
   6972        let b:netrw_curdir= getcwd()
   6973    endif
   6974    call s:NetrwRefresh(a:islocal,b:netrw_curdir)
   6975 
   6976 endfunction
   6977 
   6978 " s:NetrwSortStyle: change sorting style (name - time - size - exten) and refresh display {{{2
   6979 function s:NetrwSortStyle(islocal)
   6980    NetrwKeepj call s:NetrwSaveWordPosn()
   6981    let svpos= winsaveview()
   6982 
   6983    let g:netrw_sort_by= (g:netrw_sort_by =~# '^n')? 'time' : (g:netrw_sort_by =~# '^t')? 'size' : (g:netrw_sort_by =~# '^siz')? 'exten' : 'name'
   6984    NetrwKeepj norm! 0
   6985    NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./',0))
   6986    NetrwKeepj call winrestview(svpos)
   6987 endfunction
   6988 
   6989 " s:NetrwSplit: mode {{{2
   6990 "           =0 : net   and o
   6991 "           =1 : net   and t
   6992 "           =2 : net   and v
   6993 "           =3 : local and o
   6994 "           =4 : local and t
   6995 "           =5 : local and v
   6996 function s:NetrwSplit(mode)
   6997 
   6998    let ykeep= @@
   6999    call s:SaveWinVars()
   7000 
   7001    if a:mode == 0
   7002        " remote and o
   7003        let winsz= (g:netrw_winsize > 0)? (g:netrw_winsize*winheight(0))/100 : -g:netrw_winsize
   7004        if winsz == 0|let winsz= ""|endif
   7005        exe (g:netrw_alto? "bel " : "abo ").winsz."wincmd s"
   7006        let s:didsplit= 1
   7007        NetrwKeepj call s:RestoreWinVars()
   7008        NetrwKeepj call s:NetrwBrowse(0,s:NetrwBrowseChgDir(0,s:NetrwGetWord(),1))
   7009        unlet s:didsplit
   7010 
   7011    elseif a:mode == 1
   7012        " remote and t
   7013        let newdir  = s:NetrwBrowseChgDir(0,s:NetrwGetWord(),1)
   7014        tabnew
   7015        let s:didsplit= 1
   7016        NetrwKeepj call s:RestoreWinVars()
   7017        NetrwKeepj call s:NetrwBrowse(0,newdir)
   7018        unlet s:didsplit
   7019 
   7020    elseif a:mode == 2
   7021        " remote and v
   7022        let winsz= (g:netrw_winsize > 0)? (g:netrw_winsize*winwidth(0))/100 : -g:netrw_winsize
   7023        if winsz == 0|let winsz= ""|endif
   7024        exe (g:netrw_altv? "rightb " : "lefta ").winsz."wincmd v"
   7025        let s:didsplit= 1
   7026        NetrwKeepj call s:RestoreWinVars()
   7027        NetrwKeepj call s:NetrwBrowse(0,s:NetrwBrowseChgDir(0,s:NetrwGetWord(),1))
   7028        unlet s:didsplit
   7029 
   7030    elseif a:mode == 3
   7031        " local and o
   7032        let winsz= (g:netrw_winsize > 0)? (g:netrw_winsize*winheight(0))/100 : -g:netrw_winsize
   7033        if winsz == 0|let winsz= ""|endif
   7034        exe (g:netrw_alto? "bel " : "abo ").winsz."wincmd s"
   7035        let s:didsplit= 1
   7036        NetrwKeepj call s:RestoreWinVars()
   7037        NetrwKeepj call netrw#LocalBrowseCheck(s:NetrwBrowseChgDir(1,s:NetrwGetWord(),1))
   7038        unlet s:didsplit
   7039        if &ea
   7040            exe "keepalt wincmd ="
   7041        endif
   7042 
   7043    elseif a:mode == 4
   7044        " local and t
   7045        let cursorword  = s:NetrwGetWord()
   7046        let eikeep      = &ei
   7047        let netrw_winnr = winnr()
   7048        let netrw_line  = line(".")
   7049        let netrw_col   = virtcol(".")
   7050        NetrwKeepj norm! H0
   7051        let netrw_hline = line(".")
   7052        setl ei=all
   7053        exe "NetrwKeepj norm! ".netrw_hline."G0z\<CR>"
   7054        exe "NetrwKeepj norm! ".netrw_line."G0".netrw_col."\<bar>"
   7055        let &ei          = eikeep
   7056        let netrw_curdir = s:NetrwTreeDir(0)
   7057        tabnew
   7058        let b:netrw_curdir = netrw_curdir
   7059        let s:didsplit     = 1
   7060        NetrwKeepj call s:RestoreWinVars()
   7061        NetrwKeepj call netrw#LocalBrowseCheck(s:NetrwBrowseChgDir(1,cursorword,0))
   7062        if &ft == "netrw"
   7063            setl ei=all
   7064            exe "NetrwKeepj norm! ".netrw_hline."G0z\<CR>"
   7065            exe "NetrwKeepj norm! ".netrw_line."G0".netrw_col."\<bar>"
   7066            let &ei= eikeep
   7067        endif
   7068        unlet s:didsplit
   7069 
   7070    elseif a:mode == 5
   7071        " local and v
   7072        let winsz= (g:netrw_winsize > 0)? (g:netrw_winsize*winwidth(0))/100 : -g:netrw_winsize
   7073        if winsz == 0|let winsz= ""|endif
   7074        exe (g:netrw_altv? "rightb " : "lefta ").winsz."wincmd v"
   7075        let s:didsplit= 1
   7076        NetrwKeepj call s:RestoreWinVars()
   7077        NetrwKeepj call netrw#LocalBrowseCheck(s:NetrwBrowseChgDir(1,s:NetrwGetWord(),1))
   7078        unlet s:didsplit
   7079        if &ea
   7080            exe "keepalt wincmd ="
   7081        endif
   7082 
   7083    else
   7084        call netrw#msg#Notify('ERROR', '(NetrwSplit) unsupported mode='.a:mode)
   7085    endif
   7086 
   7087    let @@= ykeep
   7088 endfunction
   7089 
   7090 " s:NetrwTgtMenu: {{{2
   7091 function s:NetrwTgtMenu()
   7092    if !exists("s:netrw_menucnt")
   7093        return
   7094    endif
   7095 
   7096    " the following test assures that gvim is running, has menus available, and has menus enabled.
   7097    if has("gui") && has("menu") && has("gui_running") && &go =~# 'm' && g:netrw_menu
   7098        if exists("g:NetrwTopLvlMenu")
   7099            exe 'sil! unmenu '.g:NetrwTopLvlMenu.'Targets'
   7100        endif
   7101        if !exists("s:netrw_initbookhist")
   7102            call s:NetrwBookHistRead()
   7103        endif
   7104 
   7105        " try to cull duplicate entries
   7106        let tgtdict={}
   7107 
   7108        " target bookmarked places
   7109        if exists("g:netrw_bookmarklist") && g:netrw_bookmarklist != [] && g:netrw_dirhistmax > 0
   7110            let cnt= 1
   7111            for bmd in g:netrw_bookmarklist
   7112                if has_key(tgtdict,bmd)
   7113                    let cnt= cnt + 1
   7114                    continue
   7115                endif
   7116                let tgtdict[bmd]= cnt
   7117                let ebmd= escape(bmd,g:netrw_menu_escape)
   7118                " show bookmarks for goto menu
   7119                exe 'sil! menu <silent> '.g:NetrwMenuPriority.".19.1.".cnt." ".g:NetrwTopLvlMenu.'Targets.'.ebmd." :call netrw#MakeTgt('".bmd."')\<cr>"
   7120                let cnt= cnt + 1
   7121            endfor
   7122        endif
   7123 
   7124        " target directory browsing history
   7125        if exists("g:netrw_dirhistmax") && g:netrw_dirhistmax > 0
   7126            let histcnt = 1
   7127            while histcnt <= g:netrw_dirhistmax
   7128                let priority = g:netrw_dirhistcnt + histcnt
   7129                if exists("g:netrw_dirhist_{histcnt}")
   7130                    let histentry  = g:netrw_dirhist_{histcnt}
   7131                    if has_key(tgtdict,histentry)
   7132                        let histcnt = histcnt + 1
   7133                        continue
   7134                    endif
   7135                    let tgtdict[histentry] = histcnt
   7136                    let ehistentry         = escape(histentry,g:netrw_menu_escape)
   7137                    exe 'sil! menu <silent> '.g:NetrwMenuPriority.".19.2.".priority." ".g:NetrwTopLvlMenu.'Targets.'.ehistentry."     :call netrw#MakeTgt('".histentry."')\<cr>"
   7138                endif
   7139                let histcnt = histcnt + 1
   7140            endwhile
   7141        endif
   7142    endif
   7143 endfunction
   7144 
   7145 " s:NetrwTreeDir: determine tree directory given current cursor position {{{2
   7146 " (full path directory with trailing slash returned)
   7147 function s:NetrwTreeDir(islocal)
   7148 
   7149    if exists("s:treedir") && exists("s:prevwinopen")
   7150        " s:NetrwPrevWinOpen opens a "previous" window -- and thus needs to and does call s:NetrwTreeDir early
   7151        let treedir= s:treedir
   7152        unlet s:treedir
   7153        unlet s:prevwinopen
   7154        return treedir
   7155    endif
   7156    if exists("s:prevwinopen")
   7157        unlet s:prevwinopen
   7158    endif
   7159 
   7160    if !exists("b:netrw_curdir") || b:netrw_curdir == ""
   7161        let b:netrw_curdir= getcwd()
   7162    endif
   7163    let treedir = b:netrw_curdir
   7164    let s:treecurpos= winsaveview()
   7165 
   7166    if exists("w:netrw_liststyle") && w:netrw_liststyle == s:TREELIST
   7167 
   7168        " extract tree directory if on a line specifying a subdirectory (ie. ends with "/")
   7169        let curline= substitute(getline('.'),"\t -->.*$",'','')
   7170        if curline =~ '/$'
   7171            let treedir= substitute(getline('.'),'^\%('.s:treedepthstring.'\)*\([^'.s:treedepthstring.'].\{-}\)$','\1','e')
   7172        elseif curline =~ '@$'
   7173            let potentialdir= resolve(s:NetrwTreePath(w:netrw_treetop))
   7174        else
   7175            let treedir= ""
   7176        endif
   7177 
   7178        " detect user attempting to close treeroot
   7179        if curline !~ '^'.s:treedepthstring && getline('.') != '..'
   7180            " now force a refresh
   7181            sil! NetrwKeepj %d _
   7182            return b:netrw_curdir
   7183        endif
   7184 
   7185        " COMBAK: a symbolic link may point anywhere -- so it will be used to start a new treetop
   7186        "   if a:islocal && curline =~ '@$' && isdirectory(s:NetrwFile(potentialdir))
   7187        "    let newdir          = w:netrw_treetop.'/'.potentialdir
   7188        if a:islocal && curline =~ '@$'
   7189            if isdirectory(s:NetrwFile(potentialdir))
   7190                let treedir = potentialdir
   7191                let w:netrw_treetop = treedir
   7192            endif
   7193        else
   7194            let potentialdir= s:NetrwFile(substitute(curline,'^'.s:treedepthstring.'\+ \(.*\)@$','\1',''))
   7195            let treedir = s:NetrwTreePath(w:netrw_treetop)
   7196        endif
   7197    endif
   7198 
   7199    " sanity maintenance: keep those //s away...
   7200    let treedir= substitute(treedir,'//$','/','')
   7201    return treedir
   7202 endfunction
   7203 
   7204 " s:NetrwTreeDisplay: recursive tree display {{{2
   7205 function s:NetrwTreeDisplay(dir,depth)
   7206    " ensure that there are no folds
   7207    setl nofen
   7208 
   7209    " install ../ and shortdir
   7210    if a:depth == ""
   7211        call setline(line("$")+1,'../')
   7212    endif
   7213    if a:dir =~ '^\a\{3,}://'
   7214        if a:dir == w:netrw_treetop
   7215            let shortdir= a:dir
   7216        else
   7217            let shortdir= substitute(a:dir,'^.*/\([^/]\+\)/$','\1/','e')
   7218        endif
   7219        call setline(line("$")+1,a:depth.shortdir)
   7220    else
   7221        let shortdir= substitute(a:dir,'^.*/','','e')
   7222        call setline(line("$")+1,a:depth.shortdir.'/')
   7223    endif
   7224    " append a / to dir if its missing one
   7225    let dir= a:dir
   7226 
   7227    " display subtrees (if any)
   7228    let depth= s:treedepthstring.a:depth
   7229 
   7230    " implement g:netrw_hide for tree listings (uses g:netrw_list_hide)
   7231    if     g:netrw_hide == 1
   7232        " hide given patterns
   7233        let listhide= split(g:netrw_list_hide,',')
   7234        for pat in listhide
   7235            call filter(w:netrw_treedict[dir],'v:val !~ "'.escape(pat,'\\').'"')
   7236        endfor
   7237 
   7238    elseif g:netrw_hide == 2
   7239        " show given patterns (only)
   7240        let listhide= split(g:netrw_list_hide,',')
   7241        let entries=[]
   7242        for entry in w:netrw_treedict[dir]
   7243            for pat in listhide
   7244                if entry =~ pat
   7245                    call add(entries,entry)
   7246                    break
   7247                endif
   7248            endfor
   7249        endfor
   7250        let w:netrw_treedict[dir]= entries
   7251    endif
   7252    if depth != ""
   7253        " always remove "." and ".." entries when there's depth
   7254        call filter(w:netrw_treedict[dir],'v:val !~ "\\.\\.$"')
   7255        call filter(w:netrw_treedict[dir],'v:val !~ "\\.\\./$"')
   7256        call filter(w:netrw_treedict[dir],'v:val !~ "\\.$"')
   7257        call filter(w:netrw_treedict[dir],'v:val !~ "\\./$"')
   7258    endif
   7259 
   7260    for entry in w:netrw_treedict[dir]
   7261        if dir =~ '/$'
   7262            let direntry= substitute(dir.entry,'[@/]$','','e')
   7263        else
   7264            let direntry= substitute(dir.'/'.entry,'[@/]$','','e')
   7265        endif
   7266        if entry =~ '/$' && has_key(w:netrw_treedict,direntry)
   7267            NetrwKeepj call s:NetrwTreeDisplay(direntry,depth)
   7268        elseif entry =~ '/$' && has_key(w:netrw_treedict,direntry.'/')
   7269            NetrwKeepj call s:NetrwTreeDisplay(direntry.'/',depth)
   7270        elseif entry =~ '@$' && has_key(w:netrw_treedict,direntry.'@')
   7271            NetrwKeepj call s:NetrwTreeDisplay(direntry.'@',depth)
   7272        else
   7273            sil! NetrwKeepj call setline(line("$")+1,depth.entry)
   7274        endif
   7275    endfor
   7276 endfunction
   7277 
   7278 " s:NetrwRefreshTreeDict: updates the contents information for a tree (w:netrw_treedict) {{{2
   7279 function s:NetrwRefreshTreeDict(dir)
   7280    if !exists("w:netrw_treedict")
   7281        return
   7282    endif
   7283 
   7284    for entry in w:netrw_treedict[a:dir]
   7285        let direntry= substitute(a:dir.'/'.entry,'[@/]$','','e')
   7286 
   7287        if entry =~ '/$' && has_key(w:netrw_treedict,direntry)
   7288            NetrwKeepj call s:NetrwRefreshTreeDict(direntry)
   7289            let filelist = s:NetrwLocalListingList(direntry,0)
   7290            let w:netrw_treedict[direntry] = sort(filelist)
   7291 
   7292        elseif entry =~ '/$' && has_key(w:netrw_treedict,direntry.'/')
   7293            NetrwKeepj call s:NetrwRefreshTreeDict(direntry.'/')
   7294            let filelist = s:NetrwLocalListingList(direntry.'/',0)
   7295            let w:netrw_treedict[direntry] = sort(filelist)
   7296 
   7297        elseif entry =~ '@$' && has_key(w:netrw_treedict,direntry.'@')
   7298            NetrwKeepj call s:NetrwRefreshTreeDict(direntry.'/')
   7299            let liststar   = netrw#fs#Glob(direntry.'/','*',1)
   7300            let listdotstar= netrw#fs#Glob(direntry.'/','.*',1)
   7301 
   7302        else
   7303        endif
   7304    endfor
   7305 endfunction
   7306 
   7307 " s:NetrwTreeListing: displays tree listing from treetop on down, using NetrwTreeDisplay() {{{2
   7308 "                     Called by s:PerformListing()
   7309 function s:NetrwTreeListing(dirname)
   7310    if exists("w:netrw_liststyle") && w:netrw_liststyle == s:TREELIST
   7311 
   7312        " update the treetop
   7313        if !exists("w:netrw_treetop")
   7314            let w:netrw_treetop= a:dirname
   7315            let s:netrw_treetop= w:netrw_treetop
   7316        " use \V in case the directory contains specials chars like '$' or '~'
   7317        elseif (w:netrw_treetop =~ ('^'.'\V'.a:dirname)
   7318                    \ && strdisplaywidth(a:dirname) < strdisplaywidth(w:netrw_treetop))
   7319                    \ || a:dirname !~ ('^'.'\V'.w:netrw_treetop)
   7320            let w:netrw_treetop= a:dirname
   7321            let s:netrw_treetop= w:netrw_treetop
   7322        endif
   7323        if exists("w:netrw_treetop")
   7324            let s:netrw_treetop= w:netrw_treetop
   7325        else
   7326            let w:netrw_treetop= getcwd()
   7327            let s:netrw_treetop= w:netrw_treetop
   7328        endif
   7329 
   7330        if !exists("w:netrw_treedict")
   7331            " insure that we have a treedict, albeit empty
   7332            let w:netrw_treedict= {}
   7333        endif
   7334 
   7335        " update the dictionary for the current directory
   7336        exe "sil! NetrwKeepj keepp ".w:netrw_bannercnt.',$g@^\.\.\=/$@d _'
   7337        let w:netrw_treedict[a:dirname]= getline(w:netrw_bannercnt,line("$"))
   7338        exe "sil! NetrwKeepj ".w:netrw_bannercnt.",$d _"
   7339 
   7340        " if past banner, record word
   7341        if exists("w:netrw_bannercnt") && line(".") > w:netrw_bannercnt
   7342            let fname= expand("<cword>")
   7343        else
   7344            let fname= ""
   7345        endif
   7346 
   7347        " display from treetop on down
   7348        NetrwKeepj call s:NetrwTreeDisplay(w:netrw_treetop,"")
   7349 
   7350        " remove any blank line remaining as line#1 (happens in treelisting mode with banner suppressed)
   7351        while getline(1) =~ '^\s*$' && byte2line(1) > 0
   7352            1d
   7353        endwhile
   7354 
   7355        exe "setl ".g:netrw_bufsettings
   7356 
   7357        return
   7358    endif
   7359 endfunction
   7360 
   7361 " s:NetrwTreePath: returns path to current file/directory in tree listing {{{2
   7362 "                  Normally, treetop is w:netrw_treetop, but a
   7363 "                  user of the function ( netrw#SetTreetop() )
   7364 "                  wipes that out prior to calling this function
   7365 function s:NetrwTreePath(treetop)
   7366    if line(".") < w:netrw_bannercnt + 2
   7367        let treedir= a:treetop
   7368        if treedir !~ '/$'
   7369            let treedir= treedir.'/'
   7370        endif
   7371        return treedir
   7372    endif
   7373 
   7374    let svpos = winsaveview()
   7375    let depth = substitute(getline('.'),'^\(\%('.s:treedepthstring.'\)*\)[^'.s:treedepthstring.'].\{-}$','\1','e')
   7376    let depth = substitute(depth,'^'.s:treedepthstring,'','')
   7377    let curline= getline('.')
   7378    if curline =~ '/$'
   7379        let treedir= substitute(curline,'^\%('.s:treedepthstring.'\)*\([^'.s:treedepthstring.'].\{-}\)$','\1','e')
   7380    elseif curline =~ '@\s\+-->'
   7381        let treedir= substitute(curline,'^\%('.s:treedepthstring.'\)*\([^'.s:treedepthstring.'].\{-}\)$','\1','e')
   7382        let treedir= substitute(treedir,'@\s\+-->.*$','','e')
   7383    else
   7384        let treedir= ""
   7385    endif
   7386    " construct treedir by searching backwards at correct depth
   7387    while depth != "" && search('^'.depth.'[^'.s:treedepthstring.'].\{-}/$','bW')
   7388        let dirname= substitute(getline('.'),'^\('.s:treedepthstring.'\)*','','e')
   7389        let treedir= dirname.treedir
   7390        let depth  = substitute(depth,'^'.s:treedepthstring,'','')
   7391    endwhile
   7392    if a:treetop =~ '/$'
   7393        let treedir= a:treetop.treedir
   7394    else
   7395        let treedir= a:treetop.'/'.treedir
   7396    endif
   7397    let treedir= substitute(treedir,'//$','/','')
   7398    call winrestview(svpos)
   7399    return treedir
   7400 endfunction
   7401 
   7402 " s:NetrwWideListing: {{{2
   7403 function s:NetrwWideListing()
   7404 
   7405    if w:netrw_liststyle == s:WIDELIST
   7406        " look for longest filename (cpf=characters per filename)
   7407        " cpf: characters per filename
   7408        " fpl: filenames per line
   7409        " fpc: filenames per column
   7410        setl ma noro
   7411        let dict={}
   7412        " save the unnamed register and register 0-9 and a
   7413        let dict.a=[getreg('a'), getregtype('a')]
   7414        for i in range(0, 9)
   7415            let dict[i] = [getreg(i), getregtype(i)]
   7416        endfor
   7417        let dict.unnamed = [getreg(''), getregtype('')]
   7418        let b:netrw_cpf= 0
   7419        if line("$") >= w:netrw_bannercnt
   7420            " determine the maximum filename size; use that to set cpf
   7421            exe 'sil NetrwKeepj '.w:netrw_bannercnt.',$g/^./if virtcol("$") > b:netrw_cpf|let b:netrw_cpf= virtcol("$")|endif'
   7422            NetrwKeepj call histdel("/",-1)
   7423        else
   7424            " restore stored registers
   7425            call s:RestoreRegister(dict)
   7426            return
   7427        endif
   7428        " allow for two spaces to separate columns
   7429        let b:netrw_cpf= b:netrw_cpf + 2
   7430 
   7431        " determine qty files per line (fpl)
   7432        let w:netrw_fpl= winwidth(0)/b:netrw_cpf
   7433        if w:netrw_fpl <= 0
   7434            let w:netrw_fpl= 1
   7435        endif
   7436 
   7437        " make wide display
   7438        "   fpc: files per column of wide listing
   7439        exe 'sil NetrwKeepj '.w:netrw_bannercnt.',$s/^.*$/\=escape(printf("%-'.b:netrw_cpf.'S",submatch(0)),"\\")/'
   7440        NetrwKeepj call histdel("/",-1)
   7441        let fpc         = (line("$") - w:netrw_bannercnt + w:netrw_fpl)/w:netrw_fpl
   7442        let newcolstart = w:netrw_bannercnt + fpc
   7443        let newcolend   = newcolstart + fpc - 1
   7444        if !has('nvim') && has("clipboard") && g:netrw_clipboard
   7445            sil! let keepregstar = @*
   7446            sil! let keepregplus = @+
   7447        endif
   7448        while line("$") >= newcolstart
   7449            if newcolend > line("$") | let newcolend= line("$") | endif
   7450            let newcolqty= newcolend - newcolstart
   7451            exe newcolstart
   7452            " COMBAK: both of the visual-mode using lines below are problematic vis-a-vis @*
   7453            if newcolqty == 0
   7454                exe "sil! NetrwKeepj norm! 0\<c-v>$h\"ax".w:netrw_bannercnt."G$\"ap"
   7455            else
   7456                exe "sil! NetrwKeepj norm! 0\<c-v>".newcolqty.'j$h"ax'.w:netrw_bannercnt.'G$"ap'
   7457            endif
   7458            exe "sil! NetrwKeepj ".newcolstart.','.newcolend.'d _'
   7459            exe 'sil! NetrwKeepj '.w:netrw_bannercnt
   7460        endwhile
   7461        if !has('nvim') && has("clipboard")
   7462            if @* != keepregstar | sil! let @* = keepregstar | endif
   7463            if @+ != keepregplus | sil! let @+ = keepregplus | endif
   7464        endif
   7465        exe "sil! NetrwKeepj ".w:netrw_bannercnt.',$s/\s\+$//e'
   7466        NetrwKeepj call histdel("/",-1)
   7467        exe 'nno <buffer> <silent> w :call search(''^.\\|\s\s\zs\S'',''W'')'."\<cr>"
   7468        exe 'nno <buffer> <silent> b :call search(''^.\\|\s\s\zs\S'',''bW'')'."\<cr>"
   7469        exe "setl ".g:netrw_bufsettings
   7470        call s:RestoreRegister(dict)
   7471        return
   7472    else
   7473        if hasmapto("w","n")
   7474            sil! nunmap <buffer> w
   7475        endif
   7476        if hasmapto("b","n")
   7477            sil! nunmap <buffer> b
   7478        endif
   7479    endif
   7480 endfunction
   7481 
   7482 " s:PerformListing: {{{2
   7483 function s:PerformListing(islocal)
   7484    sil! NetrwKeepj %d _
   7485    "  call DechoBuf(bufnr("%"))
   7486 
   7487    " set up syntax highlighting {{{3
   7488    sil! setl ft=netrw
   7489 
   7490    NetrwKeepj call s:NetrwOptionsSafe(a:islocal)
   7491    setl noro ma
   7492 
   7493 
   7494    if exists("w:netrw_liststyle") && w:netrw_liststyle == s:TREELIST && exists("w:netrw_treedict")
   7495        " force a refresh for tree listings
   7496        sil! NetrwKeepj %d _
   7497    endif
   7498 
   7499    " save current directory on directory history list
   7500    NetrwKeepj call s:NetrwBookHistHandler(3,b:netrw_curdir)
   7501 
   7502    " Set up the banner {{{3
   7503    if g:netrw_banner
   7504        NetrwKeepj call setline(1,'" ============================================================================')
   7505        if exists("g:netrw_pchk")
   7506            " this undocumented option allows pchk to run with different versions of netrw without causing spurious
   7507            " failure detections.
   7508            NetrwKeepj call setline(2,'" Netrw Directory Listing')
   7509        else
   7510            NetrwKeepj call setline(2,'" Netrw Directory Listing                                        (netrw '.g:loaded_netrw.')')
   7511        endif
   7512        if exists("g:netrw_pchk")
   7513            let curdir= substitute(b:netrw_curdir,expand("$HOME"),'~','')
   7514        else
   7515            let curdir= b:netrw_curdir
   7516        endif
   7517        if exists("g:netrw_bannerbackslash") && g:netrw_bannerbackslash
   7518            NetrwKeepj call setline(3,'"   '.substitute(curdir,'/','\\','g'))
   7519        else
   7520            NetrwKeepj call setline(3,'"   '.curdir)
   7521        endif
   7522        let w:netrw_bannercnt= 3
   7523        NetrwKeepj exe "sil! NetrwKeepj ".w:netrw_bannercnt
   7524    else
   7525        NetrwKeepj 1
   7526        let w:netrw_bannercnt= 1
   7527    endif
   7528 
   7529    " construct sortby string: [name|time|size|exten] [reversed]
   7530    let sortby= g:netrw_sort_by
   7531    if g:netrw_sort_direction =~# "^r"
   7532        let sortby= sortby." reversed"
   7533    endif
   7534 
   7535    " Sorted by... {{{3
   7536    if g:netrw_banner
   7537        if g:netrw_sort_by =~# "^n"
   7538            " sorted by name (also includes the sorting sequence in the banner)
   7539            NetrwKeepj put ='\"   Sorted by      '.sortby
   7540            NetrwKeepj put ='\"   Sort sequence: '.g:netrw_sort_sequence
   7541            let w:netrw_bannercnt= w:netrw_bannercnt + 2
   7542        else
   7543            " sorted by time, size, exten
   7544            NetrwKeepj put ='\"   Sorted by '.sortby
   7545            let w:netrw_bannercnt= w:netrw_bannercnt + 1
   7546        endif
   7547        exe "sil! NetrwKeepj ".w:netrw_bannercnt
   7548    endif
   7549 
   7550    " show copy/move target, if any {{{3
   7551    if g:netrw_banner
   7552        if exists("s:netrwmftgt") && exists("s:netrwmftgt_islocal")
   7553            NetrwKeepj put =''
   7554            if s:netrwmftgt_islocal
   7555                sil! NetrwKeepj call setline(line("."),'"   Copy/Move Tgt: '.s:netrwmftgt.' (local)')
   7556            else
   7557                sil! NetrwKeepj call setline(line("."),'"   Copy/Move Tgt: '.s:netrwmftgt.' (remote)')
   7558            endif
   7559            let w:netrw_bannercnt= w:netrw_bannercnt + 1
   7560        else
   7561        endif
   7562        exe "sil! NetrwKeepj ".w:netrw_bannercnt
   7563    endif
   7564 
   7565    " Hiding...  -or-  Showing... {{{3
   7566    if g:netrw_banner
   7567        if g:netrw_list_hide != "" && g:netrw_hide
   7568            if g:netrw_hide == 1
   7569                NetrwKeepj put ='\"   Hiding:        '.g:netrw_list_hide
   7570            else
   7571                NetrwKeepj put ='\"   Showing:       '.g:netrw_list_hide
   7572            endif
   7573            let w:netrw_bannercnt= w:netrw_bannercnt + 1
   7574        endif
   7575        exe "NetrwKeepj ".w:netrw_bannercnt
   7576 
   7577        let quickhelp   = g:netrw_quickhelp%len(s:QuickHelp)
   7578        NetrwKeepj put ='\"   Quick Help: <F1>:help  '.s:QuickHelp[quickhelp]
   7579        NetrwKeepj put ='\" =============================================================================='
   7580        let w:netrw_bannercnt= w:netrw_bannercnt + 2
   7581    endif
   7582 
   7583    " bannercnt should index the line just after the banner
   7584    if g:netrw_banner
   7585        let w:netrw_bannercnt= w:netrw_bannercnt + 1
   7586        exe "sil! NetrwKeepj ".w:netrw_bannercnt
   7587    endif
   7588 
   7589    " get list of files
   7590    if a:islocal
   7591        let filelist = s:NetrwLocalListingList(b:netrw_curdir, 1)
   7592        call append(w:netrw_bannercnt - 1, filelist)
   7593        silent! NetrwKeepj g/^$/d
   7594        silent! NetrwKeepj %s/\r$//e
   7595        execute printf("setl ts=%d", g:netrw_maxfilenamelen + 1)
   7596    else " remote
   7597        NetrwKeepj let badresult= s:NetrwRemoteListing()
   7598        if badresult
   7599            return
   7600        endif
   7601    endif
   7602 
   7603    " manipulate the directory listing (hide, sort) {{{3
   7604    if !exists("w:netrw_bannercnt")
   7605        let w:netrw_bannercnt= 0
   7606    endif
   7607 
   7608    if !g:netrw_banner || line("$") >= w:netrw_bannercnt
   7609        if g:netrw_hide && g:netrw_list_hide != ""
   7610            NetrwKeepj call s:NetrwListHide()
   7611        endif
   7612        if !g:netrw_banner || line("$") >= w:netrw_bannercnt
   7613 
   7614            if g:netrw_sort_by =~# "^n"
   7615                " sort by name
   7616                NetrwKeepj call s:NetrwSetSort()
   7617 
   7618                if !g:netrw_banner || w:netrw_bannercnt < line("$")
   7619                    if g:netrw_sort_direction =~# 'n'
   7620                        " name: sort by name of file
   7621                        exe 'sil NetrwKeepj '.w:netrw_bannercnt.',$sort'.' '.g:netrw_sort_options
   7622                    else
   7623                        " reverse direction sorting
   7624                        exe 'sil NetrwKeepj '.w:netrw_bannercnt.',$sort!'.' '.g:netrw_sort_options
   7625                    endif
   7626                endif
   7627 
   7628                " remove priority pattern prefix
   7629                exe 'sil! NetrwKeepj '.w:netrw_bannercnt.',$s/^\d\{3}'.g:netrw_sepchr.'//e'
   7630                NetrwKeepj call histdel("/",-1)
   7631 
   7632            elseif g:netrw_sort_by =~# "^ext"
   7633                " exten: sort by extension
   7634                "   The histdel(...,-1) calls remove the last search from the search history
   7635                exe 'sil NetrwKeepj '.w:netrw_bannercnt.',$g+/+s/^/001'.g:netrw_sepchr.'/'
   7636                NetrwKeepj call histdel("/",-1)
   7637                exe 'sil NetrwKeepj '.w:netrw_bannercnt.',$v+[./]+s/^/002'.g:netrw_sepchr.'/'
   7638                NetrwKeepj call histdel("/",-1)
   7639                exe 'sil NetrwKeepj '.w:netrw_bannercnt.',$v+['.g:netrw_sepchr.'/]+s/^\(.*\.\)\(.\{-\}\)$/\2'.g:netrw_sepchr.'&/e'
   7640                NetrwKeepj call histdel("/",-1)
   7641                if !g:netrw_banner || w:netrw_bannercnt < line("$")
   7642                    if g:netrw_sort_direction =~# 'n'
   7643                        " normal direction sorting
   7644                        exe 'sil NetrwKeepj '.w:netrw_bannercnt.',$sort'.' '.g:netrw_sort_options
   7645                    else
   7646                        " reverse direction sorting
   7647                        exe 'sil NetrwKeepj '.w:netrw_bannercnt.',$sort!'.' '.g:netrw_sort_options
   7648                    endif
   7649                endif
   7650                exe 'sil! NetrwKeepj '.w:netrw_bannercnt.',$s/^.\{-}'.g:netrw_sepchr.'//e'
   7651                NetrwKeepj call histdel("/",-1)
   7652 
   7653            elseif a:islocal
   7654                if !g:netrw_banner || w:netrw_bannercnt < line("$")
   7655                    if g:netrw_sort_direction =~# 'n'
   7656                        exe 'sil! NetrwKeepj '.w:netrw_bannercnt.',$sort'.' '.g:netrw_sort_options
   7657                    else
   7658                        exe 'sil! NetrwKeepj '.w:netrw_bannercnt.',$sort!'.' '.g:netrw_sort_options
   7659                    endif
   7660                    exe 'sil! NetrwKeepj '.w:netrw_bannercnt.',$s/^\d\{-}\///e'
   7661                    NetrwKeepj call histdel("/",-1)
   7662                endif
   7663            endif
   7664 
   7665        elseif g:netrw_sort_direction =~# 'r'
   7666            if !g:netrw_banner || w:netrw_bannercnt < line('$')
   7667                exe 'sil! NetrwKeepj '.w:netrw_bannercnt.',$g/^/m '.w:netrw_bannercnt
   7668                call histdel("/",-1)
   7669            endif
   7670        endif
   7671    endif
   7672 
   7673    " convert to wide/tree listing {{{3
   7674    NetrwKeepj call s:NetrwWideListing()
   7675    NetrwKeepj call s:NetrwTreeListing(b:netrw_curdir)
   7676 
   7677    " resolve symbolic links if local and (thin or tree)
   7678    if a:islocal && (w:netrw_liststyle == s:THINLIST || (exists("w:netrw_liststyle") && w:netrw_liststyle == s:TREELIST))
   7679        sil! keepp g/@$/call s:ShowLink()
   7680    endif
   7681 
   7682    if exists("w:netrw_bannercnt") && (line("$") >= w:netrw_bannercnt || !g:netrw_banner)
   7683        " place cursor on the top-left corner of the file listing
   7684        exe 'sil! '.w:netrw_bannercnt
   7685        sil! NetrwKeepj norm! 0
   7686    else
   7687    endif
   7688 
   7689    " record previous current directory
   7690    let w:netrw_prvdir= b:netrw_curdir
   7691 
   7692    " save certain window-oriented variables into buffer-oriented variables {{{3
   7693    NetrwKeepj call s:SetBufWinVars()
   7694    NetrwKeepj call s:NetrwOptionsRestore("w:")
   7695 
   7696    " set display to netrw display settings
   7697    exe "setl ".g:netrw_bufsettings
   7698    if g:netrw_liststyle == s:LONGLIST
   7699        exe "setl ts=".(g:netrw_maxfilenamelen+1)
   7700    endif
   7701    "  call DechoBuf(bufnr("%"))
   7702 
   7703    if exists("s:treecurpos")
   7704        NetrwKeepj call winrestview(s:treecurpos)
   7705        unlet s:treecurpos
   7706    endif
   7707 
   7708 endfunction
   7709 
   7710 " s:SetupNetrwStatusLine: {{{2
   7711 function s:SetupNetrwStatusLine(statline)
   7712 
   7713    if !exists("s:netrw_setup_statline")
   7714        let s:netrw_setup_statline= 1
   7715 
   7716        if !exists("s:netrw_users_stl")
   7717            let s:netrw_users_stl= &stl
   7718        endif
   7719        if !exists("s:netrw_users_ls")
   7720            let s:netrw_users_ls= &laststatus
   7721        endif
   7722 
   7723        " set up User9 highlighting as needed
   7724        let dict={}
   7725        let dict.a=[getreg('a'), getregtype('a')]
   7726        redir @a
   7727        try
   7728            hi User9
   7729        catch /^Vim\%((\a\{3,})\)\=:E411/
   7730            if &bg == "dark"
   7731                hi User9 ctermfg=yellow ctermbg=blue guifg=yellow guibg=blue
   7732            else
   7733                hi User9 ctermbg=yellow ctermfg=blue guibg=yellow guifg=blue
   7734            endif
   7735        endtry
   7736        redir END
   7737        call s:RestoreRegister(dict)
   7738    endif
   7739 
   7740    " set up status line (may use User9 highlighting)
   7741    " insure that windows have a statusline
   7742    " make sure statusline is displayed
   7743    let &l:stl=a:statline
   7744    setl laststatus=2
   7745    redraw
   7746 
   7747 endfunction
   7748 
   7749 "  Remote Directory Browsing Support:  {{{1
   7750 
   7751 " s:NetrwRemoteFtpCmd: unfortunately, not all ftp servers honor options for ls {{{2
   7752 "  This function assumes that a long listing will be received.  Size, time,
   7753 "  and reverse sorts will be requested of the server but not otherwise
   7754 "  enforced here.
   7755 function s:NetrwRemoteFtpCmd(path,listcmd)
   7756    " sanity check: {{{3
   7757    if !exists("w:netrw_method")
   7758        if exists("b:netrw_method")
   7759            let w:netrw_method= b:netrw_method
   7760        else
   7761            call netrw#msg#Notify('ERROR', '(s:NetrwRemoteFtpCmd) internal netrw error')
   7762            return
   7763        endif
   7764    endif
   7765 
   7766    " WinXX ftp uses unix style input, so set ff to unix  " {{{3
   7767    let ffkeep= &ff
   7768    setl ma ff=unix noro
   7769 
   7770    " clear off any older non-banner lines        " {{{3
   7771    " note that w:netrw_bannercnt indexes the line after the banner
   7772    exe "sil! NetrwKeepj ".w:netrw_bannercnt.",$d _"
   7773 
   7774    ".........................................
   7775    if w:netrw_method == 2 || w:netrw_method == 5 " {{{3
   7776        " ftp + <.netrc>:  Method #2
   7777        if a:path != ""
   7778            NetrwKeepj put ='cd \"'.a:path.'\"'
   7779        endif
   7780        if exists("g:netrw_ftpextracmd")
   7781            NetrwKeepj put =g:netrw_ftpextracmd
   7782        endif
   7783        NetrwKeepj call setline(line("$")+1,a:listcmd)
   7784        if exists("g:netrw_port") && g:netrw_port != ""
   7785            exe s:netrw_silentxfer." NetrwKeepj ".w:netrw_bannercnt.",$!".s:netrw_ftp_cmd." -i ".netrw#os#Escape(g:netrw_machine,1)." ".netrw#os#Escape(g:netrw_port,1)
   7786        else
   7787            exe s:netrw_silentxfer." NetrwKeepj ".w:netrw_bannercnt.",$!".s:netrw_ftp_cmd." -i ".netrw#os#Escape(g:netrw_machine,1)
   7788        endif
   7789 
   7790        ".........................................
   7791    elseif w:netrw_method == 3    " {{{3
   7792        " ftp + machine,id,passwd,filename:  Method #3
   7793        setl ff=unix
   7794        if exists("g:netrw_port") && g:netrw_port != ""
   7795            NetrwKeepj put ='open '.g:netrw_machine.' '.g:netrw_port
   7796        else
   7797            NetrwKeepj put ='open '.g:netrw_machine
   7798        endif
   7799 
   7800        " handle userid and password
   7801        let host= substitute(g:netrw_machine,'\..*$','','')
   7802        if exists("s:netrw_hup") && exists("s:netrw_hup[host]")
   7803            call netrw#NetUserPass("ftp:".host)
   7804        endif
   7805        if exists("g:netrw_uid") && g:netrw_uid != ""
   7806            if exists("g:netrw_ftp") && g:netrw_ftp == 1
   7807                NetrwKeepj put =g:netrw_uid
   7808                if exists("s:netrw_passwd") && s:netrw_passwd != ""
   7809                    NetrwKeepj put ='\"'.s:netrw_passwd.'\"'
   7810                endif
   7811            elseif exists("s:netrw_passwd")
   7812                NetrwKeepj put ='user \"'.g:netrw_uid.'\" \"'.s:netrw_passwd.'\"'
   7813            endif
   7814        endif
   7815 
   7816        if a:path != ""
   7817            NetrwKeepj put ='cd \"'.a:path.'\"'
   7818        endif
   7819        if exists("g:netrw_ftpextracmd")
   7820            NetrwKeepj put =g:netrw_ftpextracmd
   7821        endif
   7822        NetrwKeepj call setline(line("$")+1,a:listcmd)
   7823 
   7824        " perform ftp:
   7825        " -i       : turns off interactive prompting from ftp
   7826        " -n  unix : DON'T use <.netrc>, even though it exists
   7827        " -n  win32: quit being obnoxious about password
   7828        if exists("w:netrw_bannercnt")
   7829            call netrw#os#Execute(s:netrw_silentxfer.w:netrw_bannercnt.",$!".s:netrw_ftp_cmd." ".g:netrw_ftp_options)
   7830        endif
   7831 
   7832        ".........................................
   7833    elseif w:netrw_method == 9    " {{{3
   7834        " sftp username@machine: Method #9
   7835        " s:netrw_sftp_cmd
   7836        setl ff=unix
   7837 
   7838        " restore settings
   7839        let &l:ff= ffkeep
   7840        return
   7841 
   7842        ".........................................
   7843    else  " {{{3
   7844        call netrw#msg#Notify('WARNING', printf('unable to comply with your request<%s>', bufname("%")))
   7845    endif
   7846 
   7847    " cleanup for Windows " {{{3
   7848    if has("win32")
   7849        sil! NetrwKeepj %s/\r$//e
   7850        NetrwKeepj call histdel("/",-1)
   7851    endif
   7852    if a:listcmd == "dir"
   7853        " infer directory/link based on the file permission string
   7854        sil! NetrwKeepj g/d\%([-r][-w][-x]\)\{3}/NetrwKeepj s@$@/@e
   7855        sil! NetrwKeepj g/l\%([-r][-w][-x]\)\{3}/NetrwKeepj s/$/@/e
   7856        NetrwKeepj call histdel("/",-1)
   7857        NetrwKeepj call histdel("/",-1)
   7858        if w:netrw_liststyle == s:THINLIST || w:netrw_liststyle == s:WIDELIST || (exists("w:netrw_liststyle") && w:netrw_liststyle == s:TREELIST)
   7859            exe "sil! NetrwKeepj ".w:netrw_bannercnt.',$s/^\%(\S\+\s\+\)\{8}//e'
   7860            NetrwKeepj call histdel("/",-1)
   7861        endif
   7862    endif
   7863 
   7864    " ftp's listing doesn't seem to include ./ or ../ " {{{3
   7865    if !search('^\.\/$\|\s\.\/$','wn')
   7866        exe 'NetrwKeepj '.w:netrw_bannercnt
   7867        NetrwKeepj put ='./'
   7868    endif
   7869    if !search('^\.\.\/$\|\s\.\.\/$','wn')
   7870        exe 'NetrwKeepj '.w:netrw_bannercnt
   7871        NetrwKeepj put ='../'
   7872    endif
   7873 
   7874    " restore settings " {{{3
   7875    let &l:ff= ffkeep
   7876 endfunction
   7877 
   7878 " s:NetrwRemoteListing: {{{2
   7879 function s:NetrwRemoteListing()
   7880 
   7881    if !exists("w:netrw_bannercnt") && exists("s:bannercnt")
   7882        let w:netrw_bannercnt= s:bannercnt
   7883    endif
   7884    if !exists("w:netrw_bannercnt") && exists("b:bannercnt")
   7885        let w:netrw_bannercnt= b:bannercnt
   7886    endif
   7887 
   7888    call s:RemotePathAnalysis(b:netrw_curdir)
   7889 
   7890    " sanity check:
   7891    if exists("b:netrw_method") && b:netrw_method =~ '[235]'
   7892        if !executable("ftp")
   7893            call netrw#msg#Notify('ERROR', "this system doesn't support remote directory listing via ftp")
   7894            call s:NetrwOptionsRestore("w:")
   7895            return -1
   7896        endif
   7897 
   7898    elseif !exists("g:netrw_list_cmd") || g:netrw_list_cmd == ''
   7899        if g:netrw_list_cmd == ""
   7900            call netrw#msg#Notify('ERROR', printf('your g:netrw_list_cmd is empty; perhaps %s is not executable on your system', g:netrw_ssh_cmd))
   7901        else
   7902            call netrw#msg#Notify('ERROR', "this system doesn't support remote directory listing via ".g:netrw_list_cmd)
   7903        endif
   7904 
   7905        NetrwKeepj call s:NetrwOptionsRestore("w:")
   7906        return -1
   7907    endif  " (remote handling sanity check)
   7908 
   7909    if exists("b:netrw_method")
   7910        let w:netrw_method= b:netrw_method
   7911    endif
   7912 
   7913    if s:method == "ftp"
   7914        " use ftp to get remote file listing {{{3
   7915        let s:method  = "ftp"
   7916        let listcmd = g:netrw_ftp_list_cmd
   7917        if g:netrw_sort_by =~# '^t'
   7918            let listcmd= g:netrw_ftp_timelist_cmd
   7919        elseif g:netrw_sort_by =~# '^s'
   7920            let listcmd= g:netrw_ftp_sizelist_cmd
   7921        endif
   7922        call s:NetrwRemoteFtpCmd(s:path,listcmd)
   7923 
   7924        " report on missing file or directory messages
   7925        if search('[Nn]o such file or directory\|Failed to change directory')
   7926            let mesg= getline(".")
   7927            if exists("w:netrw_bannercnt")
   7928                setl ma
   7929                exe w:netrw_bannercnt.",$d _"
   7930                setl noma
   7931            endif
   7932            NetrwKeepj call s:NetrwOptionsRestore("w:")
   7933            call netrw#msg#Notify('WARNING', mesg)
   7934            return -1
   7935        endif
   7936 
   7937        if w:netrw_liststyle == s:THINLIST || w:netrw_liststyle == s:WIDELIST || (exists("w:netrw_liststyle") && w:netrw_liststyle == s:TREELIST)
   7938            " shorten the listing
   7939            exe "sil! keepalt NetrwKeepj ".w:netrw_bannercnt
   7940 
   7941            " cleanup
   7942            if g:netrw_ftp_browse_reject != ""
   7943                exe "sil! keepalt NetrwKeepj g/".g:netrw_ftp_browse_reject."/NetrwKeepj d"
   7944                NetrwKeepj call histdel("/",-1)
   7945            endif
   7946            sil! NetrwKeepj %s/\r$//e
   7947            NetrwKeepj call histdel("/",-1)
   7948 
   7949            " if there's no ../ listed, then put ../ in
   7950            let line1= line(".")
   7951            exe "sil! NetrwKeepj ".w:netrw_bannercnt
   7952            let line2= search('\.\.\/\%(\s\|$\)','cnW')
   7953            if line2 == 0
   7954                sil! NetrwKeepj put='../'
   7955            endif
   7956            exe "sil! NetrwKeepj ".line1
   7957            sil! NetrwKeepj norm! 0
   7958 
   7959            if search('^\d\{2}-\d\{2}-\d\{2}\s','n') " M$ ftp site cleanup
   7960                exe 'sil! NetrwKeepj '.w:netrw_bannercnt.',$s/^\d\{2}-\d\{2}-\d\{2}\s\+\d\+:\d\+[AaPp][Mm]\s\+\%(<DIR>\|\d\+\)\s\+//'
   7961                NetrwKeepj call histdel("/",-1)
   7962            else " normal ftp cleanup
   7963                exe 'sil! NetrwKeepj '.w:netrw_bannercnt.',$s/^\(\%(\S\+\s\+\)\{7}\S\+\)\s\+\(\S.*\)$/\2/e'
   7964                exe "sil! NetrwKeepj ".w:netrw_bannercnt.',$g/ -> /s# -> .*/$#/#e'
   7965                exe "sil! NetrwKeepj ".w:netrw_bannercnt.',$g/ -> /s# -> .*$#/#e'
   7966                NetrwKeepj call histdel("/",-1)
   7967                NetrwKeepj call histdel("/",-1)
   7968                NetrwKeepj call histdel("/",-1)
   7969            endif
   7970        endif
   7971 
   7972    else
   7973        " use ssh to get remote file listing {{{3
   7974        let listcmd= s:MakeSshCmd(g:netrw_list_cmd)
   7975        if g:netrw_scp_cmd =~ '^pscp'
   7976            exe "NetrwKeepj r! ".listcmd.netrw#os#Escape(s:path, 1)
   7977            " remove rubbish and adjust listing format of 'pscp' to 'ssh ls -FLa' like
   7978            sil! NetrwKeepj g/^Listing directory/NetrwKeepj d
   7979            sil! NetrwKeepj g/^d[-rwx][-rwx][-rwx]/NetrwKeepj s+$+/+e
   7980            sil! NetrwKeepj g/^l[-rwx][-rwx][-rwx]/NetrwKeepj s+$+@+e
   7981            NetrwKeepj call histdel("/",-1)
   7982            NetrwKeepj call histdel("/",-1)
   7983            NetrwKeepj call histdel("/",-1)
   7984            if g:netrw_liststyle != s:LONGLIST
   7985                sil! NetrwKeepj g/^[dlsp-][-rwx][-rwx][-rwx]/NetrwKeepj s/^.*\s\(\S\+\)$/\1/e
   7986                NetrwKeepj call histdel("/",-1)
   7987            endif
   7988        else
   7989            if s:path == ""
   7990                exe "NetrwKeepj keepalt r! ".listcmd
   7991            else
   7992                exe "NetrwKeepj keepalt r! ".listcmd.' '.netrw#os#Escape(fnameescape(s:path),1)
   7993            endif
   7994        endif
   7995 
   7996        " cleanup
   7997        if g:netrw_ssh_browse_reject != ""
   7998            exe "sil! g/".g:netrw_ssh_browse_reject."/NetrwKeepj d"
   7999            NetrwKeepj call histdel("/",-1)
   8000        endif
   8001    endif
   8002 
   8003    if w:netrw_liststyle == s:LONGLIST
   8004        " do a long listing; these substitutions need to be done prior to sorting {{{3
   8005 
   8006        if s:method == "ftp"
   8007            " cleanup
   8008            exe "sil! NetrwKeepj ".w:netrw_bannercnt
   8009            while getline('.') =~# g:netrw_ftp_browse_reject
   8010                sil! NetrwKeepj d
   8011            endwhile
   8012            " if there's no ../ listed, then put ../ in
   8013            let line1= line(".")
   8014            sil! NetrwKeepj 1
   8015            sil! NetrwKeepj call search('^\.\.\/\%(\s\|$\)','W')
   8016            let line2= line(".")
   8017            if line2 == 0
   8018                if b:netrw_curdir != '/'
   8019                    exe 'sil! NetrwKeepj '.w:netrw_bannercnt."put='../'"
   8020                endif
   8021            endif
   8022            exe "sil! NetrwKeepj ".line1
   8023            sil! NetrwKeepj norm! 0
   8024        endif
   8025 
   8026        if search('^\d\{2}-\d\{2}-\d\{2}\s','n') " M$ ftp site cleanup
   8027            exe 'sil! NetrwKeepj '.w:netrw_bannercnt.',$s/^\(\d\{2}-\d\{2}-\d\{2}\s\+\d\+:\d\+[AaPp][Mm]\s\+\%(<DIR>\|\d\+\)\s\+\)\(\w.*\)$/\2\t\1/'
   8028        elseif exists("w:netrw_bannercnt") && w:netrw_bannercnt <= line("$")
   8029            exe 'sil NetrwKeepj '.w:netrw_bannercnt.',$s/ -> .*$//e'
   8030            exe 'sil NetrwKeepj '.w:netrw_bannercnt.',$s/^\(\%(\S\+\s\+\)\{7}\S\+\)\s\+\(\S.*\)$/\2 \t\1/e'
   8031            exe 'sil NetrwKeepj '.w:netrw_bannercnt
   8032            NetrwKeepj call histdel("/",-1)
   8033            NetrwKeepj call histdel("/",-1)
   8034            NetrwKeepj call histdel("/",-1)
   8035        endif
   8036    endif
   8037 
   8038 
   8039    return 0
   8040 endfunction
   8041 
   8042 " s:NetrwRemoteRm: remove/delete a remote file or directory {{{2
   8043 function s:NetrwRemoteRm(usrhost,path) range
   8044    let svpos= winsaveview()
   8045 
   8046    let all= 0
   8047    if exists("s:netrwmarkfilelist_{bufnr('%')}")
   8048        " remove all marked files
   8049        for fname in s:netrwmarkfilelist_{bufnr("%")}
   8050            let ok= s:NetrwRemoteRmFile(a:path,fname,all)
   8051            if ok =~# 'q\%[uit]'
   8052                break
   8053            elseif ok =~# 'a\%[ll]'
   8054                let all= 1
   8055            endif
   8056        endfor
   8057        call s:NetrwUnmarkList(bufnr("%"),b:netrw_curdir)
   8058 
   8059    else
   8060        " remove files specified by range
   8061 
   8062        " preparation for removing multiple files/directories
   8063        let keepsol = &l:sol
   8064        setl nosol
   8065        let ctr    = a:firstline
   8066 
   8067        " remove multiple files and directories
   8068        while ctr <= a:lastline
   8069            exe "NetrwKeepj ".ctr
   8070            let ok= s:NetrwRemoteRmFile(a:path,s:NetrwGetWord(),all)
   8071            if ok =~# 'q\%[uit]'
   8072                break
   8073            elseif ok =~# 'a\%[ll]'
   8074                let all= 1
   8075            endif
   8076            let ctr= ctr + 1
   8077        endwhile
   8078        let &l:sol = keepsol
   8079    endif
   8080 
   8081    " refresh the (remote) directory listing
   8082    NetrwKeepj call s:NetrwRefresh(0,s:NetrwBrowseChgDir(0,'./',0))
   8083    NetrwKeepj call winrestview(svpos)
   8084 endfunction
   8085 
   8086 " s:NetrwRemoteRmFile: {{{2
   8087 function s:NetrwRemoteRmFile(path,rmfile,all)
   8088 
   8089    let all= a:all
   8090    let ok = ""
   8091 
   8092    if a:rmfile !~ '^"' && (a:rmfile =~ '@$' || a:rmfile !~ '[\/]$')
   8093        " attempt to remove file
   8094        if !all
   8095            echohl Statement
   8096            call inputsave()
   8097            let ok= input("Confirm deletion of file<".a:rmfile."> ","[{y(es)},n(o),a(ll),q(uit)] ")
   8098            call inputrestore()
   8099            echohl NONE
   8100            if ok == ""
   8101                let ok="no"
   8102            endif
   8103            let ok= substitute(ok,'\[{y(es)},n(o),a(ll),q(uit)]\s*','','e')
   8104            if ok =~# 'a\%[ll]'
   8105                let all= 1
   8106            endif
   8107        endif
   8108 
   8109        if all || ok =~# 'y\%[es]' || ok == ""
   8110            if exists("w:netrw_method") && (w:netrw_method == 2 || w:netrw_method == 3)
   8111                let path= a:path
   8112                if path =~ '^\a\{3,}://'
   8113                    let path= substitute(path,'^\a\{3,}://[^/]\+/','','')
   8114                endif
   8115                sil! NetrwKeepj .,$d _
   8116                call s:NetrwRemoteFtpCmd(path,"delete ".'"'.a:rmfile.'"')
   8117            else
   8118                let netrw_rm_cmd= s:MakeSshCmd(g:netrw_rm_cmd)
   8119                if !exists("b:netrw_curdir")
   8120                    call netrw#msg#Notify('ERROR', "for some reason b:netrw_curdir doesn't exist!")
   8121                    let ok="q"
   8122                else
   8123                    let remotedir= substitute(b:netrw_curdir,'^.\{-}//[^/]\+/\(.*\)$','\1','')
   8124                    if remotedir != ""
   8125                        let netrw_rm_cmd= netrw_rm_cmd." ".netrw#os#Escape(fnameescape(remotedir.a:rmfile))
   8126                    else
   8127                        let netrw_rm_cmd= netrw_rm_cmd." ".netrw#os#Escape(fnameescape(a:rmfile))
   8128                    endif
   8129                    let ret= system(netrw_rm_cmd)
   8130                    if v:shell_error != 0
   8131                        if exists("b:netrw_curdir") && b:netrw_curdir != getcwd() && !g:netrw_keepdir
   8132                            call netrw#msg#Notify('ERROR', printf("remove failed; perhaps due to vim's current directory<%s> not matching netrw's (%s) (see :help netrw-cd)", getcwd(), b:netrw_curdir))
   8133                        else
   8134                            call netrw#msg#Notify('WARNING', printf('cmd<%s> failed', netrw_rm_cmd))
   8135                        endif
   8136                    elseif ret != 0
   8137                        call netrw#msg#Notify('WARNING', printf('cmd<%s> failed', netrw_rm_cmd))
   8138                    endif
   8139                endif
   8140            endif
   8141        elseif ok =~# 'q\%[uit]'
   8142        endif
   8143 
   8144    else
   8145        " attempt to remove directory
   8146        if !all
   8147            call inputsave()
   8148            let ok= input("Confirm deletion of directory<".a:rmfile."> ","[{y(es)},n(o),a(ll),q(uit)] ")
   8149            call inputrestore()
   8150            if ok == ""
   8151                let ok="no"
   8152            endif
   8153            let ok= substitute(ok,'\[{y(es)},n(o),a(ll),q(uit)]\s*','','e')
   8154            if ok =~# 'a\%[ll]'
   8155                let all= 1
   8156            endif
   8157        endif
   8158 
   8159        if all || ok =~# 'y\%[es]' || ok == ""
   8160            if exists("w:netrw_method") && (w:netrw_method == 2 || w:netrw_method == 3)
   8161                NetrwKeepj call s:NetrwRemoteFtpCmd(a:path,"rmdir ".a:rmfile)
   8162            else
   8163                let rmfile          = substitute(a:path.a:rmfile,'/$','','')
   8164                let netrw_rmdir_cmd = s:MakeSshCmd(netrw#fs#WinPath(g:netrw_rmdir_cmd)).' '.netrw#os#Escape(netrw#fs#WinPath(rmfile))
   8165                let ret= system(netrw_rmdir_cmd)
   8166 
   8167                if v:shell_error != 0
   8168                    let netrw_rmf_cmd= s:MakeSshCmd(netrw#fs#WinPath(g:netrw_rmf_cmd)).' '.netrw#os#Escape(netrw#fs#WinPath(substitute(rmfile,'[\/]$','','e')))
   8169                    let ret= system(netrw_rmf_cmd)
   8170 
   8171                    if v:shell_error != 0
   8172                        call netrw#msg#Notify('ERROR', printf('unable to remove directory<%s> -- is it empty?', rmfile))
   8173                    endif
   8174                endif
   8175            endif
   8176 
   8177        elseif ok =~# 'q\%[uit]'
   8178        endif
   8179    endif
   8180 
   8181    return ok
   8182 endfunction
   8183 
   8184 " s:NetrwRemoteRename: rename a remote file or directory {{{2
   8185 function s:NetrwRemoteRename(usrhost,path) range
   8186 
   8187    " preparation for removing multiple files/directories
   8188    let svpos      = winsaveview()
   8189    let ctr        = a:firstline
   8190    let rename_cmd = s:MakeSshCmd(g:netrw_rename_cmd)
   8191 
   8192    " rename files given by the markfilelist
   8193    if exists("s:netrwmarkfilelist_{bufnr('%')}")
   8194        for oldname in s:netrwmarkfilelist_{bufnr("%")}
   8195            if exists("subfrom")
   8196                let newname= substitute(oldname,subfrom,subto,'')
   8197            else
   8198                call inputsave()
   8199                let newname= input("Moving ".oldname." to : ",oldname)
   8200                call inputrestore()
   8201                if newname =~ '^s/'
   8202                    let subfrom = substitute(newname,'^s/\([^/]*\)/.*/$','\1','')
   8203                    let subto   = substitute(newname,'^s/[^/]*/\(.*\)/$','\1','')
   8204                    let newname = substitute(oldname,subfrom,subto,'')
   8205                endif
   8206            endif
   8207 
   8208            if exists("w:netrw_method") && (w:netrw_method == 2 || w:netrw_method == 3)
   8209                NetrwKeepj call s:NetrwRemoteFtpCmd(a:path,"rename ".oldname." ".newname)
   8210            else
   8211                let oldname= netrw#os#Escape(a:path.oldname)
   8212                let newname= netrw#os#Escape(a:path.newname)
   8213                let ret    = system(netrw#fs#WinPath(rename_cmd).' '.oldname.' '.newname)
   8214            endif
   8215 
   8216        endfor
   8217        call s:NetrwUnMarkFile(1)
   8218 
   8219    else
   8220 
   8221        " attempt to rename files/directories
   8222        let keepsol= &l:sol
   8223        setl nosol
   8224        while ctr <= a:lastline
   8225            exe "NetrwKeepj ".ctr
   8226 
   8227            let oldname= s:NetrwGetWord()
   8228 
   8229            call inputsave()
   8230            let newname= input("Moving ".oldname." to : ",oldname)
   8231            call inputrestore()
   8232 
   8233            if exists("w:netrw_method") && (w:netrw_method == 2 || w:netrw_method == 3)
   8234                call s:NetrwRemoteFtpCmd(a:path,"rename ".oldname." ".newname)
   8235            else
   8236                let oldname= netrw#os#Escape(a:path.oldname)
   8237                let newname= netrw#os#Escape(a:path.newname)
   8238                let ret    = system(netrw#fs#WinPath(rename_cmd).' '.oldname.' '.newname)
   8239            endif
   8240 
   8241            let ctr= ctr + 1
   8242        endwhile
   8243        let &l:sol= keepsol
   8244    endif
   8245 
   8246    " refresh the directory
   8247    NetrwKeepj call s:NetrwRefresh(0,s:NetrwBrowseChgDir(0,'./',0))
   8248    NetrwKeepj call winrestview(svpos)
   8249 endfunction
   8250 
   8251 "  Local Directory Browsing Support:    {{{1
   8252 
   8253 " netrw#FileUrlEdit: handles editing file://* files {{{2
   8254 "   Should accept:   file://localhost/etc/fstab
   8255 "                    file:///etc/fstab
   8256 "                    file:///c:/WINDOWS/clock.avi
   8257 "                    file:///c|/WINDOWS/clock.avi
   8258 "                    file://localhost/c:/WINDOWS/clock.avi
   8259 "                    file://localhost/c|/WINDOWS/clock.avi
   8260 "                    file://c:/foo.txt
   8261 "                    file:///c:/foo.txt
   8262 " and %XX (where X is [0-9a-fA-F] is converted into a character with the given hexadecimal value
   8263 function netrw#FileUrlEdit(fname)
   8264    let fname = a:fname
   8265    if fname =~ '^file://localhost/'
   8266        let fname= substitute(fname,'^file://localhost/','file:///','')
   8267    endif
   8268    if has("win32")
   8269        if fname  =~ '^file:///\=\a[|:]/'
   8270            let fname = substitute(fname,'^file:///\=\(\a\)[|:]/','file://\1:/','')
   8271        endif
   8272    endif
   8273    let fname2396 = netrw#RFC2396(fname)
   8274    let fname2396e= fnameescape(fname2396)
   8275    let plainfname= substitute(fname2396,'file://\(.*\)','\1',"")
   8276    if has("win32")
   8277        if plainfname =~ '^/\+\a:'
   8278            let plainfname= substitute(plainfname,'^/\+\(\a:\)','\1','')
   8279        endif
   8280    endif
   8281 
   8282    exe "sil doau BufReadPre ".fname2396e
   8283    exe 'NetrwKeepj keepalt edit '.plainfname
   8284    exe 'sil! NetrwKeepj keepalt bdelete '.fnameescape(a:fname)
   8285 
   8286    exe "sil doau BufReadPost ".fname2396e
   8287 endfunction
   8288 
   8289 " netrw#LocalBrowseCheck: {{{2
   8290 function netrw#LocalBrowseCheck(dirname)
   8291    " This function is called by netrwPlugin.vim's s:LocalBrowseCheck(), s:NetrwRexplore(),
   8292    " and by <cr> when atop a listed file/directory (via a buffer-local map)
   8293    "
   8294    " unfortunate interaction -- split window debugging can't be used here, must use
   8295    "                            D-echoRemOn or D-echoTabOn as the BufEnter event triggers
   8296    "                            another call to LocalBrowseCheck() when attempts to write
   8297    "                            to the DBG buffer are made.
   8298    "
   8299    " The &ft == "netrw" test was installed because the BufEnter event
   8300    " would hit when re-entering netrw windows, creating unexpected
   8301    " refreshes (and would do so in the middle of NetrwSaveOptions(), too)
   8302    " getting E930: Cannot use :redir inside execute
   8303 
   8304    let ykeep= @@
   8305    if isdirectory(s:NetrwFile(a:dirname))
   8306 
   8307        if &ft != "netrw" || (exists("b:netrw_curdir") && b:netrw_curdir != a:dirname) || g:netrw_fastbrowse <= 1
   8308            sil! NetrwKeepj keepalt call s:NetrwBrowse(1,a:dirname)
   8309 
   8310        elseif &ft == "netrw" && line("$") == 1
   8311            sil! NetrwKeepj keepalt call s:NetrwBrowse(1,a:dirname)
   8312 
   8313        elseif exists("s:treeforceredraw")
   8314            unlet s:treeforceredraw
   8315            sil! NetrwKeepj keepalt call s:NetrwBrowse(1,a:dirname)
   8316        endif
   8317        return
   8318    endif
   8319 
   8320    " The following code wipes out currently unused netrw buffers
   8321    "       IF g:netrw_fastbrowse is zero (ie. slow browsing selected)
   8322    "   AND IF the listing style is not a tree listing
   8323    if exists("g:netrw_fastbrowse") && g:netrw_fastbrowse == 0 && g:netrw_liststyle != s:TREELIST
   8324        let ibuf    = 1
   8325        let buflast = bufnr("$")
   8326        while ibuf <= buflast
   8327            if bufwinnr(ibuf) == -1 && !empty(bufname(ibuf)) && isdirectory(s:NetrwFile(bufname(ibuf)))
   8328                exe "sil! keepj keepalt ".ibuf."bw!"
   8329            endif
   8330            let ibuf= ibuf + 1
   8331        endwhile
   8332    endif
   8333    let @@= ykeep
   8334    " not a directory, ignore it
   8335 endfunction
   8336 
   8337 " s:LocalBrowseRefresh: this function is called after a user has {{{2
   8338 " performed any shell command.  The idea is to cause all local-browsing
   8339 " buffers to be refreshed after a user has executed some shell command,
   8340 " on the chance that s/he removed/created a file/directory with it.
   8341 function s:LocalBrowseRefresh()
   8342    " determine which buffers currently reside in a tab
   8343    if !exists("s:netrw_browselist")
   8344        return
   8345    endif
   8346    if !exists("w:netrw_bannercnt")
   8347        return
   8348    endif
   8349    if !empty(getcmdwintype())
   8350        " cannot move away from cmdline window, see :h E11
   8351        return
   8352    endif
   8353    if exists("s:netrw_events") && s:netrw_events == 1
   8354        " s:LocalFastBrowser gets called (indirectly) from a
   8355        let s:netrw_events= 2
   8356        return
   8357    endif
   8358    let itab       = 1
   8359    let buftablist = []
   8360    let ykeep      = @@
   8361    while itab <= tabpagenr("$")
   8362        let buftablist = buftablist + tabpagebuflist()
   8363        let itab       = itab + 1
   8364        sil! tabn
   8365    endwhile
   8366    "  GO through all buffers on netrw_browselist (ie. just local-netrw buffers):
   8367    "   | refresh any netrw window
   8368    "   | wipe out any non-displaying netrw buffer
   8369    let curwinid = win_getid(winnr())
   8370    let ibl    = 0
   8371    for ibuf in s:netrw_browselist
   8372        if bufwinnr(ibuf) == -1 && index(buftablist,ibuf) == -1
   8373            " wipe out any non-displaying netrw buffer
   8374            " (ibuf not shown in a current window AND
   8375            "  ibuf not in any tab)
   8376            exe "sil! keepj bd ".fnameescape(ibuf)
   8377            call remove(s:netrw_browselist,ibl)
   8378            continue
   8379        elseif index(tabpagebuflist(),ibuf) != -1
   8380            " refresh any netrw buffer
   8381            exe bufwinnr(ibuf)."wincmd w"
   8382            if getline(".") =~# 'Quick Help'
   8383                " decrement g:netrw_quickhelp to prevent refresh from changing g:netrw_quickhelp
   8384                " (counteracts s:NetrwBrowseChgDir()'s incrementing)
   8385                let g:netrw_quickhelp= g:netrw_quickhelp - 1
   8386            endif
   8387            if exists("w:netrw_liststyle") && w:netrw_liststyle == s:TREELIST
   8388                NetrwKeepj call s:NetrwRefreshTreeDict(w:netrw_treetop)
   8389            endif
   8390            NetrwKeepj call s:NetrwRefresh(1,s:NetrwBrowseChgDir(1,'./',0))
   8391        endif
   8392        let ibl= ibl + 1
   8393    endfor
   8394    call win_gotoid(curwinid)
   8395    let @@= ykeep
   8396 endfunction
   8397 
   8398 " s:LocalFastBrowser: handles setting up/taking down fast browsing for the local browser {{{2
   8399 "
   8400 "     g:netrw_    Directory Is
   8401 "     fastbrowse  Local  Remote
   8402 "  slow   0         D      D      D=Deleting a buffer implies it will not be re-used (slow)
   8403 "  med    1         D      H      H=Hiding a buffer implies it may be re-used        (fast)
   8404 "  fast   2         H      H
   8405 "
   8406 "  Deleting a buffer means that it will be re-loaded when examined, hence "slow".
   8407 "  Hiding   a buffer means that it will be re-used   when examined, hence "fast".
   8408 "                       (re-using a buffer may not be as accurate)
   8409 "
   8410 "  s:netrw_events : doesn't exist, s:LocalFastBrowser() will install autocmds with medium-speed or fast browsing
   8411 "                   =1: autocmds installed, but ignore next FocusGained event to avoid initial double-refresh of listing.
   8412 "                       BufEnter may be first event, then a FocusGained event.  Ignore the first FocusGained event.
   8413 "                       If :Explore used: it sets s:netrw_events to 2, so no FocusGained events are ignored.
   8414 "                   =2: autocmds installed (doesn't ignore any FocusGained events)
   8415 function s:LocalFastBrowser()
   8416 
   8417    " initialize browselist, a list of buffer numbers that the local browser has used
   8418    if !exists("s:netrw_browselist")
   8419        let s:netrw_browselist= []
   8420    endif
   8421 
   8422    " append current buffer to fastbrowse list
   8423    if empty(s:netrw_browselist) || bufnr("%") > s:netrw_browselist[-1]
   8424        call add(s:netrw_browselist,bufnr("%"))
   8425    endif
   8426 
   8427    " enable autocmd events to handle refreshing/removing local browser buffers
   8428    "    If local browse buffer is currently showing: refresh it
   8429    "    If local browse buffer is currently hidden : wipe it
   8430    "    g:netrw_fastbrowse=0 : slow   speed, never re-use directory listing
   8431    "                      =1 : medium speed, re-use directory listing for remote only
   8432    "                      =2 : fast   speed, always re-use directory listing when possible
   8433    if g:netrw_fastbrowse <= 1 && !exists("#ShellCmdPost") && !exists("s:netrw_events")
   8434        let s:netrw_events= 1
   8435        augroup AuNetrwEvent
   8436            au!
   8437            if has("win32")
   8438                au ShellCmdPost                    *       call s:LocalBrowseRefresh()
   8439            else
   8440                au ShellCmdPost,FocusGained        *       call s:LocalBrowseRefresh()
   8441            endif
   8442        augroup END
   8443 
   8444    " user must have changed fastbrowse to its fast setting, so remove
   8445    " the associated autocmd events
   8446    elseif g:netrw_fastbrowse > 1 && exists("#ShellCmdPost") && exists("s:netrw_events")
   8447        unlet s:netrw_events
   8448        augroup AuNetrwEvent
   8449            au!
   8450        augroup END
   8451        augroup! AuNetrwEvent
   8452    endif
   8453 endfunction
   8454 
   8455 function s:NetrwLocalListingList(dirname,setmaxfilenamelen)
   8456    " get the list of files contained in the current directory
   8457    let dirname    = a:dirname
   8458    let dirnamelen = strlen(dirname)
   8459    let filelist   = map(['.', '..'] + readdir(dirname), 'netrw#fs#PathJoin(dirname, v:val)')
   8460 
   8461    if g:netrw_cygwin == 0 && has("win32")
   8462    elseif index(filelist,'..') == -1 && dirname !~ '/'
   8463        " include ../ in the glob() entry if its missing
   8464        let filelist= filelist+[netrw#fs#ComposePath(dirname,"../")]
   8465    endif
   8466 
   8467    if a:setmaxfilenamelen && get(g:, 'netrw_dynamic_maxfilenamelen', 0)
   8468        let filelistcopy           = map(deepcopy(filelist),'fnamemodify(v:val, ":t")')
   8469        let g:netrw_maxfilenamelen = max(map(filelistcopy,'len(v:val)')) + 1
   8470    endif
   8471 
   8472    let resultfilelist = []
   8473    for filename in filelist
   8474 
   8475        let ftype = getftype(filename)
   8476        if ftype ==# "link"
   8477            " indicate a symbolic link
   8478            let pfile= filename."@"
   8479 
   8480        elseif ftype ==# "socket"
   8481            " indicate a socket
   8482            let pfile= filename."="
   8483 
   8484        elseif ftype ==# "fifo"
   8485            " indicate a fifo
   8486            let pfile= filename."|"
   8487 
   8488        elseif ftype ==# "dir"
   8489            " indicate a directory
   8490            let pfile= filename."/"
   8491 
   8492        elseif exists("b:netrw_curdir") && b:netrw_curdir !~ '^.*://' && !isdirectory(s:NetrwFile(filename))
   8493            if has("win32")
   8494                if filename =~ '\.[eE][xX][eE]$' || filename =~ '\.[cC][oO][mM]$' || filename =~ '\.[bB][aA][tT]$'
   8495                    " indicate an executable
   8496                    let pfile= filename."*"
   8497                else
   8498                    " normal file
   8499                    let pfile= filename
   8500                endif
   8501            elseif executable(filename)
   8502                " indicate an executable
   8503                let pfile= filename."*"
   8504            else
   8505                " normal file
   8506                let pfile= filename
   8507            endif
   8508 
   8509        else
   8510            " normal file
   8511            let pfile= filename
   8512        endif
   8513 
   8514        if pfile =~ '//$'
   8515            let pfile= substitute(pfile,'//$','/','e')
   8516        endif
   8517        let pfile= strpart(pfile,dirnamelen)
   8518        let pfile= substitute(pfile,'^[/\\]','','e')
   8519 
   8520        if w:netrw_liststyle == s:LONGLIST
   8521            let longfile = printf("%-".g:netrw_maxfilenamelen."S",pfile)
   8522            let sz       = getfsize(filename)
   8523            let szlen    = 15 - (strdisplaywidth(longfile) - g:netrw_maxfilenamelen)
   8524            let szlen    = (szlen > 0) ? szlen : 0
   8525 
   8526            if g:netrw_sizestyle =~# "[hH]"
   8527                let sz= s:NetrwHumanReadable(sz)
   8528            endif
   8529            let fsz  = printf("%".szlen."S",sz)
   8530            let pfile= longfile."  ".fsz." ".strftime(g:netrw_timefmt,getftime(filename))
   8531        endif
   8532 
   8533        if     g:netrw_sort_by =~# "^t"
   8534            " sort by time (handles time up to 1 quintillion seconds, US)
   8535            " Decorate listing by prepending a timestamp/  .  Sorting will then be done based on time.
   8536            let t  = getftime(filename)
   8537            let ft = printf("%018d",t)
   8538            let ftpfile= ft.'/'.pfile
   8539            let resultfilelist += [ftpfile]
   8540 
   8541        elseif g:netrw_sort_by =~ "^s"
   8542            " sort by size (handles file sizes up to 1 quintillion bytes, US)
   8543            let sz   = getfsize(filename)
   8544            let fsz  = printf("%018d",sz)
   8545            let fszpfile= fsz.'/'.pfile
   8546            let resultfilelist += [fszpfile]
   8547 
   8548        else
   8549            " sort by name
   8550            let resultfilelist += [pfile]
   8551        endif
   8552    endfor
   8553 
   8554    return resultfilelist
   8555 endfunction
   8556 
   8557 " s:NetrwLocalExecute: uses system() to execute command under cursor ("X" command support) {{{2
   8558 function s:NetrwLocalExecute(cmd)
   8559    let ykeep= @@
   8560    " sanity check
   8561    if !executable(a:cmd)
   8562        call netrw#msg#Notify('ERROR', printf("the file<%s> is not executable!", a:cmd))
   8563        let @@= ykeep
   8564        return
   8565    endif
   8566 
   8567    let optargs= input(":!".a:cmd,"","file")
   8568    let result= system(a:cmd.optargs)
   8569 
   8570    " strip any ansi escape sequences off
   8571    let result = substitute(result,"\e\\[[0-9;]*m","","g")
   8572 
   8573    " show user the result(s)
   8574    echomsg result
   8575    let @@= ykeep
   8576 
   8577 endfunction
   8578 
   8579 " s:NetrwLocalRename: rename a local file or directory {{{2
   8580 function s:NetrwLocalRename(path) range
   8581 
   8582    if !exists("w:netrw_bannercnt")
   8583        let w:netrw_bannercnt= b:netrw_bannercnt
   8584    endif
   8585 
   8586    " preparation for removing multiple files/directories
   8587    let ykeep     = @@
   8588    let ctr       = a:firstline
   8589    let svpos     = winsaveview()
   8590    let all       = 0
   8591 
   8592    " rename files given by the markfilelist
   8593    if exists("s:netrwmarkfilelist_{bufnr('%')}")
   8594        for oldname in s:netrwmarkfilelist_{bufnr("%")}
   8595            if exists("subfrom")
   8596                let newname= substitute(oldname,subfrom,subto,'')
   8597            else
   8598                call inputsave()
   8599                let newname= input("Moving ".oldname." to : ",oldname,"file")
   8600                call inputrestore()
   8601                if newname =~ ''
   8602                    " two ctrl-x's : ignore all of string preceding the ctrl-x's
   8603                    let newname = substitute(newname,'^.*','','')
   8604                elseif newname =~ ''
   8605                    " one ctrl-x : ignore portion of string preceding ctrl-x but after last /
   8606                    let newname = substitute(newname,'[^/]*','','')
   8607                endif
   8608                if newname =~ '^s/'
   8609                    let subfrom = substitute(newname,'^s/\([^/]*\)/.*/$','\1','')
   8610                    let subto   = substitute(newname,'^s/[^/]*/\(.*\)/$','\1','')
   8611                    let newname = substitute(oldname,subfrom,subto,'')
   8612                endif
   8613            endif
   8614            if !all && filereadable(newname)
   8615                call inputsave()
   8616                let response= input("File<".newname."> already exists; do you want to overwrite it? (y/all/n) ")
   8617                call inputrestore()
   8618                if response == "all"
   8619                    let all= 1
   8620                elseif response != "y" && response != "yes"
   8621                    " refresh the directory
   8622                    NetrwKeepj call s:NetrwRefresh(1,s:NetrwBrowseChgDir(1,'./',0))
   8623                    NetrwKeepj call winrestview(svpos)
   8624                    let @@= ykeep
   8625                    return
   8626                endif
   8627            endif
   8628            call rename(oldname,newname)
   8629        endfor
   8630        call s:NetrwUnmarkList(bufnr("%"),b:netrw_curdir)
   8631 
   8632    else
   8633 
   8634        " attempt to rename files/directories
   8635        while ctr <= a:lastline
   8636            exe "NetrwKeepj ".ctr
   8637 
   8638            " sanity checks
   8639            if line(".") < w:netrw_bannercnt
   8640                let ctr= ctr + 1
   8641                continue
   8642            endif
   8643            let curword= s:NetrwGetWord()
   8644            if curword == "./" || curword == "../"
   8645                let ctr= ctr + 1
   8646                continue
   8647            endif
   8648 
   8649            NetrwKeepj norm! 0
   8650            let oldname= netrw#fs#ComposePath(a:path,curword)
   8651 
   8652            call inputsave()
   8653            let newname= input("Moving ".oldname." to : ",substitute(oldname,'/*$','','e'))
   8654            call inputrestore()
   8655 
   8656            call rename(oldname,newname)
   8657            let ctr= ctr + 1
   8658        endwhile
   8659    endif
   8660 
   8661    " refresh the directory
   8662    NetrwKeepj call s:NetrwRefresh(1,s:NetrwBrowseChgDir(1,'./',0))
   8663    NetrwKeepj call winrestview(svpos)
   8664    let @@= ykeep
   8665 endfunction
   8666 
   8667 " s:NetrwLocalRm: {{{2
   8668 function s:NetrwLocalRm(path) range
   8669    if !exists("w:netrw_bannercnt")
   8670        let w:netrw_bannercnt = b:netrw_bannercnt
   8671    endif
   8672 
   8673    " preparation for removing multiple files/directories
   8674    let ykeep = @@
   8675    let ret = 0
   8676    let all = 0
   8677    let svpos = winsaveview()
   8678 
   8679    if exists("s:netrwmarkfilelist_{bufnr('%')}")
   8680        " remove all marked files
   8681        for fname in s:netrwmarkfilelist_{bufnr("%")}
   8682            let ok = s:NetrwLocalRmFile(a:path, fname, all)
   8683            if ok =~# '^a\%[ll]$'
   8684                let all = 1
   8685            elseif ok =~# "n\%[o]"
   8686                break
   8687            endif
   8688        endfor
   8689        call s:NetrwUnMarkFile(1)
   8690 
   8691    else
   8692        " remove (multiple) files and directories
   8693 
   8694        let keepsol = &l:sol
   8695        setl nosol
   8696        let ctr = a:firstline
   8697        while ctr <= a:lastline
   8698            exe "NetrwKeepj ".ctr
   8699 
   8700            " sanity checks
   8701            if line(".") < w:netrw_bannercnt
   8702                let ctr = ctr + 1
   8703                continue
   8704            endif
   8705 
   8706            let curword = s:NetrwGetWord()
   8707            if curword == "./" || curword == "../"
   8708                let ctr = ctr + 1
   8709                continue
   8710            endif
   8711 
   8712            let ok = s:NetrwLocalRmFile(a:path, curword, all)
   8713            if ok =~# '^a\%[ll]$'
   8714                let all = 1
   8715            elseif ok =~# "n\%[o]"
   8716                break
   8717            endif
   8718 
   8719            let ctr = ctr + 1
   8720        endwhile
   8721 
   8722        let &l:sol = keepsol
   8723    endif
   8724 
   8725    " refresh the directory
   8726    if bufname("%") != "NetrwMessage"
   8727        NetrwKeepj call s:NetrwRefresh(1, s:NetrwBrowseChgDir(1, './', 0))
   8728        NetrwKeepj call winrestview(svpos)
   8729    endif
   8730 
   8731    let @@= ykeep
   8732 endfunction
   8733 
   8734 " s:NetrwLocalRmFile: remove file fname given the path {{{2
   8735 "                     Give confirmation prompt unless all==1
   8736 function s:NetrwLocalRmFile(path, fname, all)
   8737    let all = a:all
   8738    let ok = ""
   8739    let dir = 0
   8740    NetrwKeepj norm! 0
   8741    let rmfile = s:NetrwFile(netrw#fs#ComposePath(a:path, escape(a:fname, '\\')))->fnamemodify(':.')
   8742 
   8743    " if not a directory
   8744    if rmfile !~ '^"' && (rmfile =~ '@$' || rmfile !~ '[\/]$')
   8745        let msg = "Confirm deletion of file <%s> [{y(es)},n(o),a(ll)]: "
   8746    else
   8747        let msg = "Confirm *recursive* deletion of directory <%s> [{y(es)},n(o),a(ll)]: "
   8748        let dir = 1
   8749    endif
   8750 
   8751    " Ask confirmation
   8752    if !all
   8753        echohl Statement
   8754        call inputsave()
   8755        let ok = input(printf(msg, rmfile))
   8756        call inputrestore()
   8757        echohl NONE
   8758        if ok =~# '^a\%[ll]$' || ok =~# '^y\%[es]$'
   8759            let all = 1
   8760        else
   8761            let ok = 'no'
   8762        endif
   8763    endif
   8764 
   8765    if !dir && (all || empty(ok))
   8766        " This works because delete return 0 if successful
   8767        if netrw#fs#Remove(rmfile)
   8768            call netrw#msg#Notify('ERROR', printf("unable to delete <%s>!", rmfile))
   8769        else
   8770            " Remove file only if there are no pending changes
   8771            execute printf('silent! bwipeout %s', rmfile)
   8772        endif
   8773 
   8774    elseif dir && (all || empty(ok))
   8775        " Remove trailing /
   8776        let rmfile = substitute(rmfile, '[\/]$', '', 'e')
   8777        if delete(rmfile, "rf")
   8778            call netrw#msg#Notify('ERROR', printf("unable to delete directory <%s>!", rmfile))
   8779        endif
   8780 
   8781    endif
   8782 
   8783    return ok
   8784 endfunction
   8785 
   8786 " Support Functions: {{{1
   8787 
   8788 " netrw#Call: allows user-specified mappings to call internal netrw functions {{{2
   8789 function netrw#Call(funcname,...)
   8790    return call("s:".a:funcname,a:000)
   8791 endfunction
   8792 
   8793 " netrw#Expose: allows UserMaps and pchk to look at otherwise script-local variables {{{2
   8794 "               I expect this function to be used in
   8795 "                 :PChkAssert netrw#Expose("netrwmarkfilelist")
   8796 "               for example.
   8797 function netrw#Expose(varname)
   8798    if exists("s:".a:varname)
   8799        exe "let retval= s:".a:varname
   8800        if exists("g:netrw_pchk")
   8801            if type(retval) == 3
   8802                let retval = copy(retval)
   8803                let i      = 0
   8804                while i < len(retval)
   8805                    let retval[i]= substitute(retval[i],expand("$HOME"),'~','')
   8806                    let i        = i + 1
   8807                endwhile
   8808            endif
   8809            return string(retval)
   8810        else
   8811        endif
   8812    else
   8813        let retval= "n/a"
   8814    endif
   8815 
   8816    return retval
   8817 endfunction
   8818 
   8819 " netrw#Modify: allows UserMaps to set (modify) script-local variables {{{2
   8820 function netrw#Modify(varname,newvalue)
   8821    exe "let s:".a:varname."= ".string(a:newvalue)
   8822 endfunction
   8823 
   8824 "  netrw#RFC2396: converts %xx into characters {{{2
   8825 function netrw#RFC2396(fname)
   8826    let fname = escape(substitute(a:fname,'%\(\x\x\)','\=printf("%c","0x".submatch(1))','ge')," \t")
   8827    return fname
   8828 endfunction
   8829 
   8830 " netrw#UserMaps: supports user-specified maps {{{2
   8831 "                 see :help function()
   8832 "
   8833 "                 g:Netrw_UserMaps is a List with members such as:
   8834 "                       [[keymap sequence, function reference],...]
   8835 "
   8836 "                 The referenced function may return a string,
   8837 "                       refresh : refresh the display
   8838 "                       -other- : this string will be executed
   8839 "                 or it may return a List of strings.
   8840 "
   8841 "                 Each keymap-sequence will be set up with a nnoremap
   8842 "                 to invoke netrw#UserMaps(a:islocal).
   8843 "                 Related functions:
   8844 "                   netrw#Expose(varname)          -- see s:varname variables
   8845 "                   netrw#Modify(varname,newvalue) -- modify value of s:varname variable
   8846 "                   netrw#Call(funcname,...)       -- call internal netrw function with optional arguments
   8847 function netrw#UserMaps(islocal)
   8848 
   8849    " set up usermaplist
   8850    if exists("g:Netrw_UserMaps") && type(g:Netrw_UserMaps) == 3
   8851        for umap in g:Netrw_UserMaps
   8852            " if umap[0] is a string and umap[1] is a string holding a function name
   8853            if type(umap[0]) == 1 && type(umap[1]) == 1
   8854                exe "nno <buffer> <silent> ".umap[0]." :call <SID>UserMaps(".a:islocal.",'".umap[1]."')<cr>"
   8855            else
   8856                call netrw#msg#Notify('WARNING', printf('ignoring usermap <%s> -- not a [string,funcref] entry', string(umap[0])))
   8857            endif
   8858        endfor
   8859    endif
   8860 endfunction
   8861 
   8862 " s:NetrwBadd: adds marked files to buffer list or vice versa {{{2
   8863 "              cb : bl2mf=0  add marked files to buffer list
   8864 "              cB : bl2mf=1  use bufferlist to mark files
   8865 "              (mnemonic: cb = copy (marked files) to buffer list)
   8866 function s:NetrwBadd(islocal,bl2mf)
   8867    if a:bl2mf
   8868        " cB: add buffer list to marked files
   8869        redir => bufl
   8870        ls
   8871        redir END
   8872        let bufl = map(split(bufl,"\n"),'substitute(v:val,''^.\{-}"\(.*\)".\{-}$'',''\1'','''')')
   8873        for fname in bufl
   8874            call s:NetrwMarkFile(a:islocal,fname)
   8875        endfor
   8876    else
   8877        " cb: add marked files to buffer list
   8878        for fname in s:netrwmarkfilelist_{bufnr("%")}
   8879            exe "badd ".fnameescape(fname)
   8880        endfor
   8881        let curbufnr = bufnr("%")
   8882        let curdir   = s:NetrwGetCurdir(a:islocal)
   8883        call s:NetrwUnmarkList(curbufnr,curdir)                   " remove markings from local buffer
   8884    endif
   8885 endfunction
   8886 
   8887 " s:DeleteBookmark: deletes a file/directory from Netrw's bookmark system {{{2
   8888 "   Related Functions: s:MakeBookmark() s:NetrwBookHistHandler() s:NetrwBookmark()
   8889 function s:DeleteBookmark(fname)
   8890    call s:MergeBookmarks()
   8891 
   8892    if exists("g:netrw_bookmarklist")
   8893        let indx= index(g:netrw_bookmarklist,a:fname)
   8894        if indx == -1
   8895            let indx= 0
   8896            while indx < len(g:netrw_bookmarklist)
   8897                if g:netrw_bookmarklist[indx] =~ a:fname
   8898                    call remove(g:netrw_bookmarklist,indx)
   8899                    let indx= indx - 1
   8900                endif
   8901                let indx= indx + 1
   8902            endwhile
   8903        else
   8904            " remove exact match
   8905            call remove(g:netrw_bookmarklist,indx)
   8906        endif
   8907    endif
   8908 
   8909 endfunction
   8910 
   8911 " s:FileReadable: o/s independent filereadable {{{2
   8912 function s:FileReadable(fname)
   8913    if g:netrw_cygwin
   8914        let ret = filereadable(s:NetrwFile(substitute(a:fname,g:netrw_cygdrive.'/\(.\)','\1:/','')))
   8915    else
   8916        let ret = filereadable(s:NetrwFile(a:fname))
   8917    endif
   8918 
   8919    return ret
   8920 endfunction
   8921 
   8922 "  s:GetTempfile: gets a tempname that'll work for various o/s's {{{2
   8923 "                 Places correct suffix on end of temporary filename,
   8924 "                 using the suffix provided with fname
   8925 function s:GetTempfile(fname)
   8926 
   8927    if !exists("b:netrw_tmpfile")
   8928        " get a brand new temporary filename
   8929        let tmpfile= tempname()
   8930 
   8931        let tmpfile= substitute(tmpfile,'\','/','ge')
   8932 
   8933        " sanity check -- does the temporary file's directory exist?
   8934        if !isdirectory(s:NetrwFile(substitute(tmpfile,'[^/]\+$','','e')))
   8935            call netrw#msg#Notify('ERROR', printf('your <%s> directory is missing!', substitute(tmpfile,'[^/]\+$','','e')))
   8936            return ""
   8937        endif
   8938 
   8939        " let netrw#NetSource() know about the tmpfile
   8940        let s:netrw_tmpfile= tmpfile " used by netrw#NetSource() and netrw#BrowseX()
   8941 
   8942        " o/s dependencies
   8943        if g:netrw_cygwin != 0
   8944            let tmpfile = substitute(tmpfile,'^\(\a\):',g:netrw_cygdrive.'/\1','e')
   8945        elseif has("win32")
   8946            if !exists("+shellslash") || !&ssl
   8947                let tmpfile = substitute(tmpfile,'/','\','g')
   8948            endif
   8949        else
   8950            let tmpfile = tmpfile
   8951        endif
   8952        let b:netrw_tmpfile= tmpfile
   8953    else
   8954        " re-use temporary filename
   8955        let tmpfile= b:netrw_tmpfile
   8956    endif
   8957 
   8958    " use fname's suffix for the temporary file
   8959    if a:fname != ""
   8960        if a:fname =~ '\.[^./]\+$'
   8961            if a:fname =~ '\.tar\.gz$' || a:fname =~ '\.tar\.bz2$' || a:fname =~ '\.tar\.xz$'
   8962                let suffix = ".tar".substitute(a:fname,'^.*\(\.[^./]\+\)$','\1','e')
   8963            elseif a:fname =~ '.txz$'
   8964                let suffix = ".txz".substitute(a:fname,'^.*\(\.[^./]\+\)$','\1','e')
   8965            else
   8966                let suffix = substitute(a:fname,'^.*\(\.[^./]\+\)$','\1','e')
   8967            endif
   8968            let tmpfile= substitute(tmpfile,'\.tmp$','','e')
   8969            let tmpfile .= suffix
   8970            let s:netrw_tmpfile= tmpfile " supports netrw#NetSource()
   8971        endif
   8972    endif
   8973 
   8974    return tmpfile
   8975 endfunction
   8976 
   8977 " s:MakeSshCmd: transforms input command using USEPORT HOSTNAME into {{{2
   8978 "               a correct command for use with a system() call
   8979 function s:MakeSshCmd(sshcmd)
   8980    if s:user == ""
   8981        let sshcmd = substitute(a:sshcmd,'\<HOSTNAME\>',s:machine,'')
   8982    else
   8983        let sshcmd = substitute(a:sshcmd,'\<HOSTNAME\>',s:user."@".s:machine,'')
   8984    endif
   8985    if exists("g:netrw_port") && g:netrw_port != ""
   8986        let sshcmd= substitute(sshcmd,"USEPORT",g:netrw_sshport.' '.g:netrw_port,'')
   8987    elseif exists("s:port") && s:port != ""
   8988        let sshcmd= substitute(sshcmd,"USEPORT",g:netrw_sshport.' '.s:port,'')
   8989    else
   8990        let sshcmd= substitute(sshcmd,"USEPORT ",'','')
   8991    endif
   8992    return sshcmd
   8993 endfunction
   8994 
   8995 " s:MakeBookmark: enters a bookmark into Netrw's bookmark system   {{{2
   8996 function s:MakeBookmark(fname)
   8997 
   8998    if !exists("g:netrw_bookmarklist")
   8999        let g:netrw_bookmarklist= []
   9000    endif
   9001 
   9002    if index(g:netrw_bookmarklist,a:fname) == -1
   9003        " curdir not currently in g:netrw_bookmarklist, so include it
   9004        if isdirectory(s:NetrwFile(a:fname)) && a:fname !~ '/$'
   9005            call add(g:netrw_bookmarklist,a:fname.'/')
   9006        elseif a:fname !~ '/'
   9007            call add(g:netrw_bookmarklist,getcwd()."/".a:fname)
   9008        else
   9009            call add(g:netrw_bookmarklist,a:fname)
   9010        endif
   9011        call sort(g:netrw_bookmarklist)
   9012    endif
   9013 
   9014 endfunction
   9015 
   9016 " s:MergeBookmarks: merge current bookmarks with saved bookmarks {{{2
   9017 function s:MergeBookmarks()
   9018    " get bookmarks from .netrwbook file
   9019    let savefile= s:NetrwHome()."/.netrwbook"
   9020    if filereadable(s:NetrwFile(savefile))
   9021        NetrwKeepj call s:NetrwBookHistSave()
   9022        NetrwKeepj call delete(savefile)
   9023    endif
   9024 endfunction
   9025 
   9026 " s:NetrwBMShow: {{{2
   9027 function s:NetrwBMShow()
   9028    redir => bmshowraw
   9029    menu
   9030    redir END
   9031    let bmshowlist = split(bmshowraw,'\n')
   9032    if bmshowlist != []
   9033        let bmshowfuncs= filter(bmshowlist,'v:val =~# "<SNR>\\d\\+_BMShow()"')
   9034        if bmshowfuncs != []
   9035            let bmshowfunc = substitute(bmshowfuncs[0],'^.*:\(call.*BMShow()\).*$','\1','')
   9036            if bmshowfunc =~# '^call.*BMShow()'
   9037                exe "sil! NetrwKeepj ".bmshowfunc
   9038            endif
   9039        endif
   9040    endif
   9041 endfunction
   9042 
   9043 " s:NetrwCursor: responsible for setting cursorline/cursorcolumn based upon g:netrw_cursor {{{2
   9044 function s:NetrwCursor(editfile)
   9045    if !exists("w:netrw_liststyle")
   9046        let w:netrw_liststyle= g:netrw_liststyle
   9047    endif
   9048 
   9049 
   9050    if &ft != "netrw"
   9051    " if the current window isn't a netrw directory listing window, then use user cursorline/column
   9052    " settings.  Affects when netrw is used to read/write a file using scp/ftp/etc.
   9053 
   9054    elseif g:netrw_cursor == 8
   9055        if w:netrw_liststyle == s:WIDELIST
   9056            setl cursorline
   9057            setl cursorcolumn
   9058        else
   9059            setl cursorline
   9060        endif
   9061    elseif g:netrw_cursor == 7
   9062        setl cursorline
   9063    elseif g:netrw_cursor == 6
   9064        if w:netrw_liststyle == s:WIDELIST
   9065            setl cursorline
   9066        endif
   9067    elseif g:netrw_cursor == 4
   9068        " all styles: cursorline, cursorcolumn
   9069        setl cursorline
   9070        setl cursorcolumn
   9071 
   9072    elseif g:netrw_cursor == 3
   9073        " thin-long-tree: cursorline, user's cursorcolumn
   9074        " wide          : cursorline, cursorcolumn
   9075        if w:netrw_liststyle == s:WIDELIST
   9076            setl cursorline
   9077            setl cursorcolumn
   9078        else
   9079            setl cursorline
   9080        endif
   9081 
   9082    elseif g:netrw_cursor == 2
   9083        " thin-long-tree: cursorline, user's cursorcolumn
   9084        " wide          : cursorline, user's cursorcolumn
   9085        setl cursorline
   9086 
   9087    elseif g:netrw_cursor == 1
   9088        " thin-long-tree: user's cursorline, user's cursorcolumn
   9089        " wide          : cursorline,        user's cursorcolumn
   9090        if w:netrw_liststyle == s:WIDELIST
   9091            setl cursorline
   9092        else
   9093        endif
   9094 
   9095    else
   9096        " all styles: user's cursorline, user's cursorcolumn
   9097        let &l:cursorline   = s:netrw_usercul
   9098        let &l:cursorcolumn = s:netrw_usercuc
   9099    endif
   9100 
   9101 endfunction
   9102 
   9103 " s:RestoreCursorline: restores cursorline/cursorcolumn to original user settings {{{2
   9104 function s:RestoreCursorline()
   9105    if exists("s:netrw_usercul")
   9106        let &l:cursorline   = s:netrw_usercul
   9107    endif
   9108    if exists("s:netrw_usercuc")
   9109        let &l:cursorcolumn = s:netrw_usercuc
   9110    endif
   9111 endfunction
   9112 
   9113 " s:RestoreRegister: restores all registers given in the dict {{{2
   9114 function s:RestoreRegister(dict)
   9115    for [key, val] in items(a:dict)
   9116        if key == 'unnamed'
   9117            let key = ''
   9118        endif
   9119        call setreg(key, val[0], val[1])
   9120    endfor
   9121 endfunction
   9122 
   9123 " s:NetrwEnew: opens a new buffer, passes netrw buffer variables through {{{2
   9124 function s:NetrwEnew(...)
   9125 
   9126    " Clean out the last buffer:
   9127    " Check if the last buffer has # > 1, is unlisted, is unnamed, and does not appear in a window
   9128    " If so, delete it.
   9129    let bufid = bufnr('$')
   9130    if bufid > 1 && !buflisted(bufid) && bufloaded(bufid) && bufname(bufid) == "" && bufwinid(bufid) == -1
   9131        execute printf("silent! bdelete! %s", bufid)
   9132    endif
   9133 
   9134    " grab a function-local-variable copy of buffer variables
   9135    if exists("b:netrw_bannercnt")      |let netrw_bannercnt       = b:netrw_bannercnt      |endif
   9136    if exists("b:netrw_browser_active") |let netrw_browser_active  = b:netrw_browser_active |endif
   9137    if exists("b:netrw_cpf")            |let netrw_cpf             = b:netrw_cpf            |endif
   9138    if exists("b:netrw_curdir")         |let netrw_curdir          = b:netrw_curdir         |endif
   9139    if exists("b:netrw_explore_bufnr")  |let netrw_explore_bufnr   = b:netrw_explore_bufnr  |endif
   9140    if exists("b:netrw_explore_indx")   |let netrw_explore_indx    = b:netrw_explore_indx   |endif
   9141    if exists("b:netrw_explore_line")   |let netrw_explore_line    = b:netrw_explore_line   |endif
   9142    if exists("b:netrw_explore_list")   |let netrw_explore_list    = b:netrw_explore_list   |endif
   9143    if exists("b:netrw_explore_listlen")|let netrw_explore_listlen = b:netrw_explore_listlen|endif
   9144    if exists("b:netrw_explore_mtchcnt")|let netrw_explore_mtchcnt = b:netrw_explore_mtchcnt|endif
   9145    if exists("b:netrw_fname")          |let netrw_fname           = b:netrw_fname          |endif
   9146    if exists("b:netrw_lastfile")       |let netrw_lastfile        = b:netrw_lastfile       |endif
   9147    if exists("b:netrw_liststyle")      |let netrw_liststyle       = b:netrw_liststyle      |endif
   9148    if exists("b:netrw_method")         |let netrw_method          = b:netrw_method         |endif
   9149    if exists("b:netrw_option")         |let netrw_option          = b:netrw_option         |endif
   9150    if exists("b:netrw_prvdir")         |let netrw_prvdir          = b:netrw_prvdir         |endif
   9151 
   9152    NetrwKeepj call s:NetrwOptionsRestore("w:")
   9153    " when tree listing uses file TreeListing... a new buffer is made.
   9154    " Want the old buffer to be unlisted.
   9155    " COMBAK: this causes a problem, see P43
   9156    "  setl nobl
   9157    let netrw_keepdiff= &l:diff
   9158    call s:NetrwEditFile("enew!","","")
   9159    let &l:diff= netrw_keepdiff
   9160    NetrwKeepj call s:NetrwOptionsSave("w:")
   9161 
   9162    " copy function-local-variables to buffer variable equivalents
   9163    if exists("netrw_bannercnt")      |let b:netrw_bannercnt       = netrw_bannercnt      |endif
   9164    if exists("netrw_browser_active") |let b:netrw_browser_active  = netrw_browser_active |endif
   9165    if exists("netrw_cpf")            |let b:netrw_cpf             = netrw_cpf            |endif
   9166    if exists("netrw_curdir")         |let b:netrw_curdir          = netrw_curdir         |endif
   9167    if exists("netrw_explore_bufnr")  |let b:netrw_explore_bufnr   = netrw_explore_bufnr  |endif
   9168    if exists("netrw_explore_indx")   |let b:netrw_explore_indx    = netrw_explore_indx   |endif
   9169    if exists("netrw_explore_line")   |let b:netrw_explore_line    = netrw_explore_line   |endif
   9170    if exists("netrw_explore_list")   |let b:netrw_explore_list    = netrw_explore_list   |endif
   9171    if exists("netrw_explore_listlen")|let b:netrw_explore_listlen = netrw_explore_listlen|endif
   9172    if exists("netrw_explore_mtchcnt")|let b:netrw_explore_mtchcnt = netrw_explore_mtchcnt|endif
   9173    if exists("netrw_fname")          |let b:netrw_fname           = netrw_fname          |endif
   9174    if exists("netrw_lastfile")       |let b:netrw_lastfile        = netrw_lastfile       |endif
   9175    if exists("netrw_liststyle")      |let b:netrw_liststyle       = netrw_liststyle      |endif
   9176    if exists("netrw_method")         |let b:netrw_method          = netrw_method         |endif
   9177    if exists("netrw_option")         |let b:netrw_option          = netrw_option         |endif
   9178    if exists("netrw_prvdir")         |let b:netrw_prvdir          = netrw_prvdir         |endif
   9179 
   9180    if a:0 > 0
   9181        let b:netrw_curdir= a:1
   9182        if b:netrw_curdir =~ '/$'
   9183            if exists("w:netrw_liststyle") && w:netrw_liststyle == s:TREELIST
   9184                setl nobl
   9185                file NetrwTreeListing
   9186                setl nobl bt=nowrite bh=hide
   9187                nno <silent> <buffer> [    :sil call <SID>TreeListMove('[')<cr>
   9188                nno <silent> <buffer> ]    :sil call <SID>TreeListMove(']')<cr>
   9189            else
   9190                call s:NetrwBufRename(b:netrw_curdir)
   9191            endif
   9192        endif
   9193    endif
   9194 endfunction
   9195 
   9196 " s:NetrwInsureWinVars: insure that a netrw buffer has its w: variables in spite of a wincmd v or s {{{2
   9197 function s:NetrwInsureWinVars()
   9198    if !exists("w:netrw_liststyle")
   9199        let curbuf = bufnr("%")
   9200        let curwin = winnr()
   9201        let iwin   = 1
   9202        while iwin <= winnr("$")
   9203            exe iwin."wincmd w"
   9204            if winnr() != curwin && bufnr("%") == curbuf && exists("w:netrw_liststyle")
   9205                " looks like ctrl-w_s or ctrl-w_v was used to split a netrw buffer
   9206                let winvars= w:
   9207                break
   9208            endif
   9209            let iwin= iwin + 1
   9210        endwhile
   9211        exe "keepalt ".curwin."wincmd w"
   9212        if exists("winvars")
   9213            for k in keys(winvars)
   9214                let w:{k}= winvars[k]
   9215            endfor
   9216        endif
   9217    endif
   9218 endfunction
   9219 
   9220 " s:NetrwLcd: handles changing the (local) directory {{{2
   9221 "   Returns: 0=success
   9222 "           -1=failed
   9223 function s:NetrwLcd(newdir)
   9224 
   9225    let err472= 0
   9226    try
   9227        exe 'NetrwKeepj sil lcd '.fnameescape(a:newdir)
   9228    catch /^Vim\%((\a\+)\)\=:E344/
   9229        " Vim's lcd fails with E344 when attempting to go above the 'root' of a Windows share.
   9230        " Therefore, detect if a Windows share is present, and if E344 occurs, just settle at
   9231        " 'root' (ie. '\').  The share name may start with either backslashes ('\\Foo') or
   9232        " forward slashes ('//Foo'), depending on whether backslashes have been converted to
   9233        " forward slashes by earlier code; so check for both.
   9234        if has("win32") && !g:netrw_cygwin
   9235            if a:newdir =~ '^\\\\\w\+' || a:newdir =~ '^//\w\+'
   9236                let dirname = '\'
   9237                exe 'NetrwKeepj sil lcd '.fnameescape(dirname)
   9238            endif
   9239        endif
   9240    catch /^Vim\%((\a\+)\)\=:E472/
   9241        let err472= 1
   9242    endtry
   9243 
   9244    if err472
   9245        call netrw#msg#Notify('ERROR', printf('unable to change directory to <%s> (permissions?)', a:newdir))
   9246        if exists("w:netrw_prvdir")
   9247            let a:newdir= w:netrw_prvdir
   9248        else
   9249            call s:NetrwOptionsRestore("w:")
   9250            exe "setl ".g:netrw_bufsettings
   9251            let a:newdir= dirname
   9252        endif
   9253        return -1
   9254    endif
   9255 
   9256    return 0
   9257 endfunction
   9258 
   9259 " s:NetrwSaveWordPosn: used to keep cursor on same word after refresh, {{{2
   9260 " changed sorting, etc.  Also see s:NetrwRestoreWordPosn().
   9261 function s:NetrwSaveWordPosn()
   9262    let s:netrw_saveword= '^'.fnameescape(getline('.')).'$'
   9263 endfunction
   9264 
   9265 " s:NetrwHumanReadable: takes a number and makes it "human readable" {{{2
   9266 "                       1000 -> 1K, 1000000 -> 1M, 1000000000 -> 1G
   9267 function s:NetrwHumanReadable(sz)
   9268 
   9269    if g:netrw_sizestyle ==# 'h'
   9270        if a:sz >= 1000000000
   9271            let sz = printf("%.1f",a:sz/1000000000.0)."g"
   9272        elseif a:sz >= 10000000
   9273            let sz = printf("%d",a:sz/1000000)."m"
   9274        elseif a:sz >= 1000000
   9275            let sz = printf("%.1f",a:sz/1000000.0)."m"
   9276        elseif a:sz >= 10000
   9277            let sz = printf("%d",a:sz/1000)."k"
   9278        elseif a:sz >= 1000
   9279            let sz = printf("%.1f",a:sz/1000.0)."k"
   9280        else
   9281            let sz= a:sz
   9282        endif
   9283 
   9284    elseif g:netrw_sizestyle ==# 'H'
   9285        if a:sz >= 1073741824
   9286            let sz = printf("%.1f",a:sz/1073741824.0)."G"
   9287        elseif a:sz >= 10485760
   9288            let sz = printf("%d",a:sz/1048576)."M"
   9289        elseif a:sz >= 1048576
   9290            let sz = printf("%.1f",a:sz/1048576.0)."M"
   9291        elseif a:sz >= 10240
   9292            let sz = printf("%d",a:sz/1024)."K"
   9293        elseif a:sz >= 1024
   9294            let sz = printf("%.1f",a:sz/1024.0)."K"
   9295        else
   9296            let sz= a:sz
   9297        endif
   9298 
   9299    else
   9300        let sz= a:sz
   9301    endif
   9302 
   9303    return sz
   9304 endfunction
   9305 
   9306 " s:NetrwRestoreWordPosn: used to keep cursor on same word after refresh, {{{2
   9307 "  changed sorting, etc.  Also see s:NetrwSaveWordPosn().
   9308 function s:NetrwRestoreWordPosn()
   9309    sil! call search(s:netrw_saveword,'w')
   9310 endfunction
   9311 
   9312 " s:RestoreBufVars: {{{2
   9313 function s:RestoreBufVars()
   9314 
   9315    if exists("s:netrw_curdir")        |let b:netrw_curdir         = s:netrw_curdir        |endif
   9316    if exists("s:netrw_lastfile")      |let b:netrw_lastfile       = s:netrw_lastfile      |endif
   9317    if exists("s:netrw_method")        |let b:netrw_method         = s:netrw_method        |endif
   9318    if exists("s:netrw_fname")         |let b:netrw_fname          = s:netrw_fname         |endif
   9319    if exists("s:netrw_machine")       |let b:netrw_machine        = s:netrw_machine       |endif
   9320    if exists("s:netrw_browser_active")|let b:netrw_browser_active = s:netrw_browser_active|endif
   9321 
   9322 endfunction
   9323 
   9324 " s:RemotePathAnalysis: {{{2
   9325 function s:RemotePathAnalysis(dirname)
   9326 
   9327    "                method   ://    user    @      machine      :port           /path
   9328    let dirpat  = '^\(\w\{-}\)://\(\([^@]\+\)@\)\=\([^/:#]\+\)\%([:#]\(\d\+\)\)\=/\(.*\)$'
   9329    let s:method  = substitute(a:dirname,dirpat,'\1','')
   9330    let s:user    = substitute(a:dirname,dirpat,'\3','')
   9331    let s:machine = substitute(a:dirname,dirpat,'\4','')
   9332    let s:port    = substitute(a:dirname,dirpat,'\5','')
   9333    let s:path    = substitute(a:dirname,dirpat,'\6','')
   9334    let s:fname   = substitute(s:path,'^.*/\ze.','','')
   9335    if s:machine =~ '@'
   9336        let dirpat    = '^\(.*\)@\(.\{-}\)$'
   9337        let s:user    = s:user.'@'.substitute(s:machine,dirpat,'\1','')
   9338        let s:machine = substitute(s:machine,dirpat,'\2','')
   9339    endif
   9340 
   9341 
   9342 endfunction
   9343 
   9344 " s:RemoteSystem: runs a command on a remote host using ssh {{{2
   9345 "                 Returns status
   9346 " Runs system() on
   9347 "    [cd REMOTEDIRPATH;] a:cmd
   9348 " Note that it doesn't do netrw#os#Escape(a:cmd)!
   9349 function s:RemoteSystem(cmd)
   9350    if !executable(g:netrw_ssh_cmd)
   9351        call netrw#msg#Notify('ERROR', printf('g:netrw_ssh_cmd<%s> is not executable!', g:netrw_ssh_cmd))
   9352    elseif !exists("b:netrw_curdir")
   9353        call netrw#msg#Notify('ERROR', "for some reason b:netrw_curdir doesn't exist!")
   9354    else
   9355        let cmd      = s:MakeSshCmd(g:netrw_ssh_cmd." USEPORT HOSTNAME")
   9356        let remotedir= substitute(b:netrw_curdir,'^.*//[^/]\+/\(.*\)$','\1','')
   9357        if remotedir != ""
   9358            let cmd= cmd.' cd '.netrw#os#Escape(remotedir).";"
   9359        else
   9360            let cmd= cmd.' '
   9361        endif
   9362        let cmd= cmd.a:cmd
   9363        let ret= system(cmd)
   9364    endif
   9365    return ret
   9366 endfunction
   9367 
   9368 " s:RestoreWinVars: (used by Explore() and NetrwSplit()) {{{2
   9369 function s:RestoreWinVars()
   9370    if exists("s:bannercnt")      |let w:netrw_bannercnt       = s:bannercnt      |unlet s:bannercnt      |endif
   9371    if exists("s:col")            |let w:netrw_col             = s:col            |unlet s:col            |endif
   9372    if exists("s:curdir")         |let w:netrw_curdir          = s:curdir         |unlet s:curdir         |endif
   9373    if exists("s:explore_bufnr")  |let w:netrw_explore_bufnr   = s:explore_bufnr  |unlet s:explore_bufnr  |endif
   9374    if exists("s:explore_indx")   |let w:netrw_explore_indx    = s:explore_indx   |unlet s:explore_indx   |endif
   9375    if exists("s:explore_line")   |let w:netrw_explore_line    = s:explore_line   |unlet s:explore_line   |endif
   9376    if exists("s:explore_listlen")|let w:netrw_explore_listlen = s:explore_listlen|unlet s:explore_listlen|endif
   9377    if exists("s:explore_list")   |let w:netrw_explore_list    = s:explore_list   |unlet s:explore_list   |endif
   9378    if exists("s:explore_mtchcnt")|let w:netrw_explore_mtchcnt = s:explore_mtchcnt|unlet s:explore_mtchcnt|endif
   9379    if exists("s:fpl")            |let w:netrw_fpl             = s:fpl            |unlet s:fpl            |endif
   9380    if exists("s:hline")          |let w:netrw_hline           = s:hline          |unlet s:hline          |endif
   9381    if exists("s:line")           |let w:netrw_line            = s:line           |unlet s:line           |endif
   9382    if exists("s:liststyle")      |let w:netrw_liststyle       = s:liststyle      |unlet s:liststyle      |endif
   9383    if exists("s:method")         |let w:netrw_method          = s:method         |unlet s:method         |endif
   9384    if exists("s:prvdir")         |let w:netrw_prvdir          = s:prvdir         |unlet s:prvdir         |endif
   9385    if exists("s:treedict")       |let w:netrw_treedict        = s:treedict       |unlet s:treedict       |endif
   9386    if exists("s:treetop")        |let w:netrw_treetop         = s:treetop        |unlet s:treetop        |endif
   9387    if exists("s:winnr")          |let w:netrw_winnr           = s:winnr          |unlet s:winnr          |endif
   9388 endfunction
   9389 
   9390 " s:Rexplore: implements returning from a buffer to a netrw directory {{{2
   9391 "
   9392 "             s:SetRexDir() sets up <2-leftmouse> maps (if g:netrw_retmap
   9393 "             is true) and a command, :Rexplore, which call this function.
   9394 "
   9395 "             s:netrw_posn is set up by s:NetrwBrowseChgDir()
   9396 "
   9397 "             s:rexposn_BUFNR used to save/restore cursor position
   9398 function s:NetrwRexplore(islocal,dirname)
   9399    if exists("s:netrwdrag")
   9400        return
   9401    endif
   9402 
   9403    if &ft == "netrw" && exists("w:netrw_rexfile") && w:netrw_rexfile != ""
   9404        " a :Rex while in a netrw buffer means: edit the file in w:netrw_rexfile
   9405        exe "NetrwKeepj e ".w:netrw_rexfile
   9406        unlet w:netrw_rexfile
   9407        return
   9408    endif
   9409 
   9410    " ---------------------------
   9411    " :Rex issued while in a file
   9412    " ---------------------------
   9413 
   9414    " record current file so :Rex can return to it from netrw
   9415    let w:netrw_rexfile= expand("%")
   9416 
   9417    if !exists("w:netrw_rexlocal")
   9418        return
   9419    endif
   9420    if w:netrw_rexlocal
   9421        NetrwKeepj call netrw#LocalBrowseCheck(w:netrw_rexdir)
   9422    else
   9423        NetrwKeepj call s:NetrwBrowse(0,w:netrw_rexdir)
   9424    endif
   9425    if exists("s:initbeval")
   9426        setl beval
   9427    endif
   9428    if exists("s:rexposn_".bufnr("%"))
   9429        " restore position in directory listing
   9430        NetrwKeepj call winrestview(s:rexposn_{bufnr('%')})
   9431        if exists("s:rexposn_".bufnr('%'))
   9432            unlet s:rexposn_{bufnr('%')}
   9433        endif
   9434    else
   9435    endif
   9436 
   9437    if has("syntax") && exists("g:syntax_on") && g:syntax_on
   9438        if exists("s:explore_match")
   9439            exe "2match netrwMarkFile /".s:explore_match."/"
   9440        endif
   9441    endif
   9442 
   9443 endfunction
   9444 
   9445 " s:SaveBufVars: save selected b: variables to s: variables {{{2
   9446 "                use s:RestoreBufVars() to restore b: variables from s: variables
   9447 function s:SaveBufVars()
   9448 
   9449    if exists("b:netrw_curdir")        |let s:netrw_curdir         = b:netrw_curdir        |endif
   9450    if exists("b:netrw_lastfile")      |let s:netrw_lastfile       = b:netrw_lastfile      |endif
   9451    if exists("b:netrw_method")        |let s:netrw_method         = b:netrw_method        |endif
   9452    if exists("b:netrw_fname")         |let s:netrw_fname          = b:netrw_fname         |endif
   9453    if exists("b:netrw_machine")       |let s:netrw_machine        = b:netrw_machine       |endif
   9454    if exists("b:netrw_browser_active")|let s:netrw_browser_active = b:netrw_browser_active|endif
   9455 
   9456 endfunction
   9457 
   9458 " s:SavePosn: saves position associated with current buffer into a dictionary {{{2
   9459 function s:SavePosn(posndict)
   9460 
   9461    if !exists("a:posndict[bufnr('%')]")
   9462        let a:posndict[bufnr("%")]= []
   9463    endif
   9464    call add(a:posndict[bufnr("%")],winsaveview())
   9465 
   9466    return a:posndict
   9467 endfunction
   9468 
   9469 " s:RestorePosn: restores position associated with current buffer using dictionary {{{2
   9470 function s:RestorePosn(posndict)
   9471    if exists("a:posndict")
   9472        if has_key(a:posndict,bufnr("%"))
   9473            let posnlen= len(a:posndict[bufnr("%")])
   9474            if posnlen > 0
   9475                let posnlen= posnlen - 1
   9476                call winrestview(a:posndict[bufnr("%")][posnlen])
   9477                call remove(a:posndict[bufnr("%")],posnlen)
   9478            endif
   9479        endif
   9480    endif
   9481 endfunction
   9482 
   9483 " s:SaveWinVars: (used by Explore() and NetrwSplit()) {{{2
   9484 function s:SaveWinVars()
   9485    if exists("w:netrw_bannercnt")      |let s:bannercnt       = w:netrw_bannercnt      |endif
   9486    if exists("w:netrw_col")            |let s:col             = w:netrw_col            |endif
   9487    if exists("w:netrw_curdir")         |let s:curdir          = w:netrw_curdir         |endif
   9488    if exists("w:netrw_explore_bufnr")  |let s:explore_bufnr   = w:netrw_explore_bufnr  |endif
   9489    if exists("w:netrw_explore_indx")   |let s:explore_indx    = w:netrw_explore_indx   |endif
   9490    if exists("w:netrw_explore_line")   |let s:explore_line    = w:netrw_explore_line   |endif
   9491    if exists("w:netrw_explore_listlen")|let s:explore_listlen = w:netrw_explore_listlen|endif
   9492    if exists("w:netrw_explore_list")   |let s:explore_list    = w:netrw_explore_list   |endif
   9493    if exists("w:netrw_explore_mtchcnt")|let s:explore_mtchcnt = w:netrw_explore_mtchcnt|endif
   9494    if exists("w:netrw_fpl")            |let s:fpl             = w:netrw_fpl            |endif
   9495    if exists("w:netrw_hline")          |let s:hline           = w:netrw_hline          |endif
   9496    if exists("w:netrw_line")           |let s:line            = w:netrw_line           |endif
   9497    if exists("w:netrw_liststyle")      |let s:liststyle       = w:netrw_liststyle      |endif
   9498    if exists("w:netrw_method")         |let s:method          = w:netrw_method         |endif
   9499    if exists("w:netrw_prvdir")         |let s:prvdir          = w:netrw_prvdir         |endif
   9500    if exists("w:netrw_treedict")       |let s:treedict        = w:netrw_treedict       |endif
   9501    if exists("w:netrw_treetop")        |let s:treetop         = w:netrw_treetop        |endif
   9502    if exists("w:netrw_winnr")          |let s:winnr           = w:netrw_winnr          |endif
   9503 endfunction
   9504 
   9505 " s:SetBufWinVars: (used by NetrwBrowse() and LocalBrowseCheck()) {{{2
   9506 "   To allow separate windows to have their own activities, such as
   9507 "   Explore **/pattern, several variables have been made window-oriented.
   9508 "   However, when the user splits a browser window (ex: ctrl-w s), these
   9509 "   variables are not inherited by the new window.  SetBufWinVars() and
   9510 "   UseBufWinVars() get around that.
   9511 function s:SetBufWinVars()
   9512    if exists("w:netrw_liststyle")      |let b:netrw_liststyle      = w:netrw_liststyle      |endif
   9513    if exists("w:netrw_bannercnt")      |let b:netrw_bannercnt      = w:netrw_bannercnt      |endif
   9514    if exists("w:netrw_method")         |let b:netrw_method         = w:netrw_method         |endif
   9515    if exists("w:netrw_prvdir")         |let b:netrw_prvdir         = w:netrw_prvdir         |endif
   9516    if exists("w:netrw_explore_indx")   |let b:netrw_explore_indx   = w:netrw_explore_indx   |endif
   9517    if exists("w:netrw_explore_listlen")|let b:netrw_explore_listlen= w:netrw_explore_listlen|endif
   9518    if exists("w:netrw_explore_mtchcnt")|let b:netrw_explore_mtchcnt= w:netrw_explore_mtchcnt|endif
   9519    if exists("w:netrw_explore_bufnr")  |let b:netrw_explore_bufnr  = w:netrw_explore_bufnr  |endif
   9520    if exists("w:netrw_explore_line")   |let b:netrw_explore_line   = w:netrw_explore_line   |endif
   9521    if exists("w:netrw_explore_list")   |let b:netrw_explore_list   = w:netrw_explore_list   |endif
   9522 endfunction
   9523 
   9524 " s:SetRexDir: set directory for :Rexplore {{{2
   9525 function s:SetRexDir(islocal,dirname)
   9526    let w:netrw_rexdir         = a:dirname
   9527    let w:netrw_rexlocal       = a:islocal
   9528    let s:rexposn_{bufnr("%")} = winsaveview()
   9529 endfunction
   9530 
   9531 " s:ShowLink: used to modify thin and tree listings to show links {{{2
   9532 function s:ShowLink()
   9533    if exists("b:netrw_curdir")
   9534        keepp :norm! $?\a
   9535        "call histdel("/",-1)
   9536        if exists("w:netrw_liststyle") && w:netrw_liststyle == s:TREELIST && exists("w:netrw_treetop")
   9537            let basedir = s:NetrwTreePath(w:netrw_treetop)
   9538        else
   9539            let basedir = b:netrw_curdir.'/'
   9540        endif
   9541        let fname = basedir.s:NetrwGetWord()
   9542        let resname = resolve(fname)
   9543        if resname =~ '^\M'.basedir
   9544            let dirlen  = strlen(basedir)
   9545            let resname = strpart(resname,dirlen)
   9546        endif
   9547        let modline = getline(".")."\t --> ".resname
   9548        setl noro ma
   9549        call setline(".",modline)
   9550        setl ro noma nomod
   9551    endif
   9552 endfunction
   9553 
   9554 " s:ShowStyle: {{{2
   9555 function s:ShowStyle()
   9556    if !exists("w:netrw_liststyle")
   9557        let liststyle= g:netrw_liststyle
   9558    else
   9559        let liststyle= w:netrw_liststyle
   9560    endif
   9561    if     liststyle == s:THINLIST
   9562        return s:THINLIST.":thin"
   9563    elseif liststyle == s:LONGLIST
   9564        return s:LONGLIST.":long"
   9565    elseif liststyle == s:WIDELIST
   9566        return s:WIDELIST.":wide"
   9567    elseif liststyle == s:TREELIST
   9568        return s:TREELIST.":tree"
   9569    else
   9570        return 'n/a'
   9571    endif
   9572 endfunction
   9573 
   9574 " s:TreeListMove: supports [[, ]], [], and ][ in tree mode {{{2
   9575 function s:TreeListMove(dir)
   9576    let curline      = getline('.')
   9577    let prvline      = (line(".") > 1)?         getline(line(".")-1) : ''
   9578    let nxtline      = (line(".") < line("$"))? getline(line(".")+1) : ''
   9579    let curindent    = substitute(getline('.'),'^\(\%('.s:treedepthstring.'\)*\)[^'.s:treedepthstring.'].\{-}$','\1','e')
   9580    let indentm1     = substitute(curindent,'^'.s:treedepthstring,'','')
   9581    let treedepthchr = substitute(s:treedepthstring,' ','','g')
   9582    let stopline     = exists("w:netrw_bannercnt")? w:netrw_bannercnt : 1
   9583    "  COMBAK : need to handle when on a directory
   9584    "  COMBAK : need to handle ]] and ][.  In general, needs work!!!
   9585    if curline !~ '/$'
   9586        if     a:dir == '[[' && prvline != ''
   9587            NetrwKeepj norm! 0
   9588            let nl = search('^'.indentm1.'\%('.s:treedepthstring.'\)\@!','bWe',stopline) " search backwards
   9589        elseif a:dir == '[]' && nxtline != ''
   9590            NetrwKeepj norm! 0
   9591            let nl = search('^\%('.curindent.'\)\@!','We') " search forwards
   9592            if nl != 0
   9593                NetrwKeepj norm! k
   9594            else
   9595                NetrwKeepj norm! G
   9596            endif
   9597        endif
   9598    endif
   9599 
   9600 endfunction
   9601 
   9602 " s:UpdateBuffersMenu: does emenu Buffers.Refresh (but due to locale, the menu item may not be called that) {{{2
   9603 "                      The Buffers.Refresh menu calls s:BMShow(); unfortunately, that means that that function
   9604 "                      can't be called except via emenu.  But due to locale, that menu line may not be called
   9605 "                      Buffers.Refresh; hence, s:NetrwBMShow() utilizes a "cheat" to call that function anyway.
   9606 function s:UpdateBuffersMenu()
   9607    if has("gui") && has("menu") && has("gui_running") && &go =~# 'm' && g:netrw_menu
   9608        try
   9609            sil emenu Buffers.Refresh\ menu
   9610        catch /^Vim\%((\a\+)\)\=:E/
   9611            let v:errmsg= ""
   9612            sil NetrwKeepj call s:NetrwBMShow()
   9613        endtry
   9614    endif
   9615 endfunction
   9616 
   9617 " s:UseBufWinVars: (used by NetrwBrowse() and LocalBrowseCheck() {{{2
   9618 "              Matching function to s:SetBufWinVars()
   9619 function s:UseBufWinVars()
   9620    if exists("b:netrw_liststyle")       && !exists("w:netrw_liststyle")      |let w:netrw_liststyle       = b:netrw_liststyle      |endif
   9621    if exists("b:netrw_bannercnt")       && !exists("w:netrw_bannercnt")      |let w:netrw_bannercnt       = b:netrw_bannercnt      |endif
   9622    if exists("b:netrw_method")          && !exists("w:netrw_method")         |let w:netrw_method          = b:netrw_method         |endif
   9623    if exists("b:netrw_prvdir")          && !exists("w:netrw_prvdir")         |let w:netrw_prvdir          = b:netrw_prvdir         |endif
   9624    if exists("b:netrw_explore_indx")    && !exists("w:netrw_explore_indx")   |let w:netrw_explore_indx    = b:netrw_explore_indx   |endif
   9625    if exists("b:netrw_explore_listlen") && !exists("w:netrw_explore_listlen")|let w:netrw_explore_listlen = b:netrw_explore_listlen|endif
   9626    if exists("b:netrw_explore_mtchcnt") && !exists("w:netrw_explore_mtchcnt")|let w:netrw_explore_mtchcnt = b:netrw_explore_mtchcnt|endif
   9627    if exists("b:netrw_explore_bufnr")   && !exists("w:netrw_explore_bufnr")  |let w:netrw_explore_bufnr   = b:netrw_explore_bufnr  |endif
   9628    if exists("b:netrw_explore_line")    && !exists("w:netrw_explore_line")   |let w:netrw_explore_line    = b:netrw_explore_line   |endif
   9629    if exists("b:netrw_explore_list")    && !exists("w:netrw_explore_list")   |let w:netrw_explore_list    = b:netrw_explore_list   |endif
   9630 endfunction
   9631 
   9632 " s:UserMaps: supports user-defined UserMaps {{{2
   9633 "               * calls a user-supplied funcref(islocal,curdir)
   9634 "               * interprets result
   9635 "             See netrw#UserMaps()
   9636 function s:UserMaps(islocal,funcname)
   9637    if !exists("b:netrw_curdir")
   9638        let b:netrw_curdir= getcwd()
   9639    endif
   9640    let Funcref = function(a:funcname)
   9641    let result  = Funcref(a:islocal)
   9642 
   9643    if     type(result) == 1
   9644        " if result from user's funcref is a string...
   9645        if result == "refresh"
   9646            call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./',0))
   9647        elseif result != ""
   9648            exe result
   9649        endif
   9650 
   9651    elseif type(result) == 3
   9652        " if result from user's funcref is a List...
   9653        for action in result
   9654            if action == "refresh"
   9655                call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./',0))
   9656            elseif action != ""
   9657                exe action
   9658            endif
   9659        endfor
   9660    endif
   9661 endfunction
   9662 
   9663 " Deprecated: {{{1
   9664 
   9665 " }}}
   9666 " Settings Restoration: {{{1
   9667 
   9668 let &cpo= s:keepcpo
   9669 unlet s:keepcpo
   9670 
   9671 " }}}
   9672 " vim:ts=8 sts=4 sw=4 et fdm=marker