changeset 12804:6687b321fb91 v8.0.1279

patch 8.0.1279: initializing menus can be slow commit https://github.com/vim/vim/commit/040c1feb212568cf04265e59b26182f8b76057aa Author: Bram Moolenaar <Bram@vim.org> Date: Thu Nov 9 19:45:48 2017 +0100 patch 8.0.1279: initializing menus can be slow Problem: Initializing menus can be slow, especially when there are many keymaps, color schemes, etc. Solution: Do the globbing for runtime files lazlily. (Ken Takata)
author Christian Brabandt <cb@256bit.org>
date Thu, 09 Nov 2017 20:00:05 +0100
parents a9343f343028
children 4626b2fbab80
files runtime/doc/gui.txt runtime/menu.vim src/version.c
diffstat 3 files changed, 107 insertions(+), 61 deletions(-) [+]
line wrap: on
line diff
--- a/runtime/doc/gui.txt
+++ b/runtime/doc/gui.txt
@@ -1,4 +1,4 @@
-*gui.txt*       For Vim version 8.0.  Last change: 2017 Sep 23
+*gui.txt*       For Vim version 8.0.  Last change: 2017 Nov 09
 
 
 		  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -499,6 +499,17 @@ in the menu (which can take a bit of tim
 filetypes already present at startup, add: >
 	:let do_syntax_sel_menu = 1
 
+The following menuitems show all available color schemes, keymaps and compiler
+settings:
+	Edit > Color Scheme ~
+	Edit > Keymap ~
+	Tools > Set Compiler ~
+However, they can also take a bit of time to load, because they search all
+related files from the directories in 'runtimepath'.  Therefore they are
+loaded lazily (by the |CursorHold| event), or you can also load them manually.
+If you want to have all these items already present at startup, add: >
+	:let do_no_lazyload_menus = 1
+
 Note that the menu.vim is sourced when `:syntax on` or `:filetype on` is
 executed or after your .vimrc file is sourced.  This means that the 'encoding'
 option and the language of messages (`:language messages`) must be set before
--- a/runtime/menu.vim
+++ b/runtime/menu.vim
@@ -2,7 +2,7 @@
 " You can also use this as a start for your own set of menus.
 "
 " Maintainer:	Bram Moolenaar <Bram@vim.org>
-" Last Change:	2017 Mar 04
+" Last Change:	2017 Nov 09
 
 " Note that ":an" (short for ":anoremenu") is often used to make a menu work
 " in all modes and avoid side effects from mappings defined by the user.
@@ -159,7 +159,7 @@ nnoremenu 20.370 &Edit.Put\ &Before<Tab>
 inoremenu	 &Edit.Put\ &Before<Tab>[p	<C-O>[p
 nnoremenu 20.380 &Edit.Put\ &After<Tab>]p	]p
 inoremenu	 &Edit.Put\ &After<Tab>]p	<C-O>]p
-if has("win32") || has("win16")
+if has("win32")
   vnoremenu 20.390 &Edit.&Delete<Tab>x		x
 endif
 noremenu  <script> <silent> 20.400 &Edit.&Select\ All<Tab>ggVG	:<C-U>call <SID>SelectAll()<CR>
@@ -167,7 +167,7 @@ inoremenu <script> <silent> 20.400 &Edit
 cnoremenu <script> <silent> 20.400 &Edit.&Select\ All<Tab>ggVG	<C-U>call <SID>SelectAll()<CR>
 
 an 20.405	 &Edit.-SEP2-				<Nop>
-if has("win32")  || has("win16") || has("gui_gtk") || has("gui_kde") || has("gui_motif")
+if has("win32") || has("gui_gtk") || has("gui_kde") || has("gui_motif")
   an 20.410	 &Edit.&Find\.\.\.			:promptfind<CR>
   vunmenu	 &Edit.&Find\.\.\.
   vnoremenu <silent>	 &Edit.&Find\.\.\.		y:promptfind <C-R>=<SID>FixFText()<CR><CR>
@@ -339,51 +339,65 @@ fun! s:FileFormat()
   endif
 endfun
 
+let s:did_setup_color_schemes = 0
 
 " Setup the Edit.Color Scheme submenu
+func! s:SetupColorSchemes() abort
+  if s:did_setup_color_schemes
+    return
+  endif
+  let s:did_setup_color_schemes = 1
 
