mirror of
https://github.com/preservim/nerdtree.git
synced 2025-11-08 11:23:48 -05:00
* Add an optional parameter to neredtree#exec to suppress all events. The value doesn't matter, but 1 is a good choice. Its presence is an indicator that tells NERDTree to tell Vim to ignore all events. I'm not yet sure if there needs to be an else section to that if block. It may be OK to allow all events to fire in the right situations. * Supress events in all intermediate nerdtree#exec calls. Finding all the right function calls is the key here. * Make ignoreAll a required parameter to nerdtree#exec(). * Put required ignoreAll argument (==0) in where it's now needed. * Ignore events when creating a new vertical split. * Ignore events when closing NERDTree. This may need to be reverted. * Remove debugging statment and commented-out code. * Wrap remaining buffer/window-switching commands in nerdtree#exec(). * Update version number. * Add a space between arguments in nerdtree#exec() calls.
366 lines
12 KiB
VimL
366 lines
12 KiB
VimL
" ============================================================================
|
|
" CLASS: Bookmark
|
|
"
|
|
" The Bookmark class serves two purposes:
|
|
" (1) It is the top-level prototype for new, concrete Bookmark objects.
|
|
" (2) It provides an interface for client code to query and manipulate the
|
|
" global list of Bookmark objects within the current Vim session.
|
|
" ============================================================================
|
|
|
|
|
|
let s:Bookmark = {}
|
|
let g:NERDTreeBookmark = s:Bookmark
|
|
|
|
" FUNCTION: Bookmark.activate(nerdtree) {{{1
|
|
function! s:Bookmark.activate(nerdtree, ...)
|
|
call self.open(a:nerdtree, a:0 ? a:1 : {})
|
|
endfunction
|
|
|
|
" FUNCTION: Bookmark.AddBookmark(name, path) {{{1
|
|
" Class method to add a new bookmark to the list, if a previous bookmark exists
|
|
" with the same name, just update the path for that bookmark
|
|
function! s:Bookmark.AddBookmark(name, path)
|
|
for i in s:Bookmark.Bookmarks()
|
|
if i.name ==# a:name
|
|
let i.path = a:path
|
|
return
|
|
endif
|
|
endfor
|
|
call add(s:Bookmark.Bookmarks(), s:Bookmark.New(a:name, a:path))
|
|
endfunction
|
|
|
|
" FUNCTION: Bookmark.Bookmarks() {{{1
|
|
" Class method to get all bookmarks. Lazily initializes the bookmarks global
|
|
" variable
|
|
function! s:Bookmark.Bookmarks()
|
|
if !exists("g:NERDTreeBookmarks")
|
|
let g:NERDTreeBookmarks = []
|
|
endif
|
|
return g:NERDTreeBookmarks
|
|
endfunction
|
|
|
|
" FUNCTION: Bookmark.BookmarkExistsFor(name) {{{1
|
|
" class method that returns 1 if a bookmark with the given name is found, 0
|
|
" otherwise
|
|
function! s:Bookmark.BookmarkExistsFor(name)
|
|
try
|
|
call s:Bookmark.BookmarkFor(a:name)
|
|
return 1
|
|
catch /^NERDTree.BookmarkNotFoundError/
|
|
return 0
|
|
endtry
|
|
endfunction
|
|
|
|
" FUNCTION: Bookmark.BookmarkFor(name) {{{1
|
|
" Class method that returns the Bookmark object having the specified name.
|
|
" Throws "NERDTree.BookmarkNotFoundError" if no Bookmark is found.
|
|
function! s:Bookmark.BookmarkFor(name)
|
|
let l:result = {}
|
|
for l:bookmark in s:Bookmark.Bookmarks()
|
|
if l:bookmark.name ==# a:name
|
|
let l:result = l:bookmark
|
|
break
|
|
endif
|
|
endfor
|
|
if empty(l:result)
|
|
throw 'NERDTree.BookmarkNotFoundError: "' . a:name . '" not found'
|
|
endif
|
|
return l:result
|
|
endfunction
|
|
|
|
" FUNCTION: Bookmark.BookmarkNames() {{{1
|
|
" Class method to return an array of all bookmark names
|
|
function! s:Bookmark.BookmarkNames()
|
|
let names = []
|
|
for i in s:Bookmark.Bookmarks()
|
|
call add(names, i.name)
|
|
endfor
|
|
return names
|
|
endfunction
|
|
|
|
" FUNCTION: Bookmark.CacheBookmarks(silent) {{{1
|
|
" Class method to read all bookmarks from the bookmarks file initialize
|
|
" bookmark objects for each one.
|
|
"
|
|
" Args:
|
|
" silent - dont echo an error msg if invalid bookmarks are found
|
|
function! s:Bookmark.CacheBookmarks(silent)
|
|
if filereadable(g:NERDTreeBookmarksFile)
|
|
let g:NERDTreeBookmarks = []
|
|
let g:NERDTreeInvalidBookmarks = []
|
|
let bookmarkStrings = readfile(g:NERDTreeBookmarksFile)
|
|
let invalidBookmarksFound = 0
|
|
for i in bookmarkStrings
|
|
|
|
"ignore blank lines
|
|
if i != ''
|
|
|
|
let name = substitute(i, '^\(.\{-}\) .*$', '\1', '')
|
|
let path = substitute(i, '^.\{-} \(.*\)$', '\1', '')
|
|
let path = fnamemodify(path, ':p')
|
|
|
|
try
|
|
let bookmark = s:Bookmark.New(name, g:NERDTreePath.New(path))
|
|
call add(g:NERDTreeBookmarks, bookmark)
|
|
catch /^NERDTree.InvalidArgumentsError/
|
|
call add(g:NERDTreeInvalidBookmarks, i)
|
|
let invalidBookmarksFound += 1
|
|
endtry
|
|
endif
|
|
endfor
|
|
if invalidBookmarksFound
|
|
call s:Bookmark.Write()
|
|
if !a:silent
|
|
call nerdtree#echo(invalidBookmarksFound . " invalid bookmarks were read. See :help NERDTreeInvalidBookmarks for info.")
|
|
endif
|
|
endif
|
|
endif
|
|
endfunction
|
|
|
|
" FUNCTION: Bookmark.CompareBookmarksByName(firstBookmark, secondBookmark) {{{1
|
|
" Class method that indicates the relative position of two bookmarks when
|
|
" placed in alphabetical order by name. Case-sensitivity is determined by an
|
|
" option. Supports the "s:Bookmark.SortBookmarksList()" method.
|
|
function! s:Bookmark.CompareBookmarksByName(firstBookmark, secondBookmark)
|
|
let l:result = 0
|
|
if g:NERDTreeBookmarksSort == 1
|
|
if a:firstBookmark.name <? a:secondBookmark.name
|
|
let l:result = -1
|
|
elseif a:firstBookmark.name >? a:secondBookmark.name
|
|
let l:result = 1
|
|
endif
|
|
elseif g:NERDTreeBookmarksSort == 2
|
|
if a:firstBookmark.name <# a:secondBookmark.name
|
|
let l:result = -1
|
|
elseif a:firstBookmark.name ># a:secondBookmark.name
|
|
let l:result = 1
|
|
endif
|
|
endif
|
|
return l:result
|
|
endfunction
|
|
|
|
" FUNCTION: Bookmark.ClearAll() {{{1
|
|
" Class method to delete all bookmarks.
|
|
function! s:Bookmark.ClearAll()
|
|
for i in s:Bookmark.Bookmarks()
|
|
call i.delete()
|
|
endfor
|
|
call s:Bookmark.Write()
|
|
endfunction
|
|
|
|
" FUNCTION: Bookmark.delete() {{{1
|
|
" Delete this bookmark. If the node for this bookmark is under the current
|
|
" root, then recache bookmarks for its Path object
|
|
function! s:Bookmark.delete()
|
|
call remove(s:Bookmark.Bookmarks(), index(s:Bookmark.Bookmarks(), self))
|
|
call s:Bookmark.Write()
|
|
endfunction
|
|
|
|
" FUNCTION: s:Edit() {{{1
|
|
" opens the NERDTreeBookmarks file for manual editing
|
|
function! s:Bookmark.Edit()
|
|
call nerdtree#exec("wincmd w", 1)
|
|
call nerdtree#exec("edit ".g:NERDTreeBookmarksFile, 1)
|
|
endfunction
|
|
|
|
" FUNCTION: Bookmark.getNode(nerdtree, searchFromAbsoluteRoot) {{{1
|
|
" Returns the tree node object associated with this Bookmark.
|
|
" Throws "NERDTree.BookmarkedNodeNotFoundError" if the node is not found.
|
|
"
|
|
" Args:
|
|
" searchFromAbsoluteRoot: boolean flag, search from the highest cached node
|
|
" if true and from the current tree root if false
|
|
function! s:Bookmark.getNode(nerdtree, searchFromAbsoluteRoot)
|
|
if a:searchFromAbsoluteRoot
|
|
let l:searchRoot = a:nerdtree.root.AbsoluteTreeRoot()
|
|
else
|
|
let l:searchRoot = a:nerdtree.root
|
|
endif
|
|
let l:targetNode = l:searchRoot.findNode(self.path)
|
|
if empty(l:targetNode)
|
|
throw 'NERDTree.BookmarkedNodeNotFoundError: node for bookmark "' . self.name . '" not found'
|
|
endif
|
|
return l:targetNode
|
|
endfunction
|
|
|
|
" FUNCTION: Bookmark.GetNodeForName(name, searchFromAbsoluteRoot, nerdtree) {{{1
|
|
" Class method that returns the tree node object for the Bookmark with the
|
|
" given name. Throws "NERDTree.BookmarkNotFoundError" if a Bookmark with the
|
|
" name does not exist. Throws "NERDTree.BookmarkedNodeNotFoundError" if a
|
|
" tree node for the named Bookmark could not be found.
|
|
function! s:Bookmark.GetNodeForName(name, searchFromAbsoluteRoot, nerdtree)
|
|
let l:bookmark = s:Bookmark.BookmarkFor(a:name)
|
|
return l:bookmark.getNode(a:nerdtree, a:searchFromAbsoluteRoot)
|
|
endfunction
|
|
|
|
" FUNCTION: Bookmark.GetSelected() {{{1
|
|
" returns the Bookmark the cursor is over, or {}
|
|
function! s:Bookmark.GetSelected()
|
|
let line = getline(".")
|
|
let name = substitute(line, '^>\(.\{-}\) .\+$', '\1', '')
|
|
if name != line
|
|
try
|
|
return s:Bookmark.BookmarkFor(name)
|
|
catch /^NERDTree.BookmarkNotFoundError/
|
|
return {}
|
|
endtry
|
|
endif
|
|
return {}
|
|
endfunction
|
|
|
|
" FUNCTION: Bookmark.InvalidBookmarks() {{{1
|
|
" Class method to get all invalid bookmark strings read from the bookmarks
|
|
" file
|
|
function! s:Bookmark.InvalidBookmarks()
|
|
if !exists("g:NERDTreeInvalidBookmarks")
|
|
let g:NERDTreeInvalidBookmarks = []
|
|
endif
|
|
return g:NERDTreeInvalidBookmarks
|
|
endfunction
|
|
|
|
" FUNCTION: Bookmark.mustExist() {{{1
|
|
function! s:Bookmark.mustExist()
|
|
if !self.path.exists()
|
|
call s:Bookmark.CacheBookmarks(1)
|
|
throw "NERDTree.BookmarkPointsToInvalidLocationError: the bookmark \"".
|
|
\ self.name ."\" points to a non existing location: \"". self.path.str()
|
|
endif
|
|
endfunction
|
|
|
|
" FUNCTION: Bookmark.New(name, path) {{{1
|
|
" Create a new bookmark object with the given name and path object
|
|
function! s:Bookmark.New(name, path)
|
|
if a:name =~# ' '
|
|
throw "NERDTree.IllegalBookmarkNameError: illegal name:" . a:name
|
|
endif
|
|
|
|
let newBookmark = copy(self)
|
|
let newBookmark.name = a:name
|
|
let newBookmark.path = a:path
|
|
return newBookmark
|
|
endfunction
|
|
|
|
" FUNCTION: Bookmark.open(nerdtree, [options]) {{{1
|
|
"Args:
|
|
"
|
|
"nerdtree: the tree to load open the bookmark in
|
|
"
|
|
"A dictionary containing the following keys (all optional):
|
|
" 'where': Specifies whether the node should be opened in new split/tab or in
|
|
" the previous window. Can be either 'v' (vertical split), 'h'
|
|
" (horizontal split), 't' (new tab) or 'p' (previous window).
|
|
" 'reuse': if a window is displaying the file then jump the cursor there
|
|
" 'keepopen': dont close the tree window
|
|
" 'stay': open the file, but keep the cursor in the tree win
|
|
"
|
|
function! s:Bookmark.open(nerdtree, ...)
|
|
let opts = a:0 ? a:1 : {}
|
|
|
|
if nerdtree#and(g:NERDTreeQuitOnOpen,2)
|
|
call a:nerdtree.ui.toggleShowBookmarks()
|
|
endif
|
|
|
|
if self.path.isDirectory && !has_key(opts, 'where')
|
|
call self.toRoot(a:nerdtree)
|
|
else
|
|
let opener = g:NERDTreeOpener.New(self.path, opts)
|
|
call opener.open(self)
|
|
endif
|
|
endfunction
|
|
|
|
" FUNCTION: Bookmark.openInNewTab(options) {{{1
|
|
" Create a new bookmark object with the given name and path object
|
|
function! s:Bookmark.openInNewTab(options)
|
|
call nerdtree#deprecated('Bookmark.openInNewTab', 'is deprecated, use open() instead')
|
|
call self.open(a:options)
|
|
endfunction
|
|
|
|
" FUNCTION: Bookmark.setPath(path) {{{1
|
|
" makes this bookmark point to the given path
|
|
function! s:Bookmark.setPath(path)
|
|
let self.path = a:path
|
|
endfunction
|
|
|
|
" FUNCTION: Bookmark.SortBookmarksList() {{{1
|
|
" Class method that sorts the global list of bookmarks alphabetically by name.
|
|
" Note that case-sensitivity is determined by a user option.
|
|
function! s:Bookmark.SortBookmarksList()
|
|
call sort(s:Bookmark.Bookmarks(), s:Bookmark.CompareBookmarksByName, s:Bookmark)
|
|
endfunction
|
|
|
|
" FUNCTION: Bookmark.str() {{{1
|
|
" Get the string that should be rendered in the view for this bookmark
|
|
function! s:Bookmark.str()
|
|
let pathStrMaxLen = winwidth(g:NERDTree.GetWinNum()) - 4 - strdisplaywidth(self.name)
|
|
if &nu
|
|
let pathStrMaxLen = pathStrMaxLen - &numberwidth
|
|
endif
|
|
|
|
let pathStr = self.path.str({'format': 'UI'})
|
|
if strdisplaywidth(pathStr) > pathStrMaxLen
|
|
while strdisplaywidth(pathStr) > pathStrMaxLen && strchars(pathStr) > 0
|
|
let pathStr = substitute(pathStr, '^.', '', '')
|
|
endwhile
|
|
let pathStr = '<' . pathStr
|
|
endif
|
|
return '>' . self.name . ' ' . pathStr
|
|
endfunction
|
|
|
|
" FUNCTION: Bookmark.toRoot(nerdtree) {{{1
|
|
" Set the root of the given NERDTree to the node for this Bookmark. If a node
|
|
" for this Bookmark does not exist, a new one is initialized.
|
|
function! s:Bookmark.toRoot(nerdtree)
|
|
if self.validate()
|
|
try
|
|
let l:targetNode = self.getNode(a:nerdtree, 1)
|
|
call l:targetNode.closeChildren()
|
|
catch /^NERDTree.BookmarkedNodeNotFoundError/
|
|
let l:targetNode = g:NERDTreeFileNode.New(s:Bookmark.BookmarkFor(self.name).path, a:nerdtree)
|
|
endtry
|
|
call a:nerdtree.changeRoot(l:targetNode)
|
|
endif
|
|
endfunction
|
|
|
|
" FUNCTION: Bookmark.ToRoot(name, nerdtree) {{{1
|
|
" Class method that makes the Bookmark with the given name the root of
|
|
" specified NERDTree.
|
|
function! s:Bookmark.ToRoot(name, nerdtree)
|
|
let l:bookmark = s:Bookmark.BookmarkFor(a:name)
|
|
call l:bookmark.toRoot(a:nerdtree)
|
|
endfunction
|
|
|
|
" FUNCTION: Bookmark.validate() {{{1
|
|
function! s:Bookmark.validate()
|
|
if self.path.exists()
|
|
return 1
|
|
else
|
|
call s:Bookmark.CacheBookmarks(1)
|
|
call nerdtree#echo(self.name . "now points to an invalid location. See :help NERDTreeInvalidBookmarks for info.")
|
|
return 0
|
|
endif
|
|
endfunction
|
|
|
|
" FUNCTION: Bookmark.Write() {{{1
|
|
" Class method to write all bookmarks to the bookmarks file
|
|
function! s:Bookmark.Write()
|
|
let bookmarkStrings = []
|
|
for i in s:Bookmark.Bookmarks()
|
|
call add(bookmarkStrings, i.name . ' ' . fnamemodify(i.path.str(), ':~'))
|
|
endfor
|
|
|
|
"add a blank line before the invalid ones
|
|
call add(bookmarkStrings, "")
|
|
|
|
for j in s:Bookmark.InvalidBookmarks()
|
|
call add(bookmarkStrings, j)
|
|
endfor
|
|
|
|
try
|
|
call writefile(bookmarkStrings, g:NERDTreeBookmarksFile)
|
|
catch
|
|
call nerdtree#echoError("Failed to write bookmarks file. Make sure g:NERDTreeBookmarksFile points to a valid location.")
|
|
endtry
|
|
endfunction
|
|
|
|
" vim: set sw=4 sts=4 et fdm=marker:
|