wbthomason / packer.nvim

A use-package inspired plugin manager for Neovim. Uses native packages, supports Luarocks dependencies, written in Lua, allows for expressive config
MIT License
7.9k stars 264 forks source link

question with startup time #62

Closed glepnir closed 4 years ago

glepnir commented 4 years ago

code in here https://github.com/glepnir/nvim/blob/packer/lua/loadpack.lua just three plugins. check startuptime..it takes too long time.

times in msec
 clock   self+sourced   self:  sourced script
 clock   elapsed:              other lines

000.013  000.013: --- NVIM STARTING ---
001.175  001.162: locale set
002.016  000.841: inits 1
002.045  000.029: window checked
002.049  000.004: parsing arguments
002.296  000.246: expanding arguments
002.374  000.078: inits 2
002.972  000.598: init highlight
002.973  000.001: waiting for UI
007.314  004.341: done waiting for UI
007.397  000.083: initialized screen early for UI
182.268  014.178  014.178: sourcing /usr/local/Cellar/neovim/HEAD-753a86c/share/nvim/runtime/filetype.vim
182.588  000.076  000.076: sourcing /usr/local/Cellar/neovim/HEAD-753a86c/share/nvim/runtime/ftplugin.vim
182.819  000.055  000.055: sourcing /usr/local/Cellar/neovim/HEAD-753a86c/share/nvim/runtime/indent.vim
183.714  000.403  000.403: sourcing /usr/local/Cellar/neovim/HEAD-753a86c/share/nvim/runtime/syntax/syncolor.vim
183.873  000.737  000.334: sourcing /usr/local/Cellar/neovim/HEAD-753a86c/share/nvim/runtime/syntax/synload.vim
183.911  000.935  000.199: sourcing /usr/local/Cellar/neovim/HEAD-753a86c/share/nvim/runtime/syntax/syntax.vim
186.185  000.240  000.240: sourcing /usr/local/Cellar/neovim/HEAD-753a86c/share/nvim/runtime/syntax/syncolor.vim
187.663  000.310  000.310: sourcing /usr/local/Cellar/neovim/HEAD-753a86c/share/nvim/runtime/syntax/syncolor.vim
188.521  000.220  000.220: sourcing /usr/local/Cellar/neovim/HEAD-753a86c/share/nvim/runtime/syntax/syncolor.vim
189.009  000.220  000.220: sourcing /usr/local/Cellar/neovim/HEAD-753a86c/share/nvim/runtime/syntax/syncolor.vim
192.754  006.112  005.362: sourcing /Users/stephen/.config/nvim/colors/oceanic_material.vim
192.841  184.905  163.308: sourcing /Users/stephen/.config/nvim/init.vim
192.857  000.556: sourcing vimrc file(s)
195.339  000.089  000.089: sourcing /Users/stephen/.config/nvim/plugin/bufkill.vim
195.597  000.200  000.200: sourcing /Users/stephen/.config/nvim/plugin/difftools.vim
195.877  000.155  000.155: sourcing /Users/stephen/.config/nvim/plugin/hlsearch.vim
196.114  000.178  000.178: sourcing /Users/stephen/.config/nvim/plugin/whitespace.vim
197.230  000.028  000.028: sourcing /usr/local/Cellar/neovim/HEAD-753a86c/share/nvim/runtime/plugin/gzip.vim
197.324  000.022  000.022: sourcing /usr/local/Cellar/neovim/HEAD-753a86c/share/nvim/runtime/plugin/health.vim
197.506  000.115  000.115: sourcing /usr/local/Cellar/neovim/HEAD-753a86c/share/nvim/runtime/plugin/man.vim
198.984  000.074  000.074: sourcing /usr/local/Cellar/neovim/HEAD-753a86c/share/nvim/runtime/pack/dist/opt/matchit/plugin/matchit.vim
199.367  001.768  001.694: sourcing /usr/local/Cellar/neovim/HEAD-753a86c/share/nvim/runtime/plugin/matchit.vim
199.466  000.028  000.028: sourcing /usr/local/Cellar/neovim/HEAD-753a86c/share/nvim/runtime/plugin/matchparen.vim
199.564  000.033  000.033: sourcing /usr/local/Cellar/neovim/HEAD-753a86c/share/nvim/runtime/plugin/netrwPlugin.vim
200.358  000.275  000.275: sourcing /usr/local/Cellar/neovim/HEAD-753a86c/share/nvim/runtime/autoload/remote/host.vim
200.832  000.258  000.258: sourcing /usr/local/Cellar/neovim/HEAD-753a86c/share/nvim/runtime/autoload/remote/define.vim
201.162  001.235  000.702: sourcing /Users/stephen/.local/share/nvim/rplugin.vim
201.173  001.499  000.265: sourcing /usr/local/Cellar/neovim/HEAD-753a86c/share/nvim/runtime/plugin/rplugin.vim
201.392  000.142  000.142: sourcing /usr/local/Cellar/neovim/HEAD-753a86c/share/nvim/runtime/plugin/shada.vim
201.552  000.063  000.063: sourcing /usr/local/Cellar/neovim/HEAD-753a86c/share/nvim/runtime/plugin/spellfile.vim
201.734  000.035  000.035: sourcing /usr/local/Cellar/neovim/HEAD-753a86c/share/nvim/runtime/plugin/tarPlugin.vim
201.837  000.025  000.025: sourcing /usr/local/Cellar/neovim/HEAD-753a86c/share/nvim/runtime/plugin/tohtml.vim
201.956  000.047  000.047: sourcing /usr/local/Cellar/neovim/HEAD-753a86c/share/nvim/runtime/plugin/tutor.vim
202.064  000.031  000.031: sourcing /usr/local/Cellar/neovim/HEAD-753a86c/share/nvim/runtime/plugin/zipPlugin.vim
202.156  004.839: loading plugins
203.015  000.281  000.281: sourcing /Users/stephen/.cache/vim/plugins/pack/packer/start/dashboard-nvim/plugin/dashboard.vim
203.859  000.070  000.070: sourcing /Users/stephen/.cache/vim/plugins/pack/packer/start/spaceline.vim/autoload/spaceline/seperator.vim
204.065  000.680  000.610: sourcing /Users/stephen/.cache/vim/plugins/pack/packer/start/spaceline.vim/plugin/statusline.vim
207.597  003.183  003.183: sourcing /Users/stephen/.cache/vim/plugins/pack/packer/start/vim-devicons/plugin/webdevicons.vim
207.674  001.374: loading packages
207.873  000.199: loading after plugins
207.894  000.021: inits 3
210.725  002.831: reading ShaDa
213.104  000.139  000.139: sourcing /Users/stephen/.cache/vim/plugins/pack/packer/start/spaceline.vim/autoload/spaceline.vim
213.429  000.098  000.098: sourcing /Users/stephen/.cache/vim/plugins/pack/packer/start/spaceline.vim/autoload/spaceline/colorscheme/space.vim
213.755  000.067  000.067: sourcing /Users/stephen/.cache/vim/plugins/pack/packer/start/spaceline.vim/autoload/spaceline/colors.vim
216.594  000.260  000.260: sourcing /Users/stephen/.cache/vim/plugins/pack/packer/start/spaceline.vim/autoload/spaceline/syntax.vim
217.724  000.102  000.102: sourcing /Users/stephen/.cache/vim/plugins/pack/packer/start/spaceline.vim/autoload/spaceline/diagnostic.vim
218.042  000.088  000.088: sourcing /Users/stephen/.cache/vim/plugins/pack/packer/start/spaceline.vim/autoload/spaceline/file.vim
218.327  000.105  000.105: sourcing /Users/stephen/.cache/vim/plugins/pack/packer/start/spaceline.vim/autoload/spaceline/vcs.vim
219.087  007.502: opening buffers
227.305  008.218: BufEnter autocommands
227.309  000.004: editing files in windows
227.764  000.236  000.236: sourcing /Users/stephen/.cache/vim/plugins/pack/packer/start/dashboard-nvim/autoload/dashboard.vim
228.100  000.037  000.037: sourcing /Users/stephen/.cache/vim/plugins/pack/packer/start/dashboard-nvim/autoload/dashboard/utils.vim
232.084  003.838  003.838: sourcing /Users/stephen/.cache/vim/plugins/pack/packer/start/dashboard-nvim/autoload/dashboard/header.vim
232.645  000.160  000.160: sourcing /Users/stephen/.cache/vim/plugins/pack/packer/start/dashboard-nvim/autoload/dashboard/section.vim
234.136  000.313  000.313: sourcing /usr/local/Cellar/neovim/HEAD-753a86c/share/nvim/runtime/autoload/provider/clipboard.vim
235.973  000.131  000.131: sourcing /Users/stephen/.cache/vim/plugins/pack/packer/start/dashboard-nvim/syntax/dashboard.vim
240.227  008.203: VimEnter autocommands
240.232  000.004: UIEnter autocommands
240.236  000.004: before starting main loop
242.844  002.608: first screen update
242.847  000.003: --- NVIM STARTED ---
wbthomason commented 4 years ago