-" get NL separated string with file names
-let s:n = globpath(&runtimepath, "colors/*.vim")
+  let n = globpath(&runtimepath, "colors/*.vim", 1, 1)
 
-" split at NL, Ignore case for VMS and windows, sort on name
-let s:names = sort(map(split(s:n, "\n"), 'substitute(v:val, "\\c.*[/\\\\:\\]]\\([^/\\\\:]*\\)\\.vim", "\\1", "")'), 1)
+  " Ignore case for VMS and windows, sort on name
+  let names = sort(map(n, 'substitute(v:val, "\\c.*[/\\\\:\\]]\\([^/\\\\:]*\\)\\.vim", "\\1", "")'), 1)
 
-" define all the submenu entries
-let s:idx = 100
-for s:name in s:names
-  exe "an 20.450." . s:idx . ' &Edit.C&olor\ Scheme.' . s:name . " :colors " . s:name . "<CR>"
-  let s:idx = s:idx + 10
-endfor
-unlet s:name s:names s:n s:idx
+  " define all the submenu entries
+  let idx = 100
+  for name in names
+    exe "an 20.450." . idx . ' &Edit.C&olor\ Scheme.' . name . " :colors " . name . "<CR>"
+    let idx = idx + 10
+  endfor
+  silent! aunmenu &Edit.Show\ C&olor\ Schemes\ in\ Menu
+endfun
+if exists("do_no_lazyload_menus")
+  call s:SetupColorSchemes()
+else
+  an <silent> 20.450 &Edit.Show\ C&olor\ Schemes\ in\ Menu :call <SID>SetupColorSchemes()<CR>
+endif
 
 
 " Setup the Edit.Keymap submenu
 if has("keymap")
-  let s:n = globpath(&runtimepath, "keymap/*.vim")
-  if s:n != ""
-    let s:idx = 100
-    an 20.460.90 &Edit.&Keymap.None :set keymap=<CR>
-    while strlen(s:n) > 0
-      let s:i = stridx(s:n, "\n")
-      if s:i < 0
-	let s:name = s:n
-	let s:n = ""
-      else
-	let s:name = strpart(s:n, 0, s:i)
-	let s:n = strpart(s:n, s:i + 1, 19999)
-      endif
-      " Ignore case for VMS and windows
-      let s:name = substitute(s:name, '\c.*[/\\:\]]\([^/\\:_]*\)\(_[0-9a-zA-Z-]*\)\=\.vim', '\1', '')
-      exe "an 20.460." . s:idx . ' &Edit.&Keymap.' . s:name . " :set keymap=" . s:name . "<CR>"
-      unlet s:name
-      unlet s:i
-      let s:idx = s:idx + 10
-    endwhile
-    unlet s:idx
+  let s:did_setup_keymaps = 0
+
+  func! s:SetupKeymaps() abort
+    if s:did_setup_keymaps
+      return
+    endif
+    let s:did_setup_keymaps = 1
+
+    let n = globpath(&runtimepath, "keymap/*.vim", 1, 1)
+    if !empty(n)
+      let idx = 100
+      an 20.460.90 &Edit.&Keymap.None :set keymap=<CR>
+      for name in n
+	" Ignore case for VMS and windows
+	let name = substitute(name, '\c.*[/\\:\]]\([^/\\:_]*\)\(_[0-9a-zA-Z-]*\)\=\.vim', '\1', '')
+	exe "an 20.460." . idx . ' &Edit.&Keymap.' . name . " :set keymap=" . name . "<CR>"
+	let idx = idx + 10
+      endfor
+    endif
+    silent! aunmenu &Edit.Show\ &Keymaps\ in\ Menu
+  endfun
+  if exists("do_no_lazyload_menus")
+    call s:SetupKeymaps()
+  else
+    an <silent> 20.460 &Edit.Show\ &Keymaps\ in\ Menu :call <SID>SetupKeymaps()<CR>
   endif
-  unlet s:n
 endif
-if has("win32") || has("win16") || has("gui_motif") || has("gui_gtk") || has("gui_kde") || has("gui_photon") || has("gui_mac")
+if has("win32") || has("gui_motif") || has("gui_gtk") || has("gui_kde") || has("gui_photon") || has("gui_mac")
   an 20.470 &Edit.Select\ Fo&nt\.\.\.	:set guifont=*<CR>
 endif
 
