mirror of
1
0
Fork 0

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

View File

@ -139,7 +139,7 @@ fu! s:exectags(cmd)
endf endf
fu! s:exectagsonfile(fname, ftype) 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 if type(s:types[ft]) == 1
let ags .= s:types[ft] let ags .= s:types[ft]
let bin = s:bin let bin = s:bin

View File

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

View File

@ -1,6 +1,6 @@
The MIT License (MIT) 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 Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal 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) Author: itchyny (https://github.com/itchyny)
License: MIT License License: MIT License
Repository: https://github.com/itchyny/lightline.vim 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* CONTENTS *lightline-contents*
@ -29,39 +29,40 @@ The *lightline* plugin is a light and configurable statusline/tabline for Vim.
SPIRIT *lightline-spirit* SPIRIT *lightline-spirit*
Minimalism Minimalism
The core script is very small. The core script is very small to achive enough functions as a
statusline plugin.
Configurability Configurability
You can create your own component and easily add to the You can create your own component and easily add to the statusline
statusline/tabline. and the tabline.
Orthogonality Orthogonality
Any plugin should not change the settings of another plugin. The plugin does not rely on the implementation of other plugins.
Such plugin-crossing settings should be written by users in Such plugin crossing settings should be configured by users.
.vimrc.
You might find this plugin is not so useful by default. This plugin You find this plugin does not integrate with other plugins by default.
does not provide the branch information, which is a very basic This plugin does not provide branch information, which is a basic
component in existing plugins. The reason is that branch component is component in existing statusline plugins. It is a design of
one of plugin-crossing settings so users should write the settings lightline.vim that such plugin crossing configuration should be
using the APIs of the both plugins. Hospitality makes a plugin messy. written by users. Once a plugin starts to integrate with some famous
Good APIs keep a plugin clean. 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* OPTIONS *lightline-option*
g:lightline *g:lightline* 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.active *g:lightline.active*
g:lightline.inactive *g:lightline.inactive* g:lightline.inactive *g:lightline.inactive*
g:lightline.tabline *g:lightline.tabline* g:lightline.tabline *g:lightline.tabline*
Dictionaries to specify the statusline/tabline components. Dictionaries to store the statusline/tabline components.
The components are gathered from either |g:lightline.component|,
|g:lightline.component_function| or
|g:lightline.component_expand|.
Note that right groups of components are stored from right to 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 = { let g:lightline.active = {
\ 'left': [ [ 'mode', 'paste' ], \ 'left': [ [ 'mode', 'paste' ],
@ -78,10 +79,7 @@ OPTIONS *lightline-option*
\ 'right': [ [ 'close' ] ] } \ 'right': [ [ 'close' ] ] }
< <
g:lightline.tab *g:lightline.tab* g:lightline.tab *g:lightline.tab*
Dictionaries to specify the components in each tabs. A dictionary to store the tab components in each tabs.
The components are gathered from either
|g:lightline.tab_component| or
|g:lightline.tab_component_function|.
The default values are: The default values are:
> >
let g:lightline.tab = { let g:lightline.tab = {
@ -89,7 +87,7 @@ OPTIONS *lightline-option*
\ 'inactive': [ 'tabnum', 'filename', 'modified' ] } \ 'inactive': [ 'tabnum', 'filename', 'modified' ] }
< <
g:lightline.component *g:lightline.component* g:lightline.component *g:lightline.component*
Dictionary for statusline/tabline components. A dictionary for statusline/tabline components.
The default value is: The default value is:
> >
let g:lightline.component = { let g:lightline.component = {
@ -116,11 +114,11 @@ OPTIONS *lightline-option*
< <
g:lightline.component_visible_condition g:lightline.component_visible_condition
*g:lightline.component_visible_condition* *g:lightline.component_visible_condition*
Dictionary to store the visible condition of the components. A dictionary to store the visible condition of the components.
Each expression should correspond to the condition each Note that this configuration is used to control the visibility
component is not empty. This configuration is used to control of the subseparators, not to control the visibility of the
the visibility of the subseparators. You cannot use this components themselves. Each expression should correspond to
configuration to control the visibility of the components. the condition on which each component is not empty.
The default value is: The default value is:
> >
let g:lightline.component_visible_condition = { let g:lightline.component_visible_condition = {
@ -129,52 +127,47 @@ OPTIONS *lightline-option*
\ 'paste': '&paste', \ 'paste': '&paste',
\ 'spell': '&spell' } \ 'spell': '&spell' }
< <
Users are recommended to set this option together with the
component itself.
g:lightline.component_function *g:lightline.component_function* g:lightline.component_function *g:lightline.component_function*
Another dictionary for components. This is more convenient A dictionary to store the function components.
because the user does not have to set both component and This is useful to write a complex component configuration and
component_visible_condition. If a component set to both component and to integrate with other plugins. If a component set in both
component_function, the setting of component_function has priority. component and component_function, the configuration of
component_function has priority.
The default value is: The default value is:
> >
let g:lightline.component_function = {} let g:lightline.component_function = {}
< <
For example, if you want a component for read-only mark, which For example, if you want to display the name of the git branch,
disappears in help windows: install |vim-fugitive| plugin and then configure as:
> >
let g:lightline = { let g:lightline = {
\ 'active': { \ 'active': {
\ 'left': [ [ 'mode', 'paste' ], \ 'left': [ [ 'mode', 'paste' ],
\ [ 'myreadonly', 'filename', 'modified' ] ], \ [ 'gitbranch', 'readonly', 'filename', 'modified' ] ]
\ }, \ },
\ 'component_function': { \ '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
*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 components. Each expression should correspond to the condition
each component is not empty. This configuration is used to each component is not empty. This configuration is used to
control the visibility of the subseparators. You can use this control the visibility of the subseparators. You can use this
configuration to reduce the number of function calls for 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). that the component is always visible).
The default value is: The default value is:
> >
let g:lightline.component_function_visible_condition = {} let g:lightline.component_function_visible_condition = {}
< <
g:lightline.component_expand *g:lightline.component_expand* g:lightline.component_expand *g:lightline.component_expand*
Another dictionary for components. You can create a component A dictionary to store expanding components. You can create
which has a special color. For example, error components or warning and critical components. The values should be the name
warning components. The functions should return one of: of functions should return either one of:
+ a string + a string
+ an array of three elements: + an array of three elements:
[[ left ], [ middle ], [ right ]] [[ left ], [ middle ], [ right ]]
@ -281,7 +274,6 @@ OPTIONS *lightline-option*
\ 'tabline': 1 \ 'tabline': 1
\ } \ }
< <
============================================================================== ==============================================================================
FONT *lightline-font* FONT *lightline-font*
You can use the patched font you used for |vim-powerline| and |powerline|. You can use the patched font you used for |vim-powerline| and |powerline|.

View File

@ -1,4 +1,13 @@
Next 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 - Reuse/reopen existing window trees where possible #244
- Remove NERDTree.previousBuf() - Remove NERDTree.previousBuf()
- Change color of arrow (Leeiio) #630 - 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 . '"') return filter(g:NERDTreeBookmark.BookmarkNames(), 'v:val =~# "^' . a:A . '"')
endfunction 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(dir) {{{2
function! nerdtree#compareNodes(n1, n2) function! nerdtree#compareNodes(n1, n2)
return a:n1.path.compareTo(a:n2.path) return a:n1.path.compareTo(a:n2.path)
@ -64,9 +59,33 @@ endfunction
"FUNCTION: nerdtree#compareNodesBySortKey(n1, n2) {{{2 "FUNCTION: nerdtree#compareNodesBySortKey(n1, n2) {{{2
function! nerdtree#compareNodesBySortKey(n1, n2) 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 return -1
elseif a:n1.path.getSortKey() ># a:n2.path.getSortKey() elseif len(sortKey1) > len(sortKey2)
return 1 return 1
else else
return 0 return 0

View File

@ -7,7 +7,7 @@ let g:loaded_nerdtree_ui_glue_autoload = 1
function! nerdtree#ui_glue#createDefaultBindings() function! nerdtree#ui_glue#createDefaultBindings()
let s = '<SNR>' . s:SID() . '_' 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': '<LeftRelease>', 'scope': "all", 'callback': s."handleLeftClick" })
call NERDTreeAddKeyMap({ 'key': '<2-LeftMouse>', 'scope': "DirNode", 'callback': s."activateDirNode" }) call NERDTreeAddKeyMap({ 'key': '<2-LeftMouse>', 'scope': "DirNode", 'callback': s."activateDirNode" })
call NERDTreeAddKeyMap({ 'key': '<2-LeftMouse>', 'scope': "FileNode", 'callback': s."activateFileNode" }) call NERDTreeAddKeyMap({ 'key': '<2-LeftMouse>', 'scope': "FileNode", 'callback': s."activateFileNode" })
@ -336,16 +336,22 @@ endfunction
" FUNCTION: s:handleMiddleMouse() {{{1 " FUNCTION: s:handleMiddleMouse() {{{1
function! s:handleMiddleMouse() function! s:handleMiddleMouse()
let curNode = g:NERDTreeFileNode.GetSelected()
if curNode ==# {} " A middle mouse click does not automatically position the cursor as one
call nerdtree#echo("Put the cursor on a node first" ) " 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 return
endif endif
if curNode.path.isDirectory if l:currentNode.path.isDirectory
call nerdtree#openExplorer(curNode) call l:currentNode.openExplorer()
else else
call curNode.open({'where': 'h'}) call l:currentNode.open({'where': 'h'})
endif endif
endfunction endfunction
@ -441,21 +447,19 @@ function! s:jumpToSibling(currentNode, forward)
endfunction endfunction
" FUNCTION: nerdtree#ui_glue#openBookmark(name) {{{1 " 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) function! nerdtree#ui_glue#openBookmark(name)
try try
let targetNode = g:NERDTreeBookmark.GetNodeForName(a:name, 0, b:NERDTree) let l:bookmark = g:NERDTreeBookmark.BookmarkFor(a:name)
call targetNode.putCursorHere(0, 1) catch /^NERDTree.BookmarkNotFoundError/
redraw! call nerdtree#echoError('bookmark "' . a:name . '" not found')
catch /^NERDTree.BookmarkedNodeNotFoundError/ return
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)
endtry endtry
if targetNode.path.isDirectory if l:bookmark.path.isDirectory
call targetNode.openExplorer() call l:bookmark.open(b:NERDTree)
else else
call targetNode.open({'where': 'p'}) call l:bookmark.open(b:NERDTree, {'where': 'p'})
endif endif
endfunction 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 again. If no NERD tree exists for this tab then this command acts the
same as the |:NERDTree| command. 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* :NERDTreeMirror *:NERDTreeMirror*
Shares an existing NERD tree, from another tab, in the current tab. 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 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* 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 [<name>]
Bookmark the current node as <name>. If there is already a <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 (i.e. directory nodes above it will be opened) and the cursor will be
placed on it. placed on it.
:OpenBookmark <bookmark> :OpenBookmark <name>
<bookmark> must point to a file. The file is opened as though |NERDTree-o| The Bookmark named <name> is opened as if |NERDTree-o| was applied to
was applied. If the node is cached under the current root then it will be its entry in the Bookmark table. If the Bookmark points to a directory,
revealed and the cursor will be placed on it. 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>] :ClearBookmarks [<bookmarks>]
Remove all the given bookmarks. If no bookmarks are given then remove all Remove all the given bookmarks. If no bookmarks are given then remove all
@ -282,13 +287,13 @@ previous window.
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
*NERDTree-go* *NERDTree-go*
Default key: go Default key: go
Map option: None Map option: NERDTreeMapPreview
Applies to: files. Applies to: files.
If a file node is selected, it is opened in the previous window, but the If a file node is selected, it is opened in the previous window, but the
cursor does not move. 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|). |NERDTree-o|).
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
@ -324,12 +329,12 @@ window.
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
*NERDTree-gi* *NERDTree-gi*
Default key: gi Default key: gi
Map option: None Map option: NERDTreeMapPreviewSplit
Applies to: files. Applies to: files.
The same as |NERDTree-i| except that the cursor is not moved. 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|). |NERDTree-i|).
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
@ -344,12 +349,12 @@ the new window.
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
*NERDTree-gs* *NERDTree-gs*
Default key: gs Default key: gs
Map option: None Map option: NERDTreeMapPreviewVSplit
Applies to: files. Applies to: files.
The same as |NERDTree-s| except that the cursor is not moved. 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|). |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 |'NERDTreeCaseSensitiveSort'| Tells the NERD tree whether to be case
sensitive or not when sorting nodes. 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 |'NERDTreeSortHiddenFirst'| Tells the NERD tree whether to take the dot
at the beginning of the hidden file names at the beginning of the hidden file names
into account when sorting nodes. 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. |'NERDTreeBookmarksFile'| Where the bookmarks are stored.
|'NERDTreeBookmarksSort'| Whether the bookmarks list is sorted on |'NERDTreeBookmarksSort'| Control how the Bookmark table is sorted.
display.
|'NERDTreeMouseMode'| Tells the NERD tree how to handle mouse |'NERDTreeMarkBookmarks'| Render bookmarked nodes with markers.
clicks.
|'NERDTreeMouseMode'| Manage the interpretation of mouse clicks.
|'NERDTreeQuitOnOpen'| Closes the tree window after opening a file. |'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 blarg.c
boner.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'* *'NERDTreeChDirMode'*
@ -835,11 +870,24 @@ This is where bookmarks are saved. See |NERDTreeBookmarkCommands|.
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
*'NERDTreeBookmarksSort'* *'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 Values: 0 or 1
Default: 1 Default: 1
If set to 0 then the bookmarks list is not sorted. If set to 1, Bookmarks will be specially marked whenever the NERDTree is
If set to 1 the bookmarks list is sorted. rendered. Users of the |'NERDTreeMinimalUI'| setting may prefer to disable
this setting for even less visual clutter.
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
*'NERDTreeMouseMode'* *'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 s:Bookmark = {}
let g:NERDTreeBookmark = s:Bookmark let g:NERDTreeBookmark = s:Bookmark
@ -19,12 +27,9 @@ function! s:Bookmark.AddBookmark(name, path)
endif endif
endfor endfor
call add(s:Bookmark.Bookmarks(), s:Bookmark.New(a:name, a:path)) call add(s:Bookmark.Bookmarks(), s:Bookmark.New(a:name, a:path))
if g:NERDTreeBookmarksSort ==# 1
call s:Bookmark.Sort()
endif
endfunction endfunction
" FUNCTION: Bookmark.Bookmarks() {{{1 " FUNCTION: Bookmark.Bookmarks() {{{1
" Class method to get all bookmarks. Lazily initializes the bookmarks global " Class method to get all bookmarks. Lazily initializes the bookmarks global
" variable " variable
function! s:Bookmark.Bookmarks() function! s:Bookmark.Bookmarks()
@ -34,7 +39,7 @@ function! s:Bookmark.Bookmarks()
return g:NERDTreeBookmarks return g:NERDTreeBookmarks
endfunction 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 " class method that returns 1 if a bookmark with the given name is found, 0
" otherwise " otherwise
function! s:Bookmark.BookmarkExistsFor(name) function! s:Bookmark.BookmarkExistsFor(name)
@ -46,19 +51,24 @@ function! s:Bookmark.BookmarkExistsFor(name)
endtry endtry
endfunction endfunction
" FUNCTION: Bookmark.BookmarkFor(name) {{{1 " FUNCTION: Bookmark.BookmarkFor(name) {{{1
" Class method to get the bookmark that has the given name. {} is return if no " Class method that returns the Bookmark object having the specified name.
" bookmark is found " Throws "NERDTree.BookmarkNotFoundError" if no Bookmark is found.
function! s:Bookmark.BookmarkFor(name) function! s:Bookmark.BookmarkFor(name)
for i in s:Bookmark.Bookmarks() let l:result = {}
if i.name ==# a:name for l:bookmark in s:Bookmark.Bookmarks()
return i if l:bookmark.name ==# a:name
let l:result = l:bookmark
break
endif endif
endfor 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 endfunction
" FUNCTION: Bookmark.BookmarkNames() {{{1 " FUNCTION: Bookmark.BookmarkNames() {{{1
" Class method to return an array of all bookmark names " Class method to return an array of all bookmark names
function! s:Bookmark.BookmarkNames() function! s:Bookmark.BookmarkNames()
let names = [] let names = []
@ -104,17 +114,31 @@ function! s:Bookmark.CacheBookmarks(silent)
call nerdtree#echo(invalidBookmarksFound . " invalid bookmarks were read. See :help NERDTreeInvalidBookmarks for info.") call nerdtree#echo(invalidBookmarksFound . " invalid bookmarks were read. See :help NERDTreeInvalidBookmarks for info.")
endif endif
endif endif
if g:NERDTreeBookmarksSort ==# 1
call s:Bookmark.Sort()
endif
endif endif
endfunction endfunction
" FUNCTION: Bookmark.compareTo(otherbookmark) {{{1 " FUNCTION: Bookmark.CompareBookmarksByName(firstBookmark, secondBookmark) {{{1
" Compare these two bookmarks for sorting purposes " Class method that indicates the relative position of two bookmarks when
function! s:Bookmark.compareTo(otherbookmark) " placed in alphabetical order by name. Case-sensitivity is determined by an
return a:otherbookmark.name < self.name " 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 endfunction
" FUNCTION: Bookmark.ClearAll() {{{1 " FUNCTION: Bookmark.ClearAll() {{{1
" Class method to delete all bookmarks. " Class method to delete all bookmarks.
function! s:Bookmark.ClearAll() function! s:Bookmark.ClearAll()
@ -133,26 +157,33 @@ function! s:Bookmark.delete()
endfunction endfunction
" FUNCTION: Bookmark.getNode(nerdtree, searchFromAbsoluteRoot) {{{1 " 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: " Args:
" searchFromAbsoluteRoot: specifies whether we should search from the current " searchFromAbsoluteRoot: boolean flag, search from the highest cached node
" tree root, or the highest cached node " if true and from the current tree root if false
function! s:Bookmark.getNode(nerdtree, searchFromAbsoluteRoot) function! s:Bookmark.getNode(nerdtree, searchFromAbsoluteRoot)
let searchRoot = a:searchFromAbsoluteRoot ? a:nerdtree.root.AbsoluteTreeRoot() : a:nerdtree.root if a:searchFromAbsoluteRoot
let targetNode = searchRoot.findNode(self.path) let l:searchRoot = a:nerdtree.root.AbsoluteTreeRoot()
if empty(targetNode) else
throw "NERDTree.BookmarkedNodeNotFoundError: no node was found for bookmark: " . self.name let l:searchRoot = a:nerdtree.root
endif 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 endfunction
" FUNCTION: Bookmark.GetNodeForName(name, searchFromAbsoluteRoot, nerdtree) {{{1 " FUNCTION: Bookmark.GetNodeForName(name, searchFromAbsoluteRoot, nerdtree) {{{1
" Class method that finds the bookmark with the given name and returns the " Class method that returns the tree node object for the Bookmark with the
" treenode for it. " 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) function! s:Bookmark.GetNodeForName(name, searchFromAbsoluteRoot, nerdtree)
let bookmark = s:Bookmark.BookmarkFor(a:name) let l:bookmark = s:Bookmark.BookmarkFor(a:name)
return bookmark.getNode(nerdtree, a:searchFromAbsoluteRoot) return l:bookmark.getNode(a:nerdtree, a:searchFromAbsoluteRoot)
endfunction endfunction
" FUNCTION: Bookmark.GetSelected() {{{1 " FUNCTION: Bookmark.GetSelected() {{{1
@ -170,7 +201,7 @@ function! s:Bookmark.GetSelected()
return {} return {}
endfunction endfunction
" FUNCTION: Bookmark.InvalidBookmarks() {{{1 " FUNCTION: Bookmark.InvalidBookmarks() {{{1
" Class method to get all invalid bookmark strings read from the bookmarks " Class method to get all invalid bookmark strings read from the bookmarks
" file " file
function! s:Bookmark.InvalidBookmarks() function! s:Bookmark.InvalidBookmarks()
@ -233,20 +264,20 @@ function! s:Bookmark.openInNewTab(options)
call self.open(a:options) call self.open(a:options)
endfunction endfunction
" FUNCTION: Bookmark.setPath(path) {{{1 " FUNCTION: Bookmark.setPath(path) {{{1
" makes this bookmark point to the given path " makes this bookmark point to the given path
function! s:Bookmark.setPath(path) function! s:Bookmark.setPath(path)
let self.path = a:path let self.path = a:path
endfunction endfunction
" FUNCTION: Bookmark.Sort() {{{1 " FUNCTION: Bookmark.SortBookmarksList() {{{1
" Class method that sorts all bookmarks " Class method that sorts the global list of bookmarks alphabetically by name.
function! s:Bookmark.Sort() " Note that case-sensitivity is determined by a user option.
let CompareFunc = function("nerdtree#compareBookmarks") function! s:Bookmark.SortBookmarksList()
call sort(s:Bookmark.Bookmarks(), CompareFunc) call sort(s:Bookmark.Bookmarks(), s:Bookmark.CompareBookmarksByName, s:Bookmark)
endfunction endfunction
" FUNCTION: Bookmark.str() {{{1 " FUNCTION: Bookmark.str() {{{1
" Get the string that should be rendered in the view for this bookmark " Get the string that should be rendered in the view for this bookmark
function! s:Bookmark.str() function! s:Bookmark.str()
let pathStrMaxLen = winwidth(g:NERDTree.GetWinNum()) - 4 - len(self.name) let pathStrMaxLen = winwidth(g:NERDTree.GetWinNum()) - 4 - len(self.name)
@ -292,7 +323,7 @@ function! s:Bookmark.validate()
endif endif
endfunction endfunction
" FUNCTION: Bookmark.Write() {{{1 " FUNCTION: Bookmark.Write() {{{1
" Class method to write all bookmarks to the bookmarks file " Class method to write all bookmarks to the bookmarks file
function! s:Bookmark.Write() function! s:Bookmark.Write()
let bookmarkStrings = [] let bookmarkStrings = []

View File

@ -14,7 +14,7 @@ function! s:Creator._bindMappings()
command! -buffer -nargs=? Bookmark :call nerdtree#ui_glue#bookmarkNode('<args>') 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 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=* ClearBookmarks call nerdtree#ui_glue#clearBookmarks('<args>')
command! -buffer -complete=customlist,nerdtree#completeBookmarks -nargs=+ BookmarkToRoot call g:NERDTreeBookmark.ToRoot('<args>', b:NERDTree) 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() 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 "we need to use this number many times for sorting... so we calculate it only
"once here "once here
let s:NERDTreeSortStarIndex = index(g:NERDTreeSortOrder, '*') 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 "CLASS: Path
"============================================================ "============================================================
@ -52,7 +46,7 @@ function! s:Path.cacheDisplayString() abort
call add(self._bookmarkNames, i.name) call add(self._bookmarkNames, i.name)
endif endif
endfor endfor
if !empty(self._bookmarkNames) if !empty(self._bookmarkNames) && g:NERDTreeMarkBookmarks == 1
let self.cachedDisplayString .= ' {' . join(self._bookmarkNames) . '}' let self.cachedDisplayString .= ' {' . join(self._bookmarkNames) . '}'
endif endif
@ -368,8 +362,23 @@ function! s:Path.getSortOrderIndex()
return s:NERDTreeSortStarIndex return s:NERDTreeSortStarIndex
endfunction 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 "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() function! s:Path.getSortKey()
if !exists("self._sortKey") if !exists("self._sortKey")
let path = self.getLastPathComponent(1) let path = self.getLastPathComponent(1)
@ -379,7 +388,11 @@ function! s:Path.getSortKey()
if !g:NERDTreeCaseSensitiveSort if !g:NERDTreeCaseSensitiveSort
let path = tolower(path) let path = tolower(path)
endif 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 endif
return self._sortKey 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 s:TreeDirNode = copy(g:NERDTreeFileNode)
let g:NERDTreeDirNode = s:TreeDirNode let g:NERDTreeDirNode = s:TreeDirNode
"FUNCTION: TreeDirNode.AbsoluteTreeRoot(){{{1 " FUNCTION: TreeDirNode.AbsoluteTreeRoot(){{{1
"class method that returns the highest cached ancestor of the current root " Class method that returns the highest cached ancestor of the current root.
function! s:TreeDirNode.AbsoluteTreeRoot() function! s:TreeDirNode.AbsoluteTreeRoot()
let currentNode = b:NERDTree.root let currentNode = b:NERDTree.root
while currentNode.parent != {} while currentNode.parent != {}
@ -16,7 +20,7 @@ function! s:TreeDirNode.AbsoluteTreeRoot()
return currentNode return currentNode
endfunction endfunction
"FUNCTION: TreeDirNode.activate([options]) {{{1 " FUNCTION: TreeDirNode.activate([options]) {{{1
unlet s:TreeDirNode.activate unlet s:TreeDirNode.activate
function! s:TreeDirNode.activate(...) function! s:TreeDirNode.activate(...)
let opts = a:0 ? a:1 : {} let opts = a:0 ? a:1 : {}
@ -25,12 +29,12 @@ function! s:TreeDirNode.activate(...)
call self.putCursorHere(0, 0) call self.putCursorHere(0, 0)
endfunction endfunction
"FUNCTION: TreeDirNode.addChild(treenode, inOrder) {{{1 " FUNCTION: TreeDirNode.addChild(treenode, inOrder) {{{1
"Adds the given treenode to the list of children for this node " Adds the given treenode to the list of children for this node
" "
"Args: " Args:
"-treenode: the node to add " -treenode: the node to add
"-inOrder: 1 if the new node should be inserted in sorted order " -inOrder: 1 if the new node should be inserted in sorted order
function! s:TreeDirNode.addChild(treenode, inOrder) function! s:TreeDirNode.addChild(treenode, inOrder)
call add(self.children, a:treenode) call add(self.children, a:treenode)
let a:treenode.parent = self let a:treenode.parent = self
@ -40,14 +44,14 @@ function! s:TreeDirNode.addChild(treenode, inOrder)
endif endif
endfunction endfunction
"FUNCTION: TreeDirNode.close() {{{1 " FUNCTION: TreeDirNode.close() {{{1
"Closes this directory " Closes this directory
function! s:TreeDirNode.close() function! s:TreeDirNode.close()
let self.isOpen = 0 let self.isOpen = 0
endfunction endfunction
"FUNCTION: TreeDirNode.closeChildren() {{{1 " FUNCTION: TreeDirNode.closeChildren() {{{1
"Closes all the child dir nodes of this node " Closes all the child dir nodes of this node
function! s:TreeDirNode.closeChildren() function! s:TreeDirNode.closeChildren()
for i in self.children for i in self.children
if i.path.isDirectory if i.path.isDirectory
@ -57,23 +61,23 @@ function! s:TreeDirNode.closeChildren()
endfor endfor
endfunction endfunction
"FUNCTION: TreeDirNode.createChild(path, inOrder) {{{1 " FUNCTION: TreeDirNode.createChild(path, inOrder) {{{1
"Instantiates a new child node for this node with the given path. The new " Instantiates a new child node for this node with the given path. The new
"nodes parent is set to this node. " nodes parent is set to this node.
" "
"Args: " Args:
"path: a Path object that this node will represent/contain " path: a Path object that this node will represent/contain
"inOrder: 1 if the new node should be inserted in sorted order " inOrder: 1 if the new node should be inserted in sorted order
" "
"Returns: " Returns:
"the newly created node " the newly created node
function! s:TreeDirNode.createChild(path, inOrder) function! s:TreeDirNode.createChild(path, inOrder)
let newTreeNode = g:NERDTreeFileNode.New(a:path, self.getNerdtree()) let newTreeNode = g:NERDTreeFileNode.New(a:path, self.getNerdtree())
call self.addChild(newTreeNode, a:inOrder) call self.addChild(newTreeNode, a:inOrder)
return newTreeNode return newTreeNode
endfunction endfunction
"FUNCTION: TreeDirNode.displayString() {{{1 " FUNCTION: TreeDirNode.displayString() {{{1
unlet s:TreeDirNode.displayString unlet s:TreeDirNode.displayString
function! s:TreeDirNode.displayString() function! s:TreeDirNode.displayString()
let cascade = self.getCascade() let cascade = self.getCascade()
@ -89,11 +93,11 @@ function! s:TreeDirNode.displayString()
return sym . ' ' . flags . rv return sym . ' ' . flags . rv
endfunction endfunction
"FUNCTION: TreeDirNode.findNode(path) {{{1 " FUNCTION: TreeDirNode.findNode(path) {{{1
"Will find one of the children (recursively) that has the given path " Will find one of the children (recursively) that has the given path
" "
"Args: " Args:
"path: a path object " path: a path object
unlet s:TreeDirNode.findNode unlet s:TreeDirNode.findNode
function! s:TreeDirNode.findNode(path) function! s:TreeDirNode.findNode(path)
if a:path.equals(self.path) if a:path.equals(self.path)
@ -114,8 +118,8 @@ function! s:TreeDirNode.findNode(path)
return {} return {}
endfunction endfunction
"FUNCTION: TreeDirNode.getCascade() {{{1 " FUNCTION: TreeDirNode.getCascade() {{{1
"Return an array of dir nodes (starting from self) that can be cascade opened. " Return an array of dir nodes (starting from self) that can be cascade opened.
function! s:TreeDirNode.getCascade() function! s:TreeDirNode.getCascade()
if !self.isCascadable() if !self.isCascadable()
return [self] return [self]
@ -127,20 +131,20 @@ function! s:TreeDirNode.getCascade()
return [self] + visChild.getCascade() return [self] + visChild.getCascade()
endfunction endfunction
"FUNCTION: TreeDirNode.getChildCount() {{{1 " FUNCTION: TreeDirNode.getChildCount() {{{1
"Returns the number of children this node has " Returns the number of children this node has
function! s:TreeDirNode.getChildCount() function! s:TreeDirNode.getChildCount()
return len(self.children) return len(self.children)
endfunction endfunction
"FUNCTION: TreeDirNode.getChild(path) {{{1 " FUNCTION: TreeDirNode.getChild(path) {{{1
"Returns child node of this node that has the given path or {} if no such node " Returns child node of this node that has the given path or {} if no such node
"exists. " exists.
" "
"This function doesnt not recurse into child dir nodes " This function doesnt not recurse into child dir nodes
" "
"Args: " Args:
"path: a path object " path: a path object
function! s:TreeDirNode.getChild(path) function! s:TreeDirNode.getChild(path)
if stridx(a:path.str(), self.path.str(), 0) ==# -1 if stridx(a:path.str(), self.path.str(), 0) ==# -1
return {} return {}
@ -155,12 +159,13 @@ function! s:TreeDirNode.getChild(path)
endfunction endfunction
"FUNCTION: TreeDirNode.getChildByIndex(indx, visible) {{{1 " FUNCTION: TreeDirNode.getChildByIndex(indx, visible) {{{1
"returns the child at the given index " returns the child at the given index
"Args: "
"indx: the index to get the child from " Args:
"visible: 1 if only the visible children array should be used, 0 if all the " indx: the index to get the child from
"children should be searched. " 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) function! s:TreeDirNode.getChildByIndex(indx, visible)
let array_to_search = a:visible? self.getVisibleChildren() : self.children let array_to_search = a:visible? self.getVisibleChildren() : self.children
if a:indx > len(array_to_search) if a:indx > len(array_to_search)
@ -169,14 +174,14 @@ function! s:TreeDirNode.getChildByIndex(indx, visible)
return array_to_search[a:indx] return array_to_search[a:indx]
endfunction endfunction
"FUNCTION: TreeDirNode.getChildIndex(path) {{{1 " FUNCTION: TreeDirNode.getChildIndex(path) {{{1
"Returns the index of the child node of this node that has the given path or " Returns the index of the child node of this node that has the given path or
"-1 if no such node exists. " -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: " Args:
"path: a path object " path: a path object
function! s:TreeDirNode.getChildIndex(path) function! s:TreeDirNode.getChildIndex(path)
if stridx(a:path.str(), self.path.str(), 0) ==# -1 if stridx(a:path.str(), self.path.str(), 0) ==# -1
return -1 return -1
@ -200,15 +205,88 @@ function! s:TreeDirNode.getChildIndex(path)
return -1 return -1
endfunction endfunction
"FUNCTION: TreeDirNode.getDirChildren() {{{1 " FUNCTION: TreeDirNode.getDirChildren() {{{1
"Get all children that are directories " Return a list of all child nodes from "self.children" that are of type
" TreeDirNode.
function! s:TreeDirNode.getDirChildren() function! s:TreeDirNode.getDirChildren()
return filter(self.children, 'v:val.path.isDirectory == 1') return filter(self.children, 'v:val.path.isDirectory == 1')
endfunction endfunction
"FUNCTION: TreeDirNode.GetSelected() {{{1 " FUNCTION: TreeDirNode._glob(pattern, all) {{{1
"Returns the current node if it is a dir node, or else returns the current " Return a list of strings naming the descendants of the directory in this
"nodes parent " 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 unlet s:TreeDirNode.GetSelected
function! s:TreeDirNode.GetSelected() function! s:TreeDirNode.GetSelected()
let currentDir = g:NERDTreeFileNode.GetSelected() let currentDir = g:NERDTreeFileNode.GetSelected()
@ -220,17 +298,17 @@ function! s:TreeDirNode.GetSelected()
return currentDir return currentDir
endfunction endfunction
"FUNCTION: TreeDirNode.getVisibleChildCount() {{{1 " FUNCTION: TreeDirNode.getVisibleChildCount() {{{1
"Returns the number of visible children this node has " Returns the number of visible children this node has
function! s:TreeDirNode.getVisibleChildCount() function! s:TreeDirNode.getVisibleChildCount()
return len(self.getVisibleChildren()) return len(self.getVisibleChildren())
endfunction endfunction
"FUNCTION: TreeDirNode.getVisibleChildren() {{{1 " FUNCTION: TreeDirNode.getVisibleChildren() {{{1
"Returns a list of children to display for this node, in the correct order " Returns a list of children to display for this node, in the correct order
" "
"Return: " Return:
"an array of treenodes " an array of treenodes
function! s:TreeDirNode.getVisibleChildren() function! s:TreeDirNode.getVisibleChildren()
let toReturn = [] let toReturn = []
for i in self.children for i in self.children
@ -241,14 +319,14 @@ function! s:TreeDirNode.getVisibleChildren()
return toReturn return toReturn
endfunction endfunction
"FUNCTION: TreeDirNode.hasVisibleChildren() {{{1 " FUNCTION: TreeDirNode.hasVisibleChildren() {{{1
"returns 1 if this node has any childre, 0 otherwise.. " returns 1 if this node has any childre, 0 otherwise..
function! s:TreeDirNode.hasVisibleChildren() function! s:TreeDirNode.hasVisibleChildren()
return self.getVisibleChildCount() != 0 return self.getVisibleChildCount() != 0
endfunction endfunction
"FUNCTION: TreeDirNode.isCascadable() {{{1 " FUNCTION: TreeDirNode.isCascadable() {{{1
"true if this dir has only one visible child - which is also a dir " true if this dir has only one visible child - which is also a dir
function! s:TreeDirNode.isCascadable() function! s:TreeDirNode.isCascadable()
if g:NERDTreeCascadeSingleChildDir == 0 if g:NERDTreeCascadeSingleChildDir == 0
return 0 return 0
@ -258,29 +336,19 @@ function! s:TreeDirNode.isCascadable()
return len(c) == 1 && c[0].path.isDirectory return len(c) == 1 && c[0].path.isDirectory
endfunction endfunction
"FUNCTION: TreeDirNode._initChildren() {{{1 " FUNCTION: TreeDirNode._initChildren() {{{1
"Removes all childen from this node and re-reads them " Removes all childen from this node and re-reads them
" "
"Args: " Args:
"silent: 1 if the function should not echo any "please wait" messages for " silent: 1 if the function should not echo any "please wait" messages for
"large directories " large directories
" "
"Return: the number of child nodes read " Return: the number of child nodes read
function! s:TreeDirNode._initChildren(silent) function! s:TreeDirNode._initChildren(silent)
"remove all the current child nodes "remove all the current child nodes
let self.children = [] let self.children = []
"get an array of all the files in the nodes dir let files = self._glob('*', 1) + self._glob('.*', 0)
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")
if !a:silent && len(files) > g:NERDTreeNotificationThreshold if !a:silent && len(files) > g:NERDTreeNotificationThreshold
call nerdtree#echo("Please wait, caching a large dir ...") call nerdtree#echo("Please wait, caching a large dir ...")
@ -288,21 +356,13 @@ function! s:TreeDirNode._initChildren(silent)
let invalidFilesFound = 0 let invalidFilesFound = 0
for i in files for i in files
try
"filter out the .. and . directories let path = g:NERDTreePath.New(i)
"Note: we must match .. AND ../ since sometimes the globpath returns call self.createChild(path, 0)
"../ for path with strange chars (eg $) call g:NERDTreePathNotifier.NotifyListeners('init', path, self.getNerdtree(), {})
if i[len(i)-3:2] != ".." && i[len(i)-2:2] != ".." && catch /^NERDTree.\(InvalidArguments\|InvalidFiletype\)Error/
\ i[len(i)-2:1] != "." && i[len(i)-1] != "." let invalidFilesFound += 1
"put the next file in a new node and attach it endtry
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
endfor endfor
call self.sortChildren() call self.sortChildren()
@ -317,12 +377,12 @@ function! s:TreeDirNode._initChildren(silent)
return self.getChildCount() return self.getChildCount()
endfunction endfunction
"FUNCTION: TreeDirNode.New(path, nerdtree) {{{1 " FUNCTION: TreeDirNode.New(path, nerdtree) {{{1
"Returns a new TreeNode object with the given path and parent " Return a new TreeDirNode object with the given path and parent.
" "
"Args: " Args:
"path: dir that the node represents " path: dir that the node represents
"nerdtree: the tree the node belongs to " nerdtree: the tree the node belongs to
function! s:TreeDirNode.New(path, nerdtree) function! s:TreeDirNode.New(path, nerdtree)
if a:path.isDirectory != 1 if a:path.isDirectory != 1
throw "NERDTree.InvalidArgumentsError: A TreeDirNode object must be instantiated with a directory Path object." 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 return newTreeNode
endfunction endfunction
"FUNCTION: TreeDirNode.open([opts]) {{{1 " FUNCTION: TreeDirNode.open([opts]) {{{1
"Open the dir in the current tree or in a new tree elsewhere. " 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 unlet s:TreeDirNode.open
function! s:TreeDirNode.open(...) function! s:TreeDirNode.open(...)
let opts = a:0 ? a:1 : {} let opts = a:0 ? a:1 : {}
@ -361,10 +421,10 @@ function! s:TreeDirNode.open(...)
endif endif
endfunction endfunction
"FUNCTION: TreeDirNode.openAlong([opts]) {{{1 " FUNCTION: TreeDirNode.openAlong([opts]) {{{1
"recursive open the dir if it has only one directory child. " 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(...) function! s:TreeDirNode.openAlong(...)
let opts = a:0 ? a:1 : {} let opts = a:0 ? a:1 : {}
let level = 0 let level = 0
@ -383,42 +443,42 @@ function! s:TreeDirNode.openAlong(...)
endfunction endfunction
" FUNCTION: TreeDirNode.openExplorer() {{{1 " FUNCTION: TreeDirNode.openExplorer() {{{1
" opens an explorer window for this node in the previous window (could be a " Open an explorer window for this node in the previous window. The explorer
" nerd tree or a netrw) " can be a NERDTree window or a netrw window.
function! s:TreeDirNode.openExplorer() function! s:TreeDirNode.openExplorer()
call self.open({'where': 'p'}) call self.open({'where': 'p'})
endfunction endfunction
"FUNCTION: TreeDirNode.openInNewTab(options) {{{1 " FUNCTION: TreeDirNode.openInNewTab(options) {{{1
unlet s:TreeDirNode.openInNewTab unlet s:TreeDirNode.openInNewTab
function! s:TreeDirNode.openInNewTab(options) function! s:TreeDirNode.openInNewTab(options)
call nerdtree#deprecated('TreeDirNode.openInNewTab', 'is deprecated, use open() instead') call nerdtree#deprecated('TreeDirNode.openInNewTab', 'is deprecated, use open() instead')
call self.open({'where': 't'}) call self.open({'where': 't'})
endfunction endfunction
"FUNCTION: TreeDirNode._openInNewTab() {{{1 " FUNCTION: TreeDirNode._openInNewTab() {{{1
function! s:TreeDirNode._openInNewTab() function! s:TreeDirNode._openInNewTab()
tabnew tabnew
call g:NERDTreeCreator.CreateTabTree(self.path.str()) call g:NERDTreeCreator.CreateTabTree(self.path.str())
endfunction endfunction
"FUNCTION: TreeDirNode.openRecursively() {{{1 " FUNCTION: TreeDirNode.openRecursively() {{{1
"Opens this treenode and all of its children whose paths arent 'ignored' " Opens this treenode and all of its children whose paths arent 'ignored'
"because of the file filters. " because of the file filters.
" "
"This method is actually a wrapper for the OpenRecursively2 method which does " This method is actually a wrapper for the OpenRecursively2 method which does
"the work. " the work.
function! s:TreeDirNode.openRecursively() function! s:TreeDirNode.openRecursively()
call self._openRecursively2(1) call self._openRecursively2(1)
endfunction endfunction
"FUNCTION: TreeDirNode._openRecursively2() {{{1 " FUNCTION: TreeDirNode._openRecursively2() {{{1
"Opens this all children of this treenode recursively if either: " Opens this all children of this treenode recursively if either:
" *they arent filtered by file filters " *they arent filtered by file filters
" *a:forceOpen is 1 " *a:forceOpen is 1
" "
"Args: " Args:
"forceOpen: 1 if this node should be opened regardless of file filters " forceOpen: 1 if this node should be opened regardless of file filters
function! s:TreeDirNode._openRecursively2(forceOpen) function! s:TreeDirNode._openRecursively2(forceOpen)
if self.path.ignore(self.getNerdtree()) ==# 0 || a:forceOpen if self.path.ignore(self.getNerdtree()) ==# 0 || a:forceOpen
let self.isOpen = 1 let self.isOpen = 1
@ -434,50 +494,33 @@ function! s:TreeDirNode._openRecursively2(forceOpen)
endif endif
endfunction endfunction
"FUNCTION: TreeDirNode.refresh() {{{1 " FUNCTION: TreeDirNode.refresh() {{{1
unlet s:TreeDirNode.refresh
function! s:TreeDirNode.refresh() function! s:TreeDirNode.refresh()
call self.path.refresh(self.getNerdtree()) call self.path.refresh(self.getNerdtree())
"if this node was ever opened, refresh its children "if this node was ever opened, refresh its children
if self.isOpen || !empty(self.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 newChildNodes = []
let invalidFilesFound = 0 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 for i in files
"filter out the .. and . directories try
"Note: we must match .. AND ../ cos sometimes the globpath returns "create a new path and see if it exists in this nodes children
"../ for path with strange chars (eg $) let path = g:NERDTreePath.New(i)
"if i !~# '\/\.\.\/\?$' && i !~# '\/\.\/\?$' let newNode = self.getChild(path)
if newNode != {}
call newNode.refresh()
call add(newChildNodes, newNode)
" Regular expression is too expensive. Use simply string comparison "the node doesnt exist so create it
" instead else
if i[len(i)-3:2] != ".." && i[len(i)-2:2] != ".." && let newNode = g:NERDTreeFileNode.New(path, self.getNerdtree())
\ i[len(i)-2:1] != "." && i[len(i)-1] != "." let newNode.parent = self
try call add(newChildNodes, newNode)
"create a new path and see if it exists in this nodes children endif
let path = g:NERDTreePath.New(i) catch /^NERDTree.\(InvalidArguments\|InvalidFiletype\)Error/
let newNode = self.getChild(path) let invalidFilesFound = 1
if newNode != {} endtry
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
endfor endfor
"swap this nodes children out for the children we just read/refreshed "swap this nodes children out for the children we just read/refreshed
@ -490,7 +533,7 @@ function! s:TreeDirNode.refresh()
endif endif
endfunction endfunction
"FUNCTION: TreeDirNode.refreshFlags() {{{1 " FUNCTION: TreeDirNode.refreshFlags() {{{1
unlet s:TreeDirNode.refreshFlags unlet s:TreeDirNode.refreshFlags
function! s:TreeDirNode.refreshFlags() function! s:TreeDirNode.refreshFlags()
call self.path.refreshFlags(self.getNerdtree()) call self.path.refreshFlags(self.getNerdtree())
@ -499,15 +542,15 @@ function! s:TreeDirNode.refreshFlags()
endfor endfor
endfunction endfunction
"FUNCTION: TreeDirNode.refreshDirFlags() {{{1 " FUNCTION: TreeDirNode.refreshDirFlags() {{{1
function! s:TreeDirNode.refreshDirFlags() function! s:TreeDirNode.refreshDirFlags()
call self.path.refreshFlags(self.getNerdtree()) call self.path.refreshFlags(self.getNerdtree())
endfunction endfunction
"FUNCTION: TreeDirNode.reveal(path) {{{1 " FUNCTION: TreeDirNode.reveal(path) {{{1
"reveal the given path, i.e. cache and open all treenodes needed to display it " reveal the given path, i.e. cache and open all treenodes needed to display it
"in the UI " in the UI
"Returns the revealed node " Returns the revealed node
function! s:TreeDirNode.reveal(path, ...) function! s:TreeDirNode.reveal(path, ...)
let opts = a:0 ? a:1 : {} let opts = a:0 ? a:1 : {}
@ -534,14 +577,12 @@ function! s:TreeDirNode.reveal(path, ...)
return n.reveal(a:path, opts) return n.reveal(a:path, opts)
endfunction 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 object to remove
"Args:
"treenode: the node to remove
"
"Throws a NERDTree.ChildNotFoundError if the given treenode is not found
function! s:TreeDirNode.removeChild(treenode) function! s:TreeDirNode.removeChild(treenode)
for i in range(0, self.getChildCount()-1) for i in range(0, self.getChildCount()-1)
if self.children[i].equals(a:treenode) if self.children[i].equals(a:treenode)
@ -553,18 +594,15 @@ function! s:TreeDirNode.removeChild(treenode)
throw "NERDTree.ChildNotFoundError: child node was not found" throw "NERDTree.ChildNotFoundError: child node was not found"
endfunction endfunction
"FUNCTION: TreeDirNode.sortChildren() {{{1 " FUNCTION: TreeDirNode.sortChildren() {{{1
" " Sort "self.children" by alphabetical order and directory priority.
"Sorts the children of this node according to alphabetical order and the
"directory priority.
"
function! s:TreeDirNode.sortChildren() function! s:TreeDirNode.sortChildren()
let CompareFunc = function("nerdtree#compareNodesBySortKey") let CompareFunc = function("nerdtree#compareNodesBySortKey")
call sort(self.children, CompareFunc) call sort(self.children, CompareFunc)
endfunction endfunction
"FUNCTION: TreeDirNode.toggleOpen([options]) {{{1 " FUNCTION: TreeDirNode.toggleOpen([options]) {{{1
"Opens this directory if it is closed and vice versa " Opens this directory if it is closed and vice versa
function! s:TreeDirNode.toggleOpen(...) function! s:TreeDirNode.toggleOpen(...)
let opts = a:0 ? a:1 : {} let opts = a:0 ? a:1 : {}
if self.isOpen ==# 1 if self.isOpen ==# 1
@ -578,13 +616,13 @@ function! s:TreeDirNode.toggleOpen(...)
endif endif
endfunction endfunction
"FUNCTION: TreeDirNode.transplantChild(newNode) {{{1 " FUNCTION: TreeDirNode.transplantChild(newNode) {{{1
"Replaces the child of this with the given node (where the child node's full " 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 " path matches a:newNode's fullpath). The search for the matching node is
"non-recursive " non-recursive
" "
"Arg: " Arg:
"newNode: the node to graft into the tree " newNode: the node to graft into the tree
function! s:TreeDirNode.transplantChild(newNode) function! s:TreeDirNode.transplantChild(newNode)
for i in range(0, self.getChildCount()-1) for i in range(0, self.getChildCount()-1)
if self.children[i].equals(a:newNode) if self.children[i].equals(a:newNode)

View File

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

View File

@ -46,6 +46,7 @@ endfunction
call s:initVariable("g:NERDTreeAutoCenter", 1) call s:initVariable("g:NERDTreeAutoCenter", 1)
call s:initVariable("g:NERDTreeAutoCenterThreshold", 3) call s:initVariable("g:NERDTreeAutoCenterThreshold", 3)
call s:initVariable("g:NERDTreeCaseSensitiveSort", 0) call s:initVariable("g:NERDTreeCaseSensitiveSort", 0)
call s:initVariable("g:NERDTreeNaturalSort", 0)
call s:initVariable("g:NERDTreeSortHiddenFirst", 1) call s:initVariable("g:NERDTreeSortHiddenFirst", 1)
call s:initVariable("g:NERDTreeChDirMode", 0) call s:initVariable("g:NERDTreeChDirMode", 0)
call s:initVariable("g:NERDTreeCreatePrefix", "silent") 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:NERDTreeBookmarksSort", 1)
call s:initVariable("g:NERDTreeHighlightCursorline", 1) call s:initVariable("g:NERDTreeHighlightCursorline", 1)
call s:initVariable("g:NERDTreeHijackNetrw", 1) call s:initVariable("g:NERDTreeHijackNetrw", 1)
call s:initVariable('g:NERDTreeMarkBookmarks', 1)
call s:initVariable("g:NERDTreeMouseMode", 1) call s:initVariable("g:NERDTreeMouseMode", 1)
call s:initVariable("g:NERDTreeNotificationThreshold", 100) call s:initVariable("g:NERDTreeNotificationThreshold", 100)
call s:initVariable("g:NERDTreeQuitOnOpen", 0) call s:initVariable("g:NERDTreeQuitOnOpen", 0)

View File

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

View File

@ -76,7 +76,7 @@ function! syntastic#util#tmpdir() abort " {{{2
if (has('unix') || has('mac')) && executable('mktemp') && !has('win32unix') if (has('unix') || has('mac')) && executable('mktemp') && !has('win32unix')
" TODO: option "-t" to mktemp(1) is not portable " TODO: option "-t" to mktemp(1) is not portable
let tmp = $TMPDIR !=# '' ? $TMPDIR : $TMP !=# '' ? $TMP : '/tmp' 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 if v:shell_error == 0 && len(out) == 1
let tempdir = out[0] let tempdir = out[0]
endif endif
@ -84,13 +84,13 @@ function! syntastic#util#tmpdir() abort " {{{2
if tempdir ==# '' if tempdir ==# ''
if has('win32') || has('win64') 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') elseif has('win32unix')
let tempdir = syntastic#util#CygwinPath('/tmp/vim-syntastic-' . getpid()) let tempdir = syntastic#util#CygwinPath('/tmp/vim-syntastic-' . s:_fuzz())
elseif $TMPDIR !=# '' elseif $TMPDIR !=# ''
let tempdir = $TMPDIR . '/vim-syntastic-' . getpid() let tempdir = $TMPDIR . '/vim-syntastic-' . s:_fuzz()
else else
let tempdir = '/tmp/vim-syntastic-' . getpid() let tempdir = '/tmp/vim-syntastic-' . s:_fuzz()
endif endif
try try
@ -401,9 +401,6 @@ function! syntastic#util#setLastTick(buf) abort " {{{2
call setbufvar(a:buf, 'syntastic_lasttick', getbufvar(a:buf, 'changedtick')) call setbufvar(a:buf, 'syntastic_lasttick', getbufvar(a:buf, 'changedtick'))
endfunction " }}}2 endfunction " }}}2
let s:_wid_base = 'syntastic_' . getpid() . '_' . reltimestr(g:_SYNTASTIC_START) . '_'
let s:_wid_pool = 0
" Add unique IDs to windows " Add unique IDs to windows
function! syntastic#util#setWids() abort " {{{2 function! syntastic#util#setWids() abort " {{{2
for tab in range(1, tabpagenr('$')) 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') let s:_getbufvar = function(v:version > 703 || (v:version == 703 && has('patch831')) ? 'getbufvar' : 's:_getbufvar_dumb')
lockvar s:_getbufvar 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 " }}}1
let s:_wid_base = 'syntastic_' . s:_fuzz() . '_' . reltimestr(g:_SYNTASTIC_START) . '_'
let s:_wid_pool = 0
let &cpo = s:save_cpo let &cpo = s:save_cpo
unlet 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"): The following checkers are available for CoffeeScript (filetype "coffee"):
1. Coffee...................|syntastic-coffee-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* 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|. 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 Name: coffeelint
Maintainer: Lincoln Stoll <l@lds.li> Maintainer: Lincoln Stoll <l@lds.li>

View File

@ -19,7 +19,7 @@ if has('reltime')
lockvar! g:_SYNTASTIC_START lockvar! g:_SYNTASTIC_START
endif endif
let g:_SYNTASTIC_VERSION = '3.8.0-55' let g:_SYNTASTIC_VERSION = '3.8.0-60'
lockvar g:_SYNTASTIC_VERSION lockvar g:_SYNTASTIC_VERSION
" Sanity checks {{{1 " 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({ return SyntasticMake({
\ 'makeprg': makeprg, \ 'makeprg': makeprg,
\ 'errorformat': errorformat, \ 'errorformat': errorformat,
\ 'postprocess': ['guards'],
\ 'defaults': {'bufnr': bufnr('')} }) \ 'defaults': {'bufnr': bufnr('')} })
endfunction endfunction

View File

@ -19,13 +19,13 @@ let s:save_cpo = &cpo
set cpo&vim set cpo&vim
function! SyntaxCheckers_lisp_clisp_GetLocList() dict function! SyntaxCheckers_lisp_clisp_GetLocList() dict
let buf = bufnr('')
let tmpdir = syntastic#util#tmpdir() let tmpdir = syntastic#util#tmpdir()
let out = tmpdir !=# '.' ? ('-o ' . syntastic#util#shescape(tmpdir . syntastic#util#Slash() . 'syntastic_' . getpid())) : ''
let makeprg = self.makeprgBuild({ let makeprg = self.makeprgBuild({
\ 'args_after': '-q', \ 'args_after': '-q',
\ 'fname_before': '-c', \ 'fname_before': '-c',
\ 'post_args_after': out }) \ 'post_args_after': ['-o', tmpdir] })
let errorformat = let errorformat =
\ '%-G;%.%#,' . \ '%-G;%.%#,' .
@ -40,7 +40,7 @@ function! SyntaxCheckers_lisp_clisp_GetLocList() dict
let loclist = SyntasticMake({ let loclist = SyntasticMake({
\ 'makeprg': makeprg, \ 'makeprg': makeprg,
\ 'errorformat': errorformat, \ 'errorformat': errorformat,
\ 'defaults': {'bufnr': bufnr('')} }) \ 'defaults': {'bufnr': buf} })
call syntastic#util#rmrf(tmpdir) 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. in the historic buffer to go back to the work tree version.
`:Gmove` does a `git mv` on a file and simultaneously renames the `: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. the buffer.
Use `:Ggrep` to search the work tree (or any arbitrary commit) with 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| <CR> |:Gedit|
- |:Git| add - |:Git| add
- |:Git| reset (staged files) - |:Git| reset (staged files)
a Show alternative format
cA |:Gcommit| --amend --reuse-message=HEAD cA |:Gcommit| --amend --reuse-message=HEAD
ca |:Gcommit| --amend ca |:Gcommit| --amend
cc |:Gcommit| cc |:Gcommit|
@ -197,12 +198,15 @@ that are part of Git repositories).
directory except when started with a /, in which case directory except when started with a /, in which case
it is relative to the work tree. Add a ! to pass -f. it is relative to the work tree. Add a ! to pass -f.
*fugitive-:Gremove* *fugitive-:Gdelete*
:Gremove Wrapper around git-rm that deletes the buffer :Gdelete Wrapper around git-rm that deletes the buffer
afterward. When invoked in an index file, --cached is afterward. When invoked in an index file, --cached is
passed. Add a ! to pass -f and forcefully discard the passed. Add a ! to pass -f and forcefully discard the
buffer. buffer.
*fugitive-:Gremove*
:Gremove Like :Gdelete, but keep the (now empty) buffer around.
*fugitive-:Gblame* *fugitive-:Gblame*
:Gblame [flags] Run git-blame on the file and open the results in a :Gblame [flags] Run git-blame on the file and open the results in a
scroll bound vertical split. You can give any of scroll bound vertical split. You can give any of

View File

@ -68,6 +68,15 @@ function! s:shellslash(path) abort
endif endif
endfunction 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 = {} let s:git_versions = {}
function! s:git_command() abort function! s:git_command() abort
@ -400,13 +409,13 @@ function! s:repo_git_chomp(...) dict abort
endfunction endfunction
function! s:repo_git_chomp_in_tree(...) dict abort 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() let dir = getcwd()
try try
execute cd.'`=s:repo().tree()`' execute cd s:fnameescape(s:repo().tree())
return call(s:repo().git_chomp, a:000, s:repo()) return call(s:repo().git_chomp, a:000, s:repo())
finally finally
execute cd.'`=dir`' execute cd s:fnameescape(dir)
endtry endtry
endfunction 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>)") call s:command("-bang -nargs=? -complete=customlist,s:GitComplete Git :execute s:Git(<bang>0,<q-args>)")
function! s:ExecuteInTree(cmd) abort function! s:ExecuteInTree(cmd) abort
let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd ' let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd' : 'cd'
let dir = getcwd() let dir = getcwd()
try try
execute cd.'`=s:repo().tree()`' execute cd s:fnameescape(s:repo().tree())
execute a:cmd execute a:cmd
finally finally
execute cd.'`=dir`' execute cd s:fnameescape(dir)
endtry endtry
endfunction endfunction
@ -756,8 +765,8 @@ function! s:DirComplete(A,L,P) abort
return matches return matches
endfunction 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 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 :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 Glcd :exe 'lcd<bang>' s:fnameescape(s:repo().bare() ? s:repo().dir(<q-args>) : s:repo().tree(<q-args>))")
" Section: Gstatus " Section: Gstatus
@ -1057,14 +1066,14 @@ call s:command("-nargs=? -complete=customlist,s:CommitComplete Gcommit :execute
function! s:Commit(args, ...) abort function! s:Commit(args, ...) abort
let repo = a:0 ? a:1 : s:repo() 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 dir = getcwd()
let msgfile = repo.dir('COMMIT_EDITMSG') let msgfile = repo.dir('COMMIT_EDITMSG')
let outfile = tempname() let outfile = tempname()
let errorfile = tempname() let errorfile = tempname()
try try
try try
execute cd.s:fnameescape(repo.tree()) execute cd s:fnameescape(repo.tree())
if s:winshell() if s:winshell()
let command = '' let command = ''
let old_editor = $GIT_EDITOR let old_editor = $GIT_EDITOR
@ -1082,7 +1091,7 @@ function! s:Commit(args, ...) abort
endif endif
let error = v:shell_error let error = v:shell_error
finally finally
execute cd.'`=dir`' execute cd s:fnameescape(dir)
endtry endtry
if !has('gui_running') if !has('gui_running')
redraw! redraw!
@ -1292,10 +1301,10 @@ call s:command("-bar -bang -nargs=* -range=0 -complete=customlist,s:EditComplete
function! s:Grep(cmd,bang,arg) abort function! s:Grep(cmd,bang,arg) abort
let grepprg = &grepprg let grepprg = &grepprg
let grepformat = &grepformat let grepformat = &grepformat
let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd ' let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd' : 'cd'
let dir = getcwd() let dir = getcwd()
try 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 &grepprg = s:repo().git_command('--no-pager', 'grep', '-n', '--no-color')
let &grepformat = '%f:%l:%m,%m %f match%ts,%f' let &grepformat = '%f:%l:%m,%m %f match%ts,%f'
exe a:cmd.'! '.escape(matchstr(a:arg,'\v\C.{-}%($|[''" ]\@=\|)@='),'|') exe a:cmd.'! '.escape(matchstr(a:arg,'\v\C.{-}%($|[''" ]\@=\|)@='),'|')
@ -1324,7 +1333,7 @@ function! s:Grep(cmd,bang,arg) abort
finally finally
let &grepprg = grepprg let &grepprg = grepprg
let &grepformat = grepformat let &grepformat = grepformat
execute cd.'`=dir`' execute cd s:fnameescape(dir)
endtry endtry
endfunction endfunction
@ -1352,17 +1361,17 @@ function! s:Log(cmd, line1, line2, ...) abort
endif endif
let grepformat = &grepformat let grepformat = &grepformat
let grepprg = &grepprg let grepprg = &grepprg
let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd ' let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd' : 'cd'
let dir = getcwd() let dir = getcwd()
try 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 &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%.%#' let &grepformat = '%Cdiff %.%#,%C--- %.%#,%C+++ %.%#,%Z@@ -%\d%\+\,%\d%\+ +%l\,%\d%\+ @@,%-G-%.%#,%-G+%.%#,%-G %.%#,%A%f::%m,%-G%.%#'
exe a:cmd exe a:cmd
finally finally
let &grepformat = grepformat let &grepformat = grepformat
let &grepprg = grepprg let &grepprg = grepprg
execute cd.'`=dir`' execute cd s:fnameescape(dir)
endtry endtry
endfunction 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()) !=# '' 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 vert = empty(a:vert) ? s:diff_modifier(3) : a:vert
let nr = bufnr('') 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>' execute 'nnoremap <buffer> <silent> dp :diffput '.nr.'<Bar>diffupdate<CR>'
let nr2 = bufnr('') let nr2 = bufnr('')
call s:diffthis() call s:diffthis()
wincmd p 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>' execute 'nnoremap <buffer> <silent> dp :diffput '.nr.'<Bar>diffupdate<CR>'
let nr3 = bufnr('') let nr3 = bufnr('')
call s:diffthis() call s:diffthis()
@ -1915,7 +1924,7 @@ function! s:MoveComplete(A,L,P) abort
endif endif
endfunction endfunction
function! s:Remove(force) abort function! s:Remove(after, force) abort
if s:buffer().commit() ==# '' if s:buffer().commit() ==# ''
let cmd = ['rm'] let cmd = ['rm']
elseif s:buffer().commit() ==# '0' elseif s:buffer().commit() ==# '0'
@ -1933,7 +1942,7 @@ function! s:Remove(force) abort
return 'echoerr '.string(v:errmsg) return 'echoerr '.string(v:errmsg)
else else
call fugitive#reload_status() call fugitive#reload_status()
return 'edit'.(a:force ? '!' : '') return a:after . (a:force ? '!' : '')
endif endif
endfunction endfunction
@ -1941,7 +1950,8 @@ augroup fugitive_remove
autocmd! autocmd!
autocmd User Fugitive if s:buffer().commit() =~# '^0\=$' | 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 -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 \ endif
augroup END augroup END
@ -1987,10 +1997,10 @@ function! s:Blame(bang,line1,line2,count,args) abort
let cmd += ['--', s:buffer().path()] let cmd += ['--', s:buffer().path()]
let basecmd = escape(call(s:repo().git_command,cmd,s:repo()),'!') let basecmd = escape(call(s:repo().git_command,cmd,s:repo()),'!')
try try
let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd ' let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd' : 'cd'
if !s:repo().bare() if !s:repo().bare()
let dir = getcwd() let dir = getcwd()
execute cd.'`=s:repo().tree()`' execute cd s:fnameescape(s:repo().tree())
endif endif
if a:count if a:count
execute 'write !'.substitute(basecmd,' blame ',' blame -L '.a:line1.','.a:line2.' ','g') 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 silent! execute '%write !'.basecmd.' > '.temp.' 2> '.error
endif endif
if exists('l:dir') if exists('l:dir')
execute cd.'`=dir`' execute cd s:fnameescape(dir)
unlet dir unlet dir
endif endif
if v:shell_error if v:shell_error
@ -2076,7 +2086,7 @@ function! s:Blame(bang,line1,line2,count,args) abort
endif endif
finally finally
if exists('l:dir') if exists('l:dir')
execute cd.'`=dir`' execute cd s:fnameescape(dir)
endif endif
endtry endtry
return '' return ''
@ -2170,8 +2180,8 @@ function! s:BlameSyntax() abort
let arg = exists('b:fugitive_blame_arguments') ? b:fugitive_blame_arguments : '' let arg = exists('b:fugitive_blame_arguments') ? b:fugitive_blame_arguments : ''
syn match FugitiveblameBoundary "^\^" syn match FugitiveblameBoundary "^\^"
syn match FugitiveblameBlank "^\s\+\s\@=" nextgroup=FugitiveblameAnnotation,fugitiveblameOriginalFile,FugitiveblameOriginalLineNumber skipwhite syn match FugitiveblameBlank "^\s\+\s\@=" nextgroup=FugitiveblameAnnotation,fugitiveblameOriginalFile,FugitiveblameOriginalLineNumber skipwhite
syn match FugitiveblameHash "\%(^\^\=\)\@<=\x\{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 match FugitiveblameUncommitted "\%(^\^\=\)\@<=\<0\{7,40\}\>" nextgroup=FugitiveblameAnnotation,FugitiveblameOriginalLineNumber,fugitiveblameOriginalFile skipwhite
syn region FugitiveblameAnnotation matchgroup=FugitiveblameDelimiter start="(" end="\%( \d\+\)\@<=)" contained keepend oneline syn region FugitiveblameAnnotation matchgroup=FugitiveblameDelimiter start="(" end="\%( \d\+\)\@<=)" contained keepend oneline
syn match FugitiveblameTime "[0-9:/+-][0-9:/+ -]*[0-9:/+-]\%( \+\d\+)\)\@=" contained containedin=FugitiveblameAnnotation syn match FugitiveblameTime "[0-9:/+-][0-9:/+ -]*[0-9:/+-]\%( \+\d\+)\)\@=" contained containedin=FugitiveblameAnnotation
exec 'syn match FugitiveblameLineNumber " *\d\+)\@=" contained containedin=FugitiveblameAnnotation'.conceal exec 'syn match FugitiveblameLineNumber " *\d\+)\@=" contained containedin=FugitiveblameAnnotation'.conceal
@ -2197,7 +2207,7 @@ function! s:BlameSyntax() abort
continue continue
endif endif
let seen[hash] = 1 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)) \ && 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 [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) 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>)") 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 function! s:Browse(bang,line1,count,...) abort
try try
let validremote = '\.\|\.\=/.*\|[[:alnum:]_-]\+\%(://.\{-\}\)\=' let validremote = '\.\|\.\=/.*\|[[:alnum:]_-]\+\%(://.\{-\}\)\='
@ -2332,7 +2344,7 @@ function! s:Browse(bang,line1,count,...) abort
else else
let remote_for_url = remote let remote_for_url = remote
endif 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') let raw = s:repo().git_chomp('config','remote.'.remote_for_url.'.url')
else else
let raw = s:repo().git_chomp('remote','get-url',remote_for_url) 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 let raw = remote
endif 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 for Handler in g:fugitive_browse_handlers
let url = call(Handler, [{ let url = call(Handler, [{
\ 'repo': s:repo(), \ 'repo': s:repo(),
@ -2517,7 +2540,7 @@ function! s:BufReadIndex() abort
call s:ReplaceCmd(s:repo().git_command('ls-files','--stage'),index) call s:ReplaceCmd(s:repo().git_command('ls-files','--stage'),index)
set ft=git nospell set ft=git nospell
else else
let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd ' let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd' : 'cd'
let dir = getcwd() let dir = getcwd()
if fugitive#git_version() =~# '^0\|^1\.[1-7]\.' if fugitive#git_version() =~# '^0\|^1\.[1-7]\.'
let cmd = s:repo().git_command('status') let cmd = s:repo().git_command('status')
@ -2529,10 +2552,10 @@ function! s:BufReadIndex() abort
\ 'status') \ 'status')
endif endif
try try
execute cd.'`=s:repo().tree()`' execute cd s:fnameescape(s:repo().tree())
call s:ReplaceCmd(cmd, index) call s:ReplaceCmd(cmd, index)
finally finally
execute cd.'`=dir`' execute cd s:fnameescape(dir)
endtry endtry
set ft=gitcommit set ft=gitcommit
set foldtext=fugitive#foldtext() 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. * 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`. * 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 ### Shameless Plug

View File

@ -1,8 +1,44 @@
## unplanned ## 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: 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 `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] * 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] * :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] * 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: BUG FIXES:
@ -17,11 +65,23 @@ BUG FIXES:
* internal: fix system calls when using tcsh [gh-1276] * internal: fix system calls when using tcsh [gh-1276]
* path: return the unmodified GOPATH if autodetect is disabled [gh-1280] * 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 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: 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] * `: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_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) ## 1.12 - (March 29, 2017)
@ -67,7 +127,7 @@ BUG FIXES:
* Fix `:GoAddTags` to allow modifying existing comments [gh-984] * Fix `:GoAddTags` to allow modifying existing comments [gh-984]
* Fix `:GoAddTags` to work with nested structs [gh-990] * Fix `:GoAddTags` to work with nested structs [gh-990]
* Fix `:GoAddTags` adding tags twice for existing tags [gh-1064] * 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 for fields with one line comments [gh-1181]
* Fix `:GoAddTags` not working if any field comment would contain `{}` [gh-1189] * Fix `:GoAddTags` not working if any field comment would contain `{}` [gh-1189]
* Respect go_fmt_options when running goimports [gh-1211] * Respect go_fmt_options when running goimports [gh-1211]
@ -252,7 +312,7 @@ IMPROVEMENTS:
`:GoDef`, `:GoReferrers`, etc.. [gh-944] `: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] * **: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] * 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] * `: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 docs about `go_auto_sameids` [gh-1017]
* Improve error message by printing the full path if an incompatible `goimports` is being used [gh-1006] * Improve error message by printing the full path if an incompatible `goimports` is being used [gh-1006]
@ -352,7 +412,7 @@ IMPROVEMENTS:
BUG FIXES: BUG FIXES:
* Fix `(go-freevars)` plug mapping to work as in visual mode instead of noncompatible normal mode [gh-832] * 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) * 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 `:GoCoverage` colors to work for xterm as well [gh-863]
* Fix commenting out block of texts for Go templates (filetype gothtmltmpl) [gh-813] * 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. * 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 endif
endfunction 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 " 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 " 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. " dependent files for the current folder and passes it to go build.
@ -18,8 +18,10 @@ function! go#cmd#Build(bang, ...) abort
endif endif
" create our command arguments. go build discards any results when it " create our command arguments. go build discards any results when it
" compiles multiple packages. So we pass the `errors` package just as an " compiles multiple packages. So we pass the `errors` package just as an
" placeholder with the current folder (indicated with '.') " placeholder with the current folder (indicated with '.'). We also pass -i
let args = ["build"] + goargs + [".", "errors"] " 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 go#util#has_job()
if get(g:, 'go_echo_command_info', 1) if get(g:, 'go_echo_command_info', 1)
@ -109,7 +111,7 @@ function! go#cmd#RunTerm(bang, mode, files) abort
endfunction endfunction
" Run runs the current file (and their dependencies if any) and outputs it. " 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 " suitable for long running apps, because vim is blocking by default and
" calling long running apps will block the whole UI. " calling long running apps will block the whole UI.
function! go#cmd#Run(bang, ...) abort function! go#cmd#Run(bang, ...) abort
@ -225,145 +227,6 @@ function! go#cmd#Install(bang, ...) abort
let &makeprg = default_makeprg let &makeprg = default_makeprg
endfunction 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() " Generate runs 'go generate' in similar fashion to go#cmd#Build()
function! go#cmd#Generate(bang, ...) abort function! go#cmd#Generate(bang, ...) abort
let default_makeprg = &makeprg let default_makeprg = &makeprg
@ -465,24 +328,4 @@ function s:cmd_job(args) abort
let $GOPATH = old_gopath let $GOPATH = old_gopath
endfunction 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 " vim: sw=2 ts=2 et

View File

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

View File

@ -17,7 +17,7 @@ function! go#coverage#BufferToggle(bang, ...) abort
endfunction endfunction
" Buffer creates a new cover profile with 'go test -coverprofile' and changes " 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 " the code. Calling it again reruns the tests and shows the last updated
" coverage. " coverage.
function! go#coverage#Buffer(bang, ...) abort function! go#coverage#Buffer(bang, ...) abort
@ -44,9 +44,13 @@ function! go#coverage#Buffer(bang, ...) abort
let s:toggle = 1 let s:toggle = 1
let l:tmpname = tempname() 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() if go#util#has_job()
call s:coverage_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]), \ 'custom_cb': function('s:coverage_callback', [l:tmpname]),
\ 'bang': a:bang, \ 'bang': a:bang,
\ }) \ })
@ -64,7 +68,7 @@ function! go#coverage#Buffer(bang, ...) abort
let g:go_term_enabled = 0 let g:go_term_enabled = 0
endif endif
let id = call('go#cmd#Test', args) let id = call('go#test#Test', args)
if disabled_term if disabled_term
let g:go_term_enabled = 1 let g:go_term_enabled = 1
@ -113,7 +117,7 @@ function! go#coverage#Browser(bang, ...) abort
call extend(args, a:000) call extend(args, a:000)
endif endif
let id = call('go#cmd#Test', args) let id = call('go#test#Test', args)
if has('nvim') if has('nvim')
call go#jobcontrol#AddHandler(function('s:coverage_browser_handler')) call go#jobcontrol#AddHandler(function('s:coverage_browser_handler'))
let s:coverage_browser_handler_jobs[id] = l:tmpname 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 " first mark all lines as goCoverageNormalText. We use a custom group to not
" interfere with other buffers highlightings. Because the priority is " 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 let cnt = 1
while cnt <= line('$') while cnt <= line('$')
call add(matches, {'group': 'goCoverageNormalText', 'pos': [cnt], 'priority': 1}) 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") call add(cmd, "-modified")
endif endif
if exists('g:go_guru_tags') if exists('g:go_build_tags')
let tags = get(g:, 'go_guru_tags') let tags = get(g:, 'go_build_tags')
call extend(cmd, ["-tags", tags]) call extend(cmd, ["-tags", tags])
endif endif

View File

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

View File

@ -9,18 +9,14 @@ if !exists("g:go_fmt_command")
let g:go_fmt_command = "gofmt" let g:go_fmt_command = "gofmt"
endif endif
if !exists("g:go_goimports_bin") if !exists('g:go_fmt_options')
let g:go_goimports_bin = "goimports" let g:go_fmt_options = ''
endif endif
if !exists('g:go_fmt_fail_silently') if !exists('g:go_fmt_fail_silently')
let g:go_fmt_fail_silently = 0 let g:go_fmt_fail_silently = 0
endif endif
if !exists('g:go_fmt_options')
let g:go_fmt_options = ''
endif
if !exists("g:go_fmt_experimental") if !exists("g:go_fmt_experimental")
let g:go_fmt_experimental = 0 let g:go_fmt_experimental = 0
endif endif
@ -70,7 +66,7 @@ function! go#fmt#Format(withGoimport) abort
let bin_name = g:go_fmt_command let bin_name = g:go_fmt_command
if a:withGoimport == 1 if a:withGoimport == 1
let bin_name = g:go_goimports_bin let bin_name = "goimports"
endif endif
let out = go#fmt#run(bin_name, l:tmpname, expand('%')) 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 " start constructing the command
let cmd = [bin_path] let cmd = [bin_path]
call add(cmd, "-w") 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" if a:bin_name == "goimports"
" lazy check if goimports support `-srcdir`. We should eventually remove " 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 if exists('b:goimports_vendor_compatible') && b:goimports_vendor_compatible
let ssl_save = &shellslash let ssl_save = &shellslash
set noshellslash 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 let &shellslash = ssl_save
endif endif
endif endif
@ -222,7 +228,7 @@ endfunction
" show_errors opens a location list and shows the given errors. If the given " show_errors opens a location list and shows the given errors. If the given
" errors is empty, it closes the the location list " errors is empty, it closes the the location list
function! s:show_errors(errors) abort function! s:show_errors(errors) abort
let l:listtype = "locationlist" let l:listtype = go#list#Type("locationlist")
if !empty(a:errors) if !empty(a:errors)
call go#list#Populate(l:listtype, a:errors, 'Format') call go#list#Populate(l:listtype, a:errors, 'Format')
echohl Error | echomsg "Gofmt returned error" | echohl None echohl Error | echomsg "Gofmt returned error" | echohl None

View File

@ -29,3 +29,19 @@ func Test_update_file()
call assert_equal(expected, actual) call assert_equal(expected, actual)
endfunc 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 selected = a:args.selected
let result = {} let result = {}
let dirname = expand('%:p:h') let pkg = go#package#ImportPath()
let pkg = go#package#ImportPath(dirname)
" this is important, check it! " this is important, check it!
if pkg == -1 && needs_scope if pkg == -1 && needs_scope

View File

@ -71,12 +71,12 @@ endif
function! s:root_dirs() abort function! s:root_dirs() abort
let dirs = [] let dirs = []
let root = go#util#goroot() let root = go#util#env("goroot")
if root !=# '' && isdirectory(root) if root !=# '' && isdirectory(root)
call add(dirs, root) call add(dirs, root)
endif 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() if go#util#ShellError()
return [] return []
endif endif

View File

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

View File

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

View File

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

View File

@ -39,7 +39,7 @@ endfunction
function! go#path#Default() abort function! go#path#Default() abort
if $GOPATH == "" if $GOPATH == ""
" use default GOPATH via go env " use default GOPATH via go env
return go#util#gopath() return go#util#env("gopath")
endif endif
return $GOPATH return $GOPATH
@ -173,6 +173,17 @@ function! go#path#CheckBinPath(binpath) abort
let $PATH = old_path 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 return go_bin_path . go#util#PathSep() . basename
endfunction endfunction

View File

@ -20,7 +20,7 @@ function! go#play#Share(count, line1, line2) abort
call delete(share_file) call delete(share_file)
if go#util#ShellError() != 0 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 echo command
return return
endif endif

View File

@ -53,9 +53,9 @@ function! go#statusline#Show() abort
" only update highlight if status has changed. " only update highlight if status has changed.
if status_text != s:last_status 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 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 hi goStatusLineColor cterm=bold ctermbg=208 ctermfg=88
elseif status.state =~ "failed" elseif status.state =~ "failed"
hi goStatusLineColor cterm=bold ctermbg=196 ctermfg=52 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 " files) from the directory create the template or use the cwd
" as the name " as the name
if l:package_name == -1 && l:go_template_use_pkg != 1 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) let l:template_path = go#util#Join(l:root_dir, "templates", l:template_file)
exe '0r ' . fnameescape(l:template_path) exe '0r ' . fnameescape(l:template_path)
$delete _
elseif l:package_name == -1 && l:go_template_use_pkg == 1 elseif l:package_name == -1 && l:go_template_use_pkg == 1
" cwd is now the dir of the package " cwd is now the dir of the package
let l:path = fnamemodify(getcwd(), ':t') let l:path = fnamemodify(getcwd(), ':t')
let l:content = printf("package %s", l:path) let l:content = printf("package %s", l:path)
call append(0, l:content) call append(0, l:content)
$delete _
else else
let l:content = printf("package %s", l:package_name) let l:content = printf("package %s", l:package_name)
call append(0, l:content) call append(0, l:content)
$delete _
endif endif
$delete _
" Remove the '... [New File]' message line from the command line " Remove the '... [New File]' message line from the command line
echon echon

View File

@ -23,6 +23,7 @@ function! go#term#newmode(bang, cmd, mode) abort
let $GOPATH = go#path#Detect() let $GOPATH = go#path#Detect()
" execute go build in the files directory " execute go build in the files directory
let l:winnr = winnr()
let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd ' let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd '
let dir = getcwd() let dir = getcwd()
@ -47,6 +48,10 @@ function! go#term#newmode(bang, cmd, mode) abort
let id = termopen(a:cmd, job) let id = termopen(a:cmd, job)
if l:winnr !=# winnr()
exe l:winnr . "wincmd w"
endif
execute cd . fnameescape(dir) execute cd . fnameescape(dir)
" restore back GOPATH " 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 return l:var
endfunction 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 function! go#util#goarch() abort
return substitute(go#util#System('go env GOARCH'), '\n', '', 'g') return substitute(go#util#System('go env GOARCH'), '\n', '', 'g')
endfunction 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 function! go#util#goos() abort
return substitute(go#util#System('go env GOOS'), '\n', '', 'g') return substitute(go#util#System('go env GOOS'), '\n', '', 'g')
endfunction 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 function! go#util#goroot() abort
return substitute(go#util#System('go env GOROOT'), '\n', '', 'g') return substitute(go#util#System('go env GOROOT'), '\n', '', 'g')
endfunction 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 function! go#util#gopath() abort
return substitute(go#util#System('go env GOPATH'), '\n', '', 'g') return substitute(go#util#System('go env GOPATH'), '\n', '', 'g')
endfunction endfunction
function! go#util#osarch() abort function! go#util#osarch() abort
return go#util#goos() . '_' . go#util#goarch() return go#util#env("goos") . '_' . go#util#env("goarch")
endfunction endfunction
" System runs a shell command. If possible, it will temporary set " 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 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 signature. By default it uses `gocode` to get the type informations. To
change the underlying tool from `gocode` to another tool, see change the underlying tool from `gocode` to another tool, see
|g:go_info_mode|. |'g:go_info_mode'|.
*:GoInstall* *:GoInstall*
@ -602,12 +602,12 @@ CTRL-t
use the variable |'g:go_metalinter_command'|. To override the maximum use the variable |'g:go_metalinter_command'|. To override the maximum
linters execution time use |'g:go_metalinter_deadline'| variable. linters execution time use |'g:go_metalinter_deadline'| variable.
*:GoBuildTags* *:GoBuildTags*
:GoBuildTags [tags] :GoBuildTags [tags]
Changes the build tags for various commands. If you have any file that 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 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.. etc..
The build tags is cleared (unset) if `""` is given. If no arguments is The build tags is cleared (unset) if `""` is given. If no arguments is
@ -690,7 +690,7 @@ CTRL-t
:GoAddTags xml db :GoAddTags xml db
< <
If [option] is passed it'll either add a new tag with an option or will 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: would be:
> >
:GoAddTags json,omitempty :GoAddTags json,omitempty
@ -833,7 +833,7 @@ Clears the coverage annotation
*(go-coverage-toggle)* *(go-coverage-toggle)*
Calls `go test -coverprofile-temp.out` for the current package and shows the 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. annotation.
*(go-imports)* *(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 To avoid always showing old status information, the status information is
cleaned for each package after `60` seconds. This can be changed with the 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()* *go#complete#GetInfo()*
@ -1107,10 +1107,23 @@ used >
< <
*'g:go_fmt_options'* *'g:go_fmt_options'*
Use this option to add additional options to the |'g:go_fmt_command'|. Default Use this option to add additional options to the |'g:go_fmt_command'|. It's
is empty. > 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 = '' 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'* *'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'* *'g:go_doc_keywordprg_enabled'*
Use this option to run `godoc` on words under the cursor with the default K , Use this option to run `godoc` on words under the cursor with |K|; this will
keywordprg shortcut. Usually this shortcut is set to use the program `man`. In normally run the `man` program, but for Go using `godoc` is more idiomatic. It
Go, using `godoc` is more idiomatic. Default is enabled. > will not override the |'keywordprg'| setting, but will run |:GoDoc|. Default
is enabled. >
let g:go_doc_keywordprg_enabled = 1 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'* *'g:go_def_mode'*
Use this option to define the command to be used for |:GoDef|. By default 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'] 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 Specifies the linters to be excluded from the |:GoMetaLinter| command. By
default it's empty default it's empty
@ -1382,9 +1403,10 @@ explicitly overrides this behavior. For standard Vim behavior, set it to 10.
< <
*'g:go_list_type'* *'g:go_list_type'*
Specifies the type of list to use. The default value (empty) will use the Specifies the type of list to use for command outputs (such as errors from
appropriate kind of list for the command that was called. Supported values are builds, results from static analysis commands, etc...). The default value
"", "quickfix", and "locationlist". > (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 = "" 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 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. Specifies whether `gocode` should include suggestions from unimported
By default it is disabled. packages. By default it is disabled.
> >
let g:go_gocode_unimported_packages = 0 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'* *'g:go_template_autocreate'*
When a new Go file is created, vim-go automatically fills the buffer content When a new Go file is created, vim-go automatically fills the buffer content
with a Go code template. By default the template under with a Go code template. By default, the templates under the `templates`
`templates/hello_world.go` is used. This can be changed with the folder are used. This can be changed with the |'g:go_template_file'| and
|'g:go_template_file'| setting. |'g:go_template_test_file'| settings.
If the new file is created in an already prepopulated package (with other Go 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 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. (which is automatically determined according to the current package) is added.
To always use the package name instead of the template, enable the 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. 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. the `hello_world.go` file is used.
> >
let g:go_template_file = "hello_world.go" 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'* *'g:go_template_use_pkg'*
Specifies that, rather than using a template, the package name is used if a new Specifies that, rather than using a template, the package name is used if a
Go file is created. Checkout |'g:go_template_autocreate'| for more info. By new Go file is created. Checkout |'g:go_template_autocreate'| for more info.
default the template file specified by |'g:go_template_file'| is used. By default the template file specified by |'g:go_template_file'| is used.
> >
let g:go_template_use_pkg = 0 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' 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`, Echoes information about various Go commands, such as `:GoBuild`, `:GoTest`,
`:GoCoverage`, etc... Useful to disable if you use the statusline integration, `: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. 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. default it's 60 seconds. Must be in milliseconds.
> >
let g:go_statusline_duration = 60000 let g:go_statusline_duration = 60000
@ -1577,9 +1607,9 @@ You can locally test it by running:
> >
make make
< <
This will run all tests and print either `PASS` or `FAIL` to indicate the final This will run all tests and print either `PASS` or `FAIL` to indicate the
status of all tests. Additionally, each new pull request will trigger a new final status of all tests. Additionally, each new pull request will trigger a
Travis-ci job. 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 Sometimes when using both `vim-go` and `syntastic` Vim will start lagging
while saving and opening files. The following fixes this: 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'] } let g:syntastic_mode_map = { 'mode': 'active', 'passive_filetypes': ['go'] }
< <
Another issue with `vim-go` and `syntastic` is that the location list window 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 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. 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 vim-go might not work well as good as in Vim. I'm happy to accept pull
or very detailed bug reports. If you're interested to improve the state of requests or very detailed bug reports. If you're interested to improve the
Neovim in vim-go you're always welcome! state of Neovim in vim-go you're always welcome!
Run `:GoRun` in a new tab, horizontal split or vertical split terminal 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 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 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 features. It's completely optional and is just a direct way to support
ongoing development. Thanks! Vim-go's ongoing development. Thanks!
Check it out: https://www.patreon.com/fatih 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 endif
" NOTE(arslan): experimental, disabled by default, doesn't work well. No " 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 ;) " try to search for Go identifiers ;)
" "
" if get(g:, "go_sameid_search_enabled", 0) " if get(g:, "go_sameid_search_enabled", 0)
@ -82,7 +82,7 @@ endif
" endif " endif
" let cur_offset = go#util#OffsetCursor() " 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 " if a:mode
" call reverse(matches) " call reverse(matches)
" endif " 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 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 -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 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>) " -- test
command! -nargs=* -bang GoTestCompile call go#cmd#Test(<bang>0, 1, <f-args>) 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 " -- cover
command! -nargs=* -bang GoCoverage call go#coverage#Buffer(<bang>0, <f-args>) 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') != "" if globpath(&rtp, 'plugin/ctrlp.vim') != ""
command! -nargs=? -complete=file GoDecls call ctrlp#init(ctrlp#decls#cmd(0, <q-args>)) 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>)) 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 endif
" -- impl " -- 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-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-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-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) :<C-u>call go#test#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-func) :<C-u>call go#test#Func(!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-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) :<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> nnoremap <silent> <Plug>(go-coverage-clear) :<C-u>call go#coverage#Clear()<CR>

View File

@ -6,6 +6,7 @@ cd $(dirname $0)
# install dependencies # install dependencies
go get github.com/fatih/gomodifytags go get github.com/fatih/gomodifytags
go get golang.org/x/tools/cmd/goimports
# cleanup test.log # cleanup test.log
if [ -f "test.log" ]; then 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 goTypeConstructor /\<\w\+{/he=e-1
syn match goTypeDecl /\<type\>/ nextgroup=goTypeName skipwhite skipnl syn match goTypeDecl /\<type\>/ nextgroup=goTypeName skipwhite skipnl
syn match goTypeName /\w\+/ contained nextgroup=goDeclType 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 hi def link goReceiverType Type
else else
syn keyword goDeclType struct interface 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) - [Contributing](#contributing)
- [Credit](#credit) - [Credit](#credit)
###Contributors ### Contributors
- [eapache](https://github.com/eapache) - [eapache](https://github.com/eapache)
- [aschrab](https://github.com/aschrab) - [aschrab](https://github.com/aschrab)
- [kristijanhusak](https://github.com/kristijanhusak) - [kristijanhusak](https://github.com/kristijanhusak)

View File

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

View File

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

View File

@ -40,195 +40,9 @@ afterAll(() => {
}); });
endsnippet 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 snippet ru "runs (js)" b
runs(() => { runs(() => {
$0 $0
}); });
endsnippet 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 endsnippet
snippet temp "Tempfile" 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" snip.rv = re.sub(r'[^a-zA-Z]', '_', snip.fn) or "untitled"
`})" `}.XXXXXX)"
${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/}} ${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 endsnippet

View File

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

View File

@ -226,3 +226,29 @@ snippet bench benchmark function
} }
} }
${0} ${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 snippet rpc
= render :partial => "${1:item}", :collection => ${0:@$1s} = render :partial => "${1:item}", :collection => ${0:@$1s}
snippet rpl snippet rpl
= render :partial => "${1:item}", :locals => { :${2:$1} => ${0:@$1} = render :partial => "${1:item}", :locals => { :${2:$1} => ${0:@$1} }
snippet rpo snippet rpo
= render :partial => "${1:item}", :object => ${0:@$1} = render :partial => "${1:item}", :object => ${0:@$1}
snippet lt snippet lt

View File

@ -4,7 +4,8 @@ snippet ri1
# Import both React and Component # Import both React and Component
snippet ri2 snippet ri2
import React, { Component, PropTypes } from 'react' import React, { Component } from 'react'
import PropTypes from 'prop-types'
# React class # React class
snippet rcla snippet rcla
@ -40,7 +41,7 @@ snippet rcdp
# Presentational component # Presentational component
snippet rcom snippet rcom
(props) => { props => {
return ( return (
${0:<div></div>} ${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 __ snippet __
__${1:bold}__ __${1:bold}__
snippet === snippet ===
`repeat('=', strlen(getline(line(".") - 1)) - strlen(getline('.')))` `repeat('=', strlen(getline(line('.') - 3)))`
${0} ${0}
snippet - snippet -
- ${0} - ${0}
snippet --- snippet ---
`repeat('-', strlen(getline(line(".") - 1)) - strlen(getline('.')))` `repeat('-', strlen(getline(line('.') - 3)))`
${0} ${0}
snippet blockquote snippet blockquote
{% blockquote %} {% blockquote %}
${0:quote} ${0:quote}

View File

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

View File

@ -34,11 +34,11 @@ snippet main "Main function"
snippet let "let variable declaration with type inference" snippet let "let variable declaration with type inference"
let ${1} = ${2}; let ${1} = ${2};
snippet lett "let variable declaration with explicit type annotation" 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" 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" snippet lettm "let mut variable declaration with explicit type annotation"
let mut ${1}: ${2} = ${3}; let mut ${1}: ${2} = ${3};
snippet pri "print!" snippet pri "print!"
print!("${1}"); print!("${1}");
snippet pri, "print! with format param" 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(); let (${1:tx}, ${2:rx}): (Sender<${3:i32}>, Receiver<${4:i32}>) = channel();
# Testing # Testing
snippet as "assert!" snippet as "assert!"
assert!(${1:predicate}) assert!(${1:predicate});
snippet ase "assert_eq!" 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[]{} snippet fcite \footcite[]{}
\\footcite[${1}]{${2}}${0} \\footcite[${1}]{${2}}${0}
#Formating text: italic, bold, underline, small capital, emphase .. #Formating text: italic, bold, underline, small capital, emphase ..
snippet it italic text snippet ita italic text
\\textit{${0:${VISUAL:text}}} \\textit{${1:${VISUAL:text}}} ${0}
snippet bf bold face text snippet bf bold face text
\\textbf{${0:${VISUAL:text}}} \\textbf{${1:${VISUAL:text}}} ${0}
snippet under underline text snippet under underline text
\\underline{${0:${VISUAL:text}}} \\underline{${1:${VISUAL:text}}} ${0}
snippet emp emphasize text snippet emp emphasize text
\\emph{${0:${VISUAL:text}}} \\emph{${1:${VISUAL:text}}} ${0}
snippet sc small caps text snippet sc small caps text
\\textsc{${0:${VISUAL:text}}} \\textsc{${1:${VISUAL:text}}} ${0}
#Choosing font #Choosing font
snippet sf sans serife text snippet sf sans serife text
\\textsf{${0:${VISUAL:text}}} \\textsf{${1:${VISUAL:text}}} ${0}
snippet rm roman font text snippet rm roman font text
\\textrm{${0:${VISUAL:text}}} \\textrm{${1:${VISUAL:text}}} ${0}
snippet tt typewriter (monospace) text snippet tt typewriter (monospace) text
\\texttt{${0:${VISUAL:text}}} \\texttt{${1:${VISUAL:text}}} ${0}
#Math font #Math font
snippet mf mathfrak snippet mf mathfrak
\\mathfrak{${0:${VISUAL:text}}} \\mathfrak{${1:${VISUAL:text}}} ${0}
snippet mc mathcal snippet mc mathcal
\\mathcal{${0:${VISUAL:text}}} \\mathcal{${1:${VISUAL:text}}} ${0}
snippet ms mathscr snippet ms mathscr
\\mathscr{${0:${VISUAL:text}}} \\mathscr{${1:${VISUAL:text}}} ${0}
#misc #misc
snippet ft \footnote snippet ft \footnote
\\footnote{${0:${VISUAL:text}}} \\footnote{${1:${VISUAL:text}}} ${0}
snippet fig figure environment (includegraphics) snippet fig figure environment (includegraphics)
\\begin{figure} \\begin{figure}
\\begin{center} \\begin{center}
@ -259,12 +259,19 @@ snippet subfig subfigure environment
\\label{fig:${5}} \\label{fig:${5}}
\\end{subfigure} \\end{subfigure}
${0} ${0}
snippet tikzcd tikzcd environment snippet tikzcd tikzcd environment in equation
\begin{equation} \\begin{equation}
\begin{tikzcd} \\begin{tikzcd}
${1} ${1}
\end{tikzcd} \\end{tikzcd}
\end{equation} \\end{equation}
${0}
snippet tikzcd* tikzcd environment in equation*
\\begin{equation*}
\\begin{tikzcd}
${1}
\\end{tikzcd}
\\end{equation*}
${0} ${0}
#math #math
snippet stackrel \stackrel{}{} 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-pug https://github.com/digitaltoad/vim-pug
vim-yankstack https://github.com/maxbrunsfeld/vim-yankstack vim-yankstack https://github.com/maxbrunsfeld/vim-yankstack
lightline.vim https://github.com/itchyny/lightline.vim lightline.vim https://github.com/itchyny/lightline.vim
vim-abolish https://github.com/tpope/vim-abolish
""".strip() """.strip()
GITHUB_ZIP = '%s/archive/master.zip' GITHUB_ZIP = '%s/archive/master.zip'

View File

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