I'm sorry, but I'll need more information if I'm to help. First off, from the startup trace you've provided, it's not clear that packer is responsible for the slow speed of loading init.vim - you source a lot of modules in core.lua, and your parse_config function is also doing nontrivial synchronous operations, which could easily be slowing you down.

Specifically to packer, I'll point out that you don't need to load packer at all/call use unless you want to do plugin management operations. That is, if you want to install, update, clean, or sync, you need packer loaded and your plugin specifications added with use. Otherwise, you do not.

If you can provide more detailed timing information/explain why you think the slow speed is packer's fault, I'd be happy to help. Otherwise, there's not much I can do - my entire config, using packer and some ~65 plugins, loads in ~40-50ms.

glepnir commented 4 years ago

Thank you for your reply. Check out my master branch. The only difference between it and the packer branch is that the plugin management uses packer. The other modules are basically the same. Using lua to configure neovim can not view the startup time of the script through startuptime, so it is difficult to see anything from the startuptime command. This is the startup speed of my master branch.

times in msec
 clock   self+sourced   self:  sourced script
 clock   elapsed:              other lines

000.008  000.008: --- NVIM STARTING ---
000.901  000.893: locale set
001.488  000.587: inits 1
001.512  000.024: window checked
001.516  000.003: parsing arguments
001.720  000.204: expanding arguments
001.787  000.067: inits 2
002.503  000.716: init highlight
002.505  000.001: waiting for UI
006.289  003.784: done waiting for UI
006.325  000.036: initialized screen early for UI
010.593  000.356  000.356: sourcing /Users/stephen/.cache/vim/dein/repos/github.com/Shougo/dein.vim/autoload/dein.vim
013.531  000.046  000.046: sourcing /usr/local/Cellar/neovim/HEAD-753a86c/share/nvim/runtime/ftoff.vim
014.111  003.152  003.106: sourcing /Users/stephen/.cache/vim/dein/state_nvim.vim
024.530  000.231  000.231: sourcing /Users/stephen/.cache/vim/dein/.cache/init.vim/.dein/ftdetect/ftdetect.vim
024.818  010.543  010.312: sourcing /usr/local/Cellar/neovim/HEAD-753a86c/share/nvim/runtime/filetype.vim
025.070  000.063  000.063: sourcing /Users/stephen/.cache/vim/dein/.cache/init.vim/.dein/ftplugin.vim
025.179  000.023  000.023: sourcing /usr/local/Cellar/neovim/HEAD-753a86c/share/nvim/runtime/ftplugin.vim
025.411  000.064  000.064: sourcing /usr/local/Cellar/neovim/HEAD-753a86c/share/nvim/runtime/indent.vim
026.239  000.350  000.350: sourcing /usr/local/Cellar/neovim/HEAD-753a86c/share/nvim/runtime/syntax/syncolor.vim
026.475  000.745  000.395: sourcing /usr/local/Cellar/neovim/HEAD-753a86c/share/nvim/runtime/syntax/synload.vim
026.524  000.961  000.217: sourcing /usr/local/Cellar/neovim/HEAD-753a86c/share/nvim/runtime/syntax/syntax.vim
026.930  000.257  000.257: sourcing /Users/stephen/.cache/vim/dein/repos/github.com/Shougo/dein.vim/autoload/dein/autoload.vim
027.740  000.629  000.629: sourcing /Users/stephen/.cache/vim/dein/repos/github.com/Shougo/dein.vim/autoload/dein/util.vim
030.999  000.237  000.237: sourcing /usr/local/Cellar/neovim/HEAD-753a86c/share/nvim/runtime/syntax/syncolor.vim
031.863  000.229  000.229: sourcing /usr/local/Cellar/neovim/HEAD-753a86c/share/nvim/runtime/syntax/syncolor.vim
033.063  000.233  000.233: sourcing /usr/local/Cellar/neovim/HEAD-753a86c/share/nvim/runtime/syntax/syncolor.vim
034.675  027.951  011.204: sourcing /Users/stephen/.config/nvim/init.vim
034.685  000.410: sourcing vimrc file(s)
035.445  000.096  000.096: sourcing /Users/stephen/.config/nvim/plugin/bufkill.vim
035.610  000.106  000.106: sourcing /Users/stephen/.config/nvim/plugin/cursorhold_nvim.vim
035.787  000.114  000.114: sourcing /Users/stephen/.config/nvim/plugin/difftools.vim
036.005  000.160  000.160: sourcing /Users/stephen/.config/nvim/plugin/hlsearch.vim
036.278  000.210  000.210: sourcing /Users/stephen/.config/nvim/plugin/whitespace.vim
037.062  000.245  000.245: sourcing /Users/stephen/.cache/vim/dein/.cache/init.vim/.dein/plugin/dadbod.vim
037.458  000.318  000.318: sourcing /Users/stephen/.cache/vim/dein/.cache/init.vim/.dein/plugin/dashboard.vim
040.843  003.316  003.316: sourcing /Users/stephen/.cache/vim/dein/.cache/init.vim/.dein/plugin/webdevicons.vim
041.990  000.036  000.036: sourcing /usr/local/Cellar/neovim/HEAD-753a86c/share/nvim/runtime/plugin/gzip.vim
042.099  000.027  000.027: sourcing /usr/local/Cellar/neovim/HEAD-753a86c/share/nvim/runtime/plugin/health.vim
042.276  000.102  000.102: sourcing /usr/local/Cellar/neovim/HEAD-753a86c/share/nvim/runtime/plugin/man.vim
043.483  000.042  000.042: sourcing /usr/local/Cellar/neovim/HEAD-753a86c/share/nvim/runtime/pack/dist/opt/matchit/plugin/matchit.vim
043.570  001.202  001.160: sourcing /usr/local/Cellar/neovim/HEAD-753a86c/share/nvim/runtime/plugin/matchit.vim
043.661  000.027  000.027: sourcing /usr/local/Cellar/neovim/HEAD-753a86c/share/nvim/runtime/plugin/matchparen.vim
043.755  000.031  000.031: sourcing /usr/local/Cellar/neovim/HEAD-753a86c/share/nvim/runtime/plugin/netrwPlugin.vim
044.801  000.602  000.602: sourcing /usr/local/Cellar/neovim/HEAD-753a86c/share/nvim/runtime/autoload/remote/host.vim
045.722  000.390  000.390: sourcing /usr/local/Cellar/neovim/HEAD-753a86c/share/nvim/runtime/autoload/remote/define.vim
046.133  002.083  001.090: sourcing /Users/stephen/.local/share/nvim/rplugin.vim
046.144  002.326  000.243: sourcing /usr/local/Cellar/neovim/HEAD-753a86c/share/nvim/runtime/plugin/rplugin.vim
046.384  000.163  000.163: sourcing /usr/local/Cellar/neovim/HEAD-753a86c/share/nvim/runtime/plugin/shada.vim
046.544  000.045  000.045: sourcing /usr/local/Cellar/neovim/HEAD-753a86c/share/nvim/runtime/plugin/spellfile.vim
046.653  000.031  000.031: sourcing /usr/local/Cellar/neovim/HEAD-753a86c/share/nvim/runtime/plugin/tarPlugin.vim
046.749  000.026  000.026: sourcing /usr/local/Cellar/neovim/HEAD-753a86c/share/nvim/runtime/plugin/tohtml.vim
046.862  000.034  000.034: sourcing /usr/local/Cellar/neovim/HEAD-753a86c/share/nvim/runtime/plugin/tutor.vim
046.960  000.033  000.033: sourcing /usr/local/Cellar/neovim/HEAD-753a86c/share/nvim/runtime/plugin/zipPlugin.vim
047.052  003.719: loading plugins
047.263  000.210: loading packages
047.448  000.185: loading after plugins
047.462  000.014: inits 3
050.861  003.398: reading ShaDa
052.478  001.617: opening buffers
052.534  000.056: BufEnter autocommands
052.537  000.003: editing files in windows
053.472  000.269  000.269: sourcing /Users/stephen/.cache/vim/dein/.cache/init.vim/.dein/autoload/dashboard.vim
053.785  000.039  000.039: sourcing /Users/stephen/.cache/vim/dein/.cache/init.vim/.dein/autoload/dashboard/utils.vim
057.979  003.619  003.619: sourcing /Users/stephen/.cache/vim/dein/.cache/init.vim/.dein/autoload/dashboard/header.vim
059.149  000.162  000.162: sourcing /Users/stephen/.cache/vim/dein/.cache/init.vim/.dein/autoload/dashboard/section.vim
060.647  000.324  000.324: sourcing /usr/local/Cellar/neovim/HEAD-753a86c/share/nvim/runtime/autoload/provider/clipboard.vim
063.129  000.117  000.117: sourcing /Users/stephen/.cache/vim/dein/.cache/init.vim/.dein/syntax/dashboard.vim
063.808  006.743: VimEnter autocommands
063.811  000.003: UIEnter autocommands
063.815  000.003: before starting main loop
065.867  002.053: first screen update
065.881  000.013: --- NVIM STARTED ---
glepnir commented 4 years ago

