1
0
Fork 0
mirror of synced 2024-12-22 06:51:06 -05:00

Updated vim plugins

This commit is contained in:
amix 2017-07-06 14:57:35 +02:00
parent 48a2c325c3
commit 391f8b5c06
82 changed files with 2016 additions and 2757 deletions

View file

@ -569,9 +569,14 @@ endf
fu! s:MatchedItems(items, pat, limit)
let exc = exists('s:crfilerel') ? s:crfilerel : ''
let items = s:narrowable() ? s:matched + s:mdata[3] : a:items
if s:matcher != {}
let matcher = s:getextvar('matcher')
if empty(matcher) || type(matcher) != 4 || !has_key(matcher, 'match')
unlet matcher
let matcher = s:matcher
en
if matcher != {}
let argms =
\ has_key(s:matcher, 'arg_type') && s:matcher['arg_type'] == 'dict' ? [{
\ has_key(matcher, 'arg_type') && matcher['arg_type'] == 'dict' ? [{
\ 'items': items,
\ 'str': a:pat,
\ 'limit': a:limit,
@ -580,7 +585,7 @@ fu! s:MatchedItems(items, pat, limit)
\ 'crfile': exc,
\ 'regex': s:regexp,
\ }] : [items, a:pat, a:limit, s:mmode(), s:ispath, exc, s:regexp]
let lines = call(s:matcher['match'], argms, s:matcher)
let lines = call(matcher['match'], argms, matcher)
el
let lines = s:MatchIt(items, a:pat, a:limit, exc)
en
@ -1196,7 +1201,7 @@ fu! s:AcceptSelection(action)
let type = exttype == 'dict' ? exttype : 'list'
en
en
let actargs = type == 'dict' ? [{ 'action': md, 'line': line, 'icr': icr }]
let actargs = type == 'dict' ? [{ 'action': md, 'line': line, 'icr': icr, 'input': str}]
\ : [md, line]
cal call(actfunc, actargs)
endf
@ -1873,6 +1878,11 @@ fu! s:highlight(pat, grp)
en
cal matchadd('CtrlPLinePre', '^>')
elseif !empty(a:pat) && s:regexp &&
\ exists('g:ctrlp_regex_always_higlight') &&
\ g:ctrlp_regex_always_higlight
let pat = substitute(a:pat, '\\\@<!\^', '^> \\zs', 'g')
cal matchadd(a:grp, ( s:martcs == '' ? '\c' : '\C').pat)
en
endf
@ -2494,7 +2504,9 @@ endf
fu! s:getextvar(key)
if s:itemtype >= len(s:coretypes) && len(g:ctrlp_ext_vars) > 0
let vars = g:ctrlp_ext_vars[s:itemtype - len(s:coretypes)]
retu has_key(vars, a:key) ? vars[a:key] : -1
if has_key(vars, a:key)
retu vars[a:key]
en
en
retu get(g:, 'ctrlp_' . s:matchtype . '_' . a:key, -1)
endf

View file

@ -139,7 +139,7 @@ fu! s:exectags(cmd)
endf
fu! s:exectagsonfile(fname, ftype)
let [ags, ft] = ['-f - --sort=no --excmd=pattern --fields=nKs --extra= ', a:ftype]
let [ags, ft] = ['-f - --sort=no --excmd=pattern --fields=nKs --extra= --file-scope=yes ', a:ftype]
if type(s:types[ft]) == 1
let ags .= s:types[ft]
let bin = s:bin

View file

@ -13,6 +13,7 @@ let g:loaded_ctrlp_line = 1
cal add(g:ctrlp_ext_vars, {
\ 'init': 'ctrlp#line#init(s:crbufnr)',
\ 'accept': 'ctrlp#line#accept',
\ 'act_farg' : 'dict',
\ 'lname': 'lines',
\ 'sname': 'lns',
\ 'type': 'tabe',
@ -50,11 +51,17 @@ fu! ctrlp#line#init(bufnr)
retu lines
endf
fu! ctrlp#line#accept(mode, str)
let info = matchlist(a:str, '\t|[^|]\+|\(\d\+\):\(\d\+\)|$')
fu! ctrlp#line#accept(dict)
let mode = a:dict['action']
let str = a:dict['line']
let input = a:dict['input']
let info = matchlist(str, '\t|[^|]\+|\(\d\+\):\(\d\+\)|$')
let bufnr = str2nr(get(info, 1))
if bufnr
cal ctrlp#acceptfile(a:mode, bufnr, get(info, 2))
cal ctrlp#acceptfile(mode, bufnr, get(info, 2))
let @/ = input
call search(input, 'c')
call histadd("search", input)
en
endf

View file

@ -1,6 +1,6 @@
The MIT License (MIT)
Copyright (c) 2013-2016 itchyny
Copyright (c) 2013-2017 itchyny
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

File diff suppressed because it is too large Load diff

View file

@ -4,7 +4,7 @@ Version: 0.1
Author: itchyny (https://github.com/itchyny)
License: MIT License
Repository: https://github.com/itchyny/lightline.vim
Last Change: 2016/10/24 08:12:28.
Last Change: 2017/05/28 01:07:02.
CONTENTS *lightline-contents*
@ -29,39 +29,40 @@ The *lightline* plugin is a light and configurable statusline/tabline for Vim.
SPIRIT *lightline-spirit*
Minimalism
The core script is very small.
The core script is very small to achive enough functions as a
statusline plugin.
Configurability
You can create your own component and easily add to the
statusline/tabline.
You can create your own component and easily add to the statusline
and the tabline.
Orthogonality
Any plugin should not change the settings of another plugin.
Such plugin-crossing settings should be written by users in
.vimrc.
The plugin does not rely on the implementation of other plugins.
Such plugin crossing settings should be configured by users.
You might find this plugin is not so useful by default. This plugin
does not provide the branch information, which is a very basic
component in existing plugins. The reason is that branch component is
one of plugin-crossing settings so users should write the settings
using the APIs of the both plugins. Hospitality makes a plugin messy.
Good APIs keep a plugin clean.
You find this plugin does not integrate with other plugins by default.
This plugin does not provide branch information, which is a basic
component in existing statusline plugins. It is a design of
lightline.vim that such plugin crossing configuration should be
written by users. Once a plugin starts to integrate with some famous
plugins, it should be kept updated to follow the changes of the
plugins and should accept integration requests with new plugins.
Instead, lightline.vim is designed very carefully so that users can
easily integrate with other plugins. Good APIs keep a plugin clean.
------------------------------------------------------------------------------
OPTIONS *lightline-option*
g:lightline *g:lightline*
All the options are stored into this global variable.
All the configurations are stored in this global variable.
g:lightline.active *g:lightline.active*
g:lightline.inactive *g:lightline.inactive*
g:lightline.tabline *g:lightline.tabline*
Dictionaries to specify the statusline/tabline components.
The components are gathered from either |g:lightline.component|,
|g:lightline.component_function| or
|g:lightline.component_expand|.
Dictionaries to store the statusline/tabline components.
Note that right groups of components are stored from right to
left. The default values are:
left.
The default values are:
>
let g:lightline.active = {
\ 'left': [ [ 'mode', 'paste' ],
@ -78,10 +79,7 @@ OPTIONS *lightline-option*
\ 'right': [ [ 'close' ] ] }
<
g:lightline.tab *g:lightline.tab*
Dictionaries to specify the components in each tabs.
The components are gathered from either
|g:lightline.tab_component| or
|g:lightline.tab_component_function|.
A dictionary to store the tab components in each tabs.
The default values are:
>
let g:lightline.tab = {
@ -89,7 +87,7 @@ OPTIONS *lightline-option*
\ 'inactive': [ 'tabnum', 'filename', 'modified' ] }
<
g:lightline.component *g:lightline.component*
Dictionary for statusline/tabline components.
A dictionary for statusline/tabline components.
The default value is:
>
let g:lightline.component = {
@ -116,11 +114,11 @@ OPTIONS *lightline-option*
<
g:lightline.component_visible_condition
*g:lightline.component_visible_condition*
Dictionary to store the visible condition of the components.
Each expression should correspond to the condition each
component is not empty. This configuration is used to control
the visibility of the subseparators. You cannot use this
configuration to control the visibility of the components.
A dictionary to store the visible condition of the components.
Note that this configuration is used to control the visibility
of the subseparators, not to control the visibility of the
components themselves. Each expression should correspond to
the condition on which each component is not empty.
The default value is:
>
let g:lightline.component_visible_condition = {
@ -129,52 +127,47 @@ OPTIONS *lightline-option*
\ 'paste': '&paste',
\ 'spell': '&spell' }
<
Users are recommended to set this option together with the
component itself.
g:lightline.component_function *g:lightline.component_function*
Another dictionary for components. This is more convenient
because the user does not have to set both component and
component_visible_condition. If a component set to both component and
component_function, the setting of component_function has priority.
A dictionary to store the function components.
This is useful to write a complex component configuration and
to integrate with other plugins. If a component set in both
component and component_function, the configuration of
component_function has priority.
The default value is:
>
let g:lightline.component_function = {}
<
For example, if you want a component for read-only mark, which
disappears in help windows:
For example, if you want to display the name of the git branch,
install |vim-fugitive| plugin and then configure as:
>
let g:lightline = {
\ 'active': {
\ 'left': [ [ 'mode', 'paste' ],
\ [ 'myreadonly', 'filename', 'modified' ] ],
\ [ 'gitbranch', 'readonly', 'filename', 'modified' ] ]
\ },
\ 'component_function': {
\ 'myreadonly': 'LightlineReadonly'
\ 'gitbranch': 'fugitive#head'
\ },
\ }
function! LightlineReadonly()
return &ft !~? 'help' && &readonly ? 'RO' : ''
endfunction
<
g:lightline.component_function_visible_condition
*g:lightline.component_function_visible_condition*
Dictionary to store the visible conditions of the function
A dictionary to store the visible conditions of the function
components. Each expression should correspond to the condition
each component is not empty. This configuration is used to
control the visibility of the subseparators. You can use this
configuration to reduce the number of function calls for
function components by setting the value 1 (to tell lightline
performance improvement by setting the value 1 (to tell lightline
that the component is always visible).
The default value is:
>
let g:lightline.component_function_visible_condition = {}
<
g:lightline.component_expand *g:lightline.component_expand*
Another dictionary for components. You can create a component
which has a special color. For example, error components or
warning components. The functions should return one of:
A dictionary to store expanding components. You can create
warning and critical components. The values should be the name
of functions should return either one of:
+ a string
+ an array of three elements:
[[ left ], [ middle ], [ right ]]
@ -281,7 +274,6 @@ OPTIONS *lightline-option*
\ 'tabline': 1
\ }
<
==============================================================================
FONT *lightline-font*
You can use the patched font you used for |vim-powerline| and |powerline|.

View file

@ -1,4 +1,13 @@
Next
- Update doc with already existing mapping variables (asnr) #699
- Fix the broken g:NERDTreeBookmarksSort setting (lifecrisis) #696
- Correct NERDTreeIgnore pattern in doc (cntoplolicon) #648
- Remove empty segments when splitting path (sooth-sayer) #574
- Suppress autocmds less agressively (wincent) #578 #691
- Add an Issues template to ask for more info initially.
- Fix markdown headers in readme (josephfrazier) #676
- Don't touch @o and @h registers when rendering
- Fix bug with files and directories with dollar signs (alegen) #649
- Reuse/reopen existing window trees where possible #244
- Remove NERDTree.previousBuf()
- Change color of arrow (Leeiio) #630

View file

@ -52,11 +52,6 @@ function! nerdtree#completeBookmarks(A,L,P)
return filter(g:NERDTreeBookmark.BookmarkNames(), 'v:val =~# "^' . a:A . '"')
endfunction
"FUNCTION: nerdtree#compareBookmarks(dir) {{{2
function! nerdtree#compareBookmarks(first, second)
return a:first.compareTo(a:second)
endfunction
"FUNCTION: nerdtree#compareNodes(dir) {{{2
function! nerdtree#compareNodes(n1, n2)
return a:n1.path.compareTo(a:n2.path)
@ -64,9 +59,33 @@ endfunction
"FUNCTION: nerdtree#compareNodesBySortKey(n1, n2) {{{2
function! nerdtree#compareNodesBySortKey(n1, n2)
if a:n1.path.getSortKey() <# a:n2.path.getSortKey()
let sortKey1 = a:n1.path.getSortKey()
let sortKey2 = a:n2.path.getSortKey()
let i = 0
while i < min([len(sortKey1), len(sortKey2)])
" Compare chunks upto common length.
" If chunks have different type, the one which has
" integer type is the lesser.
if type(sortKey1[i]) == type(sortKey2[i])
if sortKey1[i] <# sortKey2[i]
return - 1
elseif sortKey1[i] ># sortKey2[i]
return 1
endif
elseif sortKey1[i] == type(0)
return -1
elseif sortKey2[i] == type(0)
return 1
endif
let i = i + 1
endwhile
" Keys are identical upto common length.
" The key which has smaller chunks is the lesser one.
if len(sortKey1) < len(sortKey2)
return -1
elseif a:n1.path.getSortKey() ># a:n2.path.getSortKey()
elseif len(sortKey1) > len(sortKey2)
return 1
else
return 0

View file

@ -7,7 +7,7 @@ let g:loaded_nerdtree_ui_glue_autoload = 1
function! nerdtree#ui_glue#createDefaultBindings()
let s = '<SNR>' . s:SID() . '_'
call NERDTreeAddKeyMap({ 'key': '<MiddleRelease>', 'scope': "all", 'callback': s."handleMiddleMouse" })
call NERDTreeAddKeyMap({ 'key': '<MiddleMouse>', 'scope': 'all', 'callback': s . 'handleMiddleMouse' })
call NERDTreeAddKeyMap({ 'key': '<LeftRelease>', 'scope': "all", 'callback': s."handleLeftClick" })
call NERDTreeAddKeyMap({ 'key': '<2-LeftMouse>', 'scope': "DirNode", 'callback': s."activateDirNode" })
call NERDTreeAddKeyMap({ 'key': '<2-LeftMouse>', 'scope': "FileNode", 'callback': s."activateFileNode" })
@ -336,16 +336,22 @@ endfunction
" FUNCTION: s:handleMiddleMouse() {{{1
function! s:handleMiddleMouse()
let curNode = g:NERDTreeFileNode.GetSelected()
if curNode ==# {}
call nerdtree#echo("Put the cursor on a node first" )
" A middle mouse click does not automatically position the cursor as one
" would expect. Forcing the execution of a regular left mouse click here
" fixes this problem.
execute "normal! \<LeftMouse>"
let l:currentNode = g:NERDTreeFileNode.GetSelected()
if empty(l:currentNode)
call nerdtree#echoError('use the pointer to select a node')
return
endif
if curNode.path.isDirectory
call nerdtree#openExplorer(curNode)
if l:currentNode.path.isDirectory
call l:currentNode.openExplorer()
else
call curNode.open({'where': 'h'})
call l:currentNode.open({'where': 'h'})
endif
endfunction
@ -441,21 +447,19 @@ function! s:jumpToSibling(currentNode, forward)
endfunction
" FUNCTION: nerdtree#ui_glue#openBookmark(name) {{{1
" put the cursor on the given bookmark and, if its a file, open it
" Open the Bookmark that has the specified name. This function provides the
" implementation for the ":OpenBookmark" command.
function! nerdtree#ui_glue#openBookmark(name)
try
let targetNode = g:NERDTreeBookmark.GetNodeForName(a:name, 0, b:NERDTree)
call targetNode.putCursorHere(0, 1)
redraw!
catch /^NERDTree.BookmarkedNodeNotFoundError/
call nerdtree#echo("note - target node is not cached")
let bookmark = g:NERDTreeBookmark.BookmarkFor(a:name)
let targetNode = g:NERDTreeFileNode.New(bookmark.path, b:NERDTree)
let l:bookmark = g:NERDTreeBookmark.BookmarkFor(a:name)
catch /^NERDTree.BookmarkNotFoundError/
call nerdtree#echoError('bookmark "' . a:name . '" not found')
return
endtry
if targetNode.path.isDirectory
call targetNode.openExplorer()
if l:bookmark.path.isDirectory
call l:bookmark.open(b:NERDTree)
else
call targetNode.open({'where': 'p'})
call l:bookmark.open(b:NERDTree, {'where': 'p'})
endif
endfunction

View file

@ -117,6 +117,10 @@ The following features and functionality are provided by the NERD tree:
again. If no NERD tree exists for this tab then this command acts the
same as the |:NERDTree| command.
:NERDTreeFocus *:NERDTreeFocus*
Opens (or reopens) the NERD Tree if it is not currently visible;
otherwise, the cursor is moved to the already-open NERD Tree.
:NERDTreeMirror *:NERDTreeMirror*
Shares an existing NERD tree, from another tab, in the current tab.
Changes made to one tree are reflected in both as they are actually the
@ -158,7 +162,7 @@ click bookmarks or use the |NERDTree-o| mapping to activate them. See also,
------------------------------------------------------------------------------
2.2.2. Bookmark commands *NERDTreeBookmarkCommands*
Note that the following commands are only available in the NERD tree buffer.
Note: The following commands are only available within the NERDTree buffer.
:Bookmark [<name>]
Bookmark the current node as <name>. If there is already a <name>
@ -178,10 +182,11 @@ Note that the following commands are only available in the NERD tree buffer.
(i.e. directory nodes above it will be opened) and the cursor will be
placed on it.
:OpenBookmark <bookmark>
<bookmark> must point to a file. The file is opened as though |NERDTree-o|
was applied. If the node is cached under the current root then it will be
revealed and the cursor will be placed on it.
:OpenBookmark <name>
The Bookmark named <name> is opened as if |NERDTree-o| was applied to
its entry in the Bookmark table. If the Bookmark points to a directory,
it is made the new root of the current NERDTree. If the Bookmark points
to a file, that file is opened for editing in another window.
:ClearBookmarks [<bookmarks>]
Remove all the given bookmarks. If no bookmarks are given then remove all
@ -282,13 +287,13 @@ previous window.
------------------------------------------------------------------------------
*NERDTree-go*
Default key: go
Map option: None
Map option: NERDTreeMapPreview
Applies to: files.
If a file node is selected, it is opened in the previous window, but the
cursor does not move.
The key combo for this mapping is always "g" + NERDTreeMapActivateNode (see
The default key combo for this mapping is "g" + NERDTreeMapActivateNode (see
|NERDTree-o|).
------------------------------------------------------------------------------
@ -324,12 +329,12 @@ window.
------------------------------------------------------------------------------
*NERDTree-gi*
Default key: gi
Map option: None
Map option: NERDTreeMapPreviewSplit
Applies to: files.
The same as |NERDTree-i| except that the cursor is not moved.
The key combo for this mapping is always "g" + NERDTreeMapOpenSplit (see
The default key combo for this mapping is "g" + NERDTreeMapOpenSplit (see
|NERDTree-i|).
------------------------------------------------------------------------------
@ -344,12 +349,12 @@ the new window.
------------------------------------------------------------------------------
*NERDTree-gs*
Default key: gs
Map option: None
Map option: NERDTreeMapPreviewVSplit
Applies to: files.
The same as |NERDTree-s| except that the cursor is not moved.
The key combo for this mapping is always "g" + NERDTreeMapOpenVSplit (see
The default key combo for this mapping is "g" + NERDTreeMapOpenVSplit (see
|NERDTree-s|).
------------------------------------------------------------------------------
@ -618,6 +623,9 @@ NERD tree. These options should be set in your vimrc.
|'NERDTreeCaseSensitiveSort'| Tells the NERD tree whether to be case
sensitive or not when sorting nodes.
|'NERDTreeNaturalSort'| Tells the NERD tree whether to use
natural sort order or not when sorting nodes.
|'NERDTreeSortHiddenFirst'| Tells the NERD tree whether to take the dot
at the beginning of the hidden file names
into account when sorting nodes.
@ -637,11 +645,11 @@ NERD tree. These options should be set in your vimrc.
|'NERDTreeBookmarksFile'| Where the bookmarks are stored.
|'NERDTreeBookmarksSort'| Whether the bookmarks list is sorted on
display.
|'NERDTreeBookmarksSort'| Control how the Bookmark table is sorted.
|'NERDTreeMouseMode'| Tells the NERD tree how to handle mouse
clicks.
|'NERDTreeMarkBookmarks'| Render bookmarked nodes with markers.
|'NERDTreeMouseMode'| Manage the interpretation of mouse clicks.
|'NERDTreeQuitOnOpen'| Closes the tree window after opening a file.
@ -741,6 +749,33 @@ account. The above nodes would then be sorted like this: >
blarg.c
boner.c
<
------------------------------------------------------------------------------
*'NERDTreeNaturalSort'*
Values: 0 or 1.
Default: 0.
By default the NERD tree does not sort nodes in natural sort order, i.e. nodes
could appear like this: >
z1.txt
z10.txt
z100.txt
z11.txt
z110.txt
z2.txt
z20.txt
z3.txt
<
But if you set this option to 1 then the natural sort order will be used. The
above nodes would then be sorted like this: >
z1.txt
z2.txt
z3.txt
z10.txt
z11.txt
z20.txt
z100.txt
z110.txt
<
------------------------------------------------------------------------------
*'NERDTreeChDirMode'*
@ -835,11 +870,24 @@ This is where bookmarks are saved. See |NERDTreeBookmarkCommands|.
------------------------------------------------------------------------------
*'NERDTreeBookmarksSort'*
Values: 0, 1, or 2
Default: 1
This option controls the method by which the list of user bookmarks is
sorted. When sorted, bookmarks will render in alphabetical order by name.
If set to 0, the bookmarks list is not sorted.
If set to 1, the bookmarks list is sorted in a case-insensitive manner.
If set to 2, the bookmarks list is sorted in a case-sensitive manner.
------------------------------------------------------------------------------
*'NERDTreeMarkBookmarks'*
Values: 0 or 1
Default: 1
If set to 0 then the bookmarks list is not sorted.
If set to 1 the bookmarks list is sorted.
If set to 1, Bookmarks will be specially marked whenever the NERDTree is
rendered. Users of the |'NERDTreeMinimalUI'| setting may prefer to disable
this setting for even less visual clutter.
------------------------------------------------------------------------------
*'NERDTreeMouseMode'*

View file

@ -1,5 +1,13 @@
"CLASS: Bookmark
"============================================================
" ============================================================================
" 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
@ -19,12 +27,9 @@ function! s:Bookmark.AddBookmark(name, path)
endif
endfor
call add(s:Bookmark.Bookmarks(), s:Bookmark.New(a:name, a:path))
if g:NERDTreeBookmarksSort ==# 1
call s:Bookmark.Sort()
endif
endfunction
" FUNCTION: Bookmark.Bookmarks() {{{1
" FUNCTION: Bookmark.Bookmarks() {{{1
" Class method to get all bookmarks. Lazily initializes the bookmarks global
" variable
function! s:Bookmark.Bookmarks()
@ -34,7 +39,7 @@ function! s:Bookmark.Bookmarks()
return g:NERDTreeBookmarks
endfunction
" FUNCTION: Bookmark.BookmarkExistsFor(name) {{{1
" 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)
@ -46,19 +51,24 @@ function! s:Bookmark.BookmarkExistsFor(name)
endtry
endfunction
" FUNCTION: Bookmark.BookmarkFor(name) {{{1
" Class method to get the bookmark that has the given name. {} is return if no
" bookmark is found
" 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)
for i in s:Bookmark.Bookmarks()
if i.name ==# a:name
return i
let l:result = {}
for l:bookmark in s:Bookmark.Bookmarks()
if l:bookmark.name ==# a:name
let l:result = l:bookmark
break
endif
endfor
throw "NERDTree.BookmarkNotFoundError: no bookmark found for name: \"". a:name .'"'
if empty(l:result)
throw 'NERDTree.BookmarkNotFoundError: "' . a:name . '" not found'
endif
return l:result
endfunction
" FUNCTION: Bookmark.BookmarkNames() {{{1
" FUNCTION: Bookmark.BookmarkNames() {{{1
" Class method to return an array of all bookmark names
function! s:Bookmark.BookmarkNames()
let names = []
@ -104,17 +114,31 @@ function! s:Bookmark.CacheBookmarks(silent)
call nerdtree#echo(invalidBookmarksFound . " invalid bookmarks were read. See :help NERDTreeInvalidBookmarks for info.")
endif
endif
if g:NERDTreeBookmarksSort ==# 1
call s:Bookmark.Sort()
endif
endif
endfunction
" FUNCTION: Bookmark.compareTo(otherbookmark) {{{1
" Compare these two bookmarks for sorting purposes
function! s:Bookmark.compareTo(otherbookmark)
return a:otherbookmark.name < self.name
" 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()
@ -133,26 +157,33 @@ function! s:Bookmark.delete()
endfunction
" FUNCTION: Bookmark.getNode(nerdtree, searchFromAbsoluteRoot) {{{1
" Gets the treenode for this bookmark
" Returns the tree node object associated with this Bookmark.
" Throws "NERDTree.BookmarkedNodeNotFoundError" if the node is not found.
"
" Args:
" searchFromAbsoluteRoot: specifies whether we should search from the current
" tree root, or the highest cached node
" 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)
let searchRoot = a:searchFromAbsoluteRoot ? a:nerdtree.root.AbsoluteTreeRoot() : a:nerdtree.root
let targetNode = searchRoot.findNode(self.path)
if empty(targetNode)
throw "NERDTree.BookmarkedNodeNotFoundError: no node was found for bookmark: " . self.name
if a:searchFromAbsoluteRoot
let l:searchRoot = a:nerdtree.root.AbsoluteTreeRoot()
else
let l:searchRoot = a:nerdtree.root
endif
return targetNode
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 finds the bookmark with the given name and returns the
" treenode for it.
" 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 bookmark = s:Bookmark.BookmarkFor(a:name)
return bookmark.getNode(nerdtree, a:searchFromAbsoluteRoot)
let l:bookmark = s:Bookmark.BookmarkFor(a:name)
return l:bookmark.getNode(a:nerdtree, a:searchFromAbsoluteRoot)
endfunction
" FUNCTION: Bookmark.GetSelected() {{{1
@ -170,7 +201,7 @@ function! s:Bookmark.GetSelected()
return {}
endfunction
" FUNCTION: Bookmark.InvalidBookmarks() {{{1
" FUNCTION: Bookmark.InvalidBookmarks() {{{1
" Class method to get all invalid bookmark strings read from the bookmarks
" file
function! s:Bookmark.InvalidBookmarks()
@ -233,20 +264,20 @@ function! s:Bookmark.openInNewTab(options)
call self.open(a:options)
endfunction
" FUNCTION: Bookmark.setPath(path) {{{1
" 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.Sort() {{{1
" Class method that sorts all bookmarks
function! s:Bookmark.Sort()
let CompareFunc = function("nerdtree#compareBookmarks")
call sort(s:Bookmark.Bookmarks(), CompareFunc)
" 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
" 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 - len(self.name)
@ -292,7 +323,7 @@ function! s:Bookmark.validate()
endif
endfunction
" FUNCTION: Bookmark.Write() {{{1
" FUNCTION: Bookmark.Write() {{{1
" Class method to write all bookmarks to the bookmarks file
function! s:Bookmark.Write()
let bookmarkStrings = []

View file

@ -14,7 +14,7 @@ function! s:Creator._bindMappings()
command! -buffer -nargs=? Bookmark :call nerdtree#ui_glue#bookmarkNode('<args>')
command! -buffer -complete=customlist,nerdtree#completeBookmarks -nargs=1 RevealBookmark :call nerdtree#ui_glue#revealBookmark('<args>')
command! -buffer -complete=customlist,nerdtree#completeBookmarks -nargs=1 OpenBookmark :call nerdtree#ui_glue#openBookmark('<args>')
command! -buffer -complete=customlist,nerdtree#completeBookmarks -nargs=1 OpenBookmark call nerdtree#ui_glue#openBookmark('<args>')
command! -buffer -complete=customlist,nerdtree#completeBookmarks -nargs=* ClearBookmarks call nerdtree#ui_glue#clearBookmarks('<args>')
command! -buffer -complete=customlist,nerdtree#completeBookmarks -nargs=+ BookmarkToRoot call g:NERDTreeBookmark.ToRoot('<args>', b:NERDTree)
command! -buffer -nargs=0 ClearAllBookmarks call g:NERDTreeBookmark.ClearAll() <bar> call b:NERDTree.render()

View file

@ -1,12 +1,6 @@
"we need to use this number many times for sorting... so we calculate it only
"once here
let s:NERDTreeSortStarIndex = index(g:NERDTreeSortOrder, '*')
" used in formating sortKey, e.g. '%04d'
if exists("log10")
let s:sortKeyFormat = "%0" . float2nr(ceil(log10(len(g:NERDTreeSortOrder)))) . "d"
else
let s:sortKeyFormat = "%04d"
endif
"CLASS: Path
"============================================================
@ -52,7 +46,7 @@ function! s:Path.cacheDisplayString() abort
call add(self._bookmarkNames, i.name)
endif
endfor
if !empty(self._bookmarkNames)
if !empty(self._bookmarkNames) && g:NERDTreeMarkBookmarks == 1
let self.cachedDisplayString .= ' {' . join(self._bookmarkNames) . '}'
endif
@ -368,8 +362,23 @@ function! s:Path.getSortOrderIndex()
return s:NERDTreeSortStarIndex
endfunction
"FUNCTION: Path._splitChunks(path) {{{1
"returns a list of path chunks
function! s:Path._splitChunks(path)
let chunks = split(a:path, '\(\D\+\|\d\+\)\zs')
let i = 0
while i < len(chunks)
"convert number literals to numbers
if match(chunks[i], '^\d\+$') == 0
let chunks[i] = str2nr(chunks[i])
endif
let i = i + 1
endwhile
return chunks
endfunction
"FUNCTION: Path.getSortKey() {{{1
"returns a string used in compare function for sorting
"returns a key used in compare function for sorting
function! s:Path.getSortKey()
if !exists("self._sortKey")
let path = self.getLastPathComponent(1)
@ -379,7 +388,11 @@ function! s:Path.getSortKey()
if !g:NERDTreeCaseSensitiveSort
let path = tolower(path)
endif
let self._sortKey = printf(s:sortKeyFormat, self.getSortOrderIndex()) . path
if !g:NERDTreeNaturalSort
let self._sortKey = [self.getSortOrderIndex(), path]
else
let self._sortKey = [self.getSortOrderIndex()] + self._splitChunks(path)
endif
endif
return self._sortKey

View file

@ -1,13 +1,17 @@
"CLASS: TreeDirNode
"A subclass of NERDTreeFileNode.
" ============================================================================
" CLASS: TreeDirNode
"
"The 'composite' part of the file/dir composite.
"============================================================
" A subclass of NERDTreeFileNode.
"
" The 'composite' part of the file/dir composite.
" ============================================================================
let s:TreeDirNode = copy(g:NERDTreeFileNode)
let g:NERDTreeDirNode = s:TreeDirNode
"FUNCTION: TreeDirNode.AbsoluteTreeRoot(){{{1
"class method that returns the highest cached ancestor of the current root
" FUNCTION: TreeDirNode.AbsoluteTreeRoot(){{{1
" Class method that returns the highest cached ancestor of the current root.
function! s:TreeDirNode.AbsoluteTreeRoot()
let currentNode = b:NERDTree.root
while currentNode.parent != {}
@ -16,7 +20,7 @@ function! s:TreeDirNode.AbsoluteTreeRoot()
return currentNode
endfunction
"FUNCTION: TreeDirNode.activate([options]) {{{1
" FUNCTION: TreeDirNode.activate([options]) {{{1
unlet s:TreeDirNode.activate
function! s:TreeDirNode.activate(...)
let opts = a:0 ? a:1 : {}
@ -25,12 +29,12 @@ function! s:TreeDirNode.activate(...)
call self.putCursorHere(0, 0)
endfunction
"FUNCTION: TreeDirNode.addChild(treenode, inOrder) {{{1
"Adds the given treenode to the list of children for this node
" FUNCTION: TreeDirNode.addChild(treenode, inOrder) {{{1
" Adds the given treenode to the list of children for this node
"
"Args:
"-treenode: the node to add
"-inOrder: 1 if the new node should be inserted in sorted order
" Args:
" -treenode: the node to add
" -inOrder: 1 if the new node should be inserted in sorted order
function! s:TreeDirNode.addChild(treenode, inOrder)
call add(self.children, a:treenode)
let a:treenode.parent = self
@ -40,14 +44,14 @@ function! s:TreeDirNode.addChild(treenode, inOrder)
endif
endfunction
"FUNCTION: TreeDirNode.close() {{{1
"Closes this directory
" FUNCTION: TreeDirNode.close() {{{1
" Closes this directory
function! s:TreeDirNode.close()
let self.isOpen = 0
endfunction
"FUNCTION: TreeDirNode.closeChildren() {{{1
"Closes all the child dir nodes of this node
" FUNCTION: TreeDirNode.closeChildren() {{{1
" Closes all the child dir nodes of this node
function! s:TreeDirNode.closeChildren()
for i in self.children
if i.path.isDirectory
@ -57,23 +61,23 @@ function! s:TreeDirNode.closeChildren()
endfor
endfunction
"FUNCTION: TreeDirNode.createChild(path, inOrder) {{{1
"Instantiates a new child node for this node with the given path. The new
"nodes parent is set to this node.
" FUNCTION: TreeDirNode.createChild(path, inOrder) {{{1
" Instantiates a new child node for this node with the given path. The new
" nodes parent is set to this node.
"
"Args:
"path: a Path object that this node will represent/contain
"inOrder: 1 if the new node should be inserted in sorted order
" Args:
" path: a Path object that this node will represent/contain
" inOrder: 1 if the new node should be inserted in sorted order
"
"Returns:
"the newly created node
" Returns:
" the newly created node
function! s:TreeDirNode.createChild(path, inOrder)
let newTreeNode = g:NERDTreeFileNode.New(a:path, self.getNerdtree())
call self.addChild(newTreeNode, a:inOrder)
return newTreeNode
endfunction
"FUNCTION: TreeDirNode.displayString() {{{1
" FUNCTION: TreeDirNode.displayString() {{{1
unlet s:TreeDirNode.displayString
function! s:TreeDirNode.displayString()
let cascade = self.getCascade()
@ -89,11 +93,11 @@ function! s:TreeDirNode.displayString()
return sym . ' ' . flags . rv
endfunction
"FUNCTION: TreeDirNode.findNode(path) {{{1
"Will find one of the children (recursively) that has the given path
" FUNCTION: TreeDirNode.findNode(path) {{{1
" Will find one of the children (recursively) that has the given path
"
"Args:
"path: a path object
" Args:
" path: a path object
unlet s:TreeDirNode.findNode
function! s:TreeDirNode.findNode(path)
if a:path.equals(self.path)
@ -114,8 +118,8 @@ function! s:TreeDirNode.findNode(path)
return {}
endfunction
"FUNCTION: TreeDirNode.getCascade() {{{1
"Return an array of dir nodes (starting from self) that can be cascade opened.
" FUNCTION: TreeDirNode.getCascade() {{{1
" Return an array of dir nodes (starting from self) that can be cascade opened.
function! s:TreeDirNode.getCascade()
if !self.isCascadable()
return [self]
@ -127,20 +131,20 @@ function! s:TreeDirNode.getCascade()
return [self] + visChild.getCascade()
endfunction
"FUNCTION: TreeDirNode.getChildCount() {{{1
"Returns the number of children this node has
" FUNCTION: TreeDirNode.getChildCount() {{{1
" Returns the number of children this node has
function! s:TreeDirNode.getChildCount()
return len(self.children)
endfunction
"FUNCTION: TreeDirNode.getChild(path) {{{1
"Returns child node of this node that has the given path or {} if no such node
"exists.
" FUNCTION: TreeDirNode.getChild(path) {{{1
" Returns child node of this node that has the given path or {} if no such node
" exists.
"
"This function doesnt not recurse into child dir nodes
" This function doesnt not recurse into child dir nodes
"
"Args:
"path: a path object
" Args:
" path: a path object
function! s:TreeDirNode.getChild(path)
if stridx(a:path.str(), self.path.str(), 0) ==# -1
return {}
@ -155,12 +159,13 @@ function! s:TreeDirNode.getChild(path)
endfunction
"FUNCTION: TreeDirNode.getChildByIndex(indx, visible) {{{1
"returns the child at the given index
"Args:
"indx: the index to get the child from
"visible: 1 if only the visible children array should be used, 0 if all the
"children should be searched.
" FUNCTION: TreeDirNode.getChildByIndex(indx, visible) {{{1
" returns the child at the given index
"
" Args:
" indx: the index to get the child from
" visible: 1 if only the visible children array should be used, 0 if all the
" children should be searched.
function! s:TreeDirNode.getChildByIndex(indx, visible)
let array_to_search = a:visible? self.getVisibleChildren() : self.children
if a:indx > len(array_to_search)
@ -169,14 +174,14 @@ function! s:TreeDirNode.getChildByIndex(indx, visible)
return array_to_search[a:indx]
endfunction
"FUNCTION: TreeDirNode.getChildIndex(path) {{{1
"Returns the index of the child node of this node that has the given path or
"-1 if no such node exists.
" FUNCTION: TreeDirNode.getChildIndex(path) {{{1
" Returns the index of the child node of this node that has the given path or
" -1 if no such node exists.
"
"This function doesnt not recurse into child dir nodes
" This function doesnt not recurse into child dir nodes
"
"Args:
"path: a path object
" Args:
" path: a path object
function! s:TreeDirNode.getChildIndex(path)
if stridx(a:path.str(), self.path.str(), 0) ==# -1
return -1
@ -200,15 +205,88 @@ function! s:TreeDirNode.getChildIndex(path)
return -1
endfunction
"FUNCTION: TreeDirNode.getDirChildren() {{{1
"Get all children that are directories
" FUNCTION: TreeDirNode.getDirChildren() {{{1
" Return a list of all child nodes from "self.children" that are of type
" TreeDirNode.
function! s:TreeDirNode.getDirChildren()
return filter(self.children, 'v:val.path.isDirectory == 1')
endfunction
"FUNCTION: TreeDirNode.GetSelected() {{{1
"Returns the current node if it is a dir node, or else returns the current
"nodes parent
" FUNCTION: TreeDirNode._glob(pattern, all) {{{1
" Return a list of strings naming the descendants of the directory in this
" TreeDirNode object that match the specified glob pattern.
"
" Args:
" pattern: (string) the glob pattern to apply
" all: (0 or 1) if 1, include "." and ".." if they match "pattern"; if 0,
" always exclude them
"
" Note: If the pathnames in the result list are below the working directory,
" they are returned as pathnames relative to that directory. This is because
" this function, internally, attempts to obey 'wildignore' rules that use
" relative paths.
function! s:TreeDirNode._glob(pattern, all)
" Construct a path specification such that "globpath()" will return
" relative pathnames, if possible.
if self.path.str() == getcwd()
let l:pathSpec = ','
else
let l:pathSpec = fnamemodify(self.path.str({'format': 'Glob'}), ':.')
" On Windows, the drive letter may be removed by "fnamemodify()".
if nerdtree#runningWindows() && l:pathSpec[0] == '\'
let l:pathSpec = self.path.drive . l:pathSpec
endif
endif
let l:globList = []
" See ":h version7.txt" and ":h version8.txt" for details on the
" development of the "glob()" and "globpath()" functions.
if v:version > 704 || (v:version == 704 && has('patch654'))
let l:globList = globpath(l:pathSpec, a:pattern, !g:NERDTreeRespectWildIgnore, 1, 0)
elseif v:version == 704 && has('patch279')
let l:globList = globpath(l:pathSpec, a:pattern, !g:NERDTreeRespectWildIgnore, 1)
elseif v:version > 702 || (v:version == 702 && has('patch051'))
let l:globString = globpath(l:pathSpec, a:pattern, !g:NERDTreeRespectWildIgnore)
let l:globList = split(l:globString, "\n")
else
let l:globString = globpath(l:pathSpec, a:pattern)
let l:globList = split(l:globString, "\n")
endif
" If "a:all" is false, filter "." and ".." from the output.
if !a:all
let l:toRemove = []
for l:file in l:globList
let l:tail = fnamemodify(l:file, ':t')
" Double the modifier if only a separator was stripped.
if l:tail == ''
let l:tail = fnamemodify(l:file, ':t:t')
endif
if l:tail == '.' || l:tail == '..'
call add(l:toRemove, l:file)
if len(l:toRemove) == 2
break
endif
endif
endfor
for l:file in l:toRemove
call remove(l:globList, index(l:globList, l:file))
endfor
endif
return l:globList
endfunction
" FUNCTION: TreeDirNode.GetSelected() {{{1
" Returns the current node if it is a dir node, or else returns the current
" nodes parent
unlet s:TreeDirNode.GetSelected
function! s:TreeDirNode.GetSelected()
let currentDir = g:NERDTreeFileNode.GetSelected()
@ -220,17 +298,17 @@ function! s:TreeDirNode.GetSelected()
return currentDir
endfunction
"FUNCTION: TreeDirNode.getVisibleChildCount() {{{1
"Returns the number of visible children this node has
" FUNCTION: TreeDirNode.getVisibleChildCount() {{{1
" Returns the number of visible children this node has
function! s:TreeDirNode.getVisibleChildCount()
return len(self.getVisibleChildren())
endfunction
"FUNCTION: TreeDirNode.getVisibleChildren() {{{1
"Returns a list of children to display for this node, in the correct order
" FUNCTION: TreeDirNode.getVisibleChildren() {{{1
" Returns a list of children to display for this node, in the correct order
"
"Return:
"an array of treenodes
" Return:
" an array of treenodes
function! s:TreeDirNode.getVisibleChildren()
let toReturn = []
for i in self.children
@ -241,14 +319,14 @@ function! s:TreeDirNode.getVisibleChildren()
return toReturn
endfunction
"FUNCTION: TreeDirNode.hasVisibleChildren() {{{1
"returns 1 if this node has any childre, 0 otherwise..
" FUNCTION: TreeDirNode.hasVisibleChildren() {{{1
" returns 1 if this node has any childre, 0 otherwise..
function! s:TreeDirNode.hasVisibleChildren()
return self.getVisibleChildCount() != 0
endfunction
"FUNCTION: TreeDirNode.isCascadable() {{{1
"true if this dir has only one visible child - which is also a dir
" FUNCTION: TreeDirNode.isCascadable() {{{1
" true if this dir has only one visible child - which is also a dir
function! s:TreeDirNode.isCascadable()
if g:NERDTreeCascadeSingleChildDir == 0
return 0
@ -258,29 +336,19 @@ function! s:TreeDirNode.isCascadable()
return len(c) == 1 && c[0].path.isDirectory
endfunction
"FUNCTION: TreeDirNode._initChildren() {{{1
"Removes all childen from this node and re-reads them
" FUNCTION: TreeDirNode._initChildren() {{{1
" Removes all childen from this node and re-reads them
"
"Args:
"silent: 1 if the function should not echo any "please wait" messages for
"large directories
" Args:
" silent: 1 if the function should not echo any "please wait" messages for
" large directories
"
"Return: the number of child nodes read
" Return: the number of child nodes read
function! s:TreeDirNode._initChildren(silent)
"remove all the current child nodes
let self.children = []
"get an array of all the files in the nodes dir
let dir = self.path
let globDir = dir.str({'format': 'Glob'})
if version >= 703
let filesStr = globpath(globDir, '*', !g:NERDTreeRespectWildIgnore) . "\n" . globpath(globDir, '.*', !g:NERDTreeRespectWildIgnore)
else
let filesStr = globpath(globDir, '*') . "\n" . globpath(globDir, '.*')
endif
let files = split(filesStr, "\n")
let files = self._glob('*', 1) + self._glob('.*', 0)
if !a:silent && len(files) > g:NERDTreeNotificationThreshold
call nerdtree#echo("Please wait, caching a large dir ...")
@ -288,21 +356,13 @@ function! s:TreeDirNode._initChildren(silent)
let invalidFilesFound = 0
for i in files
"filter out the .. and . directories
"Note: we must match .. AND ../ since sometimes the globpath returns
"../ for path with strange chars (eg $)
if i[len(i)-3:2] != ".." && i[len(i)-2:2] != ".." &&
\ i[len(i)-2:1] != "." && i[len(i)-1] != "."
"put the next file in a new node and attach it
try
let path = g:NERDTreePath.New(i)
call self.createChild(path, 0)
call g:NERDTreePathNotifier.NotifyListeners('init', path, self.getNerdtree(), {})
catch /^NERDTree.\(InvalidArguments\|InvalidFiletype\)Error/
let invalidFilesFound += 1
endtry
endif
try
let path = g:NERDTreePath.New(i)
call self.createChild(path, 0)
call g:NERDTreePathNotifier.NotifyListeners('init', path, self.getNerdtree(), {})
catch /^NERDTree.\(InvalidArguments\|InvalidFiletype\)Error/
let invalidFilesFound += 1
endtry
endfor
call self.sortChildren()
@ -317,12 +377,12 @@ function! s:TreeDirNode._initChildren(silent)
return self.getChildCount()
endfunction
"FUNCTION: TreeDirNode.New(path, nerdtree) {{{1
"Returns a new TreeNode object with the given path and parent
" FUNCTION: TreeDirNode.New(path, nerdtree) {{{1
" Return a new TreeDirNode object with the given path and parent.
"
"Args:
"path: dir that the node represents
"nerdtree: the tree the node belongs to
" Args:
" path: dir that the node represents
" nerdtree: the tree the node belongs to
function! s:TreeDirNode.New(path, nerdtree)
if a:path.isDirectory != 1
throw "NERDTree.InvalidArgumentsError: A TreeDirNode object must be instantiated with a directory Path object."
@ -340,10 +400,10 @@ function! s:TreeDirNode.New(path, nerdtree)
return newTreeNode
endfunction
"FUNCTION: TreeDirNode.open([opts]) {{{1
"Open the dir in the current tree or in a new tree elsewhere.
" FUNCTION: TreeDirNode.open([opts]) {{{1
" Open the dir in the current tree or in a new tree elsewhere.
"
"If opening in the current tree, return the number of cached nodes.
" If opening in the current tree, return the number of cached nodes.
unlet s:TreeDirNode.open
function! s:TreeDirNode.open(...)
let opts = a:0 ? a:1 : {}
@ -361,10 +421,10 @@ function! s:TreeDirNode.open(...)
endif
endfunction
"FUNCTION: TreeDirNode.openAlong([opts]) {{{1
"recursive open the dir if it has only one directory child.
" FUNCTION: TreeDirNode.openAlong([opts]) {{{1
" recursive open the dir if it has only one directory child.
"
"return the level of opened directories.
" return the level of opened directories.
function! s:TreeDirNode.openAlong(...)
let opts = a:0 ? a:1 : {}
let level = 0
@ -383,42 +443,42 @@ function! s:TreeDirNode.openAlong(...)
endfunction
" FUNCTION: TreeDirNode.openExplorer() {{{1
" opens an explorer window for this node in the previous window (could be a
" nerd tree or a netrw)
" Open an explorer window for this node in the previous window. The explorer
" can be a NERDTree window or a netrw window.
function! s:TreeDirNode.openExplorer()
call self.open({'where': 'p'})
endfunction
"FUNCTION: TreeDirNode.openInNewTab(options) {{{1
" FUNCTION: TreeDirNode.openInNewTab(options) {{{1
unlet s:TreeDirNode.openInNewTab
function! s:TreeDirNode.openInNewTab(options)
call nerdtree#deprecated('TreeDirNode.openInNewTab', 'is deprecated, use open() instead')
call self.open({'where': 't'})
endfunction
"FUNCTION: TreeDirNode._openInNewTab() {{{1
" FUNCTION: TreeDirNode._openInNewTab() {{{1
function! s:TreeDirNode._openInNewTab()
tabnew
call g:NERDTreeCreator.CreateTabTree(self.path.str())
endfunction
"FUNCTION: TreeDirNode.openRecursively() {{{1
"Opens this treenode and all of its children whose paths arent 'ignored'
"because of the file filters.
" FUNCTION: TreeDirNode.openRecursively() {{{1
" Opens this treenode and all of its children whose paths arent 'ignored'
" because of the file filters.
"
"This method is actually a wrapper for the OpenRecursively2 method which does
"the work.
" This method is actually a wrapper for the OpenRecursively2 method which does
" the work.
function! s:TreeDirNode.openRecursively()
call self._openRecursively2(1)
endfunction
"FUNCTION: TreeDirNode._openRecursively2() {{{1
"Opens this all children of this treenode recursively if either:
" FUNCTION: TreeDirNode._openRecursively2() {{{1
" Opens this all children of this treenode recursively if either:
" *they arent filtered by file filters
" *a:forceOpen is 1
"
"Args:
"forceOpen: 1 if this node should be opened regardless of file filters
" Args:
" forceOpen: 1 if this node should be opened regardless of file filters
function! s:TreeDirNode._openRecursively2(forceOpen)
if self.path.ignore(self.getNerdtree()) ==# 0 || a:forceOpen
let self.isOpen = 1
@ -434,50 +494,33 @@ function! s:TreeDirNode._openRecursively2(forceOpen)
endif
endfunction
"FUNCTION: TreeDirNode.refresh() {{{1
unlet s:TreeDirNode.refresh
" FUNCTION: TreeDirNode.refresh() {{{1
function! s:TreeDirNode.refresh()
call self.path.refresh(self.getNerdtree())
"if this node was ever opened, refresh its children
if self.isOpen || !empty(self.children)
"go thru all the files/dirs under this node
let files = self._glob('*', 1) + self._glob('.*', 0)
let newChildNodes = []
let invalidFilesFound = 0
let dir = self.path
let globDir = dir.str({'format': 'Glob'})
let filesStr = globpath(globDir, '*') . "\n" . globpath(globDir, '.*')
let files = split(filesStr, "\n")
for i in files
"filter out the .. and . directories
"Note: we must match .. AND ../ cos sometimes the globpath returns
"../ for path with strange chars (eg $)
"if i !~# '\/\.\.\/\?$' && i !~# '\/\.\/\?$'
try
"create a new path and see if it exists in this nodes children
let path = g:NERDTreePath.New(i)
let newNode = self.getChild(path)
if newNode != {}
call newNode.refresh()
call add(newChildNodes, newNode)
" Regular expression is too expensive. Use simply string comparison
" instead
if i[len(i)-3:2] != ".." && i[len(i)-2:2] != ".." &&
\ i[len(i)-2:1] != "." && i[len(i)-1] != "."
try
"create a new path and see if it exists in this nodes children
let path = g:NERDTreePath.New(i)
let newNode = self.getChild(path)
if newNode != {}
call newNode.refresh()
call add(newChildNodes, newNode)
"the node doesnt exist so create it
else
let newNode = g:NERDTreeFileNode.New(path, self.getNerdtree())
let newNode.parent = self
call add(newChildNodes, newNode)
endif
catch /^NERDTree.\(InvalidArguments\|InvalidFiletype\)Error/
let invalidFilesFound = 1
endtry
endif
"the node doesnt exist so create it
else
let newNode = g:NERDTreeFileNode.New(path, self.getNerdtree())
let newNode.parent = self
call add(newChildNodes, newNode)
endif
catch /^NERDTree.\(InvalidArguments\|InvalidFiletype\)Error/
let invalidFilesFound = 1
endtry
endfor
"swap this nodes children out for the children we just read/refreshed
@ -490,7 +533,7 @@ function! s:TreeDirNode.refresh()
endif
endfunction
"FUNCTION: TreeDirNode.refreshFlags() {{{1
" FUNCTION: TreeDirNode.refreshFlags() {{{1
unlet s:TreeDirNode.refreshFlags
function! s:TreeDirNode.refreshFlags()
call self.path.refreshFlags(self.getNerdtree())
@ -499,15 +542,15 @@ function! s:TreeDirNode.refreshFlags()
endfor
endfunction
"FUNCTION: TreeDirNode.refreshDirFlags() {{{1
" FUNCTION: TreeDirNode.refreshDirFlags() {{{1
function! s:TreeDirNode.refreshDirFlags()
call self.path.refreshFlags(self.getNerdtree())
endfunction
"FUNCTION: TreeDirNode.reveal(path) {{{1
"reveal the given path, i.e. cache and open all treenodes needed to display it
"in the UI
"Returns the revealed node
" FUNCTION: TreeDirNode.reveal(path) {{{1
" reveal the given path, i.e. cache and open all treenodes needed to display it
" in the UI
" Returns the revealed node
function! s:TreeDirNode.reveal(path, ...)
let opts = a:0 ? a:1 : {}
@ -534,14 +577,12 @@ function! s:TreeDirNode.reveal(path, ...)
return n.reveal(a:path, opts)
endfunction
"FUNCTION: TreeDirNode.removeChild(treenode) {{{1
" FUNCTION: TreeDirNode.removeChild(treenode) {{{1
" Remove the given treenode from "self.children".
" Throws "NERDTree.ChildNotFoundError" if the node is not found.
"
"Removes the given treenode from this nodes set of children
"
"Args:
"treenode: the node to remove
"
"Throws a NERDTree.ChildNotFoundError if the given treenode is not found
" Args:
" treenode: the node object to remove
function! s:TreeDirNode.removeChild(treenode)
for i in range(0, self.getChildCount()-1)
if self.children[i].equals(a:treenode)
@ -553,18 +594,15 @@ function! s:TreeDirNode.removeChild(treenode)
throw "NERDTree.ChildNotFoundError: child node was not found"
endfunction
"FUNCTION: TreeDirNode.sortChildren() {{{1
"
"Sorts the children of this node according to alphabetical order and the
"directory priority.
"
" FUNCTION: TreeDirNode.sortChildren() {{{1
" Sort "self.children" by alphabetical order and directory priority.
function! s:TreeDirNode.sortChildren()
let CompareFunc = function("nerdtree#compareNodesBySortKey")
call sort(self.children, CompareFunc)
endfunction
"FUNCTION: TreeDirNode.toggleOpen([options]) {{{1
"Opens this directory if it is closed and vice versa
" FUNCTION: TreeDirNode.toggleOpen([options]) {{{1
" Opens this directory if it is closed and vice versa
function! s:TreeDirNode.toggleOpen(...)
let opts = a:0 ? a:1 : {}
if self.isOpen ==# 1
@ -578,13 +616,13 @@ function! s:TreeDirNode.toggleOpen(...)
endif
endfunction
"FUNCTION: TreeDirNode.transplantChild(newNode) {{{1
"Replaces the child of this with the given node (where the child node's full
"path matches a:newNode's fullpath). The search for the matching node is
"non-recursive
" FUNCTION: TreeDirNode.transplantChild(newNode) {{{1
" Replaces the child of this with the given node (where the child node's full
" path matches a:newNode's fullpath). The search for the matching node is
" non-recursive
"
"Arg:
"newNode: the node to graft into the tree
" Arg:
" newNode: the node to graft into the tree
function! s:TreeDirNode.transplantChild(newNode)
for i in range(0, self.getChildCount()-1)
if self.children[i].equals(a:newNode)

View file

@ -313,6 +313,10 @@ function! s:UI._renderBookmarks()
call cursor(line(".")+1, col("."))
endif
if g:NERDTreeBookmarksSort == 1 || g:NERDTreeBookmarksSort == 2
call g:NERDTreeBookmark.SortBookmarksList()
endif
for i in g:NERDTreeBookmark.Bookmarks()
call setline(line(".")+1, i.str())
call cursor(line(".")+1, col("."))

View file

@ -46,6 +46,7 @@ endfunction
call s:initVariable("g:NERDTreeAutoCenter", 1)
call s:initVariable("g:NERDTreeAutoCenterThreshold", 3)
call s:initVariable("g:NERDTreeCaseSensitiveSort", 0)
call s:initVariable("g:NERDTreeNaturalSort", 0)
call s:initVariable("g:NERDTreeSortHiddenFirst", 1)
call s:initVariable("g:NERDTreeChDirMode", 0)
call s:initVariable("g:NERDTreeCreatePrefix", "silent")
@ -57,6 +58,7 @@ call s:initVariable("g:NERDTreeBookmarksFile", expand('$HOME') . '/.NERDTreeBook
call s:initVariable("g:NERDTreeBookmarksSort", 1)
call s:initVariable("g:NERDTreeHighlightCursorline", 1)
call s:initVariable("g:NERDTreeHijackNetrw", 1)
call s:initVariable('g:NERDTreeMarkBookmarks', 1)
call s:initVariable("g:NERDTreeMouseMode", 1)
call s:initVariable("g:NERDTreeNotificationThreshold", 100)
call s:initVariable("g:NERDTreeQuitOnOpen", 0)

View file

@ -265,12 +265,17 @@ function! syntastic#preprocess#perl(errors) abort " {{{2
endfunction " }}}2
function! syntastic#preprocess#prospector(errors) abort " {{{2
let errs = s:_decode_JSON(join(a:errors, ''))
let errs = join(a:errors, '')
if errs ==# ''
return []
endif
let json = s:_decode_JSON(errs)
let out = []
if type(errs) == type({}) && has_key(errs, 'messages')
if type(errs['messages']) == type([])
for e in errs['messages']
if type(json) == type({}) && has_key(json, 'messages')
if type(json['messages']) == type([])
for e in json['messages']
if type(e) == type({})
try
if e['source'] ==# 'pylint'
@ -300,6 +305,8 @@ function! syntastic#preprocess#prospector(errors) abort " {{{2
else
call syntastic#log#warn('checker python/prospector: unrecognized error format (crashed checker?)')
endif
else
call syntastic#log#warn('checker python/prospector: unrecognized error format (crashed checker?)')
endif
return out

View file

@ -76,7 +76,7 @@ function! syntastic#util#tmpdir() abort " {{{2
if (has('unix') || has('mac')) && executable('mktemp') && !has('win32unix')
" TODO: option "-t" to mktemp(1) is not portable
let tmp = $TMPDIR !=# '' ? $TMPDIR : $TMP !=# '' ? $TMP : '/tmp'
let out = split(syntastic#util#system('mktemp -q -d ' . tmp . '/vim-syntastic-' . getpid() . '-XXXXXXXX'), "\n")
let out = split(syntastic#util#system('mktemp -q -d ' . tmp . '/vim-syntastic-' . s:_fuzz() . '-XXXXXXXX'), "\n")
if v:shell_error == 0 && len(out) == 1
let tempdir = out[0]
endif
@ -84,13 +84,13 @@ function! syntastic#util#tmpdir() abort " {{{2
if tempdir ==# ''
if has('win32') || has('win64')
let tempdir = $TEMP . syntastic#util#Slash() . 'vim-syntastic-' . getpid()
let tempdir = $TEMP . syntastic#util#Slash() . 'vim-syntastic-' . s:_fuzz()
elseif has('win32unix')
let tempdir = syntastic#util#CygwinPath('/tmp/vim-syntastic-' . getpid())
let tempdir = syntastic#util#CygwinPath('/tmp/vim-syntastic-' . s:_fuzz())
elseif $TMPDIR !=# ''
let tempdir = $TMPDIR . '/vim-syntastic-' . getpid()
let tempdir = $TMPDIR . '/vim-syntastic-' . s:_fuzz()
else
let tempdir = '/tmp/vim-syntastic-' . getpid()
let tempdir = '/tmp/vim-syntastic-' . s:_fuzz()
endif
try
@ -401,9 +401,6 @@ function! syntastic#util#setLastTick(buf) abort " {{{2
call setbufvar(a:buf, 'syntastic_lasttick', getbufvar(a:buf, 'changedtick'))
endfunction " }}}2
let s:_wid_base = 'syntastic_' . getpid() . '_' . reltimestr(g:_SYNTASTIC_START) . '_'
let s:_wid_pool = 0
" Add unique IDs to windows
function! syntastic#util#setWids() abort " {{{2
for tab in range(1, tabpagenr('$'))
@ -614,8 +611,18 @@ endfunction "}}}2
let s:_getbufvar = function(v:version > 703 || (v:version == 703 && has('patch831')) ? 'getbufvar' : 's:_getbufvar_dumb')
lockvar s:_getbufvar
function! s:_fuzz_dumb() abort " {{{2
return 'tmp'
endfunction " }}}2
let s:_fuzz = function(exists('*getpid') ? 'getpid' : 's:_fuzz_dumb')
lockvar s:_fuzz
" }}}1
let s:_wid_base = 'syntastic_' . s:_fuzz() . '_' . reltimestr(g:_SYNTASTIC_START) . '_'
let s:_wid_pool = 0
let &cpo = s:save_cpo
unlet s:save_cpo

View file

@ -1614,7 +1614,8 @@ SYNTAX CHECKERS FOR COFFEESCRIPT *syntastic-checkers-coffee*
The following checkers are available for CoffeeScript (filetype "coffee"):
1. Coffee...................|syntastic-coffee-coffee|
2. CoffeeLint...............|syntastic-coffee-coffeelint|
2. Coffee->JSHint...........|syntastic-coffee-coffee_jshint|
3. CoffeeLint...............|syntastic-coffee-coffeelint|
------------------------------------------------------------------------------
1. Coffee *syntastic-coffee-coffee*
@ -1634,7 +1635,28 @@ This checker is initialised using the "makeprgBuild()" function and thus it
accepts the standard options described at |syntastic-config-makeprg|.
------------------------------------------------------------------------------
2. CoffeeLint *syntastic-coffee-coffeelint*
2. Coffee->JSHint *syntastic-coffee-coffee_jshint*
Name: coffee_jshint
Maintainer: John Krauss <john@johnkrauss.com>
"Coffee->JSHint" is a JSHint validator for CoffeeScript. See the project's
page at GitHub for details:
https://github.com/marviq/coffee-jshint
Installation~
Install it with "npm": >
npm install -g coffee-jshint
<
Checker options~
This checker is initialised using the "makeprgBuild()" function and thus it
Accepts the standard options described at |syntastic-config-makeprg|.
------------------------------------------------------------------------------
3. CoffeeLint *syntastic-coffee-coffeelint*
Name: coffeelint
Maintainer: Lincoln Stoll <l@lds.li>

View file

@ -19,7 +19,7 @@ if has('reltime')
lockvar! g:_SYNTASTIC_START
endif
let g:_SYNTASTIC_VERSION = '3.8.0-55'
let g:_SYNTASTIC_VERSION = '3.8.0-60'
lockvar g:_SYNTASTIC_VERSION
" Sanity checks {{{1

View file

@ -0,0 +1,44 @@
"============================================================================
"File: coffee_jshint.vim
"Description: Syntax checking plugin for syntastic
"Maintainer: John Krauss <john@johnkrauss.com>
"License: This program is free software. It comes without any warranty,
" to the extent permitted by applicable law. You can redistribute
" it and/or modify it under the terms of the Do What The Fuck You
" Want To Public License, Version 2, as published by Sam Hocevar.
" See http://sam.zoy.org/wtfpl/COPYING for more details.
"
"============================================================================
if exists('g:loaded_syntastic_coffee_coffee_jshint_checker')
finish
endif
let g:loaded_syntastic_coffee_coffee_jshint_checker = 1
let s:save_cpo = &cpo
set cpo&vim
function! SyntaxCheckers_coffee_coffee_jshint_GetLocList() dict
let makeprg = self.makeprgBuild({})
let errorformat =
\ '%Q-%\{32\,},' .
\ '%E%l:%c: %m,' .
\ '%P%f'
return SyntasticMake({
\ 'makeprg': makeprg,
\ 'errorformat': errorformat,
\ 'returns': [0, 1] })
endfunction
call g:SyntasticRegistry.CreateAndRegisterChecker({
\ 'filetype': 'coffee',
\ 'exec': 'coffee-jshint',
\ 'name': 'coffee_jshint' })
let &cpo = s:save_cpo
unlet s:save_cpo
" vim: set sw=4 sts=4 et fdm=marker:

View file

@ -33,6 +33,7 @@ function! SyntaxCheckers_css_csslint_GetLocList() dict
return SyntasticMake({
\ 'makeprg': makeprg,
\ 'errorformat': errorformat,
\ 'postprocess': ['guards'],
\ 'defaults': {'bufnr': bufnr('')} })
endfunction

View file

@ -19,13 +19,13 @@ let s:save_cpo = &cpo
set cpo&vim
function! SyntaxCheckers_lisp_clisp_GetLocList() dict
let buf = bufnr('')
let tmpdir = syntastic#util#tmpdir()
let out = tmpdir !=# '.' ? ('-o ' . syntastic#util#shescape(tmpdir . syntastic#util#Slash() . 'syntastic_' . getpid())) : ''
let makeprg = self.makeprgBuild({
\ 'args_after': '-q',
\ 'fname_before': '-c',
\ 'post_args_after': out })
\ 'post_args_after': ['-o', tmpdir] })
let errorformat =
\ '%-G;%.%#,' .
@ -40,7 +40,7 @@ function! SyntaxCheckers_lisp_clisp_GetLocList() dict
let loclist = SyntasticMake({
\ 'makeprg': makeprg,
\ 'errorformat': errorformat,
\ 'defaults': {'bufnr': bufnr('')} })
\ 'defaults': {'bufnr': buf} })
call syntastic#util#rmrf(tmpdir)

View file

@ -1 +0,0 @@
/doc/tags

View file

@ -1 +0,0 @@
See the [contribution guidelines for pathogen.vim](https://github.com/tpope/vim-pathogen/blob/master/CONTRIBUTING.markdown).

View file

@ -1,150 +0,0 @@
# abolish.vim
I sat on this plugin for 3 years before releasing it, primarily
because it's so gosh darn hard to explain. It's three superficially
unrelated plugins in one that share a common theme: working with
variants of a word.
## Abbreviation
I know how to spell "separate". I know how to spell "desperate". My
fingers, however, have trouble distinguishing between the two, and I
invariably have a 50 percent chance of typing "seperate" or "desparate"
each time one of these comes up. At first, I tried abbreviations:
:iabbrev seperate separate
:iabbrev desparate desperate
But this falls short at the beginning of a sentence.
:iabbrev Seperate Separate
:iabbrev Desparate Desperate
To be really thorough, we need uppercase too!
:iabbrev SEPERATE SEPARATE
:iabbrev DESPARATE DESPERATE
Oh, but consider the noun form, and the adverb form!
:iabbrev seperation separation
:iabbrev desparation desperation
:iabbrev seperately separately
:iabbrev desparately desperately
:iabbrev Seperation separation
:iabbrev Desparation Desperation
:iabbrev Seperately Separately
:iabbrev Desparately Desperately
:iabbrev SEPERATION SEPARATION
:iabbrev DESPARATION DESPERATION
:iabbrev SEPERATELY SEPARATELY
:iabbrev DESPARATELY DESPERATELY
Wait, there's also "separates", "separated", "separating",
"separations", "separator"...
Abolish.vim provides a simpler way. The following one command produces
48 abbreviations including all of the above.
:Abolish {despa,sepe}rat{e,es,ed,ing,ely,ion,ions,or} {despe,sepa}rat{}
My current configuration has 25 Abolish commands that create hundreds of
corrections my fingers refuse to learn.
## Substitution
One time I had an application with a domain model called
"facility" that needed to be renamed to "building". So, a simple
search and replace, right?
:%s/facility/building/g
Oh, but the case variants!
:%s/Facility/Building/g
:%s/FACILITY/BUILDING/g
Wait, the plural is more than "s" so we need to get that too!
:%s/facilities/buildings/g
:%s/Facilities/Buildings/g
:%s/FACILITIES/BUILDINGS/g
Abolish.vim has your back. One command to do all six, and you can
repeat it with `&` too!
:%Subvert/facilit{y,ies}/building{,s}/g
From a conceptual level, one way to think about how this substitution
works is to imagine that in the braces you are declaring the
requirements for turning that word from singular to plural. In
the facility example, the same base letters in both the singular
and plural form of the word are `facilit` To turn "facility" to a
plural word you must change the `y` to `ies` so you specify
`{y,ies}` in the braces.
To convert the word "building" from singular to plural, again
look at the common letters between the singular and plural forms:
`building`. In this case you do not need to remove any letter
from building to turn it into plural form and you need to
add an `s` so the braces should be `{,s}`.
A few more examples:
Address to Reference
:Subvert/address{,es}/reference{,s}/g
Blog to Post (you can just do this with a regular :s also)
:Subvert/blog{,s}/post{,s}/g
Child to Adult
:Subvert/child{,ren}/adult{,s}/g
Be amazed as it correctly turns the word children into the word adults!
Die to Spinner
:Subvert/di{e,ce}/spinner{,s}/g
You can abbreviate it as `:S`, and it accepts the full range of flags
including things like `c` (confirm).
There's also a variant for searching and a variant for grepping.
## Coercion
Want to turn `fooBar` into `foo_bar`? Press `crs` (coerce to
snake\_case). MixedCase (`crm`), camelCase (`crc`), snake\_case
(`crs`), UPPER\_CASE (`cru`), dash-case (`cr-`), dot.case (`cr.`),
space case (`cr<space>`), and Title Case (`crt`) are all just 3
keystrokes away. These commands support
[repeat.vim](https://github.com/tpope/vim-repeat).
## Installation
If you don't have a preferred installation method, I recommend
installing [pathogen.vim](https://github.com/tpope/vim-pathogen), and
then simply copy and paste:
cd ~/.vim/bundle
git clone git://github.com/tpope/vim-abolish.git
Once help tags have been generated, you can view the manual with
`:help abolish`.
## Self-Promotion
Like abolish.vim? Follow the repository on
[GitHub](https://github.com/tpope/vim-abolish) and vote for it on
[vim.org](http://www.vim.org/scripts/script.php?script_id=1545). And if
you're feeling especially charitable, follow [tpope](http://tpo.pe/) on
[Twitter](http://twitter.com/tpope) and
[GitHub](https://github.com/tpope).
## License
Copyright (c) Tim Pope. Distributed under the same terms as Vim itself.
See `:help license`.

View file

@ -1,181 +0,0 @@
*abolish.txt* Language friendly searches, substitutions, and abbreviations
Author: Tim Pope <http://tpo.pe/>
License: Same terms as Vim itself (see |license|)
This plugin is only available if 'compatible' is not set.
INTRODUCTION *abolish* *:Abolish* *:Subvert*
Abolish lets you quickly find, substitute, and abbreviate several variations
of a word at once. By default, three case variants (foo, Foo, and FOO) are
operated on by every command.
Two commands are provided. :Abolish is the most general interface.
:Subvert provides an alternative, more concise syntax for searching and
substituting.
>
:Abolish [options] {abbreviation} {replacement}
:Abolish -delete [options] {abbreviation}
:Abolish -search [options] {pattern}
:Subvert/{pattern}[/flags]
:Abolish!-search [options] {pattern}
:Subvert?{pattern}[?flags]
:Abolish -search [options] {pattern} {grep-arguments}
:Subvert /{pattern}/[flags] {grep-options}
:Abolish!-search [options] {pattern} {grep-arguments}
:Subvert!/{pattern}/[flags] {grep-options}
:[range]Abolish -substitute [options] {pattern} {replacement}
:[range]Subvert/{pattern}/{replacement}[/flags]
<
*:S*
In addition to the :Subvert command, a :S synonym is provided if not
already defined. This will be used in examples below.
PATTERNS *abolish-patterns*
Patterns can include brace pairs that contain comma separated alternatives:
box{,es} => box, boxes, Box, Boxes, BOX, BOXES
For commands with a replacement, corresponding brace pairs are used in both
halves. If the replacement should be identical to the pattern, an empty
brace pair may be used. If fewer replacements are given than were given in
the pattern, they are looped. That is, {a,b} on the replacement side is the
same as {a,b,a,b,a,b,...} repeated indefinitely.
The following replaces several different misspellings of "necessary":
>
:%S/{,un}nec{ce,ces,e}sar{y,ily}/{}nec{es}sar{}/g
<
ABBREVIATING *abolish-abbrev*
By default :Abolish creates abbreviations, which replace words automatically
as you type. This is good for words you frequently misspell, or as
shortcuts for longer words. Since these are just Vim abbreviations, only
whole words will match.
>
:Abolish anomol{y,ies} anomal{}
:Abolish {,in}consistant{,ly} {}consistent{}
:Abolish Tqbf The quick, brown fox jumps over the lazy dog
<
Accepts the following options:
-buffer: buffer local
-cmdline: work in command line in addition to insert mode
A good place to define abbreviations is "after/plugin/abolish.vim",
relative to ~\vimfiles on Windows and ~/.vim everywhere else.
With a bang (:Abolish!) the abbreviation is also appended to the file in
g:abolish_save_file. The default is "after/plugin/abolish.vim", relative
to the install directory.
Abbreviations can be removed with :Abolish -delete:
>
Abolish -delete -buffer -cmdline anomol{y,ies}
<
SEARCHING *abolish-search*
The -search command does a search in a manner similar to / key.
search. After searching, you can use |n| and |N| as you would with a normal
search.
The following will search for box, Box, and BOX:
>
:Abolish -search box
<
When given a single word to operate on, :Subvert defaults to doing a
search as well:
>
:S/box/
<
This one searches for box, boxes, boxed, boxing, Box, Boxes, Boxed, Boxing,
BOX, BOXES, BOXED, and BOXING:
>
:S/box{,es,ed,ing}/
<
The following syntaxes search in reverse.
>
:Abolish! -search box
:S?box?
<
Flags can be given with the -flags= option to :Abolish, or by appending them
after the separator to :Subvert. The flags trigger the following behaviors:
I: Disable case variations (box, Box, BOX)
v: Match inside variable names (match my_box, myBox, but not mybox)
w: Match whole words (like surrounding with \< and \>)
A |search-offset| may follow the flags.
>
:Abolish -search -flags=avs+1 box
:S?box{,es,ed,ing}?we
<
GREPPING *abolish-grep*
Grepping works similar to searching, and is invoked when additional options
are given. These options are passed directly to the :grep command.
>
:Abolish -search box{,es}
:S /box{,es}/ *
:S /box/aw *.txt *.html
<
The slash delimiters must both be present if used with :Subvert. They may
both be omitted if no flags are used.
Both an external grepprg and vimgrep (via grepprg=internal) are supported.
With an external grep, the "v" flag behaves less intelligently, due to the
lack of look ahead and look behind support in grep regexps.
SUBSTITUTING *abolish-substitute*
Giving a range switches :Subvert into substitute mode. This command will
change box -> bag, boxes -> bags, Box -> Bag, Boxes -> Bags, BOX -> BAG,
BOXES -> BAGS across the entire document:
>
:%Abolish -substitute -flags=g box{,es} bag{,s}
:%S/box{,es}/bag{,s}/g
<
The "c", "e", "g", and "n" flags can be used from the substitute command
|:s_flags|, along with the "a", "I", "v", and "w" flags from searching.
COERCION *abolish-coercion* *cr*
Abolish's case mutating algorithms can be applied to the word under the cursor
using the cr mapping (mnemonic: CoeRce) followed by one of the following
characters:
c: camelCase
m: MixedCase
_: snake_case
s: snake_case
u: SNAKE_UPPERCASE
U: SNAKE_UPPERCASE
-: dash-case (not usually reversible; see |abolish-coercion-reversible|)
k: kebab-case (not usually reversible; see |abolish-coercion-reversible|)
.: dot.case (not usually reversible; see |abolish-coercion-reversible|)
<space>: space case (not usually reversible; see |abolish-coercion-reversible|)
t: Title Case (not usually reversible; see |abolish-coercion-reversible|)
For example, cru on a lowercase word is a slightly easier to type equivalent
to gUiw.
COERCION REVERSIBILITY *abolish-coercion-reversible*
Some separators, such as "-" and ".", are listed as "not usually reversible".
The reason is that these are not "keyword characters", so vim (and
abolish.vim) will treat them as breaking a word.
For example: "key_word" is a single keyword. The dash-case version,
"key-word", is treated as two keywords, "key" and "word".
This behaviour is governed by the 'iskeyword' option. If a separator appears
in 'iskeyword', the corresponding coercion will be reversible. For instance,
dash-case is reversible in 'lisp' files, and dot-case is reversible in R
files.
vim:tw=78:ts=8:ft=help:norl:

View file

@ -1,631 +0,0 @@
" abolish.vim - Language friendly searches, substitutions, and abbreviations
" Maintainer: Tim Pope <http://tpo.pe/>
" Version: 1.1
" GetLatestVimScripts: 1545 1 :AutoInstall: abolish.vim
" Initialization {{{1
if exists("g:loaded_abolish") || &cp || v:version < 700
finish
endif
let g:loaded_abolish = 1
if !exists("g:abolish_save_file")
if isdirectory(expand("~/.vim"))
let g:abolish_save_file = expand("~/.vim/after/plugin/abolish.vim")
elseif isdirectory(expand("~/vimfiles")) || has("win32")
let g:abolish_save_file = expand("~/vimfiles/after/plugin/abolish.vim")
else
let g:abolish_save_file = expand("~/.vim/after/plugin/abolish.vim")
endif
endif
" }}}1
" Utility functions {{{1
function! s:function(name)
return function(substitute(a:name,'^s:',matchstr(expand('<sfile>'), '<SNR>\d\+_'),''))
endfunction
function! s:send(self,func,...)
if type(a:func) == type('') || type(a:func) == type(0)
let Func = get(a:self,a:func,'')
else
let Func = a:func
endif
let s = type(a:self) == type({}) ? a:self : {}
if type(Func) == type(function('tr'))
return call(Func,a:000,s)
elseif type(Func) == type({}) && has_key(Func,'apply')
return call(Func.apply,a:000,Func)
elseif type(Func) == type({}) && has_key(Func,'call')
return call(Func.call,a:000,s)
elseif type(Func) == type('') && Func == '' && has_key(s,'function missing')
return call('s:send',[s,'function missing',a:func] + a:000)
else
return Func
endif
endfunction
let s:object = {}
function! s:object.clone(...)
let sub = deepcopy(self)
return a:0 ? extend(sub,a:1) : sub
endfunction
if !exists("g:Abolish")
let Abolish = {}
endif
call extend(Abolish, s:object, 'force')
call extend(Abolish, {'Coercions': {}}, 'keep')
function! s:throw(msg)
let v:errmsg = a:msg
throw "Abolish: ".a:msg
endfunction
function! s:words()
let words = []
let lnum = line('w0')
while lnum <= line('w$')
let line = getline(lnum)
let col = 0
while match(line,'\<\k\k\+\>',col) != -1
let words += [matchstr(line,'\<\k\k\+\>',col)]
let col = matchend(line,'\<\k\k\+\>',col)
endwhile
let lnum += 1
endwhile
return words
endfunction
function! s:extractopts(list,opts)
let i = 0
while i < len(a:list)
if a:list[i] =~ '^-[^=]' && has_key(a:opts,matchstr(a:list[i],'-\zs[^=]*'))
let key = matchstr(a:list[i],'-\zs[^=]*')
let value = matchstr(a:list[i],'=\zs.*')
if type(get(a:opts,key)) == type([])
let a:opts[key] += [value]
elseif type(get(a:opts,key)) == type(0)
let a:opts[key] = 1
else
let a:opts[key] = value
endif
else
let i += 1
continue
endif
call remove(a:list,i)
endwhile
return a:opts
endfunction
" }}}1
" Dictionary creation {{{1
function! s:mixedcase(word)
return substitute(s:camelcase(a:word),'^.','\u&','')
endfunction
function! s:camelcase(word)
let word = substitute(a:word, '-', '_', 'g')
if word !~# '_' && word =~# '\l'
return substitute(word,'^.','\l&','')
else
return substitute(word,'\C\(_\)\=\(.\)','\=submatch(1)==""?tolower(submatch(2)) : toupper(submatch(2))','g')
endif
endfunction
function! s:snakecase(word)
let word = substitute(a:word,'::','/','g')
let word = substitute(word,'\(\u\+\)\(\u\l\)','\1_\2','g')
let word = substitute(word,'\(\l\|\d\)\(\u\)','\1_\2','g')
let word = substitute(word,'[.-]','_','g')
let word = tolower(word)
return word
endfunction
function! s:uppercase(word)
return toupper(s:snakecase(a:word))
endfunction
function! s:dashcase(word)
return substitute(s:snakecase(a:word),'_','-','g')
endfunction
function! s:spacecase(word)
return substitute(s:snakecase(a:word),'_',' ','g')
endfunction
function! s:dotcase(word)
return substitute(s:snakecase(a:word),'_','.','g')
endfunction
function! s:titlecase(word)
return substitute(s:spacecase(a:word), '\(\<\w\)','\=toupper(submatch(1))','g')
endfunction
call extend(Abolish, {
\ 'camelcase': s:function('s:camelcase'),
\ 'mixedcase': s:function('s:mixedcase'),
\ 'snakecase': s:function('s:snakecase'),
\ 'uppercase': s:function('s:uppercase'),
\ 'dashcase': s:function('s:dashcase'),
\ 'dotcase': s:function('s:dotcase'),
\ 'spacecase': s:function('s:spacecase'),
\ 'titlecase': s:function('s:titlecase')
\ }, 'keep')
function! s:create_dictionary(lhs,rhs,opts)
let dictionary = {}
let i = 0
let expanded = s:expand_braces({a:lhs : a:rhs})
for [lhs,rhs] in items(expanded)
if get(a:opts,'case',1)
let dictionary[s:mixedcase(lhs)] = s:mixedcase(rhs)
let dictionary[tolower(lhs)] = tolower(rhs)
let dictionary[toupper(lhs)] = toupper(rhs)
endif
let dictionary[lhs] = rhs
endfor
let i += 1
return dictionary
endfunction
function! s:expand_braces(dict)
let new_dict = {}
for [key,val] in items(a:dict)
if key =~ '{.*}'
let redo = 1
let [all,kbefore,kmiddle,kafter;crap] = matchlist(key,'\(.\{-\}\){\(.\{-\}\)}\(.*\)')
let [all,vbefore,vmiddle,vafter;crap] = matchlist(val,'\(.\{-\}\){\(.\{-\}\)}\(.*\)') + ["","","",""]
if all == ""
let [vbefore,vmiddle,vafter] = [val, ",", ""]
endif
let targets = split(kmiddle,',',1)
let replacements = split(vmiddle,',',1)
if replacements == [""]
let replacements = targets
endif
for i in range(0,len(targets)-1)
let new_dict[kbefore.targets[i].kafter] = vbefore.replacements[i%len(replacements)].vafter
endfor
else
let new_dict[key] = val
endif
endfor
if exists("redo")
return s:expand_braces(new_dict)
else
return new_dict
endif
endfunction
" }}}1
" Abolish Dispatcher {{{1
function! s:SubComplete(A,L,P)
if a:A =~ '^[/?]\k\+$'
let char = strpart(a:A,0,1)
return join(map(s:words(),'char . v:val'),"\n")
elseif a:A =~# '^\k\+$'
return join(s:words(),"\n")
endif
endfunction
function! s:Complete(A,L,P)
let g:L = a:L
" Vim bug: :Abolish -<Tab> calls this function with a:A equal to 0
if a:A =~# '^[^/?-]' && type(a:A) != type(0)
return join(s:words(),"\n")
elseif a:L =~# '^\w\+\s\+\%(-\w*\)\=$'
return "-search\n-substitute\n-delete\n-buffer\n-cmdline\n"
elseif a:L =~# ' -\%(search\|substitute\)\>'
return "-flags="
else
return "-buffer\n-cmdline"
endif
endfunction
let s:commands = {}
let s:commands.abstract = s:object.clone()
function! s:commands.abstract.dispatch(bang,line1,line2,count,args)
return self.clone().go(a:bang,a:line1,a:line2,a:count,a:args)
endfunction
function! s:commands.abstract.go(bang,line1,line2,count,args)
let self.bang = a:bang
let self.line1 = a:line1
let self.line2 = a:line2
let self.count = a:count
return self.process(a:bang,a:line1,a:line2,a:count,a:args)
endfunction
function! s:dispatcher(bang,line1,line2,count,args)
let i = 0
let args = copy(a:args)
let command = s:commands.abbrev
while i < len(args)
if args[i] =~# '^-\w\+$' && has_key(s:commands,matchstr(args[i],'-\zs.*'))
let command = s:commands[matchstr(args[i],'-\zs.*')]
call remove(args,i)
break
endif
let i += 1
endwhile
try
return command.dispatch(a:bang,a:line1,a:line2,a:count,args)
catch /^Abolish: /
echohl ErrorMsg
echo v:errmsg
echohl NONE
return ""
endtry
endfunction
" }}}1
" Subvert Dispatcher {{{1
function! s:subvert_dispatcher(bang,line1,line2,count,args)
try
return s:parse_subvert(a:bang,a:line1,a:line2,a:count,a:args)
catch /^Subvert: /
echohl ErrorMsg
echo v:errmsg
echohl NONE
return ""
endtry
endfunction
function! s:parse_subvert(bang,line1,line2,count,args)
if a:args =~ '^\%(\w\|$\)'
let args = (a:bang ? "!" : "").a:args
else
let args = a:args
endif
let separator = matchstr(args,'^.')
let split = split(args,separator,1)[1:]
if a:count || split == [""]
return s:parse_substitute(a:bang,a:line1,a:line2,a:count,split)
elseif len(split) == 1
return s:find_command(separator,"",split[0])
elseif len(split) == 2 && split[1] =~# '^[A-Za-z]*n[A-Za-z]*$'
return s:parse_substitute(a:bang,a:line1,a:line2,a:count,[split[0],"",split[1]])
elseif len(split) == 2 && split[1] =~# '^[A-Za-z]*\%([+-]\d\+\)\=$'
return s:find_command(separator,split[1],split[0])
elseif len(split) >= 2 && split[1] =~# '^[A-Za-z]* '
let flags = matchstr(split[1],'^[A-Za-z]*')
let rest = matchstr(join(split[1:],separator),' \zs.*')
return s:grep_command(rest,a:bang,flags,split[0])
elseif len(split) >= 2 && separator == ' '
return s:grep_command(join(split[1:],' '),a:bang,"",split[0])
else
return s:parse_substitute(a:bang,a:line1,a:line2,a:count,split)
endif
endfunction
function! s:normalize_options(flags)
if type(a:flags) == type({})
let opts = a:flags
let flags = get(a:flags,"flags","")
else
let opts = {}
let flags = a:flags
endif
let g:op1 = copy(opts)
if flags =~# 'w'
let opts.boundaries = 2
elseif flags =~# 'v'
let opts.boundaries = 1
elseif !has_key(opts,'boundaries')
let opts.boundaries = 0
endif
let opts.case = (flags !~# 'I' ? get(opts,'case',1) : 0)
let opts.flags = substitute(flags,'\C[avIiw]','','g')
let g:op2 = copy(opts)
return opts
endfunction
" }}}1
" Searching {{{1
function! s:subesc(pattern)
return substitute(a:pattern,'[][\\/.*+?~%()&]','\\&','g')
endfunction
function! s:sort(a,b)
if a:a ==? a:b
return a:a == a:b ? 0 : a:a > a:b ? 1 : -1
elseif strlen(a:a) == strlen(a:b)
return a:a >? a:b ? 1 : -1
else
return strlen(a:a) < strlen(a:b) ? 1 : -1
endif
endfunction
function! s:pattern(dict,boundaries)
if a:boundaries == 2
let a = '<'
let b = '>'
elseif a:boundaries
let a = '%(<|_@<=|[[:lower:]]@<=[[:upper:]]@=)'
let b = '%(>|_@=|[[:lower:]]@<=[[:upper:]]@=)'
else
let a = ''
let b = ''
endif
return '\v\C'.a.'%('.join(map(sort(keys(a:dict),function('s:sort')),'s:subesc(v:val)'),'|').')'.b
endfunction
function! s:egrep_pattern(dict,boundaries)
if a:boundaries == 2
let a = '\<'
let b = '\>'
elseif a:boundaries
let a = '(\<\|_)'
let b = '(\>\|_\|[[:upper:]][[:lower:]])'
else
let a = ''
let b = ''
endif
return a.'('.join(map(sort(keys(a:dict),function('s:sort')),'s:subesc(v:val)'),'\|').')'.b
endfunction
function! s:c()
call histdel('search',-1)
return ""
endfunction
function! s:find_command(cmd,flags,word)
let opts = s:normalize_options(a:flags)
let dict = s:create_dictionary(a:word,"",opts)
" This is tricky. If we use :/pattern, the search drops us at the
" beginning of the line, and we can't use position flags (e.g., /foo/e).
" If we use :norm /pattern, we leave ourselves vulnerable to "press enter"
" prompts (even with :silent).
let cmd = (a:cmd =~ '[?!]' ? '?' : '/')
let @/ = s:pattern(dict,opts.boundaries)
if opts.flags == "" || !search(@/,'n')
return "norm! ".cmd."\<CR>"
elseif opts.flags =~ ';[/?]\@!'
call s:throw("E386: Expected '?' or '/' after ';'")
else
return "exe 'norm! ".cmd.cmd.opts.flags."\<CR>'|call histdel('search',-1)"
return ""
endif
endfunction
function! s:grep_command(args,bang,flags,word)
let opts = s:normalize_options(a:flags)
let dict = s:create_dictionary(a:word,"",opts)
if &grepprg == "internal"
let lhs = "'".s:pattern(dict,opts.boundaries)."'"
else
let lhs = "-E '".s:egrep_pattern(dict,opts.boundaries)."'"
endif
return "grep".(a:bang ? "!" : "")." ".lhs." ".a:args
endfunction
let s:commands.search = s:commands.abstract.clone()
let s:commands.search.options = {"word": 0, "variable": 0, "flags": ""}
function! s:commands.search.process(bang,line1,line2,count,args)
call s:extractopts(a:args,self.options)
if self.options.word
let self.options.flags .= "w"
elseif self.options.variable
let self.options.flags .= "v"
endif
let opts = s:normalize_options(self.options)
if len(a:args) > 1
return s:grep_command(join(a:args[1:]," "),a:bang,opts,a:args[0])
elseif len(a:args) == 1
return s:find_command(a:bang ? "!" : " ",opts,a:args[0])
else
call s:throw("E471: Argument required")
endif
endfunction
" }}}1
" Substitution {{{1
function! Abolished()
return get(g:abolish_last_dict,submatch(0),submatch(0))
endfunction
function! s:substitute_command(cmd,bad,good,flags)
let opts = s:normalize_options(a:flags)
let dict = s:create_dictionary(a:bad,a:good,opts)
let lhs = s:pattern(dict,opts.boundaries)
let g:abolish_last_dict = dict
return a:cmd.'/'.lhs.'/\=Abolished()'."/".opts.flags
endfunction
function! s:parse_substitute(bang,line1,line2,count,args)
if get(a:args,0,'') =~ '^[/?'']'
let separator = matchstr(a:args[0],'^.')
let args = split(join(a:args,' '),separator,1)
call remove(args,0)
else
let args = a:args
endif
if len(args) < 2
call s:throw("E471: Argument required")
elseif len(args) > 3
call s:throw("E488: Trailing characters")
endif
let [bad,good,flags] = (args + [""])[0:2]
if a:count == 0
let cmd = "substitute"
else
let cmd = a:line1.",".a:line2."substitute"
endif
return s:substitute_command(cmd,bad,good,flags)
endfunction
let s:commands.substitute = s:commands.abstract.clone()
let s:commands.substitute.options = {"word": 0, "variable": 0, "flags": "g"}
function! s:commands.substitute.process(bang,line1,line2,count,args)
call s:extractopts(a:args,self.options)
if self.options.word
let self.options.flags .= "w"
elseif self.options.variable
let self.options.flags .= "v"
endif
let opts = s:normalize_options(self.options)
if len(a:args) <= 1
call s:throw("E471: Argument required")
else
let good = join(a:args[1:],"")
let cmd = a:bang ? "." : "%"
return s:substitute_command(cmd,a:args[0],good,self.options)
endif
endfunction
" }}}1
" Abbreviations {{{1
function! s:badgood(args)
let words = filter(copy(a:args),'v:val !~ "^-"')
call filter(a:args,'v:val =~ "^-"')
if empty(words)
call s:throw("E471: Argument required")
elseif !empty(a:args)
call s:throw("Unknown argument: ".a:args[0])
endif
let [bad; words] = words
return [bad, join(words," ")]
endfunction
function! s:abbreviate_from_dict(cmd,dict)
for [lhs,rhs] in items(a:dict)
exe a:cmd lhs rhs
endfor
endfunction
let s:commands.abbrev = s:commands.abstract.clone()
let s:commands.abbrev.options = {"buffer":0,"cmdline":0,"delete":0}
function! s:commands.abbrev.process(bang,line1,line2,count,args)
let args = copy(a:args)
call s:extractopts(a:args,self.options)
if self.options.delete
let cmd = "unabbrev"
let good = ""
else
let cmd = "noreabbrev"
endif
if !self.options.cmdline
let cmd = "i" . cmd
endif
if self.options.delete
let cmd = "silent! ".cmd
endif
if self.options.buffer
let cmd = cmd . " <buffer>"
endif
let [bad, good] = s:badgood(a:args)
if substitute(bad,'{.\{-\}.}','','g') !~ '^\k\+$'
call s:throw("E474: Invalid argument (not a keyword: ".string(bad).")")
endif
if !self.options.delete && good == ""
call s:throw("E471: Argument required".a:args[0])
endif
let dict = s:create_dictionary(bad,good,self.options)
call s:abbreviate_from_dict(cmd,dict)
if a:bang
let i = 0
let str = "Abolish ".join(args," ")
let file = g:abolish_save_file
if !isdirectory(fnamemodify(file,':h'))
call mkdir(fnamemodify(file,':h'),'p')
endif
if filereadable(file)
let old = readfile(file)
else
let old = ["\" Exit if :Abolish isn't available.","if !exists(':Abolish')"," finish","endif",""]
endif
call writefile(old + [str],file)
endif
return ""
endfunction
let s:commands.delete = s:commands.abbrev.clone()
let s:commands.delete.options.delete = 1
" }}}1
" Maps {{{1
function! s:unknown_coercion(letter,word)
return a:word
endfunction
call extend(Abolish.Coercions, {
\ 'c': Abolish.camelcase,
\ 'm': Abolish.mixedcase,
\ 's': Abolish.snakecase,
\ '_': Abolish.snakecase,
\ 'u': Abolish.uppercase,
\ 'U': Abolish.uppercase,
\ '-': Abolish.dashcase,
\ 'k': Abolish.dashcase,
\ '.': Abolish.dotcase,
\ ' ': Abolish.spacecase,
\ 't': Abolish.titlecase,
\ "function missing": s:function("s:unknown_coercion")
\}, "keep")
function! s:coerce(transformation)
let clipboard = &clipboard
try
set clipboard=
let regbody = getreg('"')
let regtype = getregtype('"')
let c = v:count1
while c > 0
let c -= 1
norm! yiw
let word = @@
let @@ = s:send(g:Abolish.Coercions,a:transformation,word)
if !exists('begin')
let begin = getpos("'[")
endif
if word !=# @@
let changed = 1
norm! viwpw
else
norm! w
endif
endwhile
call setreg('"',regbody,regtype)
call setpos("'[",begin)
call setpos(".",begin)
if exists("changed")
silent! call repeat#set("\<Plug>Coerce".a:transformation)
endif
finally
let &clipboard = clipboard
endtry
endfunction
nnoremap <silent> <Plug>Coerce :<C-U>call <SID>coerce(nr2char(getchar()))<CR>
" }}}1
if !exists("g:abolish_no_mappings") || ! g:abolish_no_mappings
nmap cr <Plug>Coerce
endif
command! -nargs=+ -bang -bar -range=0 -complete=custom,s:Complete Abolish
\ :exec s:dispatcher(<bang>0,<line1>,<line2>,<count>,[<f-args>])
command! -nargs=1 -bang -bar -range=0 -complete=custom,s:SubComplete Subvert
\ :exec s:subvert_dispatcher(<bang>0,<line1>,<line2>,<count>,<q-args>)
if exists(':S') != 2
command -nargs=1 -bang -bar -range=0 -complete=custom,s:SubComplete S
\ :exec s:subvert_dispatcher(<bang>0,<line1>,<line2>,<count>,<q-args>)
endif
" vim:set ft=vim sw=2 sts=2:

View file

@ -20,7 +20,7 @@ changed, or `o` to open it in a split. When you're done, use `:Gedit`
in the historic buffer to go back to the work tree version.
`:Gmove` does a `git mv` on a file and simultaneously renames the
buffer. `:Gremove` does a `git rm` on a file and simultaneously deletes
buffer. `:Gdelete` does a `git rm` on a file and simultaneously deletes
the buffer.
Use `:Ggrep` to search the work tree (or any arbitrary commit) with

View file

@ -40,6 +40,7 @@ that are part of Git repositories).
<CR> |:Gedit|
- |:Git| add
- |:Git| reset (staged files)
a Show alternative format
cA |:Gcommit| --amend --reuse-message=HEAD
ca |:Gcommit| --amend
cc |:Gcommit|
@ -197,12 +198,15 @@ that are part of Git repositories).
directory except when started with a /, in which case
it is relative to the work tree. Add a ! to pass -f.
*fugitive-:Gremove*
:Gremove Wrapper around git-rm that deletes the buffer
*fugitive-:Gdelete*
:Gdelete Wrapper around git-rm that deletes the buffer
afterward. When invoked in an index file, --cached is
passed. Add a ! to pass -f and forcefully discard the
buffer.
*fugitive-:Gremove*
:Gremove Like :Gdelete, but keep the (now empty) buffer around.
*fugitive-:Gblame*
:Gblame [flags] Run git-blame on the file and open the results in a
scroll bound vertical split. You can give any of

View file

@ -68,6 +68,15 @@ function! s:shellslash(path) abort
endif
endfunction
let s:executables = {}
function! s:executable(binary) abort
if !has_key(s:executables, a:binary)
let s:executables[a:binary] = executable(a:binary)
endif
return s:executables[a:binary]
endfunction
let s:git_versions = {}
function! s:git_command() abort
@ -400,13 +409,13 @@ function! s:repo_git_chomp(...) dict abort
endfunction
function! s:repo_git_chomp_in_tree(...) dict abort
let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd '
let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd' : 'cd'
let dir = getcwd()
try
execute cd.'`=s:repo().tree()`'
execute cd s:fnameescape(s:repo().tree())
return call(s:repo().git_chomp, a:000, s:repo())
finally
execute cd.'`=dir`'
execute cd s:fnameescape(dir)
endtry
endfunction
@ -696,13 +705,13 @@ call s:add_methods('buffer',['getvar','setvar','getline','repo','type','spec','n
call s:command("-bang -nargs=? -complete=customlist,s:GitComplete Git :execute s:Git(<bang>0,<q-args>)")
function! s:ExecuteInTree(cmd) abort
let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd '
let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd' : 'cd'
let dir = getcwd()
try
execute cd.'`=s:repo().tree()`'
execute cd s:fnameescape(s:repo().tree())
execute a:cmd
finally
execute cd.'`=dir`'
execute cd s:fnameescape(dir)
endtry
endfunction
@ -756,8 +765,8 @@ function! s:DirComplete(A,L,P) abort
return matches
endfunction
call s:command("-bar -bang -nargs=? -complete=customlist,s:DirComplete Gcd :cd<bang> `=s:repo().bare() ? s:repo().dir(<q-args>) : s:repo().tree(<q-args>)`")
call s:command("-bar -bang -nargs=? -complete=customlist,s:DirComplete Glcd :lcd<bang> `=s:repo().bare() ? s:repo().dir(<q-args>) : s:repo().tree(<q-args>)`")
call s:command("-bar -bang -nargs=? -complete=customlist,s:DirComplete Gcd :exe 'cd<bang>' s:fnameescape(s:repo().bare() ? s:repo().dir(<q-args>) : s:repo().tree(<q-args>))")
call s:command("-bar -bang -nargs=? -complete=customlist,s:DirComplete Glcd :exe 'lcd<bang>' s:fnameescape(s:repo().bare() ? s:repo().dir(<q-args>) : s:repo().tree(<q-args>))")
" Section: Gstatus
@ -1057,14 +1066,14 @@ call s:command("-nargs=? -complete=customlist,s:CommitComplete Gcommit :execute
function! s:Commit(args, ...) abort
let repo = a:0 ? a:1 : s:repo()
let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd '
let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd' : 'cd'
let dir = getcwd()
let msgfile = repo.dir('COMMIT_EDITMSG')
let outfile = tempname()
let errorfile = tempname()
try
try
execute cd.s:fnameescape(repo.tree())
execute cd s:fnameescape(repo.tree())
if s:winshell()
let command = ''
let old_editor = $GIT_EDITOR
@ -1082,7 +1091,7 @@ function! s:Commit(args, ...) abort
endif
let error = v:shell_error
finally
execute cd.'`=dir`'
execute cd s:fnameescape(dir)
endtry
if !has('gui_running')
redraw!
@ -1292,10 +1301,10 @@ call s:command("-bar -bang -nargs=* -range=0 -complete=customlist,s:EditComplete
function! s:Grep(cmd,bang,arg) abort
let grepprg = &grepprg
let grepformat = &grepformat
let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd '
let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd' : 'cd'
let dir = getcwd()
try
execute cd.'`=s:repo().tree()`'
execute cd s:fnameescape(s:repo().tree())
let &grepprg = s:repo().git_command('--no-pager', 'grep', '-n', '--no-color')
let &grepformat = '%f:%l:%m,%m %f match%ts,%f'
exe a:cmd.'! '.escape(matchstr(a:arg,'\v\C.{-}%($|[''" ]\@=\|)@='),'|')
@ -1324,7 +1333,7 @@ function! s:Grep(cmd,bang,arg) abort
finally
let &grepprg = grepprg
let &grepformat = grepformat
execute cd.'`=dir`'
execute cd s:fnameescape(dir)
endtry
endfunction
@ -1352,17 +1361,17 @@ function! s:Log(cmd, line1, line2, ...) abort
endif
let grepformat = &grepformat
let grepprg = &grepprg
let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd '
let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd' : 'cd'
let dir = getcwd()
try
execute cd.'`=s:repo().tree()`'
execute cd s:fnameescape(s:repo().tree())
let &grepprg = escape(call(s:repo().git_command,cmd,s:repo()),'%#')
let &grepformat = '%Cdiff %.%#,%C--- %.%#,%C+++ %.%#,%Z@@ -%\d%\+\,%\d%\+ +%l\,%\d%\+ @@,%-G-%.%#,%-G+%.%#,%-G %.%#,%A%f::%m,%-G%.%#'
exe a:cmd
finally
let &grepformat = grepformat
let &grepprg = grepprg
execute cd.'`=dir`'
execute cd s:fnameescape(dir)
endtry
endfunction
@ -1803,12 +1812,12 @@ function! s:Diff(vert,keepfocus,...) abort
elseif (empty(args) || args[0] == ':') && s:buffer().commit() =~# '^[0-1]\=$' && s:repo().git_chomp_in_tree('ls-files', '--unmerged', '--', s:buffer().path()) !=# ''
let vert = empty(a:vert) ? s:diff_modifier(3) : a:vert
let nr = bufnr('')
execute 'leftabove '.vert.'split `=fugitive#buffer().repo().translate(s:buffer().expand('':2''))`'
execute 'leftabove '.vert.'split' s:fnameescape(fugitive#repo().translate(s:buffer().expand(':2')))
execute 'nnoremap <buffer> <silent> dp :diffput '.nr.'<Bar>diffupdate<CR>'
let nr2 = bufnr('')
call s:diffthis()
wincmd p
execute 'rightbelow '.vert.'split `=fugitive#buffer().repo().translate(s:buffer().expand('':3''))`'
execute 'rightbelow '.vert.'split' s:fnameescape(fugitive#repo().translate(s:buffer().expand(':3')))
execute 'nnoremap <buffer> <silent> dp :diffput '.nr.'<Bar>diffupdate<CR>'
let nr3 = bufnr('')
call s:diffthis()
@ -1915,7 +1924,7 @@ function! s:MoveComplete(A,L,P) abort
endif
endfunction
function! s:Remove(force) abort
function! s:Remove(after, force) abort
if s:buffer().commit() ==# ''
let cmd = ['rm']
elseif s:buffer().commit() ==# '0'
@ -1933,7 +1942,7 @@ function! s:Remove(force) abort
return 'echoerr '.string(v:errmsg)
else
call fugitive#reload_status()
return 'edit'.(a:force ? '!' : '')
return a:after . (a:force ? '!' : '')
endif
endfunction
@ -1941,7 +1950,8 @@ augroup fugitive_remove
autocmd!
autocmd User Fugitive if s:buffer().commit() =~# '^0\=$' |
\ exe "command! -buffer -bar -bang -nargs=1 -complete=customlist,s:MoveComplete Gmove :execute s:Move(<bang>0,<q-args>)" |
\ exe "command! -buffer -bar -bang Gremove :execute s:Remove(<bang>0)" |
\ exe "command! -buffer -bar -bang Gremove :execute s:Remove('edit',<bang>0)" |
\ exe "command! -buffer -bar -bang Gdelete :execute s:Remove('bdelete',<bang>0)" |
\ endif
augroup END
@ -1987,10 +1997,10 @@ function! s:Blame(bang,line1,line2,count,args) abort
let cmd += ['--', s:buffer().path()]
let basecmd = escape(call(s:repo().git_command,cmd,s:repo()),'!')
try
let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd '
let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd' : 'cd'
if !s:repo().bare()
let dir = getcwd()
execute cd.'`=s:repo().tree()`'
execute cd s:fnameescape(s:repo().tree())
endif
if a:count
execute 'write !'.substitute(basecmd,' blame ',' blame -L '.a:line1.','.a:line2.' ','g')
@ -2003,7 +2013,7 @@ function! s:Blame(bang,line1,line2,count,args) abort
silent! execute '%write !'.basecmd.' > '.temp.' 2> '.error
endif
if exists('l:dir')
execute cd.'`=dir`'
execute cd s:fnameescape(dir)
unlet dir
endif
if v:shell_error
@ -2076,7 +2086,7 @@ function! s:Blame(bang,line1,line2,count,args) abort
endif
finally
if exists('l:dir')
execute cd.'`=dir`'
execute cd s:fnameescape(dir)
endif
endtry
return ''
@ -2170,8 +2180,8 @@ function! s:BlameSyntax() abort
let arg = exists('b:fugitive_blame_arguments') ? b:fugitive_blame_arguments : ''
syn match FugitiveblameBoundary "^\^"
syn match FugitiveblameBlank "^\s\+\s\@=" nextgroup=FugitiveblameAnnotation,fugitiveblameOriginalFile,FugitiveblameOriginalLineNumber skipwhite
syn match FugitiveblameHash "\%(^\^\=\)\@<=\x\{7,40\}\>" nextgroup=FugitiveblameAnnotation,FugitiveblameOriginalLineNumber,fugitiveblameOriginalFile skipwhite
syn match FugitiveblameUncommitted "\%(^\^\=\)\@<=0\{7,40\}\>" nextgroup=FugitiveblameAnnotation,FugitiveblameOriginalLineNumber,fugitiveblameOriginalFile skipwhite
syn match FugitiveblameHash "\%(^\^\=\)\@<=\<\x\{7,40\}\>" nextgroup=FugitiveblameAnnotation,FugitiveblameOriginalLineNumber,fugitiveblameOriginalFile skipwhite
syn match FugitiveblameUncommitted "\%(^\^\=\)\@<=\<0\{7,40\}\>" nextgroup=FugitiveblameAnnotation,FugitiveblameOriginalLineNumber,fugitiveblameOriginalFile skipwhite
syn region FugitiveblameAnnotation matchgroup=FugitiveblameDelimiter start="(" end="\%( \d\+\)\@<=)" contained keepend oneline
syn match FugitiveblameTime "[0-9:/+-][0-9:/+ -]*[0-9:/+-]\%( \+\d\+)\)\@=" contained containedin=FugitiveblameAnnotation
exec 'syn match FugitiveblameLineNumber " *\d\+)\@=" contained containedin=FugitiveblameAnnotation'.conceal
@ -2197,7 +2207,7 @@ function! s:BlameSyntax() abort
continue
endif
let seen[hash] = 1
if &t_Co > 16 && exists('g:CSApprox_loaded')
if &t_Co > 16 && get(g:, 'CSApprox_loaded') && !empty(findfile('autoload/csapprox/per_component.vim', escape(&rtp, ' ')))
\ && empty(get(s:hash_colors, hash))
let [s, r, g, b; __] = map(matchlist(hash, '\(\x\x\)\(\x\x\)\(\x\x\)'), 'str2nr(v:val,16)')
let color = csapprox#per_component#Approximate(r, g, b)
@ -2227,6 +2237,8 @@ endfunction
call s:command("-bar -bang -range=0 -nargs=* -complete=customlist,s:EditComplete Gbrowse :execute s:Browse(<bang>0,<line1>,<count>,<f-args>)")
let s:redirects = {}
function! s:Browse(bang,line1,count,...) abort
try
let validremote = '\.\|\.\=/.*\|[[:alnum:]_-]\+\%(://.\{-\}\)\='
@ -2332,7 +2344,7 @@ function! s:Browse(bang,line1,count,...) abort
else
let remote_for_url = remote
endif
if fugitive#git_version() =~# '^[01]\.|^2\.[0-6]\.'
if fugitive#git_version() =~# '^[01]\.\|^2\.[0-6]\.'
let raw = s:repo().git_chomp('config','remote.'.remote_for_url.'.url')
else
let raw = s:repo().git_chomp('remote','get-url',remote_for_url)
@ -2341,6 +2353,17 @@ function! s:Browse(bang,line1,count,...) abort
let raw = remote
endif
if raw =~# '^https\=://' && s:executable('curl')
if !has_key(s:redirects, raw)
let s:redirects[raw] = matchstr(system('curl -I ' .
\ s:shellesc(raw . '/info/refs?service=git-upload-pack')),
\ 'Location: \zs\S\+\ze/info/refs?')
endif
if len(s:redirects[raw])
let raw = s:redirects[raw]
endif
endif
for Handler in g:fugitive_browse_handlers
let url = call(Handler, [{
\ 'repo': s:repo(),
@ -2517,7 +2540,7 @@ function! s:BufReadIndex() abort
call s:ReplaceCmd(s:repo().git_command('ls-files','--stage'),index)
set ft=git nospell
else
let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd '
let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd' : 'cd'
let dir = getcwd()
if fugitive#git_version() =~# '^0\|^1\.[1-7]\.'
let cmd = s:repo().git_command('status')
@ -2529,10 +2552,10 @@ function! s:BufReadIndex() abort
\ 'status')
endif
try
execute cd.'`=s:repo().tree()`'
execute cd s:fnameescape(s:repo().tree())
call s:ReplaceCmd(cmd, index)
finally
execute cd.'`=dir`'
execute cd s:fnameescape(dir)
endtry
set ft=gitcommit
set foldtext=fugitive#foldtext()

View file

@ -529,6 +529,10 @@ Here are some things you can check:
* Your file is being tracked by git and has unstaged changes.
* If you have aliased or configured `grep` to use any flags, add `let g:gitgutter_grep_command = 'grep'` to your `~/.vimrc`.
> Why is the whole file marked as added when I edit it?
* If you use zsh, and you set `CDPATH`, make sure `CDPATH` doesn't include the current directory.
### Shameless Plug

View file

@ -1,8 +1,44 @@
## unplanned
IMPROVEMENTS
* Files created with `_test.go` extension have a new template with a ready to go test function. The template can be changed with the `g:go_template_test_file` setting. [gh-1318]
* Improve performance for highly used operations by caching `go env` calls [gh-1320]
* `:GoCoverage` can accept arguments now. i.e: `:GoCoverage -run TestFoo` [gh-1326]
* `:GoDecls` and `:GoDeclsDir` shows a warning if [ctrlp.vim](https://github.com/ctrlpvim/ctrlp.vim) is not installed
* `:GoBuild` now compiles the package with the `-i` flag added. This means that subsequent calls are much more faster due caching of packages [gh-1330]
* `:GoCoverage` echos now the progress if `g:go_echo_command_info` is enabled [gh-1333]
* Add `g:go_doc_max_height` setting to control the maximum height of the window created by `:GoDoc` and `K` mapping [gh-1335]
BUG FIXES:
* Fix obtaining package's import path for the current directory. This fixes some issues we had if the user was using multiple GOPATH's [gh-1321]
* Fix documentation for vim-go & syntastic integration for errcheck using [gh-1323]
* Fix showing an output if a test has finished when `:GoTest` is called [gh-1327]
## 1.13 - (June 6, 2017)
FEATURES:
* New `:GoKeyify` command that turns unkeyed struct literals into keyed struct literals. [gh-1258]
* New `:GoKeyify` command that turns unkeyed struct literals into keyed struct literals. [gh-1258]. i.e:
```
Example{"foo", "bar", "qux"}
```
will be converted to:
```
Example{
foo: "foo",
bar: "bar",
qux: "qux",
}
```
Checkout the demo here: https://twitter.com/fatih/status/860410299714764802
* New `g:go_addtags_transform` setting to change the transform rule (snakecase, camelcase, etc..) for `:GoAddTags` command [gh-1275]
* New snippet shortcut assigned to `ife` that expands to `if err := foo(); err != nil { ... }` [gh-1268]
@ -10,6 +46,18 @@ IMPROVEMENTS
* :GoMetaLinter can now exclude linters with the new `g:go_metalinter_excludes` option [gh-1253]
* Override `<C-LeftMouse>` mapping so `:GoDef` is used by default (as we do the same for `CTRL-]`, `gd`, etc. [gh-1264]
* add support for `go_list_type` setting in `:GoFmt` and `:GoImports` commands [gh-1304]
* add support for `go_list_type` setting in `:GoMetaLinter` commands [gh-1309]
* `go_fmt_options` can be now a dictionary to allow us to specifcy the
options for multiple binaries [gh-1308]. i.e:
```
let g:go_fmt_options = {
\ 'gofmt': '-s',
\ 'goimports': '-local mycompany.com',
\ }
```
* If win-vim(x64) with Cygwin is used, `cygpath` is used for constructing the paths [gh-1092]
BUG FIXES:
@ -17,11 +65,23 @@ BUG FIXES:
* internal: fix system calls when using tcsh [gh-1276]
* path: return the unmodified GOPATH if autodetect is disabled [gh-1280]
* fix jumping to quickfix window when autom gometalinter on save was enabled [gh-1293]
* fix highlighting for `interface` and `structs` words when `go_highlight_types` is enabled [gh-1301]
* fix cwd for running `:GoRun` when used with neovim [gh-1296]
* `:GoFmt` handles files that are symlinked into GOPATH better (note that this behaviour is discouraged, but we're trying our best to handle all edge case :)) [gh-1310]
* `:GoTest` is able to parse error messages that include a colon `:` [gh-1316]
* `:GoTestCompile` under the hood doesn't produces a test binary anymore. Sometimes a race condition would happen which would not delete the test binary. [gh-1317]
* `:GoDef` jumps now to definition for build tags defined with `:GoBuildTags` (only guru) [gh-1319]
BACKWARDS INCOMPATIBILITIES:
* `:GoLint` works on the whole directory instead of the current file. To use it for the current file give it as an argument, i.e `:GoLint foo.go` [gh-1295]
* `go_snippet_case_type` is removed in favor of the new `go_addtags_transform` setting [gh-1299]
* `go_imports_bin` is removed to avoid confusion as it would lead to race
conditions when set to `gofmt` along with the usage of `go_fmt_command`
[gh-1212] [gh-1308]
* commands such as `:GoTest` has been refactored for easy maintainability. If
you use any custom script that was using the function `go#cmd#Test`, it
should be renamed to `go#test#Test`
## 1.12 - (March 29, 2017)
@ -67,7 +127,7 @@ BUG FIXES:
* Fix `:GoAddTags` to allow modifying existing comments [gh-984]
* Fix `:GoAddTags` to work with nested structs [gh-990]
* Fix `:GoAddTags` adding tags twice for existing tags [gh-1064]
* Fix `:GoAddTags` not working for fiels of types `interface{}` [gh-1091]
* Fix `:GoAddTags` not working for fields of types `interface{}` [gh-1091]
* Fix `:GoAddTags` not working for fields with one line comments [gh-1181]
* Fix `:GoAddTags` not working if any field comment would contain `{}` [gh-1189]
* Respect go_fmt_options when running goimports [gh-1211]
@ -252,7 +312,7 @@ IMPROVEMENTS:
`:GoDef`, `:GoReferrers`, etc.. [gh-944]
* **:GoDoc** uses now the `-modified` flag under the hood (for `gogetdoc), which allows us to get documentation for the identifier under the cursor ina modified buffer. [gh-1014]
* Cleanup and improve documentation [gh-987]
* Add new `g:go_gocode_socket_type` setting to change the underlying socket type passed to `gocode`. Usefull to fallback to `tcp` on cases such as Bash on Windows [gh-1000]
* Add new `g:go_gocode_socket_type` setting to change the underlying socket type passed to `gocode`. Useful to fallback to `tcp` on cases such as Bash on Windows [gh-1000]
* `:GoSameIds` is now automatically re-evaluated in cases of buffer reloads (such as `:GoRename`) [gh-998]
* Improve docs about `go_auto_sameids` [gh-1017]
* Improve error message by printing the full path if an incompatible `goimports` is being used [gh-1006]
@ -352,7 +412,7 @@ IMPROVEMENTS:
BUG FIXES:
* Fix `(go-freevars)` plug mapping to work as in visual mode instead of noncompatible normal mode [gh-832]
* Commands based on guru now shows a more meaningful error message instead of just showing the exit status (-1)
* Fix `:GoCoverage` accidently enabling syntax highlighting for users who don't use syntax (i.e syntax off) [gh-827]
* Fix `:GoCoverage` accidentally enabling syntax highlighting for users who don't use syntax (i.e syntax off) [gh-827]
* Fix `:GoCoverage` colors to work for xterm as well [gh-863]
* Fix commenting out block of texts for Go templates (filetype gothtmltmpl) [gh-813]
* Fix `:GoImplements` failing because of an empty scope definition. Now we default to current package to make it usable.

View file

@ -4,7 +4,7 @@ function! go#cmd#autowrite() abort
endif
endfunction
" Build builds the source code without producting any output binary. We live in
" Build builds the source code without producing any output binary. We live in
" an editor so the best is to build it to catch errors and fix them. By
" default it tries to call simply 'go build', but it first tries to get all
" dependent files for the current folder and passes it to go build.
@ -18,8 +18,10 @@ function! go#cmd#Build(bang, ...) abort
endif
" create our command arguments. go build discards any results when it
" compiles multiple packages. So we pass the `errors` package just as an
" placeholder with the current folder (indicated with '.')
let args = ["build"] + goargs + [".", "errors"]
" placeholder with the current folder (indicated with '.'). We also pass -i
" that tries to install the dependencies, this has the side effect that it
" caches the build results, so every other build is faster.
let args = ["build"] + goargs + ["-i", ".", "errors"]
if go#util#has_job()
if get(g:, 'go_echo_command_info', 1)
@ -109,7 +111,7 @@ function! go#cmd#RunTerm(bang, mode, files) abort
endfunction
" Run runs the current file (and their dependencies if any) and outputs it.
" This is intented to test small programs and play with them. It's not
" This is intended to test small programs and play with them. It's not
" suitable for long running apps, because vim is blocking by default and
" calling long running apps will block the whole UI.
function! go#cmd#Run(bang, ...) abort
@ -225,145 +227,6 @@ function! go#cmd#Install(bang, ...) abort
let &makeprg = default_makeprg
endfunction
" Test runs `go test` in the current directory. If compile is true, it'll
" compile the tests instead of running them (useful to catch errors in the
" test files). Any other argument is appendend to the final `go test` command
function! go#cmd#Test(bang, compile, ...) abort
let args = ["test"]
" don't run the test, only compile it. Useful to capture and fix errors.
if a:compile
let compile_file = "vim-go-test-compile"
call extend(args, ["-c", "-o", compile_file])
endif
if a:0
let goargs = a:000
" do not expand for coverage mode as we're passing the arg ourself
if a:1 != '-coverprofile'
" expand all wildcards(i.e: '%' to the current file name)
let goargs = map(copy(a:000), "expand(v:val)")
endif
if !(has('nvim') || go#util#has_job())
let goargs = go#util#Shelllist(goargs, 1)
endif
call extend(args, goargs, 1)
else
" only add this if no custom flags are passed
let timeout = get(g:, 'go_test_timeout', '10s')
call add(args, printf("-timeout=%s", timeout))
endif
if get(g:, 'go_echo_command_info', 1)
if a:compile
echon "vim-go: " | echohl Identifier | echon "compiling tests ..." | echohl None
else
echon "vim-go: " | echohl Identifier | echon "testing ..." | echohl None
endif
endif
if go#util#has_job()
" use vim's job functionality to call it asynchronously
let job_args = {
\ 'cmd': ['go'] + args,
\ 'bang': a:bang,
\ }
if a:compile
let job_args['custom_cb'] = function('s:test_compile', [compile_file])
endif
call s:cmd_job(job_args)
return
elseif has('nvim')
" use nvims's job functionality
if get(g:, 'go_term_enabled', 0)
let id = go#term#new(a:bang, ["go"] + args)
else
let id = go#jobcontrol#Spawn(a:bang, "test", args)
endif
if a:compile
call go#jobcontrol#AddHandler(function('s:test_compile_handler'))
let s:test_compile_handlers[id] = compile_file
endif
return id
endif
call go#cmd#autowrite()
redraw
let command = "go " . join(args, ' ')
let out = go#tool#ExecuteInDir(command)
let l:listtype = "quickfix"
let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd '
let dir = getcwd()
execute cd fnameescape(expand("%:p:h"))
if a:compile
call delete(compile_file)
endif
if go#util#ShellError() != 0
let errors = go#tool#ParseErrors(split(out, '\n'))
let errors = go#tool#FilterValids(errors)
call go#list#Populate(l:listtype, errors, command)
call go#list#Window(l:listtype, len(errors))
if !empty(errors) && !a:bang
call go#list#JumpToFirst(l:listtype)
elseif empty(errors)
" failed to parse errors, output the original content
call go#util#EchoError(out)
endif
echon "vim-go: " | echohl ErrorMsg | echon "[test] FAIL" | echohl None
else
call go#list#Clean(l:listtype)
call go#list#Window(l:listtype)
if a:compile
echon "vim-go: " | echohl Function | echon "[test] SUCCESS" | echohl None
else
echon "vim-go: " | echohl Function | echon "[test] PASS" | echohl None
endif
endif
execute cd . fnameescape(dir)
endfunction
" Testfunc runs a single test that surrounds the current cursor position.
" Arguments are passed to the `go test` command.
function! go#cmd#TestFunc(bang, ...) abort
" search flags legend (used only)
" 'b' search backward instead of forward
" 'c' accept a match at the cursor position
" 'n' do Not move the cursor
" 'W' don't wrap around the end of the file
"
" for the full list
" :help search
let test = search('func \(Test\|Example\)', "bcnW")
if test == 0
echo "vim-go: [test] no test found immediate to cursor"
return
end
let line = getline(test)
let name = split(split(line, " ")[1], "(")[0]
let args = [a:bang, 0, "-run", name . "$"]
if a:0
call extend(args, a:000)
endif
call call('go#cmd#Test', args)
endfunction
" Generate runs 'go generate' in similar fashion to go#cmd#Build()
function! go#cmd#Generate(bang, ...) abort
let default_makeprg = &makeprg
@ -465,24 +328,4 @@ function s:cmd_job(args) abort
let $GOPATH = old_gopath
endfunction
" test_compile is called when a GoTestCompile call is finished
function! s:test_compile(test_file, job, exit_status, data) abort
call delete(a:test_file)
endfunction
" -----------------------
" | Neovim job handlers |
" -----------------------
let s:test_compile_handlers = {}
function! s:test_compile_handler(job, exit_status, data) abort
if !has_key(s:test_compile_handlers, a:job.id)
return
endif
let l:compile_file = s:test_compile_handlers[a:job.id]
call delete(l:compile_file)
unlet s:test_compile_handlers[a:job.id]
endfunction
" vim: sw=2 ts=2 et

View file

@ -103,7 +103,7 @@ function! go#complete#GetInfo() abort
return ""
endif
" only one candiate is found
" only one candidate is found
if len(out) == 2
return split(out[1], ',,')[0]
endif

View file

@ -17,7 +17,7 @@ function! go#coverage#BufferToggle(bang, ...) abort
endfunction
" Buffer creates a new cover profile with 'go test -coverprofile' and changes
" teh current buffers highlighting to show covered and uncovered sections of
" the current buffers highlighting to show covered and uncovered sections of
" the code. Calling it again reruns the tests and shows the last updated
" coverage.
function! go#coverage#Buffer(bang, ...) abort
@ -44,9 +44,13 @@ function! go#coverage#Buffer(bang, ...) abort
let s:toggle = 1
let l:tmpname = tempname()
if get(g:, 'go_echo_command_info', 1)
echon "vim-go: " | echohl Identifier | echon "testing ..." | echohl None
endif
if go#util#has_job()
call s:coverage_job({
\ 'cmd': ['go', 'test', '-coverprofile', l:tmpname],
\ 'cmd': ['go', 'test', '-coverprofile', l:tmpname] + a:000,
\ 'custom_cb': function('s:coverage_callback', [l:tmpname]),
\ 'bang': a:bang,
\ })
@ -64,7 +68,7 @@ function! go#coverage#Buffer(bang, ...) abort
let g:go_term_enabled = 0
endif
let id = call('go#cmd#Test', args)
let id = call('go#test#Test', args)
if disabled_term
let g:go_term_enabled = 1
@ -113,7 +117,7 @@ function! go#coverage#Browser(bang, ...) abort
call extend(args, a:000)
endif
let id = call('go#cmd#Test', args)
let id = call('go#test#Test', args)
if has('nvim')
call go#jobcontrol#AddHandler(function('s:coverage_browser_handler'))
let s:coverage_browser_handler_jobs[id] = l:tmpname
@ -212,7 +216,7 @@ function! go#coverage#overlay(file) abort
" first mark all lines as goCoverageNormalText. We use a custom group to not
" interfere with other buffers highlightings. Because the priority is
" lower than the cover and uncover matches, it'll be overriden.
" lower than the cover and uncover matches, it'll be overridden.
let cnt = 1
while cnt <= line('$')
call add(matches, {'group': 'goCoverageNormalText', 'pos': [cnt], 'priority': 1})

View file

@ -46,8 +46,8 @@ function! go#def#Jump(mode) abort
call add(cmd, "-modified")
endif
if exists('g:go_guru_tags')
let tags = get(g:, 'go_guru_tags')
if exists('g:go_build_tags')
let tags = get(g:, 'go_build_tags')
call extend(cmd, ["-tags", tags])
endif

View file

@ -93,8 +93,8 @@ function! s:GodocView(newposition, position, content) abort
endif
if a:position == "split"
" cap buffer height to 20, but resize it for smaller contents
let max_height = 20
" cap window height to 20, but resize it for smaller contents
let max_height = get(g:, "go_doc_max_height", 20)
let content_height = len(split(a:content, "\n"))
if content_height > max_height
exe 'resize ' . max_height

View file

@ -9,18 +9,14 @@ if !exists("g:go_fmt_command")
let g:go_fmt_command = "gofmt"
endif
if !exists("g:go_goimports_bin")
let g:go_goimports_bin = "goimports"
if !exists('g:go_fmt_options')
let g:go_fmt_options = ''
endif
if !exists('g:go_fmt_fail_silently')
let g:go_fmt_fail_silently = 0
endif
if !exists('g:go_fmt_options')
let g:go_fmt_options = ''
endif
if !exists("g:go_fmt_experimental")
let g:go_fmt_experimental = 0
endif
@ -70,7 +66,7 @@ function! go#fmt#Format(withGoimport) abort
let bin_name = g:go_fmt_command
if a:withGoimport == 1
let bin_name = g:go_goimports_bin
let bin_name = "goimports"
endif
let out = go#fmt#run(bin_name, l:tmpname, expand('%'))
@ -172,7 +168,15 @@ function! s:fmt_cmd(bin_name, source, target)
" start constructing the command
let cmd = [bin_path]
call add(cmd, "-w")
call extend(cmd, split(g:go_fmt_options, " "))
" add the options for binary (if any). go_fmt_options was by default of type
" string, however to allow customization it's now a dictionary of binary
" name mapping to options.
let opts = g:go_fmt_options
if type(g:go_fmt_options) == type({})
let opts = has_key(g:go_fmt_options, a:bin_name) ? g:go_fmt_options[a:bin_name] : ""
endif
call extend(cmd, split(opts, " "))
if a:bin_name == "goimports"
" lazy check if goimports support `-srcdir`. We should eventually remove
@ -189,7 +193,9 @@ function! s:fmt_cmd(bin_name, source, target)
if exists('b:goimports_vendor_compatible') && b:goimports_vendor_compatible
let ssl_save = &shellslash
set noshellslash
call extend(cmd, ["-srcdir", shellescape(fnamemodify(a:target, ":p"))])
" use the filename without the fully qualified name if the tree is
" symlinked into the GOPATH, goimports won't work properly.
call extend(cmd, ["-srcdir", shellescape(a:target)])
let &shellslash = ssl_save
endif
endif
@ -222,7 +228,7 @@ endfunction
" show_errors opens a location list and shows the given errors. If the given
" errors is empty, it closes the the location list
function! s:show_errors(errors) abort
let l:listtype = "locationlist"
let l:listtype = go#list#Type("locationlist")
if !empty(a:errors)
call go#list#Populate(l:listtype, a:errors, 'Format')
echohl Error | echomsg "Gofmt returned error" | echohl None

View file

@ -29,3 +29,19 @@ func Test_update_file()
call assert_equal(expected, actual)
endfunc
func Test_goimports()
let $GOPATH = 'test-fixtures/fmt/'
let actual_file = tempname()
call writefile(readfile("test-fixtures/fmt/src/imports/goimports.go"), actual_file)
let expected = join(readfile("test-fixtures/fmt/src/imports/goimports_golden.go"), "\n")
" run our code
call go#fmt#run("goimports", actual_file, "test-fixtures/fmt/src/imports/goimports.go")
" this should now contain the formatted code
let actual = join(readfile(actual_file), "\n")
call assert_equal(expected, actual)
endfunc

View file

@ -16,8 +16,7 @@ function! s:guru_cmd(args) range abort
let selected = a:args.selected
let result = {}
let dirname = expand('%:p:h')
let pkg = go#package#ImportPath(dirname)
let pkg = go#package#ImportPath()
" this is important, check it!
if pkg == -1 && needs_scope

View file

@ -71,12 +71,12 @@ endif
function! s:root_dirs() abort
let dirs = []
let root = go#util#goroot()
let root = go#util#env("goroot")
if root !=# '' && isdirectory(root)
call add(dirs, root)
endif
let paths = map(split(go#util#gopath(), go#util#PathListSep()), "substitute(v:val, '\\\\', '/', 'g')")
let paths = map(split(go#util#env("gopath"), go#util#PathListSep()), "substitute(v:val, '\\\\', '/', 'g')")
if go#util#ShellError()
return []
endif

View file

@ -52,7 +52,7 @@ function! s:spawn(bang, desc, args) abort
\ 'desc': a:desc,
\ 'bang': a:bang,
\ 'winnr': winnr(),
\ 'importpath': go#package#ImportPath(expand('%:p:h')),
\ 'importpath': go#package#ImportPath(),
\ 'state': "RUNNING",
\ 'stderr' : [],
\ 'stdout' : [],

View file

@ -171,13 +171,13 @@ endfunction
" the location list
function! go#lint#Errcheck(...) abort
if a:0 == 0
let goargs = go#package#ImportPath(expand('%:p:h'))
if goargs == -1
let import_path = go#package#ImportPath()
if import_path == -1
echohl Error | echomsg "vim-go: package is not inside GOPATH src" | echohl None
return
endif
else
let goargs = go#util#Shelljoin(a:000)
let import_path = go#util#Shelljoin(a:000)
endif
let bin_path = go#path#CheckBinPath(g:go_errcheck_bin)
@ -188,7 +188,7 @@ function! go#lint#Errcheck(...) abort
echon "vim-go: " | echohl Identifier | echon "errcheck analysing ..." | echohl None
redraw
let command = bin_path . ' -abspath ' . goargs
let command = bin_path . ' -abspath ' . import_path
let out = go#tool#ExecuteInDir(command)
let l:listtype = "quickfix"
@ -199,7 +199,6 @@ function! go#lint#Errcheck(...) abort
call go#list#ParseFormat(l:listtype, errformat, split(out, "\n"), 'Errcheck')
let errors = go#list#Get(l:listtype)
if empty(errors)
echohl Error | echomsg "GoErrCheck returned error" | echohl None
echo out
@ -207,6 +206,7 @@ function! go#lint#Errcheck(...) abort
endif
if !empty(errors)
echohl Error | echomsg "GoErrCheck found errors" | echohl None
call go#list#Populate(l:listtype, errors, 'Errcheck')
call go#list#Window(l:listtype, len(errors))
if !empty(errors)
@ -251,16 +251,20 @@ function s:lint_job(args)
function! s:callback(chan, msg) closure
let old_errorformat = &errorformat
let &errorformat = l:errformat
caddexpr a:msg
if l:listtype == "locationlist"
lad a:msg
elseif l:listtype == "quickfix"
caddexpr a:msg
endif
let &errorformat = old_errorformat
" TODO(jinleileiking): give a configure to jump or not
let l:winnr = winnr()
copen
let errors = go#list#Get(l:listtype)
call go#list#Window(l:listtype, len(errors))
exe l:winnr . "wincmd w"
endfunction
function! s:exit_cb(job, exitval) closure

View file

@ -68,7 +68,7 @@ function! go#list#PopulateWin(winnr, items) abort
call setloclist(a:winnr, a:items, 'r')
endfunction
" Parse parses the given items based on the specified errorformat nad
" Parse parses the given items based on the specified errorformat and
" populates the location list.
function! go#list#ParseFormat(listtype, errformat, items, title) abort
let l:listtype = go#list#Type(a:listtype)

View file

@ -33,7 +33,7 @@ function! go#package#Paths() abort
if !exists("s:goroot")
if executable('go')
let s:goroot = go#util#goroot()
let s:goroot = go#util#env("goroot")
if go#util#ShellError() != 0
echomsg '''go env GOROOT'' failed'
endif
@ -54,29 +54,25 @@ function! go#package#Paths() abort
return dirs
endfunction
function! go#package#ImportPath(arg) abort
let path = fnamemodify(resolve(a:arg), ':p')
let dirs = go#package#Paths()
for dir in dirs
if len(dir) && matchstr(escape(path, '\/'), escape(dir, '\/')) == 0
let workspace = dir
endif
endfor
if !exists('workspace')
" ImportPath returns the import path in the current directory it was executed
function! go#package#ImportPath() abort
let out = go#tool#ExecuteInDir("go list")
if go#util#ShellError() != 0
return -1
endif
if go#util#IsWin()
let srcdir = substitute(workspace . '\src\', '//', '/', '')
return path[len(srcdir):]
else
let srcdir = substitute(workspace . '/src/', '//', '/', '')
return substitute(path, srcdir, '', '')
let import_path = split(out, '\n')[0]
" go list returns '_CURRENTDIRECTORY' if the directory is not inside GOPATH.
" Check it and retun an error if that is the case
if import_path[0] ==# '_'
return -1
endif
return import_path
endfunction
function! go#package#FromPath(arg) abort
let path = fnamemodify(resolve(a:arg), ':p')
let dirs = go#package#Paths()

View file

@ -39,7 +39,7 @@ endfunction
function! go#path#Default() abort
if $GOPATH == ""
" use default GOPATH via go env
return go#util#gopath()
return go#util#env("gopath")
endif
return $GOPATH
@ -173,6 +173,17 @@ function! go#path#CheckBinPath(binpath) abort
let $PATH = old_path
" When you are using:
" 1) Windows system
" 2) Has cygpath executable
" 3) Use *sh* as 'shell'
"
" This converts your <path> to $(cygpath '<path>') to make cygwin working in
" shell of cygwin way
if go#util#IsWin() && executable('cygpath') && &shell !~ '.*sh.*'
return printf("$(cygpath '%s')", a:bin_path)
endif
return go_bin_path . go#util#PathSep() . basename
endfunction

View file

@ -20,7 +20,7 @@ function! go#play#Share(count, line1, line2) abort
call delete(share_file)
if go#util#ShellError() != 0
echo 'A error has occured. Run this command to see what the problem is:'
echo 'A error has occurred. Run this command to see what the problem is:'
echo command
return
endif

View file

@ -53,9 +53,9 @@ function! go#statusline#Show() abort
" only update highlight if status has changed.
if status_text != s:last_status
if status.state =~ "success" || status.state =~ "finished"
if status.state =~ "success" || status.state =~ "finished" || status.state =~ "pass"
hi goStatusLineColor cterm=bold ctermbg=76 ctermfg=22
elseif status.state =~ "started" || status.state =~ "analysing"
elseif status.state =~ "started" || status.state =~ "analysing" || status.state =~ "compiling"
hi goStatusLineColor cterm=bold ctermbg=208 ctermfg=88
elseif status.state =~ "failed"
hi goStatusLineColor cterm=bold ctermbg=196 ctermfg=52

View file

@ -14,21 +14,24 @@ function! go#template#create() abort
" files) from the directory create the template or use the cwd
" as the name
if l:package_name == -1 && l:go_template_use_pkg != 1
let l:template_file = get(g:, 'go_template_file', "hello_world.go")
let l:filename = fnamemodify(expand("%"), ':t')
if l:filename =~ "_test.go$"
let l:template_file = get(g:, 'go_template_test_file', "hello_world_test.go")
else
let l:template_file = get(g:, 'go_template_file', "hello_world.go")
endif
let l:template_path = go#util#Join(l:root_dir, "templates", l:template_file)
exe '0r ' . fnameescape(l:template_path)
$delete _
elseif l:package_name == -1 && l:go_template_use_pkg == 1
" cwd is now the dir of the package
let l:path = fnamemodify(getcwd(), ':t')
let l:content = printf("package %s", l:path)
call append(0, l:content)
$delete _
else
let l:content = printf("package %s", l:package_name)
call append(0, l:content)
$delete _
endif
$delete _
" Remove the '... [New File]' message line from the command line
echon

View file

@ -23,6 +23,7 @@ function! go#term#newmode(bang, cmd, mode) abort
let $GOPATH = go#path#Detect()
" execute go build in the files directory
let l:winnr = winnr()
let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd '
let dir = getcwd()
@ -47,6 +48,10 @@ function! go#term#newmode(bang, cmd, mode) abort
let id = termopen(a:cmd, job)
if l:winnr !=# winnr()
exe l:winnr . "wincmd w"
endif
execute cd . fnameescape(dir)
" restore back GOPATH

View file

@ -0,0 +1,13 @@
package main
import (
"fmt"
)
func Foo(log *logging.TestLogger) {
log.Debug("vim-go")
}
func main() {
fmt.Println("vim-go")
}

View file

@ -0,0 +1,15 @@
package main
import (
"fmt"
logging "gh.com/gi/foo-logging"
)
func Foo(log *logging.TestLogger) {
log.Debug("vim-go")
}
func main() {
fmt.Println("vim-go")
}

View file

@ -0,0 +1,12 @@
package logging
import "fmt"
type TestLogger struct {
Value string
}
func (l *TestLogger) Debug(msg string) {
fmt.Println(msg)
fmt.Println(l.Value)
}

View file

@ -0,0 +1 @@
../imports/

View file

@ -0,0 +1,287 @@
" Test runs `go test` in the current directory. If compile is true, it'll
" compile the tests instead of running them (useful to catch errors in the
" test files). Any other argument is appendend to the final `go test` command
function! go#test#Test(bang, compile, ...) abort
let args = ["test"]
" don't run the test, only compile it. Useful to capture and fix errors.
if a:compile
" we're going to tell to run a test function that doesn't exist. This
" triggers a build of the test file itself but no tests will run.
call extend(args, ["-run", "499EE4A2-5C85-4D35-98FC-7377CD87F263"])
endif
if a:0
let goargs = a:000
" do not expand for coverage mode as we're passing the arg ourself
if a:1 != '-coverprofile'
" expand all wildcards(i.e: '%' to the current file name)
let goargs = map(copy(a:000), "expand(v:val)")
endif
if !(has('nvim') || go#util#has_job())
let goargs = go#util#Shelllist(goargs, 1)
endif
call extend(args, goargs, 1)
else
" only add this if no custom flags are passed
let timeout = get(g:, 'go_test_timeout', '10s')
call add(args, printf("-timeout=%s", timeout))
endif
if get(g:, 'go_echo_command_info', 1)
if a:compile
echon "vim-go: " | echohl Identifier | echon "compiling tests ..." | echohl None
else
echon "vim-go: " | echohl Identifier | echon "testing ..." | echohl None
endif
endif
if go#util#has_job()
" use vim's job functionality to call it asynchronously
let job_args = {
\ 'cmd': ['go'] + args,
\ 'bang': a:bang,
\ 'winnr': winnr(),
\ 'dir': getcwd(),
\ 'compile_test': a:compile,
\ 'jobdir': fnameescape(expand("%:p:h")),
\ }
call s:test_job(job_args)
return
elseif has('nvim')
" use nvims's job functionality
if get(g:, 'go_term_enabled', 0)
let id = go#term#new(a:bang, ["go"] + args)
else
let id = go#jobcontrol#Spawn(a:bang, "test", args)
endif
return id
endif
call go#cmd#autowrite()
redraw
let command = "go " . join(args, ' ')
let out = go#tool#ExecuteInDir(command)
let l:listtype = "quickfix"
let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd '
let dir = getcwd()
execute cd fnameescape(expand("%:p:h"))
if go#util#ShellError() != 0
let errors = s:parse_errors(split(out, '\n'))
let errors = go#tool#FilterValids(errors)
call go#list#Populate(l:listtype, errors, command)
call go#list#Window(l:listtype, len(errors))
if !empty(errors) && !a:bang
call go#list#JumpToFirst(l:listtype)
elseif empty(errors)
" failed to parse errors, output the original content
call go#util#EchoError(out)
endif
echon "vim-go: " | echohl ErrorMsg | echon "[test] FAIL" | echohl None
else
call go#list#Clean(l:listtype)
call go#list#Window(l:listtype)
if a:compile
echon "vim-go: " | echohl Function | echon "[test] SUCCESS" | echohl None
else
echon "vim-go: " | echohl Function | echon "[test] PASS" | echohl None
endif
endif
execute cd . fnameescape(dir)
endfunction
" Testfunc runs a single test that surrounds the current cursor position.
" Arguments are passed to the `go test` command.
function! go#test#Func(bang, ...) abort
" search flags legend (used only)
" 'b' search backward instead of forward
" 'c' accept a match at the cursor position
" 'n' do Not move the cursor
" 'W' don't wrap around the end of the file
"
" for the full list
" :help search
let test = search('func \(Test\|Example\)', "bcnW")
if test == 0
echo "vim-go: [test] no test found immediate to cursor"
return
end
let line = getline(test)
let name = split(split(line, " ")[1], "(")[0]
let args = [a:bang, 0, "-run", name . "$"]
if a:0
call extend(args, a:000)
endif
call call('go#test#Test', args)
endfunction
function s:test_job(args) abort
let status_dir = expand('%:p:h')
let started_at = reltime()
let status = {
\ 'desc': 'current status',
\ 'type': "test",
\ 'state': "started",
\ }
if a:args.compile_test
let status.state = "compiling"
endif
call go#statusline#Update(status_dir, status)
" autowrite is not enabled for jobs
call go#cmd#autowrite()
let messages = []
function! s:callback(chan, msg) closure
call add(messages, a:msg)
endfunction
function! s:exit_cb(job, exitval) closure
let status = {
\ 'desc': 'last status',
\ 'type': "test",
\ 'state': "pass",
\ }
if a:args.compile_test
let status.state = "success"
endif
if a:exitval
let status.state = "failed"
endif
if get(g:, 'go_echo_command_info', 1)
if a:exitval == 0
if a:args.compile_test
call go#util#EchoSuccess("SUCCESS")
else
call go#util#EchoSuccess("PASS")
endif
else
call go#util#EchoError("FAILED")
endif
endif
let elapsed_time = reltimestr(reltime(started_at))
" strip whitespace
let elapsed_time = substitute(elapsed_time, '^\s*\(.\{-}\)\s*$', '\1', '')
let status.state .= printf(" (%ss)", elapsed_time)
call go#statusline#Update(status_dir, status)
let l:listtype = go#list#Type("quickfix")
if a:exitval == 0
call go#list#Clean(l:listtype)
call go#list#Window(l:listtype)
return
endif
call s:show_errors(a:args, a:exitval, messages)
endfunction
let start_options = {
\ 'callback': funcref("s:callback"),
\ 'exit_cb': funcref("s:exit_cb"),
\ }
" modify GOPATH if needed
let old_gopath = $GOPATH
let $GOPATH = go#path#Detect()
" pre start
let dir = getcwd()
let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd '
let jobdir = fnameescape(expand("%:p:h"))
execute cd . jobdir
call job_start(a:args.cmd, start_options)
" post start
execute cd . fnameescape(dir)
let $GOPATH = old_gopath
endfunction
" show_errors parses the given list of lines of a 'go test' output and returns
" a quickfix compatible list of errors. It's intended to be used only for go
" test output.
function! s:show_errors(args, exit_val, messages) abort
let l:listtype = go#list#Type("quickfix")
let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd '
try
execute cd a:args.jobdir
let errors = s:parse_errors(a:messages)
let errors = go#tool#FilterValids(errors)
finally
execute cd . fnameescape(a:args.dir)
endtry
if !len(errors)
" failed to parse errors, output the original content
call go#util#EchoError(join(a:messages, " "))
call go#util#EchoError(a:args.dir)
return
endif
if a:args.winnr == winnr()
call go#list#Populate(l:listtype, errors, join(a:args.cmd))
call go#list#Window(l:listtype, len(errors))
if !empty(errors) && !a:args.bang
call go#list#JumpToFirst(l:listtype)
endif
endif
endfunction
function! s:parse_errors(lines) abort
let errors = []
" NOTE(arslan): once we get JSON output everything will be easier :)
" https://github.com/golang/go/issues/2981
for line in a:lines
let fatalerrors = matchlist(line, '^\(fatal error:.*\)$')
let tokens = matchlist(line, '^\s*\(.\{-}\.go\):\(\d\+\):\s*\(.*\)')
if !empty(fatalerrors)
call add(errors, {"text": fatalerrors[1]})
elseif !empty(tokens)
" strip endlines of form ^M
let out = substitute(tokens[3], '\r$', '', '')
call add(errors, {
\ "filename" : fnamemodify(tokens[1], ':p'),
\ "lnum" : tokens[2],
\ "text" : out,
\ })
elseif !empty(errors)
" Preserve indented lines.
" This comes up especially with multi-line test output.
if match(line, '^\s') >= 0
call add(errors, {"text": line})
endif
endif
endfor
return errors
endfunction
" vim: sw=2 ts=2 et
"

View file

@ -74,24 +74,32 @@ function! go#util#env(key) abort
return l:var
endfunction
" goarch returns 'go env GOARCH'. This is an internal function and shouldn't
" be used. Instead use 'go#util#env("goarch")'
function! go#util#goarch() abort
return substitute(go#util#System('go env GOARCH'), '\n', '', 'g')
endfunction
" goos returns 'go env GOOS'. This is an internal function and shouldn't
" be used. Instead use 'go#util#env("goos")'
function! go#util#goos() abort
return substitute(go#util#System('go env GOOS'), '\n', '', 'g')
endfunction
" goroot returns 'go env GOROOT'. This is an internal function and shouldn't
" be used. Instead use 'go#util#env("goroot")'
function! go#util#goroot() abort
return substitute(go#util#System('go env GOROOT'), '\n', '', 'g')
endfunction
" gopath returns 'go env GOPATH'. This is an internal function and shouldn't
" be used. Instead use 'go#util#env("gopath")'
function! go#util#gopath() abort
return substitute(go#util#System('go env GOPATH'), '\n', '', 'g')
endfunction
function! go#util#osarch() abort
return go#util#goos() . '_' . go#util#goarch()
return go#util#env("goos") . '_' . go#util#env("goarch")
endfunction
" System runs a shell command. If possible, it will temporary set

View file

@ -333,7 +333,7 @@ CTRL-t
putting it above a function call is going to show the full function
signature. By default it uses `gocode` to get the type informations. To
change the underlying tool from `gocode` to another tool, see
|g:go_info_mode|.
|'g:go_info_mode'|.
*:GoInstall*
@ -602,12 +602,12 @@ CTRL-t
use the variable |'g:go_metalinter_command'|. To override the maximum
linters execution time use |'g:go_metalinter_deadline'| variable.
*:GoBuildTags*
*:GoBuildTags*
:GoBuildTags [tags]
Changes the build tags for various commands. If you have any file that
uses a custom build tag, such as `//+build integration` , this command can
be used to pass it to all tools that accepts tags, such as guru, gorenate,
be used to pass it to all tools that accepts tags, such as guru, gorename,
etc..
The build tags is cleared (unset) if `""` is given. If no arguments is
@ -690,7 +690,7 @@ CTRL-t
:GoAddTags xml db
<
If [option] is passed it'll either add a new tag with an option or will
modify exising tags. An example of adding `omitempty` to all `json` fields
modify existing tags. An example of adding `omitempty` to all `json` fields
would be:
>
:GoAddTags json,omitempty
@ -833,7 +833,7 @@ Clears the coverage annotation
*(go-coverage-toggle)*
Calls `go test -coverprofile-temp.out` for the current package and shows the
coverage annotation. If run agains it acts as a toggle and clears the
coverage annotation. If run again it acts as a toggle and clears the
annotation.
*(go-imports)*
@ -1014,7 +1014,7 @@ the package build (`:GoBuild`) is successful, all statusline's will show
To avoid always showing old status information, the status information is
cleaned for each package after `60` seconds. This can be changed with the
|g:go_statusline_duration| setting.
|'g:go_statusline_duration'| setting.
*go#complete#GetInfo()*
@ -1107,10 +1107,23 @@ used >
<
*'g:go_fmt_options'*
Use this option to add additional options to the |'g:go_fmt_command'|. Default
is empty. >
Use this option to add additional options to the |'g:go_fmt_command'|. It's
value type can be either a string or a dictionary. This is due backwards
compatibility. The string version will be removed in the future so please use
the dictionary version. Default is empty.
>
let g:go_fmt_options = ''
or
let g:go_fmt_options = {}
<
The dictionary version allows you to define options for multiple binaries:
>
let g:go_fmt_options = {
\ 'gofmt': '-s',
\ 'goimports': '-local mycompany.com',
\ }
<
*'g:go_fmt_fail_silently'*
@ -1130,12 +1143,20 @@ it's causing problems on some Vim versions. By default it's disabled. >
<
*'g:go_doc_keywordprg_enabled'*
Use this option to run `godoc` on words under the cursor with the default K ,
keywordprg shortcut. Usually this shortcut is set to use the program `man`. In
Go, using `godoc` is more idiomatic. Default is enabled. >
Use this option to run `godoc` on words under the cursor with |K|; this will
normally run the `man` program, but for Go using `godoc` is more idiomatic. It
will not override the |'keywordprg'| setting, but will run |:GoDoc|. Default
is enabled. >
let g:go_doc_keywordprg_enabled = 1
<
*'g:go_doc_height'*
Maximum height for the GoDoc window created with |:GoDoc|. Default is 20. >
let g:go_doc_max_height = 20
<
*'g:go_def_mode'*
Use this option to define the command to be used for |:GoDef|. By default
@ -1349,7 +1370,7 @@ default it's using `vet`, `golint` and `errcheck`.
>
let g:go_metalinter_enabled = ['vet', 'golint', 'errcheck']
<
*'g:go_metalinter_excludes'*
*'g:go_metalinter_excludes'*
Specifies the linters to be excluded from the |:GoMetaLinter| command. By
default it's empty
@ -1382,9 +1403,10 @@ explicitly overrides this behavior. For standard Vim behavior, set it to 10.
<
*'g:go_list_type'*
Specifies the type of list to use. The default value (empty) will use the
appropriate kind of list for the command that was called. Supported values are
"", "quickfix", and "locationlist". >
Specifies the type of list to use for command outputs (such as errors from
builds, results from static analysis commands, etc...). The default value
(empty) will use the appropriate kind of list for the command that was called.
Supported values are "", "quickfix", and "locationlist". >
let g:go_list_type = ""
<
@ -1453,10 +1475,10 @@ to an autocompletion proposals. By default it is enabled.
>
let g:go_gocode_propose_builtins = 1
<
*'g:go_gocode_unimported_packages'*
*'g:go_gocode_unimported_packages'*
Specifies whether `gocode` should include suggestions from unimported packages.
By default it is disabled.
Specifies whether `gocode` should include suggestions from unimported
packages. By default it is disabled.
>
let g:go_gocode_unimported_packages = 0
<
@ -1471,16 +1493,16 @@ Specifies whether `gocode` should use a different socket type. By default
*'g:go_template_autocreate'*
When a new Go file is created, vim-go automatically fills the buffer content
with a Go code template. By default the template under
`templates/hello_world.go` is used. This can be changed with the
|'g:go_template_file'| setting.
with a Go code template. By default, the templates under the `templates`
folder are used. This can be changed with the |'g:go_template_file'| and
|'g:go_template_test_file'| settings.
If the new file is created in an already prepopulated package (with other Go
files), in this case a Go code template with only the Go package declaration
(which is automatically determined according to the current package) is added.
To always use the package name instead of the template, enable the
|`g:go_template_use_pkg`| setting.
|'g:go_template_use_pkg'| setting.
By default it is enabled.
>
@ -1493,12 +1515,20 @@ is created. Checkout |'g:go_template_autocreate'| for more info. By default
the `hello_world.go` file is used.
>
let g:go_template_file = "hello_world.go"
<
*'g:go_template_test_file'*
Specifies the file under the `templates` folder that is used if a new Go test
file is created. Checkout |'g:go_template_autocreate'| for more info. By
default the `hello_world_test.go` file is used.
>
let g:go_template_test_file = "hello_world_test.go"
<
*'g:go_template_use_pkg'*
Specifies that, rather than using a template, the package name is used if a new
Go file is created. Checkout |'g:go_template_autocreate'| for more info. By
default the template file specified by |'g:go_template_file'| is used.
Specifies that, rather than using a template, the package name is used if a
new Go file is created. Checkout |'g:go_template_autocreate'| for more info.
By default the template file specified by |'g:go_template_file'| is used.
>
let g:go_template_use_pkg = 0
@ -1511,7 +1541,7 @@ for |:GoDecls|. It is a Comma delimited list Possible options are:
let g:go_decls_includes = 'func,type'
<
*'g:go_echo_command_info'*
*'g:go_echo_command_info'*
Echoes information about various Go commands, such as `:GoBuild`, `:GoTest`,
`:GoCoverage`, etc... Useful to disable if you use the statusline integration,
@ -1528,9 +1558,9 @@ default it's enabled >
<
Please note that 'noshowmode' must be set for this feature to work correctly.
*'g:go_statusline_duration'*
*'g:go_statusline_duration'*
Specifices the duration of statusline information being showed per package. By
Specifies the duration of statusline information being showed per package. By
default it's 60 seconds. Must be in milliseconds.
>
let g:go_statusline_duration = 60000
@ -1577,9 +1607,9 @@ You can locally test it by running:
>
make
<
This will run all tests and print either `PASS` or `FAIL` to indicate the final
status of all tests. Additionally, each new pull request will trigger a new
Travis-ci job.
This will run all tests and print either `PASS` or `FAIL` to indicate the
final status of all tests. Additionally, each new pull request will trigger a
new Travis-ci job.
==============================================================================
@ -1635,7 +1665,13 @@ How do I use vim-go with syntastic?~
Sometimes when using both `vim-go` and `syntastic` Vim will start lagging
while saving and opening files. The following fixes this:
>
let g:syntastic_go_checkers = ['golint', 'govet', 'errcheck']
let g:syntastic_go_checkers = ['golint', 'govet']
let g:syntastic_mode_map = { 'mode': 'active', 'passive_filetypes': ['go'] }
<
If you want to add errcheck you can use gometalinter as a wrapper
>
let g:syntastic_go_checkers = ['golint', 'govet', 'gometalinter']
let g:syntastic_go_gometalinter_args = ['--disable-all', '--enable=errcheck']
let g:syntastic_mode_map = { 'mode': 'active', 'passive_filetypes': ['go'] }
<
Another issue with `vim-go` and `syntastic` is that the location list window
@ -1649,9 +1685,9 @@ Using with NeoVim~
Note: Neovim currently is not a first class citizen for vim-go. You are free
to open bug, however I'm not using Neovim so it's hard for me to test it.
vim-go might not work well as good as in Vim. I'm happy to accept pull requests
or very detailed bug reports. If you're interested to improve the state of
Neovim in vim-go you're always welcome!
vim-go might not work well as good as in Vim. I'm happy to accept pull
requests or very detailed bug reports. If you're interested to improve the
state of Neovim in vim-go you're always welcome!
Run `:GoRun` in a new tab, horizontal split or vertical split terminal
>
@ -1672,8 +1708,8 @@ by being a patreon at: https://www.patreon.com/fatih
By being a patron, you are enabling vim-go to grow and mature, helping me to
invest in bug fixes, new documentation, and improving both current and future
features. It's completely optional and is just a direct way to support Vim-go's
ongoing development. Thanks!
features. It's completely optional and is just a direct way to support
Vim-go's ongoing development. Thanks!
Check it out: https://www.patreon.com/fatih

View file

@ -63,7 +63,7 @@ if get(g:, "go_auto_type_info", 0) || get(g:, "go_auto_sameids", 0)
endif
" NOTE(arslan): experimental, disabled by default, doesn't work well. No
" documentation as well. If anyone feels adventerous, enable the following and
" documentation as well. If anyone feels adventurous, enable the following and
" try to search for Go identifiers ;)
"
" if get(g:, "go_sameid_search_enabled", 0)
@ -82,7 +82,7 @@ endif
" endif
" let cur_offset = go#util#OffsetCursor()
" " reverse list to make it easy to find the prev occurence
" " reverse list to make it easy to find the prev occurrence
" if a:mode
" call reverse(matches)
" endif

View file

@ -34,9 +34,11 @@ command! -nargs=? -bang GoBuildTags call go#cmd#BuildTags(<bang>0, <f-args>)
command! -nargs=* -bang GoGenerate call go#cmd#Generate(<bang>0,<f-args>)
command! -nargs=* -bang -complete=file GoRun call go#cmd#Run(<bang>0,<f-args>)
command! -nargs=* -bang GoInstall call go#cmd#Install(<bang>0, <f-args>)
command! -nargs=* -bang GoTest call go#cmd#Test(<bang>0, 0, <f-args>)
command! -nargs=* -bang GoTestFunc call go#cmd#TestFunc(<bang>0, <f-args>)
command! -nargs=* -bang GoTestCompile call go#cmd#Test(<bang>0, 1, <f-args>)
" -- test
command! -nargs=* -bang GoTest call go#test#Test(<bang>0, 0, <f-args>)
command! -nargs=* -bang GoTestFunc call go#test#Func(<bang>0, <f-args>)
command! -nargs=* -bang GoTestCompile call go#test#Test(<bang>0, 1, <f-args>)
" -- cover
command! -nargs=* -bang GoCoverage call go#coverage#Buffer(<bang>0, <f-args>)
@ -84,6 +86,13 @@ command! -bang GoAlternate call go#alternate#Switch(<bang>0, '')
if globpath(&rtp, 'plugin/ctrlp.vim') != ""
command! -nargs=? -complete=file GoDecls call ctrlp#init(ctrlp#decls#cmd(0, <q-args>))
command! -nargs=? -complete=dir GoDeclsDir call ctrlp#init(ctrlp#decls#cmd(1, <q-args>))
else
function! s:ctrlp_warning()
call go#util#EchoError("ctrlp.vim plugin is not installed. Please install from: https://github.com/ctrlpvim/ctrlp.vim")
endfunction
command! -nargs=? -complete=file GoDecls call <SID>ctrlp_warning()
command! -nargs=? -complete=file GoDeclsDir call <SID>ctrlp_warning()
endif
" -- impl

View file

@ -20,9 +20,9 @@ endif
nnoremap <silent> <Plug>(go-build) :<C-u>call go#cmd#Build(!g:go_jump_to_error)<CR>
nnoremap <silent> <Plug>(go-generate) :<C-u>call go#cmd#Generate(!g:go_jump_to_error)<CR>
nnoremap <silent> <Plug>(go-install) :<C-u>call go#cmd#Install(!g:go_jump_to_error)<CR>
nnoremap <silent> <Plug>(go-test) :<C-u>call go#cmd#Test(!g:go_jump_to_error, 0)<CR>
nnoremap <silent> <Plug>(go-test-func) :<C-u>call go#cmd#TestFunc(!g:go_jump_to_error)<CR>
nnoremap <silent> <Plug>(go-test-compile) :<C-u>call go#cmd#Test(!g:go_jump_to_error, 1)<CR>
nnoremap <silent> <Plug>(go-test) :<C-u>call go#test#Test(!g:go_jump_to_error, 0)<CR>
nnoremap <silent> <Plug>(go-test-func) :<C-u>call go#test#Func(!g:go_jump_to_error)<CR>
nnoremap <silent> <Plug>(go-test-compile) :<C-u>call go#test#Test(!g:go_jump_to_error, 1)<CR>
nnoremap <silent> <Plug>(go-coverage) :<C-u>call go#coverage#Buffer(!g:go_jump_to_error)<CR>
nnoremap <silent> <Plug>(go-coverage-clear) :<C-u>call go#coverage#Clear()<CR>

View file

@ -6,6 +6,7 @@ cd $(dirname $0)
# install dependencies
go get github.com/fatih/gomodifytags
go get golang.org/x/tools/cmd/goimports
# cleanup test.log
if [ -f "test.log" ]; then

View file

@ -324,7 +324,7 @@ if g:go_highlight_types != 0
syn match goTypeConstructor /\<\w\+{/he=e-1
syn match goTypeDecl /\<type\>/ nextgroup=goTypeName skipwhite skipnl
syn match goTypeName /\w\+/ contained nextgroup=goDeclType skipwhite skipnl
syn match goDeclType /\<interface\|struct\>/ skipwhite skipnl
syn match goDeclType /\<\(interface\|struct\)\>/ skipwhite skipnl
hi def link goReceiverType Type
else
syn keyword goDeclType struct interface

View file

@ -0,0 +1,7 @@
package main
import "testing"
func TestHelloWorld(t *testing.T) {
// t.Fatal("not implemented")
}

View file

@ -18,7 +18,7 @@
- [Contributing](#contributing)
- [Credit](#credit)
###Contributors
### Contributors
- [eapache](https://github.com/eapache)
- [aschrab](https://github.com/aschrab)
- [kristijanhusak](https://github.com/kristijanhusak)

View file

@ -1 +1,2 @@
*.pyc
*~

View file

@ -76,6 +76,10 @@ snippet inject "@inject directive"
@inject('$1', '$2')
endsnippet
snippet lang "@lang directive" i
@lang('$1')
endsnippet
snippet php "@php directive"
@php
${1:${VISUAL}}
@ -124,11 +128,11 @@ snippet yield "@yield directive"
@yield('$1')
endsnippet
snippet { "{{ }} statement."
snippet { "{{ }} statement." i
{{ $1 }}
endsnippet
snippet {! "{!! !!} statement"
snippet {! "{!! !!} statement" i
{!! $1 !!}
endsnippet

View file

@ -40,195 +40,9 @@ afterAll(() => {
});
endsnippet
snippet any "any (js)" b
jasmine.any($1)
endsnippet
snippet anyt "anything (js)" b
jasmine.anything()
endsnippet
snippet objc "object containing (js)" b
jasmine.objectContaining({
${VISUAL}$0
});
endsnippet
snippet arrc "array containing (js)" b
jasmine.arrayContaining([${1:value1}]);
endsnippet
snippet strm "string matching (js)" b
jasmine.stringMatching("${1:matcher}")
endsnippet
snippet ru "runs (js)" b
runs(() => {
$0
});
endsnippet
snippet wa "waits (js)" b
waits($1);
endsnippet
snippet ex "expect (js)" b
expect(${1:target})$0;
endsnippet
snippet ee "expect to equal (js)" b
expect(${1:target}).toEqual(${2:value});
endsnippet
snippet el "expect to be less than (js)" b
expect(${1:target}).toBeLessThan(${2:value});
endsnippet
snippet eg "expect to be greater than (js)" b
expect(${1:target}).toBeGreaterThan(${2:value});
endsnippet
snippet eb "expect to be (js)" b
expect(${1:target}).toBe(${2:value});
endsnippet
snippet em "expect to match (js)" b
expect(${1:target}).toMatch(${2:pattern});
endsnippet
snippet eha "expect to have attribute (js)" b
expect(${1:target}).toHaveAttr('${2:attr}'${3:, '${4:value}'});
endsnippet
snippet et "expect to be truthy (js)" b
expect(${1:target}).toBeTruthy();
endsnippet
snippet ef "expect to be falsy (js)" b
expect(${1:target}).toBeFalsy();
endsnippet
snippet ed "expect to be defined (js)" b
expect(${1:target}).toBeDefined();
endsnippet
snippet eud "expect to be defined (js)" b
expect(${1:target}).toBeUndefined();
endsnippet
snippet en "expect to be null (js)" b
expect(${1:target}).toBeNull();
endsnippet
snippet ec "expect to contain (js)" b
expect(${1:target}).toContain(${2:value});
endsnippet
snippet ev "expect to be visible (js)" b
expect(${1:target}).toBeVisible();
endsnippet
snippet eh "expect to be hidden (js)" b
expect(${1:target}).toBeHidden();
endsnippet
snippet eth "expect to throw (js)" b
expect(${1:target}).toThrow(${2:value});
endsnippet
snippet ethe "expect to throw error (js)" b
expect(${1:target}).toThrowError(${2:value});
endsnippet
snippet notx "expect not (js)" b
expect(${1:target}).not$0;
endsnippet
snippet note "expect not to equal (js)" b
expect(${1:target}).not.toEqual(${2:value});
endsnippet
snippet notl "expect to not be less than (js)" b
expect(${1:target}).not.toBeLessThan(${2:value});
endsnippet
snippet notg "expect to not be greater than (js)" b
expect(${1:target}).not.toBeGreaterThan(${2:value});
endsnippet
snippet notm "expect not to match (js)" b
expect(${1:target}).not.toMatch(${2:pattern});
endsnippet
snippet notha "expect to not have attribute (js)" b
expect(${1:target}).not.toHaveAttr('${2:attr}'${3:, '${4:value}'});
endsnippet
snippet nott "expect not to be truthy (js)" b
expect(${1:target}).not.toBeTruthy();
endsnippet
snippet notf "expect not to be falsy (js)" b
expect(${1:target}).not.toBeFalsy();
endsnippet
snippet notd "expect not to be defined (js)" b
expect(${1:target}).not.toBeDefined();
endsnippet
snippet notn "expect not to be null (js)" b
expect(${1:target}).not.toBeNull();
endsnippet
snippet notc "expect not to contain (js)" b
expect(${1:target}).not.toContain(${2:value});
endsnippet
snippet notv "expect not to be visible (js)" b
expect(${1:target}).not.toBeVisible();
endsnippet
snippet noth "expect not to be hidden (js)" b
expect(${1:target}).not.toBeHidden();
endsnippet
snippet notth "expect not to throw (js)" b
expect(${1:target}).not.toThrow(${2:value});
endsnippet
snippet notthe "expect not to throw error (js)" b
expect(${1:target}).not.toThrowError(${2:value});
endsnippet
snippet s "spy on (js)" b
spyOn(${1:object}, '${2:method}')$0;
endsnippet
snippet sr "spy on and return (js)" b
spyOn(${1:object}, '${2:method}').and.returnValue(${3:arguments});
endsnippet
snippet st "spy on and throw (js)" b
spyOn(${1:object}, '${2:method}').and.throwError(${3:exception});
endsnippet
snippet sct "spy on and call through (js)" b
spyOn(${1:object}, '${2:method}').and.callThrough();
endsnippet
snippet scf "spy on and call fake (js)" b
spyOn(${1:object}, '${2:method}').and.callFake(${3:function});
endsnippet
snippet ethbc "expect to have been called (js)" b
expect(${1:target}).toHaveBeenCalled();
endsnippet
snippet nthbc "expect not to have been called (js)" b
expect(${1:target}).not.toHaveBeenCalled();
endsnippet
snippet ethbcw "expect to have been called with (js)" b
expect(${1:target}).toHaveBeenCalledWith(${2:arguments});
endsnippet

View file

@ -1,234 +0,0 @@
priority -50
# JavaScript versions -- from the TextMate bundle + some additions
# for jasmine-jquery matchers
#
snippet des "Describe (js)" b
describe('${1:description}', function() {
$0
});
endsnippet
snippet it "it (js)" b
it('${1:description}', function() {
$0
});
endsnippet
snippet bef "before each (js)" b
beforeEach(function() {
$0
});
endsnippet
snippet aft "after each (js)" b
afterEach(function() {
$0
});
endsnippet
snippet befa "before all (js)" b
beforeAll(function() {
$0
});
endsnippet
snippet afta "after all (js)" b
afterAll(function() {
$0
});
endsnippet
snippet any "any (js)" b
jasmine.any($1)
endsnippet
snippet anyt "anything (js)" b
jasmine.anything()
endsnippet
snippet objc "object containing (js)" b
jasmine.objectContaining({
${VISUAL}$0
});
endsnippet
snippet arrc "array containing (js)" b
jasmine.arrayContaining([${1:value1}]);
endsnippet
snippet strm "string matching (js)" b
jasmine.stringMatching("${1:matcher}")
endsnippet
snippet ru "runs (js)" b
runs(function() {
$0
});
endsnippet
snippet wa "waits (js)" b
waits($1);
endsnippet
snippet ex "expect (js)" b
expect(${1:target})$0;
endsnippet
snippet ee "expect to equal (js)" b
expect(${1:target}).toEqual(${2:value});
endsnippet
snippet el "expect to be less than (js)" b
expect(${1:target}).toBeLessThan(${2:value});
endsnippet
snippet eg "expect to be greater than (js)" b
expect(${1:target}).toBeGreaterThan(${2:value});
endsnippet
snippet eb "expect to be (js)" b
expect(${1:target}).toBe(${2:value});
endsnippet
snippet em "expect to match (js)" b
expect(${1:target}).toMatch(${2:pattern});
endsnippet
snippet eha "expect to have attribute (js)" b
expect(${1:target}).toHaveAttr('${2:attr}'${3:, '${4:value}'});
endsnippet
snippet et "expect to be truthy (js)" b
expect(${1:target}).toBeTruthy();
endsnippet
snippet ef "expect to be falsy (js)" b
expect(${1:target}).toBeFalsy();
endsnippet
snippet ed "expect to be defined (js)" b
expect(${1:target}).toBeDefined();
endsnippet
snippet eud "expect to be defined (js)" b
expect(${1:target}).toBeUndefined();
endsnippet
snippet en "expect to be null (js)" b
expect(${1:target}).toBeNull();
endsnippet
snippet ec "expect to contain (js)" b
expect(${1:target}).toContain(${2:value});
endsnippet
snippet ev "expect to be visible (js)" b
expect(${1:target}).toBeVisible();
endsnippet
snippet eh "expect to be hidden (js)" b
expect(${1:target}).toBeHidden();
endsnippet
snippet eth "expect to throw (js)" b
expect(${1:target}).toThrow(${2:value});
endsnippet
snippet ethe "expect to throw error (js)" b
expect(${1:target}).toThrowError(${2:value});
endsnippet
snippet notx "expect not (js)" b
expect(${1:target}).not$0;
endsnippet
snippet note "expect not to equal (js)" b
expect(${1:target}).not.toEqual(${2:value});
endsnippet
snippet notl "expect to not be less than (js)" b
expect(${1:target}).not.toBeLessThan(${2:value});
endsnippet
snippet notg "expect to not be greater than (js)" b
expect(${1:target}).not.toBeGreaterThan(${2:value});
endsnippet
snippet notm "expect not to match (js)" b
expect(${1:target}).not.toMatch(${2:pattern});
endsnippet
snippet notha "expect to not have attribute (js)" b
expect(${1:target}).not.toHaveAttr('${2:attr}'${3:, '${4:value}'});
endsnippet
snippet nott "expect not to be truthy (js)" b
expect(${1:target}).not.toBeTruthy();
endsnippet
snippet notf "expect not to be falsy (js)" b
expect(${1:target}).not.toBeFalsy();
endsnippet
snippet notd "expect not to be defined (js)" b
expect(${1:target}).not.toBeDefined();
endsnippet
snippet notn "expect not to be null (js)" b
expect(${1:target}).not.toBeNull();
endsnippet
snippet notc "expect not to contain (js)" b
expect(${1:target}).not.toContain(${2:value});
endsnippet
snippet notv "expect not to be visible (js)" b
expect(${1:target}).not.toBeVisible();
endsnippet
snippet noth "expect not to be hidden (js)" b
expect(${1:target}).not.toBeHidden();
endsnippet
snippet notth "expect not to throw (js)" b
expect(${1:target}).not.toThrow(${2:value});
endsnippet
snippet notthe "expect not to throw error (js)" b
expect(${1:target}).not.toThrowError(${2:value});
endsnippet
snippet s "spy on (js)" b
spyOn(${1:object}, '${2:method}')$0;
endsnippet
snippet sr "spy on and return (js)" b
spyOn(${1:object}, '${2:method}').and.returnValue(${3:arguments});
endsnippet
snippet st "spy on and throw (js)" b
spyOn(${1:object}, '${2:method}').and.throwError(${3:exception});
endsnippet
snippet sct "spy on and call through (js)" b
spyOn(${1:object}, '${2:method}').and.callThrough();
endsnippet
snippet scf "spy on and call fake (js)" b
spyOn(${1:object}, '${2:method}').and.callFake(${3:function});
endsnippet
snippet ethbc "expect to have been called (js)" b
expect(${1:target}).toHaveBeenCalled();
endsnippet
snippet nthbc "expect not to have been called (js)" b
expect(${1:target}).not.toHaveBeenCalled();
endsnippet
snippet ethbcw "expect to have been called with (js)" b
expect(${1:target}).toHaveBeenCalledWith(${2:arguments});
endsnippet

View file

@ -41,10 +41,10 @@ IFS=$'\n\t'
endsnippet
snippet temp "Tempfile"
${1:TMPFILE}="$(mktemp -t ${2:`!p
${1:TMPFILE}="$(mktemp -t ${3:--suffix=${4:.SUFFIX}} ${2:`!p
snip.rv = re.sub(r'[^a-zA-Z]', '_', snip.fn) or "untitled"
`})"
${3:${4/(.+)/trap "/}${4:rm -f '$${1/.*\s//}'}${4/(.+)/" 0 # EXIT\n/}${5/(.+)/trap "/}${5:rm -f '$${1/.*\s//}'; exit 1}${5/(.+)/" 2 # INT\n/}${6/(.+)/trap "/}${6:rm -f '$${1/.*\s//}'; exit 1}${6/(.+)/" 1 15 # HUP TERM\n/}}
`}.XXXXXX)"
${5:${6/(.+)/trap "/}${6:rm -f '$${1/.*\s//}'}${6/(.+)/" 0 # EXIT\n/}${7/(.+)/trap "/}${7:rm -f '$${1/.*\s//}'; exit 1}${7/(.+)/" 2 # INT\n/}${8/(.+)/trap "/}${8:rm -f '$${1/.*\s//}'; exit 1}${8/(.+)/" 1 15 # HUP TERM\n/}}
endsnippet

View file

@ -88,10 +88,20 @@ snippet def
snippet defd
@doc """
${1:doc string}
"""
def ${2:name} do
${0}
end
snippet defsd
@doc """
${1:doc string}
"""
@spec ${2:name} :: ${3:no_return}
def ${2} do
${0}
end
snippet defim
defimpl ${1:protocol_name}, for: ${2:data_type} do
${0}
@ -117,6 +127,7 @@ snippet defr
snippet doc
@doc """
${0}
"""
snippet docf
@doc false
@ -125,6 +136,7 @@ snippet fn
snippet mdoc
@moduledoc """
${0}
"""
snippet mdocf
@moduledoc false

View file

@ -226,3 +226,29 @@ snippet bench benchmark function
}
}
${0}
# composite literals
snippet cl
type ${1:name} struct {
${2:attrName} ${3:attrType}
}
# if key in a map
snippet om
if ${1:value}, ok := ${2:map}[${3:key}]; ok == true {
${4:/* code */}
}
# Grouped globals with anonymous struct
snippet gg
var ${1:var} = struct{
${2:name} ${3:type}
}{
$2: ${4:value},
}
# Marshalable json alias
snippet ja
type ${1:parentType}Alias $1
func (p *$1) MarshalJSON() ([]byte, error) {
return json.Marshal(&struct{ *$1Alias }{(*$1Alias)(p)})
}

View file

@ -16,7 +16,7 @@ snippet rp
snippet rpc
= render :partial => "${1:item}", :collection => ${0:@$1s}
snippet rpl
= render :partial => "${1:item}", :locals => { :${2:$1} => ${0:@$1}
= render :partial => "${1:item}", :locals => { :${2:$1} => ${0:@$1} }
snippet rpo
= render :partial => "${1:item}", :object => ${0:@$1}
snippet lt

View file

@ -4,7 +4,8 @@ snippet ri1
# Import both React and Component
snippet ri2
import React, { Component, PropTypes } from 'react'
import React, { Component } from 'react'
import PropTypes from 'prop-types'
# React class
snippet rcla
@ -40,7 +41,7 @@ snippet rcdp
# Presentational component
snippet rcom
(props) => {
props => {
return (
${0:<div></div>}
)

View file

@ -0,0 +1,175 @@
snippet des "Describe (js)"
describe('${1:description}', function() {
$0
});
snippet it "it (js)"
it('${1:description}', function() {
$0
});
snippet bef "before each (js)"
beforeEach(function() {
$0
});
snippet aft "after each (js)"
afterEach(function() {
$0
});
snippet befa "before all (js)"
beforeAll(function() {
$0
});
snippet afta "after all (js)"
afterAll(function() {
$0
});
snippet any "any (js)"
jasmine.any($1)
snippet anyt "anything (js)"
jasmine.anything()
snippet objc "object containing (js)"
jasmine.objectContaining({
${VISUAL}$0
});
snippet arrc "array containing (js)"
jasmine.arrayContaining([${1:value1}]);
snippet strm "string matching (js)"
jasmine.stringMatching("${1:matcher}")
snippet ru "runs (js)"
runs(function() {
$0
});
snippet wa "waits (js)"
waits($1);
snippet ex "expect (js)"
expect(${1:target})$0;
snippet ee "expect to equal (js)"
expect(${1:target}).toEqual(${2:value});
snippet el "expect to be less than (js)"
expect(${1:target}).toBeLessThan(${2:value});
snippet eg "expect to be greater than (js)"
expect(${1:target}).toBeGreaterThan(${2:value});
snippet eb "expect to be (js)"
expect(${1:target}).toBe(${2:value});
snippet em "expect to match (js)"
expect(${1:target}).toMatch(${2:pattern});
snippet eha "expect to have attribute (js)"
expect(${1:target}).toHaveAttr('${2:attr}'${3:, '${4:value}'});
snippet et "expect to be truthy (js)"
expect(${1:target}).toBeTruthy();
snippet ef "expect to be falsy (js)"
expect(${1:target}).toBeFalsy();
snippet ed "expect to be defined (js)"
expect(${1:target}).toBeDefined();
snippet eud "expect to be defined (js)"
expect(${1:target}).toBeUndefined();
snippet en "expect to be null (js)"
expect(${1:target}).toBeNull();
snippet ec "expect to contain (js)"
expect(${1:target}).toContain(${2:value});
snippet ev "expect to be visible (js)"
expect(${1:target}).toBeVisible();
snippet eh "expect to be hidden (js)"
expect(${1:target}).toBeHidden();
snippet eth "expect to throw (js)"
expect(${1:target}).toThrow(${2:value});
snippet ethe "expect to throw error (js)"
expect(${1:target}).toThrowError(${2:value});
snippet notx "expect not (js)"
expect(${1:target}).not$0;
snippet note "expect not to equal (js)"
expect(${1:target}).not.toEqual(${2:value});
snippet notl "expect to not be less than (js)"
expect(${1:target}).not.toBeLessThan(${2:value});
snippet notg "expect to not be greater than (js)"
expect(${1:target}).not.toBeGreaterThan(${2:value});
snippet notm "expect not to match (js)"
expect(${1:target}).not.toMatch(${2:pattern});
snippet notha "expect to not have attribute (js)"
expect(${1:target}).not.toHaveAttr('${2:attr}'${3:, '${4:value}'});
snippet nott "expect not to be truthy (js)"
expect(${1:target}).not.toBeTruthy();
snippet notf "expect not to be falsy (js)"
expect(${1:target}).not.toBeFalsy();
snippet notd "expect not to be defined (js)"
expect(${1:target}).not.toBeDefined();
snippet notn "expect not to be null (js)"
expect(${1:target}).not.toBeNull();
snippet notc "expect not to contain (js)"
expect(${1:target}).not.toContain(${2:value});
snippet notv "expect not to be visible (js)"
expect(${1:target}).not.toBeVisible();
snippet noth "expect not to be hidden (js)"
expect(${1:target}).not.toBeHidden();
snippet notth "expect not to throw (js)"
expect(${1:target}).not.toThrow(${2:value});
snippet notthe "expect not to throw error (js)"
expect(${1:target}).not.toThrowError(${2:value});
snippet s "spy on (js)"
spyOn(${1:object}, '${2:method}')$0;
snippet sr "spy on and return (js)"
spyOn(${1:object}, '${2:method}').and.returnValue(${3:arguments});
snippet st "spy on and throw (js)"
spyOn(${1:object}, '${2:method}').and.throwError(${3:exception});
snippet sct "spy on and call through (js)"
spyOn(${1:object}, '${2:method}').and.callThrough();
snippet scf "spy on and call fake (js)"
spyOn(${1:object}, '${2:method}').and.callFake(${3:function});
snippet ethbc "expect to have been called (js)"
expect(${1:target}).toHaveBeenCalled();
snippet nthbc "expect not to have been called (js)"
expect(${1:target}).not.toHaveBeenCalled();
snippet ethbcw "expect to have been called with (js)"
expect(${1:target}).toHaveBeenCalledWith(${2:arguments});

View file

@ -72,16 +72,15 @@ snippet **
snippet __
__${1:bold}__
snippet ===
`repeat('=', strlen(getline(line(".") - 1)) - strlen(getline('.')))`
`repeat('=', strlen(getline(line('.') - 3)))`
${0}
snippet -
- ${0}
snippet ---
`repeat('-', strlen(getline(line(".") - 1)) - strlen(getline('.')))`
`repeat('-', strlen(getline(line('.') - 3)))`
${0}
snippet blockquote
{% blockquote %}
${0:quote}

View file

@ -142,10 +142,6 @@ snippet ipdb
snippet iem
import IPython
IPython.embed()
# ipython debugger (pdbbb)
snippet pdbbb
import pdbpp
pdbpp.set_trace()
# remote python debugger (rpdb)
snippet rpdb
import rpdb

View file

@ -34,11 +34,11 @@ snippet main "Main function"
snippet let "let variable declaration with type inference"
let ${1} = ${2};
snippet lett "let variable declaration with explicit type annotation"
let ${1}: ${2} = ${3};
let ${1}: ${2} = ${3};
snippet letm "let mut variable declaration with type inference"
let mut ${1} = ${2};
let mut ${1} = ${2};
snippet lettm "let mut variable declaration with explicit type annotation"
let mut ${1}: ${2} = ${3};
let mut ${1}: ${2} = ${3};
snippet pri "print!"
print!("${1}");
snippet pri, "print! with format param"
@ -188,6 +188,6 @@ snippet chan "Declare (Sender, Receiver) pair of asynchronous channel()"
let (${1:tx}, ${2:rx}): (Sender<${3:i32}>, Receiver<${4:i32}>) = channel();
# Testing
snippet as "assert!"
assert!(${1:predicate})
assert!(${1:predicate});
snippet ase "assert_eq!"
assert_eq!(${1:expected}, ${2:actual})
assert_eq!(${1:expected}, ${2:actual});

View file

@ -203,33 +203,33 @@ snippet citey \citeyear
snippet fcite \footcite[]{}
\\footcite[${1}]{${2}}${0}
#Formating text: italic, bold, underline, small capital, emphase ..
snippet it italic text
\\textit{${0:${VISUAL:text}}}
snippet ita italic text
\\textit{${1:${VISUAL:text}}} ${0}
snippet bf bold face text
\\textbf{${0:${VISUAL:text}}}
\\textbf{${1:${VISUAL:text}}} ${0}
snippet under underline text
\\underline{${0:${VISUAL:text}}}
\\underline{${1:${VISUAL:text}}} ${0}
snippet emp emphasize text
\\emph{${0:${VISUAL:text}}}
\\emph{${1:${VISUAL:text}}} ${0}
snippet sc small caps text
\\textsc{${0:${VISUAL:text}}}
\\textsc{${1:${VISUAL:text}}} ${0}
#Choosing font
snippet sf sans serife text
\\textsf{${0:${VISUAL:text}}}
\\textsf{${1:${VISUAL:text}}} ${0}
snippet rm roman font text
\\textrm{${0:${VISUAL:text}}}
\\textrm{${1:${VISUAL:text}}} ${0}
snippet tt typewriter (monospace) text
\\texttt{${0:${VISUAL:text}}}
\\texttt{${1:${VISUAL:text}}} ${0}
#Math font
snippet mf mathfrak
\\mathfrak{${0:${VISUAL:text}}}
\\mathfrak{${1:${VISUAL:text}}} ${0}
snippet mc mathcal
\\mathcal{${0:${VISUAL:text}}}
\\mathcal{${1:${VISUAL:text}}} ${0}
snippet ms mathscr
\\mathscr{${0:${VISUAL:text}}}
\\mathscr{${1:${VISUAL:text}}} ${0}
#misc
snippet ft \footnote
\\footnote{${0:${VISUAL:text}}}
\\footnote{${1:${VISUAL:text}}} ${0}
snippet fig figure environment (includegraphics)
\\begin{figure}
\\begin{center}
@ -259,12 +259,19 @@ snippet subfig subfigure environment
\\label{fig:${5}}
\\end{subfigure}
${0}
snippet tikzcd tikzcd environment
\begin{equation}
\begin{tikzcd}
snippet tikzcd tikzcd environment in equation
\\begin{equation}
\\begin{tikzcd}
${1}
\end{tikzcd}
\end{equation}
\\end{tikzcd}
\\end{equation}
${0}
snippet tikzcd* tikzcd environment in equation*
\\begin{equation*}
\\begin{tikzcd}
${1}
\\end{tikzcd}
\\end{equation*}
${0}
#math
snippet stackrel \stackrel{}{}

View file

@ -1 +1,183 @@
extends html, javascript, css
# This snippet file enables vue files to use tabs for html, js and css. It also
# includes some vue-specific html-like snippets, as well as some general
# boilerplate code for vue.
extends html, javascript, css
# These snippets form a port of Sarah Drasner's vue-sublime-snippets
# some html-like snippets
snippet slot
<slot></slot>
snippet template
<template></template>
snippet transition
<transition></transition>
# The following snippets create more complex boilerplate code.
snippet vbase
<template>
<div>
</div>
</template>
<script>
export default{
}
</script>
<style scoped>
</style>
snippet vimport:c
import New from './components/New.vue';
export default{
components: {
appNew: New
}
}
snippet vactionsis now
actions: {
updateValue({commit}, payload) {
commit(updateValue, payload);
}
}
# Add in js animation hooks
snippet vanim:js:el
<transition
@before-enter="beforeEnter"
@enter="enter"
@after-enter="afterEnter"
@enter-cancelled="enterCancelled"
@before-Leave="beforeLeave"
@leave="leave"
@after-leave="afterLeave"
@leave-cancelled="leaveCancelled"
:css="false">
</transition>
snippet vanim:js:method
methods: {
beforeEnter(el) {
console.log('beforeEnter');
},
enter(el, done) {
console.log('enter');
done();
},
afterEnter(el) {
console.log('afterEnter');
},
enterCancelled(el, done) {
console.log('enterCancelled');
},
beforeLeave(el) {
console.log('beforeLeave');
},
leave(el, done) {
console.log('leave');
done();
},
afterLeave(el) {
console.log('afterLeave');
},
leaveCancelled(el, done) {
console.log('leaveCancelled');
}
}
snippet vcl
@click=""
snippet vdata
data: function () {
return {
key: value
};
}
snippet vfilter
filters: {
fnName: function (v) {
return;
}
}
snippet vfor
<div v-for="item in items" :key="item.id">
{{ item }}
</div
snippet vgetters
getters: {
value: state => {
return state.value;
}
}
snippet vimport
import New from './components/New.vue';
snippet vkeep
<keep-alive>
<component :is="">
<p>default</p>
</component>
</keep-alive>
snippet vmixin
// define a mixin object
var myMixin = {
created: function () {
this.hello()
},
methods: {
hello: function () {
console.log('hello from mixin!')
}
}
}
// define a component that uses this mixin
var Component = Vue.extend({
mixins: [myMixin]
})
var component = new Component() // -> "hello from mixin!"
snippet vmutations
// define a mixin object
var myMixin = {
created: function () {
this.hello()
},
methods: {
hello: function () {
console.log('hello from mixin!')
}
}
}
// define a component that uses this mixin
var Component = Vue.extend({
mixins: [myMixin]
})
var component = new Component() // -> "hello from mixin!"
snippet vprops:d
propName: {
type: Number,
default: 100
},
snippet vprops
propName: {
type: Number
},

View file

@ -51,7 +51,6 @@ vim-flake8 https://github.com/nvie/vim-flake8
vim-pug https://github.com/digitaltoad/vim-pug
vim-yankstack https://github.com/maxbrunsfeld/vim-yankstack
lightline.vim https://github.com/itchyny/lightline.vim
vim-abolish https://github.com/tpope/vim-abolish
""".strip()
GITHUB_ZIP = '%s/archive/master.zip'

View file

@ -34,7 +34,7 @@ map <leader>f :MRU<CR>
" => YankStack
""""""""""""""""""""""""""""""
nmap <c-p> <Plug>yankstack_substitute_older_paste
nmap <c-P> <Plug>yankstack_substitute_newer_paste
nmap <c-n> <Plug>yankstack_substitute_newer_paste
""""""""""""""""""""""""""""""