@@ -441,10 +455,10 @@ if has("spell")
     endif
 
     let found = 0
-    let s = globpath(&rtp, "spell/*." . enc . ".spl")
-    if s != ""
+    let s = globpath(&runtimepath, "spell/*." . enc . ".spl", 1, 1)
+    if !empty(s)
       let n = 300
-      for f in split(s, "\n")
+      for f in s
 	let nm = substitute(f, '.*spell[/\\]\(..\)\.[^/\\]*\.spl', '\1', "")
 	if nm != "en" && nm !~ '/'
           let _nm = nm
@@ -574,27 +588,46 @@ func! s:XxdFind()
   endif
 endfun
 
+let s:did_setup_compilers = 0
+
 " Setup the Tools.Compiler submenu
-let s:n = globpath(&runtimepath, "compiler/*.vim")
-let s:idx = 100
-while strlen(s:n) > 0
-  let s:i = stridx(s:n, "\n")
-  if s:i < 0
-    let s:name = s:n
-    let s:n = ""
-  else
-    let s:name = strpart(s:n, 0, s:i)
-    let s:n = strpart(s:n, s:i + 1, 19999)
+func! s:SetupCompilers() abort
+  if s:did_setup_compilers
+    return
   endif
-  " Ignore case for VMS and windows
-  let s:name = substitute(s:name, '\c.*[/\\:\]]\([^/\\:]*\)\.vim', '\1', '')
-  exe "an 30.440." . s:idx . ' &Tools.Se&t\ Compiler.' . s:name . " :compiler " . s:name . "<CR>"
-  unlet s:name
-  unlet s:i
-  let s:idx = s:idx + 10
-endwhile
-unlet s:n
-unlet s:idx
+  let s:did_setup_compilers = 1
+
+  let n = globpath(&runtimepath, "compiler/*.vim", 1, 1)
+  let idx = 100
+  for name in n
+    " Ignore case for VMS and windows
+    let name = substitute(name, '\c.*[/\\:\]]\([^/\\:]*\)\.vim', '\1', '')
+    exe "an 30.440." . idx . ' &Tools.Se&t\ Compiler.' . name . " :compiler " . name . "<CR>"
+    let idx = idx + 10
+  endfor
+  silent! aunmenu &Tools.Show\ Compiler\ Se&ttings\ in\ Menu
+endfun
+if exists("do_no_lazyload_menus")
+  call s:SetupCompilers()
+else
+  an <silent> 30.440 &Tools.Show\ Compiler\ Se&ttings\ in\ Menu :call <SID>SetupCompilers()<CR>
+endif
+
+" Load ColorScheme, Compiler Setting and Keymap menus when idle.
+if !exists("do_no_lazyload_menus")
+  func! s:SetupLazyloadMenus()
+    call s:SetupColorSchemes()
+    call s:SetupCompilers()
+    if has("keymap")
+      call s:SetupKeymaps()
+    endif
+  endfunc
+  augroup SetupLazyloadMenus
+    au!
+    au CursorHold,CursorHoldI * call <SID>SetupLazyloadMenus() | au! SetupLazyloadMenus
+  augroup END
+endif
+
 
 if !exists("no_buffers_menu")
 
@@ -1095,7 +1128,7 @@ if (exists("did_load_filetypes") || exis
 if exists("do_syntax_sel_menu")
   runtime! synmenu.vim
 else
-  an 50.10 &Syntax.&Show\ File\ Types\ in\ Menu	:let do_syntax_sel_menu = 1<Bar>runtime! synmenu.vim<Bar>aunmenu &Syntax.&Show\ File\ Types\ in\ Menu<CR>
+  an <silent> 50.10 &Syntax.&Show\ File\ Types\ in\ Menu	:let do_syntax_sel_menu = 1<Bar>runtime! synmenu.vim<Bar>aunmenu &Syntax.&Show\ File\ Types\ in\ Menu<CR>
   an 50.195 &Syntax.-SEP1-		<Nop>
 endif
 
--- a/src/version.c
+++ b/src/version.c
@@ -762,6 +762,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    1279,
+/**/
     1278,
 /**/
     1277,