@wbthomason got a new error image

glepnir commented 4 years ago

In dein I can use on_map to bind the keymap like n = <Plug> , but in packer keys just support {mode,map} or key map string like - { repo: rhysd/accelerated-jk, on_map: { n: <Plug> } } , bind j and k for this plugin. when i use j or k load this plugin. In packer {'rhysd/accelerated-jk', keys = 'j'} or keys = {{'n','j'},{'n','k'}} It's too troublesome..

wbthomason commented 4 years ago

The only difference between it and the packer branch is that the plugin management uses packer. The other modules are basically the same.

I will note that your parse_config function is different in both as well, and the python you (may?) execute in the packer branch is likely slower than the find command you use in master.

Using lua to configure neovim can not view the startup time of the script through startuptime, so it is difficult to see anything from the startuptime command.

Yes, this is an unfortunate shortcoming of startuptime. If you would like to do more fine-grained profiling, I suggest using the reltime() function, built-in to Neovim. Using this, for example, I can see that requiring packer and calling packer.init() and packer.reset() takes ~7ms on my machine.

@wbthomason got a new error

The only time this error happens (that I'm aware of) is when there's an issue with your config, e.g. https://github.com/wbthomason/packer.nvim/pull/59 (there, there was an autocommand that was triggering and setting the update buffer to nonmodifiable when packer was trying to write to it).

In dein I can use on_map to bind the keymap like n = , but in packer keys just support {mode,map} or key map string like - { repo: rhysd/accelerated-jk, on_map: { n: } } , bind j and k for this plugin. when i use j or k load this plugin. In packer {'rhysd/accelerated-jk', keys = 'j'} or keys = {{'n','j'},{'n','k'}}

PRs are always welcome! I would definitely merge something adding dein's keymap shortcuts.

It's too troublesome..

I'm sorry you find packer difficult to use. You're welcome to use (or not use) whatever plugin manager you would like, and PRs to improve packer are always welcome.

glepnir commented 4 years ago

hey I have rewrite it on my master branch. seems like only buffer modified problem is trouble some…

--------------原始邮件-------------- 发件人:"Wil Thomason "<notifications@github.com>; 发送时间:2020年10月9日(星期五) 凌晨0:03 收件人:"wbthomason/packer.nvim" <packer.nvim@noreply.github.com>; 抄送:"Raphael "<glepnir@gopherhub.org>;"Author "<author@noreply.github.com>; 主题:Re: [wbthomason/packer.nvim] question with startup time (#62)

The only difference between it and the packer branch is that the plugin management uses packer. The other modules are basically the same.

I will note that your parse_config function is different in both as well, and the python you (may?) execute in the packer branch is likely slower than the find command you use in master.

Using lua to configure neovim can not view the startup time of the script through startuptime, so it is difficult to see anything from the startuptime command.

Yes, this is an unfortunate shortcoming of startuptime. If you would like to do more fine-grained profiling, I suggest using the reltime() function, built-in to Neovim. Using this, for example, I can see that requiring packer and calling packer.init() and packer.reset() takes ~7ms on my machine.

@wbthomason got a new error

The only time this error happens (that I'm aware of) is when there's an issue with your config, e.g. #59 (there, there was an autocommand that was triggering and setting the update buffer to nonmodifiable when packer was trying to write to it).

In dein I can use on_map to bind the keymap like n = , but in packer keys just support {mode,map} or key map string like - { repo: rhysd/accelerated-jk, on_map: { n: } } , bind j and k for this plugin. when i use j or k load this plugin. In packer {'rhysd/accelerated-jk', keys = 'j'} or keys = {{'n','j'},{'n','k'}}

PRs are always welcome! I would definitely merge something adding dein's keymap shortcuts.

It's too troublesome..

I'm sorry you find packer difficult to use. You're welcome to use (or not use) whatever plugin manager you would like, and PRs to improve packer are always welcome.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub, or unsubscribe.

glepnir commented 4 years ago

bug of keys keyword. j doesn't work..

{rhysd/accelerated-jk,keys={'n','j'}`
nmap <silent> j <Plug>(accelerated_jk_gj)
nmap <silent> k <Plug>(accelerated_jk_gk)

To be honest, packer is a good direction, but there are many missing features and some problems. I have done a lot of work to make packer suitable for me, but I failed.. If I have time, maybe I will improve packer, but my currently job is to fix neovim-lsp bugs and implement new functions to nvim-lua/lsp_extension, so I don’t have much time to check packer. Here is what I have done to packer may be helpful to you here, you may refer to dein about keys https://github.com/Shougo/dein.vim/blob/master/autoload/dein/parse.vim#L313

best wishes

wbthomason commented 4 years ago

I'll note that your keys example is not a bug, but is just the dein feature you mention being absent.

I'm sorry packer didn't work out for you this time. Please feel free to file issues requesting features you'd like to see added.

glepnir commented 4 years ago

Okay, maybe I don’t understand the meaning of keys. My understanding is that the plugin will only be loaded when the key is triggered. It’s strange. When I do this, my j can’t work properly. Check verbose nmap j I got no mapping:) In addition, the packer also lacks some functions, but I think I can hack, but I still don’t understand how some packages are loaded. For example, if I install the plugin like this, defx-git and defx-icon did not work..I spent too much time in packer... so I am going to do other things.. But when I have time ,I will retry packer.

  {'Shougo/defx.nvim',
   cmd = 'Defx',
   setup = function()
    vim.api.nvim_command('autocmd FileType defx setlocal nonumber | setlocal norelativenumber')
   end,
   requires = {{'kristijanhusak/defx-icons',opt = true},{'kristijanhusak/defx-git',opt = true }},
   config = function()
    vim.g.defx_icons_column_length = 1
    vim.g.defx_icons_mark_icon = ''
    vim.g.defx_icons_parent_icon = ""
    vim.fn['defx#custom#option']('_', {
      resume = 1,
      winwidth =  30,
      split = 'vertical',
      direction = 'topleft',
      show_ignored_files = 0,
      columns =' mark:indent:git:icons:filename',
      root_marker = '[in]: ',
    })
    vim.fn['defx#custom#column']('git', {
      indicators = {
        Modified  = '•',
        Staged    = '✚',
        Untracked = 'ᵁ',
        Renamed   = '≫',
        Unmerged  = '≠',
        Ignored   = 'ⁱ',
        Deleted   = '✖',
        Unknown   = '⁇'}
    })
    vim.fn['defx#custom#column']('mark', { readonly_icon= '', selected_icon = '' })
    vim.api.nvim_command([[
    " Events
    " ---
    augroup user_plugin_defx
      autocmd!
      " Define defx window mappings
      autocmd FileType defx call <SID>defx_mappings()
      " Delete defx if it's the only buffer left in the window
      autocmd WinEnter * if &filetype == 'defx' && winnr('$') == 1 | bdel | endif
      " Move focus to the next window if current buffer is defx
      autocmd TabLeave * if &filetype == 'defx' | wincmd w | endif
    augroup END
    " Internal functions
    " ---
    function! s:jump_dirty(dir) abort
      " Jump to the next position with defx-git dirty symbols
      let l:icons = get(g:, 'defx_git_indicators', {})
      let l:icons_pattern = join(values(l:icons), '\|')
      if ! empty(l:icons_pattern)
        let l:direction = a:dir > 0 ? 'w' : 'bw'
        return search(printf('\(%s\)', l:icons_pattern), l:direction)
      endif
    endfunction
    function! s:defx_toggle_tree() abort
      " Open current file, or toggle directory expand/collapse
      if defx#is_directory()
        return defx#do_action('open_or_close_tree')
      endif
      return defx#do_action('multi', ['drop'])
    endfunction
    function! s:defx_mappings() abort
      " Defx window keyboard mappings
      setlocal signcolumn=no expandtab
      nnoremap <silent><buffer><expr> <CR>  defx#do_action('drop')
      nnoremap <silent><buffer><expr> l     <sid>defx_toggle_tree()
      nnoremap <silent><buffer><expr> h     defx#async_action('cd', ['..'])
      nnoremap <silent><buffer><expr> st    defx#do_action('multi', [['drop', 'tabnew'], 'quit'])
      nnoremap <silent><buffer><expr> s     defx#do_action('open', 'botright vsplit')
      nnoremap <silent><buffer><expr> i     defx#do_action('open', 'botright split')
      nnoremap <silent><buffer><expr> P     defx#do_action('preview')
      nnoremap <silent><buffer><expr> K     defx#do_action('new_directory')
      nnoremap <silent><buffer><expr> N     defx#do_action('new_multiple_files')
      nnoremap <silent><buffer><expr> dd    defx#do_action('remove_trash')
      nnoremap <silent><buffer><expr> r     defx#do_action('rename')
      nnoremap <silent><buffer><expr> x     defx#do_action('execute_system')
      nnoremap <silent><buffer><expr> .     defx#do_action('toggle_ignored_files')
      nnoremap <silent><buffer><expr> yy    defx#do_action('yank_path')
      nnoremap <silent><buffer><expr> ~     defx#async_action('cd')
      nnoremap <silent><buffer><expr> q     defx#do_action('quit')
      nnoremap <silent><buffer><expr> <Tab> winnr('$') != 1 ?
        \ ':<C-u>wincmd w<CR>' :
        \ ':<C-u>Defx -buffer-name=temp -split=vertical<CR>'
      " Defx's buffer management
      nnoremap <silent><buffer><expr> q      defx#do_action('quit')
      nnoremap <silent><buffer><expr> se     defx#do_action('save_session')
      nnoremap <silent><buffer><expr> <C-r>  defx#do_action('redraw')
      nnoremap <silent><buffer><expr> <C-g>  defx#do_action('print')
      " File/dir management
      nnoremap <silent><buffer><expr><nowait> c  defx#do_action('copy')
      nnoremap <silent><buffer><expr><nowait> m  defx#do_action('move')
      nnoremap <silent><buffer><expr><nowait> p  defx#do_action('paste')
      nnoremap <silent><buffer><expr><nowait> r  defx#do_action('rename')
      nnoremap <silent><buffer><expr> dd defx#do_action('remove_trash')
      nnoremap <silent><buffer><expr> K  defx#do_action('new_directory')
      nnoremap <silent><buffer><expr> N  defx#do_action('new_multiple_files')
      " Jump
      nnoremap <silent><buffer>  [g :<C-u>call <SID>jump_dirty(-1)<CR>
      nnoremap <silent><buffer>  ]g :<C-u>call <SID>jump_dirty(1)<CR>
      " Change directory
      nnoremap <silent><buffer><expr><nowait> \  defx#do_action('cd', getcwd())
      nnoremap <silent><buffer><expr><nowait> &  defx#do_action('cd', getcwd())
      nnoremap <silent><buffer><expr> <BS>  defx#async_action('cd', ['..'])
      nnoremap <silent><buffer><expr> ~     defx#async_action('cd')
      nnoremap <silent><buffer><expr> u   defx#do_action('cd', ['..'])
      nnoremap <silent><buffer><expr> 2u  defx#do_action('cd', ['../..'])
      nnoremap <silent><buffer><expr> 3u  defx#do_action('cd', ['../../..'])
      nnoremap <silent><buffer><expr> 4u  defx#do_action('cd', ['../../../..'])
      " Selection
      nnoremap <silent><buffer><expr> *  defx#do_action('toggle_select_all')
      nnoremap <silent><buffer><expr><nowait> <Space>
        \ defx#do_action('toggle_select') . 'j'
      nnoremap <silent><buffer><expr> S  defx#do_action('toggle_sort', 'Time')
      nnoremap <silent><buffer><expr> C
        \ defx#do_action('toggle_columns', 'indent:mark:filename:type:size:time')
    endfunction
    ]])
   end
  }