mirror of
https://github.com/preservim/nerdtree.git
synced 2025-11-08 11:23:48 -05:00
* Extract the menu action prompts to a function * Add a NERDTreeMinimalMenu configuration option If this option is set, Vim’s command line displays a single-line version of the menu: Which action? (a*/m/d/r/o/q/c/l): Pressing ‘a’ will call the ‘add child node’ menu item as that is its shortcut. The * denotes the position of the currently selected menu item which can be changed with NERDTreeMenuDown and Up in the usual way. The user may wish to set these to <left>, <right> or h, l if they prefer. * Minimise the text once a menu item is chosen If NERDTreeMinimalMenu is set, then echo a single line prompt after the menu item is chosen. This reduces noise for users who are already familiar with how the menu works and prevents Vim scrolling down to accommodate the menu text. If the directory is non-empty we display ‘Delete directory?’ instead of ‘Delete?’ and the user must still type ‘yes’ to confirm, rather than just pressing ‘y’. * Document the new NERDTreeMinimalMenu feature * Tweak the format for the minimal menu prompt As per @PhilRunninger’s suggestions: - The menu now shows the ‘j/k/enter’ help text - The first word of the selected item is shown* - Use commas between menu items so that it’s visually distinct from the ‘j/k/enter’ text * I tried displaying the full menuItem text, but this can be quite long, e.g. > (o)pen the current node with system editor This causes the menu to jump around a lot. We could add another minimal versions of these, but I think the first word seems ok for now.
207 lines
5.9 KiB
VimL
207 lines
5.9 KiB
VimL
"CLASS: MenuController
|
|
"============================================================
|
|
let s:MenuController = {}
|
|
let g:NERDTreeMenuController = s:MenuController
|
|
|
|
"FUNCTION: MenuController.New(menuItems) {{{1
|
|
"create a new menu controller that operates on the given menu items
|
|
function! s:MenuController.New(menuItems)
|
|
let newMenuController = copy(self)
|
|
if a:menuItems[0].isSeparator()
|
|
let newMenuController.menuItems = a:menuItems[1:-1]
|
|
else
|
|
let newMenuController.menuItems = a:menuItems
|
|
endif
|
|
return newMenuController
|
|
endfunction
|
|
|
|
" FUNCTION: s:MenuController.isMinimal() {{{1
|
|
function! s:MenuController.isMinimal()
|
|
return g:NERDTreeMinimalMenu
|
|
endfunction
|
|
|
|
" FUNCTION: MenuController.showMenu() {{{1
|
|
" Enter the main loop of the NERDTree menu, prompting the user to select
|
|
" a menu item.
|
|
function! s:MenuController.showMenu()
|
|
call self._saveOptions()
|
|
|
|
try
|
|
let self.selection = 0
|
|
let l:done = 0
|
|
|
|
while !l:done
|
|
redraw!
|
|
call self._echoPrompt()
|
|
|
|
let l:key = nr2char(getchar())
|
|
let l:done = self._handleKeypress(l:key)
|
|
endwhile
|
|
finally
|
|
call self._restoreOptions()
|
|
|
|
" Redraw when "Ctrl-C" or "Esc" is received.
|
|
if !l:done || self.selection == -1
|
|
redraw!
|
|
endif
|
|
endtry
|
|
|
|
if self.selection != -1
|
|
let l:m = self._current()
|
|
call l:m.execute()
|
|
endif
|
|
endfunction
|
|
|
|
"FUNCTION: MenuController._echoPrompt() {{{1
|
|
function! s:MenuController._echoPrompt()
|
|
let navHelp = "Use " . g:NERDTreeMenuDown . "/" . g:NERDTreeMenuUp . "/enter"
|
|
|
|
if self.isMinimal()
|
|
let selection = self.menuItems[self.selection].text
|
|
|
|
let shortcuts = map(copy(self.menuItems), "v:val['shortcut']")
|
|
let shortcuts[self.selection] = " " . split(selection)[0] . " "
|
|
|
|
echo "Menu: [" . join(shortcuts, ",") . "] (" . navHelp . " or shortcut): "
|
|
else
|
|
echo "NERDTree Menu. " . navHelp . " . or the shortcuts indicated"
|
|
echo "========================================================="
|
|
|
|
for i in range(0, len(self.menuItems)-1)
|
|
if self.selection == i
|
|
echo "> " . self.menuItems[i].text
|
|
else
|
|
echo " " . self.menuItems[i].text
|
|
endif
|
|
endfor
|
|
endif
|
|
endfunction
|
|
|
|
"FUNCTION: MenuController._current(key) {{{1
|
|
"get the MenuItem that is currently selected
|
|
function! s:MenuController._current()
|
|
return self.menuItems[self.selection]
|
|
endfunction
|
|
|
|
"FUNCTION: MenuController._handleKeypress(key) {{{1
|
|
"change the selection (if appropriate) and return 1 if the user has made
|
|
"their choice, 0 otherwise
|
|
function! s:MenuController._handleKeypress(key)
|
|
if a:key == g:NERDTreeMenuDown
|
|
call self._cursorDown()
|
|
elseif a:key == g:NERDTreeMenuUp
|
|
call self._cursorUp()
|
|
elseif a:key == nr2char(27) "escape
|
|
let self.selection = -1
|
|
return 1
|
|
elseif a:key == "\r" || a:key == "\n" "enter and ctrl-j
|
|
return 1
|
|
else
|
|
let index = self._nextIndexFor(a:key)
|
|
if index != -1
|
|
let self.selection = index
|
|
if len(self._allIndexesFor(a:key)) == 1
|
|
return 1
|
|
endif
|
|
endif
|
|
endif
|
|
|
|
return 0
|
|
endfunction
|
|
|
|
"FUNCTION: MenuController._allIndexesFor(shortcut) {{{1
|
|
"get indexes to all menu items with the given shortcut
|
|
function! s:MenuController._allIndexesFor(shortcut)
|
|
let toReturn = []
|
|
|
|
for i in range(0, len(self.menuItems)-1)
|
|
if self.menuItems[i].shortcut == a:shortcut
|
|
call add(toReturn, i)
|
|
endif
|
|
endfor
|
|
|
|
return toReturn
|
|
endfunction
|
|
|
|
"FUNCTION: MenuController._nextIndexFor(shortcut) {{{1
|
|
"get the index to the next menu item with the given shortcut, starts from the
|
|
"current cursor location and wraps around to the top again if need be
|
|
function! s:MenuController._nextIndexFor(shortcut)
|
|
for i in range(self.selection+1, len(self.menuItems)-1)
|
|
if self.menuItems[i].shortcut == a:shortcut
|
|
return i
|
|
endif
|
|
endfor
|
|
|
|
for i in range(0, self.selection)
|
|
if self.menuItems[i].shortcut == a:shortcut
|
|
return i
|
|
endif
|
|
endfor
|
|
|
|
return -1
|
|
endfunction
|
|
|
|
"FUNCTION: MenuController._setCmdheight() {{{1
|
|
"sets &cmdheight to whatever is needed to display the menu
|
|
function! s:MenuController._setCmdheight()
|
|
if self.isMinimal()
|
|
let &cmdheight = 1
|
|
else
|
|
let &cmdheight = len(self.menuItems) + 3
|
|
endif
|
|
endfunction
|
|
|
|
"FUNCTION: MenuController._saveOptions() {{{1
|
|
"set any vim options that are required to make the menu work (saving their old
|
|
"values)
|
|
function! s:MenuController._saveOptions()
|
|
let self._oldLazyredraw = &lazyredraw
|
|
let self._oldCmdheight = &cmdheight
|
|
set nolazyredraw
|
|
call self._setCmdheight()
|
|
endfunction
|
|
|
|
"FUNCTION: MenuController._restoreOptions() {{{1
|
|
"restore the options we saved in _saveOptions()
|
|
function! s:MenuController._restoreOptions()
|
|
let &cmdheight = self._oldCmdheight
|
|
let &lazyredraw = self._oldLazyredraw
|
|
endfunction
|
|
|
|
"FUNCTION: MenuController._cursorDown() {{{1
|
|
"move the cursor to the next menu item, skipping separators
|
|
function! s:MenuController._cursorDown()
|
|
let done = 0
|
|
while !done
|
|
if self.selection < len(self.menuItems)-1
|
|
let self.selection += 1
|
|
else
|
|
let self.selection = 0
|
|
endif
|
|
|
|
if !self._current().isSeparator()
|
|
let done = 1
|
|
endif
|
|
endwhile
|
|
endfunction
|
|
|
|
"FUNCTION: MenuController._cursorUp() {{{1
|
|
"move the cursor to the previous menu item, skipping separators
|
|
function! s:MenuController._cursorUp()
|
|
let done = 0
|
|
while !done
|
|
if self.selection > 0
|
|
let self.selection -= 1
|
|
else
|
|
let self.selection = len(self.menuItems)-1
|
|
endif
|
|
|
|
if !self._current().isSeparator()
|
|
let done = 1
|
|
endif
|
|
endwhile
|
|
endfunction
|
|
|
|
" vim: set sw=4 sts=4 et fdm=marker:
|