Updated plugins
This commit is contained in:
parent
7c643a2d9c
commit
02572caa95
84 changed files with 4588 additions and 1749 deletions
|
@ -89,7 +89,7 @@ I recommend reading the docs of these plugins to understand them better. Each pl
|
||||||
* [open_file_under_cursor.vim](https://github.com/amix/open_file_under_cursor.vim): Open file under cursor when pressing `gf`
|
* [open_file_under_cursor.vim](https://github.com/amix/open_file_under_cursor.vim): Open file under cursor when pressing `gf`
|
||||||
* [pathogen.vim](https://github.com/tpope/vim-pathogen): Manage your vim runtimepath
|
* [pathogen.vim](https://github.com/tpope/vim-pathogen): Manage your vim runtimepath
|
||||||
* [snipmate.vim](https://github.com/garbas/vim-snipmate): snipmate.vim aims to be a concise vim script that implements some of TextMate's snippets features in Vim
|
* [snipmate.vim](https://github.com/garbas/vim-snipmate): snipmate.vim aims to be a concise vim script that implements some of TextMate's snippets features in Vim
|
||||||
* [syntastic](https://github.com/scrooloose/syntastic): Syntax checking hacks for vim
|
* [ale](https://github.com/w0rp/ale): Syntax and lint checking for vim (async)
|
||||||
* [vim-commentary](https://github.com/tpope/vim-commentary): Comment stuff out. Use `gcc` to comment out a line (takes a count), `gc` to comment out the target of a motion. `gcu` uncomments a set of adjacent commented lines.
|
* [vim-commentary](https://github.com/tpope/vim-commentary): Comment stuff out. Use `gcc` to comment out a line (takes a count), `gc` to comment out the target of a motion. `gcu` uncomments a set of adjacent commented lines.
|
||||||
* [vim-expand-region](https://github.com/terryma/vim-expand-region): Allows you to visually select increasingly larger regions of text using the same key combination
|
* [vim-expand-region](https://github.com/terryma/vim-expand-region): Allows you to visually select increasingly larger regions of text using the same key combination
|
||||||
* [vim-fugitive](https://github.com/tpope/vim-fugitive): A Git wrapper so awesome, it should be illegal
|
* [vim-fugitive](https://github.com/tpope/vim-fugitive): A Git wrapper so awesome, it should be illegal
|
||||||
|
|
|
@ -130,8 +130,8 @@ function! s:ApplyMappings() "{{{
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if exists("g:ackpreview") " if auto preview in on, remap j and k keys
|
if exists("g:ackpreview") " if auto preview in on, remap j and k keys
|
||||||
nnoremap <buffer> <silent> j j<CR><C-W><C-W>
|
nnoremap <buffer> <silent> j j<CR><C-W><C-P>
|
||||||
nnoremap <buffer> <silent> k k<CR><C-W><C-W>
|
nnoremap <buffer> <silent> k k<CR><C-W><C-P>
|
||||||
nmap <buffer> <silent> <Down> j
|
nmap <buffer> <silent> <Down> j
|
||||||
nmap <buffer> <silent> <Up> k
|
nmap <buffer> <silent> <Up> k
|
||||||
endif
|
endif
|
||||||
|
|
|
@ -540,7 +540,7 @@ fu! s:bufparts(bufnr)
|
||||||
endf
|
endf
|
||||||
fu! ctrlp#buffers(...)
|
fu! ctrlp#buffers(...)
|
||||||
let ids = sort(filter(range(1, bufnr('$')), '(empty(getbufvar(v:val, "&bt"))'
|
let ids = sort(filter(range(1, bufnr('$')), '(empty(getbufvar(v:val, "&bt"))'
|
||||||
\ .' || s:isneovimterminal(v:val)) && getbufvar(v:val, "&bl")'), 's:compmreb')
|
\ .' || s:isterminal(v:val)) && getbufvar(v:val, "&bl")'), 's:compmreb')
|
||||||
if a:0 && a:1 == 'id'
|
if a:0 && a:1 == 'id'
|
||||||
retu ids
|
retu ids
|
||||||
el
|
el
|
||||||
|
@ -2031,7 +2031,7 @@ fu! ctrlp#normcmd(cmd, ...)
|
||||||
let buftypes = [ 'quickfix', 'help' ]
|
let buftypes = [ 'quickfix', 'help' ]
|
||||||
if a:0 < 2 && s:nosplit() | retu a:cmd | en
|
if a:0 < 2 && s:nosplit() | retu a:cmd | en
|
||||||
let norwins = filter(range(1, winnr('$')),
|
let norwins = filter(range(1, winnr('$')),
|
||||||
\ 'index(buftypes, getbufvar(winbufnr(v:val), "&bt")) == -1 || s:isneovimterminal(winbufnr(v:val))')
|
\ 'index(buftypes, getbufvar(winbufnr(v:val), "&bt")) == -1 || s:isterminal(winbufnr(v:val))')
|
||||||
for each in norwins
|
for each in norwins
|
||||||
let bufnr = winbufnr(each)
|
let bufnr = winbufnr(each)
|
||||||
if empty(bufname(bufnr)) && empty(getbufvar(bufnr, '&ft'))
|
if empty(bufname(bufnr)) && empty(getbufvar(bufnr, '&ft'))
|
||||||
|
@ -2305,8 +2305,8 @@ fu! s:delbuf()
|
||||||
cal s:PrtClearCache()
|
cal s:PrtClearCache()
|
||||||
endf
|
endf
|
||||||
|
|
||||||
fu! s:isneovimterminal(buf)
|
fu! s:isterminal(buf)
|
||||||
retu has('nvim') && getbufvar(a:buf, "&bt") == "terminal"
|
retu getbufvar(a:buf, "&bt") == "terminal"
|
||||||
endf
|
endf
|
||||||
" Entering & Exiting {{{2
|
" Entering & Exiting {{{2
|
||||||
fu! s:getenv()
|
fu! s:getenv()
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
*ctrlp.txt* 支持模糊匹配的 文件, 缓冲区, 最近最多使用, 标签, ... 检索. v1.79
|
*ctrlp.txt* 支持模糊匹配的 文件, 缓冲区, 最近最多使用, 标签, ... 检索. v1.80
|
||||||
*CtrlP* *ControlP* *'ctrlp'* *'ctrl-p'*
|
*CtrlP* *ControlP* *'ctrlp'* *'ctrl-p'*
|
||||||
===============================================================================
|
===============================================================================
|
||||||
# #
|
# #
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
*ctrlp.txt* Fuzzy file, buffer, mru, tag, ... finder. v1.79
|
*ctrlp.txt* Fuzzy file, buffer, mru, tag, ... finder. v1.80
|
||||||
*CtrlP* *ControlP* *'ctrlp'* *'ctrl-p'*
|
*CtrlP* *ControlP* *'ctrlp'* *'ctrl-p'*
|
||||||
===============================================================================
|
===============================================================================
|
||||||
# #
|
# #
|
||||||
|
|
|
@ -688,8 +688,8 @@ hi! link EasyMotionShade Comment
|
||||||
" }}}
|
" }}}
|
||||||
" Sneak: {{{
|
" Sneak: {{{
|
||||||
|
|
||||||
autocmd ColorScheme gruvbox hi! link Sneak Search
|
hi! link Sneak Search
|
||||||
autocmd ColorScheme gruvbox hi! link SneakLabel Search
|
hi! link SneakLabel Search
|
||||||
|
|
||||||
" }}}
|
" }}}
|
||||||
" Indent Guides: {{{
|
" Indent Guides: {{{
|
||||||
|
|
|
@ -1,37 +1,28 @@
|
||||||
_To assist in resolving your issue, provide as much information as possible, in place of the ellipses (`…`) below._
|
<!--- To assist in resolving your issue, provide as much information as possible. -->
|
||||||
|
|
||||||
---
|
### Environment
|
||||||
**Environment:** _Describe your Vim/NERDTree setup._
|
<!--- Describe your Vim/NERDTree setup. -->
|
||||||
|
|
||||||
>* Operating System: …
|
* Operating System:
|
||||||
>* Vim version `:version`: …
|
* Vim version `:version`:
|
||||||
>* NERDTree version `git rev-parse --short HEAD`: …
|
* NERDTree version `git rev-parse --short HEAD`:
|
||||||
>* NERDTree settings applied in your vimrc, if any:
|
* NERDTree settings applied in your vimrc, if any:
|
||||||
>
|
```vim
|
||||||
> ```
|
```
|
||||||
> …
|
|
||||||
> ```
|
|
||||||
|
|
||||||
**Process:** _List the steps that will recreate the issue._
|
### Process
|
||||||
|
<!--- List the steps that will recreate the issue. -->
|
||||||
|
|
||||||
>1. …
|
1.
|
||||||
|
|
||||||
**Current Result:** _Describe what you you currently experience from this process._
|
### Current Result
|
||||||
|
<!--- Describe what you you currently experience from this process. -->
|
||||||
|
|
||||||
>…
|
### Expected Result
|
||||||
|
<!--- Describe what you would have expected from this process. -->
|
||||||
|
|
||||||
**Expected Result:** _Describe what you would expect to have resulted from this process._
|
### Screenshot(s)
|
||||||
|
|
||||||
>…
|
### Possible Fix
|
||||||
|
<!--- If you have explored the code, share what you've found. -->
|
||||||
---
|
|
||||||
**Optional**
|
|
||||||
|
|
||||||
**Screenshot(s):**
|
|
||||||
|
|
||||||
>…
|
|
||||||
|
|
||||||
**Possible Fix:** _(Have you poked around in the code?)_
|
|
||||||
|
|
||||||
>…
|
|
||||||
|
|
||||||
|
|
|
@ -694,6 +694,16 @@ NERD tree. These options should be set in your vimrc.
|
||||||
|'NERDTreeCreatePrefix'| Specify a prefix to be used when creating the
|
|'NERDTreeCreatePrefix'| Specify a prefix to be used when creating the
|
||||||
NERDTree window.
|
NERDTree window.
|
||||||
|
|
||||||
|
|'NERDTreeRemoveFileCmd'| Specify a custom shell command to be used when
|
||||||
|
deleting files. Note that it should include
|
||||||
|
one space character at the end of the command
|
||||||
|
and it applies only to files.
|
||||||
|
|
||||||
|
|'NERDTreeRemoveDirCmd'| Specify a custom shell command to be used when
|
||||||
|
deleting directories. Note that it should
|
||||||
|
include one space character at the end of the
|
||||||
|
command and it applies only to directories.
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
3.2. Customisation details *NERDTreeOptionDetails*
|
3.2. Customisation details *NERDTreeOptionDetails*
|
||||||
|
|
||||||
|
|
|
@ -185,7 +185,7 @@ function! s:Creator._createTreeWin()
|
||||||
let splitLocation = g:NERDTreeWinPos ==# "left" ? "topleft " : "botright "
|
let splitLocation = g:NERDTreeWinPos ==# "left" ? "topleft " : "botright "
|
||||||
let splitSize = g:NERDTreeWinSize
|
let splitSize = g:NERDTreeWinSize
|
||||||
|
|
||||||
if !exists('t:NERDTreeBufName')
|
if !g:NERDTree.ExistsForTab()
|
||||||
let t:NERDTreeBufName = self._nextBufferName()
|
let t:NERDTreeBufName = self._nextBufferName()
|
||||||
silent! exec splitLocation . 'vertical ' . splitSize . ' new'
|
silent! exec splitLocation . 'vertical ' . splitSize . ' new'
|
||||||
silent! exec "edit " . t:NERDTreeBufName
|
silent! exec "edit " . t:NERDTreeBufName
|
||||||
|
|
|
@ -245,8 +245,14 @@ function! s:Path.delete()
|
||||||
if v:shell_error != 0
|
if v:shell_error != 0
|
||||||
throw "NERDTree.PathDeletionError: Could not delete directory: '" . self.str() . "'"
|
throw "NERDTree.PathDeletionError: Could not delete directory: '" . self.str() . "'"
|
||||||
endif
|
endif
|
||||||
|
else
|
||||||
|
if exists('g:NERDTreeRemoveFileCmd')
|
||||||
|
let cmd = g:NERDTreeRemoveFileCmd . self.str({'escape': 1})
|
||||||
|
let success = system(cmd)
|
||||||
else
|
else
|
||||||
let success = delete(self.str())
|
let success = delete(self.str())
|
||||||
|
endif
|
||||||
|
|
||||||
if success != 0
|
if success != 0
|
||||||
throw "NERDTree.PathDeletionError: Could not delete file: '" . self.str() . "'"
|
throw "NERDTree.PathDeletionError: Could not delete file: '" . self.str() . "'"
|
||||||
endif
|
endif
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
|
||||||
|
" TODO refactor: create glob function
|
||||||
|
" noremap \og :call<space>glob_linux#FileByGlobCurrentDir('**/*'.input('glob open '),"\\.git\\<bar>\\.hg\\<bar>node_modules\\<bar>\\.pyc" )<cr>
|
||||||
|
" noremap \og :call<space>glob_linux#FileByGlobCurrentDir('**/*'.input('glob open '),"default" )<cr>
|
||||||
|
function! glob_linux#FileByGlobCurrentDir(glob, exclude_pattern)
|
||||||
|
if a:exclude_pattern == "default"
|
||||||
|
let exclude_pattern = '\.git\|\.hg\|node_modules\|\.pyc'
|
||||||
|
else
|
||||||
|
let exclude_pattern = a:exclude_pattern
|
||||||
|
endif
|
||||||
|
|
||||||
|
" let files = split(glob(a:glob),"\n")
|
||||||
|
let g = a:glob
|
||||||
|
let replace = {'**': '.*','*': '[^/\]*','.': '\.'}
|
||||||
|
let g = substitute(g, '\(\*\*\|\*\|\.\)', '\='.string(replace).'[submatch(1)]','g')
|
||||||
|
|
||||||
|
let exclude = exclude_pattern == '' ? '' : ' | grep -v -e '.shellescape(exclude_pattern)
|
||||||
|
|
||||||
|
let cmd = 'find | grep -e '.shellescape(g).exclude
|
||||||
|
let files = split(system(cmd),"\n")
|
||||||
|
" for nom in a:excludes
|
||||||
|
" call filter(files,nom)
|
||||||
|
" endfor
|
||||||
|
if len(files) > 1000
|
||||||
|
echoe "more than ".2000." files - would be too slow. Open the file in another way"
|
||||||
|
else
|
||||||
|
if empty(files)
|
||||||
|
echoe "no file found"
|
||||||
|
elseif len(files) == 1
|
||||||
|
exec 'e '.fnameescape(files[0])
|
||||||
|
else
|
||||||
|
let g:abc=7
|
||||||
|
call tovl#ui#filter_list#ListView({
|
||||||
|
\ 'number' : 1,
|
||||||
|
\ 'selectByIdOrFilter' : 1,
|
||||||
|
\ 'Continuation' : funcref#Function('exec "e ".fnameescape(ARGS[0])'),
|
||||||
|
\ 'items' : files,
|
||||||
|
\ 'cmds' : ['wincmd J']
|
||||||
|
\ })
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
endfunction
|
|
@ -32,7 +32,7 @@ hi def link coffeeConditional Conditional
|
||||||
syn match coffeeException /\<\%(try\|catch\|finally\)\>/ display
|
syn match coffeeException /\<\%(try\|catch\|finally\)\>/ display
|
||||||
hi def link coffeeException Exception
|
hi def link coffeeException Exception
|
||||||
|
|
||||||
syn match coffeeKeyword /\<\%(new\|in\|of\|by\|and\|or\|not\|is\|isnt\|class\|extends\|super\|do\|yield\|debugger\|import\|export\|default\|await\)\>/
|
syn match coffeeKeyword /\<\%(new\|in\|of\|from\|by\|and\|or\|not\|is\|isnt\|class\|extends\|super\|do\|yield\|debugger\|import\|export\|default\|await\)\>/
|
||||||
\ display
|
\ display
|
||||||
" The `own` keyword is only a keyword after `for`.
|
" The `own` keyword is only a keyword after `for`.
|
||||||
syn match coffeeKeyword /\<for\s\+own\>/ contained containedin=coffeeRepeat
|
syn match coffeeKeyword /\<for\s\+own\>/ contained containedin=coffeeRepeat
|
||||||
|
|
|
@ -8,8 +8,14 @@ platform issues, and interactions with other plugins. I end up bisecting a
|
||||||
lot more than other projects, and thus I'm especially meticulous here about
|
lot more than other projects, and thus I'm especially meticulous here about
|
||||||
maintaining a clean, readable, history. Squash and force push any requested
|
maintaining a clean, readable, history. Squash and force push any requested
|
||||||
changes to a pull request. And if your [commit message
|
changes to a pull request. And if your [commit message
|
||||||
sucks](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html),
|
sucks](https://commit.style), I'm not going to accept it. Period.
|
||||||
I'm not going to accept it. Period.
|
|
||||||
|
If your contribution involves adding a configuration option, you are going to
|
||||||
|
need a very compelling justification for it. Options add a maintenance
|
||||||
|
burden, support burden, and documentation bloat, and oftentimes can be
|
||||||
|
achieved much more simply with a custom map or autocommand. If your option
|
||||||
|
controls an underlying Git command, ask yourself why Git itself does not offer
|
||||||
|
such configuration.
|
||||||
|
|
||||||
Beyond that, don't be shy about asking before patching. What takes you hours
|
Beyond that, don't be shy about asking before patching. What takes you hours
|
||||||
might take me minutes simply because I have both domain knowledge and a
|
might take me minutes simply because I have both domain knowledge and a
|
||||||
|
|
8
sources_non_forked/vim-gitgutter/.github/issue_template.md
vendored
Normal file
8
sources_non_forked/vim-gitgutter/.github/issue_template.md
vendored
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
> What is the latest commit SHA in your installed vim-gitgutter?
|
||||||
|
|
||||||
|
> What vim/nvim version are you on?
|
||||||
|
|
||||||
|
> If no signs are showing at all, what does `:echo b:gitgutter.path` give?
|
||||||
|
|
||||||
|
> If no signs are showing at all, and the `path` value is a path and not `-2`, does it work with `let g:gitgutter_grep=''`?
|
||||||
|
|
|
@ -1,12 +1,14 @@
|
||||||
## vim-gitgutter
|
## vim-gitgutter
|
||||||
|
|
||||||
A Vim plugin which shows a git diff in the 'gutter' (sign column). It shows whether each line has been added, modified, and where lines have been removed. You can also stage and undo individual hunks.
|
A Vim plugin which shows a git diff in the 'gutter' (sign column). It shows which lines have been added, modified, or removed. You can also preview, stage, and undo individual hunks. The plugin also provides a hunk text object.
|
||||||
|
|
||||||
|
The signs are always up to date and the plugin never saves your buffer.
|
||||||
|
|
||||||
Features:
|
Features:
|
||||||
|
|
||||||
* Shows signs for added, modified, and removed lines.
|
* Shows signs for added, modified, and removed lines.
|
||||||
* Runs the diffs asynchronously in terminal Vim/MacVim (7.4.1826+), gVim (7.4.1850+), MacVim GUI (7.4.1832+), and NeoVim.
|
* Runs the diffs asynchronously where possible.
|
||||||
* Ensures signs are always as up to date as possible (but without running more than necessary).
|
* Ensures signs are always up to date.
|
||||||
* Quick jumping between blocks of changed lines ("hunks").
|
* Quick jumping between blocks of changed lines ("hunks").
|
||||||
* Stage/undo/preview individual hunks.
|
* Stage/undo/preview individual hunks.
|
||||||
* Provides a hunk text object.
|
* Provides a hunk text object.
|
||||||
|
@ -21,9 +23,8 @@ Features:
|
||||||
|
|
||||||
Constraints:
|
Constraints:
|
||||||
|
|
||||||
* Supports git only.
|
* Supports git only. If you work with other version control systems, I recommend [vim-signify](https://github.com/mhinz/vim-signify).
|
||||||
|
* Relies on the `FocusGained` event. If your terminal doesn't report focus events, either use something like [Terminus][] or set `let g:gitgutter_terminal_reports_focus=0`.
|
||||||
If you work with other version control systems, I recommend [vim-signify](https://github.com/mhinz/vim-signify).
|
|
||||||
|
|
||||||
|
|
||||||
### Screenshot
|
### Screenshot
|
||||||
|
@ -39,7 +40,7 @@ In the screenshot above you can see:
|
||||||
|
|
||||||
### Installation
|
### Installation
|
||||||
|
|
||||||
Before installation, please check your Vim supports signs by running `:echo has('signs')`. `1` means you're all set; `0` means you need to install a Vim with signs support. If you're compiling Vim yourself you need the 'big' or 'huge' feature set. [MacVim][] supports signs.
|
Before installation, please check your Vim supports signs by running `:echo has('signs')`. `1` means you're all set; `0` means you need to install a Vim with signs support. If you're compiling Vim yourself you need the 'big' or 'huge' feature set. MacVim supports signs.
|
||||||
|
|
||||||
You install vim-gitgutter like any other vim plugin.
|
You install vim-gitgutter like any other vim plugin.
|
||||||
|
|
||||||
|
@ -100,16 +101,13 @@ cp -r vim-gitgutter/* ~/.vim/
|
||||||
See `:help add-global-plugin`.
|
See `:help add-global-plugin`.
|
||||||
|
|
||||||
|
|
||||||
If you are on Windows you may find the command prompt pops up briefly every time vim-gitgutter runs. You can avoid this by installing both [vim-misc](https://github.com/xolox/vim-misc) and [vim-shell](https://github.com/xolox/vim-shell). If you have those two plugins but don't want vim-gitgutter to use them, you can opt out with `let g:gitgutter_avoid_cmd_prompt_on_windows = 0` in your `~/.vimrc`.
|
|
||||||
|
|
||||||
|
|
||||||
### Getting started
|
### Getting started
|
||||||
|
|
||||||
When you make a change to a file tracked by git, the diff markers should appear automatically. The delay is governed by vim's `updatetime` option; the default value is 4 seconds but I suggest reducing it to around 250ms (add `set updatetime=250` to your vimrc).
|
When you make a change to a file tracked by git, the diff markers should appear automatically. The delay is governed by vim's `updatetime` option; the default value is `4000`, i.e. 4 seconds, but I suggest reducing it to around 100ms (add `set updatetime=100` to your vimrc).
|
||||||
|
|
||||||
You can jump between hunks with `[c` and `]c`. You can preview, stage, and undo hunks with `<leader>hp`, `<leader>hs`, and `<leader>hu` respectively.
|
You can jump between hunks with `[c` and `]c`. You can preview, stage, and undo hunks with `<leader>hp`, `<leader>hs`, and `<leader>hu` respectively.
|
||||||
|
|
||||||
You cannot currently unstage a staged hunk.
|
You cannot unstage a staged hunk.
|
||||||
|
|
||||||
|
|
||||||
#### Activation
|
#### Activation
|
||||||
|
@ -136,7 +134,7 @@ Note that if you have line highlighting on and signs off, you will have an empty
|
||||||
|
|
||||||
If you switch off both line highlighting and signs, you won't see the sign column. That is unless you configure the sign column always to be there (see Sign Column section).
|
If you switch off both line highlighting and signs, you won't see the sign column. That is unless you configure the sign column always to be there (see Sign Column section).
|
||||||
|
|
||||||
To keep your Vim snappy, vim-gitgutter will suppress itself when a file has more than 500 changes. As soon as the number of changes falls below the limit vim-gitgutter will show the signs again. You can configure the threshold with:
|
To keep your Vim snappy, vim-gitgutter will suppress the signs when a file has more than 500 changes. As soon as the number of changes falls below the limit vim-gitgutter will show the signs again. You can configure the threshold with:
|
||||||
|
|
||||||
```viml
|
```viml
|
||||||
let g:gitgutter_max_signs = 500 " default value
|
let g:gitgutter_max_signs = 500 " default value
|
||||||
|
@ -205,33 +203,6 @@ Finally, you can force vim-gitgutter to update its signs across all visible buff
|
||||||
See the customisation section below for how to change the defaults.
|
See the customisation section below for how to change the defaults.
|
||||||
|
|
||||||
|
|
||||||
### When are the signs updated?
|
|
||||||
|
|
||||||
By default the signs are updated as follows:
|
|
||||||
|
|
||||||
| Event | Reason for update | Configuration |
|
|
||||||
|---------------------------|--------------------------------------|------------------------|
|
|
||||||
| Stop typing | So the signs are real time | `g:gitgutter_realtime` |
|
|
||||||
| Switch buffer | To notice change to git index | `g:gitgutter_eager` |
|
|
||||||
| Switch tab | To notice change to git index | `g:gitgutter_eager` |
|
|
||||||
| Focus the GUI | To notice change to git index | `g:gitgutter_eager` (not gVim on Windows) |
|
|
||||||
| After shell command | To notice change to git index | `g:gitgutter_eager` |
|
|
||||||
| Read a file into a buffer | To display initial signs | [always] |
|
|
||||||
| Save a buffer | So non-realtime signs are up to date | [always] |
|
|
||||||
| Change a file outside Vim | To notice `git stash` | [always] |
|
|
||||||
|
|
||||||
The length of time Vim waits after you stop typing before it triggers the plugin is governed by the setting `updatetime`. This defaults to `4000` milliseconds which is rather too long. I recommend around `250` milliseconds but it depends on your system and your preferences. Note that in terminal Vim pre-7.4.427 an `updatetime` of less than approximately `1000` milliseconds can lead to random highlighting glitches; the lower the `updatetime`, the more glitches.
|
|
||||||
|
|
||||||
If you experience a lag, you can trade speed for accuracy:
|
|
||||||
|
|
||||||
```viml
|
|
||||||
let g:gitgutter_realtime = 0
|
|
||||||
let g:gitgutter_eager = 0
|
|
||||||
```
|
|
||||||
|
|
||||||
Note the realtime updating requires Vim 7.3.105 or higher.
|
|
||||||
|
|
||||||
|
|
||||||
### Customisation
|
### Customisation
|
||||||
|
|
||||||
You can customise:
|
You can customise:
|
||||||
|
@ -351,7 +322,7 @@ If you use an alternative to grep, you can tell vim-gitgutter to use it here.
|
||||||
|
|
||||||
```viml
|
```viml
|
||||||
" Default:
|
" Default:
|
||||||
let g:gitgutter_grep_command = 'grep'
|
let g:gitgutter_grep = 'grep'
|
||||||
```
|
```
|
||||||
|
|
||||||
#### To turn off vim-gitgutter by default
|
#### To turn off vim-gitgutter by default
|
||||||
|
@ -490,57 +461,53 @@ nmap <silent> [c :call PrevHunkAllBuffers()<CR>
|
||||||
|
|
||||||
### FAQ
|
### FAQ
|
||||||
|
|
||||||
|
> How can I turn off realtime updates?
|
||||||
|
|
||||||
|
Add this to your vim configuration (in an `/after/plugin` directory):
|
||||||
|
|
||||||
|
```viml
|
||||||
|
" .vim/after/plugin/gitgutter.vim
|
||||||
|
autocmd! gitgutter CursorHold,CursorHoldI
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
> Why can't I unstage staged changes?
|
> Why can't I unstage staged changes?
|
||||||
|
|
||||||
Unstaging staged hunks is feasible but not quite as easy as it sounds. There are three relevant versions of a file at any one time:
|
This plugin is for showing changes between the working tree and the index (and staging/undoing those changes). Unstaging a staged hunk would require showing changes between the index and HEAD, which is out of scope.
|
||||||
|
|
||||||
1. The version at HEAD in the repo.
|
|
||||||
2. The version staged in the index.
|
|
||||||
3. The version in the working tree, in your vim buffer.
|
|
||||||
|
|
||||||
`git-diff` without arguments shows you how 3 and 2 differ; this is what vim-gitgutter shows too.
|
|
||||||
|
|
||||||
`git-diff --staged` shows you how 2 and 1 differ.
|
|
||||||
|
|
||||||
Let's say you are looking at a file in vim which has some unstaged changes. Now you stage a hunk, either via vim-gitgutter or another means. The hunk is no longer marked in vim-gitgutter because it is the same in 3 and 2.
|
|
||||||
|
|
||||||
Now you want to unstage that hunk. To see it, you need the difference between 2 and 1. For vim-gitgutter to show those differences, it would need to show you 2 instead of 3 in your vim buffer. But 2 is virtual so vim-gitgutter would need to handle it without touching 3.
|
|
||||||
|
|
||||||
I intend to implement this but I can't commit to any deadline.
|
|
||||||
|
|
||||||
> Why are the colours in the sign column weird?
|
> Why are the colours in the sign column weird?
|
||||||
|
|
||||||
Your colorscheme is configuring the `SignColumn` highlight group weirdly. Please see the section above on customising the sign column.
|
Your colorscheme is configuring the `SignColumn` highlight group weirdly. Please see the section above on customising the sign column.
|
||||||
|
|
||||||
> There's a noticeable lag when vim-gitter runs; how can I avoid it?
|
|
||||||
|
|
||||||
By default vim-gitgutter runs often so the signs are as accurate as possible. The delay is governed by `updatetime`; see [above](#when-are-the-signs-updated) for more information.
|
|
||||||
|
|
||||||
If you don't want realtime updates and would like to trade a little accuracy for speed, add this to your `~/.vimrc`:
|
|
||||||
|
|
||||||
```viml
|
|
||||||
let g:gitgutter_realtime = 0
|
|
||||||
let g:gitgutter_eager = 0
|
|
||||||
```
|
|
||||||
|
|
||||||
> What happens if I also use another plugin which uses signs (e.g. Syntastic)?
|
> What happens if I also use another plugin which uses signs (e.g. Syntastic)?
|
||||||
|
|
||||||
Vim only allows one sign per line. Before adding a sign to a line, vim-gitgutter checks whether a sign has already been added by somebody else. If so it doesn't do anything. In other words vim-gitgutter won't overwrite another plugin's signs. It also won't remove another plugin's signs.
|
Vim only allows one sign per line. Before adding a sign to a line, vim-gitgutter checks whether a sign has already been added by somebody else. If so it doesn't do anything. In other words vim-gitgutter won't overwrite another plugin's signs. It also won't remove another plugin's signs.
|
||||||
|
|
||||||
> Why aren't any signs showing at all?
|
|
||||||
|
### Troubleshooting
|
||||||
|
|
||||||
|
#### When no signs are showing at all
|
||||||
|
|
||||||
Here are some things you can check:
|
Here are some things you can check:
|
||||||
|
|
||||||
* `:echo system("git --version")` succeeds.
|
* Try adding `let g:gitgutter_grep=''` to your vimrc. If it works, the problem is grep producing non-plain output; e.g. ANSI escape codes or colours.
|
||||||
* Your git config is compatible with the version of git returned by the command above.
|
* Verify `:echo system("git --version")` succeeds.
|
||||||
* Your Vim supports signs (`:echo has('signs')` should give `1`).
|
* Verify your git config is compatible with the version of git returned by the command above.
|
||||||
* Your file is being tracked by git and has unstaged changes.
|
* Verify your Vim supports signs (`:echo has('signs')` should give `1`).
|
||||||
* If you have aliased or configured `grep` to use any flags, add `let g:gitgutter_grep_command = 'grep'` to your `~/.vimrc`.
|
* Verify your file is being tracked by git and has unstaged changes.
|
||||||
|
|
||||||
> Why is the whole file marked as added when I edit it?
|
#### When the whole file is marked as added
|
||||||
|
|
||||||
* If you use zsh, and you set `CDPATH`, make sure `CDPATH` doesn't include the current directory.
|
* If you use zsh, and you set `CDPATH`, make sure `CDPATH` doesn't include the current directory.
|
||||||
|
|
||||||
|
#### When signs take a few seconds to appear
|
||||||
|
|
||||||
|
* Try reducing `updatetime`, e.g. `set updatetime=100`.
|
||||||
|
|
||||||
|
#### When signs don't update after focusing Vim
|
||||||
|
|
||||||
|
* Your terminal probably isn't reporting focus events. Either try installing [Terminus][] or set `let g:gitgutter_terminal_reports_focus=0`.
|
||||||
|
|
||||||
|
|
||||||
### Shameless Plug
|
### Shameless Plug
|
||||||
|
|
||||||
|
@ -561,4 +528,4 @@ Copyright Andrew Stewart, AirBlade Software Ltd. Released under the MIT licence
|
||||||
[pathogen]: https://github.com/tpope/vim-pathogen
|
[pathogen]: https://github.com/tpope/vim-pathogen
|
||||||
[siv]: http://pluralsight.com/training/Courses/TableOfContents/smash-into-vim
|
[siv]: http://pluralsight.com/training/Courses/TableOfContents/smash-into-vim
|
||||||
[airblade]: http://airbladesoftware.com/peepcode-vim
|
[airblade]: http://airbladesoftware.com/peepcode-vim
|
||||||
[macvim]: http://code.google.com/p/macvim/
|
[terminus]: https://github.com/wincent/terminus
|
||||||
|
|
|
@ -1,67 +1,54 @@
|
||||||
let s:nomodeline = (v:version > 703 || (v:version == 703 && has('patch442'))) ? '<nomodeline>' : ''
|
let s:t_string = type('')
|
||||||
|
|
||||||
" Primary functions {{{
|
" Primary functions {{{
|
||||||
|
|
||||||
function! gitgutter#all() abort
|
function! gitgutter#all(force) abort
|
||||||
for buffer_id in gitgutter#utility#dedup(tabpagebuflist())
|
for bufnr in s:uniq(tabpagebuflist())
|
||||||
let file = expand('#' . buffer_id . ':p')
|
let file = expand('#'.bufnr.':p')
|
||||||
if !empty(file)
|
if !empty(file)
|
||||||
call gitgutter#process_buffer(buffer_id, 0)
|
call gitgutter#init_buffer(bufnr)
|
||||||
|
call gitgutter#process_buffer(bufnr, a:force)
|
||||||
endif
|
endif
|
||||||
endfor
|
endfor
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
" bufnr: (integer) the buffer to process.
|
|
||||||
" realtime: (boolean) when truthy, do a realtime diff; otherwise do a disk-based diff.
|
|
||||||
function! gitgutter#process_buffer(bufnr, realtime) abort
|
|
||||||
call gitgutter#utility#use_known_shell()
|
|
||||||
|
|
||||||
call gitgutter#utility#set_buffer(a:bufnr)
|
" Finds the file's path relative to the repo root.
|
||||||
if gitgutter#utility#is_active()
|
function! gitgutter#init_buffer(bufnr)
|
||||||
if g:gitgutter_sign_column_always
|
if gitgutter#utility#is_active(a:bufnr)
|
||||||
call gitgutter#sign#add_dummy_sign()
|
let p = gitgutter#utility#repo_path(a:bufnr, 0)
|
||||||
|
if type(p) != s:t_string || empty(p)
|
||||||
|
call gitgutter#utility#set_repo_path(a:bufnr)
|
||||||
endif
|
endif
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
function! gitgutter#process_buffer(bufnr, force) abort
|
||||||
|
" NOTE a:bufnr is not necessarily the current buffer.
|
||||||
|
|
||||||
|
if gitgutter#utility#is_active(a:bufnr)
|
||||||
|
if a:force || s:has_fresh_changes(a:bufnr)
|
||||||
|
|
||||||
|
let diff = ''
|
||||||
try
|
try
|
||||||
if !a:realtime || gitgutter#utility#has_fresh_changes()
|
let diff = gitgutter#diff#run_diff(a:bufnr, 0)
|
||||||
let diff = gitgutter#diff#run_diff(a:realtime || gitgutter#utility#has_unsaved_changes(), 0)
|
catch /gitgutter not tracked/
|
||||||
if diff != 'async'
|
call gitgutter#debug#log('Not tracked: '.gitgutter#utility#file(a:bufnr))
|
||||||
call gitgutter#handle_diff(diff)
|
catch /gitgutter diff failed/
|
||||||
endif
|
call gitgutter#debug#log('Diff failed: '.gitgutter#utility#file(a:bufnr))
|
||||||
endif
|
call gitgutter#hunk#reset(a:bufnr)
|
||||||
catch /diff failed/
|
|
||||||
call gitgutter#debug#log('diff failed')
|
|
||||||
call gitgutter#hunk#reset()
|
|
||||||
endtry
|
endtry
|
||||||
execute "silent doautocmd" s:nomodeline "User GitGutter"
|
|
||||||
else
|
if diff != 'async'
|
||||||
call gitgutter#hunk#reset()
|
call gitgutter#diff#handler(a:bufnr, diff)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
call gitgutter#utility#restore_shell()
|
endif
|
||||||
|
endif
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
function! gitgutter#handle_diff(diff) abort
|
|
||||||
call gitgutter#debug#log(a:diff)
|
|
||||||
|
|
||||||
call gitgutter#utility#setbufvar(gitgutter#utility#bufnr(), 'tracked', 1)
|
|
||||||
|
|
||||||
call gitgutter#hunk#set_hunks(gitgutter#diff#parse_diff(a:diff))
|
|
||||||
let modified_lines = gitgutter#diff#process_hunks(gitgutter#hunk#hunks())
|
|
||||||
|
|
||||||
if len(modified_lines) > g:gitgutter_max_signs
|
|
||||||
call gitgutter#utility#warn_once('exceeded maximum number of signs (configured by g:gitgutter_max_signs).', 'max_signs')
|
|
||||||
call gitgutter#sign#clear_signs()
|
|
||||||
return
|
|
||||||
endif
|
|
||||||
|
|
||||||
if g:gitgutter_signs || g:gitgutter_highlight_lines
|
|
||||||
call gitgutter#sign#update_signs(modified_lines)
|
|
||||||
endif
|
|
||||||
|
|
||||||
call gitgutter#utility#save_last_seen_change()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function! gitgutter#disable() abort
|
function! gitgutter#disable() abort
|
||||||
" get list of all buffers (across all tabs)
|
" get list of all buffers (across all tabs)
|
||||||
let buflist = []
|
let buflist = []
|
||||||
|
@ -69,13 +56,10 @@ function! gitgutter#disable() abort
|
||||||
call extend(buflist, tabpagebuflist(i + 1))
|
call extend(buflist, tabpagebuflist(i + 1))
|
||||||
endfor
|
endfor
|
||||||
|
|
||||||
for buffer_id in gitgutter#utility#dedup(buflist)
|
for bufnr in s:uniq(buflist)
|
||||||
let file = expand('#' . buffer_id . ':p')
|
let file = expand('#'.bufnr.':p')
|
||||||
if !empty(file)
|
if !empty(file)
|
||||||
call gitgutter#utility#set_buffer(buffer_id)
|
call s:clear(bufnr)
|
||||||
call gitgutter#sign#clear_signs()
|
|
||||||
call gitgutter#sign#remove_dummy_sign(1)
|
|
||||||
call gitgutter#hunk#reset()
|
|
||||||
endif
|
endif
|
||||||
endfor
|
endfor
|
||||||
|
|
||||||
|
@ -84,7 +68,7 @@ endfunction
|
||||||
|
|
||||||
function! gitgutter#enable() abort
|
function! gitgutter#enable() abort
|
||||||
let g:gitgutter_enabled = 1
|
let g:gitgutter_enabled = 1
|
||||||
call gitgutter#all()
|
call gitgutter#all(1)
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! gitgutter#toggle() abort
|
function! gitgutter#toggle() abort
|
||||||
|
@ -97,163 +81,33 @@ endfunction
|
||||||
|
|
||||||
" }}}
|
" }}}
|
||||||
|
|
||||||
" Line highlights {{{
|
function! s:has_fresh_changes(bufnr) abort
|
||||||
|
return getbufvar(a:bufnr, 'changedtick') != gitgutter#utility#getbufvar(a:bufnr, 'tick')
|
||||||
function! gitgutter#line_highlights_disable() abort
|
|
||||||
let g:gitgutter_highlight_lines = 0
|
|
||||||
call gitgutter#highlight#define_sign_line_highlights()
|
|
||||||
|
|
||||||
if !g:gitgutter_signs
|
|
||||||
call gitgutter#sign#clear_signs()
|
|
||||||
call gitgutter#sign#remove_dummy_sign(0)
|
|
||||||
endif
|
|
||||||
|
|
||||||
redraw!
|
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! gitgutter#line_highlights_enable() abort
|
function! s:reset_tick(bufnr) abort
|
||||||
let old_highlight_lines = g:gitgutter_highlight_lines
|
call gitgutter#utility#setbufvar(a:bufnr, 'tick', 0)
|
||||||
|
|
||||||
let g:gitgutter_highlight_lines = 1
|
|
||||||
call gitgutter#highlight#define_sign_line_highlights()
|
|
||||||
|
|
||||||
if !old_highlight_lines && !g:gitgutter_signs
|
|
||||||
call gitgutter#all()
|
|
||||||
endif
|
|
||||||
|
|
||||||
redraw!
|
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! gitgutter#line_highlights_toggle() abort
|
function! s:clear(bufnr)
|
||||||
if g:gitgutter_highlight_lines
|
call gitgutter#sign#clear_signs(a:bufnr)
|
||||||
call gitgutter#line_highlights_disable()
|
call gitgutter#sign#remove_dummy_sign(a:bufnr, 1)
|
||||||
else
|
call gitgutter#hunk#reset(a:bufnr)
|
||||||
call gitgutter#line_highlights_enable()
|
call s:reset_tick(a:bufnr)
|
||||||
endif
|
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
" }}}
|
if exists('*uniq') " Vim 7.4.218
|
||||||
|
function! s:uniq(list)
|
||||||
" Signs {{{
|
return uniq(sort(a:list))
|
||||||
|
endfunction
|
||||||
function! gitgutter#signs_enable() abort
|
else
|
||||||
let old_signs = g:gitgutter_signs
|
function! s:uniq(list)
|
||||||
|
let processed = []
|
||||||
let g:gitgutter_signs = 1
|
for e in a:list
|
||||||
call gitgutter#highlight#define_sign_text_highlights()
|
if index(processed, e) == -1
|
||||||
|
call add(processed, e)
|
||||||
if !old_signs && !g:gitgutter_highlight_lines
|
|
||||||
call gitgutter#all()
|
|
||||||
endif
|
endif
|
||||||
endfunction
|
endfor
|
||||||
|
return processed
|
||||||
function! gitgutter#signs_disable() abort
|
endfunction
|
||||||
let g:gitgutter_signs = 0
|
endif
|
||||||
call gitgutter#highlight#define_sign_text_highlights()
|
|
||||||
|
|
||||||
if !g:gitgutter_highlight_lines
|
|
||||||
call gitgutter#sign#clear_signs()
|
|
||||||
call gitgutter#sign#remove_dummy_sign(0)
|
|
||||||
endif
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function! gitgutter#signs_toggle() abort
|
|
||||||
if g:gitgutter_signs
|
|
||||||
call gitgutter#signs_disable()
|
|
||||||
else
|
|
||||||
call gitgutter#signs_enable()
|
|
||||||
endif
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}
|
|
||||||
|
|
||||||
" Hunks {{{
|
|
||||||
|
|
||||||
function! gitgutter#stage_hunk() abort
|
|
||||||
call gitgutter#utility#use_known_shell()
|
|
||||||
if gitgutter#utility#is_active()
|
|
||||||
" Ensure the working copy of the file is up to date.
|
|
||||||
" It doesn't make sense to stage a hunk otherwise.
|
|
||||||
noautocmd silent write
|
|
||||||
let diff = gitgutter#diff#run_diff(0, 1)
|
|
||||||
call gitgutter#handle_diff(diff)
|
|
||||||
|
|
||||||
if empty(gitgutter#hunk#current_hunk())
|
|
||||||
call gitgutter#utility#warn('cursor is not in a hunk')
|
|
||||||
else
|
|
||||||
let diff_for_hunk = gitgutter#diff#generate_diff_for_hunk(diff, 'stage')
|
|
||||||
call gitgutter#utility#system(gitgutter#utility#command_in_directory_of_file(g:gitgutter_git_executable.' apply --cached --unidiff-zero - '), diff_for_hunk)
|
|
||||||
|
|
||||||
" refresh gitgutter's view of buffer
|
|
||||||
silent execute "GitGutter"
|
|
||||||
endif
|
|
||||||
|
|
||||||
silent! call repeat#set("\<Plug>GitGutterStageHunk", -1)<CR>
|
|
||||||
endif
|
|
||||||
call gitgutter#utility#restore_shell()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function! gitgutter#undo_hunk() abort
|
|
||||||
call gitgutter#utility#use_known_shell()
|
|
||||||
if gitgutter#utility#is_active()
|
|
||||||
" Ensure the working copy of the file is up to date.
|
|
||||||
" It doesn't make sense to stage a hunk otherwise.
|
|
||||||
noautocmd silent write
|
|
||||||
let diff = gitgutter#diff#run_diff(0, 1)
|
|
||||||
call gitgutter#handle_diff(diff)
|
|
||||||
|
|
||||||
if empty(gitgutter#hunk#current_hunk())
|
|
||||||
call gitgutter#utility#warn('cursor is not in a hunk')
|
|
||||||
else
|
|
||||||
let diff_for_hunk = gitgutter#diff#generate_diff_for_hunk(diff, 'undo')
|
|
||||||
call gitgutter#utility#system(gitgutter#utility#command_in_directory_of_file(g:gitgutter_git_executable.' apply --reverse --unidiff-zero - '), diff_for_hunk)
|
|
||||||
|
|
||||||
" reload file preserving screen line position
|
|
||||||
" CTRL-Y and CTRL-E treat negative counts as positive counts.
|
|
||||||
let x = line('w0')
|
|
||||||
silent edit
|
|
||||||
let y = line('w0')
|
|
||||||
let z = x - y
|
|
||||||
if z > 0
|
|
||||||
execute "normal! ".z."\<C-E>"
|
|
||||||
else
|
|
||||||
execute "normal! ".z."\<C-Y>"
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
|
|
||||||
silent! call repeat#set("\<Plug>GitGutterUndoHunk", -1)<CR>
|
|
||||||
endif
|
|
||||||
call gitgutter#utility#restore_shell()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function! gitgutter#preview_hunk() abort
|
|
||||||
call gitgutter#utility#use_known_shell()
|
|
||||||
if gitgutter#utility#is_active()
|
|
||||||
" Ensure the working copy of the file is up to date.
|
|
||||||
" It doesn't make sense to stage a hunk otherwise.
|
|
||||||
noautocmd silent write
|
|
||||||
let diff = gitgutter#diff#run_diff(0, 1)
|
|
||||||
call gitgutter#handle_diff(diff)
|
|
||||||
|
|
||||||
if empty(gitgutter#hunk#current_hunk())
|
|
||||||
call gitgutter#utility#warn('cursor is not in a hunk')
|
|
||||||
else
|
|
||||||
let diff_for_hunk = gitgutter#diff#generate_diff_for_hunk(diff, 'preview')
|
|
||||||
|
|
||||||
silent! wincmd P
|
|
||||||
if !&previewwindow
|
|
||||||
noautocmd execute 'bo' &previewheight 'new'
|
|
||||||
set previewwindow
|
|
||||||
endif
|
|
||||||
|
|
||||||
setlocal noro modifiable filetype=diff buftype=nofile bufhidden=delete noswapfile
|
|
||||||
execute "%delete_"
|
|
||||||
call append(0, split(diff_for_hunk, "\n"))
|
|
||||||
|
|
||||||
noautocmd wincmd p
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
call gitgutter#utility#restore_shell()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}
|
|
||||||
|
|
|
@ -11,10 +11,13 @@ function! gitgutter#async#available()
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
function! gitgutter#async#execute(cmd) abort
|
function! gitgutter#async#execute(cmd, bufnr, handler) abort
|
||||||
|
call gitgutter#debug#log('[async] '.a:cmd)
|
||||||
|
|
||||||
let options = {
|
let options = {
|
||||||
\ 'stdoutbuffer': [],
|
\ 'stdoutbuffer': [],
|
||||||
\ 'buffer': gitgutter#utility#bufnr()
|
\ 'buffer': a:bufnr,
|
||||||
|
\ 'handler': a:handler
|
||||||
\ }
|
\ }
|
||||||
let command = s:build_command(a:cmd)
|
let command = s:build_command(a:cmd)
|
||||||
|
|
||||||
|
@ -58,33 +61,13 @@ function! s:on_stdout_nvim(_job_id, data, _event) dict abort
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! s:on_stderr_nvim(_job_id, _data, _event) dict abort
|
function! s:on_stderr_nvim(_job_id, _data, _event) dict abort
|
||||||
" Backward compatibility for nvim < 0.2.0
|
call self.handler.err(self.buffer)
|
||||||
if !has('nvim-0.2.0')
|
|
||||||
let current_buffer = gitgutter#utility#bufnr()
|
|
||||||
call gitgutter#utility#set_buffer(self.buffer)
|
|
||||||
if gitgutter#utility#is_active()
|
|
||||||
call gitgutter#hunk#reset()
|
|
||||||
endif
|
|
||||||
call gitgutter#utility#set_buffer(current_buffer)
|
|
||||||
return
|
|
||||||
endif
|
|
||||||
|
|
||||||
call s:buffer_exec(self.buffer, function('gitgutter#hunk#reset'))
|
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! s:on_exit_nvim(_job_id, _data, _event) dict abort
|
function! s:on_exit_nvim(_job_id, exit_code, _event) dict abort
|
||||||
" Backward compatibility for nvim < 0.2.0
|
if !a:exit_code
|
||||||
if !has('nvim-0.2.0')
|
call self.handler.out(self.buffer, join(self.stdoutbuffer, "\n"))
|
||||||
let current_buffer = gitgutter#utility#bufnr()
|
|
||||||
call gitgutter#utility#set_buffer(self.buffer)
|
|
||||||
if gitgutter#utility#is_active()
|
|
||||||
call gitgutter#handle_diff(gitgutter#utility#stringify(self.stdoutbuffer))
|
|
||||||
endif
|
endif
|
||||||
call gitgutter#utility#set_buffer(current_buffer)
|
|
||||||
return
|
|
||||||
endif
|
|
||||||
|
|
||||||
call s:buffer_exec(self.buffer, function('gitgutter#handle_diff', [gitgutter#utility#stringify(self.stdoutbuffer)]))
|
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
@ -92,22 +75,15 @@ function! s:on_stdout_vim(_channel, data) dict abort
|
||||||
call add(self.stdoutbuffer, a:data)
|
call add(self.stdoutbuffer, a:data)
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! s:on_stderr_vim(_channel, _data) dict abort
|
function! s:on_stderr_vim(channel, _data) dict abort
|
||||||
call s:buffer_exec(self.buffer, function('gitgutter#hunk#reset'))
|
call self.handler.err(self.buffer)
|
||||||
|
try
|
||||||
|
call ch_close(a:channel) " so close_cb and its 'out' handler are not triggered
|
||||||
|
catch /E906/
|
||||||
|
" noop
|
||||||
|
endtry
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! s:on_exit_vim(_channel) dict abort
|
function! s:on_exit_vim(_channel) dict abort
|
||||||
call s:buffer_exec(self.buffer, function('gitgutter#handle_diff', [gitgutter#utility#stringify(self.stdoutbuffer)]))
|
call self.handler.out(self.buffer, join(self.stdoutbuffer, "\n"))
|
||||||
endfunction
|
|
||||||
|
|
||||||
|
|
||||||
function! s:buffer_exec(buffer, fn)
|
|
||||||
let current_buffer = gitgutter#utility#bufnr()
|
|
||||||
call gitgutter#utility#set_buffer(a:buffer)
|
|
||||||
|
|
||||||
if gitgutter#utility#is_active()
|
|
||||||
call a:fn()
|
|
||||||
endif
|
|
||||||
|
|
||||||
call gitgutter#utility#set_buffer(current_buffer)
|
|
||||||
endfunction
|
endfunction
|
||||||
|
|
|
@ -12,67 +12,67 @@ function! gitgutter#debug#debug()
|
||||||
setlocal bufhidden=delete
|
setlocal bufhidden=delete
|
||||||
setlocal noswapfile
|
setlocal noswapfile
|
||||||
|
|
||||||
call gitgutter#debug#vim_version()
|
call s:vim_version()
|
||||||
call gitgutter#debug#separator()
|
call s:separator()
|
||||||
|
|
||||||
call gitgutter#debug#git_version()
|
call s:git_version()
|
||||||
call gitgutter#debug#separator()
|
call s:separator()
|
||||||
|
|
||||||
call gitgutter#debug#grep_version()
|
call s:grep_version()
|
||||||
call gitgutter#debug#separator()
|
call s:separator()
|
||||||
|
|
||||||
call gitgutter#debug#option('updatetime')
|
call s:option('updatetime')
|
||||||
call gitgutter#debug#option('shell')
|
call s:option('shell')
|
||||||
call gitgutter#debug#option('shellcmdflag')
|
call s:option('shellcmdflag')
|
||||||
call gitgutter#debug#option('shellpipe')
|
call s:option('shellpipe')
|
||||||
call gitgutter#debug#option('shellquote')
|
call s:option('shellquote')
|
||||||
call gitgutter#debug#option('shellredir')
|
call s:option('shellredir')
|
||||||
call gitgutter#debug#option('shellslash')
|
call s:option('shellslash')
|
||||||
call gitgutter#debug#option('shelltemp')
|
call s:option('shelltemp')
|
||||||
call gitgutter#debug#option('shelltype')
|
call s:option('shelltype')
|
||||||
call gitgutter#debug#option('shellxescape')
|
call s:option('shellxescape')
|
||||||
call gitgutter#debug#option('shellxquote')
|
call s:option('shellxquote')
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
function! gitgutter#debug#separator()
|
function! s:separator()
|
||||||
call gitgutter#debug#output('')
|
call s:output('')
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! gitgutter#debug#vim_version()
|
function! s:vim_version()
|
||||||
redir => version_info
|
redir => version_info
|
||||||
silent execute 'version'
|
silent execute 'version'
|
||||||
redir END
|
redir END
|
||||||
call gitgutter#debug#output(split(version_info, '\n')[0:2])
|
call s:output(split(version_info, '\n')[0:2])
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! gitgutter#debug#git_version()
|
function! s:git_version()
|
||||||
let v = system(g:gitgutter_git_executable.' --version')
|
let v = system(g:gitgutter_git_executable.' --version')
|
||||||
call gitgutter#debug#output( substitute(v, '\n$', '', '') )
|
call s:output( substitute(v, '\n$', '', '') )
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! gitgutter#debug#grep_version()
|
function! s:grep_version()
|
||||||
let v = system('grep --version')
|
let v = system('grep --version')
|
||||||
call gitgutter#debug#output( substitute(v, '\n$', '', '') )
|
call s:output( substitute(v, '\n$', '', '') )
|
||||||
|
|
||||||
let v = system('grep --help')
|
let v = system('grep --help')
|
||||||
call gitgutter#debug#output( substitute(v, '\%x00', '', 'g') )
|
call s:output( substitute(v, '\%x00', '', 'g') )
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! gitgutter#debug#option(name)
|
function! s:option(name)
|
||||||
if exists('+' . a:name)
|
if exists('+' . a:name)
|
||||||
let v = eval('&' . a:name)
|
let v = eval('&' . a:name)
|
||||||
call gitgutter#debug#output(a:name . '=' . v)
|
call s:output(a:name . '=' . v)
|
||||||
" redir => output
|
" redir => output
|
||||||
" silent execute "verbose set " . a:name . "?"
|
" silent execute "verbose set " . a:name . "?"
|
||||||
" redir END
|
" redir END
|
||||||
" call gitgutter#debug#output(a:name . '=' . output)
|
" call s:output(a:name . '=' . output)
|
||||||
else
|
else
|
||||||
call gitgutter#debug#output(a:name . ' [n/a]')
|
call s:output(a:name . ' [n/a]')
|
||||||
end
|
end
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! gitgutter#debug#output(text)
|
function! s:output(text)
|
||||||
call append(line('$'), a:text)
|
call append(line('$'), a:text)
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
|
@ -1,152 +1,176 @@
|
||||||
if exists('g:gitgutter_grep_command')
|
let s:nomodeline = (v:version > 703 || (v:version == 703 && has('patch442'))) ? '<nomodeline>' : ''
|
||||||
let s:grep_available = 1
|
|
||||||
let s:grep_command = g:gitgutter_grep_command
|
|
||||||
else
|
|
||||||
let s:grep_available = executable('grep')
|
|
||||||
if s:grep_available
|
|
||||||
let s:grep_command = 'grep'
|
|
||||||
if $GREP_OPTIONS =~# '--color=always'
|
|
||||||
let s:grep_command .= ' --color=never'
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
let s:hunk_re = '^@@ -\(\d\+\),\?\(\d*\) +\(\d\+\),\?\(\d*\) @@'
|
let s:hunk_re = '^@@ -\(\d\+\),\?\(\d*\) +\(\d\+\),\?\(\d*\) @@'
|
||||||
|
|
||||||
let s:c_flag = gitgutter#utility#git_supports_command_line_config_override()
|
" True for git v1.7.2+.
|
||||||
|
function! s:git_supports_command_line_config_override() abort
|
||||||
|
call system(g:gitgutter_git_executable.' -c foo.bar=baz --version')
|
||||||
|
return !v:shell_error
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
let s:c_flag = s:git_supports_command_line_config_override()
|
||||||
|
|
||||||
|
|
||||||
let s:temp_index = tempname()
|
let s:temp_index = tempname()
|
||||||
let s:temp_buffer = tempname()
|
let s:temp_buffer = tempname()
|
||||||
|
|
||||||
" Returns a diff of the buffer.
|
" Returns a diff of the buffer.
|
||||||
"
|
"
|
||||||
" The way to get the diff depends on whether the buffer is saved or unsaved.
|
" The buffer contents is not the same as the file on disk so we need to pass
|
||||||
"
|
" two instances of the file to git-diff:
|
||||||
" * Saved: the buffer contents is the same as the file on disk in the working
|
|
||||||
" tree so we simply do:
|
|
||||||
"
|
|
||||||
" git diff myfile
|
|
||||||
"
|
|
||||||
" * Unsaved: the buffer contents is not the same as the file on disk so we
|
|
||||||
" need to pass two instances of the file to git-diff:
|
|
||||||
"
|
"
|
||||||
" git diff myfileA myfileB
|
" git diff myfileA myfileB
|
||||||
"
|
"
|
||||||
" The first instance is the file in the index which we obtain with:
|
" where myfileA comes from
|
||||||
"
|
"
|
||||||
" git show :myfile > myfileA
|
" git show :myfile > myfileA
|
||||||
"
|
"
|
||||||
" The second instance is the buffer contents. Ideally we would pass this to
|
" and myfileB is the buffer contents.
|
||||||
" git-diff on stdin via the second argument to vim's system() function.
|
|
||||||
" Unfortunately git-diff does not do CRLF conversion for input received on
|
|
||||||
" stdin, and git-show never performs CRLF conversion, so repos with CRLF
|
|
||||||
" conversion report that every line is modified due to mismatching EOLs.
|
|
||||||
"
|
|
||||||
" Instead, we write the buffer contents to a temporary file - myfileB in this
|
|
||||||
" example. Note the file extension must be preserved for the CRLF
|
|
||||||
" conversion to work.
|
|
||||||
"
|
|
||||||
" Before diffing a buffer for the first time, we check whether git knows about
|
|
||||||
" the file:
|
|
||||||
"
|
|
||||||
" git ls-files --error-unmatch myfile
|
|
||||||
"
|
"
|
||||||
" After running the diff we pass it through grep where available to reduce
|
" After running the diff we pass it through grep where available to reduce
|
||||||
" subsequent processing by the plugin. If grep is not available the plugin
|
" subsequent processing by the plugin. If grep is not available the plugin
|
||||||
" does the filtering instead.
|
" does the filtering instead.
|
||||||
function! gitgutter#diff#run_diff(realtime, preserve_full_diff) abort
|
"
|
||||||
|
"
|
||||||
|
" Regarding line endings:
|
||||||
|
"
|
||||||
|
" git-show does not convert line endings.
|
||||||
|
" git-diff FILE FILE does convert line endings for the given files.
|
||||||
|
"
|
||||||
|
" If a file has CRLF line endings and git's core.autocrlf is true,
|
||||||
|
" the file in git's object store will have LF line endings. Writing
|
||||||
|
" it out via git-show will produce a file with LF line endings.
|
||||||
|
"
|
||||||
|
" If this last file is one of the files passed to git-diff, git-diff will
|
||||||
|
" convert its line endings to CRLF before diffing -- which is what we want --
|
||||||
|
" but also by default output a warning on stderr.
|
||||||
|
"
|
||||||
|
" warning: LF will be replace by CRLF in <temp file>.
|
||||||
|
" The file will have its original line endings in your working directory.
|
||||||
|
"
|
||||||
|
" When running the diff asynchronously, the warning message triggers the stderr
|
||||||
|
" callbacks which assume the overall command has failed and reset all the
|
||||||
|
" signs. As this is not what we want, and we can safely ignore the warning,
|
||||||
|
" we turn it off by passing the '-c "core.safecrlf=false"' argument to
|
||||||
|
" git-diff.
|
||||||
|
"
|
||||||
|
" When writing the temporary files we preserve the original file's extension
|
||||||
|
" so that repos using .gitattributes to control EOL conversion continue to
|
||||||
|
" convert correctly.
|
||||||
|
function! gitgutter#diff#run_diff(bufnr, preserve_full_diff) abort
|
||||||
|
while gitgutter#utility#repo_path(a:bufnr, 0) == -1
|
||||||
|
sleep 5m
|
||||||
|
endwhile
|
||||||
|
|
||||||
|
if gitgutter#utility#repo_path(a:bufnr, 0) == -2
|
||||||
|
throw 'gitgutter not tracked'
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
" Wrap compound commands in parentheses to make Windows happy.
|
" Wrap compound commands in parentheses to make Windows happy.
|
||||||
" bash doesn't mind the parentheses.
|
" bash doesn't mind the parentheses.
|
||||||
let cmd = '('
|
let cmd = '('
|
||||||
|
|
||||||
let bufnr = gitgutter#utility#bufnr()
|
" Append buffer number to avoid race conditions between writing and reading
|
||||||
let tracked = gitgutter#utility#getbufvar(bufnr, 'tracked', 0) " i.e. tracked by git
|
" the files when asynchronously processing multiple buffers.
|
||||||
if !tracked
|
"
|
||||||
" Don't bother trying to realtime-diff an untracked file.
|
" Without the buffer number, index_file would have a race in the shell
|
||||||
" NOTE: perhaps we should pull this guard up to the caller?
|
" between the second process writing it (with git-show) and the first
|
||||||
if a:realtime
|
" reading it (with git-diff).
|
||||||
throw 'diff failed'
|
let index_file = s:temp_index.'.'.a:bufnr
|
||||||
else
|
|
||||||
let cmd .= g:gitgutter_git_executable.' ls-files --error-unmatch '.gitgutter#utility#shellescape(gitgutter#utility#filename()).' && ('
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
|
|
||||||
if a:realtime
|
" Without the buffer number, buff_file would have a race between the
|
||||||
let blob_name = g:gitgutter_diff_base.':'.gitgutter#utility#shellescape(gitgutter#utility#file_relative_to_repo_root())
|
" second gitgutter#process_buffer() writing the file (synchronously, below)
|
||||||
let blob_file = s:temp_index
|
" and the first gitgutter#process_buffer()'s async job reading it (with
|
||||||
let buff_file = s:temp_buffer
|
" git-diff).
|
||||||
let extension = gitgutter#utility#extension()
|
let buff_file = s:temp_buffer.'.'.a:bufnr
|
||||||
|
|
||||||
|
let extension = gitgutter#utility#extension(a:bufnr)
|
||||||
if !empty(extension)
|
if !empty(extension)
|
||||||
let blob_file .= '.'.extension
|
let index_file .= '.'.extension
|
||||||
let buff_file .= '.'.extension
|
let buff_file .= '.'.extension
|
||||||
endif
|
endif
|
||||||
let cmd .= g:gitgutter_git_executable.' show '.blob_name.' > '.blob_file.' && '
|
|
||||||
|
|
||||||
" Writing the whole buffer resets the '[ and '] marks and also the
|
" Write file from index to temporary file.
|
||||||
" 'modified' flag (if &cpoptions includes '+'). These are unwanted
|
let index_name = g:gitgutter_diff_base.':'.gitgutter#utility#repo_path(a:bufnr, 1)
|
||||||
" side-effects so we save and restore the values ourselves.
|
let cmd .= g:gitgutter_git_executable.' --no-pager show '.index_name.' > '.index_file.' && '
|
||||||
let modified = getbufvar(bufnr, "&mod")
|
|
||||||
let op_mark_start = getpos("'[")
|
|
||||||
let op_mark_end = getpos("']")
|
|
||||||
|
|
||||||
let current_buffer = bufnr('')
|
" Write buffer to temporary file.
|
||||||
execute 'buffer '.bufnr
|
" Note: this is synchronous.
|
||||||
execute 'keepalt noautocmd silent write!' buff_file
|
call s:write_buffer(a:bufnr, buff_file)
|
||||||
execute 'buffer '.current_buffer
|
|
||||||
|
|
||||||
call setbufvar(bufnr, "&mod", modified)
|
" Call git-diff with the temporary files.
|
||||||
call setpos("'[", op_mark_start)
|
let cmd .= g:gitgutter_git_executable.' --no-pager'
|
||||||
call setpos("']", op_mark_end)
|
|
||||||
endif
|
|
||||||
|
|
||||||
let cmd .= g:gitgutter_git_executable
|
|
||||||
if s:c_flag
|
if s:c_flag
|
||||||
let cmd .= ' -c "diff.autorefreshindex=0"'
|
let cmd .= ' -c "diff.autorefreshindex=0"'
|
||||||
let cmd .= ' -c "diff.noprefix=false"'
|
let cmd .= ' -c "diff.noprefix=false"'
|
||||||
|
let cmd .= ' -c "core.safecrlf=false"'
|
||||||
endif
|
endif
|
||||||
let cmd .= ' diff --no-ext-diff --no-color -U0 '.g:gitgutter_diff_args.' '
|
let cmd .= ' diff --no-ext-diff --no-color -U0 '.g:gitgutter_diff_args.' -- '.index_file.' '.buff_file
|
||||||
|
|
||||||
if a:realtime
|
" Pipe git-diff output into grep.
|
||||||
let cmd .= ' -- '.blob_file.' '.buff_file
|
if !a:preserve_full_diff && !empty(g:gitgutter_grep)
|
||||||
else
|
let cmd .= ' | '.g:gitgutter_grep.' '.gitgutter#utility#shellescape('^@@ ')
|
||||||
let cmd .= g:gitgutter_diff_base.' -- '.gitgutter#utility#shellescape(gitgutter#utility#filename())
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if !a:preserve_full_diff && s:grep_available
|
" grep exits with 1 when no matches are found; git-diff exits with 1 when
|
||||||
let cmd .= ' | '.s:grep_command.' '.gitgutter#utility#shellescape('^@@ ')
|
|
||||||
endif
|
|
||||||
|
|
||||||
if (!a:preserve_full_diff && s:grep_available) || a:realtime
|
|
||||||
" grep exits with 1 when no matches are found; diff exits with 1 when
|
|
||||||
" differences are found. However we want to treat non-matches and
|
" differences are found. However we want to treat non-matches and
|
||||||
" differences as non-erroneous behaviour; so we OR the command with one
|
" differences as non-erroneous behaviour; so we OR the command with one
|
||||||
" which always exits with success (0).
|
" which always exits with success (0).
|
||||||
let cmd .= ' || exit 0'
|
let cmd .= ' || exit 0'
|
||||||
endif
|
|
||||||
|
|
||||||
let cmd .= ')'
|
let cmd .= ')'
|
||||||
|
|
||||||
if !tracked
|
let cmd = gitgutter#utility#cd_cmd(a:bufnr, cmd)
|
||||||
let cmd .= ')'
|
|
||||||
endif
|
|
||||||
|
|
||||||
let cmd = gitgutter#utility#command_in_directory_of_file(cmd)
|
if g:gitgutter_async && gitgutter#async#available()
|
||||||
|
call gitgutter#async#execute(cmd, a:bufnr, {
|
||||||
if g:gitgutter_async && gitgutter#async#available() && !a:preserve_full_diff
|
\ 'out': function('gitgutter#diff#handler'),
|
||||||
call gitgutter#async#execute(cmd)
|
\ 'err': function('gitgutter#hunk#reset'),
|
||||||
|
\ })
|
||||||
return 'async'
|
return 'async'
|
||||||
|
|
||||||
else
|
else
|
||||||
let diff = gitgutter#utility#system(cmd)
|
let diff = gitgutter#utility#system(cmd)
|
||||||
|
|
||||||
if gitgutter#utility#shell_error()
|
if v:shell_error
|
||||||
" A shell error indicates the file is not tracked by git (unless something bizarre is going on).
|
call gitgutter#debug#log(diff)
|
||||||
throw 'diff failed'
|
throw 'gitgutter diff failed'
|
||||||
endif
|
endif
|
||||||
|
|
||||||
return diff
|
return diff
|
||||||
endif
|
endif
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
function! gitgutter#diff#handler(bufnr, diff) abort
|
||||||
|
call gitgutter#debug#log(a:diff)
|
||||||
|
|
||||||
|
call gitgutter#hunk#set_hunks(a:bufnr, gitgutter#diff#parse_diff(a:diff))
|
||||||
|
let modified_lines = gitgutter#diff#process_hunks(a:bufnr, gitgutter#hunk#hunks(a:bufnr))
|
||||||
|
|
||||||
|
let signs_count = len(modified_lines)
|
||||||
|
if signs_count > g:gitgutter_max_signs
|
||||||
|
call gitgutter#utility#warn_once(a:bufnr, printf(
|
||||||
|
\ 'exceeded maximum number of signs (%d > %d, configured by g:gitgutter_max_signs).',
|
||||||
|
\ signs_count, g:gitgutter_max_signs), 'max_signs')
|
||||||
|
call gitgutter#sign#clear_signs(a:bufnr)
|
||||||
|
|
||||||
|
else
|
||||||
|
if g:gitgutter_signs || g:gitgutter_highlight_lines
|
||||||
|
call gitgutter#sign#update_signs(a:bufnr, modified_lines)
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
call s:save_last_seen_change(a:bufnr)
|
||||||
|
if exists('#User#GitGutter')
|
||||||
|
let g:gitgutter_hook_context = {'bufnr': a:bufnr}
|
||||||
|
execute 'doautocmd' s:nomodeline 'User GitGutter'
|
||||||
|
unlet g:gitgutter_hook_context
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
function! gitgutter#diff#parse_diff(diff) abort
|
function! gitgutter#diff#parse_diff(diff) abort
|
||||||
let hunks = []
|
let hunks = []
|
||||||
for line in split(a:diff, '\n')
|
for line in split(a:diff, '\n')
|
||||||
|
@ -171,69 +195,71 @@ function! gitgutter#diff#parse_hunk(line) abort
|
||||||
end
|
end
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! gitgutter#diff#process_hunks(hunks) abort
|
" This function is public so it may be used by other plugins
|
||||||
|
" e.g. vim-signature.
|
||||||
|
function! gitgutter#diff#process_hunks(bufnr, hunks) abort
|
||||||
let modified_lines = []
|
let modified_lines = []
|
||||||
for hunk in a:hunks
|
for hunk in a:hunks
|
||||||
call extend(modified_lines, gitgutter#diff#process_hunk(hunk))
|
call extend(modified_lines, s:process_hunk(a:bufnr, hunk))
|
||||||
endfor
|
endfor
|
||||||
return modified_lines
|
return modified_lines
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
" Returns [ [<line_number (number)>, <name (string)>], ...]
|
" Returns [ [<line_number (number)>, <name (string)>], ...]
|
||||||
function! gitgutter#diff#process_hunk(hunk) abort
|
function! s:process_hunk(bufnr, hunk) abort
|
||||||
let modifications = []
|
let modifications = []
|
||||||
let from_line = a:hunk[0]
|
let from_line = a:hunk[0]
|
||||||
let from_count = a:hunk[1]
|
let from_count = a:hunk[1]
|
||||||
let to_line = a:hunk[2]
|
let to_line = a:hunk[2]
|
||||||
let to_count = a:hunk[3]
|
let to_count = a:hunk[3]
|
||||||
|
|
||||||
if gitgutter#diff#is_added(from_count, to_count)
|
if s:is_added(from_count, to_count)
|
||||||
call gitgutter#diff#process_added(modifications, from_count, to_count, to_line)
|
call s:process_added(modifications, from_count, to_count, to_line)
|
||||||
call gitgutter#hunk#increment_lines_added(to_count)
|
call gitgutter#hunk#increment_lines_added(a:bufnr, to_count)
|
||||||
|
|
||||||
elseif gitgutter#diff#is_removed(from_count, to_count)
|
elseif s:is_removed(from_count, to_count)
|
||||||
call gitgutter#diff#process_removed(modifications, from_count, to_count, to_line)
|
call s:process_removed(modifications, from_count, to_count, to_line)
|
||||||
call gitgutter#hunk#increment_lines_removed(from_count)
|
call gitgutter#hunk#increment_lines_removed(a:bufnr, from_count)
|
||||||
|
|
||||||
elseif gitgutter#diff#is_modified(from_count, to_count)
|
elseif s:is_modified(from_count, to_count)
|
||||||
call gitgutter#diff#process_modified(modifications, from_count, to_count, to_line)
|
call s:process_modified(modifications, from_count, to_count, to_line)
|
||||||
call gitgutter#hunk#increment_lines_modified(to_count)
|
call gitgutter#hunk#increment_lines_modified(a:bufnr, to_count)
|
||||||
|
|
||||||
elseif gitgutter#diff#is_modified_and_added(from_count, to_count)
|
elseif s:is_modified_and_added(from_count, to_count)
|
||||||
call gitgutter#diff#process_modified_and_added(modifications, from_count, to_count, to_line)
|
call s:process_modified_and_added(modifications, from_count, to_count, to_line)
|
||||||
call gitgutter#hunk#increment_lines_added(to_count - from_count)
|
call gitgutter#hunk#increment_lines_added(a:bufnr, to_count - from_count)
|
||||||
call gitgutter#hunk#increment_lines_modified(from_count)
|
call gitgutter#hunk#increment_lines_modified(a:bufnr, from_count)
|
||||||
|
|
||||||
elseif gitgutter#diff#is_modified_and_removed(from_count, to_count)
|
elseif s:is_modified_and_removed(from_count, to_count)
|
||||||
call gitgutter#diff#process_modified_and_removed(modifications, from_count, to_count, to_line)
|
call s:process_modified_and_removed(modifications, from_count, to_count, to_line)
|
||||||
call gitgutter#hunk#increment_lines_modified(to_count)
|
call gitgutter#hunk#increment_lines_modified(a:bufnr, to_count)
|
||||||
call gitgutter#hunk#increment_lines_removed(from_count - to_count)
|
call gitgutter#hunk#increment_lines_removed(a:bufnr, from_count - to_count)
|
||||||
|
|
||||||
endif
|
endif
|
||||||
return modifications
|
return modifications
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! gitgutter#diff#is_added(from_count, to_count) abort
|
function! s:is_added(from_count, to_count) abort
|
||||||
return a:from_count == 0 && a:to_count > 0
|
return a:from_count == 0 && a:to_count > 0
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! gitgutter#diff#is_removed(from_count, to_count) abort
|
function! s:is_removed(from_count, to_count) abort
|
||||||
return a:from_count > 0 && a:to_count == 0
|
return a:from_count > 0 && a:to_count == 0
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! gitgutter#diff#is_modified(from_count, to_count) abort
|
function! s:is_modified(from_count, to_count) abort
|
||||||
return a:from_count > 0 && a:to_count > 0 && a:from_count == a:to_count
|
return a:from_count > 0 && a:to_count > 0 && a:from_count == a:to_count
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! gitgutter#diff#is_modified_and_added(from_count, to_count) abort
|
function! s:is_modified_and_added(from_count, to_count) abort
|
||||||
return a:from_count > 0 && a:to_count > 0 && a:from_count < a:to_count
|
return a:from_count > 0 && a:to_count > 0 && a:from_count < a:to_count
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! gitgutter#diff#is_modified_and_removed(from_count, to_count) abort
|
function! s:is_modified_and_removed(from_count, to_count) abort
|
||||||
return a:from_count > 0 && a:to_count > 0 && a:from_count > a:to_count
|
return a:from_count > 0 && a:to_count > 0 && a:from_count > a:to_count
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! gitgutter#diff#process_added(modifications, from_count, to_count, to_line) abort
|
function! s:process_added(modifications, from_count, to_count, to_line) abort
|
||||||
let offset = 0
|
let offset = 0
|
||||||
while offset < a:to_count
|
while offset < a:to_count
|
||||||
let line_number = a:to_line + offset
|
let line_number = a:to_line + offset
|
||||||
|
@ -242,7 +268,7 @@ function! gitgutter#diff#process_added(modifications, from_count, to_count, to_l
|
||||||
endwhile
|
endwhile
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! gitgutter#diff#process_removed(modifications, from_count, to_count, to_line) abort
|
function! s:process_removed(modifications, from_count, to_count, to_line) abort
|
||||||
if a:to_line == 0
|
if a:to_line == 0
|
||||||
call add(a:modifications, [1, 'removed_first_line'])
|
call add(a:modifications, [1, 'removed_first_line'])
|
||||||
else
|
else
|
||||||
|
@ -250,7 +276,7 @@ function! gitgutter#diff#process_removed(modifications, from_count, to_count, to
|
||||||
endif
|
endif
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! gitgutter#diff#process_modified(modifications, from_count, to_count, to_line) abort
|
function! s:process_modified(modifications, from_count, to_count, to_line) abort
|
||||||
let offset = 0
|
let offset = 0
|
||||||
while offset < a:to_count
|
while offset < a:to_count
|
||||||
let line_number = a:to_line + offset
|
let line_number = a:to_line + offset
|
||||||
|
@ -259,7 +285,7 @@ function! gitgutter#diff#process_modified(modifications, from_count, to_count, t
|
||||||
endwhile
|
endwhile
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! gitgutter#diff#process_modified_and_added(modifications, from_count, to_count, to_line) abort
|
function! s:process_modified_and_added(modifications, from_count, to_count, to_line) abort
|
||||||
let offset = 0
|
let offset = 0
|
||||||
while offset < a:from_count
|
while offset < a:from_count
|
||||||
let line_number = a:to_line + offset
|
let line_number = a:to_line + offset
|
||||||
|
@ -273,7 +299,7 @@ function! gitgutter#diff#process_modified_and_added(modifications, from_count, t
|
||||||
endwhile
|
endwhile
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! gitgutter#diff#process_modified_and_removed(modifications, from_count, to_count, to_line) abort
|
function! s:process_modified_and_removed(modifications, from_count, to_count, to_line) abort
|
||||||
let offset = 0
|
let offset = 0
|
||||||
while offset < a:to_count
|
while offset < a:to_count
|
||||||
let line_number = a:to_line + offset
|
let line_number = a:to_line + offset
|
||||||
|
@ -283,28 +309,14 @@ function! gitgutter#diff#process_modified_and_removed(modifications, from_count,
|
||||||
let a:modifications[-1] = [a:to_line + offset - 1, 'modified_removed']
|
let a:modifications[-1] = [a:to_line + offset - 1, 'modified_removed']
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
" Generates a zero-context diff for the current hunk.
|
|
||||||
"
|
|
||||||
" diff - the full diff for the buffer
|
|
||||||
" type - stage | undo | preview
|
|
||||||
function! gitgutter#diff#generate_diff_for_hunk(diff, type) abort
|
|
||||||
let diff_for_hunk = gitgutter#diff#discard_hunks(a:diff, a:type == 'stage' || a:type == 'undo')
|
|
||||||
|
|
||||||
if a:type == 'stage' || a:type == 'undo'
|
" Returns a diff for the current hunk.
|
||||||
let diff_for_hunk = gitgutter#diff#adjust_hunk_summary(diff_for_hunk, a:type == 'stage')
|
function! gitgutter#diff#hunk_diff(bufnr, full_diff)
|
||||||
endif
|
|
||||||
|
|
||||||
return diff_for_hunk
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" Returns the diff with all hunks discarded except the current.
|
|
||||||
"
|
|
||||||
" diff - the diff to process
|
|
||||||
" keep_header - truthy to keep the diff header and hunk summary, falsy to discard it
|
|
||||||
function! gitgutter#diff#discard_hunks(diff, keep_header) abort
|
|
||||||
let modified_diff = []
|
let modified_diff = []
|
||||||
let keep_line = a:keep_header
|
let keep_line = 1
|
||||||
for line in split(a:diff, '\n')
|
" Don't keepempty when splitting because the diff we want may not be the
|
||||||
|
" final one. Instead add trailing NL at end of function.
|
||||||
|
for line in split(a:full_diff, '\n')
|
||||||
let hunk_info = gitgutter#diff#parse_hunk(line)
|
let hunk_info = gitgutter#diff#parse_hunk(line)
|
||||||
if len(hunk_info) == 4 " start of new hunk
|
if len(hunk_info) == 4 " start of new hunk
|
||||||
let keep_line = gitgutter#hunk#cursor_in_hunk(hunk_info)
|
let keep_line = gitgutter#hunk#cursor_in_hunk(hunk_info)
|
||||||
|
@ -313,36 +325,32 @@ function! gitgutter#diff#discard_hunks(diff, keep_header) abort
|
||||||
call add(modified_diff, line)
|
call add(modified_diff, line)
|
||||||
endif
|
endif
|
||||||
endfor
|
endfor
|
||||||
|
return join(modified_diff, "\n")."\n"
|
||||||
if a:keep_header
|
|
||||||
return gitgutter#utility#stringify(modified_diff)
|
|
||||||
else
|
|
||||||
" Discard hunk summary too.
|
|
||||||
return gitgutter#utility#stringify(modified_diff[1:])
|
|
||||||
endif
|
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
" Adjust hunk summary (from's / to's line number) to ignore changes above/before this one.
|
|
||||||
"
|
function! s:write_buffer(bufnr, file)
|
||||||
" diff_for_hunk - a diff containing only the hunk of interest
|
let bufcontents = getbufline(a:bufnr, 1, '$')
|
||||||
" staging - truthy if the hunk is to be staged, falsy if it is to be undone
|
|
||||||
"
|
if getbufvar(a:bufnr, '&fileformat') ==# 'dos'
|
||||||
" TODO: push this down to #discard_hunks?
|
call map(bufcontents, 'v:val."\r"')
|
||||||
function! gitgutter#diff#adjust_hunk_summary(diff_for_hunk, staging) abort
|
|
||||||
let line_adjustment = gitgutter#hunk#line_adjustment_for_current_hunk()
|
|
||||||
let adj_diff = []
|
|
||||||
for line in split(a:diff_for_hunk, '\n')
|
|
||||||
if match(line, s:hunk_re) != -1
|
|
||||||
if a:staging
|
|
||||||
" increment 'to' line number
|
|
||||||
let line = substitute(line, '+\@<=\(\d\+\)', '\=submatch(1)+line_adjustment', '')
|
|
||||||
else
|
|
||||||
" decrement 'from' line number
|
|
||||||
let line = substitute(line, '-\@<=\(\d\+\)', '\=submatch(1)-line_adjustment', '')
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
let fenc = getbufvar(a:bufnr, '&fileencoding')
|
||||||
|
if fenc !=# &encoding
|
||||||
|
call map(bufcontents, 'iconv(v:val, &encoding, "'.fenc.'")')
|
||||||
endif
|
endif
|
||||||
call add(adj_diff, line)
|
|
||||||
endfor
|
if getbufvar(a:bufnr, '&bomb')
|
||||||
return gitgutter#utility#stringify(adj_diff)
|
let bufcontents[0]=''.bufcontents[0]
|
||||||
|
endif
|
||||||
|
|
||||||
|
call writefile(bufcontents, a:file)
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
function! s:save_last_seen_change(bufnr) abort
|
||||||
|
call gitgutter#utility#setbufvar(a:bufnr, 'tick', getbufvar(a:bufnr, 'changedtick'))
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,37 @@
|
||||||
|
function! gitgutter#highlight#line_disable() abort
|
||||||
|
let g:gitgutter_highlight_lines = 0
|
||||||
|
call s:define_sign_line_highlights()
|
||||||
|
|
||||||
|
if !g:gitgutter_signs
|
||||||
|
call gitgutter#sign#clear_signs(bufnr(''))
|
||||||
|
call gitgutter#sign#remove_dummy_sign(bufnr(''), 0)
|
||||||
|
endif
|
||||||
|
|
||||||
|
redraw!
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! gitgutter#highlight#line_enable() abort
|
||||||
|
let old_highlight_lines = g:gitgutter_highlight_lines
|
||||||
|
|
||||||
|
let g:gitgutter_highlight_lines = 1
|
||||||
|
call s:define_sign_line_highlights()
|
||||||
|
|
||||||
|
if !old_highlight_lines && !g:gitgutter_signs
|
||||||
|
call gitgutter#all(1)
|
||||||
|
endif
|
||||||
|
|
||||||
|
redraw!
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! gitgutter#highlight#line_toggle() abort
|
||||||
|
if g:gitgutter_highlight_lines
|
||||||
|
call gitgutter#highlight#line_disable()
|
||||||
|
else
|
||||||
|
call gitgutter#highlight#line_enable()
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
function! gitgutter#highlight#define_sign_column_highlight() abort
|
function! gitgutter#highlight#define_sign_column_highlight() abort
|
||||||
if g:gitgutter_override_sign_column_highlight
|
if g:gitgutter_override_sign_column_highlight
|
||||||
highlight! link SignColumn LineNr
|
highlight! link SignColumn LineNr
|
||||||
|
@ -7,7 +41,7 @@ function! gitgutter#highlight#define_sign_column_highlight() abort
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! gitgutter#highlight#define_highlights() abort
|
function! gitgutter#highlight#define_highlights() abort
|
||||||
let [guibg, ctermbg] = gitgutter#highlight#get_background_colors('SignColumn')
|
let [guibg, ctermbg] = s:get_background_colors('SignColumn')
|
||||||
|
|
||||||
" Highlights used by the signs.
|
" Highlights used by the signs.
|
||||||
|
|
||||||
|
@ -42,12 +76,12 @@ function! gitgutter#highlight#define_signs() abort
|
||||||
sign define GitGutterLineModifiedRemoved
|
sign define GitGutterLineModifiedRemoved
|
||||||
sign define GitGutterDummy
|
sign define GitGutterDummy
|
||||||
|
|
||||||
call gitgutter#highlight#define_sign_text()
|
call s:define_sign_text()
|
||||||
call gitgutter#highlight#define_sign_text_highlights()
|
call gitgutter#highlight#define_sign_text_highlights()
|
||||||
call gitgutter#highlight#define_sign_line_highlights()
|
call s:define_sign_line_highlights()
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! gitgutter#highlight#define_sign_text() abort
|
function! s:define_sign_text() abort
|
||||||
execute "sign define GitGutterLineAdded text=" . g:gitgutter_sign_added
|
execute "sign define GitGutterLineAdded text=" . g:gitgutter_sign_added
|
||||||
execute "sign define GitGutterLineModified text=" . g:gitgutter_sign_modified
|
execute "sign define GitGutterLineModified text=" . g:gitgutter_sign_modified
|
||||||
execute "sign define GitGutterLineRemoved text=" . g:gitgutter_sign_removed
|
execute "sign define GitGutterLineRemoved text=" . g:gitgutter_sign_removed
|
||||||
|
@ -75,7 +109,7 @@ function! gitgutter#highlight#define_sign_text_highlights() abort
|
||||||
endif
|
endif
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! gitgutter#highlight#define_sign_line_highlights() abort
|
function! s:define_sign_line_highlights() abort
|
||||||
if g:gitgutter_highlight_lines
|
if g:gitgutter_highlight_lines
|
||||||
sign define GitGutterLineAdded linehl=GitGutterAddLine
|
sign define GitGutterLineAdded linehl=GitGutterAddLine
|
||||||
sign define GitGutterLineModified linehl=GitGutterChangeLine
|
sign define GitGutterLineModified linehl=GitGutterChangeLine
|
||||||
|
@ -91,22 +125,22 @@ function! gitgutter#highlight#define_sign_line_highlights() abort
|
||||||
endif
|
endif
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! gitgutter#highlight#get_background_colors(group) abort
|
function! s:get_background_colors(group) abort
|
||||||
redir => highlight
|
redir => highlight
|
||||||
silent execute 'silent highlight ' . a:group
|
silent execute 'silent highlight ' . a:group
|
||||||
redir END
|
redir END
|
||||||
|
|
||||||
let link_matches = matchlist(highlight, 'links to \(\S\+\)')
|
let link_matches = matchlist(highlight, 'links to \(\S\+\)')
|
||||||
if len(link_matches) > 0 " follow the link
|
if len(link_matches) > 0 " follow the link
|
||||||
return gitgutter#highlight#get_background_colors(link_matches[1])
|
return s:get_background_colors(link_matches[1])
|
||||||
endif
|
endif
|
||||||
|
|
||||||
let ctermbg = gitgutter#highlight#match_highlight(highlight, 'ctermbg=\([0-9A-Za-z]\+\)')
|
let ctermbg = s:match_highlight(highlight, 'ctermbg=\([0-9A-Za-z]\+\)')
|
||||||
let guibg = gitgutter#highlight#match_highlight(highlight, 'guibg=\([#0-9A-Za-z]\+\)')
|
let guibg = s:match_highlight(highlight, 'guibg=\([#0-9A-Za-z]\+\)')
|
||||||
return [guibg, ctermbg]
|
return [guibg, ctermbg]
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! gitgutter#highlight#match_highlight(highlight, pattern) abort
|
function! s:match_highlight(highlight, pattern) abort
|
||||||
let matches = matchlist(a:highlight, a:pattern)
|
let matches = matchlist(a:highlight, a:pattern)
|
||||||
if len(matches) == 0
|
if len(matches) == 0
|
||||||
return 'NONE'
|
return 'NONE'
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
function! gitgutter#hunk#set_hunks(hunks) abort
|
function! gitgutter#hunk#set_hunks(bufnr, hunks) abort
|
||||||
call gitgutter#utility#setbufvar(gitgutter#utility#bufnr(), 'hunks', a:hunks)
|
call gitgutter#utility#setbufvar(a:bufnr, 'hunks', a:hunks)
|
||||||
call s:reset_summary()
|
call s:reset_summary(a:bufnr)
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! gitgutter#hunk#hunks() abort
|
function! gitgutter#hunk#hunks(bufnr) abort
|
||||||
return gitgutter#utility#getbufvar(gitgutter#utility#bufnr(), 'hunks', [])
|
return gitgutter#utility#getbufvar(a:bufnr, 'hunks', [])
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! gitgutter#hunk#reset() abort
|
function! gitgutter#hunk#reset(bufnr) abort
|
||||||
call gitgutter#utility#setbufvar(gitgutter#utility#bufnr(), 'hunks', [])
|
call gitgutter#utility#setbufvar(a:bufnr, 'hunks', [])
|
||||||
call s:reset_summary()
|
call s:reset_summary(a:bufnr)
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
@ -17,37 +17,35 @@ function! gitgutter#hunk#summary(bufnr) abort
|
||||||
return gitgutter#utility#getbufvar(a:bufnr, 'summary', [0,0,0])
|
return gitgutter#utility#getbufvar(a:bufnr, 'summary', [0,0,0])
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! s:reset_summary() abort
|
function! s:reset_summary(bufnr) abort
|
||||||
call gitgutter#utility#setbufvar(gitgutter#utility#bufnr(), 'summary', [0,0,0])
|
call gitgutter#utility#setbufvar(a:bufnr, 'summary', [0,0,0])
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! gitgutter#hunk#increment_lines_added(count) abort
|
function! gitgutter#hunk#increment_lines_added(bufnr, count) abort
|
||||||
let bufnr = gitgutter#utility#bufnr()
|
let summary = gitgutter#hunk#summary(a:bufnr)
|
||||||
let summary = gitgutter#hunk#summary(bufnr)
|
|
||||||
let summary[0] += a:count
|
let summary[0] += a:count
|
||||||
call gitgutter#utility#setbufvar(bufnr, 'summary', summary)
|
call gitgutter#utility#setbufvar(a:bufnr, 'summary', summary)
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! gitgutter#hunk#increment_lines_modified(count) abort
|
function! gitgutter#hunk#increment_lines_modified(bufnr, count) abort
|
||||||
let bufnr = gitgutter#utility#bufnr()
|
let summary = gitgutter#hunk#summary(a:bufnr)
|
||||||
let summary = gitgutter#hunk#summary(bufnr)
|
|
||||||
let summary[1] += a:count
|
let summary[1] += a:count
|
||||||
call gitgutter#utility#setbufvar(bufnr, 'summary', summary)
|
call gitgutter#utility#setbufvar(a:bufnr, 'summary', summary)
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! gitgutter#hunk#increment_lines_removed(count) abort
|
function! gitgutter#hunk#increment_lines_removed(bufnr, count) abort
|
||||||
let bufnr = gitgutter#utility#bufnr()
|
let summary = gitgutter#hunk#summary(a:bufnr)
|
||||||
let summary = gitgutter#hunk#summary(bufnr)
|
|
||||||
let summary[2] += a:count
|
let summary[2] += a:count
|
||||||
call gitgutter#utility#setbufvar(bufnr, 'summary', summary)
|
call gitgutter#utility#setbufvar(a:bufnr, 'summary', summary)
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
function! gitgutter#hunk#next_hunk(count) abort
|
function! gitgutter#hunk#next_hunk(count) abort
|
||||||
if gitgutter#utility#is_active()
|
let bufnr = bufnr('')
|
||||||
|
if gitgutter#utility#is_active(bufnr)
|
||||||
let current_line = line('.')
|
let current_line = line('.')
|
||||||
let hunk_count = 0
|
let hunk_count = 0
|
||||||
for hunk in gitgutter#hunk#hunks()
|
for hunk in gitgutter#hunk#hunks(bufnr)
|
||||||
if hunk[2] > current_line
|
if hunk[2] > current_line
|
||||||
let hunk_count += 1
|
let hunk_count += 1
|
||||||
if hunk_count == a:count
|
if hunk_count == a:count
|
||||||
|
@ -61,10 +59,11 @@ function! gitgutter#hunk#next_hunk(count) abort
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! gitgutter#hunk#prev_hunk(count) abort
|
function! gitgutter#hunk#prev_hunk(count) abort
|
||||||
if gitgutter#utility#is_active()
|
let bufnr = bufnr('')
|
||||||
|
if gitgutter#utility#is_active(bufnr)
|
||||||
let current_line = line('.')
|
let current_line = line('.')
|
||||||
let hunk_count = 0
|
let hunk_count = 0
|
||||||
for hunk in reverse(copy(gitgutter#hunk#hunks()))
|
for hunk in reverse(copy(gitgutter#hunk#hunks(bufnr)))
|
||||||
if hunk[2] < current_line
|
if hunk[2] < current_line
|
||||||
let hunk_count += 1
|
let hunk_count += 1
|
||||||
if hunk_count == a:count
|
if hunk_count == a:count
|
||||||
|
@ -80,10 +79,11 @@ endfunction
|
||||||
|
|
||||||
" Returns the hunk the cursor is currently in or an empty list if the cursor
|
" Returns the hunk the cursor is currently in or an empty list if the cursor
|
||||||
" isn't in a hunk.
|
" isn't in a hunk.
|
||||||
function! gitgutter#hunk#current_hunk() abort
|
function! s:current_hunk() abort
|
||||||
|
let bufnr = bufnr('')
|
||||||
let current_hunk = []
|
let current_hunk = []
|
||||||
|
|
||||||
for hunk in gitgutter#hunk#hunks()
|
for hunk in gitgutter#hunk#hunks(bufnr)
|
||||||
if gitgutter#hunk#cursor_in_hunk(hunk)
|
if gitgutter#hunk#cursor_in_hunk(hunk)
|
||||||
let current_hunk = hunk
|
let current_hunk = hunk
|
||||||
break
|
break
|
||||||
|
@ -107,22 +107,8 @@ function! gitgutter#hunk#cursor_in_hunk(hunk) abort
|
||||||
return 0
|
return 0
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
" Returns the number of lines the current hunk is offset from where it would
|
|
||||||
" be if any changes above it in the file didn't exist.
|
|
||||||
function! gitgutter#hunk#line_adjustment_for_current_hunk() abort
|
|
||||||
let adj = 0
|
|
||||||
for hunk in gitgutter#hunk#hunks()
|
|
||||||
if gitgutter#hunk#cursor_in_hunk(hunk)
|
|
||||||
break
|
|
||||||
else
|
|
||||||
let adj += hunk[1] - hunk[3]
|
|
||||||
endif
|
|
||||||
endfor
|
|
||||||
return adj
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function! gitgutter#hunk#text_object(inner) abort
|
function! gitgutter#hunk#text_object(inner) abort
|
||||||
let hunk = gitgutter#hunk#current_hunk()
|
let hunk = s:current_hunk()
|
||||||
|
|
||||||
if empty(hunk)
|
if empty(hunk)
|
||||||
return
|
return
|
||||||
|
@ -141,3 +127,155 @@ function! gitgutter#hunk#text_object(inner) abort
|
||||||
|
|
||||||
execute 'normal! 'first_line.'GV'.last_line.'G'
|
execute 'normal! 'first_line.'GV'.last_line.'G'
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
function! gitgutter#hunk#stage() abort
|
||||||
|
call s:hunk_op(function('s:stage'))
|
||||||
|
silent! call repeat#set("\<Plug>GitGutterStageHunk", -1)<CR>
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! gitgutter#hunk#undo() abort
|
||||||
|
call s:hunk_op(function('s:undo'))
|
||||||
|
silent! call repeat#set("\<Plug>GitGutterUndoHunk", -1)<CR>
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! gitgutter#hunk#preview() abort
|
||||||
|
call s:hunk_op(function('s:preview'))
|
||||||
|
silent! call repeat#set("\<Plug>GitGutterPreviewHunk", -1)<CR>
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
function! s:hunk_op(op)
|
||||||
|
let bufnr = bufnr('')
|
||||||
|
|
||||||
|
if gitgutter#utility#is_active(bufnr)
|
||||||
|
" Get a (synchronous) diff.
|
||||||
|
let [async, g:gitgutter_async] = [g:gitgutter_async, 0]
|
||||||
|
let diff = gitgutter#diff#run_diff(bufnr, 1)
|
||||||
|
let g:gitgutter_async = async
|
||||||
|
|
||||||
|
call gitgutter#hunk#set_hunks(bufnr, gitgutter#diff#parse_diff(diff))
|
||||||
|
|
||||||
|
if empty(s:current_hunk())
|
||||||
|
call gitgutter#utility#warn('cursor is not in a hunk')
|
||||||
|
else
|
||||||
|
call a:op(gitgutter#diff#hunk_diff(bufnr, diff))
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
function! s:stage(hunk_diff)
|
||||||
|
let bufnr = bufnr('')
|
||||||
|
let diff = s:adjust_header(bufnr, a:hunk_diff)
|
||||||
|
" Apply patch to index.
|
||||||
|
call gitgutter#utility#system(
|
||||||
|
\ gitgutter#utility#cd_cmd(bufnr, g:gitgutter_git_executable.' apply --cached --unidiff-zero - '),
|
||||||
|
\ diff)
|
||||||
|
|
||||||
|
" Refresh gitgutter's view of buffer.
|
||||||
|
call gitgutter#process_buffer(bufnr, 1)
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
function! s:undo(hunk_diff)
|
||||||
|
" Apply reverse patch to buffer.
|
||||||
|
let hunk = gitgutter#diff#parse_hunk(split(a:hunk_diff, '\n')[4])
|
||||||
|
let lines = map(split(a:hunk_diff, '\n')[5:], 'v:val[1:]')
|
||||||
|
let lnum = hunk[2]
|
||||||
|
let added_only = hunk[1] == 0 && hunk[3] > 0
|
||||||
|
let removed_only = hunk[1] > 0 && hunk[3] == 0
|
||||||
|
|
||||||
|
if removed_only
|
||||||
|
call append(lnum, lines)
|
||||||
|
elseif added_only
|
||||||
|
execute lnum .','. (lnum+len(lines)-1) .'d'
|
||||||
|
else
|
||||||
|
call append(lnum-1, lines[0:hunk[1]])
|
||||||
|
execute (lnum+hunk[1]) .','. (lnum+hunk[1]+hunk[3]) .'d'
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
function! s:preview(hunk_diff)
|
||||||
|
let hunk_lines = split(s:discard_header(a:hunk_diff), "\n")
|
||||||
|
let hunk_lines_length = len(hunk_lines)
|
||||||
|
let previewheight = min([hunk_lines_length, &previewheight])
|
||||||
|
|
||||||
|
silent! wincmd P
|
||||||
|
if !&previewwindow
|
||||||
|
noautocmd execute 'bo' previewheight 'new'
|
||||||
|
set previewwindow
|
||||||
|
else
|
||||||
|
execute 'resize' previewheight
|
||||||
|
endif
|
||||||
|
|
||||||
|
setlocal noreadonly modifiable filetype=diff buftype=nofile bufhidden=delete noswapfile
|
||||||
|
execute "%delete_"
|
||||||
|
call append(0, hunk_lines)
|
||||||
|
normal! gg
|
||||||
|
setlocal readonly nomodifiable
|
||||||
|
|
||||||
|
noautocmd wincmd p
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
function! s:adjust_header(bufnr, hunk_diff)
|
||||||
|
let filepath = gitgutter#utility#repo_path(a:bufnr, 0)
|
||||||
|
return s:adjust_hunk_summary(s:fix_file_references(filepath, a:hunk_diff))
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
" Replaces references to temp files with the actual file.
|
||||||
|
function! s:fix_file_references(filepath, hunk_diff)
|
||||||
|
let lines = split(a:hunk_diff, '\n')
|
||||||
|
|
||||||
|
let left_prefix = matchstr(lines[2], '[abciow12]').'/'
|
||||||
|
let right_prefix = matchstr(lines[3], '[abciow12]').'/'
|
||||||
|
let quote = lines[0][11] == '"' ? '"' : ''
|
||||||
|
|
||||||
|
let left_file = quote.left_prefix.a:filepath.quote
|
||||||
|
let right_file = quote.right_prefix.a:filepath.quote
|
||||||
|
|
||||||
|
let lines[0] = 'diff --git '.left_file.' '.right_file
|
||||||
|
let lines[2] = '--- '.left_file
|
||||||
|
let lines[3] = '+++ '.right_file
|
||||||
|
|
||||||
|
return join(lines, "\n")."\n"
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
if $VIM_GITGUTTER_TEST
|
||||||
|
function! gitgutter#hunk#fix_file_references(filepath, hunk_diff)
|
||||||
|
return s:fix_file_references(a:filepath, a:hunk_diff)
|
||||||
|
endfunction
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
function! s:adjust_hunk_summary(hunk_diff) abort
|
||||||
|
let line_adjustment = s:line_adjustment_for_current_hunk()
|
||||||
|
let diff = split(a:hunk_diff, '\n', 1)
|
||||||
|
let diff[4] = substitute(diff[4], '+\@<=\(\d\+\)', '\=submatch(1)+line_adjustment', '')
|
||||||
|
return join(diff, "\n")
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
function! s:discard_header(hunk_diff)
|
||||||
|
return join(split(a:hunk_diff, '\n', 1)[5:], "\n")
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
" Returns the number of lines the current hunk is offset from where it would
|
||||||
|
" be if any changes above it in the file didn't exist.
|
||||||
|
function! s:line_adjustment_for_current_hunk() abort
|
||||||
|
let bufnr = bufnr('')
|
||||||
|
let adj = 0
|
||||||
|
for hunk in gitgutter#hunk#hunks(bufnr)
|
||||||
|
if gitgutter#hunk#cursor_in_hunk(hunk)
|
||||||
|
break
|
||||||
|
else
|
||||||
|
let adj += hunk[1] - hunk[3]
|
||||||
|
endif
|
||||||
|
endfor
|
||||||
|
return adj
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
|
|
@ -10,14 +10,43 @@ let s:dummy_sign_id = s:first_sign_id - 1
|
||||||
let s:supports_star = v:version > 703 || (v:version == 703 && has("patch596"))
|
let s:supports_star = v:version > 703 || (v:version == 703 && has("patch596"))
|
||||||
|
|
||||||
|
|
||||||
" Removes gitgutter's signs (excluding dummy sign) from the buffer being processed.
|
function! gitgutter#sign#enable() abort
|
||||||
function! gitgutter#sign#clear_signs() abort
|
let old_signs = g:gitgutter_signs
|
||||||
let bufnr = gitgutter#utility#bufnr()
|
|
||||||
call gitgutter#sign#find_current_signs()
|
|
||||||
|
|
||||||
let sign_ids = map(values(gitgutter#utility#getbufvar(bufnr, 'gitgutter_signs')), 'v:val.id')
|
let g:gitgutter_signs = 1
|
||||||
call gitgutter#sign#remove_signs(sign_ids, 1)
|
call gitgutter#highlight#define_sign_text_highlights()
|
||||||
call gitgutter#utility#setbufvar(bufnr, 'gitgutter_signs', {})
|
|
||||||
|
if !old_signs && !g:gitgutter_highlight_lines
|
||||||
|
call gitgutter#all(1)
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! gitgutter#sign#disable() abort
|
||||||
|
let g:gitgutter_signs = 0
|
||||||
|
call gitgutter#highlight#define_sign_text_highlights()
|
||||||
|
|
||||||
|
if !g:gitgutter_highlight_lines
|
||||||
|
call gitgutter#sign#clear_signs(bufnr(''))
|
||||||
|
call gitgutter#sign#remove_dummy_sign(bufnr(''), 0)
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! gitgutter#sign#toggle() abort
|
||||||
|
if g:gitgutter_signs
|
||||||
|
call gitgutter#sign#disable()
|
||||||
|
else
|
||||||
|
call gitgutter#sign#enable()
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
" Removes gitgutter's signs (excluding dummy sign) from the buffer being processed.
|
||||||
|
function! gitgutter#sign#clear_signs(bufnr) abort
|
||||||
|
call s:find_current_signs(a:bufnr)
|
||||||
|
|
||||||
|
let sign_ids = map(values(gitgutter#utility#getbufvar(a:bufnr, 'gitgutter_signs')), 'v:val.id')
|
||||||
|
call s:remove_signs(a:bufnr, sign_ids, 1)
|
||||||
|
call gitgutter#utility#setbufvar(a:bufnr, 'gitgutter_signs', {})
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
@ -25,39 +54,37 @@ endfunction
|
||||||
"
|
"
|
||||||
" modified_lines: list of [<line_number (number)>, <name (string)>]
|
" modified_lines: list of [<line_number (number)>, <name (string)>]
|
||||||
" where name = 'added|removed|modified|modified_removed'
|
" where name = 'added|removed|modified|modified_removed'
|
||||||
function! gitgutter#sign#update_signs(modified_lines) abort
|
function! gitgutter#sign#update_signs(bufnr, modified_lines) abort
|
||||||
call gitgutter#sign#find_current_signs()
|
call s:find_current_signs(a:bufnr)
|
||||||
|
|
||||||
let new_gitgutter_signs_line_numbers = map(copy(a:modified_lines), 'v:val[0]')
|
let new_gitgutter_signs_line_numbers = map(copy(a:modified_lines), 'v:val[0]')
|
||||||
let obsolete_signs = gitgutter#sign#obsolete_gitgutter_signs_to_remove(new_gitgutter_signs_line_numbers)
|
let obsolete_signs = s:obsolete_gitgutter_signs_to_remove(a:bufnr, new_gitgutter_signs_line_numbers)
|
||||||
|
|
||||||
let flicker_possible = s:remove_all_old_signs && !empty(a:modified_lines)
|
let flicker_possible = s:remove_all_old_signs && !empty(a:modified_lines)
|
||||||
if flicker_possible
|
if flicker_possible
|
||||||
call gitgutter#sign#add_dummy_sign()
|
call s:add_dummy_sign(a:bufnr)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
call gitgutter#sign#remove_signs(obsolete_signs, s:remove_all_old_signs)
|
call s:remove_signs(a:bufnr, obsolete_signs, s:remove_all_old_signs)
|
||||||
call gitgutter#sign#upsert_new_gitgutter_signs(a:modified_lines)
|
call s:upsert_new_gitgutter_signs(a:bufnr, a:modified_lines)
|
||||||
|
|
||||||
if flicker_possible
|
if flicker_possible
|
||||||
call gitgutter#sign#remove_dummy_sign(0)
|
call gitgutter#sign#remove_dummy_sign(a:bufnr, 0)
|
||||||
endif
|
endif
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
function! gitgutter#sign#add_dummy_sign() abort
|
function! s:add_dummy_sign(bufnr) abort
|
||||||
let bufnr = gitgutter#utility#bufnr()
|
if !gitgutter#utility#getbufvar(a:bufnr, 'dummy_sign')
|
||||||
if !gitgutter#utility#getbufvar(bufnr, 'dummy_sign')
|
execute "sign place" s:dummy_sign_id "line=" . 9999 "name=GitGutterDummy buffer=" . a:bufnr
|
||||||
execute "sign place" s:dummy_sign_id "line=" . 9999 "name=GitGutterDummy buffer=" . bufnr
|
call gitgutter#utility#setbufvar(a:bufnr, 'dummy_sign', 1)
|
||||||
call gitgutter#utility#setbufvar(bufnr, 'dummy_sign', 1)
|
|
||||||
endif
|
endif
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! gitgutter#sign#remove_dummy_sign(force) abort
|
function! gitgutter#sign#remove_dummy_sign(bufnr, force) abort
|
||||||
let bufnr = gitgutter#utility#bufnr()
|
if gitgutter#utility#getbufvar(a:bufnr, 'dummy_sign') && (a:force || !g:gitgutter_sign_column_always)
|
||||||
if gitgutter#utility#getbufvar(bufnr, 'dummy_sign') && (a:force || !g:gitgutter_sign_column_always)
|
execute "sign unplace" s:dummy_sign_id "buffer=" . a:bufnr
|
||||||
execute "sign unplace" s:dummy_sign_id "buffer=" . bufnr
|
call gitgutter#utility#setbufvar(a:bufnr, 'dummy_sign', 0)
|
||||||
call gitgutter#utility#setbufvar(bufnr, 'dummy_sign', 0)
|
|
||||||
endif
|
endif
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
@ -67,14 +94,13 @@ endfunction
|
||||||
"
|
"
|
||||||
|
|
||||||
|
|
||||||
function! gitgutter#sign#find_current_signs() abort
|
function! s:find_current_signs(bufnr) abort
|
||||||
let bufnr = gitgutter#utility#bufnr()
|
|
||||||
let gitgutter_signs = {} " <line_number (string)>: {'id': <id (number)>, 'name': <name (string)>}
|
let gitgutter_signs = {} " <line_number (string)>: {'id': <id (number)>, 'name': <name (string)>}
|
||||||
let other_signs = [] " [<line_number (number),...]
|
let other_signs = [] " [<line_number (number),...]
|
||||||
let dummy_sign_placed = 0
|
let dummy_sign_placed = 0
|
||||||
|
|
||||||
redir => signs
|
redir => signs
|
||||||
silent execute "sign place buffer=" . bufnr
|
silent execute "sign place buffer=" . a:bufnr
|
||||||
redir END
|
redir END
|
||||||
|
|
||||||
for sign_line in filter(split(signs, '\n')[2:], 'v:val =~# "="')
|
for sign_line in filter(split(signs, '\n')[2:], 'v:val =~# "="')
|
||||||
|
@ -101,19 +127,18 @@ function! gitgutter#sign#find_current_signs() abort
|
||||||
end
|
end
|
||||||
endfor
|
endfor
|
||||||
|
|
||||||
call gitgutter#utility#setbufvar(bufnr, 'dummy_sign', dummy_sign_placed)
|
call gitgutter#utility#setbufvar(a:bufnr, 'dummy_sign', dummy_sign_placed)
|
||||||
call gitgutter#utility#setbufvar(bufnr, 'gitgutter_signs', gitgutter_signs)
|
call gitgutter#utility#setbufvar(a:bufnr, 'gitgutter_signs', gitgutter_signs)
|
||||||
call gitgutter#utility#setbufvar(bufnr, 'other_signs', other_signs)
|
call gitgutter#utility#setbufvar(a:bufnr, 'other_signs', other_signs)
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
" Returns a list of [<id (number)>, ...]
|
" Returns a list of [<id (number)>, ...]
|
||||||
" Sets `s:remove_all_old_signs` as a side-effect.
|
" Sets `s:remove_all_old_signs` as a side-effect.
|
||||||
function! gitgutter#sign#obsolete_gitgutter_signs_to_remove(new_gitgutter_signs_line_numbers) abort
|
function! s:obsolete_gitgutter_signs_to_remove(bufnr, new_gitgutter_signs_line_numbers) abort
|
||||||
let bufnr = gitgutter#utility#bufnr()
|
|
||||||
let signs_to_remove = [] " list of [<id (number)>, ...]
|
let signs_to_remove = [] " list of [<id (number)>, ...]
|
||||||
let remove_all_signs = 1
|
let remove_all_signs = 1
|
||||||
let old_gitgutter_signs = gitgutter#utility#getbufvar(bufnr, 'gitgutter_signs')
|
let old_gitgutter_signs = gitgutter#utility#getbufvar(a:bufnr, 'gitgutter_signs')
|
||||||
for line_number in keys(old_gitgutter_signs)
|
for line_number in keys(old_gitgutter_signs)
|
||||||
if index(a:new_gitgutter_signs_line_numbers, str2nr(line_number)) == -1
|
if index(a:new_gitgutter_signs_line_numbers, str2nr(line_number)) == -1
|
||||||
call add(signs_to_remove, old_gitgutter_signs[line_number].id)
|
call add(signs_to_remove, old_gitgutter_signs[line_number].id)
|
||||||
|
@ -126,13 +151,12 @@ function! gitgutter#sign#obsolete_gitgutter_signs_to_remove(new_gitgutter_signs_
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
function! gitgutter#sign#remove_signs(sign_ids, all_signs) abort
|
function! s:remove_signs(bufnr, sign_ids, all_signs) abort
|
||||||
let bufnr = gitgutter#utility#bufnr()
|
if a:all_signs && s:supports_star && empty(gitgutter#utility#getbufvar(a:bufnr, 'other_signs'))
|
||||||
if a:all_signs && s:supports_star && empty(gitgutter#utility#getbufvar(bufnr, 'other_signs'))
|
let dummy_sign_present = gitgutter#utility#getbufvar(a:bufnr, 'dummy_sign')
|
||||||
let dummy_sign_present = gitgutter#utility#getbufvar(bufnr, 'dummy_sign')
|
execute "sign unplace * buffer=" . a:bufnr
|
||||||
execute "sign unplace * buffer=" . bufnr
|
|
||||||
if dummy_sign_present
|
if dummy_sign_present
|
||||||
execute "sign place" s:dummy_sign_id "line=" . 9999 "name=GitGutterDummy buffer=" . bufnr
|
execute "sign place" s:dummy_sign_id "line=" . 9999 "name=GitGutterDummy buffer=" . a:bufnr
|
||||||
endif
|
endif
|
||||||
else
|
else
|
||||||
for id in a:sign_ids
|
for id in a:sign_ids
|
||||||
|
@ -142,22 +166,21 @@ function! gitgutter#sign#remove_signs(sign_ids, all_signs) abort
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
function! gitgutter#sign#upsert_new_gitgutter_signs(modified_lines) abort
|
function! s:upsert_new_gitgutter_signs(bufnr, modified_lines) abort
|
||||||
let bufnr = gitgutter#utility#bufnr()
|
let other_signs = gitgutter#utility#getbufvar(a:bufnr, 'other_signs')
|
||||||
let other_signs = gitgutter#utility#getbufvar(bufnr, 'other_signs')
|
let old_gitgutter_signs = gitgutter#utility#getbufvar(a:bufnr, 'gitgutter_signs')
|
||||||
let old_gitgutter_signs = gitgutter#utility#getbufvar(bufnr, 'gitgutter_signs')
|
|
||||||
|
|
||||||
for line in a:modified_lines
|
for line in a:modified_lines
|
||||||
let line_number = line[0] " <number>
|
let line_number = line[0] " <number>
|
||||||
if index(other_signs, line_number) == -1 " don't clobber others' signs
|
if index(other_signs, line_number) == -1 " don't clobber others' signs
|
||||||
let name = gitgutter#utility#highlight_name_for_change(line[1])
|
let name = s:highlight_name_for_change(line[1])
|
||||||
if !has_key(old_gitgutter_signs, line_number) " insert
|
if !has_key(old_gitgutter_signs, line_number) " insert
|
||||||
let id = gitgutter#sign#next_sign_id()
|
let id = s:next_sign_id()
|
||||||
execute "sign place" id "line=" . line_number "name=" . name "buffer=" . bufnr
|
execute "sign place" id "line=" . line_number "name=" . name "buffer=" . a:bufnr
|
||||||
else " update if sign has changed
|
else " update if sign has changed
|
||||||
let old_sign = old_gitgutter_signs[line_number]
|
let old_sign = old_gitgutter_signs[line_number]
|
||||||
if old_sign.name !=# name
|
if old_sign.name !=# name
|
||||||
execute "sign place" old_sign.id "name=" . name "buffer=" . bufnr
|
execute "sign place" old_sign.id "name=" . name "buffer=" . a:bufnr
|
||||||
end
|
end
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
@ -166,7 +189,7 @@ function! gitgutter#sign#upsert_new_gitgutter_signs(modified_lines) abort
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
function! gitgutter#sign#next_sign_id() abort
|
function! s:next_sign_id() abort
|
||||||
let next_id = s:next_sign_id
|
let next_id = s:next_sign_id
|
||||||
let s:next_sign_id += 1
|
let s:next_sign_id += 1
|
||||||
return next_id
|
return next_id
|
||||||
|
@ -177,3 +200,20 @@ endfunction
|
||||||
function! gitgutter#sign#reset()
|
function! gitgutter#sign#reset()
|
||||||
let s:next_sign_id = s:first_sign_id
|
let s:next_sign_id = s:first_sign_id
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
function! s:highlight_name_for_change(text) abort
|
||||||
|
if a:text ==# 'added'
|
||||||
|
return 'GitGutterLineAdded'
|
||||||
|
elseif a:text ==# 'removed'
|
||||||
|
return 'GitGutterLineRemoved'
|
||||||
|
elseif a:text ==# 'removed_first_line'
|
||||||
|
return 'GitGutterLineRemovedFirstLine'
|
||||||
|
elseif a:text ==# 'modified'
|
||||||
|
return 'GitGutterLineModified'
|
||||||
|
elseif a:text ==# 'modified_removed'
|
||||||
|
return 'GitGutterLineModifiedRemoved'
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,18 @@
|
||||||
let s:file = ''
|
function! gitgutter#utility#supports_overscore_sign()
|
||||||
let s:using_xolox_shell = -1
|
if s:windows()
|
||||||
let s:exit_code = 0
|
return &encoding ==? 'utf-8'
|
||||||
|
else
|
||||||
|
return &termencoding ==? &encoding || &termencoding == ''
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
function! gitgutter#utility#setbufvar(buffer, varname, val)
|
function! gitgutter#utility#setbufvar(buffer, varname, val)
|
||||||
let dict = get(getbufvar(a:buffer, ''), 'gitgutter', {})
|
let dict = get(getbufvar(a:buffer, ''), 'gitgutter', {})
|
||||||
|
let needs_setting = empty(dict)
|
||||||
let dict[a:varname] = a:val
|
let dict[a:varname] = a:val
|
||||||
|
if needs_setting
|
||||||
call setbufvar(a:buffer, 'gitgutter', dict)
|
call setbufvar(a:buffer, 'gitgutter', dict)
|
||||||
|
endif
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! gitgutter#utility#getbufvar(buffer, varname, ...)
|
function! gitgutter#utility#getbufvar(buffer, varname, ...)
|
||||||
|
@ -26,11 +33,11 @@ function! gitgutter#utility#warn(message) abort
|
||||||
let v:warningmsg = a:message
|
let v:warningmsg = a:message
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! gitgutter#utility#warn_once(message, key) abort
|
function! gitgutter#utility#warn_once(bufnr, message, key) abort
|
||||||
if empty(gitgutter#utility#getbufvar(s:bufnr, a:key))
|
if empty(gitgutter#utility#getbufvar(a:bufnr, a:key))
|
||||||
call gitgutter#utility#setbufvar(s:bufnr, a:key, '1')
|
call gitgutter#utility#setbufvar(a:bufnr, a:key, '1')
|
||||||
echohl WarningMsg
|
echohl WarningMsg
|
||||||
redraw | echo 'vim-gitgutter: ' . a:message
|
redraw | echom 'vim-gitgutter: ' . a:message
|
||||||
echohl None
|
echohl None
|
||||||
let v:warningmsg = a:message
|
let v:warningmsg = a:message
|
||||||
endif
|
endif
|
||||||
|
@ -38,188 +45,166 @@ endfunction
|
||||||
|
|
||||||
" Returns truthy when the buffer's file should be processed; and falsey when it shouldn't.
|
" Returns truthy when the buffer's file should be processed; and falsey when it shouldn't.
|
||||||
" This function does not and should not make any system calls.
|
" This function does not and should not make any system calls.
|
||||||
function! gitgutter#utility#is_active() abort
|
function! gitgutter#utility#is_active(bufnr) abort
|
||||||
return g:gitgutter_enabled &&
|
return g:gitgutter_enabled &&
|
||||||
\ !pumvisible() &&
|
\ !pumvisible() &&
|
||||||
\ gitgutter#utility#is_file_buffer() &&
|
\ s:is_file_buffer(a:bufnr) &&
|
||||||
\ gitgutter#utility#exists_file() &&
|
\ s:exists_file(a:bufnr) &&
|
||||||
\ gitgutter#utility#not_git_dir()
|
\ s:not_git_dir(a:bufnr)
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! gitgutter#utility#not_git_dir() abort
|
function! s:not_git_dir(bufnr) abort
|
||||||
return gitgutter#utility#full_path_to_directory_of_file() !~ '[/\\]\.git\($\|[/\\]\)'
|
return s:dir(a:bufnr) !~ '[/\\]\.git\($\|[/\\]\)'
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! gitgutter#utility#is_file_buffer() abort
|
function! s:is_file_buffer(bufnr) abort
|
||||||
return empty(getbufvar(s:bufnr, '&buftype'))
|
return empty(getbufvar(a:bufnr, '&buftype'))
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
" A replacement for the built-in `shellescape(arg)`.
|
" From tpope/vim-fugitive
|
||||||
"
|
function! s:winshell()
|
||||||
" Recent versions of Vim handle shell escaping pretty well. However older
|
return &shell =~? 'cmd' || exists('+shellslash') && !&shellslash
|
||||||
" versions aren't as good. This attempts to do the right thing.
|
endfunction
|
||||||
"
|
|
||||||
" See:
|
" From tpope/vim-fugitive
|
||||||
" https://github.com/tpope/vim-fugitive/blob/8f0b8edfbd246c0026b7a2388e1d883d579ac7f6/plugin/fugitive.vim#L29-L37
|
|
||||||
function! gitgutter#utility#shellescape(arg) abort
|
function! gitgutter#utility#shellescape(arg) abort
|
||||||
if a:arg =~ '^[A-Za-z0-9_/.-]\+$'
|
if a:arg =~ '^[A-Za-z0-9_/.-]\+$'
|
||||||
return a:arg
|
return a:arg
|
||||||
elseif &shell =~# 'cmd' || gitgutter#utility#using_xolox_shell()
|
elseif s:winshell()
|
||||||
return '"' . substitute(substitute(a:arg, '"', '""', 'g'), '%', '"%"', 'g') . '"'
|
return '"' . substitute(substitute(a:arg, '"', '""', 'g'), '%', '"%"', 'g') . '"'
|
||||||
else
|
else
|
||||||
return shellescape(a:arg)
|
return shellescape(a:arg)
|
||||||
endif
|
endif
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! gitgutter#utility#set_buffer(bufnr) abort
|
function! gitgutter#utility#file(bufnr)
|
||||||
let s:bufnr = a:bufnr
|
return s:abs_path(a:bufnr, 1)
|
||||||
let s:file = resolve(bufname(a:bufnr))
|
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! gitgutter#utility#bufnr()
|
" Not shellescaped
|
||||||
return s:bufnr
|
function! gitgutter#utility#extension(bufnr) abort
|
||||||
endfunction
|
return fnamemodify(s:abs_path(a:bufnr, 0), ':e')
|
||||||
|
|
||||||
function! gitgutter#utility#file()
|
|
||||||
return s:file
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function! gitgutter#utility#filename() abort
|
|
||||||
return fnamemodify(s:file, ':t')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function! gitgutter#utility#extension() abort
|
|
||||||
return fnamemodify(s:file, ':e')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function! gitgutter#utility#full_path_to_directory_of_file() abort
|
|
||||||
return fnamemodify(s:file, ':p:h')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function! gitgutter#utility#directory_of_file() abort
|
|
||||||
return fnamemodify(s:file, ':h')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function! gitgutter#utility#exists_file() abort
|
|
||||||
return filereadable(s:file)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function! gitgutter#utility#has_unsaved_changes() abort
|
|
||||||
return getbufvar(s:bufnr, "&mod")
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function! gitgutter#utility#has_fresh_changes() abort
|
|
||||||
return getbufvar(s:bufnr, 'changedtick') != gitgutter#utility#getbufvar(s:bufnr, 'last_tick')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function! gitgutter#utility#save_last_seen_change() abort
|
|
||||||
call gitgutter#utility#setbufvar(s:bufnr, 'last_tick', getbufvar(s:bufnr, 'changedtick'))
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function! gitgutter#utility#shell_error() abort
|
|
||||||
return gitgutter#utility#using_xolox_shell() ? s:exit_code : v:shell_error
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function! gitgutter#utility#using_xolox_shell() abort
|
|
||||||
if s:using_xolox_shell == -1
|
|
||||||
if !g:gitgutter_avoid_cmd_prompt_on_windows
|
|
||||||
let s:using_xolox_shell = 0
|
|
||||||
" Although xolox/vim-shell works on both windows and unix we only want to use
|
|
||||||
" it on windows.
|
|
||||||
elseif has('win32') || has('win64') || has('win32unix')
|
|
||||||
let s:using_xolox_shell = exists('g:xolox#misc#version') && exists('g:xolox#shell#version')
|
|
||||||
else
|
|
||||||
let s:using_xolox_shell = 0
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
return s:using_xolox_shell
|
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! gitgutter#utility#system(cmd, ...) abort
|
function! gitgutter#utility#system(cmd, ...) abort
|
||||||
call gitgutter#debug#log(a:cmd, a:000)
|
call gitgutter#debug#log(a:cmd, a:000)
|
||||||
|
|
||||||
if gitgutter#utility#using_xolox_shell()
|
call s:use_known_shell()
|
||||||
let options = {'command': a:cmd, 'check': 0}
|
|
||||||
if a:0 > 0
|
|
||||||
let options['stdin'] = a:1
|
|
||||||
endif
|
|
||||||
let ret = xolox#misc#os#exec(options)
|
|
||||||
let output = join(ret.stdout, "\n")
|
|
||||||
let s:exit_code = ret.exit_code
|
|
||||||
else
|
|
||||||
silent let output = (a:0 == 0) ? system(a:cmd) : system(a:cmd, a:1)
|
silent let output = (a:0 == 0) ? system(a:cmd) : system(a:cmd, a:1)
|
||||||
endif
|
call s:restore_shell()
|
||||||
|
|
||||||
return output
|
return output
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! gitgutter#utility#file_relative_to_repo_root() abort
|
" Path of file relative to repo root.
|
||||||
let file_path_relative_to_repo_root = gitgutter#utility#getbufvar(s:bufnr, 'repo_relative_path')
|
"
|
||||||
if empty(file_path_relative_to_repo_root)
|
" * empty string - not set
|
||||||
let dir_path_relative_to_repo_root = gitgutter#utility#system(gitgutter#utility#command_in_directory_of_file(g:gitgutter_git_executable.' rev-parse --show-prefix'))
|
" * non-empty string - path
|
||||||
let dir_path_relative_to_repo_root = gitgutter#utility#strip_trailing_new_line(dir_path_relative_to_repo_root)
|
" * -1 - pending
|
||||||
let file_path_relative_to_repo_root = dir_path_relative_to_repo_root . gitgutter#utility#filename()
|
" * -2 - not tracked by git
|
||||||
call gitgutter#utility#setbufvar(s:bufnr, 'repo_relative_path', file_path_relative_to_repo_root)
|
function! gitgutter#utility#repo_path(bufnr, shellesc) abort
|
||||||
|
let p = gitgutter#utility#getbufvar(a:bufnr, 'path')
|
||||||
|
return a:shellesc ? gitgutter#utility#shellescape(p) : p
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! gitgutter#utility#set_repo_path(bufnr) abort
|
||||||
|
" Values of path:
|
||||||
|
" * non-empty string - path
|
||||||
|
" * -1 - pending
|
||||||
|
" * -2 - not tracked by git
|
||||||
|
|
||||||
|
call gitgutter#utility#setbufvar(a:bufnr, 'path', -1)
|
||||||
|
let cmd = gitgutter#utility#cd_cmd(a:bufnr, g:gitgutter_git_executable.' ls-files --error-unmatch --full-name '.gitgutter#utility#shellescape(s:filename(a:bufnr)))
|
||||||
|
|
||||||
|
if g:gitgutter_async && gitgutter#async#available()
|
||||||
|
if has('lambda')
|
||||||
|
call gitgutter#async#execute(cmd, a:bufnr, {
|
||||||
|
\ 'out': {bufnr, path -> gitgutter#utility#setbufvar(bufnr, 'path', s:strip_trailing_new_line(path))},
|
||||||
|
\ 'err': {bufnr -> gitgutter#utility#setbufvar(bufnr, 'path', -2)},
|
||||||
|
\ })
|
||||||
|
else
|
||||||
|
if has('nvim') && !has('nvim-0.2.0')
|
||||||
|
call gitgutter#async#execute(cmd, a:bufnr, {
|
||||||
|
\ 'out': function('s:set_path'),
|
||||||
|
\ 'err': function('s:not_tracked_by_git')
|
||||||
|
\ })
|
||||||
|
else
|
||||||
|
call gitgutter#async#execute(cmd, a:bufnr, {
|
||||||
|
\ 'out': function('s:set_path'),
|
||||||
|
\ 'err': function('s:set_path', [-2])
|
||||||
|
\ })
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
else
|
||||||
|
let path = gitgutter#utility#system(cmd)
|
||||||
|
if v:shell_error
|
||||||
|
call gitgutter#utility#setbufvar(a:bufnr, 'path', -2)
|
||||||
|
else
|
||||||
|
call gitgutter#utility#setbufvar(a:bufnr, 'path', s:strip_trailing_new_line(path))
|
||||||
endif
|
endif
|
||||||
return file_path_relative_to_repo_root
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function! gitgutter#utility#command_in_directory_of_file(cmd) abort
|
|
||||||
return 'cd '.gitgutter#utility#shellescape(gitgutter#utility#directory_of_file()).' && '.a:cmd
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function! gitgutter#utility#highlight_name_for_change(text) abort
|
|
||||||
if a:text ==# 'added'
|
|
||||||
return 'GitGutterLineAdded'
|
|
||||||
elseif a:text ==# 'removed'
|
|
||||||
return 'GitGutterLineRemoved'
|
|
||||||
elseif a:text ==# 'removed_first_line'
|
|
||||||
return 'GitGutterLineRemovedFirstLine'
|
|
||||||
elseif a:text ==# 'modified'
|
|
||||||
return 'GitGutterLineModified'
|
|
||||||
elseif a:text ==# 'modified_removed'
|
|
||||||
return 'GitGutterLineModifiedRemoved'
|
|
||||||
endif
|
endif
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
" Dedups list in-place.
|
if has('nvim') && !has('nvim-0.2.0')
|
||||||
" Assumes list has no empty entries.
|
function! s:not_tracked_by_git(bufnr)
|
||||||
function! gitgutter#utility#dedup(list)
|
call s:set_path(a:bufnr, -2)
|
||||||
return filter(sort(a:list), 'index(a:list, v:val, v:key + 1) == -1')
|
endfunction
|
||||||
|
endif
|
||||||
|
|
||||||
|
function! s:set_path(bufnr, path)
|
||||||
|
if a:bufnr == -2
|
||||||
|
let [bufnr, path] = [a:path, a:bufnr]
|
||||||
|
call gitgutter#utility#setbufvar(bufnr, 'path', path)
|
||||||
|
else
|
||||||
|
call gitgutter#utility#setbufvar(a:bufnr, 'path', s:strip_trailing_new_line(a:path))
|
||||||
|
endif
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! gitgutter#utility#strip_trailing_new_line(line) abort
|
function! gitgutter#utility#cd_cmd(bufnr, cmd) abort
|
||||||
|
let cd = s:unc_path(a:bufnr) ? 'pushd' : (s:windows() ? 'cd /d' : 'cd')
|
||||||
|
return cd.' '.s:dir(a:bufnr).' && '.a:cmd
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! s:unc_path(bufnr)
|
||||||
|
return s:abs_path(a:bufnr, 0) =~ '^\\\\'
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! s:use_known_shell() abort
|
||||||
|
if has('unix') && &shell !=# 'sh'
|
||||||
|
let [s:shell, s:shellcmdflag, s:shellredir] = [&shell, &shellcmdflag, &shellredir]
|
||||||
|
let &shell = 'sh'
|
||||||
|
set shellcmdflag=-c shellredir=>%s\ 2>&1
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! s:restore_shell() abort
|
||||||
|
if has('unix') && exists('s:shell')
|
||||||
|
let [&shell, &shellcmdflag, &shellredir] = [s:shell, s:shellcmdflag, s:shellredir]
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! s:abs_path(bufnr, shellesc)
|
||||||
|
let p = resolve(expand('#'.a:bufnr.':p'))
|
||||||
|
return a:shellesc ? gitgutter#utility#shellescape(p) : p
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! s:dir(bufnr) abort
|
||||||
|
return gitgutter#utility#shellescape(fnamemodify(s:abs_path(a:bufnr, 0), ':h'))
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" Not shellescaped.
|
||||||
|
function! s:filename(bufnr) abort
|
||||||
|
return fnamemodify(s:abs_path(a:bufnr, 0), ':t')
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! s:exists_file(bufnr) abort
|
||||||
|
return filereadable(s:abs_path(a:bufnr, 0))
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! s:strip_trailing_new_line(line) abort
|
||||||
return substitute(a:line, '\n$', '', '')
|
return substitute(a:line, '\n$', '', '')
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
" True for git v1.7.2+.
|
function! s:windows()
|
||||||
function! gitgutter#utility#git_supports_command_line_config_override() abort
|
return has('win64') || has('win32') || has('win16')
|
||||||
call system(g:gitgutter_git_executable.' -c foo.bar=baz --version')
|
|
||||||
return !v:shell_error
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function! gitgutter#utility#stringify(list) abort
|
|
||||||
return join(a:list, "\n")."\n"
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function! gitgutter#utility#use_known_shell() abort
|
|
||||||
if has('unix')
|
|
||||||
if &shell !=# 'sh'
|
|
||||||
let s:shell = &shell
|
|
||||||
let s:shellcmdflag = &shellcmdflag
|
|
||||||
let s:shellredir = &shellredir
|
|
||||||
let &shell = 'sh'
|
|
||||||
set shellcmdflag=-c
|
|
||||||
set shellredir=>%s\ 2>&1
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function! gitgutter#utility#restore_shell() abort
|
|
||||||
if has('unix')
|
|
||||||
if exists('s:shell')
|
|
||||||
let &shell = s:shell
|
|
||||||
let &shellcmdflag = s:shellcmdflag
|
|
||||||
let &shellredir = s:shellredir
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
endfunction
|
endfunction
|
||||||
|
|
|
@ -4,45 +4,50 @@
|
||||||
Vim Git Gutter
|
Vim Git Gutter
|
||||||
|
|
||||||
|
|
||||||
Author: Andy Stewart <http://airbladesoftware.com/>
|
Author: Andy Stewart <https://airbladesoftware.com/>
|
||||||
Plugin Homepage: <https://github.com/airblade/vim-gitgutter>
|
Plugin Homepage: <https://github.com/airblade/vim-gitgutter>
|
||||||
|
|
||||||
===============================================================================
|
|
||||||
CONTENTS *GitGutterContents*
|
|
||||||
|
|
||||||
1. Introduction ................. |GitGutterIntroduction|
|
|
||||||
2. Installation ................. |GitGutterInstallation|
|
|
||||||
3. Usage ........................ |GitGutterUsage|
|
|
||||||
4. Commands ..................... |GitGutterCommands|
|
|
||||||
5. Autocommand .................. |GitGutterAutocmd|
|
|
||||||
6. CUSTOMISATION................. |GitGutterCustomisation|
|
|
||||||
7. FAQ .......................... |GitGutterFAQ|
|
|
||||||
|
|
||||||
===============================================================================
|
===============================================================================
|
||||||
1. INTRODUCTION *GitGutterIntroduction*
|
CONTENTS *gitgutter*
|
||||||
*GitGutter*
|
|
||||||
|
|
||||||
Vim Git Gutter is a Vim plugin which shows a git diff in the 'gutter' (sign
|
Introduction ................. |gitgutter-introduction|
|
||||||
column). It shows whether each line has been added, modified, and where lines
|
Installation ................. |gitgutter-installation|
|
||||||
have been removed.
|
Commands ..................... |gitgutter-commands|
|
||||||
|
Mappings ..................... |gitgutter-mappings|
|
||||||
|
Autocommand .................. |gitgutter-autocommand|
|
||||||
|
Options ...................... |gitgutter-options|
|
||||||
|
Highlights ................... |gitgutter-highlights|
|
||||||
|
FAQ .......................... |gitgutter-faq|
|
||||||
|
TROUBLESHOOTING .............. |gitgutter-troubleshooting|
|
||||||
|
|
||||||
This is a port of the Git Gutter plugin for Sublime Text 2.
|
|
||||||
|
|
||||||
===============================================================================
|
===============================================================================
|
||||||
2. INSTALLATION *GitGutterInstallation*
|
INTRODUCTION *gitgutter-introduction*
|
||||||
|
|
||||||
* Pathogen:
|
GitGutter is a Vim plugin which shows a git diff in the 'gutter' (sign column).
|
||||||
|
It shows which lines have been added, modified, or removed. You can also
|
||||||
|
preview, stage, and undo individual hunks. The plugin also provides a hunk
|
||||||
|
text object.
|
||||||
|
|
||||||
|
The signs are always up to date and the plugin never saves your buffer.
|
||||||
|
|
||||||
|
|
||||||
|
===============================================================================
|
||||||
|
INSTALLATION *gitgutter-installation*
|
||||||
|
|
||||||
|
Pathogen:~
|
||||||
>
|
>
|
||||||
cd ~/.vim/bundle
|
cd ~/.vim/bundle
|
||||||
git clone git://github.com/airblade/vim-gitgutter.git
|
git clone git://github.com/airblade/vim-gitgutter.git
|
||||||
<
|
<
|
||||||
* Voom:
|
Voom:~
|
||||||
|
|
||||||
Edit your plugin manifest (`voom edit`) and add:
|
Edit your plugin manifest (`voom edit`) and add:
|
||||||
>
|
>
|
||||||
airblade/vim-gitgutter
|
airblade/vim-gitgutter
|
||||||
<
|
<
|
||||||
* VimPlug:
|
VimPlug:~
|
||||||
|
|
||||||
Place this in your .vimrc:
|
Place this in your .vimrc:
|
||||||
>
|
>
|
||||||
|
@ -53,7 +58,7 @@ Then run the following in Vim:
|
||||||
:source %
|
:source %
|
||||||
:PlugInstall
|
:PlugInstall
|
||||||
<
|
<
|
||||||
* NeoBundle:
|
NeoBundle:~
|
||||||
|
|
||||||
Place this in your .vimrc:
|
Place this in your .vimrc:
|
||||||
>
|
>
|
||||||
|
@ -64,7 +69,7 @@ Then run the following in Vim:
|
||||||
:source %
|
:source %
|
||||||
:NeoBundleInstall
|
:NeoBundleInstall
|
||||||
<
|
<
|
||||||
* No plugin manager:
|
No plugin manager:~
|
||||||
|
|
||||||
Copy vim-gitgutter's subdirectories into your vim configuration directory:
|
Copy vim-gitgutter's subdirectories into your vim configuration directory:
|
||||||
>
|
>
|
||||||
|
@ -73,108 +78,282 @@ Copy vim-gitgutter's subdirectories into your vim configuration directory:
|
||||||
<
|
<
|
||||||
See |add-global-plugin|.
|
See |add-global-plugin|.
|
||||||
|
|
||||||
===============================================================================
|
|
||||||
3. USAGE *GitGutterUsage*
|
|
||||||
|
|
||||||
You don't have to do anything: it just works.
|
|
||||||
|
|
||||||
===============================================================================
|
===============================================================================
|
||||||
4. COMMANDS *GitGutterCommands*
|
COMMANDS *gitgutter-commands*
|
||||||
|
|
||||||
Commands for turning Git Gutter on and off:
|
Commands for turning vim-gitgutter on and off:~
|
||||||
|
|
||||||
:GitGutterDisable *:GitGutterDisable*
|
*gitgutter-:GitGutterDisable*
|
||||||
Explicitly turn Git Gutter off.
|
:GitGutterDisable Turn vim-gitgutter off for all buffers.
|
||||||
|
|
||||||
:GitGutterEnable *:GitGutterEnable*
|
*gitgutter-:GitGutterEnable*
|
||||||
Explicitly turn Git Gutter on.
|
:GitGutterEnable Turn vim-gitgutter on for all buffers.
|
||||||
|
|
||||||
:GitGutterToggle *:GitGutterToggle*
|
*gitgutter-:GitGutterToggle*
|
||||||
Explicitly turn Git Gutter on if it was off and vice versa.
|
:GitGutterToggle Toggle vim-gitgutter on or off for all buffers.
|
||||||
|
|
||||||
:GitGutter *:GitGutter*
|
*gitgutter-:GitGutter*
|
||||||
Update signs for the current buffer.
|
:GitGutter Update signs for the current buffer. You shouldn't
|
||||||
|
need to run this.
|
||||||
|
|
||||||
:GitGutterAll *:GitGutterAll*
|
*gitgutter-:GitGutterAll*
|
||||||
Update signs across all buffers.
|
:GitGutterAll Update signs for all buffers. You shouldn't need to
|
||||||
|
run this.
|
||||||
|
|
||||||
Commands for turning signs on and off (defaults to on):
|
|
||||||
|
|
||||||
:GitGutterSignsEnable *:GitGutterSignsEnable*
|
Commands for turning signs on and off (defaults to on):~
|
||||||
Explicitly turn line signs on.
|
|
||||||
|
|
||||||
:GitGutterSignsDisable *:GitGutterSignsDisable*
|
*gitgutter-:GitGutterSignsEnable*
|
||||||
Explicitly turn line signs off.
|
:GitGutterSignsEnable Show signs for the diff.
|
||||||
|
|
||||||
:GitGutterSignsToggle *:GitGutterSignsToggle*
|
*gitgutter-:GitGutterSignsDisable*
|
||||||
Explicitly turn line signs on if it was off and vice versa.
|
:GitGutterSignsDisable Do not show signs for the diff.
|
||||||
|
|
||||||
Commands for turning line highlighting on and off (defaults to off):
|
*gitgutter-:GitGutterSignsToggle*
|
||||||
|
:GitGutterSignsToggle Toggle signs on or off.
|
||||||
|
|
||||||
:GitGutterLineHighlightsEnable *:GitGutterLineHighlightsEnable*
|
|
||||||
Explicitly turn line highlighting on.
|
|
||||||
|
|
||||||
:GitGutterLineHighlightsDisable *:GitGutterLineHighlightsDisable*
|
Commands for turning line highlighting on and off (defaults to off):~
|
||||||
Explicitly turn line highlighting off.
|
|
||||||
|
|
||||||
:GitGutterLineHighlightsToggle *:GitGutterLineHighlightsToggle*
|
*gitgutter-:GitGutterLineHighlightsEnable*
|
||||||
Explicitly turn line highlighting on if it was off and vice versa.
|
:GitGutterLineHighlightsEnable Turn on line highlighting.
|
||||||
|
|
||||||
Commands for jumping between marked hunks:
|
*gitgutter-:GitGutterLineHighlightsDisable*
|
||||||
|
:GitGutterLineHighlightsDisable Turn off line highlighting.
|
||||||
|
|
||||||
:GitGutterNextHunk *:GitGutterNextHunk*
|
*gitgutter-:GitGutterLineHighlightsToggle*
|
||||||
Jump to the next marked hunk. Takes a count.
|
:GitGutterLineHighlightsToggle Turn line highlighting on or off.
|
||||||
|
|
||||||
:GitGutterPrevHunk *:GitGutterPrevHunk*
|
|
||||||
Jump to the previous marked hunk. Takes a count.
|
|
||||||
|
|
||||||
Commands for staging or undoing individual hunks:
|
Commands for jumping between hunks:~
|
||||||
|
|
||||||
:GitGutterStageHunk *:GitGutterStageHunk*
|
*gitgutter-:GitGutterNextHunk*
|
||||||
Stage the hunk the cursor is in.
|
:GitGutterNextHunk Jump to the next [count] hunk.
|
||||||
|
|
||||||
:GitGutterUndoHunk *:GitGutterUndoHunk*
|
*gitgutter-:GitGutterPrevHunk*
|
||||||
Undo the hunk the cursor is in.
|
:GitGutterPrevHunk Jump to the previous [count] hunk.
|
||||||
|
|
||||||
|
|
||||||
|
Commands for operating on a hunk:~
|
||||||
|
|
||||||
|
*gitgutter-:GitGutterStageHunk*
|
||||||
|
:GitGutterStageHunk Stage the hunk the cursor is in.
|
||||||
|
|
||||||
|
*gitgutter-:GitGutterUndoHunk*
|
||||||
|
:GitGutterUndoHunk Undo the hunk the cursor is in.
|
||||||
|
|
||||||
|
*gitgutter-:GitGutterPreviewHunk*
|
||||||
|
:GitGutterPreviewHunk Preview the hunk the cursor is in.
|
||||||
|
Use |:pclose| or |CTRL-W_CTRL-Z| to close the preview
|
||||||
|
window.
|
||||||
|
|
||||||
:GitGutterPreviewHunk *:GitGutterPreviewHunk*
|
|
||||||
Preview the hunk the cursor is in.
|
|
||||||
Use |:pclose| or |CTRL-W_CTRL-Z| to close the preview window.
|
|
||||||
|
|
||||||
===============================================================================
|
===============================================================================
|
||||||
5. AUTOCOMMAND *GitGutterAutocmd*
|
AUTOCOMMAND *gitgutter-autocommand*
|
||||||
|
|
||||||
|
User GitGutter~
|
||||||
|
|
||||||
After updating a buffer's signs vim-gitgutter fires a |User| |autocmd| with the
|
After updating a buffer's signs vim-gitgutter fires a |User| |autocmd| with the
|
||||||
event GitGutter. You can listen for this event, for example:
|
event GitGutter. You can listen for this event, for example:
|
||||||
>
|
>
|
||||||
autocmd User GitGutter call updateMyStatusLine()
|
autocmd User GitGutter call updateMyStatusLine()
|
||||||
<
|
<
|
||||||
|
A dictionary `g:gitgutter_hook_context` is made available during its execution,
|
||||||
|
which contains an entry `bufnr` that contains the buffer number being updated.
|
||||||
|
|
||||||
|
|
||||||
===============================================================================
|
===============================================================================
|
||||||
6. CUSTOMISATION *GitGutterCustomisation*
|
MAPPINGS *gitgutter-mappings*
|
||||||
|
|
||||||
You can customise:
|
You can disable all these mappings with:
|
||||||
|
>
|
||||||
|
let g:gitgutter_map_keys = 0
|
||||||
|
<
|
||||||
|
|
||||||
- The sign column's colours
|
Hunk operations:~
|
||||||
- The signs' colours and symbols
|
|
||||||
- Line highlights
|
|
||||||
- The base of the diff
|
|
||||||
- Extra arguments for git-diff
|
|
||||||
- Key mappings
|
|
||||||
- The grep executable used
|
|
||||||
- Whether or not vim-gitgutter is on initially (defaults to on)
|
|
||||||
- Whether or not signs are shown (defaults to yes)
|
|
||||||
- Whether or not line highlighting is on initially (defaults to off)
|
|
||||||
- Whether or not vim-gitgutter runs in realtime (defaults to yes)
|
|
||||||
- Whether or not vim-gitgutter runs eagerly (defaults to yes)
|
|
||||||
- Whether or not vim-gitgutter runs asynchronously (defaults to yes)
|
|
||||||
|
|
||||||
Please note that vim-gitgutter won't override any colours or highlights you've
|
These can be repeated with `.` if you have vim-repeat installed.
|
||||||
set in your colorscheme.
|
|
||||||
|
|
||||||
SIGN COLUMN
|
*gitgutter-<Leader>hp*
|
||||||
|
<Leader>hp Preview the hunk under the cursor.
|
||||||
|
|
||||||
By default vim-gitgutter will make the sign column look like the line number
|
*gitgutter-<Leader>hs*
|
||||||
column (i.e. the |hl-LineNr| highlight group).
|
<Leader>hs Stage the hunk under the cursor.
|
||||||
|
|
||||||
|
*gitgutter-<Leader>hu*
|
||||||
|
<Leader>hu Undo the hunk under the cursor.
|
||||||
|
|
||||||
|
You can change these mappings like this:
|
||||||
|
>
|
||||||
|
nmap ghp <Plug>GitGutterPreviewHunk
|
||||||
|
nmap ghs <Plug>GitGutterStageHunk
|
||||||
|
nmap ghu <Plug>GitGutterUndoHunk
|
||||||
|
<
|
||||||
|
|
||||||
|
Hunk jumping:~
|
||||||
|
|
||||||
|
*gitgutter-]c*
|
||||||
|
]c Jump to the next [count] hunk.
|
||||||
|
|
||||||
|
*gitgutter-[c*
|
||||||
|
[c Jump to the previous [count] hunk.
|
||||||
|
|
||||||
|
You can change these mappings like this:
|
||||||
|
>
|
||||||
|
nmap [c <Plug>GitGutterPrevHunk
|
||||||
|
nmap ]c <Plug>GitGutterNextHunk
|
||||||
|
<
|
||||||
|
|
||||||
|
Hunk text object:~
|
||||||
|
|
||||||
|
*gitgutter-ic* *gitgutter-ac* *gitgutter-text-object*
|
||||||
|
"ic" operates on the current hunk's lines. "ac" does the same but also includes
|
||||||
|
trailing empty lines.
|
||||||
|
>
|
||||||
|
omap ic <Plug>GitGutterTextObjectInnerPending
|
||||||
|
omap ac <Plug>GitGutterTextObjectOuterPending
|
||||||
|
xmap ic <Plug>GitGutterTextObjectInnerVisual
|
||||||
|
xmap ac <Plug>GitGutterTextObjectOuterVisual
|
||||||
|
<
|
||||||
|
|
||||||
|
|
||||||
|
===============================================================================
|
||||||
|
OPTIONS *gitgutter-options*
|
||||||
|
|
||||||
|
The most important option is 'updatetime' which determines how long (in
|
||||||
|
milliseconds) the plugin will wait after you stop typing before it updates the
|
||||||
|
signs. Vim's default is 4000. I recommend 100.
|
||||||
|
|
||||||
|
Most important option:~
|
||||||
|
|
||||||
|
'updatetime'
|
||||||
|
|
||||||
|
Git:~
|
||||||
|
|
||||||
|
|g:gitgutter_git_executable|
|
||||||
|
|g:gitgutter_diff_args|
|
||||||
|
|g:gitgutter_diff_base|
|
||||||
|
|
||||||
|
Grep:~
|
||||||
|
|
||||||
|
|g:gitgutter_grep|
|
||||||
|
|
||||||
|
Signs:~
|
||||||
|
|
||||||
|
|g:gitgutter_signs|
|
||||||
|
|g:gitgutter_highlight_lines|
|
||||||
|
|g:gitgutter_max_signs|
|
||||||
|
|g:gitgutter_sign_added|
|
||||||
|
|g:gitgutter_sign_modified|
|
||||||
|
|g:gitgutter_sign_removed|
|
||||||
|
|g:gitgutter_sign_removed_first_line|
|
||||||
|
|g:gitgutter_sign_modified_removed|
|
||||||
|
|g:gitgutter_sign_column_always|
|
||||||
|
|g:gitgutter_override_sign_column_highlight|
|
||||||
|
|
||||||
|
Terminal:~
|
||||||
|
|
||||||
|
|g:gitgutter_terminal_reports_focus|
|
||||||
|
|
||||||
|
General:~
|
||||||
|
|
||||||
|
|g:gitgutter_enabled|
|
||||||
|
|g:gitgutter_map_keys|
|
||||||
|
|g:gitgutter_async|
|
||||||
|
|g:gitgutter_log|
|
||||||
|
|
||||||
|
|
||||||
|
*g:gitgutter_git_executable*
|
||||||
|
Default: 'git'
|
||||||
|
|
||||||
|
This option determines what git binary to use. Set this if git is not on your
|
||||||
|
path.
|
||||||
|
|
||||||
|
*g:gitgutter_diff_args*
|
||||||
|
Default: empty
|
||||||
|
|
||||||
|
Use this option to pass any extra arguments to git-diff. For example:
|
||||||
|
>
|
||||||
|
let g:gitgutter_diff_args = '-w'
|
||||||
|
<
|
||||||
|
|
||||||
|
*g:gitgutter_diff_base*
|
||||||
|
Default: empty
|
||||||
|
|
||||||
|
By default buffers are diffed against the index. Use this option to diff against
|
||||||
|
a revision instead. For example:
|
||||||
|
>
|
||||||
|
let g:gitgutter_diff_base = '<some commit SHA>'
|
||||||
|
<
|
||||||
|
|
||||||
|
*g:gitgutter_grep*
|
||||||
|
Default: 'grep'
|
||||||
|
|
||||||
|
The plugin pipes the output of git-diff into grep to minimise the amount of data
|
||||||
|
vim has to process. Set this option if grep is not on your path.
|
||||||
|
|
||||||
|
grep must produce plain-text output without any ANSI escape codes or colours.
|
||||||
|
Use this option to turn off colours if necessary.
|
||||||
|
>
|
||||||
|
let g:gitgutter_grep = 'grep --color=never'
|
||||||
|
<
|
||||||
|
If you do not want to use grep at all (perhaps to debug why signs are not
|
||||||
|
showing), set this option to an empty string:
|
||||||
|
>
|
||||||
|
let g:gitgutter_grep = ''
|
||||||
|
<
|
||||||
|
|
||||||
|
*g:gitgutter_signs*
|
||||||
|
Default: 1
|
||||||
|
|
||||||
|
Determines whether or not to show signs.
|
||||||
|
|
||||||
|
*g:gitgutter_highlight_lines*
|
||||||
|
Default: 0
|
||||||
|
|
||||||
|
Determines whether or not to show line highlights.
|
||||||
|
|
||||||
|
*g:gitgutter_max_signs*
|
||||||
|
Default: 500
|
||||||
|
|
||||||
|
Sets the maximum number of signs to show in a buffer. Vim is slow at updating
|
||||||
|
signs, so to avoid slowing down the GUI the number of signs is capped. When
|
||||||
|
the number of changed lines exceeds this value, the plugin removes all signs
|
||||||
|
and displays a warning message.
|
||||||
|
|
||||||
|
*g:gitgutter_sign_added*
|
||||||
|
*g:gitgutter_sign_modified*
|
||||||
|
*g:gitgutter_sign_removed*
|
||||||
|
*g:gitgutter_sign_removed_first_line*
|
||||||
|
*g:gitgutter_sign_modified_removed*
|
||||||
|
Defaults:
|
||||||
|
>
|
||||||
|
let g:gitgutter_sign_added = '+'
|
||||||
|
let g:gitgutter_sign_modified = '~'
|
||||||
|
let g:gitgutter_sign_removed = '_'
|
||||||
|
let g:gitgutter_sign_removed_first_line = '‾'
|
||||||
|
let g:gitgutter_sign_modified_removed = '~_'
|
||||||
|
<
|
||||||
|
You can use unicode characters but not images. Signs must not take up more than
|
||||||
|
2 columns.
|
||||||
|
|
||||||
|
*g:gitgutter_sign_column_always*
|
||||||
|
Default: 0
|
||||||
|
|
||||||
|
This legacy option controls whether the sign column should always be shown, even
|
||||||
|
if there are no signs to display.
|
||||||
|
|
||||||
|
From Vim 7.4.2201, use 'signcolumn' instead:
|
||||||
|
>
|
||||||
|
set signcolumn=yes
|
||||||
|
<
|
||||||
|
|
||||||
|
*g:gitgutter_override_sign_column_highlight*
|
||||||
|
Default: 1
|
||||||
|
|
||||||
|
Controls whether to make the sign column look like the line-number column (i.e.
|
||||||
|
the |hl-LineNr| highlight group).
|
||||||
|
|
||||||
To customise your sign column's background color, first tell vim-gitgutter to
|
To customise your sign column's background color, first tell vim-gitgutter to
|
||||||
leave it alone:
|
leave it alone:
|
||||||
|
@ -186,15 +365,54 @@ And then either update your colorscheme's |hlSignColumn| highlight group or set
|
||||||
it in your |vimrc|:
|
it in your |vimrc|:
|
||||||
|
|
||||||
Desired appearance Command ~
|
Desired appearance Command ~
|
||||||
Same as line number column highlight clear SignColumn
|
Same as line-number column highlight clear SignColumn
|
||||||
User-defined (terminal Vim) highlight SignColumn ctermbg={whatever}
|
User-defined (terminal Vim) highlight SignColumn ctermbg={whatever}
|
||||||
User-defined (graphical Vim) highlight SignColumn guibg={whatever}
|
User-defined (graphical Vim) highlight SignColumn guibg={whatever}
|
||||||
|
|
||||||
SIGNS' COLOURS AND SYMBOLS
|
|
||||||
|
|
||||||
To customise the colours, set up the following highlight groups in your
|
*g:gitgutter_terminal_reports_focus*
|
||||||
|
Default: 1
|
||||||
|
|
||||||
|
Normally the plugin uses |FocusGained| to force-update all buffers when Vim
|
||||||
|
receives focus. However some terminals do not report focus events and so the
|
||||||
|
|FocusGained| autocommand never fires.
|
||||||
|
|
||||||
|
If this applies to you, either install something like Terminus
|
||||||
|
(https://github.com/wincent/terminus) to make |FocusGained| work or set this
|
||||||
|
option to 0.
|
||||||
|
|
||||||
|
When this option is 0, the plugin force-updates the buffer on |BufEnter|
|
||||||
|
(instead of only updating if the buffer's contents has changed since the last
|
||||||
|
update).
|
||||||
|
|
||||||
|
*g:gitgutter_enabled*
|
||||||
|
Default: 1
|
||||||
|
|
||||||
|
Controls whether or not the plugin is on at startup.
|
||||||
|
|
||||||
|
*g:gitgutter_map_keys*
|
||||||
|
Default: 1
|
||||||
|
|
||||||
|
Controls whether or not the plugin provides mappings. See |gitgutter-mapppings|.
|
||||||
|
|
||||||
|
*g:gitgutter_async*
|
||||||
|
Default: 1
|
||||||
|
|
||||||
|
Controls whether or not diffs are run in the background. This has no effect if
|
||||||
|
your Vim does not support background jobs.
|
||||||
|
|
||||||
|
*g:gitgutter_log*
|
||||||
|
Default: 0
|
||||||
|
|
||||||
|
When switched on, the plugin logs to gitgutter.log in the directory where it is
|
||||||
|
installed. Additionally it logs channel activity to channel.log.
|
||||||
|
|
||||||
|
|
||||||
|
===============================================================================
|
||||||
|
HIGHLIGHTS *gitgutter-highlights*
|
||||||
|
|
||||||
|
To change the signs' colours, set up the following highlight groups in your
|
||||||
colorscheme or |vimrc|:
|
colorscheme or |vimrc|:
|
||||||
|
|
||||||
>
|
>
|
||||||
GitGutterAdd " an added line
|
GitGutterAdd " an added line
|
||||||
GitGutterChange " a changed line
|
GitGutterChange " a changed line
|
||||||
|
@ -208,17 +426,7 @@ them to existing highlight groups with, say:
|
||||||
highlight link GitGutterAdd DiffAdd
|
highlight link GitGutterAdd DiffAdd
|
||||||
<
|
<
|
||||||
|
|
||||||
To customise the symbols, add the following to your |vimrc|:
|
To change the line highlights, set up the following highlight groups in your
|
||||||
>
|
|
||||||
let g:gitgutter_sign_added = 'xx'
|
|
||||||
let g:gitgutter_sign_modified = 'yy'
|
|
||||||
let g:gitgutter_sign_removed = 'zz'
|
|
||||||
let g:gitgutter_sign_modified_removed = 'ww'
|
|
||||||
<
|
|
||||||
|
|
||||||
LINE HIGHLIGHTS
|
|
||||||
|
|
||||||
Similarly to the signs' colours, set up the following highlight groups in your
|
|
||||||
colorscheme or |vimrc|:
|
colorscheme or |vimrc|:
|
||||||
>
|
>
|
||||||
GitGutterAddLine " default: links to DiffAdd
|
GitGutterAddLine " default: links to DiffAdd
|
||||||
|
@ -227,115 +435,85 @@ colorscheme or |vimrc|:
|
||||||
GitGutterChangeDeleteLine " default: links to GitGutterChangeLineDefault
|
GitGutterChangeDeleteLine " default: links to GitGutterChangeLineDefault
|
||||||
<
|
<
|
||||||
|
|
||||||
THE BASE OF THE DIFF
|
|
||||||
|
|
||||||
By default buffers are diffed against the index. To diff against a commit
|
|
||||||
instead:
|
|
||||||
>
|
|
||||||
let g:gitgutter_diff_base = '<commit SHA>'
|
|
||||||
<
|
|
||||||
|
|
||||||
EXTRA ARGUMENTS FOR GIT-DIFF
|
|
||||||
|
|
||||||
To pass extra arguments to git-diff, add this to your |vimrc|:
|
|
||||||
>
|
|
||||||
let g:gitgutter_diff_args = '-w'
|
|
||||||
<
|
|
||||||
|
|
||||||
KEY MAPPINGS
|
|
||||||
|
|
||||||
To disable all key maps:
|
|
||||||
>
|
|
||||||
let g:gitgutter_map_keys = 0
|
|
||||||
<
|
|
||||||
|
|
||||||
To change the hunk-jumping maps (defaults shown):
|
|
||||||
>
|
|
||||||
nmap [c <Plug>GitGutterPrevHunk
|
|
||||||
nmap ]c <Plug>GitGutterNextHunk
|
|
||||||
<
|
|
||||||
|
|
||||||
To change the hunk-staging/undoing/previewing maps (defaults shown):
|
|
||||||
>
|
|
||||||
nmap <Leader>hs <Plug>GitGutterStageHunk
|
|
||||||
nmap <Leader>hu <Plug>GitGutterUndoHunk
|
|
||||||
nmap <Leader>hp <Plug>GitGutterPreviewHunk
|
|
||||||
<
|
|
||||||
|
|
||||||
To change the hunk text object maps (defaults shown):
|
|
||||||
>
|
|
||||||
omap ic <Plug>GitGutterTextObjectInnerPending
|
|
||||||
omap ac <Plug>GitGutterTextObjectOuterPending
|
|
||||||
xmap ic <Plug>GitGutterTextObjectInnerVisual
|
|
||||||
xmap ac <Plug>GitGutterTextObjectOuterVisual
|
|
||||||
<
|
|
||||||
|
|
||||||
TO USE A CUSTOM GREP COMMAND
|
|
||||||
|
|
||||||
To use a custom invocation for grep, use this:
|
|
||||||
>
|
|
||||||
let g:gitgutter_grep_command = 'grep'
|
|
||||||
<
|
|
||||||
|
|
||||||
TO TURN OFF VIM-GITGUTTER BY DEFAULT
|
|
||||||
|
|
||||||
Add to your |vimrc|
|
|
||||||
>
|
|
||||||
let g:gitgutter_enabled = 0
|
|
||||||
<
|
|
||||||
|
|
||||||
TO TURN OFF SIGNS BY DEFAULT
|
|
||||||
|
|
||||||
Add to your |vimrc|
|
|
||||||
>
|
|
||||||
let g:gitgutter_signs = 0
|
|
||||||
<
|
|
||||||
|
|
||||||
Note that the sign column will still be present if you have line highlighting
|
|
||||||
switched on.
|
|
||||||
|
|
||||||
TO TURN ON LINE HIGHLIGHTING BY DEFAULT
|
|
||||||
|
|
||||||
Add to your |vimrc|
|
|
||||||
>
|
|
||||||
let g:gitgutter_highlight_lines = 1
|
|
||||||
<
|
|
||||||
|
|
||||||
TO STOP VIM-GITGUTTER RUNNING IN REALTIME
|
|
||||||
|
|
||||||
Add to your |vimrc|
|
|
||||||
>
|
|
||||||
let g:gitgutter_realtime = 0
|
|
||||||
<
|
|
||||||
|
|
||||||
TO STOP VIM-GITGUTTER RUNNING EAGERLY
|
|
||||||
|
|
||||||
Add to your |vimrc|
|
|
||||||
>
|
|
||||||
let g:gitgutter_eager = 0
|
|
||||||
<
|
|
||||||
|
|
||||||
TO TURN OFF ASYNCHRONOUS UPDATES
|
|
||||||
|
|
||||||
By default diffs are run asynchronously. To run diffs synchronously
|
|
||||||
instead:
|
|
||||||
|
|
||||||
Add to your |vimrc|
|
|
||||||
>
|
|
||||||
let g:gitgutter_async = 0
|
|
||||||
<
|
|
||||||
|
|
||||||
===============================================================================
|
===============================================================================
|
||||||
7. FAQ *GitGutterFAQ*
|
FAQ *gitgutter-faq*
|
||||||
|
|
||||||
a. Why are the colours in the sign column weird?
|
a. How do I turn off realtime updates?
|
||||||
|
|
||||||
|
Add this to your vim configuration in an |after-directory|:
|
||||||
|
>
|
||||||
|
autocmd! gitgutter CursorHold,CursorHoldI
|
||||||
|
<
|
||||||
|
b. Why can't I unstage staged changes?
|
||||||
|
|
||||||
|
This plugin is for showing changes between the working tree and the index
|
||||||
|
(and staging/undoing those changes). Unstaging a staged hunk would require
|
||||||
|
showing changes between the index and HEAD, which is out of scope.
|
||||||
|
|
||||||
|
c. Why are the colours in the sign column weird?
|
||||||
|
|
||||||
Your colorscheme is configuring the |hl-SignColumn| highlight group weirdly.
|
Your colorscheme is configuring the |hl-SignColumn| highlight group weirdly.
|
||||||
Please see |GitGutterCustomisation| on customising the sign column.
|
Please see |g:gitgutter_override_sign_column_highlight| on customising the
|
||||||
|
sign column.
|
||||||
|
|
||||||
b. What happens if I also use another plugin which uses signs (e.g. Syntastic)?
|
d. What happens if I also use another plugin which uses signs (e.g. Syntastic)?
|
||||||
|
|
||||||
|
Vim only allows one sign per line. Vim-gitgutter will not interfere with
|
||||||
|
signs it did not add.
|
||||||
|
|
||||||
|
|
||||||
|
===============================================================================
|
||||||
|
TROUBLESHOOTING *gitgutter-troubleshooting*
|
||||||
|
|
||||||
|
When no signs are showing at all:~
|
||||||
|
|
||||||
|
1. Try bypassing grep with:
|
||||||
|
>
|
||||||
|
let g:gitgutter_grep = ''
|
||||||
|
<
|
||||||
|
If it works, the problem is grep outputting ANSI escape codes. Use this
|
||||||
|
option to pass arguments to grep to turn off the escape codes.
|
||||||
|
|
||||||
|
2. Verify git is on your path:
|
||||||
|
>
|
||||||
|
:echo system('git --version')
|
||||||
|
<
|
||||||
|
|
||||||
|
3. Verify your git config is compatible with the version of git return by the
|
||||||
|
command above.
|
||||||
|
|
||||||
|
4. Verify your Vim supports signs. The following should give 1:
|
||||||
|
>
|
||||||
|
:echo has('signs')
|
||||||
|
<
|
||||||
|
|
||||||
|
5. Check whether the plugin thinks git knows about your file:
|
||||||
|
>
|
||||||
|
:echo getbufvar('','gitgutter').path
|
||||||
|
<
|
||||||
|
If the result is -2, the plugin thinks your file is not tracked by git.
|
||||||
|
|
||||||
|
|
||||||
|
When the whole file is marked as added:~
|
||||||
|
|
||||||
|
If you use zsh, and you set "CDPATH", make sure "CDPATH" does not include the
|
||||||
|
current directory.
|
||||||
|
|
||||||
|
|
||||||
|
When signs take a few seconds to appear:~
|
||||||
|
|
||||||
|
Try reducing 'updatetime':
|
||||||
|
>
|
||||||
|
set updatetime=100
|
||||||
|
<
|
||||||
|
|
||||||
|
|
||||||
|
When signs don't update after focusing Vim:~
|
||||||
|
|
||||||
|
Your terminal probably isn't reporting focus events. Either try installing
|
||||||
|
Terminus (https://github.com/wincent/terminus) or set:
|
||||||
|
>
|
||||||
|
let g:gitgutter_terminal_reports_focus = 0
|
||||||
|
<
|
||||||
|
|
||||||
Vim only allows one sign per line. Before adding a sign to a line,
|
|
||||||
vim-gitgutter checks whether a sign has already been added by somebody else.
|
|
||||||
If so it doesn't do anything. In other words vim-gitgutter won't overwrite
|
|
||||||
another plugin's signs. It also won't remove another plugin's signs.
|
|
||||||
|
|
|
@ -7,14 +7,9 @@ let g:loaded_gitgutter = 1
|
||||||
|
|
||||||
" Initialisation {{{
|
" Initialisation {{{
|
||||||
|
|
||||||
" Realtime sign updates require Vim 7.3.105+.
|
|
||||||
if v:version < 703 || (v:version == 703 && !has("patch105"))
|
if v:version < 703 || (v:version == 703 && !has("patch105"))
|
||||||
let g:gitgutter_realtime = 0
|
call gitgutter#utility#warn('requires Vim 7.3.105')
|
||||||
endif
|
finish
|
||||||
|
|
||||||
" Eager updates require gettabvar()/settabvar().
|
|
||||||
if !exists("*gettabvar")
|
|
||||||
let g:gitgutter_eager = 0
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
function! s:set(var, default) abort
|
function! s:set(var, default) abort
|
||||||
|
@ -33,35 +28,50 @@ call s:set('g:gitgutter_signs', 1)
|
||||||
call s:set('g:gitgutter_highlight_lines', 0)
|
call s:set('g:gitgutter_highlight_lines', 0)
|
||||||
call s:set('g:gitgutter_sign_column_always', 0)
|
call s:set('g:gitgutter_sign_column_always', 0)
|
||||||
if g:gitgutter_sign_column_always && exists('&signcolumn')
|
if g:gitgutter_sign_column_always && exists('&signcolumn')
|
||||||
|
" Vim 7.4.2201.
|
||||||
set signcolumn=yes
|
set signcolumn=yes
|
||||||
let g:gitgutter_sign_column_always = 0
|
let g:gitgutter_sign_column_always = 0
|
||||||
call gitgutter#utility#warn('please replace "let g:gitgutter_sign_column_always=1" with "set signcolumn=yes"')
|
call gitgutter#utility#warn('please replace "let g:gitgutter_sign_column_always=1" with "set signcolumn=yes"')
|
||||||
endif
|
endif
|
||||||
call s:set('g:gitgutter_override_sign_column_highlight', 1)
|
call s:set('g:gitgutter_override_sign_column_highlight', 1)
|
||||||
call s:set('g:gitgutter_realtime', 1)
|
|
||||||
call s:set('g:gitgutter_eager', 1)
|
|
||||||
call s:set('g:gitgutter_sign_added', '+')
|
call s:set('g:gitgutter_sign_added', '+')
|
||||||
call s:set('g:gitgutter_sign_modified', '~')
|
call s:set('g:gitgutter_sign_modified', '~')
|
||||||
call s:set('g:gitgutter_sign_removed', '_')
|
call s:set('g:gitgutter_sign_removed', '_')
|
||||||
try
|
|
||||||
|
if gitgutter#utility#supports_overscore_sign()
|
||||||
call s:set('g:gitgutter_sign_removed_first_line', '‾')
|
call s:set('g:gitgutter_sign_removed_first_line', '‾')
|
||||||
catch /E239/
|
else
|
||||||
let g:gitgutter_sign_removed_first_line = '_^'
|
call s:set('g:gitgutter_sign_removed_first_line', '_^')
|
||||||
endtry
|
endif
|
||||||
|
|
||||||
call s:set('g:gitgutter_sign_modified_removed', '~_')
|
call s:set('g:gitgutter_sign_modified_removed', '~_')
|
||||||
call s:set('g:gitgutter_diff_args', '')
|
call s:set('g:gitgutter_diff_args', '')
|
||||||
call s:set('g:gitgutter_diff_base', '')
|
call s:set('g:gitgutter_diff_base', '')
|
||||||
call s:set('g:gitgutter_map_keys', 1)
|
call s:set('g:gitgutter_map_keys', 1)
|
||||||
call s:set('g:gitgutter_avoid_cmd_prompt_on_windows', 1)
|
call s:set('g:gitgutter_terminal_reports_focus', 1)
|
||||||
call s:set('g:gitgutter_async', 1)
|
call s:set('g:gitgutter_async', 1)
|
||||||
call s:set('g:gitgutter_log', 0)
|
call s:set('g:gitgutter_log', 0)
|
||||||
call s:set('g:gitgutter_git_executable', 'git')
|
|
||||||
|
|
||||||
|
call s:set('g:gitgutter_git_executable', 'git')
|
||||||
if !executable(g:gitgutter_git_executable)
|
if !executable(g:gitgutter_git_executable)
|
||||||
call gitgutter#utility#warn('cannot find git. Please set g:gitgutter_git_executable.')
|
call gitgutter#utility#warn('cannot find git. Please set g:gitgutter_git_executable.')
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
let default_grep = 'grep'
|
||||||
|
call s:set('g:gitgutter_grep', default_grep)
|
||||||
|
if !empty(g:gitgutter_grep)
|
||||||
|
if executable(split(g:gitgutter_grep)[0])
|
||||||
|
if $GREP_OPTIONS =~# '--color=always'
|
||||||
|
let g:gitgutter_grep .= ' --color=never'
|
||||||
|
endif
|
||||||
|
else
|
||||||
|
if g:gitgutter_grep !=# default_grep
|
||||||
|
call gitgutter#utility#warn('cannot find '.g:gitgutter_grep.'. Please check g:gitgutter_grep.')
|
||||||
|
endif
|
||||||
|
let g:gitgutter_grep = ''
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
call gitgutter#highlight#define_sign_column_highlight()
|
call gitgutter#highlight#define_sign_column_highlight()
|
||||||
call gitgutter#highlight#define_highlights()
|
call gitgutter#highlight#define_highlights()
|
||||||
call gitgutter#highlight#define_signs()
|
call gitgutter#highlight#define_signs()
|
||||||
|
@ -70,40 +80,39 @@ call gitgutter#highlight#define_signs()
|
||||||
|
|
||||||
" Primary functions {{{
|
" Primary functions {{{
|
||||||
|
|
||||||
command -bar GitGutterAll call gitgutter#all()
|
command! -bar GitGutterAll call gitgutter#all(1)
|
||||||
command -bar GitGutter call gitgutter#process_buffer(bufnr(''), 0)
|
command! -bar GitGutter call gitgutter#process_buffer(bufnr(''), 1)
|
||||||
|
|
||||||
command -bar GitGutterDisable call gitgutter#disable()
|
command! -bar GitGutterDisable call gitgutter#disable()
|
||||||
command -bar GitGutterEnable call gitgutter#enable()
|
command! -bar GitGutterEnable call gitgutter#enable()
|
||||||
command -bar GitGutterToggle call gitgutter#toggle()
|
command! -bar GitGutterToggle call gitgutter#toggle()
|
||||||
|
|
||||||
" }}}
|
" }}}
|
||||||
|
|
||||||
" Line highlights {{{
|
" Line highlights {{{
|
||||||
|
|
||||||
command -bar GitGutterLineHighlightsDisable call gitgutter#line_highlights_disable()
|
command! -bar GitGutterLineHighlightsDisable call gitgutter#highlight#line_disable()
|
||||||
command -bar GitGutterLineHighlightsEnable call gitgutter#line_highlights_enable()
|
command! -bar GitGutterLineHighlightsEnable call gitgutter#highlight#line_enable()
|
||||||
command -bar GitGutterLineHighlightsToggle call gitgutter#line_highlights_toggle()
|
command! -bar GitGutterLineHighlightsToggle call gitgutter#highlight#line_toggle()
|
||||||
|
|
||||||
" }}}
|
" }}}
|
||||||
|
|
||||||
" Signs {{{
|
" Signs {{{
|
||||||
|
|
||||||
command -bar GitGutterSignsEnable call gitgutter#signs_enable()
|
command! -bar GitGutterSignsEnable call gitgutter#sign#enable()
|
||||||
command -bar GitGutterSignsDisable call gitgutter#signs_disable()
|
command! -bar GitGutterSignsDisable call gitgutter#sign#disable()
|
||||||
command -bar GitGutterSignsToggle call gitgutter#signs_toggle()
|
command! -bar GitGutterSignsToggle call gitgutter#sign#toggle()
|
||||||
|
|
||||||
" }}}
|
" }}}
|
||||||
|
|
||||||
" Hunks {{{
|
" Hunks {{{
|
||||||
|
|
||||||
command -bar -count=1 GitGutterNextHunk call gitgutter#hunk#next_hunk(<count>)
|
command! -bar -count=1 GitGutterNextHunk call gitgutter#hunk#next_hunk(<count>)
|
||||||
command -bar -count=1 GitGutterPrevHunk call gitgutter#hunk#prev_hunk(<count>)
|
command! -bar -count=1 GitGutterPrevHunk call gitgutter#hunk#prev_hunk(<count>)
|
||||||
|
|
||||||
command -bar GitGutterStageHunk call gitgutter#stage_hunk()
|
command! -bar GitGutterStageHunk call gitgutter#hunk#stage()
|
||||||
command -bar GitGutterUndoHunk call gitgutter#undo_hunk()
|
command! -bar GitGutterUndoHunk call gitgutter#hunk#undo()
|
||||||
command -bar GitGutterRevertHunk echomsg 'GitGutterRevertHunk is deprecated. Use GitGutterUndoHunk'<Bar>call gitgutter#undo_hunk()
|
command! -bar GitGutterPreviewHunk call gitgutter#hunk#preview()
|
||||||
command -bar GitGutterPreviewHunk call gitgutter#preview_hunk()
|
|
||||||
|
|
||||||
" Hunk text object
|
" Hunk text object
|
||||||
onoremap <silent> <Plug>GitGutterTextObjectInnerPending :<C-U>call gitgutter#hunk#text_object(1)<CR>
|
onoremap <silent> <Plug>GitGutterTextObjectInnerPending :<C-U>call gitgutter#hunk#text_object(1)<CR>
|
||||||
|
@ -130,7 +139,8 @@ xnoremap <silent> <Plug>GitGutterTextObjectOuterVisual :<C-U>call gitgutter#hun
|
||||||
" `line` - refers to the line number where the change starts
|
" `line` - refers to the line number where the change starts
|
||||||
" `count` - refers to the number of lines the change covers
|
" `count` - refers to the number of lines the change covers
|
||||||
function! GitGutterGetHunks()
|
function! GitGutterGetHunks()
|
||||||
return gitgutter#utility#is_active() ? gitgutter#hunk#hunks() : []
|
let bufnr = bufnr('')
|
||||||
|
return gitgutter#utility#is_active(bufnr) ? gitgutter#hunk#hunks(bufnr) : []
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
" Returns an array that contains a summary of the hunk status for the current
|
" Returns an array that contains a summary of the hunk status for the current
|
||||||
|
@ -142,7 +152,7 @@ endfunction
|
||||||
|
|
||||||
" }}}
|
" }}}
|
||||||
|
|
||||||
command -bar GitGutterDebug call gitgutter#debug#debug()
|
command! -bar GitGutterDebug call gitgutter#debug#debug()
|
||||||
|
|
||||||
" Maps {{{
|
" Maps {{{
|
||||||
|
|
||||||
|
@ -169,7 +179,6 @@ if g:gitgutter_map_keys
|
||||||
endif
|
endif
|
||||||
if !hasmapto('<Plug>GitGutterUndoHunk') && maparg('<Leader>hu', 'n') ==# ''
|
if !hasmapto('<Plug>GitGutterUndoHunk') && maparg('<Leader>hu', 'n') ==# ''
|
||||||
nmap <Leader>hu <Plug>GitGutterUndoHunk
|
nmap <Leader>hu <Plug>GitGutterUndoHunk
|
||||||
nmap <Leader>hr <Plug>GitGutterUndoHunk:echomsg '<Leader>hr is deprecated. Use <Leader>hu'<CR>
|
|
||||||
endif
|
endif
|
||||||
if !hasmapto('<Plug>GitGutterPreviewHunk') && maparg('<Leader>hp', 'n') ==# ''
|
if !hasmapto('<Plug>GitGutterPreviewHunk') && maparg('<Leader>hp', 'n') ==# ''
|
||||||
nmap <Leader>hp <Plug>GitGutterPreviewHunk
|
nmap <Leader>hp <Plug>GitGutterPreviewHunk
|
||||||
|
@ -196,35 +205,26 @@ endif
|
||||||
augroup gitgutter
|
augroup gitgutter
|
||||||
autocmd!
|
autocmd!
|
||||||
|
|
||||||
if g:gitgutter_realtime
|
autocmd TabEnter * let t:gitgutter_didtabenter = 1
|
||||||
autocmd CursorHold,CursorHoldI * call gitgutter#process_buffer(bufnr(''), 1)
|
|
||||||
endif
|
|
||||||
|
|
||||||
if g:gitgutter_eager
|
|
||||||
autocmd BufWritePost,FileChangedShellPost,ShellCmdPost * call gitgutter#process_buffer(bufnr(''), 0)
|
|
||||||
|
|
||||||
autocmd BufEnter *
|
autocmd BufEnter *
|
||||||
\ if gettabvar(tabpagenr(), 'gitgutter_didtabenter') |
|
\ if exists('t:gitgutter_didtabenter') && t:gitgutter_didtabenter |
|
||||||
\ call settabvar(tabpagenr(), 'gitgutter_didtabenter', 0) |
|
\ let t:gitgutter_didtabenter = 0 |
|
||||||
\ call gitgutter#all() |
|
\ call gitgutter#all(!g:gitgutter_terminal_reports_focus) |
|
||||||
\ else |
|
\ else |
|
||||||
\ call gitgutter#process_buffer(bufnr(''), 0) |
|
\ call gitgutter#init_buffer(bufnr('')) |
|
||||||
|
\ call gitgutter#process_buffer(bufnr(''), !g:gitgutter_terminal_reports_focus) |
|
||||||
\ endif
|
\ endif
|
||||||
|
|
||||||
autocmd TabEnter * call settabvar(tabpagenr(), 'gitgutter_didtabenter', 1)
|
autocmd CursorHold,CursorHoldI * call gitgutter#process_buffer(bufnr(''), 0)
|
||||||
|
autocmd FileChangedShellPost,ShellCmdPost * call gitgutter#process_buffer(bufnr(''), 1)
|
||||||
|
|
||||||
" Ensure that all buffers are processed when opening vim with multiple files, e.g.:
|
" Ensure that all buffers are processed when opening vim with multiple files, e.g.:
|
||||||
"
|
"
|
||||||
" vim -o file1 file2
|
" vim -o file1 file2
|
||||||
autocmd VimEnter * if winnr() != winnr('$') | :GitGutterAll | endif
|
autocmd VimEnter * if winnr() != winnr('$') | call gitgutter#all(0) | endif
|
||||||
|
|
||||||
if !has('gui_win32')
|
autocmd FocusGained * call gitgutter#all(1)
|
||||||
autocmd FocusGained * call gitgutter#all()
|
|
||||||
endif
|
|
||||||
|
|
||||||
else
|
|
||||||
autocmd BufRead,BufWritePost,FileChangedShellPost * call gitgutter#process_buffer(bufnr(''), 0)
|
|
||||||
endif
|
|
||||||
|
|
||||||
autocmd ColorScheme * call gitgutter#highlight#define_sign_column_highlight() | call gitgutter#highlight#define_highlights()
|
autocmd ColorScheme * call gitgutter#highlight#define_sign_column_highlight() | call gitgutter#highlight#define_highlights()
|
||||||
|
|
||||||
|
|
8
sources_non_forked/vim-gitgutter/test/cp932.txt
Normal file
8
sources_non_forked/vim-gitgutter/test/cp932.txt
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
The quick brown fox jumps
|
||||||
|
over the lazy dog
|
||||||
|
|
||||||
|
いろはにほへとちりぬるを
|
||||||
|
わかよたれそつねならむ
|
||||||
|
うゐのおくやまけふこえて
|
||||||
|
あさきゆめみしゑひもせす
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
VIM="/Applications/MacVim.app/Contents/MacOS/Vim -v"
|
VIM="/Applications/MacVim.app/Contents/MacOS/Vim -v"
|
||||||
|
|
||||||
|
export VIM_GITGUTTER_TEST=1
|
||||||
|
|
||||||
$VIM -u NONE -U NONE -N \
|
$VIM -u NONE -U NONE -N \
|
||||||
--cmd 'set rtp+=../' \
|
--cmd 'set rtp+=../' \
|
||||||
--cmd 'let g:gitgutter_async=0' \
|
--cmd 'let g:gitgutter_async=0' \
|
||||||
|
|
|
@ -31,6 +31,10 @@ function s:git_diff_staged()
|
||||||
return split(system('git diff -U0 --staged fixture.txt'), '\n')
|
return split(system('git diff -U0 --staged fixture.txt'), '\n')
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
function s:trigger_gitgutter()
|
||||||
|
doautocmd CursorHold
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
"
|
"
|
||||||
" SetUp / TearDown
|
" SetUp / TearDown
|
||||||
|
@ -40,7 +44,8 @@ function SetUp()
|
||||||
call system("git init ".s:test_repo.
|
call system("git init ".s:test_repo.
|
||||||
\ " && cd ".s:test_repo.
|
\ " && cd ".s:test_repo.
|
||||||
\ " && cp ../fixture.txt .".
|
\ " && cp ../fixture.txt .".
|
||||||
\ " && git add . && git commit -m 'initial'")
|
\ " && git add . && git commit -m 'initial'".
|
||||||
|
\ " && git config diff.mnemonicPrefix false")
|
||||||
execute ':cd' s:test_repo
|
execute ':cd' s:test_repo
|
||||||
edit! fixture.txt
|
edit! fixture.txt
|
||||||
call gitgutter#sign#reset()
|
call gitgutter#sign#reset()
|
||||||
|
@ -64,7 +69,7 @@ endfunction
|
||||||
|
|
||||||
function Test_add_lines()
|
function Test_add_lines()
|
||||||
normal ggo*
|
normal ggo*
|
||||||
write
|
call s:trigger_gitgutter()
|
||||||
|
|
||||||
let expected = ["line=2 id=3000 name=GitGutterLineAdded"]
|
let expected = ["line=2 id=3000 name=GitGutterLineAdded"]
|
||||||
call assert_equal(expected, s:signs('fixture.txt'))
|
call assert_equal(expected, s:signs('fixture.txt'))
|
||||||
|
@ -76,7 +81,7 @@ function Test_add_lines_fish()
|
||||||
set shell=/usr/local/bin/fish
|
set shell=/usr/local/bin/fish
|
||||||
|
|
||||||
normal ggo*
|
normal ggo*
|
||||||
write
|
call s:trigger_gitgutter()
|
||||||
|
|
||||||
let expected = ["line=2 id=3000 name=GitGutterLineAdded"]
|
let expected = ["line=2 id=3000 name=GitGutterLineAdded"]
|
||||||
call assert_equal(expected, s:signs('fixture.txt'))
|
call assert_equal(expected, s:signs('fixture.txt'))
|
||||||
|
@ -87,7 +92,7 @@ endfunction
|
||||||
|
|
||||||
function Test_modify_lines()
|
function Test_modify_lines()
|
||||||
normal ggi*
|
normal ggi*
|
||||||
write
|
call s:trigger_gitgutter()
|
||||||
|
|
||||||
let expected = ["line=1 id=3000 name=GitGutterLineModified"]
|
let expected = ["line=1 id=3000 name=GitGutterLineModified"]
|
||||||
call assert_equal(expected, s:signs('fixture.txt'))
|
call assert_equal(expected, s:signs('fixture.txt'))
|
||||||
|
@ -96,7 +101,7 @@ endfunction
|
||||||
|
|
||||||
function Test_remove_lines()
|
function Test_remove_lines()
|
||||||
execute '5d'
|
execute '5d'
|
||||||
write
|
call s:trigger_gitgutter()
|
||||||
|
|
||||||
let expected = ["line=4 id=3000 name=GitGutterLineRemoved"]
|
let expected = ["line=4 id=3000 name=GitGutterLineRemoved"]
|
||||||
call assert_equal(expected, s:signs('fixture.txt'))
|
call assert_equal(expected, s:signs('fixture.txt'))
|
||||||
|
@ -105,7 +110,7 @@ endfunction
|
||||||
|
|
||||||
function Test_remove_first_lines()
|
function Test_remove_first_lines()
|
||||||
execute '1d'
|
execute '1d'
|
||||||
write
|
call s:trigger_gitgutter()
|
||||||
|
|
||||||
let expected = ["line=1 id=3000 name=GitGutterLineRemovedFirstLine"]
|
let expected = ["line=1 id=3000 name=GitGutterLineRemovedFirstLine"]
|
||||||
call assert_equal(expected, s:signs('fixture.txt'))
|
call assert_equal(expected, s:signs('fixture.txt'))
|
||||||
|
@ -115,7 +120,7 @@ endfunction
|
||||||
function Test_edit_file_with_same_name_as_a_branch()
|
function Test_edit_file_with_same_name_as_a_branch()
|
||||||
normal 5Gi*
|
normal 5Gi*
|
||||||
call system('git checkout -b fixture.txt')
|
call system('git checkout -b fixture.txt')
|
||||||
write
|
call s:trigger_gitgutter()
|
||||||
|
|
||||||
let expected = ["line=5 id=3000 name=GitGutterLineModified"]
|
let expected = ["line=5 id=3000 name=GitGutterLineModified"]
|
||||||
call assert_equal(expected, s:signs('fixture.txt'))
|
call assert_equal(expected, s:signs('fixture.txt'))
|
||||||
|
@ -127,7 +132,7 @@ function Test_file_added_to_git()
|
||||||
call system('touch '.tmpfile.' && git add '.tmpfile)
|
call system('touch '.tmpfile.' && git add '.tmpfile)
|
||||||
execute 'edit '.tmpfile
|
execute 'edit '.tmpfile
|
||||||
normal ihello
|
normal ihello
|
||||||
write
|
call s:trigger_gitgutter()
|
||||||
|
|
||||||
let expected = ["line=1 id=3000 name=GitGutterLineAdded"]
|
let expected = ["line=1 id=3000 name=GitGutterLineAdded"]
|
||||||
call assert_equal(expected, s:signs('fileAddedToGit.tmp'))
|
call assert_equal(expected, s:signs('fileAddedToGit.tmp'))
|
||||||
|
@ -138,7 +143,7 @@ function Test_filename_with_equals()
|
||||||
call system('touch =fixture=.txt && git add =fixture=.txt')
|
call system('touch =fixture=.txt && git add =fixture=.txt')
|
||||||
edit =fixture=.txt
|
edit =fixture=.txt
|
||||||
normal ggo*
|
normal ggo*
|
||||||
write
|
call s:trigger_gitgutter()
|
||||||
|
|
||||||
let expected = [
|
let expected = [
|
||||||
\ 'line=1 id=3000 name=GitGutterLineAdded',
|
\ 'line=1 id=3000 name=GitGutterLineAdded',
|
||||||
|
@ -152,7 +157,7 @@ function Test_filename_with_square_brackets()
|
||||||
call system('touch fix[tu]re.txt && git add fix[tu]re.txt')
|
call system('touch fix[tu]re.txt && git add fix[tu]re.txt')
|
||||||
edit fix[tu]re.txt
|
edit fix[tu]re.txt
|
||||||
normal ggo*
|
normal ggo*
|
||||||
write
|
call s:trigger_gitgutter()
|
||||||
|
|
||||||
let expected = [
|
let expected = [
|
||||||
\ 'line=1 id=3000 name=GitGutterLineAdded',
|
\ 'line=1 id=3000 name=GitGutterLineAdded',
|
||||||
|
@ -168,7 +173,7 @@ function Test_follow_symlink()
|
||||||
call system('ln -nfs fixture.txt '.tmp)
|
call system('ln -nfs fixture.txt '.tmp)
|
||||||
execute 'edit '.tmp
|
execute 'edit '.tmp
|
||||||
6d
|
6d
|
||||||
write
|
call s:trigger_gitgutter()
|
||||||
|
|
||||||
let expected = ['line=5 id=3000 name=GitGutterLineRemoved']
|
let expected = ['line=5 id=3000 name=GitGutterLineRemoved']
|
||||||
call assert_equal(expected, s:signs('symlink'))
|
call assert_equal(expected, s:signs('symlink'))
|
||||||
|
@ -183,7 +188,7 @@ function Test_keep_alt()
|
||||||
call assert_equal('', bufname('#'))
|
call assert_equal('', bufname('#'))
|
||||||
|
|
||||||
normal ggx
|
normal ggx
|
||||||
doautocmd CursorHold
|
call s:trigger_gitgutter()
|
||||||
|
|
||||||
call assert_equal('', bufname('#'))
|
call assert_equal('', bufname('#'))
|
||||||
endfunction
|
endfunction
|
||||||
|
@ -193,7 +198,7 @@ function Test_keep_modified()
|
||||||
normal 5Go*
|
normal 5Go*
|
||||||
call assert_equal(1, getbufvar('', '&modified'))
|
call assert_equal(1, getbufvar('', '&modified'))
|
||||||
|
|
||||||
doautocmd CursorHold
|
call s:trigger_gitgutter()
|
||||||
|
|
||||||
call assert_equal(1, getbufvar('', '&modified'))
|
call assert_equal(1, getbufvar('', '&modified'))
|
||||||
endfunction
|
endfunction
|
||||||
|
@ -204,7 +209,7 @@ function Test_keep_op_marks()
|
||||||
call assert_equal([0,6,1,0], getpos("'["))
|
call assert_equal([0,6,1,0], getpos("'["))
|
||||||
call assert_equal([0,6,2,0], getpos("']"))
|
call assert_equal([0,6,2,0], getpos("']"))
|
||||||
|
|
||||||
doautocmd CursorHold
|
call s:trigger_gitgutter()
|
||||||
|
|
||||||
call assert_equal([0,6,1,0], getpos("'["))
|
call assert_equal([0,6,1,0], getpos("'["))
|
||||||
call assert_equal([0,6,2,0], getpos("']"))
|
call assert_equal([0,6,2,0], getpos("']"))
|
||||||
|
@ -218,26 +223,15 @@ endfunction
|
||||||
|
|
||||||
function Test_orphaned_signs()
|
function Test_orphaned_signs()
|
||||||
execute "normal 5GoX\<CR>Y"
|
execute "normal 5GoX\<CR>Y"
|
||||||
write
|
call s:trigger_gitgutter()
|
||||||
6d
|
6d
|
||||||
write
|
call s:trigger_gitgutter()
|
||||||
|
|
||||||
let expected = ['line=6 id=3001 name=GitGutterLineAdded']
|
let expected = ['line=6 id=3001 name=GitGutterLineAdded']
|
||||||
call assert_equal(expected, s:signs('fixture.txt'))
|
call assert_equal(expected, s:signs('fixture.txt'))
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
function Test_sign_column_always()
|
|
||||||
let g:gitgutter_sign_column_always=1
|
|
||||||
write
|
|
||||||
|
|
||||||
let expected = ['line=9999 id=2999 name=GitGutterDummy']
|
|
||||||
call assert_equal(expected, s:signs('fixture.txt'))
|
|
||||||
|
|
||||||
let g:gitgutter_sign_column_always=0
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
|
|
||||||
function Test_untracked_file_outside_repo()
|
function Test_untracked_file_outside_repo()
|
||||||
let tmp = tempname()
|
let tmp = tempname()
|
||||||
call system('touch '.tmp)
|
call system('touch '.tmp)
|
||||||
|
@ -252,7 +246,7 @@ function Test_untracked_file_within_repo()
|
||||||
call system('touch '.tmp)
|
call system('touch '.tmp)
|
||||||
execute 'edit '.tmp
|
execute 'edit '.tmp
|
||||||
normal ggo*
|
normal ggo*
|
||||||
doautocmd CursorHold
|
call s:trigger_gitgutter()
|
||||||
|
|
||||||
call assert_equal([], s:signs(tmp))
|
call assert_equal([], s:signs(tmp))
|
||||||
|
|
||||||
|
@ -265,7 +259,7 @@ function Test_untracked_file_square_brackets_within_repo()
|
||||||
call system('touch '.tmp)
|
call system('touch '.tmp)
|
||||||
execute 'edit '.tmp
|
execute 'edit '.tmp
|
||||||
normal ggo*
|
normal ggo*
|
||||||
doautocmd CursorHold
|
call s:trigger_gitgutter()
|
||||||
|
|
||||||
call assert_equal([], s:signs(tmp))
|
call assert_equal([], s:signs(tmp))
|
||||||
|
|
||||||
|
@ -301,8 +295,19 @@ function Test_hunk_stage()
|
||||||
|
|
||||||
call assert_equal([], s:signs('fixture.txt'))
|
call assert_equal([], s:signs('fixture.txt'))
|
||||||
|
|
||||||
call assert_equal([], s:git_diff())
|
" Buffer is unsaved
|
||||||
|
let expected = [
|
||||||
|
\ 'diff --git a/fixture.txt b/fixture.txt',
|
||||||
|
\ 'index ae8e546..f5c6aff 100644',
|
||||||
|
\ '--- a/fixture.txt',
|
||||||
|
\ '+++ b/fixture.txt',
|
||||||
|
\ '@@ -5 +5 @@ d',
|
||||||
|
\ '-*e',
|
||||||
|
\ '+e'
|
||||||
|
\ ]
|
||||||
|
call assert_equal(expected, s:git_diff())
|
||||||
|
|
||||||
|
" Index has been updated
|
||||||
let expected = [
|
let expected = [
|
||||||
\ 'diff --git a/fixture.txt b/fixture.txt',
|
\ 'diff --git a/fixture.txt b/fixture.txt',
|
||||||
\ 'index f5c6aff..ae8e546 100644',
|
\ 'index f5c6aff..ae8e546 100644',
|
||||||
|
@ -313,6 +318,11 @@ function Test_hunk_stage()
|
||||||
\ '+*e'
|
\ '+*e'
|
||||||
\ ]
|
\ ]
|
||||||
call assert_equal(expected, s:git_diff_staged())
|
call assert_equal(expected, s:git_diff_staged())
|
||||||
|
|
||||||
|
" Save the buffer
|
||||||
|
write
|
||||||
|
|
||||||
|
call assert_equal([], s:git_diff())
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
@ -329,6 +339,31 @@ function Test_hunk_stage_nearby_hunk()
|
||||||
\ ]
|
\ ]
|
||||||
call assert_equal(expected, s:signs('fixture.txt'))
|
call assert_equal(expected, s:signs('fixture.txt'))
|
||||||
|
|
||||||
|
" Buffer is unsaved
|
||||||
|
let expected = [
|
||||||
|
\ 'diff --git a/fixture.txt b/fixture.txt',
|
||||||
|
\ 'index 53b13df..f5c6aff 100644',
|
||||||
|
\ '--- a/fixture.txt',
|
||||||
|
\ '+++ b/fixture.txt',
|
||||||
|
\ '@@ -3,0 +4 @@ c',
|
||||||
|
\ '+d',
|
||||||
|
\ ]
|
||||||
|
call assert_equal(expected, s:git_diff())
|
||||||
|
|
||||||
|
" Index has been updated
|
||||||
|
let expected = [
|
||||||
|
\ 'diff --git a/fixture.txt b/fixture.txt',
|
||||||
|
\ 'index f5c6aff..53b13df 100644',
|
||||||
|
\ '--- a/fixture.txt',
|
||||||
|
\ '+++ b/fixture.txt',
|
||||||
|
\ '@@ -4 +3,0 @@ c',
|
||||||
|
\ '-d',
|
||||||
|
\ ]
|
||||||
|
call assert_equal(expected, s:git_diff_staged())
|
||||||
|
|
||||||
|
" Save the buffer
|
||||||
|
write
|
||||||
|
|
||||||
let expected = [
|
let expected = [
|
||||||
\ 'diff --git a/fixture.txt b/fixture.txt',
|
\ 'diff --git a/fixture.txt b/fixture.txt',
|
||||||
\ 'index 53b13df..8fdfda7 100644',
|
\ 'index 53b13df..8fdfda7 100644',
|
||||||
|
@ -340,16 +375,6 @@ function Test_hunk_stage_nearby_hunk()
|
||||||
\ '+z',
|
\ '+z',
|
||||||
\ ]
|
\ ]
|
||||||
call assert_equal(expected, s:git_diff())
|
call assert_equal(expected, s:git_diff())
|
||||||
|
|
||||||
let expected = [
|
|
||||||
\ 'diff --git a/fixture.txt b/fixture.txt',
|
|
||||||
\ 'index f5c6aff..53b13df 100644',
|
|
||||||
\ '--- a/fixture.txt',
|
|
||||||
\ '+++ b/fixture.txt',
|
|
||||||
\ '@@ -4 +3,0 @@ c',
|
|
||||||
\ '-d',
|
|
||||||
\ ]
|
|
||||||
call assert_equal(expected, s:git_diff_staged())
|
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
@ -359,7 +384,6 @@ function Test_hunk_undo()
|
||||||
|
|
||||||
normal 5Gi*
|
normal 5Gi*
|
||||||
GitGutterUndoHunk
|
GitGutterUndoHunk
|
||||||
write " write file so we can verify git diff (--staged)
|
|
||||||
|
|
||||||
call assert_equal('foo', &shell)
|
call assert_equal('foo', &shell)
|
||||||
let &shell = _shell
|
let &shell = _shell
|
||||||
|
@ -374,8 +398,9 @@ function Test_undo_nearby_hunk()
|
||||||
execute "normal! 2Gox\<CR>y\<CR>z"
|
execute "normal! 2Gox\<CR>y\<CR>z"
|
||||||
normal 2jdd
|
normal 2jdd
|
||||||
normal k
|
normal k
|
||||||
|
call s:trigger_gitgutter()
|
||||||
GitGutterUndoHunk
|
GitGutterUndoHunk
|
||||||
write " write file so we can verify git diff (--staged)
|
call s:trigger_gitgutter()
|
||||||
|
|
||||||
let expected = [
|
let expected = [
|
||||||
\ 'line=3 id=3000 name=GitGutterLineAdded',
|
\ 'line=3 id=3000 name=GitGutterLineAdded',
|
||||||
|
@ -384,6 +409,13 @@ function Test_undo_nearby_hunk()
|
||||||
\ ]
|
\ ]
|
||||||
call assert_equal(expected, s:signs('fixture.txt'))
|
call assert_equal(expected, s:signs('fixture.txt'))
|
||||||
|
|
||||||
|
call assert_equal([], s:git_diff())
|
||||||
|
|
||||||
|
call assert_equal([], s:git_diff_staged())
|
||||||
|
|
||||||
|
" Save the buffer
|
||||||
|
write
|
||||||
|
|
||||||
let expected = [
|
let expected = [
|
||||||
\ 'diff --git a/fixture.txt b/fixture.txt',
|
\ 'diff --git a/fixture.txt b/fixture.txt',
|
||||||
\ 'index f5c6aff..3fbde56 100644',
|
\ 'index f5c6aff..3fbde56 100644',
|
||||||
|
@ -396,5 +428,148 @@ function Test_undo_nearby_hunk()
|
||||||
\ ]
|
\ ]
|
||||||
call assert_equal(expected, s:git_diff())
|
call assert_equal(expected, s:git_diff())
|
||||||
|
|
||||||
call assert_equal([], s:git_diff_staged())
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
function Test_write_option()
|
||||||
|
set nowrite
|
||||||
|
|
||||||
|
normal ggo*
|
||||||
|
call s:trigger_gitgutter()
|
||||||
|
|
||||||
|
let expected = ["line=2 id=3000 name=GitGutterLineAdded"]
|
||||||
|
call assert_equal(expected, s:signs('fixture.txt'))
|
||||||
|
|
||||||
|
set write
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
function Test_inner_text_object()
|
||||||
|
execute "normal! 2Gox\<CR>y\<CR>z\<CR>\<CR>"
|
||||||
|
call s:trigger_gitgutter()
|
||||||
|
normal dic
|
||||||
|
call s:trigger_gitgutter()
|
||||||
|
|
||||||
|
call assert_equal([], s:signs('fixture.txt'))
|
||||||
|
call assert_equal(readfile('fixture.txt'), getline(1,'$'))
|
||||||
|
|
||||||
|
" Excludes trailing lines
|
||||||
|
normal 9Gi*
|
||||||
|
normal 10Gi*
|
||||||
|
call s:trigger_gitgutter()
|
||||||
|
execute "normal vic\<Esc>"
|
||||||
|
call assert_equal([9, 10], [line("'<"), line("'>")])
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
function Test_around_text_object()
|
||||||
|
execute "normal! 2Gox\<CR>y\<CR>z\<CR>\<CR>"
|
||||||
|
call s:trigger_gitgutter()
|
||||||
|
normal dac
|
||||||
|
call s:trigger_gitgutter()
|
||||||
|
|
||||||
|
call assert_equal([], s:signs('fixture.txt'))
|
||||||
|
call assert_equal(readfile('fixture.txt'), getline(1,'$'))
|
||||||
|
|
||||||
|
" Includes trailing lines
|
||||||
|
normal 9Gi*
|
||||||
|
normal 10Gi*
|
||||||
|
call s:trigger_gitgutter()
|
||||||
|
execute "normal vac\<Esc>"
|
||||||
|
call assert_equal([9, 11], [line("'<"), line("'>")])
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
function Test_user_autocmd()
|
||||||
|
autocmd User GitGutter let s:autocmd_user = g:gitgutter_hook_context.bufnr
|
||||||
|
|
||||||
|
" Verify not fired when nothing changed.
|
||||||
|
let s:autocmd_user = 0
|
||||||
|
call s:trigger_gitgutter()
|
||||||
|
call assert_equal(0, s:autocmd_user)
|
||||||
|
|
||||||
|
" Verify fired when there was a change.
|
||||||
|
normal ggo*
|
||||||
|
let bufnr = bufnr('')
|
||||||
|
call s:trigger_gitgutter()
|
||||||
|
call assert_equal(bufnr, s:autocmd_user)
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
function Test_fix_file_references()
|
||||||
|
" No special characters
|
||||||
|
let hunk_diff = join([
|
||||||
|
\ 'diff --git a/fixture.txt b/fixture.txt',
|
||||||
|
\ 'index f5c6aff..3fbde56 100644',
|
||||||
|
\ '--- a/fixture.txt',
|
||||||
|
\ '+++ b/fixture.txt',
|
||||||
|
\ '@@ -2,0 +3,1 @@ b',
|
||||||
|
\ '+x'
|
||||||
|
\ ], "\n")."\n"
|
||||||
|
let filepath = 'blah.txt'
|
||||||
|
|
||||||
|
let expected = join([
|
||||||
|
\ 'diff --git a/blah.txt b/blah.txt',
|
||||||
|
\ 'index f5c6aff..3fbde56 100644',
|
||||||
|
\ '--- a/blah.txt',
|
||||||
|
\ '+++ b/blah.txt',
|
||||||
|
\ '@@ -2,0 +3,1 @@ b',
|
||||||
|
\ '+x'
|
||||||
|
\ ], "\n")."\n"
|
||||||
|
|
||||||
|
call assert_equal(expected, gitgutter#hunk#fix_file_references(filepath, hunk_diff))
|
||||||
|
|
||||||
|
" diff.mnemonicPrefix; spaces in filename
|
||||||
|
let hunk_diff = join([
|
||||||
|
\ 'diff --git i/x/cat dog w/x/cat dog',
|
||||||
|
\ 'index f5c6aff..3fbde56 100644',
|
||||||
|
\ '--- i/x/cat dog',
|
||||||
|
\ '+++ w/x/cat dog',
|
||||||
|
\ '@@ -2,0 +3,1 @@ b',
|
||||||
|
\ '+x'
|
||||||
|
\ ], "\n")."\n"
|
||||||
|
let filepath = 'blah.txt'
|
||||||
|
|
||||||
|
let expected = join([
|
||||||
|
\ 'diff --git i/blah.txt w/blah.txt',
|
||||||
|
\ 'index f5c6aff..3fbde56 100644',
|
||||||
|
\ '--- i/blah.txt',
|
||||||
|
\ '+++ w/blah.txt',
|
||||||
|
\ '@@ -2,0 +3,1 @@ b',
|
||||||
|
\ '+x'
|
||||||
|
\ ], "\n")."\n"
|
||||||
|
|
||||||
|
call assert_equal(expected, gitgutter#hunk#fix_file_references(filepath, hunk_diff))
|
||||||
|
|
||||||
|
" Backslashes in filename; quotation marks
|
||||||
|
let hunk_diff = join([
|
||||||
|
\ 'diff --git "a/C:\\Users\\FOO~1.PAR\\AppData\\Local\\Temp\\nvimJcmSv9\\11.1.vim" "b/C:\\Users\\FOO~1.PAR\\AppData\\Local\\Temp\\nvimJcmSv9\\12.1.vim"',
|
||||||
|
\ 'index f42aeb0..4930403 100644',
|
||||||
|
\ '--- "a/C:\\Users\\FOO~1.PAR\\AppData\\Local\\Temp\\nvimJcmSv9\\11.1.vim"',
|
||||||
|
\ '+++ "b/C:\\Users\\FOO~1.PAR\\AppData\\Local\\Temp\\nvimJcmSv9\\12.1.vim"',
|
||||||
|
\ '@@ -172,0 +173 @@ stuff',
|
||||||
|
\ '+x'
|
||||||
|
\ ], "\n")."\n"
|
||||||
|
let filepath = 'init.vim'
|
||||||
|
|
||||||
|
let expected = join([
|
||||||
|
\ 'diff --git "a/init.vim" "b/init.vim"',
|
||||||
|
\ 'index f42aeb0..4930403 100644',
|
||||||
|
\ '--- "a/init.vim"',
|
||||||
|
\ '+++ "b/init.vim"',
|
||||||
|
\ '@@ -172,0 +173 @@ stuff',
|
||||||
|
\ '+x'
|
||||||
|
\ ], "\n")."\n"
|
||||||
|
|
||||||
|
call assert_equal(expected, gitgutter#hunk#fix_file_references(filepath, hunk_diff))
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
function Test_encoding()
|
||||||
|
call system('cp ../cp932.txt . && git add cp932.txt')
|
||||||
|
edit ++enc=cp932 cp932.txt
|
||||||
|
|
||||||
|
call s:trigger_gitgutter()
|
||||||
|
|
||||||
|
call assert_equal([], s:signs('cp932.txt'))
|
||||||
endfunction
|
endfunction
|
||||||
|
|
27
sources_non_forked/vim-gitgutter/unplace.vim
Normal file
27
sources_non_forked/vim-gitgutter/unplace.vim
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
" Measure how long it takes to unplace signs.
|
||||||
|
"
|
||||||
|
" Source this file with `:source %` or `vim -S unplace.vim`
|
||||||
|
|
||||||
|
|
||||||
|
let num = 500
|
||||||
|
sign define Foo text=*
|
||||||
|
|
||||||
|
new
|
||||||
|
|
||||||
|
call append(0, range(1, num))
|
||||||
|
|
||||||
|
for i in range(1, num)
|
||||||
|
execute "sign place ".i." line=".i." name=Foo buffer=".bufnr('')
|
||||||
|
endfor
|
||||||
|
|
||||||
|
let start = reltime()
|
||||||
|
for i in range(1, num)
|
||||||
|
execute "sign unplace ".i
|
||||||
|
endfor
|
||||||
|
let elapsed = reltime(start)
|
||||||
|
|
||||||
|
bdelete!
|
||||||
|
|
||||||
|
echom split(reltimestr(elapsed))[0]."s to remove ".num." signs"
|
||||||
|
echom string(reltimefloat(elapsed) * 1000 / num).' ms/sign'
|
||||||
|
echom string(float2nr(num / reltimefloat(elapsed))).' sign/s'
|
12
sources_non_forked/vim-go/.codecov.yml
Normal file
12
sources_non_forked/vim-go/.codecov.yml
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
---
|
||||||
|
coverage:
|
||||||
|
status:
|
||||||
|
project:
|
||||||
|
default:
|
||||||
|
target: auto
|
||||||
|
threshold: 1
|
||||||
|
base: auto
|
||||||
|
comment: false
|
||||||
|
ignore:
|
||||||
|
- "!autoload/go/*.vim$"
|
||||||
|
- "autoload/go/*_test.vim$"
|
|
@ -1,5 +1,15 @@
|
||||||
## unplanned
|
## unplanned
|
||||||
|
|
||||||
|
## 1.17 - (March 27, 2018)
|
||||||
|
|
||||||
|
FEATURES:
|
||||||
|
|
||||||
|
* **Debugger support!** Add integrated support for the
|
||||||
|
[`delve`](https://github.com/derekparker/delve) debugger. Use
|
||||||
|
`:GoInstallBinaries` to install `dlv`, and see `:help go-debug` to get
|
||||||
|
started.
|
||||||
|
[[GH-1390]](https://github.com/fatih/vim-go/pull/1390)
|
||||||
|
|
||||||
IMPROVEMENTS:
|
IMPROVEMENTS:
|
||||||
|
|
||||||
* Add descriptions to neosnippet abbrevations.
|
* Add descriptions to neosnippet abbrevations.
|
||||||
|
@ -8,6 +18,16 @@ IMPROVEMENTS:
|
||||||
`gometalinter` is run automatically when saving a buffer. Whether the
|
`gometalinter` is run automatically when saving a buffer. Whether the
|
||||||
location list or quickfix list is used can be customized in the usual ways.
|
location list or quickfix list is used can be customized in the usual ways.
|
||||||
[[GH-1652]](https://github.com/fatih/vim-go/pull/1652)
|
[[GH-1652]](https://github.com/fatih/vim-go/pull/1652)
|
||||||
|
* Redraw the screen before executing blocking calls to gocode.
|
||||||
|
[[GH-1671]](https://github.com/fatih/vim-go/pull/1671)
|
||||||
|
* Add `fe` -> `fmt.Errorf()` snippet for NeoSnippet and UltiSnippets.
|
||||||
|
[[GH-1677]](https://github.com/fatih/vim-go/pull/1677)
|
||||||
|
* Use the async api when calling guru from neovim.
|
||||||
|
[[GH-1678]](https://github.com/fatih/vim-go/pull/1678)
|
||||||
|
* Use the async api when calling gocode to get type info.
|
||||||
|
[[GH-1697]](https://github.com/fatih/vim-go/pull/1697)
|
||||||
|
* Cache import path lookups to improve responsiveness.
|
||||||
|
[[GH-1713]](https://github.com/fatih/vim-go/pull/1713)
|
||||||
|
|
||||||
BUG FIXES:
|
BUG FIXES:
|
||||||
|
|
||||||
|
@ -47,7 +67,17 @@ BUG FIXES:
|
||||||
* Show the file location of test errors when the message is empty or begins
|
* Show the file location of test errors when the message is empty or begins
|
||||||
with a newline.
|
with a newline.
|
||||||
[[GH-1664]](https://github.com/fatih/vim-go/pull/1664)
|
[[GH-1664]](https://github.com/fatih/vim-go/pull/1664)
|
||||||
|
* Fix minisnip on Windows.
|
||||||
|
[[GH-1698]](https://github.com/fatih/vim-go/pull/1698)
|
||||||
|
* Keep alternate filename when loading an autocreate template.
|
||||||
|
[[GH-1675]](https://github.com/fatih/vim-go/pull/1675)
|
||||||
|
* Parse the column number in errors correctly in vim8 and neovim.
|
||||||
|
[[GH-1716]](https://github.com/fatih/vim-go/pull/1716)
|
||||||
|
* Fix race conditions in the terminal handling for neovim.
|
||||||
|
[[GH-1721]](https://github.com/fatih/vim-go/pull/1721)
|
||||||
|
* Put the user back in the original window regardless of the value of
|
||||||
|
`splitright` after starting a neovim terminal window.
|
||||||
|
[[GH-1725]](https://github.com/fatih/vim-go/pull/1725)
|
||||||
|
|
||||||
BACKWARDS INCOMPATIBILITIES:
|
BACKWARDS INCOMPATIBILITIES:
|
||||||
|
|
||||||
|
@ -67,6 +97,9 @@ BACKWARDS INCOMPATIBILITIES:
|
||||||
[[GH-1557]](https://github.com/fatih/vim-go/pull/1557)
|
[[GH-1557]](https://github.com/fatih/vim-go/pull/1557)
|
||||||
* Rename g`g:go_metalinter_excludes` to `g:go_metalinter_disabled`.
|
* Rename g`g:go_metalinter_excludes` to `g:go_metalinter_disabled`.
|
||||||
[[GH-1648]](https://github.com/fatih/vim-go/pull/1648)
|
[[GH-1648]](https://github.com/fatih/vim-go/pull/1648)
|
||||||
|
* `:GoBuild` doesn't append the `-i` flag anymore due the recent Go 1.10
|
||||||
|
changes that introduced a build cache.
|
||||||
|
[[GH-1701]](https://github.com/fatih/vim-go/pull/1701)
|
||||||
|
|
||||||
## 1.16 - (December 29, 2017)
|
## 1.16 - (December 29, 2017)
|
||||||
|
|
||||||
|
|
|
@ -9,16 +9,16 @@
|
||||||
This plugin adds Go language support for Vim, with the following main features:
|
This plugin adds Go language support for Vim, with the following main features:
|
||||||
|
|
||||||
* Compile your package with `:GoBuild`, install it with `:GoInstall` or test it
|
* Compile your package with `:GoBuild`, install it with `:GoInstall` or test it
|
||||||
with `:GoTest`. Run a single tests with `:GoTestFunc`).
|
with `:GoTest`. Run a single test with `:GoTestFunc`).
|
||||||
* Quickly execute your current file(s) with `:GoRun`.
|
* Quickly execute your current file(s) with `:GoRun`.
|
||||||
* Improved syntax highlighting and folding.
|
* Improved syntax highlighting and folding.
|
||||||
|
* Debug programs with integrated `delve` support with `:GoDebugStart`.
|
||||||
* Completion support via `gocode`.
|
* Completion support via `gocode`.
|
||||||
* `gofmt` or `goimports` on save keeps the cursor position and undo history.
|
* `gofmt` or `goimports` on save keeps the cursor position and undo history.
|
||||||
* Go to symbol/declaration with `:GoDef`.
|
* Go to symbol/declaration with `:GoDef`.
|
||||||
* Look up documentation with `:GoDoc` or `:GoDocBrowser`.
|
* Look up documentation with `:GoDoc` or `:GoDocBrowser`.
|
||||||
* Easily import packages via `:GoImport`, remove them via `:GoDrop`.
|
* Easily import packages via `:GoImport`, remove them via `:GoDrop`.
|
||||||
* Automatic `GOPATH` detection which works with `gb` and `godep`. Change or
|
* Precise type-safe renaming of identifiers with `:GoRename`.
|
||||||
display `GOPATH` with `:GoPath`.
|
|
||||||
* See which code is covered by tests with `:GoCoverage`.
|
* See which code is covered by tests with `:GoCoverage`.
|
||||||
* Add or remove tags on struct fields with `:GoAddTags` and `:GoRemoveTags`.
|
* Add or remove tags on struct fields with `:GoAddTags` and `:GoRemoveTags`.
|
||||||
* Call `gometalinter` with `:GoMetaLinter` to invoke all possible linters
|
* Call `gometalinter` with `:GoMetaLinter` to invoke all possible linters
|
||||||
|
@ -28,7 +28,6 @@ This plugin adds Go language support for Vim, with the following main features:
|
||||||
errors, or make sure errors are checked with `:GoErrCheck`.
|
errors, or make sure errors are checked with `:GoErrCheck`.
|
||||||
* Advanced source analysis tools utilizing `guru`, such as `:GoImplements`,
|
* Advanced source analysis tools utilizing `guru`, such as `:GoImplements`,
|
||||||
`:GoCallees`, and `:GoReferrers`.
|
`:GoCallees`, and `:GoReferrers`.
|
||||||
* Precise type-safe renaming of identifiers with `:GoRename`.
|
|
||||||
* ... and many more! Please see [doc/vim-go.txt](doc/vim-go.txt) for more
|
* ... and many more! Please see [doc/vim-go.txt](doc/vim-go.txt) for more
|
||||||
information.
|
information.
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@ function! go#cmd#Build(bang, ...) abort
|
||||||
let args =
|
let args =
|
||||||
\ ["build"] +
|
\ ["build"] +
|
||||||
\ map(copy(a:000), "expand(v:val)") +
|
\ map(copy(a:000), "expand(v:val)") +
|
||||||
\ ["-i", ".", "errors"]
|
\ [".", "errors"]
|
||||||
|
|
||||||
" Vim async.
|
" Vim async.
|
||||||
if go#util#has_job()
|
if go#util#has_job()
|
||||||
|
|
30
sources_non_forked/vim-go/autoload/go/cmd_test.vim
Normal file
30
sources_non_forked/vim-go/autoload/go/cmd_test.vim
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
func! Test_GoBuildErrors()
|
||||||
|
try
|
||||||
|
let l:filename = 'cmd/bad.go'
|
||||||
|
let l:tmp = gotest#load_fixture(l:filename)
|
||||||
|
exe 'cd ' . l:tmp . '/src/cmd'
|
||||||
|
|
||||||
|
" set the compiler type so that the errorformat option will be set
|
||||||
|
" correctly.
|
||||||
|
compiler go
|
||||||
|
|
||||||
|
let expected = [{'lnum': 4, 'bufnr': bufnr('%'), 'col': 2, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'undefined: notafunc'}]
|
||||||
|
" clear the quickfix lists
|
||||||
|
call setqflist([], 'r')
|
||||||
|
|
||||||
|
call go#cmd#Build(1)
|
||||||
|
|
||||||
|
let actual = getqflist()
|
||||||
|
let start = reltime()
|
||||||
|
while len(actual) == 0 && reltimefloat(reltime(start)) < 10
|
||||||
|
sleep 100m
|
||||||
|
let actual = getqflist()
|
||||||
|
endwhile
|
||||||
|
|
||||||
|
call gotest#assert_quickfix(actual, l:expected)
|
||||||
|
finally
|
||||||
|
call delete(l:tmp, 'rf')
|
||||||
|
endtry
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
" vim: sw=2 ts=2 et
|
|
@ -1,58 +1,51 @@
|
||||||
let s:sock_type = (has('win32') || has('win64')) ? 'tcp' : 'unix'
|
let s:sock_type = (has('win32') || has('win64')) ? 'tcp' : 'unix'
|
||||||
|
|
||||||
function! s:gocodeCurrentBuffer() abort
|
function! s:gocodeCommand(cmd, args) abort
|
||||||
let file = tempname()
|
|
||||||
call writefile(go#util#GetLines(), file)
|
|
||||||
return file
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function! s:gocodeCommand(cmd, preargs, args) abort
|
|
||||||
for i in range(0, len(a:args) - 1)
|
|
||||||
let a:args[i] = go#util#Shellescape(a:args[i])
|
|
||||||
endfor
|
|
||||||
for i in range(0, len(a:preargs) - 1)
|
|
||||||
let a:preargs[i] = go#util#Shellescape(a:preargs[i])
|
|
||||||
endfor
|
|
||||||
|
|
||||||
let bin_path = go#path#CheckBinPath("gocode")
|
let bin_path = go#path#CheckBinPath("gocode")
|
||||||
if empty(bin_path)
|
if empty(bin_path)
|
||||||
return
|
return []
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
let socket_type = get(g:, 'go_gocode_socket_type', s:sock_type)
|
||||||
|
|
||||||
|
let cmd = [bin_path]
|
||||||
|
let cmd = extend(cmd, ['-sock', socket_type])
|
||||||
|
let cmd = extend(cmd, ['-f', 'vim'])
|
||||||
|
let cmd = extend(cmd, [a:cmd])
|
||||||
|
let cmd = extend(cmd, a:args)
|
||||||
|
|
||||||
|
return cmd
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! s:sync_gocode(cmd, args, input) abort
|
||||||
" We might hit cache problems, as gocode doesn't handle different GOPATHs
|
" We might hit cache problems, as gocode doesn't handle different GOPATHs
|
||||||
" well. See: https://github.com/nsf/gocode/issues/239
|
" well. See: https://github.com/nsf/gocode/issues/239
|
||||||
let old_goroot = $GOROOT
|
let old_goroot = $GOROOT
|
||||||
let $GOROOT = go#util#env("goroot")
|
let $GOROOT = go#util#env("goroot")
|
||||||
|
|
||||||
try
|
try
|
||||||
let socket_type = get(g:, 'go_gocode_socket_type', s:sock_type)
|
let cmd = s:gocodeCommand(a:cmd, a:args)
|
||||||
let cmd = printf('%s -sock %s %s %s %s',
|
" gocode can sometimes be slow, so redraw now to avoid waiting for gocode
|
||||||
\ go#util#Shellescape(bin_path),
|
" to return before redrawing automatically.
|
||||||
\ socket_type,
|
redraw
|
||||||
\ join(a:preargs),
|
|
||||||
\ go#util#Shellescape(a:cmd),
|
|
||||||
\ join(a:args)
|
|
||||||
\ )
|
|
||||||
|
|
||||||
let result = go#util#System(cmd)
|
let [l:result, l:err] = go#util#Exec(cmd, a:input)
|
||||||
finally
|
finally
|
||||||
let $GOROOT = old_goroot
|
let $GOROOT = old_goroot
|
||||||
endtry
|
endtry
|
||||||
|
|
||||||
if go#util#ShellError() != 0
|
if l:err != 0
|
||||||
return "[\"0\", []]"
|
return "[0, []]"
|
||||||
else
|
endif
|
||||||
|
|
||||||
if &encoding != 'utf-8'
|
if &encoding != 'utf-8'
|
||||||
let result = iconv(result, 'utf-8', &encoding)
|
let l:result = iconv(l:result, 'utf-8', &encoding)
|
||||||
endif
|
|
||||||
return result
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
return l:result
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! s:gocodeCurrentBufferOpt(filename) abort
|
" TODO(bc): reset when gocode isn't running
|
||||||
return '-in=' . a:filename
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
let s:optionsEnabled = 0
|
let s:optionsEnabled = 0
|
||||||
function! s:gocodeEnableOptions() abort
|
function! s:gocodeEnableOptions() abort
|
||||||
if s:optionsEnabled
|
if s:optionsEnabled
|
||||||
|
@ -78,62 +71,161 @@ endfunction
|
||||||
function! s:gocodeAutocomplete() abort
|
function! s:gocodeAutocomplete() abort
|
||||||
call s:gocodeEnableOptions()
|
call s:gocodeEnableOptions()
|
||||||
|
|
||||||
let filename = s:gocodeCurrentBuffer()
|
" use the offset as is, because the cursor position is the position for
|
||||||
let result = s:gocodeCommand('autocomplete',
|
" which autocomplete candidates are needed.
|
||||||
\ [s:gocodeCurrentBufferOpt(filename), '-f=vim'],
|
return s:sync_gocode('autocomplete',
|
||||||
\ [expand('%:p'), go#util#OffsetCursor()])
|
\ [expand('%:p'), go#util#OffsetCursor()],
|
||||||
call delete(filename)
|
\ go#util#GetLines())
|
||||||
return result
|
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
" go#complete#GoInfo returns the description of the identifier under the
|
||||||
|
" cursor.
|
||||||
function! go#complete#GetInfo() abort
|
function! go#complete#GetInfo() abort
|
||||||
let offset = go#util#OffsetCursor()+1
|
return s:sync_info(0)
|
||||||
let filename = s:gocodeCurrentBuffer()
|
|
||||||
let result = s:gocodeCommand('autocomplete',
|
|
||||||
\ [s:gocodeCurrentBufferOpt(filename), '-f=godit'],
|
|
||||||
\ [expand('%:p'), offset])
|
|
||||||
call delete(filename)
|
|
||||||
|
|
||||||
" first line is: Charcount,,NumberOfCandidates, i.e: 8,,1
|
|
||||||
" following lines are candiates, i.e: func foo(name string),,foo(
|
|
||||||
let out = split(result, '\n')
|
|
||||||
|
|
||||||
" no candidates are found
|
|
||||||
if len(out) == 1
|
|
||||||
return ""
|
|
||||||
endif
|
|
||||||
|
|
||||||
" only one candidate is found
|
|
||||||
if len(out) == 2
|
|
||||||
return split(out[1], ',,')[0]
|
|
||||||
endif
|
|
||||||
|
|
||||||
" to many candidates are available, pick one that maches the word under the
|
|
||||||
" cursor
|
|
||||||
let infos = []
|
|
||||||
for info in out[1:]
|
|
||||||
call add(infos, split(info, ',,')[0])
|
|
||||||
endfor
|
|
||||||
|
|
||||||
let wordMatch = '\<' . expand("<cword>") . '\>'
|
|
||||||
" escape single quotes in wordMatch before passing it to filter
|
|
||||||
let wordMatch = substitute(wordMatch, "'", "''", "g")
|
|
||||||
let filtered = filter(infos, "v:val =~ '".wordMatch."'")
|
|
||||||
|
|
||||||
if len(filtered) == 1
|
|
||||||
return filtered[0]
|
|
||||||
endif
|
|
||||||
|
|
||||||
return ""
|
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! go#complete#Info(auto) abort
|
function! go#complete#Info(auto) abort
|
||||||
|
if go#util#has_job()
|
||||||
|
return s:async_info(a:auto)
|
||||||
|
else
|
||||||
|
return s:sync_info(a:auto)
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! s:async_info(auto)
|
||||||
|
if exists("s:async_info_job")
|
||||||
|
call job_stop(s:async_info_job)
|
||||||
|
unlet s:async_info_job
|
||||||
|
endif
|
||||||
|
|
||||||
|
let state = {
|
||||||
|
\ 'exited': 0,
|
||||||
|
\ 'exit_status': 0,
|
||||||
|
\ 'closed': 0,
|
||||||
|
\ 'messages': [],
|
||||||
|
\ 'auto': a:auto
|
||||||
|
\ }
|
||||||
|
|
||||||
|
function! s:callback(chan, msg) dict
|
||||||
|
let l:msg = a:msg
|
||||||
|
if &encoding != 'utf-8'
|
||||||
|
let l:msg = iconv(l:msg, 'utf-8', &encoding)
|
||||||
|
endif
|
||||||
|
call add(self.messages, l:msg)
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! s:exit_cb(job, exitval) dict
|
||||||
|
let self.exit_status = a:exitval
|
||||||
|
let self.exited = 1
|
||||||
|
|
||||||
|
if self.closed
|
||||||
|
call self.complete()
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! s:close_cb(ch) dict
|
||||||
|
let self.closed = 1
|
||||||
|
if self.exited
|
||||||
|
call self.complete()
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function state.complete() dict
|
||||||
|
if self.exit_status != 0
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
let result = s:info_filter(self.auto, join(self.messages, "\n"))
|
||||||
|
call s:info_complete(self.auto, result)
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" add 1 to the offset, so that the position at the cursor will be included
|
||||||
|
" in gocode's search
|
||||||
|
let offset = go#util#OffsetCursor()+1
|
||||||
|
|
||||||
|
" We might hit cache problems, as gocode doesn't handle different GOPATHs
|
||||||
|
" well. See: https://github.com/nsf/gocode/issues/239
|
||||||
|
let env = {
|
||||||
|
\ "GOROOT": go#util#env("goroot")
|
||||||
|
\ }
|
||||||
|
|
||||||
|
let cmd = s:gocodeCommand('autocomplete',
|
||||||
|
\ [expand('%:p'), offset])
|
||||||
|
|
||||||
|
" TODO(bc): Don't write the buffer to a file; pass the buffer directrly to
|
||||||
|
" gocode's stdin. It shouldn't be necessary to use {in_io: 'file', in_name:
|
||||||
|
" s:gocodeFile()}, but unfortunately {in_io: 'buffer', in_buf: bufnr('%')}
|
||||||
|
" should work.
|
||||||
|
let options = {
|
||||||
|
\ 'env': env,
|
||||||
|
\ 'in_io': 'file',
|
||||||
|
\ 'in_name': s:gocodeFile(),
|
||||||
|
\ 'callback': funcref("s:callback", [], state),
|
||||||
|
\ 'exit_cb': funcref("s:exit_cb", [], state),
|
||||||
|
\ 'close_cb': funcref("s:close_cb", [], state)
|
||||||
|
\ }
|
||||||
|
|
||||||
|
let s:async_info_job = job_start(cmd, options)
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! s:gocodeFile()
|
||||||
|
let file = tempname()
|
||||||
|
call writefile(go#util#GetLines(), file)
|
||||||
|
return file
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! s:sync_info(auto)
|
||||||
" auto is true if we were called by g:go_auto_type_info's autocmd
|
" auto is true if we were called by g:go_auto_type_info's autocmd
|
||||||
let result = go#complete#GetInfo()
|
|
||||||
if !empty(result)
|
" add 1 to the offset, so that the position at the cursor will be included
|
||||||
" if auto, and the result is a PANIC by gocode, hide it
|
" in gocode's search
|
||||||
if a:auto && result ==# 'PANIC PANIC PANIC' | return | endif
|
let offset = go#util#OffsetCursor()+1
|
||||||
echo "vim-go: " | echohl Function | echon result | echohl None
|
|
||||||
|
let result = s:sync_gocode('autocomplete',
|
||||||
|
\ [expand('%:p'), offset],
|
||||||
|
\ go#util#GetLines())
|
||||||
|
|
||||||
|
let result = s:info_filter(a:auto, result)
|
||||||
|
call s:info_complete(a:auto, result)
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! s:info_filter(auto, result) abort
|
||||||
|
if empty(a:result)
|
||||||
|
return ""
|
||||||
|
endif
|
||||||
|
|
||||||
|
let l:result = eval(a:result)
|
||||||
|
if len(l:result) != 2
|
||||||
|
return ""
|
||||||
|
endif
|
||||||
|
|
||||||
|
let l:candidates = l:result[1]
|
||||||
|
if len(l:candidates) == 1
|
||||||
|
" When gocode panics in vim mode, it returns
|
||||||
|
" [0, [{'word': 'PANIC', 'abbr': 'PANIC PANIC PANIC', 'info': 'PANIC PANIC PANIC'}]]
|
||||||
|
if a:auto && l:candidates[0].info ==# "PANIC PANIC PANIC"
|
||||||
|
return ""
|
||||||
|
endif
|
||||||
|
|
||||||
|
return l:candidates[0].info
|
||||||
|
endif
|
||||||
|
|
||||||
|
let filtered = []
|
||||||
|
let wordMatch = '\<' . expand("<cword>") . '\>'
|
||||||
|
" escape single quotes in wordMatch before passing it to filter
|
||||||
|
let wordMatch = substitute(wordMatch, "'", "''", "g")
|
||||||
|
let filtered = filter(l:candidates, "v:val.info =~ '".wordMatch."'")
|
||||||
|
|
||||||
|
if len(l:filtered) != 1
|
||||||
|
return ""
|
||||||
|
endif
|
||||||
|
|
||||||
|
return l:filtered[0].info
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! s:info_complete(auto, result) abort
|
||||||
|
if !empty(a:result)
|
||||||
|
echo "vim-go: " | echohl Function | echon a:result | echohl None
|
||||||
endif
|
endif
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
@ -142,20 +234,22 @@ function! s:trim_bracket(val) abort
|
||||||
return a:val
|
return a:val
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
let s:completions = ""
|
||||||
function! go#complete#Complete(findstart, base) abort
|
function! go#complete#Complete(findstart, base) abort
|
||||||
"findstart = 1 when we need to get the text length
|
"findstart = 1 when we need to get the text length
|
||||||
if a:findstart == 1
|
if a:findstart == 1
|
||||||
execute "silent let g:gocomplete_completions = " . s:gocodeAutocomplete()
|
execute "silent let s:completions = " . s:gocodeAutocomplete()
|
||||||
return col('.') - g:gocomplete_completions[0] - 1
|
return col('.') - s:completions[0] - 1
|
||||||
"findstart = 0 when we need to return the list of completions
|
"findstart = 0 when we need to return the list of completions
|
||||||
else
|
else
|
||||||
let s = getline(".")[col('.') - 1]
|
let s = getline(".")[col('.') - 1]
|
||||||
if s =~ '[(){}\{\}]'
|
if s =~ '[(){}\{\}]'
|
||||||
return map(copy(g:gocomplete_completions[1]), 's:trim_bracket(v:val)')
|
return map(copy(s:completions[1]), 's:trim_bracket(v:val)')
|
||||||
endif
|
endif
|
||||||
return g:gocomplete_completions[1]
|
|
||||||
|
return s:completions[1]
|
||||||
endif
|
endif
|
||||||
endf
|
endfunction
|
||||||
|
|
||||||
function! go#complete#ToggleAutoTypeInfo() abort
|
function! go#complete#ToggleAutoTypeInfo() abort
|
||||||
if get(g:, "go_auto_type_info", 0)
|
if get(g:, "go_auto_type_info", 0)
|
||||||
|
@ -168,5 +262,4 @@ function! go#complete#ToggleAutoTypeInfo() abort
|
||||||
call go#util#EchoProgress("auto type info enabled")
|
call go#util#EchoProgress("auto type info enabled")
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
" vim: sw=2 ts=2 et
|
" vim: sw=2 ts=2 et
|
||||||
|
|
|
@ -45,7 +45,7 @@ function! go#coverage#Buffer(bang, ...) abort
|
||||||
let l:tmpname = tempname()
|
let l:tmpname = tempname()
|
||||||
|
|
||||||
if get(g:, 'go_echo_command_info', 1)
|
if get(g:, 'go_echo_command_info', 1)
|
||||||
echon "vim-go: " | echohl Identifier | echon "testing ..." | echohl None
|
call go#util#EchoProgress("testing...")
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if go#util#has_job()
|
if go#util#has_job()
|
||||||
|
|
904
sources_non_forked/vim-go/autoload/go/debug.vim
Normal file
904
sources_non_forked/vim-go/autoload/go/debug.vim
Normal file
|
@ -0,0 +1,904 @@
|
||||||
|
scriptencoding utf-8
|
||||||
|
|
||||||
|
if !exists('g:go_debug_windows')
|
||||||
|
let g:go_debug_windows = {
|
||||||
|
\ 'stack': 'leftabove 20vnew',
|
||||||
|
\ 'out': 'botright 10new',
|
||||||
|
\ 'vars': 'leftabove 30vnew',
|
||||||
|
\ }
|
||||||
|
endif
|
||||||
|
|
||||||
|
if !exists('g:go_debug_address')
|
||||||
|
let g:go_debug_address = '127.0.0.1:8181'
|
||||||
|
endif
|
||||||
|
|
||||||
|
if !exists('s:state')
|
||||||
|
let s:state = {
|
||||||
|
\ 'rpcid': 1,
|
||||||
|
\ 'running': 0,
|
||||||
|
\ 'breakpoint': {},
|
||||||
|
\ 'currentThread': {},
|
||||||
|
\ 'localVars': {},
|
||||||
|
\ 'functionArgs': {},
|
||||||
|
\ 'message': [],
|
||||||
|
\ 'is_test': 0,
|
||||||
|
\}
|
||||||
|
|
||||||
|
if go#util#HasDebug('debugger-state')
|
||||||
|
let g:go_debug_diag = s:state
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
if !exists('s:start_args')
|
||||||
|
let s:start_args = []
|
||||||
|
endif
|
||||||
|
|
||||||
|
function! s:groutineID() abort
|
||||||
|
return s:state['currentThread'].goroutineID
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! s:exit(job, status) abort
|
||||||
|
if has_key(s:state, 'job')
|
||||||
|
call remove(s:state, 'job')
|
||||||
|
endif
|
||||||
|
call s:clearState()
|
||||||
|
if a:status > 0
|
||||||
|
call go#util#EchoError(s:state['message'])
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! s:logger(prefix, ch, msg) abort
|
||||||
|
let l:cur_win = bufwinnr('')
|
||||||
|
let l:log_win = bufwinnr(bufnr('__GODEBUG_OUTPUT__'))
|
||||||
|
if l:log_win == -1
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
exe l:log_win 'wincmd w'
|
||||||
|
|
||||||
|
try
|
||||||
|
setlocal modifiable
|
||||||
|
if getline(1) == ''
|
||||||
|
call setline('$', a:prefix . a:msg)
|
||||||
|
else
|
||||||
|
call append('$', a:prefix . a:msg)
|
||||||
|
endif
|
||||||
|
normal! G
|
||||||
|
setlocal nomodifiable
|
||||||
|
finally
|
||||||
|
exe l:cur_win 'wincmd w'
|
||||||
|
endtry
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! s:call_jsonrpc(method, ...) abort
|
||||||
|
if go#util#HasDebug('debugger-commands')
|
||||||
|
if !exists('g:go_debug_commands')
|
||||||
|
let g:go_debug_commands = []
|
||||||
|
endif
|
||||||
|
echom 'sending to dlv ' . a:method
|
||||||
|
endif
|
||||||
|
|
||||||
|
if len(a:000) > 0 && type(a:000[0]) == v:t_func
|
||||||
|
let Cb = a:000[0]
|
||||||
|
let args = a:000[1:]
|
||||||
|
else
|
||||||
|
let Cb = v:none
|
||||||
|
let args = a:000
|
||||||
|
endif
|
||||||
|
let s:state['rpcid'] += 1
|
||||||
|
let req_json = json_encode({
|
||||||
|
\ 'id': s:state['rpcid'],
|
||||||
|
\ 'method': a:method,
|
||||||
|
\ 'params': args,
|
||||||
|
\})
|
||||||
|
|
||||||
|
try
|
||||||
|
" Use callback
|
||||||
|
if type(Cb) == v:t_func
|
||||||
|
let s:ch = ch_open('127.0.0.1:8181', {'mode': 'nl', 'callback': Cb})
|
||||||
|
call ch_sendraw(s:ch, req_json)
|
||||||
|
|
||||||
|
if go#util#HasDebug('debugger-commands')
|
||||||
|
let g:go_debug_commands = add(g:go_debug_commands, {
|
||||||
|
\ 'request': req_json,
|
||||||
|
\ 'response': Cb,
|
||||||
|
\ })
|
||||||
|
endif
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
let ch = ch_open('127.0.0.1:8181', {'mode': 'nl', 'timeout': 20000})
|
||||||
|
call ch_sendraw(ch, req_json)
|
||||||
|
let resp_json = ch_readraw(ch)
|
||||||
|
|
||||||
|
if go#util#HasDebug('debugger-commands')
|
||||||
|
let g:go_debug_commands = add(g:go_debug_commands, {
|
||||||
|
\ 'request': req_json,
|
||||||
|
\ 'response': resp_json,
|
||||||
|
\ })
|
||||||
|
endif
|
||||||
|
|
||||||
|
let obj = json_decode(resp_json)
|
||||||
|
if type(obj) == v:t_dict && has_key(obj, 'error') && !empty(obj.error)
|
||||||
|
throw obj.error
|
||||||
|
endif
|
||||||
|
return obj
|
||||||
|
catch
|
||||||
|
throw substitute(v:exception, '^Vim', '', '')
|
||||||
|
endtry
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" Update the location of the current breakpoint or line we're halted on based on
|
||||||
|
" response from dlv.
|
||||||
|
function! s:update_breakpoint(res) abort
|
||||||
|
if type(a:res) ==# v:t_none
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
let state = a:res.result.State
|
||||||
|
if !has_key(state, 'currentThread')
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
let s:state['currentThread'] = state.currentThread
|
||||||
|
let bufs = filter(map(range(1, winnr('$')), '[v:val,bufname(winbufnr(v:val))]'), 'v:val[1]=~"\.go$"')
|
||||||
|
if len(bufs) == 0
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
exe bufs[0][0] 'wincmd w'
|
||||||
|
let filename = state.currentThread.file
|
||||||
|
let linenr = state.currentThread.line
|
||||||
|
let oldfile = fnamemodify(expand('%'), ':p:gs!\\!/!')
|
||||||
|
if oldfile != filename
|
||||||
|
silent! exe 'edit' filename
|
||||||
|
endif
|
||||||
|
silent! exe 'norm!' linenr.'G'
|
||||||
|
silent! normal! zvzz
|
||||||
|
silent! sign unplace 9999
|
||||||
|
silent! exe 'sign place 9999 line=' . linenr . ' name=godebugcurline file=' . filename
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" Populate the stacktrace window.
|
||||||
|
function! s:show_stacktrace(res) abort
|
||||||
|
if !has_key(a:res, 'result')
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
let l:stack_win = bufwinnr(bufnr('__GODEBUG_STACKTRACE__'))
|
||||||
|
if l:stack_win == -1
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
let l:cur_win = bufwinnr('')
|
||||||
|
exe l:stack_win 'wincmd w'
|
||||||
|
|
||||||
|
try
|
||||||
|
setlocal modifiable
|
||||||
|
silent %delete _
|
||||||
|
for i in range(len(a:res.result.Locations))
|
||||||
|
let loc = a:res.result.Locations[i]
|
||||||
|
call setline(i+1, printf('%s - %s:%d', loc.function.name, fnamemodify(loc.file, ':p'), loc.line))
|
||||||
|
endfor
|
||||||
|
finally
|
||||||
|
setlocal nomodifiable
|
||||||
|
exe l:cur_win 'wincmd w'
|
||||||
|
endtry
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" Populate the variable window.
|
||||||
|
function! s:show_variables() abort
|
||||||
|
let l:var_win = bufwinnr(bufnr('__GODEBUG_VARIABLES__'))
|
||||||
|
if l:var_win == -1
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
let l:cur_win = bufwinnr('')
|
||||||
|
exe l:var_win 'wincmd w'
|
||||||
|
|
||||||
|
try
|
||||||
|
setlocal modifiable
|
||||||
|
silent %delete _
|
||||||
|
|
||||||
|
let v = []
|
||||||
|
let v += ['# Local Variables']
|
||||||
|
if type(get(s:state, 'localVars', [])) is type([])
|
||||||
|
for c in s:state['localVars']
|
||||||
|
let v += split(s:eval_tree(c, 0), "\n")
|
||||||
|
endfor
|
||||||
|
endif
|
||||||
|
|
||||||
|
let v += ['']
|
||||||
|
let v += ['# Function Arguments']
|
||||||
|
if type(get(s:state, 'functionArgs', [])) is type([])
|
||||||
|
for c in s:state['functionArgs']
|
||||||
|
let v += split(s:eval_tree(c, 0), "\n")
|
||||||
|
endfor
|
||||||
|
endif
|
||||||
|
|
||||||
|
call setline(1, v)
|
||||||
|
finally
|
||||||
|
setlocal nomodifiable
|
||||||
|
exe l:cur_win 'wincmd w'
|
||||||
|
endtry
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! s:clearState() abort
|
||||||
|
let s:state['currentThread'] = {}
|
||||||
|
let s:state['localVars'] = {}
|
||||||
|
let s:state['functionArgs'] = {}
|
||||||
|
let s:state['message'] = []
|
||||||
|
silent! sign unplace 9999
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! s:stop() abort
|
||||||
|
call s:clearState()
|
||||||
|
if has_key(s:state, 'job')
|
||||||
|
call job_stop(s:state['job'])
|
||||||
|
call remove(s:state, 'job')
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! go#debug#Stop() abort
|
||||||
|
" Remove signs.
|
||||||
|
for k in keys(s:state['breakpoint'])
|
||||||
|
let bt = s:state['breakpoint'][k]
|
||||||
|
if bt.id >= 0
|
||||||
|
silent exe 'sign unplace ' . bt.id
|
||||||
|
endif
|
||||||
|
endfor
|
||||||
|
|
||||||
|
" Remove all commands and add back the default commands.
|
||||||
|
for k in map(split(execute('command GoDebug'), "\n")[1:], 'matchstr(v:val, "^\\s*\\zs\\S\\+")')
|
||||||
|
exe 'delcommand' k
|
||||||
|
endfor
|
||||||
|
command! -nargs=* -complete=customlist,go#package#Complete GoDebugStart call go#debug#Start(0, <f-args>)
|
||||||
|
command! -nargs=* -complete=customlist,go#package#Complete GoDebugTest call go#debug#Start(1, <f-args>)
|
||||||
|
command! -nargs=? GoDebugBreakpoint call go#debug#Breakpoint(<f-args>)
|
||||||
|
|
||||||
|
" Remove all mappings.
|
||||||
|
for k in map(split(execute('map <Plug>(go-debug-'), "\n")[1:], 'matchstr(v:val, "^n\\s\\+\\zs\\S\\+")')
|
||||||
|
exe 'unmap' k
|
||||||
|
endfor
|
||||||
|
|
||||||
|
call s:stop()
|
||||||
|
|
||||||
|
let bufs = filter(map(range(1, winnr('$')), '[v:val,bufname(winbufnr(v:val))]'), 'v:val[1]=~"\.go$"')
|
||||||
|
if len(bufs) > 0
|
||||||
|
exe bufs[0][0] 'wincmd w'
|
||||||
|
else
|
||||||
|
wincmd p
|
||||||
|
endif
|
||||||
|
silent! exe bufwinnr(bufnr('__GODEBUG_STACKTRACE__')) 'wincmd c'
|
||||||
|
silent! exe bufwinnr(bufnr('__GODEBUG_VARIABLES__')) 'wincmd c'
|
||||||
|
silent! exe bufwinnr(bufnr('__GODEBUG_OUTPUT__')) 'wincmd c'
|
||||||
|
|
||||||
|
set noballooneval
|
||||||
|
set balloonexpr=
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! s:goto_file() abort
|
||||||
|
let m = matchlist(getline('.'), ' - \(.*\):\([0-9]\+\)$')
|
||||||
|
if m[1] == ''
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
let bufs = filter(map(range(1, winnr('$')), '[v:val,bufname(winbufnr(v:val))]'), 'v:val[1]=~"\.go$"')
|
||||||
|
if len(bufs) == 0
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
exe bufs[0][0] 'wincmd w'
|
||||||
|
let filename = m[1]
|
||||||
|
let linenr = m[2]
|
||||||
|
let oldfile = fnamemodify(expand('%'), ':p:gs!\\!/!')
|
||||||
|
if oldfile != filename
|
||||||
|
silent! exe 'edit' filename
|
||||||
|
endif
|
||||||
|
silent! exe 'norm!' linenr.'G'
|
||||||
|
silent! normal! zvzz
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! s:delete_expands()
|
||||||
|
let nr = line('.')
|
||||||
|
while 1
|
||||||
|
let l = getline(nr+1)
|
||||||
|
if empty(l) || l =~ '^\S'
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
silent! exe (nr+1) . 'd _'
|
||||||
|
endwhile
|
||||||
|
silent! exe 'norm!' nr.'G'
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! s:expand_var() abort
|
||||||
|
" Get name from struct line.
|
||||||
|
let name = matchstr(getline('.'), '^[^:]\+\ze: [a-zA-Z0-9\.·]\+{\.\.\.}$')
|
||||||
|
" Anonymous struct
|
||||||
|
if name == ''
|
||||||
|
let name = matchstr(getline('.'), '^[^:]\+\ze: struct {.\{-}}$')
|
||||||
|
endif
|
||||||
|
|
||||||
|
if name != ''
|
||||||
|
setlocal modifiable
|
||||||
|
let not_open = getline(line('.')+1) !~ '^ '
|
||||||
|
let l = line('.')
|
||||||
|
call s:delete_expands()
|
||||||
|
|
||||||
|
if not_open
|
||||||
|
call append(l, split(s:eval(name), "\n")[1:])
|
||||||
|
endif
|
||||||
|
silent! exe 'norm!' l.'G'
|
||||||
|
setlocal nomodifiable
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
" Expand maps
|
||||||
|
let m = matchlist(getline('.'), '^[^:]\+\ze: map.\{-}\[\(\d\+\)\]$')
|
||||||
|
if len(m) > 0 && m[1] != ''
|
||||||
|
setlocal modifiable
|
||||||
|
let not_open = getline(line('.')+1) !~ '^ '
|
||||||
|
let l = line('.')
|
||||||
|
call s:delete_expands()
|
||||||
|
if not_open
|
||||||
|
" TODO: Not sure how to do this yet... Need to get keys of the map.
|
||||||
|
" let vs = ''
|
||||||
|
" for i in range(0, min([10, m[1]-1]))
|
||||||
|
" let vs .= ' ' . s:eval(printf("%s[%s]", m[0], ))
|
||||||
|
" endfor
|
||||||
|
" call append(l, split(vs, "\n"))
|
||||||
|
endif
|
||||||
|
|
||||||
|
silent! exe 'norm!' l.'G'
|
||||||
|
setlocal nomodifiable
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
" Expand string.
|
||||||
|
let m = matchlist(getline('.'), '^\([^:]\+\)\ze: \(string\)\[\([0-9]\+\)\]\(: .\{-}\)\?$')
|
||||||
|
if len(m) > 0 && m[1] != ''
|
||||||
|
setlocal modifiable
|
||||||
|
let not_open = getline(line('.')+1) !~ '^ '
|
||||||
|
let l = line('.')
|
||||||
|
call s:delete_expands()
|
||||||
|
|
||||||
|
if not_open
|
||||||
|
let vs = ''
|
||||||
|
for i in range(0, min([10, m[3]-1]))
|
||||||
|
let vs .= ' ' . s:eval(m[1] . '[' . i . ']')
|
||||||
|
endfor
|
||||||
|
call append(l, split(vs, "\n"))
|
||||||
|
endif
|
||||||
|
|
||||||
|
silent! exe 'norm!' l.'G'
|
||||||
|
setlocal nomodifiable
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
" Expand slice.
|
||||||
|
let m = matchlist(getline('.'), '^\([^:]\+\)\ze: \(\[\]\w\{-}\)\[\([0-9]\+\)\]$')
|
||||||
|
if len(m) > 0 && m[1] != ''
|
||||||
|
setlocal modifiable
|
||||||
|
let not_open = getline(line('.')+1) !~ '^ '
|
||||||
|
let l = line('.')
|
||||||
|
call s:delete_expands()
|
||||||
|
|
||||||
|
if not_open
|
||||||
|
let vs = ''
|
||||||
|
for i in range(0, min([10, m[3]-1]))
|
||||||
|
let vs .= ' ' . s:eval(m[1] . '[' . i . ']')
|
||||||
|
endfor
|
||||||
|
call append(l, split(vs, "\n"))
|
||||||
|
endif
|
||||||
|
silent! exe 'norm!' l.'G'
|
||||||
|
setlocal nomodifiable
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! s:start_cb(ch, json) abort
|
||||||
|
let res = json_decode(a:json)
|
||||||
|
if type(res) == v:t_dict && has_key(res, 'error') && !empty(res.error)
|
||||||
|
throw res.error
|
||||||
|
endif
|
||||||
|
if empty(res) || !has_key(res, 'result')
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
for bt in res.result.Breakpoints
|
||||||
|
if bt.id >= 0
|
||||||
|
let s:state['breakpoint'][bt.id] = bt
|
||||||
|
exe 'sign place '. bt.id .' line=' . bt.line . ' name=godebugbreakpoint file=' . bt.file
|
||||||
|
endif
|
||||||
|
endfor
|
||||||
|
|
||||||
|
let oldbuf = bufnr('%')
|
||||||
|
silent! only!
|
||||||
|
|
||||||
|
let winnum = bufwinnr(bufnr('__GODEBUG_STACKTRACE__'))
|
||||||
|
if winnum != -1
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
if exists('g:go_debug_windows["stack"]') && g:go_debug_windows['stack'] != ''
|
||||||
|
exe 'silent ' . g:go_debug_windows['stack']
|
||||||
|
silent file `='__GODEBUG_STACKTRACE__'`
|
||||||
|
setlocal buftype=nofile bufhidden=wipe nomodified nobuflisted noswapfile nowrap nonumber nocursorline
|
||||||
|
setlocal filetype=godebugstacktrace
|
||||||
|
nmap <buffer> <cr> :<c-u>call <SID>goto_file()<cr>
|
||||||
|
nmap <buffer> q <Plug>(go-debug-stop)
|
||||||
|
endif
|
||||||
|
|
||||||
|
if exists('g:go_debug_windows["out"]') && g:go_debug_windows['out'] != ''
|
||||||
|
exe 'silent ' . g:go_debug_windows['out']
|
||||||
|
silent file `='__GODEBUG_OUTPUT__'`
|
||||||
|
setlocal buftype=nofile bufhidden=wipe nomodified nobuflisted noswapfile nowrap nonumber nocursorline
|
||||||
|
setlocal filetype=godebugoutput
|
||||||
|
nmap <buffer> q <Plug>(go-debug-stop)
|
||||||
|
endif
|
||||||
|
|
||||||
|
if exists('g:go_debug_windows["vars"]') && g:go_debug_windows['vars'] != ''
|
||||||
|
exe 'silent ' . g:go_debug_windows['vars']
|
||||||
|
silent file `='__GODEBUG_VARIABLES__'`
|
||||||
|
setlocal buftype=nofile bufhidden=wipe nomodified nobuflisted noswapfile nowrap nonumber nocursorline
|
||||||
|
setlocal filetype=godebugvariables
|
||||||
|
call append(0, ["# Local Variables", "", "# Function Arguments"])
|
||||||
|
nmap <buffer> <silent> <cr> :<c-u>call <SID>expand_var()<cr>
|
||||||
|
nmap <buffer> q <Plug>(go-debug-stop)
|
||||||
|
endif
|
||||||
|
|
||||||
|
silent! delcommand GoDebugStart
|
||||||
|
silent! delcommand GoDebugTest
|
||||||
|
command! -nargs=0 GoDebugContinue call go#debug#Stack('continue')
|
||||||
|
command! -nargs=0 GoDebugNext call go#debug#Stack('next')
|
||||||
|
command! -nargs=0 GoDebugStep call go#debug#Stack('step')
|
||||||
|
command! -nargs=0 GoDebugStepOut call go#debug#Stack('stepOut')
|
||||||
|
command! -nargs=0 GoDebugRestart call go#debug#Restart()
|
||||||
|
command! -nargs=0 GoDebugStop call go#debug#Stop()
|
||||||
|
command! -nargs=* GoDebugSet call go#debug#Set(<f-args>)
|
||||||
|
command! -nargs=1 GoDebugPrint call go#debug#Print(<q-args>)
|
||||||
|
|
||||||
|
nnoremap <silent> <Plug>(go-debug-breakpoint) :<C-u>call go#debug#Breakpoint()<CR>
|
||||||
|
nnoremap <silent> <Plug>(go-debug-next) :<C-u>call go#debug#Stack('next')<CR>
|
||||||
|
nnoremap <silent> <Plug>(go-debug-step) :<C-u>call go#debug#Stack('step')<CR>
|
||||||
|
nnoremap <silent> <Plug>(go-debug-stepout) :<C-u>call go#debug#Stack('stepout')<CR>
|
||||||
|
nnoremap <silent> <Plug>(go-debug-continue) :<C-u>call go#debug#Stack('continue')<CR>
|
||||||
|
nnoremap <silent> <Plug>(go-debug-stop) :<C-u>call go#debug#Stop()<CR>
|
||||||
|
nnoremap <silent> <Plug>(go-debug-print) :<C-u>call go#debug#Print(expand('<cword>'))<CR>
|
||||||
|
|
||||||
|
nmap <F5> <Plug>(go-debug-continue)
|
||||||
|
nmap <F6> <Plug>(go-debug-print)
|
||||||
|
nmap <F9> <Plug>(go-debug-breakpoint)
|
||||||
|
nmap <F10> <Plug>(go-debug-next)
|
||||||
|
nmap <F11> <Plug>(go-debug-step)
|
||||||
|
|
||||||
|
set balloonexpr=go#debug#BalloonExpr()
|
||||||
|
set ballooneval
|
||||||
|
|
||||||
|
exe bufwinnr(oldbuf) 'wincmd w'
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! s:err_cb(ch, msg) abort
|
||||||
|
call go#util#EchoError(a:msg)
|
||||||
|
let s:state['message'] += [a:msg]
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! s:out_cb(ch, msg) abort
|
||||||
|
call go#util#EchoProgress(a:msg)
|
||||||
|
let s:state['message'] += [a:msg]
|
||||||
|
|
||||||
|
" TODO: why do this in this callback?
|
||||||
|
if stridx(a:msg, g:go_debug_address) != -1
|
||||||
|
call ch_setoptions(a:ch, {
|
||||||
|
\ 'out_cb': function('s:logger', ['OUT: ']),
|
||||||
|
\ 'err_cb': function('s:logger', ['ERR: ']),
|
||||||
|
\})
|
||||||
|
|
||||||
|
" Tell dlv about the breakpoints that the user added before delve started.
|
||||||
|
let l:breaks = copy(s:state.breakpoint)
|
||||||
|
let s:state['breakpoint'] = {}
|
||||||
|
for l:bt in values(l:breaks)
|
||||||
|
call go#debug#Breakpoint(bt.line)
|
||||||
|
endfor
|
||||||
|
|
||||||
|
call s:call_jsonrpc('RPCServer.ListBreakpoints', function('s:start_cb'))
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" Start the debug mode. The first argument is the package name to compile and
|
||||||
|
" debug, anything else will be passed to the running program.
|
||||||
|
function! go#debug#Start(is_test, ...) abort
|
||||||
|
if has('nvim')
|
||||||
|
call go#util#EchoError('This feature only works in Vim for now; Neovim is not (yet) supported. Sorry :-(')
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
if !go#util#has_job()
|
||||||
|
call go#util#EchoError('This feature requires Vim 8.0.0087 or newer with +job.')
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
" It's already running.
|
||||||
|
if has_key(s:state, 'job') && job_status(s:state['job']) == 'run'
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
let s:start_args = a:000
|
||||||
|
|
||||||
|
if go#util#HasDebug('debugger-state')
|
||||||
|
let g:go_debug_diag = s:state
|
||||||
|
endif
|
||||||
|
|
||||||
|
" cd in to test directory; this is also what running "go test" does.
|
||||||
|
if a:is_test
|
||||||
|
lcd %:p:h
|
||||||
|
endif
|
||||||
|
|
||||||
|
let s:state.is_test = a:is_test
|
||||||
|
|
||||||
|
let dlv = go#path#CheckBinPath("dlv")
|
||||||
|
if empty(dlv)
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
try
|
||||||
|
if len(a:000) > 0
|
||||||
|
let l:pkgname = a:1
|
||||||
|
" Expand .; otherwise this won't work from a tmp dir.
|
||||||
|
if l:pkgname[0] == '.'
|
||||||
|
let l:pkgname = go#package#FromPath(getcwd()) . l:pkgname[1:]
|
||||||
|
endif
|
||||||
|
else
|
||||||
|
let l:pkgname = go#package#FromPath(getcwd())
|
||||||
|
endif
|
||||||
|
|
||||||
|
let l:args = []
|
||||||
|
if len(a:000) > 1
|
||||||
|
let l:args = ['--'] + a:000[1:]
|
||||||
|
endif
|
||||||
|
|
||||||
|
let l:cmd = [
|
||||||
|
\ dlv,
|
||||||
|
\ (a:is_test ? 'test' : 'debug'),
|
||||||
|
\ '--output', tempname(),
|
||||||
|
\ '--headless',
|
||||||
|
\ '--api-version', '2',
|
||||||
|
\ '--log',
|
||||||
|
\ '--listen', g:go_debug_address,
|
||||||
|
\ '--accept-multiclient',
|
||||||
|
\]
|
||||||
|
if get(g:, 'go_build_tags', '') isnot ''
|
||||||
|
let l:cmd += ['--build-flags', '--tags=' . g:go_build_tags]
|
||||||
|
endif
|
||||||
|
let l:cmd += l:args
|
||||||
|
|
||||||
|
call go#util#EchoProgress('Starting GoDebug...')
|
||||||
|
let s:state['message'] = []
|
||||||
|
let s:state['job'] = job_start(l:cmd, {
|
||||||
|
\ 'out_cb': function('s:out_cb'),
|
||||||
|
\ 'err_cb': function('s:err_cb'),
|
||||||
|
\ 'exit_cb': function('s:exit'),
|
||||||
|
\ 'stoponexit': 'kill',
|
||||||
|
\})
|
||||||
|
catch
|
||||||
|
call go#util#EchoError(v:exception)
|
||||||
|
endtry
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" Translate a reflect kind constant to a human string.
|
||||||
|
function! s:reflect_kind(k)
|
||||||
|
" Kind constants from Go's reflect package.
|
||||||
|
return [
|
||||||
|
\ 'Invalid Kind',
|
||||||
|
\ 'Bool',
|
||||||
|
\ 'Int',
|
||||||
|
\ 'Int8',
|
||||||
|
\ 'Int16',
|
||||||
|
\ 'Int32',
|
||||||
|
\ 'Int64',
|
||||||
|
\ 'Uint',
|
||||||
|
\ 'Uint8',
|
||||||
|
\ 'Uint16',
|
||||||
|
\ 'Uint32',
|
||||||
|
\ 'Uint64',
|
||||||
|
\ 'Uintptr',
|
||||||
|
\ 'Float32',
|
||||||
|
\ 'Float64',
|
||||||
|
\ 'Complex64',
|
||||||
|
\ 'Complex128',
|
||||||
|
\ 'Array',
|
||||||
|
\ 'Chan',
|
||||||
|
\ 'Func',
|
||||||
|
\ 'Interface',
|
||||||
|
\ 'Map',
|
||||||
|
\ 'Ptr',
|
||||||
|
\ 'Slice',
|
||||||
|
\ 'String',
|
||||||
|
\ 'Struct',
|
||||||
|
\ 'UnsafePointer',
|
||||||
|
\ ][a:k]
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! s:eval_tree(var, nest) abort
|
||||||
|
if a:var.name =~ '^\~'
|
||||||
|
return ''
|
||||||
|
endif
|
||||||
|
let nest = a:nest
|
||||||
|
let v = ''
|
||||||
|
let kind = s:reflect_kind(a:var.kind)
|
||||||
|
if !empty(a:var.name)
|
||||||
|
let v .= repeat(' ', nest) . a:var.name . ': '
|
||||||
|
|
||||||
|
if kind == 'Bool'
|
||||||
|
let v .= printf("%s\n", a:var.value)
|
||||||
|
|
||||||
|
elseif kind == 'Struct'
|
||||||
|
" Anonymous struct
|
||||||
|
if a:var.type[:8] == 'struct { '
|
||||||
|
let v .= printf("%s\n", a:var.type)
|
||||||
|
else
|
||||||
|
let v .= printf("%s{...}\n", a:var.type)
|
||||||
|
endif
|
||||||
|
|
||||||
|
elseif kind == 'String'
|
||||||
|
let v .= printf("%s[%d]%s\n", a:var.type, a:var.len,
|
||||||
|
\ len(a:var.value) > 0 ? ': ' . a:var.value : '')
|
||||||
|
|
||||||
|
elseif kind == 'Slice' || kind == 'String' || kind == 'Map' || kind == 'Array'
|
||||||
|
let v .= printf("%s[%d]\n", a:var.type, a:var.len)
|
||||||
|
|
||||||
|
elseif kind == 'Chan' || kind == 'Func' || kind == 'Interface'
|
||||||
|
let v .= printf("%s\n", a:var.type)
|
||||||
|
|
||||||
|
elseif kind == 'Ptr'
|
||||||
|
" TODO: We can do something more useful here.
|
||||||
|
let v .= printf("%s\n", a:var.type)
|
||||||
|
|
||||||
|
elseif kind == 'Complex64' || kind == 'Complex128'
|
||||||
|
let v .= printf("%s%s\n", a:var.type, a:var.value)
|
||||||
|
|
||||||
|
" Int, Float
|
||||||
|
else
|
||||||
|
let v .= printf("%s(%s)\n", a:var.type, a:var.value)
|
||||||
|
endif
|
||||||
|
else
|
||||||
|
let nest -= 1
|
||||||
|
endif
|
||||||
|
|
||||||
|
if index(['Chan', 'Complex64', 'Complex128'], kind) == -1 && a:var.type != 'error'
|
||||||
|
for c in a:var.children
|
||||||
|
let v .= s:eval_tree(c, nest+1)
|
||||||
|
endfor
|
||||||
|
endif
|
||||||
|
return v
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! s:eval(arg) abort
|
||||||
|
try
|
||||||
|
let res = s:call_jsonrpc('RPCServer.State')
|
||||||
|
let goroutineID = res.result.State.currentThread.goroutineID
|
||||||
|
let res = s:call_jsonrpc('RPCServer.Eval', {
|
||||||
|
\ 'expr': a:arg,
|
||||||
|
\ 'scope': {'GoroutineID': goroutineID}
|
||||||
|
\ })
|
||||||
|
return s:eval_tree(res.result.Variable, 0)
|
||||||
|
catch
|
||||||
|
call go#util#EchoError(v:exception)
|
||||||
|
return ''
|
||||||
|
endtry
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! go#debug#BalloonExpr() abort
|
||||||
|
silent! let l:v = s:eval(v:beval_text)
|
||||||
|
return l:v
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! go#debug#Print(arg) abort
|
||||||
|
try
|
||||||
|
echo substitute(s:eval(a:arg), "\n$", "", 0)
|
||||||
|
catch
|
||||||
|
call go#util#EchoError(v:exception)
|
||||||
|
endtry
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! s:update_variables() abort
|
||||||
|
" FollowPointers requests pointers to be automatically dereferenced.
|
||||||
|
" MaxVariableRecurse is how far to recurse when evaluating nested types.
|
||||||
|
" MaxStringLen is the maximum number of bytes read from a string
|
||||||
|
" MaxArrayValues is the maximum number of elements read from an array, a slice or a map.
|
||||||
|
" MaxStructFields is the maximum number of fields read from a struct, -1 will read all fields.
|
||||||
|
let l:cfg = {
|
||||||
|
\ 'scope': {'GoroutineID': s:groutineID()},
|
||||||
|
\ 'cfg': {'MaxStringLen': 20, 'MaxArrayValues': 20}
|
||||||
|
\ }
|
||||||
|
|
||||||
|
try
|
||||||
|
let res = s:call_jsonrpc('RPCServer.ListLocalVars', l:cfg)
|
||||||
|
let s:state['localVars'] = res.result['Variables']
|
||||||
|
catch
|
||||||
|
call go#util#EchoError(v:exception)
|
||||||
|
endtry
|
||||||
|
|
||||||
|
try
|
||||||
|
let res = s:call_jsonrpc('RPCServer.ListFunctionArgs', l:cfg)
|
||||||
|
let s:state['functionArgs'] = res.result['Args']
|
||||||
|
catch
|
||||||
|
call go#util#EchoError(v:exception)
|
||||||
|
endtry
|
||||||
|
|
||||||
|
call s:show_variables()
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! go#debug#Set(symbol, value) abort
|
||||||
|
try
|
||||||
|
let res = s:call_jsonrpc('RPCServer.State')
|
||||||
|
let goroutineID = res.result.State.currentThread.goroutineID
|
||||||
|
call s:call_jsonrpc('RPCServer.Set', {
|
||||||
|
\ 'symbol': a:symbol,
|
||||||
|
\ 'value': a:value,
|
||||||
|
\ 'scope': {'GoroutineID': goroutineID}
|
||||||
|
\ })
|
||||||
|
catch
|
||||||
|
call go#util#EchoError(v:exception)
|
||||||
|
endtry
|
||||||
|
|
||||||
|
call s:update_variables()
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! s:update_stacktrace() abort
|
||||||
|
try
|
||||||
|
let res = s:call_jsonrpc('RPCServer.Stacktrace', {'id': s:groutineID(), 'depth': 5})
|
||||||
|
call s:show_stacktrace(res)
|
||||||
|
catch
|
||||||
|
call go#util#EchoError(v:exception)
|
||||||
|
endtry
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! s:stack_cb(ch, json) abort
|
||||||
|
let s:stack_name = ''
|
||||||
|
let res = json_decode(a:json)
|
||||||
|
if type(res) == v:t_dict && has_key(res, 'error') && !empty(res.error)
|
||||||
|
call go#util#EchoError(res.error)
|
||||||
|
call s:clearState()
|
||||||
|
call go#debug#Restart()
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
if empty(res) || !has_key(res, 'result')
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
call s:update_breakpoint(res)
|
||||||
|
call s:update_stacktrace()
|
||||||
|
call s:update_variables()
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" Send a command to change the cursor location to Delve.
|
||||||
|
"
|
||||||
|
" a:name must be one of continue, next, step, or stepOut.
|
||||||
|
function! go#debug#Stack(name) abort
|
||||||
|
let l:name = a:name
|
||||||
|
|
||||||
|
" Run continue if the program hasn't started yet.
|
||||||
|
if s:state.running is 0
|
||||||
|
let s:state.running = 1
|
||||||
|
let l:name = 'continue'
|
||||||
|
endif
|
||||||
|
|
||||||
|
" Add a breakpoint to the main.Main if the user didn't define any.
|
||||||
|
if len(s:state['breakpoint']) is 0
|
||||||
|
if go#debug#Breakpoint() isnot 0
|
||||||
|
let s:state.running = 0
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
try
|
||||||
|
" TODO: document why this is needed.
|
||||||
|
if l:name is# 'next' && get(s:, 'stack_name', '') is# 'next'
|
||||||
|
call s:call_jsonrpc('RPCServer.CancelNext')
|
||||||
|
endif
|
||||||
|
let s:stack_name = l:name
|
||||||
|
call s:call_jsonrpc('RPCServer.Command', function('s:stack_cb'), {'name': l:name})
|
||||||
|
catch
|
||||||
|
call go#util#EchoError(v:exception)
|
||||||
|
endtry
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! go#debug#Restart() abort
|
||||||
|
try
|
||||||
|
call job_stop(s:state['job'])
|
||||||
|
while has_key(s:state, 'job') && job_status(s:state['job']) is# 'run'
|
||||||
|
sleep 50m
|
||||||
|
endwhile
|
||||||
|
|
||||||
|
let l:breaks = s:state['breakpoint']
|
||||||
|
let s:state = {
|
||||||
|
\ 'rpcid': 1,
|
||||||
|
\ 'running': 0,
|
||||||
|
\ 'breakpoint': {},
|
||||||
|
\ 'currentThread': {},
|
||||||
|
\ 'localVars': {},
|
||||||
|
\ 'functionArgs': {},
|
||||||
|
\ 'message': [],
|
||||||
|
\}
|
||||||
|
|
||||||
|
" Preserve breakpoints.
|
||||||
|
for bt in values(l:breaks)
|
||||||
|
" TODO: should use correct filename
|
||||||
|
exe 'sign unplace '. bt.id .' file=' . bt.file
|
||||||
|
call go#debug#Breakpoint(bt.line)
|
||||||
|
endfor
|
||||||
|
call call('go#debug#Start', s:start_args)
|
||||||
|
catch
|
||||||
|
call go#util#EchoError(v:exception)
|
||||||
|
endtry
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" Report if debugger mode is active.
|
||||||
|
function! s:isActive()
|
||||||
|
return len(s:state['message']) > 0
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" Toggle breakpoint. Returns 0 on success and 1 on failure.
|
||||||
|
function! go#debug#Breakpoint(...) abort
|
||||||
|
let l:filename = fnamemodify(expand('%'), ':p:gs!\\!/!')
|
||||||
|
|
||||||
|
" Get line number from argument.
|
||||||
|
if len(a:000) > 0
|
||||||
|
let linenr = str2nr(a:1)
|
||||||
|
if linenr is 0
|
||||||
|
call go#util#EchoError('not a number: ' . a:1)
|
||||||
|
return 0
|
||||||
|
endif
|
||||||
|
else
|
||||||
|
let linenr = line('.')
|
||||||
|
endif
|
||||||
|
|
||||||
|
try
|
||||||
|
" Check if we already have a breakpoint for this line.
|
||||||
|
let found = v:none
|
||||||
|
for k in keys(s:state.breakpoint)
|
||||||
|
let bt = s:state.breakpoint[k]
|
||||||
|
if bt.file == l:filename && bt.line == linenr
|
||||||
|
let found = bt
|
||||||
|
break
|
||||||
|
endif
|
||||||
|
endfor
|
||||||
|
|
||||||
|
" Remove breakpoint.
|
||||||
|
if type(found) == v:t_dict
|
||||||
|
call remove(s:state['breakpoint'], bt.id)
|
||||||
|
exe 'sign unplace '. found.id .' file=' . found.file
|
||||||
|
if s:isActive()
|
||||||
|
let res = s:call_jsonrpc('RPCServer.ClearBreakpoint', {'id': found.id})
|
||||||
|
endif
|
||||||
|
" Add breakpoint.
|
||||||
|
else
|
||||||
|
if s:isActive()
|
||||||
|
let res = s:call_jsonrpc('RPCServer.CreateBreakpoint', {'Breakpoint': {'file': l:filename, 'line': linenr}})
|
||||||
|
let bt = res.result.Breakpoint
|
||||||
|
exe 'sign place '. bt.id .' line=' . bt.line . ' name=godebugbreakpoint file=' . bt.file
|
||||||
|
let s:state['breakpoint'][bt.id] = bt
|
||||||
|
else
|
||||||
|
let id = len(s:state['breakpoint']) + 1
|
||||||
|
let s:state['breakpoint'][id] = {'id': id, 'file': l:filename, 'line': linenr}
|
||||||
|
exe 'sign place '. id .' line=' . linenr . ' name=godebugbreakpoint file=' . l:filename
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
catch
|
||||||
|
call go#util#EchoError(v:exception)
|
||||||
|
return 1
|
||||||
|
endtry
|
||||||
|
|
||||||
|
return 0
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
sign define godebugbreakpoint text=> texthl=GoDebugBreakpoint
|
||||||
|
sign define godebugcurline text== linehl=GoDebugCurrent texthl=GoDebugCurrent
|
||||||
|
|
||||||
|
fun! s:hi()
|
||||||
|
hi GoDebugBreakpoint term=standout ctermbg=117 ctermfg=0 guibg=#BAD4F5 guifg=Black
|
||||||
|
hi GoDebugCurrent term=reverse ctermbg=12 ctermfg=7 guibg=DarkBlue guifg=White
|
||||||
|
endfun
|
||||||
|
augroup vim-go-breakpoint
|
||||||
|
autocmd!
|
||||||
|
autocmd ColorScheme * call s:hi()
|
||||||
|
augroup end
|
||||||
|
call s:hi()
|
||||||
|
|
||||||
|
" vim: sw=2 ts=2 et
|
|
@ -148,7 +148,6 @@ function! go#fmt#update_file(source, target)
|
||||||
|
|
||||||
if has_key(l:list_title, "title") && l:list_title['title'] == "Format"
|
if has_key(l:list_title, "title") && l:list_title['title'] == "Format"
|
||||||
call go#list#Clean(l:listtype)
|
call go#list#Clean(l:listtype)
|
||||||
call go#list#Window(l:listtype)
|
|
||||||
endif
|
endif
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
|
@ -78,7 +78,7 @@ function! s:guru_cmd(args) range abort
|
||||||
let scopes = go#util#StripTrailingSlash(scopes)
|
let scopes = go#util#StripTrailingSlash(scopes)
|
||||||
|
|
||||||
" create shell-safe entries of the list
|
" create shell-safe entries of the list
|
||||||
if !go#util#has_job() | let scopes = go#util#Shelllist(scopes) | endif
|
if !has("nvim") && !go#util#has_job() | let scopes = go#util#Shelllist(scopes) | endif
|
||||||
|
|
||||||
" guru expect a comma-separated list of patterns, construct it
|
" guru expect a comma-separated list of patterns, construct it
|
||||||
let l:scope = join(scopes, ",")
|
let l:scope = join(scopes, ",")
|
||||||
|
@ -129,7 +129,7 @@ function! s:sync_guru(args) abort
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if has_key(a:args, 'custom_parse')
|
if has_key(a:args, 'custom_parse')
|
||||||
call a:args.custom_parse(go#util#ShellError(), out)
|
call a:args.custom_parse(go#util#ShellError(), out, a:args.mode)
|
||||||
else
|
else
|
||||||
call s:parse_guru_output(go#util#ShellError(), out, a:args.mode)
|
call s:parse_guru_output(go#util#ShellError(), out, a:args.mode)
|
||||||
endif
|
endif
|
||||||
|
@ -137,6 +137,33 @@ function! s:sync_guru(args) abort
|
||||||
return out
|
return out
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
" use vim or neovim job api as appropriate
|
||||||
|
function! s:job_start(cmd, start_options) abort
|
||||||
|
if go#util#has_job()
|
||||||
|
return job_start(a:cmd, a:start_options)
|
||||||
|
endif
|
||||||
|
|
||||||
|
let opts = {'stdout_buffered': v:true, 'stderr_buffered': v:true}
|
||||||
|
function opts.on_stdout(job_id, data, event) closure
|
||||||
|
call a:start_options.callback(a:job_id, join(a:data, "\n"))
|
||||||
|
endfunction
|
||||||
|
function opts.on_stderr(job_id, data, event) closure
|
||||||
|
call a:start_options.callback(a:job_id, join(a:data, "\n"))
|
||||||
|
endfunction
|
||||||
|
function opts.on_exit(job_id, exit_code, event) closure
|
||||||
|
call a:start_options.exit_cb(a:job_id, a:exit_code)
|
||||||
|
call a:start_options.close_cb(a:job_id)
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" use a shell for input redirection if needed
|
||||||
|
let cmd = a:cmd
|
||||||
|
if has_key(a:start_options, 'in_io') && a:start_options.in_io ==# 'file' && !empty(a:start_options.in_name)
|
||||||
|
let cmd = ['/bin/sh', '-c', join(a:cmd, ' ') . ' <' . a:start_options.in_name]
|
||||||
|
endif
|
||||||
|
|
||||||
|
return jobstart(cmd, opts)
|
||||||
|
endfunction
|
||||||
|
|
||||||
" async_guru runs guru in async mode with the given arguments
|
" async_guru runs guru in async mode with the given arguments
|
||||||
function! s:async_guru(args) abort
|
function! s:async_guru(args) abort
|
||||||
let result = s:guru_cmd(a:args)
|
let result = s:guru_cmd(a:args)
|
||||||
|
@ -145,8 +172,6 @@ function! s:async_guru(args) abort
|
||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
|
|
||||||
let status_dir = expand('%:p:h')
|
|
||||||
let statusline_type = printf("%s", a:args.mode)
|
|
||||||
|
|
||||||
if !has_key(a:args, 'disable_progress')
|
if !has_key(a:args, 'disable_progress')
|
||||||
if a:args.needs_scope
|
if a:args.needs_scope
|
||||||
|
@ -155,59 +180,63 @@ function! s:async_guru(args) abort
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
let messages = []
|
let state = {
|
||||||
function! s:callback(chan, msg) closure
|
\ 'status_dir': expand('%:p:h'),
|
||||||
call add(messages, a:msg)
|
\ 'statusline_type': printf("%s", a:args.mode),
|
||||||
|
\ 'mode': a:args.mode,
|
||||||
|
\ 'status': {},
|
||||||
|
\ 'exitval': 0,
|
||||||
|
\ 'closed': 0,
|
||||||
|
\ 'exited': 0,
|
||||||
|
\ 'messages': [],
|
||||||
|
\ 'parse' : get(a:args, 'custom_parse', funcref("s:parse_guru_output"))
|
||||||
|
\ }
|
||||||
|
|
||||||
|
function! s:callback(chan, msg) dict
|
||||||
|
call add(self.messages, a:msg)
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
let status = {}
|
function! s:exit_cb(job, exitval) dict
|
||||||
let exitval = 0
|
let self.exited = 1
|
||||||
let closed = 0
|
|
||||||
let exited = 0
|
|
||||||
|
|
||||||
function! s:exit_cb(job, exitval) closure
|
|
||||||
let exited = 1
|
|
||||||
|
|
||||||
let status = {
|
let status = {
|
||||||
\ 'desc': 'last status',
|
\ 'desc': 'last status',
|
||||||
\ 'type': statusline_type,
|
\ 'type': self.statusline_type,
|
||||||
\ 'state': "finished",
|
\ 'state': "finished",
|
||||||
\ }
|
\ }
|
||||||
|
|
||||||
if a:exitval
|
if a:exitval
|
||||||
let exitval = a:exitval
|
let self.exitval = a:exitval
|
||||||
let status.state = "failed"
|
let status.state = "failed"
|
||||||
endif
|
endif
|
||||||
|
|
||||||
call go#statusline#Update(status_dir, status)
|
call go#statusline#Update(self.status_dir, status)
|
||||||
|
|
||||||
if closed
|
if self.closed
|
||||||
call s:complete()
|
call self.complete()
|
||||||
endif
|
endif
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! s:close_cb(ch) closure
|
function! s:close_cb(ch) dict
|
||||||
let closed = 1
|
let self.closed = 1
|
||||||
|
|
||||||
if exited
|
if self.exited
|
||||||
call s:complete()
|
call self.complete()
|
||||||
endif
|
endif
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! s:complete() closure
|
function state.complete() dict
|
||||||
let out = join(messages, "\n")
|
let out = join(self.messages, "\n")
|
||||||
|
|
||||||
if has_key(a:args, 'custom_parse')
|
call self.parse(self.exitval, out, self.mode)
|
||||||
call a:args.custom_parse(exitval, out)
|
|
||||||
else
|
|
||||||
call s:parse_guru_output(exitval, out, a:args.mode)
|
|
||||||
endif
|
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
" explicitly bind the callbacks to state so that self within them always
|
||||||
|
" refers to state. See :help Partial for more information.
|
||||||
let start_options = {
|
let start_options = {
|
||||||
\ 'callback': funcref("s:callback"),
|
\ 'callback': function('s:callback', [], state),
|
||||||
\ 'exit_cb': funcref("s:exit_cb"),
|
\ 'exit_cb': function('s:exit_cb', [], state),
|
||||||
\ 'close_cb': funcref("s:close_cb"),
|
\ 'close_cb': function('s:close_cb', [], state)
|
||||||
\ }
|
\ }
|
||||||
|
|
||||||
if has_key(result, 'stdin_content')
|
if has_key(result, 'stdin_content')
|
||||||
|
@ -217,18 +246,18 @@ function! s:async_guru(args) abort
|
||||||
let l:start_options.in_name = l:tmpname
|
let l:start_options.in_name = l:tmpname
|
||||||
endif
|
endif
|
||||||
|
|
||||||
call go#statusline#Update(status_dir, {
|
call go#statusline#Update(state.status_dir, {
|
||||||
\ 'desc': "current status",
|
\ 'desc': "current status",
|
||||||
\ 'type': statusline_type,
|
\ 'type': state.statusline_type,
|
||||||
\ 'state': "analysing",
|
\ 'state': "analysing",
|
||||||
\})
|
\})
|
||||||
|
|
||||||
return job_start(result.cmd, start_options)
|
return s:job_start(result.cmd, start_options)
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
" run_guru runs the given guru argument
|
" run_guru runs the given guru argument
|
||||||
function! s:run_guru(args) abort
|
function! s:run_guru(args) abort
|
||||||
if go#util#has_job()
|
if has('nvim') || go#util#has_job()
|
||||||
let res = s:async_guru(a:args)
|
let res = s:async_guru(a:args)
|
||||||
else
|
else
|
||||||
let res = s:sync_guru(a:args)
|
let res = s:sync_guru(a:args)
|
||||||
|
@ -289,7 +318,7 @@ function! go#guru#DescribeInfo() abort
|
||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
|
|
||||||
function! s:info(exit_val, output)
|
function! s:info(exit_val, output, mode)
|
||||||
if a:exit_val != 0
|
if a:exit_val != 0
|
||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
|
@ -464,10 +493,6 @@ function! go#guru#Referrers(selected) abort
|
||||||
call s:run_guru(args)
|
call s:run_guru(args)
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! go#guru#SameIdsTimer() abort
|
|
||||||
call timer_start(200, function('go#guru#SameIds'), {'repeat': -1})
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function! go#guru#SameIds() abort
|
function! go#guru#SameIds() abort
|
||||||
" we use matchaddpos() which was introduce with 7.4.330, be sure we have
|
" we use matchaddpos() which was introduce with 7.4.330, be sure we have
|
||||||
" it: http://ftp.vim.org/vim/patches/7.4/7.4.330
|
" it: http://ftp.vim.org/vim/patches/7.4/7.4.330
|
||||||
|
@ -495,7 +520,7 @@ function! go#guru#SameIds() abort
|
||||||
call s:run_guru(args)
|
call s:run_guru(args)
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! s:same_ids_highlight(exit_val, output) abort
|
function! s:same_ids_highlight(exit_val, output, mode) abort
|
||||||
call go#guru#ClearSameIds() " run after calling guru to reduce flicker.
|
call go#guru#ClearSameIds() " run after calling guru to reduce flicker.
|
||||||
|
|
||||||
if a:output[0] !=# '{'
|
if a:output[0] !=# '{'
|
||||||
|
|
|
@ -19,10 +19,6 @@
|
||||||
" list of messages received from the channel. The default value will
|
" list of messages received from the channel. The default value will
|
||||||
" process the messages and manage the error list after the job exits and
|
" process the messages and manage the error list after the job exits and
|
||||||
" the channel is closed.
|
" the channel is closed.
|
||||||
" 'callback':
|
|
||||||
" A function to call when there is a message to read from the job's
|
|
||||||
" channel. The function will be passed two arguments: the channel and a
|
|
||||||
" message. See job-callback.
|
|
||||||
|
|
||||||
" The return value is a dictionary with these keys:
|
" The return value is a dictionary with these keys:
|
||||||
" 'callback':
|
" 'callback':
|
||||||
|
@ -36,43 +32,46 @@
|
||||||
" job-close_cb.
|
" job-close_cb.
|
||||||
function go#job#Spawn(args)
|
function go#job#Spawn(args)
|
||||||
let cbs = {}
|
let cbs = {}
|
||||||
|
let state = {
|
||||||
let winnr = winnr()
|
\ 'winnr': winnr(),
|
||||||
let dir = getcwd()
|
\ 'dir': getcwd(),
|
||||||
let jobdir = fnameescape(expand("%:p:h"))
|
\ 'jobdir': fnameescape(expand("%:p:h")),
|
||||||
let messages = []
|
\ 'messages': [],
|
||||||
let args = a:args.cmd
|
\ 'args': a:args.cmd,
|
||||||
let bang = 0
|
\ 'bang': 0,
|
||||||
let for = "_job"
|
\ 'for': "_job",
|
||||||
|
\ 'exited': 0,
|
||||||
|
\ 'exit_status': 0,
|
||||||
|
\ 'closed': 0,
|
||||||
|
\ 'errorformat': &errorformat
|
||||||
|
\ }
|
||||||
|
|
||||||
if has_key(a:args, 'bang')
|
if has_key(a:args, 'bang')
|
||||||
let l:bang = a:args.bang
|
let state.bang = a:args.bang
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if has_key(a:args, 'for')
|
if has_key(a:args, 'for')
|
||||||
let l:for = a:args.for
|
let state.for = a:args.for
|
||||||
endif
|
endif
|
||||||
|
|
||||||
let l:exited = 0
|
" do nothing in state.complete by default.
|
||||||
let l:exit_status = 0
|
function state.complete(job, exit_status, data)
|
||||||
let l:closed = 0
|
|
||||||
|
|
||||||
function! s:NopComplete(job, exit_status, data)
|
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
let Complete = funcref('s:NopComplete')
|
|
||||||
|
|
||||||
if has_key(a:args, 'complete')
|
if has_key(a:args, 'complete')
|
||||||
let Complete = a:args.complete
|
let state.complete = a:args.complete
|
||||||
endif
|
endif
|
||||||
|
|
||||||
function cbs.callback(chan, msg) dict closure
|
function! s:callback(chan, msg) dict
|
||||||
call add(messages, a:msg)
|
call add(self.messages, a:msg)
|
||||||
endfunction
|
endfunction
|
||||||
|
" explicitly bind callback to state so that within it, self will
|
||||||
|
" always refer to state. See :help Partial for more information.
|
||||||
|
let cbs.callback = function('s:callback', [], state)
|
||||||
|
|
||||||
function cbs.exit_cb(job, exitval) dict closure
|
function! s:exit_cb(job, exitval) dict
|
||||||
let exit_status = a:exitval
|
let self.exit_status = a:exitval
|
||||||
let exited = 1
|
let self.exited = 1
|
||||||
|
|
||||||
if get(g:, 'go_echo_command_info', 1)
|
if get(g:, 'go_echo_command_info', 1)
|
||||||
if a:exitval == 0
|
if a:exitval == 0
|
||||||
|
@ -82,56 +81,63 @@ function go#job#Spawn(args)
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if closed
|
if self.closed
|
||||||
call Complete(a:job, exit_status, messages)
|
call self.complete(a:job, self.exit_status, self.messages)
|
||||||
call s:show_errors(a:job, exit_status, messages)
|
call self.show_errors(a:job, self.exit_status, self.messages)
|
||||||
endif
|
endif
|
||||||
endfunction
|
endfunction
|
||||||
|
" explicitly bind exit_cb to state so that within it, self will always refer
|
||||||
|
" to state. See :help Partial for more information.
|
||||||
|
let cbs.exit_cb = function('s:exit_cb', [], state)
|
||||||
|
|
||||||
function cbs.close_cb(ch) dict closure
|
function! s:close_cb(ch) dict
|
||||||
let closed = 1
|
let self.closed = 1
|
||||||
|
|
||||||
if exited
|
if self.exited
|
||||||
let job = ch_getjob(a:ch)
|
let job = ch_getjob(a:ch)
|
||||||
call Complete(job, exit_status, messages)
|
call self.complete(job, self.exit_status, self.messages)
|
||||||
call s:show_errors(job, exit_status, messages)
|
call self.show_errors(job, self.exit_status, self.messages)
|
||||||
endif
|
endif
|
||||||
endfunction
|
endfunction
|
||||||
|
" explicitly bind close_cb to state so that within it, self will
|
||||||
|
" always refer to state. See :help Partial for more information.
|
||||||
|
let cbs.close_cb = function('s:close_cb', [], state)
|
||||||
|
|
||||||
function! s:show_errors(job, exit_status, data) closure
|
function state.show_errors(job, exit_status, data)
|
||||||
let l:listtype = go#list#Type(for)
|
let l:listtype = go#list#Type(self.for)
|
||||||
if a:exit_status == 0
|
if a:exit_status == 0
|
||||||
call go#list#Clean(l:listtype)
|
call go#list#Clean(l:listtype)
|
||||||
call go#list#Window(l:listtype)
|
|
||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
|
|
||||||
let l:listtype = go#list#Type(for)
|
let l:listtype = go#list#Type(self.for)
|
||||||
if len(a:data) == 0
|
if len(a:data) == 0
|
||||||
call go#list#Clean(l:listtype)
|
call go#list#Clean(l:listtype)
|
||||||
call go#list#Window(l:listtype)
|
|
||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
let out = join(self.messages, "\n")
|
||||||
|
|
||||||
let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd '
|
let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd '
|
||||||
try
|
try
|
||||||
execute cd jobdir
|
" parse the errors relative to self.jobdir
|
||||||
let errors = go#tool#ParseErrors(a:data)
|
execute cd self.jobdir
|
||||||
let errors = go#tool#FilterValids(errors)
|
call go#list#ParseFormat(l:listtype, self.errorformat, out, self.for)
|
||||||
|
let errors = go#list#Get(l:listtype)
|
||||||
finally
|
finally
|
||||||
execute cd . fnameescape(dir)
|
execute cd . fnameescape(self.dir)
|
||||||
endtry
|
endtry
|
||||||
|
|
||||||
|
|
||||||
if empty(errors)
|
if empty(errors)
|
||||||
" failed to parse errors, output the original content
|
" failed to parse errors, output the original content
|
||||||
call go#util#EchoError(messages + [dir])
|
call go#util#EchoError(self.messages + [self.dir])
|
||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if winnr == winnr()
|
if self.winnr == winnr()
|
||||||
call go#list#Populate(l:listtype, errors, join(args))
|
|
||||||
call go#list#Window(l:listtype, len(errors))
|
call go#list#Window(l:listtype, len(errors))
|
||||||
if !bang
|
if !self.bang
|
||||||
call go#list#JumpToFirst(l:listtype)
|
call go#list#JumpToFirst(l:listtype)
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
|
@ -62,6 +62,7 @@ function! s:spawn(bang, desc, for, args) abort
|
||||||
\ 'status_dir' : status_dir,
|
\ 'status_dir' : status_dir,
|
||||||
\ 'started_at' : started_at,
|
\ 'started_at' : started_at,
|
||||||
\ 'for' : a:for,
|
\ 'for' : a:for,
|
||||||
|
\ 'errorformat': &errorformat,
|
||||||
\ }
|
\ }
|
||||||
|
|
||||||
" execute go build in the files directory
|
" execute go build in the files directory
|
||||||
|
@ -125,7 +126,6 @@ function! s:on_exit(job_id, exit_status, event) dict abort
|
||||||
let l:listtype = go#list#Type(self.for)
|
let l:listtype = go#list#Type(self.for)
|
||||||
if a:exit_status == 0
|
if a:exit_status == 0
|
||||||
call go#list#Clean(l:listtype)
|
call go#list#Clean(l:listtype)
|
||||||
call go#list#Window(l:listtype)
|
|
||||||
|
|
||||||
let self.state = "SUCCESS"
|
let self.state = "SUCCESS"
|
||||||
|
|
||||||
|
@ -143,8 +143,9 @@ function! s:on_exit(job_id, exit_status, event) dict abort
|
||||||
call go#util#EchoError("[" . self.status_type . "] FAILED")
|
call go#util#EchoError("[" . self.status_type . "] FAILED")
|
||||||
endif
|
endif
|
||||||
|
|
||||||
let errors = go#tool#ParseErrors(std_combined)
|
" parse the errors relative to self.jobdir
|
||||||
let errors = go#tool#FilterValids(errors)
|
call go#list#ParseFormat(l:listtype, self.errorformat, std_combined, self.for)
|
||||||
|
let errors = go#list#Get(l:listtype)
|
||||||
|
|
||||||
execute cd . fnameescape(dir)
|
execute cd . fnameescape(dir)
|
||||||
|
|
||||||
|
@ -156,7 +157,6 @@ function! s:on_exit(job_id, exit_status, event) dict abort
|
||||||
|
|
||||||
" if we are still in the same windows show the list
|
" if we are still in the same windows show the list
|
||||||
if self.winnr == winnr()
|
if self.winnr == winnr()
|
||||||
call go#list#Populate(l:listtype, errors, self.desc)
|
|
||||||
call go#list#Window(l:listtype, len(errors))
|
call go#list#Window(l:listtype, len(errors))
|
||||||
if !empty(errors) && !self.bang
|
if !empty(errors) && !self.bang
|
||||||
call go#list#JumpToFirst(l:listtype)
|
call go#list#JumpToFirst(l:listtype)
|
||||||
|
|
|
@ -105,7 +105,6 @@ function! go#lint#Gometa(autosave, ...) abort
|
||||||
|
|
||||||
if l:err == 0
|
if l:err == 0
|
||||||
call go#list#Clean(l:listtype)
|
call go#list#Clean(l:listtype)
|
||||||
call go#list#Window(l:listtype)
|
|
||||||
echon "vim-go: " | echohl Function | echon "[metalinter] PASS" | echohl None
|
echon "vim-go: " | echohl Function | echon "[metalinter] PASS" | echohl None
|
||||||
else
|
else
|
||||||
" GoMetaLinter can output one of the two, so we look for both:
|
" GoMetaLinter can output one of the two, so we look for both:
|
||||||
|
@ -147,7 +146,7 @@ function! go#lint#Golint(...) abort
|
||||||
endif
|
endif
|
||||||
|
|
||||||
let l:listtype = go#list#Type("GoLint")
|
let l:listtype = go#list#Type("GoLint")
|
||||||
call go#list#Parse(l:listtype, out)
|
call go#list#Parse(l:listtype, out, "GoLint")
|
||||||
let errors = go#list#Get(l:listtype)
|
let errors = go#list#Get(l:listtype)
|
||||||
call go#list#Window(l:listtype, len(errors))
|
call go#list#Window(l:listtype, len(errors))
|
||||||
call go#list#JumpToFirst(l:listtype)
|
call go#list#JumpToFirst(l:listtype)
|
||||||
|
@ -166,8 +165,9 @@ function! go#lint#Vet(bang, ...) abort
|
||||||
|
|
||||||
let l:listtype = go#list#Type("GoVet")
|
let l:listtype = go#list#Type("GoVet")
|
||||||
if go#util#ShellError() != 0
|
if go#util#ShellError() != 0
|
||||||
let errors = go#tool#ParseErrors(split(out, '\n'))
|
let errorformat="%-Gexit status %\\d%\\+," . &errorformat
|
||||||
call go#list#Populate(l:listtype, errors, 'Vet')
|
call go#list#ParseFormat(l:listtype, l:errorformat, out, "GoVet")
|
||||||
|
let errors = go#list#Get(l:listtype)
|
||||||
call go#list#Window(l:listtype, len(errors))
|
call go#list#Window(l:listtype, len(errors))
|
||||||
if !empty(errors) && !a:bang
|
if !empty(errors) && !a:bang
|
||||||
call go#list#JumpToFirst(l:listtype)
|
call go#list#JumpToFirst(l:listtype)
|
||||||
|
@ -175,7 +175,6 @@ function! go#lint#Vet(bang, ...) abort
|
||||||
echon "vim-go: " | echohl ErrorMsg | echon "[vet] FAIL" | echohl None
|
echon "vim-go: " | echohl ErrorMsg | echon "[vet] FAIL" | echohl None
|
||||||
else
|
else
|
||||||
call go#list#Clean(l:listtype)
|
call go#list#Clean(l:listtype)
|
||||||
call go#list#Window(l:listtype)
|
|
||||||
redraw | echon "vim-go: " | echohl Function | echon "[vet] PASS" | echohl None
|
redraw | echon "vim-go: " | echohl Function | echon "[vet] PASS" | echohl None
|
||||||
endif
|
endif
|
||||||
endfunction
|
endfunction
|
||||||
|
@ -228,7 +227,6 @@ function! go#lint#Errcheck(...) abort
|
||||||
endif
|
endif
|
||||||
else
|
else
|
||||||
call go#list#Clean(l:listtype)
|
call go#list#Clean(l:listtype)
|
||||||
call go#list#Window(l:listtype)
|
|
||||||
echon "vim-go: " | echohl Function | echon "[errcheck] PASS" | echohl None
|
echon "vim-go: " | echohl Function | echon "[errcheck] PASS" | echohl None
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
@ -246,10 +244,18 @@ function! go#lint#ToggleMetaLinterAutoSave() abort
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! s:lint_job(args, autosave)
|
function! s:lint_job(args, autosave)
|
||||||
let status_dir = expand('%:p:h')
|
let state = {
|
||||||
let started_at = reltime()
|
\ 'status_dir': expand('%:p:h'),
|
||||||
|
\ 'started_at': reltime(),
|
||||||
|
\ 'messages': [],
|
||||||
|
\ 'exited': 0,
|
||||||
|
\ 'closed': 0,
|
||||||
|
\ 'exit_status': 0,
|
||||||
|
\ 'winnr': winnr(),
|
||||||
|
\ 'autosave': a:autosave
|
||||||
|
\ }
|
||||||
|
|
||||||
call go#statusline#Update(status_dir, {
|
call go#statusline#Update(state.status_dir, {
|
||||||
\ 'desc': "current status",
|
\ 'desc': "current status",
|
||||||
\ 'type': "gometalinter",
|
\ 'type': "gometalinter",
|
||||||
\ 'state': "analysing",
|
\ 'state': "analysing",
|
||||||
|
@ -259,26 +265,18 @@ function! s:lint_job(args, autosave)
|
||||||
call go#cmd#autowrite()
|
call go#cmd#autowrite()
|
||||||
|
|
||||||
if a:autosave
|
if a:autosave
|
||||||
let l:listtype = go#list#Type("GoMetaLinterAutoSave")
|
let state.listtype = go#list#Type("GoMetaLinterAutoSave")
|
||||||
else
|
else
|
||||||
let l:listtype = go#list#Type("GoMetaLinter")
|
let state.listtype = go#list#Type("GoMetaLinter")
|
||||||
endif
|
endif
|
||||||
|
|
||||||
let l:errformat = '%f:%l:%c:%t%*[^:]:\ %m,%f:%l::%t%*[^:]:\ %m'
|
function! s:callback(chan, msg) dict closure
|
||||||
|
call add(self.messages, a:msg)
|
||||||
let l:messages = []
|
|
||||||
let l:exited = 0
|
|
||||||
let l:closed = 0
|
|
||||||
let l:exit_status = 0
|
|
||||||
let l:winnr = winnr()
|
|
||||||
|
|
||||||
function! s:callback(chan, msg) closure
|
|
||||||
call add(messages, a:msg)
|
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! s:exit_cb(job, exitval) closure
|
function! s:exit_cb(job, exitval) dict
|
||||||
let exited = 1
|
let self.exited = 1
|
||||||
let exit_status = a:exitval
|
let self.exit_status = a:exitval
|
||||||
|
|
||||||
let status = {
|
let status = {
|
||||||
\ 'desc': 'last status',
|
\ 'desc': 'last status',
|
||||||
|
@ -290,50 +288,63 @@ function! s:lint_job(args, autosave)
|
||||||
let status.state = "failed"
|
let status.state = "failed"
|
||||||
endif
|
endif
|
||||||
|
|
||||||
let elapsed_time = reltimestr(reltime(started_at))
|
let elapsed_time = reltimestr(reltime(self.started_at))
|
||||||
" strip whitespace
|
" strip whitespace
|
||||||
let elapsed_time = substitute(elapsed_time, '^\s*\(.\{-}\)\s*$', '\1', '')
|
let elapsed_time = substitute(elapsed_time, '^\s*\(.\{-}\)\s*$', '\1', '')
|
||||||
let status.state .= printf(" (%ss)", elapsed_time)
|
let status.state .= printf(" (%ss)", elapsed_time)
|
||||||
|
|
||||||
call go#statusline#Update(status_dir, status)
|
call go#statusline#Update(self.status_dir, status)
|
||||||
|
|
||||||
if closed
|
if self.closed
|
||||||
call s:show_errors()
|
call self.show_errors()
|
||||||
endif
|
endif
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! s:close_cb(ch) closure
|
function! s:close_cb(ch) dict
|
||||||
let closed = 1
|
let self.closed = 1
|
||||||
|
|
||||||
if exited
|
if self.exited
|
||||||
call s:show_errors()
|
call self.show_errors()
|
||||||
endif
|
endif
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
function! s:show_errors() closure
|
function state.show_errors()
|
||||||
|
let l:winnr = winnr()
|
||||||
|
|
||||||
" make sure the current window is the window from which gometalinter was
|
" make sure the current window is the window from which gometalinter was
|
||||||
" run when the listtype is locationlist so that the location list for the
|
" run when the listtype is locationlist so that the location list for the
|
||||||
" correct window will be populated.
|
" correct window will be populated.
|
||||||
if l:listtype == 'locationlist'
|
if self.listtype == 'locationlist'
|
||||||
exe l:winnr . "wincmd w"
|
exe self.winnr . "wincmd w"
|
||||||
endif
|
endif
|
||||||
|
|
||||||
let l:errorformat = '%f:%l:%c:%t%*[^:]:\ %m,%f:%l::%t%*[^:]:\ %m'
|
let l:errorformat = '%f:%l:%c:%t%*[^:]:\ %m,%f:%l::%t%*[^:]:\ %m'
|
||||||
call go#list#ParseFormat(l:listtype, l:errorformat, messages, 'GoMetaLinter')
|
call go#list#ParseFormat(self.listtype, l:errorformat, self.messages, 'GoMetaLinter')
|
||||||
|
|
||||||
let errors = go#list#Get(l:listtype)
|
let errors = go#list#Get(self.listtype)
|
||||||
call go#list#Window(l:listtype, len(errors))
|
call go#list#Window(self.listtype, len(errors))
|
||||||
|
|
||||||
|
" move to the window that was active before processing the errors, because
|
||||||
|
" the user may have moved around within the window or even moved to a
|
||||||
|
" different window since saving. Moving back to current window as of the
|
||||||
|
" start of this function avoids the perception that the quickfix window
|
||||||
|
" steals focus when linting takes a while.
|
||||||
|
if self.autosave
|
||||||
|
exe l:winnr . "wincmd w"
|
||||||
|
endif
|
||||||
|
|
||||||
if get(g:, 'go_echo_command_info', 1)
|
if get(g:, 'go_echo_command_info', 1)
|
||||||
call go#util#EchoSuccess("linting finished")
|
call go#util#EchoSuccess("linting finished")
|
||||||
endif
|
endif
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
" explicitly bind the callbacks to state so that self within them always
|
||||||
|
" refers to state. See :help Partial for more information.
|
||||||
let start_options = {
|
let start_options = {
|
||||||
\ 'callback': funcref("s:callback"),
|
\ 'callback': funcref("s:callback", [], state),
|
||||||
\ 'exit_cb': funcref("s:exit_cb"),
|
\ 'exit_cb': funcref("s:exit_cb", [], state),
|
||||||
\ 'close_cb': funcref("s:close_cb"),
|
\ 'close_cb': funcref("s:close_cb", [], state),
|
||||||
\ }
|
\ }
|
||||||
|
|
||||||
call job_start(a:args.cmd, start_options)
|
call job_start(a:args.cmd, start_options)
|
||||||
|
|
|
@ -3,7 +3,7 @@ func! Test_Gometa() abort
|
||||||
silent exe 'e ' . $GOPATH . '/src/lint/lint.go'
|
silent exe 'e ' . $GOPATH . '/src/lint/lint.go'
|
||||||
|
|
||||||
let expected = [
|
let expected = [
|
||||||
\ {'lnum': 5, 'bufnr': 3, 'col': 1, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': 'w', 'pattern': '', 'text': 'exported function MissingFooDoc should have comment or be unexported (golint)'}
|
\ {'lnum': 5, 'bufnr': bufnr('%')+1, 'col': 1, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': 'w', 'pattern': '', 'text': 'exported function MissingFooDoc should have comment or be unexported (golint)'}
|
||||||
\ ]
|
\ ]
|
||||||
|
|
||||||
" clear the quickfix lists
|
" clear the quickfix lists
|
||||||
|
@ -37,7 +37,7 @@ func! Test_GometaWithDisabled() abort
|
||||||
silent exe 'e ' . $GOPATH . '/src/lint/lint.go'
|
silent exe 'e ' . $GOPATH . '/src/lint/lint.go'
|
||||||
|
|
||||||
let expected = [
|
let expected = [
|
||||||
\ {'lnum': 5, 'bufnr': 3, 'col': 1, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': 'w', 'pattern': '', 'text': 'exported function MissingFooDoc should have comment or be unexported (golint)'}
|
\ {'lnum': 5, 'bufnr': bufnr('%')+1, 'col': 1, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': 'w', 'pattern': '', 'text': 'exported function MissingFooDoc should have comment or be unexported (golint)'}
|
||||||
\ ]
|
\ ]
|
||||||
|
|
||||||
" clear the quickfix lists
|
" clear the quickfix lists
|
||||||
|
@ -71,7 +71,7 @@ func! Test_GometaAutoSave() abort
|
||||||
silent exe 'e ' . $GOPATH . '/src/lint/lint.go'
|
silent exe 'e ' . $GOPATH . '/src/lint/lint.go'
|
||||||
|
|
||||||
let expected = [
|
let expected = [
|
||||||
\ {'lnum': 5, 'bufnr': 2, 'col': 1, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': 'w', 'pattern': '', 'text': 'exported function MissingDoc should have comment or be unexported (golint)'}
|
\ {'lnum': 5, 'bufnr': bufnr('%'), 'col': 1, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': 'w', 'pattern': '', 'text': 'exported function MissingDoc should have comment or be unexported (golint)'}
|
||||||
\ ]
|
\ ]
|
||||||
|
|
||||||
let winnr = winnr()
|
let winnr = winnr()
|
||||||
|
@ -102,4 +102,30 @@ func! Test_GometaAutoSave() abort
|
||||||
let g:go_metalinter_autosave_enabled = orig_go_metalinter_autosave_enabled
|
let g:go_metalinter_autosave_enabled = orig_go_metalinter_autosave_enabled
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
func! Test_Vet()
|
||||||
|
let $GOPATH = fnameescape(fnamemodify(getcwd(), ':p')) . 'test-fixtures/lint'
|
||||||
|
silent exe 'e ' . $GOPATH . '/src/vet/vet.go'
|
||||||
|
compiler go
|
||||||
|
|
||||||
|
let expected = [
|
||||||
|
\ {'lnum': 7, 'bufnr': bufnr('%'), 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'arg str for printf verb %d of wrong type: string'}
|
||||||
|
\ ]
|
||||||
|
|
||||||
|
let winnr = winnr()
|
||||||
|
|
||||||
|
" clear the location lists
|
||||||
|
call setqflist([], 'r')
|
||||||
|
|
||||||
|
call go#lint#Vet(1)
|
||||||
|
|
||||||
|
let actual = getqflist()
|
||||||
|
let start = reltime()
|
||||||
|
while len(actual) == 0 && reltimefloat(reltime(start)) < 10
|
||||||
|
sleep 100m
|
||||||
|
let actual = getqflist()
|
||||||
|
endwhile
|
||||||
|
|
||||||
|
call gotest#assert_quickfix(actual, expected)
|
||||||
|
endfunc
|
||||||
|
|
||||||
" vim: sw=2 ts=2 et
|
" vim: sw=2 ts=2 et
|
||||||
|
|
|
@ -18,14 +18,7 @@ function! go#list#Window(listtype, ...) abort
|
||||||
" location list increases/decreases, cwindow will not resize when a new
|
" location list increases/decreases, cwindow will not resize when a new
|
||||||
" updated height is passed. lopen in the other hand resizes the screen.
|
" updated height is passed. lopen in the other hand resizes the screen.
|
||||||
if !a:0 || a:1 == 0
|
if !a:0 || a:1 == 0
|
||||||
let autoclose_window = get(g:, 'go_list_autoclose', 1)
|
call go#list#Close(a:listtype)
|
||||||
if autoclose_window
|
|
||||||
if a:listtype == "locationlist"
|
|
||||||
lclose
|
|
||||||
else
|
|
||||||
cclose
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
@ -79,13 +72,7 @@ function! go#list#ParseFormat(listtype, errformat, items, title) abort
|
||||||
" parse and populate the location list
|
" parse and populate the location list
|
||||||
let &errorformat = a:errformat
|
let &errorformat = a:errformat
|
||||||
try
|
try
|
||||||
if a:listtype == "locationlist"
|
call go#list#Parse(a:listtype, a:items, a:title)
|
||||||
lgetexpr a:items
|
|
||||||
if has("patch-7.4.2200") | call setloclist(0, [], 'a', {'title': a:title}) | endif
|
|
||||||
else
|
|
||||||
cgetexpr a:items
|
|
||||||
if has("patch-7.4.2200") | call setqflist([], 'a', {'title': a:title}) | endif
|
|
||||||
endif
|
|
||||||
finally
|
finally
|
||||||
"restore back
|
"restore back
|
||||||
let &errorformat = old_errorformat
|
let &errorformat = old_errorformat
|
||||||
|
@ -94,11 +81,13 @@ endfunction
|
||||||
|
|
||||||
" Parse parses the given items based on the global errorformat and
|
" Parse parses the given items based on the global errorformat and
|
||||||
" populates the list.
|
" populates the list.
|
||||||
function! go#list#Parse(listtype, items) abort
|
function! go#list#Parse(listtype, items, title) abort
|
||||||
if a:listtype == "locationlist"
|
if a:listtype == "locationlist"
|
||||||
lgetexpr a:items
|
lgetexpr a:items
|
||||||
|
if has("patch-7.4.2200") | call setloclist(0, [], 'a', {'title': a:title}) | endif
|
||||||
else
|
else
|
||||||
cgetexpr a:items
|
cgetexpr a:items
|
||||||
|
if has("patch-7.4.2200") | call setqflist([], 'a', {'title': a:title}) | endif
|
||||||
endif
|
endif
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
@ -111,13 +100,29 @@ function! go#list#JumpToFirst(listtype) abort
|
||||||
endif
|
endif
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
" Clean cleans the location list
|
" Clean cleans and closes the location list
|
||||||
function! go#list#Clean(listtype) abort
|
function! go#list#Clean(listtype) abort
|
||||||
if a:listtype == "locationlist"
|
if a:listtype == "locationlist"
|
||||||
lex []
|
lex []
|
||||||
else
|
else
|
||||||
cex []
|
cex []
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
call go#list#Close(a:listtype)
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" Close closes the location list
|
||||||
|
function! go#list#Close(listtype) abort
|
||||||
|
let autoclose_window = get(g:, 'go_list_autoclose', 1)
|
||||||
|
if !autoclose_window
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
if a:listtype == "locationlist"
|
||||||
|
lclose
|
||||||
|
else
|
||||||
|
cclose
|
||||||
|
endif
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! s:listtype(listtype) abort
|
function! s:listtype(listtype) abort
|
||||||
|
|
|
@ -54,8 +54,14 @@ function! go#package#Paths() abort
|
||||||
return dirs
|
return dirs
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
let s:import_paths = {}
|
||||||
" ImportPath returns the import path in the current directory it was executed
|
" ImportPath returns the import path in the current directory it was executed
|
||||||
function! go#package#ImportPath() abort
|
function! go#package#ImportPath() abort
|
||||||
|
let dir = expand("%:p:h")
|
||||||
|
if has_key(s:import_paths, dir)
|
||||||
|
return s:import_paths[dir]
|
||||||
|
endif
|
||||||
|
|
||||||
let out = go#tool#ExecuteInDir("go list")
|
let out = go#tool#ExecuteInDir("go list")
|
||||||
if go#util#ShellError() != 0
|
if go#util#ShellError() != 0
|
||||||
return -1
|
return -1
|
||||||
|
@ -69,6 +75,8 @@ function! go#package#ImportPath() abort
|
||||||
return -1
|
return -1
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
let s:import_paths[dir] = import_path
|
||||||
|
|
||||||
return import_path
|
return import_path
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
|
@ -72,20 +72,22 @@ function! go#rename#Rename(bang, ...) abort
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function s:rename_job(args)
|
function s:rename_job(args)
|
||||||
let exited = 0
|
let state = {
|
||||||
let closed = 0
|
\ 'exited': 0,
|
||||||
let exitval = 0
|
\ 'closed': 0,
|
||||||
let messages = []
|
\ 'exitval': 0,
|
||||||
|
\ 'messages': [],
|
||||||
|
\ 'status_dir': expand('%:p:h'),
|
||||||
|
\ 'bang': a:args.bang
|
||||||
|
\ }
|
||||||
|
|
||||||
function! s:callback(chan, msg) closure
|
function! s:callback(chan, msg) dict
|
||||||
call add(messages, a:msg)
|
call add(self.messages, a:msg)
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
let status_dir = expand('%:p:h')
|
function! s:exit_cb(job, exitval) dict
|
||||||
|
let self.exited = 1
|
||||||
function! s:exit_cb(job, exitval) closure
|
let self.exitval = a:exitval
|
||||||
let exited = 1
|
|
||||||
let exitval = a:exitval
|
|
||||||
|
|
||||||
let status = {
|
let status = {
|
||||||
\ 'desc': 'last status',
|
\ 'desc': 'last status',
|
||||||
|
@ -97,28 +99,30 @@ function s:rename_job(args)
|
||||||
let status.state = "failed"
|
let status.state = "failed"
|
||||||
endif
|
endif
|
||||||
|
|
||||||
call go#statusline#Update(status_dir, status)
|
call go#statusline#Update(self.status_dir, status)
|
||||||
|
|
||||||
if closed
|
if self.closed
|
||||||
call s:parse_errors(a:exitval, a:args.bang, messages)
|
call s:parse_errors(self.exitval, self.bang, self.messages)
|
||||||
endif
|
endif
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! s:close_cb(ch) closure
|
function! s:close_cb(ch) dict
|
||||||
let closed = 1
|
let self.closed = 1
|
||||||
|
|
||||||
if exited
|
if self.exited
|
||||||
call s:parse_errors(exitval, a:args.bang, messages)
|
call s:parse_errors(self.exitval, self.bang, self.messages)
|
||||||
endif
|
endif
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
" explicitly bind the callbacks to state so that self within them always
|
||||||
|
" refers to state. See :help Partial for more information.
|
||||||
let start_options = {
|
let start_options = {
|
||||||
\ 'callback': funcref("s:callback"),
|
\ 'callback': funcref("s:callback", [], state),
|
||||||
\ 'exit_cb': funcref("s:exit_cb"),
|
\ 'exit_cb': funcref("s:exit_cb", [], state),
|
||||||
\ 'close_cb': funcref("s:close_cb"),
|
\ 'close_cb': funcref("s:close_cb", [], state),
|
||||||
\ }
|
\ }
|
||||||
|
|
||||||
call go#statusline#Update(status_dir, {
|
call go#statusline#Update(state.status_dir, {
|
||||||
\ 'desc': "current status",
|
\ 'desc': "current status",
|
||||||
\ 'type': "gorename",
|
\ 'type': "gorename",
|
||||||
\ 'state': "started",
|
\ 'state': "started",
|
||||||
|
@ -156,7 +160,6 @@ function s:parse_errors(exit_val, bang, out)
|
||||||
" strip out newline on the end that gorename puts. If we don't remove, it
|
" strip out newline on the end that gorename puts. If we don't remove, it
|
||||||
" will trigger the 'Hit ENTER to continue' prompt
|
" will trigger the 'Hit ENTER to continue' prompt
|
||||||
call go#list#Clean(l:listtype)
|
call go#list#Clean(l:listtype)
|
||||||
call go#list#Window(l:listtype)
|
|
||||||
call go#util#EchoSuccess(a:out[0])
|
call go#util#EchoSuccess(a:out[0])
|
||||||
|
|
||||||
" refresh the buffer so we can see the new content
|
" refresh the buffer so we can see the new content
|
||||||
|
|
|
@ -24,7 +24,7 @@ function! go#template#create() abort
|
||||||
let l:template_file = get(g:, 'go_template_file', "hello_world.go")
|
let l:template_file = get(g:, 'go_template_file', "hello_world.go")
|
||||||
endif
|
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)
|
||||||
silent exe '0r ' . fnameescape(l:template_path)
|
silent exe 'keepalt 0r ' . fnameescape(l:template_path)
|
||||||
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')
|
||||||
|
|
|
@ -2,9 +2,6 @@ if has('nvim') && !exists("g:go_term_mode")
|
||||||
let g:go_term_mode = 'vsplit'
|
let g:go_term_mode = 'vsplit'
|
||||||
endif
|
endif
|
||||||
|
|
||||||
" s:jobs is a global reference to all jobs started with new()
|
|
||||||
let s:jobs = {}
|
|
||||||
|
|
||||||
" new creates a new terminal with the given command. Mode is set based on the
|
" new creates a new terminal with the given command. Mode is set based on the
|
||||||
" global variable g:go_term_mode, which is by default set to :vsplit
|
" global variable g:go_term_mode, which is by default set to :vsplit
|
||||||
function! go#term#new(bang, cmd) abort
|
function! go#term#new(bang, cmd) abort
|
||||||
|
@ -18,8 +15,14 @@ function! go#term#newmode(bang, cmd, mode) abort
|
||||||
let mode = g:go_term_mode
|
let mode = g:go_term_mode
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
let state = {
|
||||||
|
\ 'cmd': a:cmd,
|
||||||
|
\ 'bang' : a:bang,
|
||||||
|
\ 'winid': win_getid(winnr()),
|
||||||
|
\ 'stdout': []
|
||||||
|
\ }
|
||||||
|
|
||||||
" 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()
|
||||||
|
|
||||||
|
@ -33,30 +36,27 @@ function! go#term#newmode(bang, cmd, mode) abort
|
||||||
setlocal noswapfile
|
setlocal noswapfile
|
||||||
setlocal nobuflisted
|
setlocal nobuflisted
|
||||||
|
|
||||||
|
" explicitly bind callbacks to state so that within them, self will always
|
||||||
|
" refer to state. See :help Partial for more information.
|
||||||
|
"
|
||||||
|
" Don't set an on_stderr, because it will be passed the same data as
|
||||||
|
" on_stdout. See https://github.com/neovim/neovim/issues/2836
|
||||||
let job = {
|
let job = {
|
||||||
\ 'stderr' : [],
|
\ 'on_stdout': function('s:on_stdout', [], state),
|
||||||
\ 'stdout' : [],
|
\ 'on_exit' : function('s:on_exit', [], state),
|
||||||
\ 'bang' : a:bang,
|
|
||||||
\ 'on_stdout': function('s:on_stdout'),
|
|
||||||
\ 'on_stderr': function('s:on_stderr'),
|
|
||||||
\ 'on_exit' : function('s:on_exit'),
|
|
||||||
\ }
|
\ }
|
||||||
|
|
||||||
let id = termopen(a:cmd, job)
|
let state.id = termopen(a:cmd, job)
|
||||||
|
let state.termwinid = win_getid(winnr())
|
||||||
|
|
||||||
execute cd . fnameescape(dir)
|
execute cd . fnameescape(dir)
|
||||||
|
|
||||||
let job.id = id
|
|
||||||
let job.cmd = a:cmd
|
|
||||||
startinsert
|
|
||||||
|
|
||||||
" resize new term if needed.
|
" resize new term if needed.
|
||||||
let height = get(g:, 'go_term_height', winheight(0))
|
let height = get(g:, 'go_term_height', winheight(0))
|
||||||
let width = get(g:, 'go_term_width', winwidth(0))
|
let width = get(g:, 'go_term_width', winwidth(0))
|
||||||
|
|
||||||
" we are careful how to resize. for example it's vsplit we don't change
|
" Adjust the window width or height depending on whether it's a vertical or
|
||||||
" the height. The below command resizes the buffer
|
" horizontal split.
|
||||||
|
|
||||||
if mode =~ "vertical" || mode =~ "vsplit" || mode =~ "vnew"
|
if mode =~ "vertical" || mode =~ "vsplit" || mode =~ "vnew"
|
||||||
exe 'vertical resize ' . width
|
exe 'vertical resize ' . width
|
||||||
elseif mode =~ "split" || mode =~ "new"
|
elseif mode =~ "split" || mode =~ "new"
|
||||||
|
@ -64,77 +64,56 @@ function! go#term#newmode(bang, cmd, mode) abort
|
||||||
endif
|
endif
|
||||||
|
|
||||||
" we also need to resize the pty, so there you go...
|
" we also need to resize the pty, so there you go...
|
||||||
call jobresize(id, width, height)
|
call jobresize(state.id, width, height)
|
||||||
|
|
||||||
let s:jobs[id] = job
|
call win_gotoid(state.winid)
|
||||||
stopinsert
|
|
||||||
|
|
||||||
if l:winnr !=# winnr()
|
return state.id
|
||||||
exe l:winnr . "wincmd w"
|
|
||||||
endif
|
|
||||||
|
|
||||||
return id
|
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! s:on_stdout(job_id, data, event) dict abort
|
function! s:on_stdout(job_id, data, event) dict abort
|
||||||
if !has_key(s:jobs, a:job_id)
|
call extend(self.stdout, a:data)
|
||||||
return
|
|
||||||
endif
|
|
||||||
let job = s:jobs[a:job_id]
|
|
||||||
|
|
||||||
call extend(job.stdout, a:data)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function! s:on_stderr(job_id, data, event) dict abort
|
|
||||||
if !has_key(s:jobs, a:job_id)
|
|
||||||
return
|
|
||||||
endif
|
|
||||||
let job = s:jobs[a:job_id]
|
|
||||||
|
|
||||||
call extend(job.stderr, a:data)
|
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! s:on_exit(job_id, exit_status, event) dict abort
|
function! s:on_exit(job_id, exit_status, event) dict abort
|
||||||
if !has_key(s:jobs, a:job_id)
|
|
||||||
return
|
|
||||||
endif
|
|
||||||
let job = s:jobs[a:job_id]
|
|
||||||
|
|
||||||
let l:listtype = go#list#Type("_term")
|
let l:listtype = go#list#Type("_term")
|
||||||
|
|
||||||
" usually there is always output so never branch into this clause
|
" usually there is always output so never branch into this clause
|
||||||
if empty(job.stdout)
|
if empty(self.stdout)
|
||||||
call go#list#Clean(l:listtype)
|
call s:cleanlist(self.winid, l:listtype)
|
||||||
call go#list#Window(l:listtype)
|
|
||||||
unlet s:jobs[a:job_id]
|
|
||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
|
|
||||||
let errors = go#tool#ParseErrors(job.stdout)
|
let errors = go#tool#ParseErrors(self.stdout)
|
||||||
let errors = go#tool#FilterValids(errors)
|
let errors = go#tool#FilterValids(errors)
|
||||||
|
|
||||||
if !empty(errors)
|
if !empty(errors)
|
||||||
" close terminal we don't need it anymore
|
" close terminal; we don't need it anymore
|
||||||
|
call win_gotoid(self.termwinid)
|
||||||
close
|
close
|
||||||
|
|
||||||
call go#list#Populate(l:listtype, errors, job.cmd)
|
call win_gotoid(self.winid)
|
||||||
|
|
||||||
|
call go#list#Populate(l:listtype, errors, self.cmd)
|
||||||
call go#list#Window(l:listtype, len(errors))
|
call go#list#Window(l:listtype, len(errors))
|
||||||
if !self.bang
|
if !self.bang
|
||||||
call go#list#JumpToFirst(l:listtype)
|
call go#list#JumpToFirst(l:listtype)
|
||||||
endif
|
endif
|
||||||
unlet s:jobs[a:job_id]
|
|
||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
|
|
||||||
" tests are passing clean the list and close the list. But we only can
|
call s:cleanlist(self.winid, l:listtype)
|
||||||
" close them from a normal view, so jump back, close the list and then
|
endfunction
|
||||||
" again jump back to the terminal
|
|
||||||
wincmd p
|
|
||||||
call go#list#Clean(l:listtype)
|
|
||||||
call go#list#Window(l:listtype)
|
|
||||||
wincmd p
|
|
||||||
|
|
||||||
unlet s:jobs[a:job_id]
|
function! s:cleanlist(winid, listtype) abort
|
||||||
|
" There are no errors. Clean and close the list. Jump to the window to which
|
||||||
|
" the location list is attached, close the list, and then jump back to the
|
||||||
|
" current window.
|
||||||
|
let winid = win_getid(winnr())
|
||||||
|
call win_gotoid(a:winid)
|
||||||
|
call go#list#Clean(a:listtype)
|
||||||
|
call win_gotoid(l:winid)
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
" vim: sw=2 ts=2 et
|
" vim: sw=2 ts=2 et
|
||||||
|
|
50
sources_non_forked/vim-go/autoload/go/term_test.vim
Normal file
50
sources_non_forked/vim-go/autoload/go/term_test.vim
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
func! Test_GoTermNewMode()
|
||||||
|
if !has('nvim')
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
try
|
||||||
|
let l:filename = 'term/term.go'
|
||||||
|
let l:tmp = gotest#load_fixture(l:filename)
|
||||||
|
exe 'cd ' . l:tmp . '/src/term'
|
||||||
|
|
||||||
|
let expected = expand('%:p')
|
||||||
|
|
||||||
|
let cmd = "go run ". go#util#Shelljoin(go#tool#Files())
|
||||||
|
|
||||||
|
set nosplitright
|
||||||
|
call go#term#newmode(0, cmd, '')
|
||||||
|
let actual = expand('%:p')
|
||||||
|
call assert_equal(actual, l:expected)
|
||||||
|
|
||||||
|
finally
|
||||||
|
call delete(l:tmp, 'rf')
|
||||||
|
endtry
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
func! Test_GoTermNewMode_SplitRight()
|
||||||
|
if !has('nvim')
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
try
|
||||||
|
let l:filename = 'term/term.go'
|
||||||
|
let l:tmp = gotest#load_fixture(l:filename)
|
||||||
|
exe 'cd ' . l:tmp . '/src/term'
|
||||||
|
|
||||||
|
let expected = expand('%:p')
|
||||||
|
|
||||||
|
let cmd = "go run ". go#util#Shelljoin(go#tool#Files())
|
||||||
|
|
||||||
|
set splitright
|
||||||
|
call go#term#newmode(0, cmd, '')
|
||||||
|
let actual = expand('%:p')
|
||||||
|
call assert_equal(actual, l:expected)
|
||||||
|
|
||||||
|
finally
|
||||||
|
call delete(l:tmp, 'rf')
|
||||||
|
set nosplitright
|
||||||
|
endtry
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
" vim: sw=2 ts=2 et
|
|
@ -0,0 +1,5 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
notafunc()
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
str := "hello world!"
|
||||||
|
fmt.Printf("%d\n", str)
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
println("hello, world")
|
||||||
|
}
|
|
@ -94,7 +94,6 @@ function! go#test#Test(bang, compile, ...) abort
|
||||||
call go#util#EchoError("[test] FAIL")
|
call go#util#EchoError("[test] FAIL")
|
||||||
else
|
else
|
||||||
call go#list#Clean(l:listtype)
|
call go#list#Clean(l:listtype)
|
||||||
call go#list#Window(l:listtype)
|
|
||||||
|
|
||||||
if a:compile
|
if a:compile
|
||||||
call go#util#EchoSuccess("[test] SUCCESS")
|
call go#util#EchoSuccess("[test] SUCCESS")
|
||||||
|
@ -139,9 +138,6 @@ function! go#test#Func(bang, ...) abort
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! s:test_job(args) abort
|
function! s:test_job(args) abort
|
||||||
let status_dir = expand('%:p:h')
|
|
||||||
let started_at = reltime()
|
|
||||||
|
|
||||||
let status = {
|
let status = {
|
||||||
\ 'desc': 'current status',
|
\ 'desc': 'current status',
|
||||||
\ 'type': "test",
|
\ 'type': "test",
|
||||||
|
@ -152,23 +148,29 @@ function! s:test_job(args) abort
|
||||||
let status.state = "compiling"
|
let status.state = "compiling"
|
||||||
endif
|
endif
|
||||||
|
|
||||||
call go#statusline#Update(status_dir, status)
|
|
||||||
|
|
||||||
" autowrite is not enabled for jobs
|
" autowrite is not enabled for jobs
|
||||||
call go#cmd#autowrite()
|
call go#cmd#autowrite()
|
||||||
|
|
||||||
let l:exited = 0
|
let state = {
|
||||||
let l:closed = 0
|
\ 'exited': 0,
|
||||||
let l:exitval = 0
|
\ 'closed': 0,
|
||||||
let messages = []
|
\ 'exitval': 0,
|
||||||
|
\ 'messages': [],
|
||||||
|
\ 'args': a:args,
|
||||||
|
\ 'compile_test': a:args.compile_test,
|
||||||
|
\ 'status_dir': expand('%:p:h'),
|
||||||
|
\ 'started_at': reltime()
|
||||||
|
\ }
|
||||||
|
|
||||||
function! s:callback(chan, msg) closure
|
call go#statusline#Update(state.status_dir, status)
|
||||||
call add(messages, a:msg)
|
|
||||||
|
function! s:callback(chan, msg) dict
|
||||||
|
call add(self.messages, a:msg)
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! s:exit_cb(job, exitval) closure
|
function! s:exit_cb(job, exitval) dict
|
||||||
let exited = 1
|
let self.exited = 1
|
||||||
let exitval = a:exitval
|
let self.exitval = a:exitval
|
||||||
|
|
||||||
let status = {
|
let status = {
|
||||||
\ 'desc': 'last status',
|
\ 'desc': 'last status',
|
||||||
|
@ -176,7 +178,7 @@ function! s:test_job(args) abort
|
||||||
\ 'state': "pass",
|
\ 'state': "pass",
|
||||||
\ }
|
\ }
|
||||||
|
|
||||||
if a:args.compile_test
|
if self.compile_test
|
||||||
let status.state = "success"
|
let status.state = "success"
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
@ -186,7 +188,7 @@ function! s:test_job(args) abort
|
||||||
|
|
||||||
if get(g:, 'go_echo_command_info', 1)
|
if get(g:, 'go_echo_command_info', 1)
|
||||||
if a:exitval == 0
|
if a:exitval == 0
|
||||||
if a:args.compile_test
|
if self.compile_test
|
||||||
call go#util#EchoSuccess("[test] SUCCESS")
|
call go#util#EchoSuccess("[test] SUCCESS")
|
||||||
else
|
else
|
||||||
call go#util#EchoSuccess("[test] PASS")
|
call go#util#EchoSuccess("[test] PASS")
|
||||||
|
@ -196,30 +198,32 @@ function! s:test_job(args) abort
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
let elapsed_time = reltimestr(reltime(started_at))
|
let elapsed_time = reltimestr(reltime(self.started_at))
|
||||||
" strip whitespace
|
" strip whitespace
|
||||||
let elapsed_time = substitute(elapsed_time, '^\s*\(.\{-}\)\s*$', '\1', '')
|
let elapsed_time = substitute(elapsed_time, '^\s*\(.\{-}\)\s*$', '\1', '')
|
||||||
let status.state .= printf(" (%ss)", elapsed_time)
|
let status.state .= printf(" (%ss)", elapsed_time)
|
||||||
|
|
||||||
call go#statusline#Update(status_dir, status)
|
call go#statusline#Update(self.status_dir, status)
|
||||||
|
|
||||||
if closed
|
if self.closed
|
||||||
call s:show_errors(a:args, l:exitval, messages)
|
call s:show_errors(self.args, self.exitval, self.messages)
|
||||||
endif
|
endif
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! s:close_cb(ch) closure
|
function! s:close_cb(ch) dict
|
||||||
let closed = 1
|
let self.closed = 1
|
||||||
|
|
||||||
if exited
|
if self.exited
|
||||||
call s:show_errors(a:args, l:exitval, messages)
|
call s:show_errors(self.args, self.exitval, self.messages)
|
||||||
endif
|
endif
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
" explicitly bind the callbacks to state so that self within them always
|
||||||
|
" refers to state. See :help Partial for more information.
|
||||||
let start_options = {
|
let start_options = {
|
||||||
\ 'callback': funcref("s:callback"),
|
\ 'callback': funcref("s:callback", [], state),
|
||||||
\ 'exit_cb': funcref("s:exit_cb"),
|
\ 'exit_cb': funcref("s:exit_cb", [], state),
|
||||||
\ 'close_cb': funcref("s:close_cb"),
|
\ 'close_cb': funcref("s:close_cb", [], state)
|
||||||
\ }
|
\ }
|
||||||
|
|
||||||
" pre start
|
" pre start
|
||||||
|
@ -241,7 +245,6 @@ function! s:show_errors(args, exit_val, messages) abort
|
||||||
let l:listtype = go#list#Type("GoTest")
|
let l:listtype = go#list#Type("GoTest")
|
||||||
if a:exit_val == 0
|
if a:exit_val == 0
|
||||||
call go#list#Clean(l:listtype)
|
call go#list#Clean(l:listtype)
|
||||||
call go#list#Window(l:listtype)
|
|
||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@ endif
|
||||||
" < >
|
" < >
|
||||||
" t for tag
|
" t for tag
|
||||||
|
|
||||||
|
" Select a function in visual mode.
|
||||||
function! go#textobj#Function(mode) abort
|
function! go#textobj#Function(mode) abort
|
||||||
let offset = go#util#OffsetCursor()
|
let offset = go#util#OffsetCursor()
|
||||||
|
|
||||||
|
@ -98,23 +99,8 @@ function! go#textobj#Function(mode) abort
|
||||||
call cursor(info.rbrace.line-1, 1)
|
call cursor(info.rbrace.line-1, 1)
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! go#textobj#FunctionJump(mode, direction) abort
|
" Get the location of the previous or next function.
|
||||||
" get count of the motion. This should be done before all the normal
|
function! go#textobj#FunctionLocation(direction, cnt) abort
|
||||||
" expressions below as those reset this value(because they have zero
|
|
||||||
" count!). We abstract -1 because the index starts from 0 in motion.
|
|
||||||
let l:cnt = v:count1 - 1
|
|
||||||
|
|
||||||
" set context mark so we can jump back with '' or ``
|
|
||||||
normal! m'
|
|
||||||
|
|
||||||
" select already previously selected visual content and continue from there.
|
|
||||||
" If it's the first time starts with the visual mode. This is needed so
|
|
||||||
" after selecting something in visual mode, every consecutive motion
|
|
||||||
" continues.
|
|
||||||
if a:mode == 'v'
|
|
||||||
normal! gv
|
|
||||||
endif
|
|
||||||
|
|
||||||
let offset = go#util#OffsetCursor()
|
let offset = go#util#OffsetCursor()
|
||||||
|
|
||||||
let fname = shellescape(expand("%:p"))
|
let fname = shellescape(expand("%:p"))
|
||||||
|
@ -131,7 +117,7 @@ function! go#textobj#FunctionJump(mode, direction) abort
|
||||||
endif
|
endif
|
||||||
|
|
||||||
let command = printf("%s -format vim -file %s -offset %s", bin_path, fname, offset)
|
let command = printf("%s -format vim -file %s -offset %s", bin_path, fname, offset)
|
||||||
let command .= ' -shift ' . l:cnt
|
let command .= ' -shift ' . a:cnt
|
||||||
|
|
||||||
if a:direction == 'next'
|
if a:direction == 'next'
|
||||||
let command .= ' -mode next'
|
let command .= ' -mode next'
|
||||||
|
@ -154,9 +140,33 @@ function! go#textobj#FunctionJump(mode, direction) abort
|
||||||
call delete(l:tmpname)
|
call delete(l:tmpname)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
" convert our string dict representation into native Vim dictionary type
|
let l:result = json_decode(out)
|
||||||
let result = eval(out)
|
if type(l:result) != 4 || !has_key(l:result, 'fn')
|
||||||
if type(result) != 4 || !has_key(result, 'fn')
|
return 0
|
||||||
|
endif
|
||||||
|
|
||||||
|
return l:result
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! go#textobj#FunctionJump(mode, direction) abort
|
||||||
|
" get count of the motion. This should be done before all the normal
|
||||||
|
" expressions below as those reset this value(because they have zero
|
||||||
|
" count!). We abstract -1 because the index starts from 0 in motion.
|
||||||
|
let l:cnt = v:count1 - 1
|
||||||
|
|
||||||
|
" set context mark so we can jump back with '' or ``
|
||||||
|
normal! m'
|
||||||
|
|
||||||
|
" select already previously selected visual content and continue from there.
|
||||||
|
" If it's the first time starts with the visual mode. This is needed so
|
||||||
|
" after selecting something in visual mode, every consecutive motion
|
||||||
|
" continues.
|
||||||
|
if a:mode == 'v'
|
||||||
|
normal! gv
|
||||||
|
endif
|
||||||
|
|
||||||
|
let l:result = go#textobj#FunctionLocation(a:direction, l:cnt)
|
||||||
|
if l:result is 0
|
||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
|
@ -330,6 +330,7 @@ function! go#util#EchoWarning(msg)
|
||||||
call s:echo(a:msg, 'WarningMsg')
|
call s:echo(a:msg, 'WarningMsg')
|
||||||
endfunction
|
endfunction
|
||||||
function! go#util#EchoProgress(msg)
|
function! go#util#EchoProgress(msg)
|
||||||
|
redraw
|
||||||
call s:echo(a:msg, 'Identifier')
|
call s:echo(a:msg, 'Identifier')
|
||||||
endfunction
|
endfunction
|
||||||
function! go#util#EchoInfo(msg)
|
function! go#util#EchoInfo(msg)
|
||||||
|
@ -362,7 +363,6 @@ function! go#util#archive()
|
||||||
return expand("%:p:gs!\\!/!") . "\n" . strlen(l:buffer) . "\n" . l:buffer
|
return expand("%:p:gs!\\!/!") . "\n" . strlen(l:buffer) . "\n" . l:buffer
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
" Make a named temporary directory which starts with "prefix".
|
" Make a named temporary directory which starts with "prefix".
|
||||||
"
|
"
|
||||||
" Unfortunately Vim's tempname() is not portable enough across various systems;
|
" Unfortunately Vim's tempname() is not portable enough across various systems;
|
||||||
|
@ -384,7 +384,7 @@ function! go#util#tempdir(prefix) abort
|
||||||
endfor
|
endfor
|
||||||
|
|
||||||
if l:dir == ''
|
if l:dir == ''
|
||||||
echoerr 'Unable to find directory to store temporary directory in'
|
call go#util#EchoError('Unable to find directory to store temporary directory in')
|
||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
@ -395,4 +395,9 @@ function! go#util#tempdir(prefix) abort
|
||||||
return l:tmp
|
return l:tmp
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
" Report if the user enabled a debug flag in g:go_debug.
|
||||||
|
function! go#util#HasDebug(flag)
|
||||||
|
return index(get(g:, 'go_debug', []), a:flag) >= 0
|
||||||
|
endfunction
|
||||||
|
|
||||||
" vim: sw=2 ts=2 et
|
" vim: sw=2 ts=2 et
|
||||||
|
|
|
@ -22,10 +22,11 @@ CONTENTS *go-contents*
|
||||||
6. Functions....................................|go-functions|
|
6. Functions....................................|go-functions|
|
||||||
7. Settings.....................................|go-settings|
|
7. Settings.....................................|go-settings|
|
||||||
8. Syntax highlighting..........................|go-syntax|
|
8. Syntax highlighting..........................|go-syntax|
|
||||||
9. FAQ/Troubleshooting..........................|go-troubleshooting|
|
9. Debugger.....................................|go-debug|
|
||||||
10. Development..................................|go-development|
|
10. FAQ/Troubleshooting..........................|go-troubleshooting|
|
||||||
11. Donation.....................................|go-donation|
|
11. Development..................................|go-development|
|
||||||
12. Credits......................................|go-credits|
|
12. Donation.....................................|go-donation|
|
||||||
|
13. Credits......................................|go-credits|
|
||||||
|
|
||||||
==============================================================================
|
==============================================================================
|
||||||
INTRO *go-intro*
|
INTRO *go-intro*
|
||||||
|
@ -37,16 +38,16 @@ and individual features can be toggled easily. vim-go leverages a number of
|
||||||
tools developed by the Go community to provide a seamless Vim experience.
|
tools developed by the Go community to provide a seamless Vim experience.
|
||||||
|
|
||||||
* Compile your package with |:GoBuild|, install it with |:GoInstall| or
|
* Compile your package with |:GoBuild|, install it with |:GoInstall| or
|
||||||
test it with |:GoTest|. Run a single tests with |:GoTestFunc|).
|
test it with |:GoTest|. Run a single test with |:GoTestFunc|).
|
||||||
* Quickly execute your current file(s) with |:GoRun|.
|
* Quickly execute your current file(s) with |:GoRun|.
|
||||||
* Improved syntax highlighting and folding.
|
* Improved syntax highlighting and folding.
|
||||||
|
* Debug programs with integrated `delve` support with |:GoDebugStart|.
|
||||||
* Completion support via `gocode`.
|
* Completion support via `gocode`.
|
||||||
* `gofmt` or `goimports` on save keeps the cursor position and undo history.
|
* `gofmt` or `goimports` on save keeps the cursor position and undo history.
|
||||||
* Go to symbol/declaration with |:GoDef|.
|
* Go to symbol/declaration with |:GoDef|.
|
||||||
* Look up documentation with |:GoDoc| or |:GoDocBrowser|.
|
* Look up documentation with |:GoDoc| or |:GoDocBrowser|.
|
||||||
* Easily import packages via |:GoImport|, remove them via |:GoDrop|.
|
* Easily import packages via |:GoImport|, remove them via |:GoDrop|.
|
||||||
* Automatic `GOPATH` detection which works with `gb` and `godep`. Change or
|
* Precise type-safe renaming of identifiers with |:GoRename|.
|
||||||
display `GOPATH` with |:GoPath|.
|
|
||||||
* See which code is covered by tests with |:GoCoverage|.
|
* See which code is covered by tests with |:GoCoverage|.
|
||||||
* Add or remove tags on struct fields with |:GoAddTags| and |:GoRemoveTags|.
|
* Add or remove tags on struct fields with |:GoAddTags| and |:GoRemoveTags|.
|
||||||
* Call `gometalinter` with |:GoMetaLinter| to invoke all possible linters
|
* Call `gometalinter` with |:GoMetaLinter| to invoke all possible linters
|
||||||
|
@ -56,7 +57,8 @@ tools developed by the Go community to provide a seamless Vim experience.
|
||||||
static errors, or make sure errors are checked with |:GoErrCheck|.
|
static errors, or make sure errors are checked with |:GoErrCheck|.
|
||||||
* Advanced source analysis tools utilizing `guru`, such as |:GoImplements|,
|
* Advanced source analysis tools utilizing `guru`, such as |:GoImplements|,
|
||||||
|:GoCallees|, and |:GoReferrers|.
|
|:GoCallees|, and |:GoReferrers|.
|
||||||
* Precise type-safe renaming of identifiers with |:GoRename|.
|
* Automatic `GOPATH` detection which works with `gb` and `godep`. Change or
|
||||||
|
display `GOPATH` with |:GoPath|.
|
||||||
* Integrated and improved snippets, supporting `ultisnips`, `neosnippet`,
|
* Integrated and improved snippets, supporting `ultisnips`, `neosnippet`,
|
||||||
and `vim-minisnip`.
|
and `vim-minisnip`.
|
||||||
* Share your current code to play.golang.org with |:GoPlay|.
|
* Share your current code to play.golang.org with |:GoPlay|.
|
||||||
|
@ -1100,7 +1102,7 @@ cleaned for each package after `60` seconds. This can be changed with the
|
||||||
*go#complete#GetInfo()*
|
*go#complete#GetInfo()*
|
||||||
|
|
||||||
Returns the description of the identifer under the cursor. Can be used to plug
|
Returns the description of the identifer under the cursor. Can be used to plug
|
||||||
into the statusline. This function is also used for |'g:go_auto_type_info'|.
|
into the statusline.
|
||||||
|
|
||||||
==============================================================================
|
==============================================================================
|
||||||
SETTINGS *go-settings*
|
SETTINGS *go-settings*
|
||||||
|
@ -1658,6 +1660,18 @@ By default "snakecase" is used. Current values are: ["snakecase",
|
||||||
>
|
>
|
||||||
let g:go_addtags_transform = 'snakecase'
|
let g:go_addtags_transform = 'snakecase'
|
||||||
<
|
<
|
||||||
|
*'g:go_debug'*
|
||||||
|
|
||||||
|
A list of options to debug; useful for development and/or reporting bugs.
|
||||||
|
|
||||||
|
Currently accepted values:
|
||||||
|
|
||||||
|
debugger-state Expose debugger state in 'g:go_debug_diag'.
|
||||||
|
debugger-commands Echo communication between vim-go and `dlv`; requests and
|
||||||
|
responses are recorded in `g:go_debug_commands`.
|
||||||
|
>
|
||||||
|
let g:go_debug = []
|
||||||
|
<
|
||||||
|
|
||||||
==============================================================================
|
==============================================================================
|
||||||
SYNTAX HIGHLIGHTING *ft-go-syntax* *go-syntax*
|
SYNTAX HIGHLIGHTING *ft-go-syntax* *go-syntax*
|
||||||
|
@ -1815,6 +1829,212 @@ The `gohtmltmpl` filetype is automatically set for `*.tmpl` files; the
|
||||||
`gotexttmpl` is never automatically set and needs to be set manually.
|
`gotexttmpl` is never automatically set and needs to be set manually.
|
||||||
|
|
||||||
|
|
||||||
|
==============================================================================
|
||||||
|
DEBUGGER *go-debug*
|
||||||
|
|
||||||
|
Vim-go comes with a special "debugger mode". This starts a `dlv` process in
|
||||||
|
the background and provides various commands to communicate with it.
|
||||||
|
|
||||||
|
This debugger is similar to Visual Studio or Eclipse and has the following
|
||||||
|
features:
|
||||||
|
|
||||||
|
* Show stack trace and jumps.
|
||||||
|
* List local variables.
|
||||||
|
* List function arguments.
|
||||||
|
* Expand values of struct or array/slice.
|
||||||
|
* Show balloon on the symbol.
|
||||||
|
* Show output of stdout/stderr.
|
||||||
|
* Toggle breakpoint.
|
||||||
|
* Stack operation continue/next/step out.
|
||||||
|
|
||||||
|
This feature requires Vim 8.0.0087 or newer with the |+job| feature. Neovim
|
||||||
|
does _not_ work (yet).
|
||||||
|
This requires Delve 1.0.0 or newer, and it is recommended to use Go 1.10 or
|
||||||
|
newer, as its new caching will speed up recompiles.
|
||||||
|
|
||||||
|
*go-debug-intro*
|
||||||
|
GETTING STARTED WITH THE DEBUGGER~
|
||||||
|
|
||||||
|
Use |:GoDebugStart| or |:GoDebugTest| to start the debugger. The first
|
||||||
|
argument is the package name, and any arguments after that will be passed on
|
||||||
|
to the program; for example:
|
||||||
|
>
|
||||||
|
:GoDebugStart . -someflag value
|
||||||
|
<
|
||||||
|
This may take few seconds. After the code is compiled you'll see three new
|
||||||
|
windows: the stack trace on left side, the variable list on the bottom-left,
|
||||||
|
and program output at the bottom.
|
||||||
|
|
||||||
|
You can add breakpoints with |:GoDebugBreakpoint| (<F9>) and run your program
|
||||||
|
with |:GoDebugContinue| (<F5>).
|
||||||
|
|
||||||
|
The program will halt on the breakpoint, at which point you can inspect the
|
||||||
|
program state. You can go to the next line with |:GoDebugNext| (<F10>) or step
|
||||||
|
in with |:GoDebugStep| (<F11>).
|
||||||
|
|
||||||
|
The variable window in the bottom left (`GODEBUG_VARIABLES`) will display all
|
||||||
|
local variables. Struct values are displayed as `{...}`, array/slices as
|
||||||
|
`[4]`. Use <CR> on the variable name to expand the values.
|
||||||
|
|
||||||
|
The `GODEBUG_OUTPUT` window displays output from the program and the Delve
|
||||||
|
debugger.
|
||||||
|
|
||||||
|
The `GODEBUG_STACKTRACE` window can be used to jump to different places in the
|
||||||
|
call stack.
|
||||||
|
|
||||||
|
When you're done use |:GoDebugStop| to close the debugging windows and halt
|
||||||
|
the `dlv` process, or |:GoDebugRestart| to recompile the code.
|
||||||
|
|
||||||
|
*go-debug-commands*
|
||||||
|
DEBUGGER COMMANDS~
|
||||||
|
|
||||||
|
Only |:GoDebugStart| and |:GoDebugBreakpoint| are available by default; the
|
||||||
|
rest of the commands and mappings become available after starting debug mode.
|
||||||
|
|
||||||
|
*:GoDebugStart*
|
||||||
|
:GoDebugStart [pkg] [program-args]
|
||||||
|
|
||||||
|
Start the debug mode for [pkg]; this does several things:
|
||||||
|
|
||||||
|
* Setup the debug windows according to |'g:go_debug_windows'|.
|
||||||
|
* Make the `:GoDebug*` commands and `(go-debug-*)` mappings available.
|
||||||
|
|
||||||
|
The current directory is used if [pkg] is empty. Any other arguments will
|
||||||
|
be passed to the program.
|
||||||
|
|
||||||
|
Use |:GoDebugStop| to stop `dlv` and exit debugging mode.
|
||||||
|
|
||||||
|
*:GoDebugTest*
|
||||||
|
:GoDebugTest [pkg] [program-args]
|
||||||
|
|
||||||
|
Behaves the same as |:GoDebugStart| but runs `dlv test` instead of
|
||||||
|
`dlv debug` so you can debug tests.
|
||||||
|
|
||||||
|
Use `-test.flag` to pass flags to `go test` when debugging a test; for
|
||||||
|
example `-test.v` or `-test.run TestFoo`
|
||||||
|
|
||||||
|
|
||||||
|
*:GoDebugRestart*
|
||||||
|
:GoDebugRestart
|
||||||
|
|
||||||
|
Stop the program (if running) and restart `dlv` to recompile the package.
|
||||||
|
The current window layout and breakpoints will be left intact.
|
||||||
|
|
||||||
|
*:GoDebugStop*
|
||||||
|
*(go-debug-stop)*
|
||||||
|
:GoDebugStop
|
||||||
|
|
||||||
|
Stop `dlv` and remove all debug-specific commands, mappings, and windows.
|
||||||
|
|
||||||
|
*:GoDebugBreakpoint*
|
||||||
|
*(go-debug-breakpoint)*
|
||||||
|
:GoDebugBreakpoint [linenr]
|
||||||
|
|
||||||
|
Toggle breakpoint for the [linenr]. [linenr] defaults to the current line
|
||||||
|
if it is omitted. A line with a breakpoint will have the
|
||||||
|
{godebugbreakpoint} |:sign| placed on it. The line the program is
|
||||||
|
currently halted on will have the {godebugcurline} sign.
|
||||||
|
|
||||||
|
*hl-GoDebugCurrent* *hl-GoDebugBreakpoint*
|
||||||
|
A line with a breakpoint will be highlighted with the {GoDebugBreakpoint}
|
||||||
|
group; the line the program is currently halted on will be highlighted
|
||||||
|
with {GoDebugCurrent}.
|
||||||
|
|
||||||
|
Mapped to <F9> by default.
|
||||||
|
|
||||||
|
*:GoDebugContinue*
|
||||||
|
*(go-debug-continue)*
|
||||||
|
:GoDebugContinue
|
||||||
|
|
||||||
|
Continue execution until breakpoint or program termination. It will start
|
||||||
|
the program if it hasn't been started yet.
|
||||||
|
|
||||||
|
Mapped to <F5> by default.
|
||||||
|
|
||||||
|
*:GoDebugNext*
|
||||||
|
*(go-debug-next)*
|
||||||
|
:GoDebugNext
|
||||||
|
|
||||||
|
Advance execution by one line, also called "step over" by some other
|
||||||
|
debuggers.
|
||||||
|
It will behave as |:GoDebugContinue| if the program isn't started.
|
||||||
|
|
||||||
|
Mapped to <F10> by default.
|
||||||
|
|
||||||
|
*:GoDebugStep*
|
||||||
|
*(go-debug-step)*
|
||||||
|
:GoDebugStep
|
||||||
|
|
||||||
|
Advance execution by one step, stopping at the next line of code that will
|
||||||
|
be executed (regardless of location).
|
||||||
|
It will behave as |:GoDebugContinue| if the program isn't started.
|
||||||
|
|
||||||
|
Mapped to <F11> by default.
|
||||||
|
|
||||||
|
*:GoDebugStepOut*
|
||||||
|
*(go-debug-stepout)*
|
||||||
|
|
||||||
|
:GoDebugStepOut
|
||||||
|
|
||||||
|
Run all the code in the current function and halt when the function
|
||||||
|
returns ("step out of the current function").
|
||||||
|
It will behave as |:GoDebugContinue| if the program isn't started.
|
||||||
|
|
||||||
|
*:GoDebugSet*
|
||||||
|
:GoDebugSet {var} {value}
|
||||||
|
|
||||||
|
Set the variable {var} to {value}. Example:
|
||||||
|
>
|
||||||
|
:GoDebugSet truth 42
|
||||||
|
<
|
||||||
|
This only works for `float`, `int` and variants, `uint` and variants,
|
||||||
|
`bool`, and pointers (this is a `delve` limitation, not a vim-go
|
||||||
|
limitation).
|
||||||
|
|
||||||
|
*:GoDebugPrint*
|
||||||
|
*(go-debug-print)*
|
||||||
|
:GoDebugPrint {expr}
|
||||||
|
|
||||||
|
Print the result of a Go expression.
|
||||||
|
>
|
||||||
|
:GoDebugPrint truth == 42
|
||||||
|
truth == 42 true
|
||||||
|
<
|
||||||
|
Mapped to <F6> by default, which will evaluate the <cword> under the
|
||||||
|
cursor.
|
||||||
|
|
||||||
|
*go-debug-settings*
|
||||||
|
DEBUGGER SETTINGS~
|
||||||
|
|
||||||
|
*'g:go_debug_windows'*
|
||||||
|
|
||||||
|
Controls the window layout for debugging mode. This is a |dict| with three
|
||||||
|
possible keys: "stack", "out", and "vars"; the windows will created in that
|
||||||
|
order with the commands in the value.
|
||||||
|
A window will not be created if a key is missing or empty.
|
||||||
|
|
||||||
|
Defaults:
|
||||||
|
>
|
||||||
|
let g:go_debug_windows = {
|
||||||
|
\ 'stack': 'leftabove 20vnew',
|
||||||
|
\ 'out': 'botright 10new',
|
||||||
|
\ 'vars': 'leftabove 30vnew',
|
||||||
|
\ }
|
||||||
|
<
|
||||||
|
Show only variables on the right-hand side: >
|
||||||
|
|
||||||
|
let g:go_debug_windows = {
|
||||||
|
\ 'vars': 'rightbelow 60vnew',
|
||||||
|
\ }
|
||||||
|
<
|
||||||
|
*'g:go_debug_address'*
|
||||||
|
|
||||||
|
Server address `dlv` will listen on; must be in `hostname:port` format.
|
||||||
|
Defaults to `127.0.0.1:8181`:
|
||||||
|
>
|
||||||
|
let g:go_debug_address = '127.0.0.1:8181'
|
||||||
|
<
|
||||||
|
|
||||||
==============================================================================
|
==============================================================================
|
||||||
FAQ TROUBLESHOOTING *go-troubleshooting*
|
FAQ TROUBLESHOOTING *go-troubleshooting*
|
||||||
|
|
||||||
|
|
|
@ -98,4 +98,11 @@ command! -nargs=0 GoKeyify call go#keyify#Keyify()
|
||||||
" -- fillstruct
|
" -- fillstruct
|
||||||
command! -nargs=0 GoFillStruct call go#fillstruct#FillStruct()
|
command! -nargs=0 GoFillStruct call go#fillstruct#FillStruct()
|
||||||
|
|
||||||
|
" -- debug
|
||||||
|
if !exists(':GoDebugStart')
|
||||||
|
command! -nargs=* -complete=customlist,go#package#Complete GoDebugStart call go#debug#Start(0, <f-args>)
|
||||||
|
command! -nargs=* -complete=customlist,go#package#Complete GoDebugTest call go#debug#Start(1, <f-args>)
|
||||||
|
command! -nargs=? GoDebugBreakpoint call go#debug#Breakpoint(<f-args>)
|
||||||
|
endif
|
||||||
|
|
||||||
" vim: sw=2 ts=2 et
|
" vim: sw=2 ts=2 et
|
||||||
|
|
|
@ -40,7 +40,7 @@ function! s:GoMinisnip() abort
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if exists('g:minisnip_dir')
|
if exists('g:minisnip_dir')
|
||||||
let g:minisnip_dir .= ':' . globpath(&rtp, 'gosnippets/minisnip')
|
let g:minisnip_dir .= go#util#PathListSep() . globpath(&rtp, 'gosnippets/minisnip')
|
||||||
else
|
else
|
||||||
let g:minisnip_dir = globpath(&rtp, 'gosnippets/minisnip')
|
let g:minisnip_dir = globpath(&rtp, 'gosnippets/minisnip')
|
||||||
endif
|
endif
|
||||||
|
|
|
@ -252,6 +252,11 @@ snippet fn "fmt.Println(...)"
|
||||||
fmt.Println("${1:${VISUAL}}")
|
fmt.Println("${1:${VISUAL}}")
|
||||||
endsnippet
|
endsnippet
|
||||||
|
|
||||||
|
# Fmt Errorf debug
|
||||||
|
snippet fe "fmt.Errorf(...)"
|
||||||
|
fmt.Errorf("${1:${VISUAL}}")
|
||||||
|
endsnippet
|
||||||
|
|
||||||
# log printf
|
# log printf
|
||||||
snippet lf "log.Printf(...)"
|
snippet lf "log.Printf(...)"
|
||||||
log.Printf("${1:${VISUAL}} = %+v\n", $1)
|
log.Printf("${1:${VISUAL}} = %+v\n", $1)
|
||||||
|
|
|
@ -219,6 +219,10 @@ abbr fmt.Printf(...)
|
||||||
snippet fn
|
snippet fn
|
||||||
abbr fmt.Println(...)
|
abbr fmt.Println(...)
|
||||||
fmt.Println("${1}")
|
fmt.Println("${1}")
|
||||||
|
# Fmt Errorf
|
||||||
|
snippet fe
|
||||||
|
abbr fmt.Errorf(...)
|
||||||
|
fmt.Errorf("${1}")
|
||||||
# log printf
|
# log printf
|
||||||
snippet lf
|
snippet lf
|
||||||
abbr log.Printf(...)
|
abbr log.Printf(...)
|
||||||
|
|
|
@ -31,6 +31,7 @@ endif
|
||||||
" needed by the user with GoInstallBinaries
|
" needed by the user with GoInstallBinaries
|
||||||
let s:packages = {
|
let s:packages = {
|
||||||
\ 'asmfmt': ['github.com/klauspost/asmfmt/cmd/asmfmt'],
|
\ 'asmfmt': ['github.com/klauspost/asmfmt/cmd/asmfmt'],
|
||||||
|
\ 'dlv': ['github.com/derekparker/delve/cmd/dlv'],
|
||||||
\ 'errcheck': ['github.com/kisielk/errcheck'],
|
\ 'errcheck': ['github.com/kisielk/errcheck'],
|
||||||
\ 'fillstruct': ['github.com/davidrjenni/reftools/cmd/fillstruct'],
|
\ 'fillstruct': ['github.com/davidrjenni/reftools/cmd/fillstruct'],
|
||||||
\ 'gocode': ['github.com/nsf/gocode', {'windows': '-ldflags -H=windowsgui'}],
|
\ 'gocode': ['github.com/nsf/gocode', {'windows': '-ldflags -H=windowsgui'}],
|
||||||
|
|
|
@ -453,7 +453,7 @@ if g:go_highlight_build_constraints != 0 || s:fold_package_comment
|
||||||
\ . ' contains=@goCommentGroup,@Spell'
|
\ . ' contains=@goCommentGroup,@Spell'
|
||||||
\ . (s:fold_package_comment ? ' fold' : '')
|
\ . (s:fold_package_comment ? ' fold' : '')
|
||||||
exe 'syn region goPackageComment start=/\v\/\*.*\n(.*\n)*\s*\*\/\npackage/'
|
exe 'syn region goPackageComment start=/\v\/\*.*\n(.*\n)*\s*\*\/\npackage/'
|
||||||
\ . ' end=/\v\n\s*package/he=e-7,me=e-7,re=e-7'
|
\ . ' end=/\v\*\/\n\s*package/he=e-7,me=e-7,re=e-7'
|
||||||
\ . ' contains=@goCommentGroup,@Spell'
|
\ . ' contains=@goCommentGroup,@Spell'
|
||||||
\ . (s:fold_package_comment ? ' fold' : '')
|
\ . (s:fold_package_comment ? ' fold' : '')
|
||||||
hi def link goPackageComment Comment
|
hi def link goPackageComment Comment
|
||||||
|
|
13
sources_non_forked/vim-go/syntax/godebugoutput.vim
Normal file
13
sources_non_forked/vim-go/syntax/godebugoutput.vim
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
if exists("b:current_syntax")
|
||||||
|
finish
|
||||||
|
endif
|
||||||
|
|
||||||
|
syn match godebugOutputErr '^ERR:.*'
|
||||||
|
syn match godebugOutputOut '^OUT:.*'
|
||||||
|
|
||||||
|
let b:current_syntax = "godebugoutput"
|
||||||
|
|
||||||
|
hi def link godebugOutputErr Comment
|
||||||
|
hi def link godebugOutputOut Normal
|
||||||
|
|
||||||
|
" vim: sw=2 ts=2 et
|
11
sources_non_forked/vim-go/syntax/godebugstacktrace.vim
Normal file
11
sources_non_forked/vim-go/syntax/godebugstacktrace.vim
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
if exists("b:current_syntax")
|
||||||
|
finish
|
||||||
|
endif
|
||||||
|
|
||||||
|
syn match godebugStacktrace '^\S\+'
|
||||||
|
|
||||||
|
let b:current_syntax = "godebugoutput"
|
||||||
|
|
||||||
|
hi def link godebugStacktrace SpecialKey
|
||||||
|
|
||||||
|
" vim: sw=2 ts=2 et
|
23
sources_non_forked/vim-go/syntax/godebugvariables.vim
Normal file
23
sources_non_forked/vim-go/syntax/godebugvariables.vim
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
if exists("b:current_syntax")
|
||||||
|
finish
|
||||||
|
endif
|
||||||
|
|
||||||
|
syn match godebugTitle '^#.*'
|
||||||
|
syn match godebugVariables '^\s*\S\+\ze:'
|
||||||
|
|
||||||
|
syn keyword goType chan map bool string error
|
||||||
|
syn keyword goSignedInts int int8 int16 int32 int64 rune
|
||||||
|
syn keyword goUnsignedInts byte uint uint8 uint16 uint32 uint64 uintptr
|
||||||
|
syn keyword goFloats float32 float64
|
||||||
|
syn keyword goComplexes complex64 complex128
|
||||||
|
|
||||||
|
syn keyword goBoolean true false
|
||||||
|
|
||||||
|
let b:current_syntax = "godebugvariables"
|
||||||
|
|
||||||
|
hi def link godebugTitle Underlined
|
||||||
|
hi def link godebugVariables Statement
|
||||||
|
hi def link goType Type
|
||||||
|
hi def link goBoolean Boolean
|
||||||
|
|
||||||
|
" vim: sw=2 ts=2 et
|
|
@ -123,7 +123,7 @@ let g:vim_markdown_toc_autofit = 1
|
||||||
|
|
||||||
### Text emphasis restriction to single-lines
|
### Text emphasis restriction to single-lines
|
||||||
|
|
||||||
By default text emphasis works across multiple lines until a closing token is found. However, it's possible to restrict text emphasis to a single line (ie, for it to be applied a closing token must be found on the same line). To do so:
|
By default text emphasis works across multiple lines until a closing token is found. However, it's possible to restrict text emphasis to a single line (i.e., for it to be applied a closing token must be found on the same line). To do so:
|
||||||
|
|
||||||
```vim
|
```vim
|
||||||
let g:vim_markdown_emphasis_multiline = 0
|
let g:vim_markdown_emphasis_multiline = 0
|
||||||
|
@ -176,7 +176,7 @@ Default is `['c++=cpp', 'viml=vim', 'bash=sh', 'ini=dosini']`.
|
||||||
|
|
||||||
### Follow named anchors
|
### Follow named anchors
|
||||||
|
|
||||||
This feature allows ge to follow named anchors in links of the form
|
This feature allows the `ge` command to follow named anchors in links of the form
|
||||||
`file#anchor` or just `#anchor`, where file may omit the `.md` extension as
|
`file#anchor` or just `#anchor`, where file may omit the `.md` extension as
|
||||||
usual. Two variables control its operation:
|
usual. Two variables control its operation:
|
||||||
|
|
||||||
|
|
|
@ -764,10 +764,10 @@ function! s:MarkdownClearSyntaxVariables()
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
augroup Mkd
|
augroup Mkd
|
||||||
autocmd!
|
autocmd! * <buffer>
|
||||||
au BufWinEnter * call s:MarkdownRefreshSyntax(1)
|
autocmd BufWinEnter <buffer> call s:MarkdownRefreshSyntax(1)
|
||||||
au BufUnload * call s:MarkdownClearSyntaxVariables()
|
autocmd BufUnload <buffer> call s:MarkdownClearSyntaxVariables()
|
||||||
au BufWritePost * call s:MarkdownRefreshSyntax(0)
|
autocmd BufWritePost <buffer> call s:MarkdownRefreshSyntax(0)
|
||||||
au InsertEnter,InsertLeave * call s:MarkdownRefreshSyntax(0)
|
autocmd InsertEnter,InsertLeave <buffer> call s:MarkdownRefreshSyntax(0)
|
||||||
au CursorHold,CursorHoldI * call s:MarkdownRefreshSyntax(0)
|
autocmd CursorHold,CursorHoldI <buffer> call s:MarkdownRefreshSyntax(0)
|
||||||
augroup END
|
augroup END
|
||||||
|
|
|
@ -35,7 +35,7 @@ Vim command sequence: `2Gfp<C-n><C-n><C-n>cname`
|
||||||
### Add a cursor to each line of your visual selection
|
### Add a cursor to each line of your visual selection
|
||||||
![Example2](assets/example2.gif?raw=true)
|
![Example2](assets/example2.gif?raw=true)
|
||||||
|
|
||||||
Vim command sequence: `2Gvip<C-n>i"<Right><Right><Right>",<Esc>vipJ$r]Idays = [`
|
Vim command sequence: `2Gvip<C-n>i"<Right><Right><Right>",<Esc>vipgJ$r]Idays = [`
|
||||||
|
|
||||||
### Do it backwards too! This is not just a replay of the above gif :)
|
### Do it backwards too! This is not just a replay of the above gif :)
|
||||||
![Example3](assets/example3.gif?raw=true)
|
![Example3](assets/example3.gif?raw=true)
|
||||||
|
@ -51,8 +51,8 @@ To see what keystrokes are used for the above examples, see [the wiki page](http
|
||||||
- Live update in Insert mode
|
- Live update in Insert mode
|
||||||
- One key to rule it all! See [Quick Start](#quick-start) on what the key does in different scenarios
|
- One key to rule it all! See [Quick Start](#quick-start) on what the key does in different scenarios
|
||||||
- Works in Normal, Insert, and Visual mode for any commands (including
|
- Works in Normal, Insert, and Visual mode for any commands (including
|
||||||
multi-key commands, assuming you set `g:multicursor_insert_maps` and
|
multi-key commands, assuming you set `g:multicursor_normal_maps`;
|
||||||
`g:multicursor_normal_maps`; see Settings below for details)
|
see Settings below for details)
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
Install using [Pathogen], [Vundle], [Neobundle], or your favorite Vim package manager.
|
Install using [Pathogen], [Vundle], [Neobundle], or your favorite Vim package manager.
|
||||||
|
@ -123,15 +123,6 @@ If set to 0, then pressing `g:multi_cursor_quit_key` in _Visual_ mode will not q
|
||||||
### ```g:multi_cursor_exit_from_insert_mode``` (Default: 1)
|
### ```g:multi_cursor_exit_from_insert_mode``` (Default: 1)
|
||||||
If set to 0, then pressing `g:multi_cursor_quit_key` in _Insert_ mode will not quit and delete all existing cursors. This is useful if you want to press Escape and go back to Normal mode, and still be able to operate on all the cursors.
|
If set to 0, then pressing `g:multi_cursor_quit_key` in _Insert_ mode will not quit and delete all existing cursors. This is useful if you want to press Escape and go back to Normal mode, and still be able to operate on all the cursors.
|
||||||
|
|
||||||
### ```g:multi_cursor_insert_maps``` (Default: `{}`)
|
|
||||||
Any key in this map (values are ignored) will cause multi-cursor _Insert_ mode
|
|
||||||
to pause for `timeoutlen` waiting for map completion just like normal vim.
|
|
||||||
Otherwise keys mapped in insert mode are ignored when multiple cursors are
|
|
||||||
active. For example, setting it to `{'\':1}` will make insert-mode mappings
|
|
||||||
beginning with the default leader key work in multi-cursor mode. You have to
|
|
||||||
manually set this because vim doesn't provide a way to see which keys _start_
|
|
||||||
mappings.
|
|
||||||
|
|
||||||
### ```g:multi_cursor_normal_maps``` (Default: see below)
|
### ```g:multi_cursor_normal_maps``` (Default: see below)
|
||||||
Default value: `{'!':1, '@':1, '=':1, 'q':1, 'r':1, 't':1, 'T':1, 'y':1, '[':1, ']':1, '\':1, 'd':1, 'f':1, 'F':1, 'g':1, '"':1, 'z':1, 'c':1, 'm':1, '<':1, '>':1}`
|
Default value: `{'!':1, '@':1, '=':1, 'q':1, 'r':1, 't':1, 'T':1, 'y':1, '[':1, ']':1, '\':1, 'd':1, 'f':1, 'F':1, 'g':1, '"':1, 'z':1, 'c':1, 'm':1, '<':1, '>':1}`
|
||||||
|
|
||||||
|
|
|
@ -103,7 +103,7 @@ endfunction
|
||||||
|
|
||||||
function! s:fire_pre_triggers()
|
function! s:fire_pre_triggers()
|
||||||
if !s:before_function_called
|
if !s:before_function_called
|
||||||
doautocmd User MultipleCursorsPre
|
silent doautocmd User MultipleCursorsPre
|
||||||
if exists('*Multiple_cursors_before')
|
if exists('*Multiple_cursors_before')
|
||||||
exe "call Multiple_cursors_before()"
|
exe "call Multiple_cursors_before()"
|
||||||
endif
|
endif
|
||||||
|
@ -445,7 +445,7 @@ function! s:CursorManager.reset(restore_view, restore_setting, ...) dict
|
||||||
if exists('*Multiple_cursors_after')
|
if exists('*Multiple_cursors_after')
|
||||||
exe "call Multiple_cursors_after()"
|
exe "call Multiple_cursors_after()"
|
||||||
endif
|
endif
|
||||||
doautocmd User MultipleCursorsPost
|
silent doautocmd User MultipleCursorsPost
|
||||||
let s:before_function_called = 0
|
let s:before_function_called = 0
|
||||||
endif
|
endif
|
||||||
endfunction
|
endfunction
|
||||||
|
@ -516,7 +516,6 @@ function! s:CursorManager.update_current() dict
|
||||||
if s:to_mode ==# 'V'
|
if s:to_mode ==# 'V'
|
||||||
exec "normal! gvv\<Esc>"
|
exec "normal! gvv\<Esc>"
|
||||||
endif
|
endif
|
||||||
|
|
||||||
" Sets the cursor at the right place
|
" Sets the cursor at the right place
|
||||||
exec "normal! gv\<Esc>"
|
exec "normal! gv\<Esc>"
|
||||||
call cur.update_visual_selection(s:get_visual_region(s:pos('.')))
|
call cur.update_visual_selection(s:get_visual_region(s:pos('.')))
|
||||||
|
@ -525,17 +524,18 @@ function! s:CursorManager.update_current() dict
|
||||||
" This should be executed after user input is processed, when unnamed
|
" This should be executed after user input is processed, when unnamed
|
||||||
" register already contains the text.
|
" register already contains the text.
|
||||||
call cur.save_unnamed_register()
|
call cur.save_unnamed_register()
|
||||||
|
|
||||||
call cur.remove_visual_selection()
|
call cur.remove_visual_selection()
|
||||||
elseif s:from_mode ==# 'i' && s:to_mode ==# 'n' && self.current_index != self.size() - 1
|
elseif s:from_mode ==# 'i' && s:to_mode ==# 'n' && self.current_index != 0
|
||||||
normal! h
|
normal! h
|
||||||
elseif s:from_mode ==# 'n'
|
elseif s:from_mode ==# 'n'
|
||||||
" Save contents of unnamed register after each operation in Normal mode.
|
" Save contents of unnamed register after each operation in Normal mode.
|
||||||
call cur.save_unnamed_register()
|
call cur.save_unnamed_register()
|
||||||
endif
|
endif
|
||||||
let vdelta = line('$') - s:saved_linecount
|
let pos = s:pos('.')
|
||||||
|
|
||||||
" If the total number of lines changed in the buffer, we need to potentially
|
" If the total number of lines changed in the buffer, we need to potentially
|
||||||
" adjust other cursor locations
|
" adjust other cursor locations
|
||||||
|
let vdelta = line('$') - s:saved_linecount
|
||||||
if vdelta != 0
|
if vdelta != 0
|
||||||
if self.current_index != self.size() - 1
|
if self.current_index != self.size() - 1
|
||||||
let cur_column_offset = (cur.column() - col('.')) * -1
|
let cur_column_offset = (cur.column() - col('.')) * -1
|
||||||
|
@ -547,7 +547,7 @@ function! s:CursorManager.update_current() dict
|
||||||
let c = self.get(i)
|
let c = self.get(i)
|
||||||
" If there're other cursors on the same line, we need to adjust their
|
" If there're other cursors on the same line, we need to adjust their
|
||||||
" columns. This needs to happen before we adjust their line!
|
" columns. This needs to happen before we adjust their line!
|
||||||
if cur.line() == c.line()
|
if cur.line() == c.line() || cur.position == pos
|
||||||
if vdelta > 0
|
if vdelta > 0
|
||||||
" Added a line
|
" Added a line
|
||||||
let hdelta = cur_column_offset
|
let hdelta = cur_column_offset
|
||||||
|
@ -583,7 +583,6 @@ function! s:CursorManager.update_current() dict
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
let pos = s:pos('.')
|
|
||||||
if cur.position == pos
|
if cur.position == pos
|
||||||
return 0
|
return 0
|
||||||
endif
|
endif
|
||||||
|
@ -598,7 +597,8 @@ endfunction
|
||||||
|
|
||||||
" Start tracking cursor updates
|
" Start tracking cursor updates
|
||||||
function! s:CursorManager.start_loop() dict
|
function! s:CursorManager.start_loop() dict
|
||||||
let self.starting_index = self.current_index
|
let self.current_index = 0
|
||||||
|
let self.starting_index = 0
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
" Returns true if we're cycled through all the cursors
|
" Returns true if we're cycled through all the cursors
|
||||||
|
@ -1210,28 +1210,51 @@ function! s:wait_for_user_input(mode)
|
||||||
let s:saved_keys = ""
|
let s:saved_keys = ""
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if s:from_mode ==# 'i' && has_key(g:multi_cursor_insert_maps, s:last_char())
|
" ambiguous mappings are note supported; e.g.:
|
||||||
let c = getchar(0)
|
" imap jj JJ
|
||||||
let char_type = type(c)
|
" imap jjj JJJ
|
||||||
|
" will always trigger the 'jj' mapping
|
||||||
|
if s:from_mode ==# 'i' && mapcheck(s:char, "i") != ""
|
||||||
let poll_count = 0
|
let poll_count = 0
|
||||||
while char_type == 0 && c == 0 && poll_count < &timeoutlen
|
let map_dict = {}
|
||||||
sleep 1m
|
while poll_count < &timeoutlen
|
||||||
let c = getchar(0)
|
let c = getchar(0)
|
||||||
let char_type = type(c)
|
let char_type = type(c)
|
||||||
let poll_count += 1
|
let poll_count += 1.5
|
||||||
endwhile
|
|
||||||
|
|
||||||
if char_type == 0 && c != 0
|
if char_type == 0 && c != 0
|
||||||
let s:char .= nr2char(c)
|
let s:char .= nr2char(c)
|
||||||
elseif char_type == 1 " char with more than 8 bits (as string)
|
elseif char_type == 1 " char with more than 8 bits (as string)
|
||||||
let s:char .= c
|
let s:char .= c
|
||||||
endif
|
endif
|
||||||
|
let map_dict = maparg(s:char, "i", 0, 1)
|
||||||
|
" break if chars exactly match mapping or if chars don't match beging of mapping anymore
|
||||||
|
if map_dict != {} || mapcheck(s:char, "i") == ""
|
||||||
|
if get(map_dict, 'expr', 0)
|
||||||
|
" handle case where {rhs} is a function
|
||||||
|
exec 'let char_mapping = ' . map_dict['rhs']
|
||||||
|
else
|
||||||
|
let char_mapping = get(map_dict, 'rhs', s:char)
|
||||||
|
endif
|
||||||
|
" handle case where mapping is <esc>
|
||||||
|
exec 'let s:char = "'.substitute(char_mapping, '<', '\\<', 'g').'"'
|
||||||
|
break
|
||||||
|
endif
|
||||||
|
sleep 1m
|
||||||
|
endwhile
|
||||||
elseif s:from_mode !=# 'i' && s:char[0] ==# ":"
|
elseif s:from_mode !=# 'i' && s:char[0] ==# ":"
|
||||||
call feedkeys(s:char)
|
call feedkeys(s:char)
|
||||||
call s:cm.reset(1, 1)
|
call s:cm.reset(1, 1)
|
||||||
return
|
return
|
||||||
elseif s:from_mode ==# 'n'
|
elseif s:from_mode ==# 'n' || s:from_mode =~# 'v\|V'
|
||||||
while match(s:last_char(), "\\d") == 0
|
while match(s:last_char(), "\\d") == 0
|
||||||
|
if match(s:char, '\(^\|\a\)0') == 0
|
||||||
|
" fixes an edge case concerning the `0` key.
|
||||||
|
" The 0 key behaves differently from [1-9].
|
||||||
|
" It's consumed immediately when it is the
|
||||||
|
" first key typed while we're waiting for input.
|
||||||
|
" References: issue #152, pull #241
|
||||||
|
break
|
||||||
|
endif
|
||||||
let s:char .= s:get_char()
|
let s:char .= s:get_char()
|
||||||
endwhile
|
endwhile
|
||||||
endif
|
endif
|
||||||
|
|
|
@ -157,16 +157,6 @@ quit and delete all existing cursors. This is useful if you want to press
|
||||||
Escape and go back to Normal mode, and still be able to operate on all the
|
Escape and go back to Normal mode, and still be able to operate on all the
|
||||||
cursors.
|
cursors.
|
||||||
|
|
||||||
*g:multi_cursor_insert_maps* (Default: `{}`)
|
|
||||||
|
|
||||||
Any key in this map (values are ignored) will cause multi-cursor _Insert_ mode
|
|
||||||
to pause for `timeoutlen` waiting for map completion just like normal vim.
|
|
||||||
Otherwise keys mapped in insert mode are ignored when multiple cursors are
|
|
||||||
active. For example, setting it to `{'\':1}` will make insert-mode mappings
|
|
||||||
beginning with the default leader key work in multi-cursor mode. You have to
|
|
||||||
manually set this because vim doesn't provide a way to see which keys _start_
|
|
||||||
mappings.
|
|
||||||
|
|
||||||
*g:multi_cursor_normal_maps* (Default: see below)
|
*g:multi_cursor_normal_maps* (Default: see below)
|
||||||
|
|
||||||
Default value: `{'!':1, '@':1, '=':1, 'q':1, 'r':1, 't':1, 'T':1, 'y':1, '[':1, ']':1, '\':1, 'd':1, 'f':1, 'F':1, 'g':1, '"':1, 'z':1, 'c':1, 'm':1, '<':1, '>':1}`
|
Default value: `{'!':1, '@':1, '=':1, 'q':1, 'r':1, 't':1, 'T':1, 'y':1, '[':1, ']':1, '\':1, 'd':1, 'f':1, 'F':1, 'g':1, '"':1, 'z':1, 'c':1, 'm':1, '<':1, '>':1}`
|
||||||
|
|
|
@ -40,12 +40,9 @@ let s:settings_if_default = {
|
||||||
\ 'skip_key': '<C-x>',
|
\ 'skip_key': '<C-x>',
|
||||||
\ }
|
\ }
|
||||||
|
|
||||||
let s:default_insert_maps = {}
|
|
||||||
let s:default_normal_maps = {'!':1, '@':1, '=':1, 'q':1, 'r':1, 't':1, 'T':1, 'y':1, '[':1, ']':1, '\':1, 'd':1, 'f':1, 'F':1, 'g':1, '"':1, 'z':1, 'c':1, 'm':1, '<':1, '>':1}
|
let s:default_normal_maps = {'!':1, '@':1, '=':1, 'q':1, 'r':1, 't':1, 'T':1, 'y':1, '[':1, ']':1, '\':1, 'd':1, 'f':1, 'F':1, 'g':1, '"':1, 'z':1, 'c':1, 'm':1, '<':1, '>':1}
|
||||||
let s:default_visual_maps = {'i':1, 'a':1, 'f':1, 'F':1, 't':1, 'T':1}
|
let s:default_visual_maps = {'i':1, 'a':1, 'f':1, 'F':1, 't':1, 'T':1}
|
||||||
|
|
||||||
let g:multi_cursor_insert_maps =
|
|
||||||
\ get(g:, 'multi_cursor_insert_maps', s:default_insert_maps)
|
|
||||||
let g:multi_cursor_normal_maps =
|
let g:multi_cursor_normal_maps =
|
||||||
\ get(g:, 'multi_cursor_normal_maps', s:default_normal_maps)
|
\ get(g:, 'multi_cursor_normal_maps', s:default_normal_maps)
|
||||||
let g:multi_cursor_visual_maps =
|
let g:multi_cursor_visual_maps =
|
||||||
|
|
|
@ -136,6 +136,79 @@ describe "Multiple Cursors op pending & exit from insert|visual mode" do
|
||||||
EOF
|
EOF
|
||||||
end
|
end
|
||||||
|
|
||||||
|
specify "#normal mode '0': goes to 1st char of line" do
|
||||||
|
before <<-EOF
|
||||||
|
hello jan world
|
||||||
|
hello feb world
|
||||||
|
hello mar world
|
||||||
|
EOF
|
||||||
|
|
||||||
|
type '<C-n><C-n><C-n>vw0dw<Esc><Esc>'
|
||||||
|
|
||||||
|
after <<-EOF
|
||||||
|
jan world
|
||||||
|
feb world
|
||||||
|
mar world
|
||||||
|
EOF
|
||||||
|
end
|
||||||
|
|
||||||
|
specify "#normal mode 'd0': deletes backward to 1st char of line" do
|
||||||
|
before <<-EOF
|
||||||
|
hello jan world
|
||||||
|
hello feb world
|
||||||
|
hello mar world
|
||||||
|
EOF
|
||||||
|
|
||||||
|
type '<C-n><C-n><C-n>vwd0<Esc><Esc>'
|
||||||
|
|
||||||
|
after <<-EOF
|
||||||
|
jan world
|
||||||
|
feb world
|
||||||
|
mar world
|
||||||
|
EOF
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "Multiple Cursors when using insert mapings" do
|
||||||
|
let(:filename) { 'test.txt' }
|
||||||
|
let(:options) { ['imap jj <esc>', 'imap jojo dude'] }
|
||||||
|
specify "#mapping doing <Esc>" do
|
||||||
|
before <<-EOF
|
||||||
|
hello world!
|
||||||
|
hello world!
|
||||||
|
bla bla bla
|
||||||
|
bla bla bla
|
||||||
|
EOF
|
||||||
|
|
||||||
|
type 'w<C-n><C-n>cjjidude<Esc>'
|
||||||
|
|
||||||
|
after <<-EOF
|
||||||
|
hello dude!
|
||||||
|
hello !
|
||||||
|
bla bla bla
|
||||||
|
bla bla bla
|
||||||
|
EOF
|
||||||
|
end
|
||||||
|
|
||||||
|
specify "#mapping using more than 2 characters" do
|
||||||
|
before <<-EOF
|
||||||
|
hello
|
||||||
|
hello
|
||||||
|
bla bla bla
|
||||||
|
bla bla bla
|
||||||
|
EOF
|
||||||
|
|
||||||
|
type '<C-n><C-n>A jojo<Esc>'
|
||||||
|
|
||||||
|
after <<-EOF
|
||||||
|
hello dude
|
||||||
|
hello dude
|
||||||
|
bla bla bla
|
||||||
|
bla bla bla
|
||||||
|
EOF
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "Multiple Cursors when normal_maps is empty" do
|
describe "Multiple Cursors when normal_maps is empty" do
|
||||||
|
@ -190,7 +263,53 @@ describe "Multiple Cursors when visual_maps is empty" do
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "Multiple Cursors" do
|
describe "Multiple Cursors when changing the line count" do
|
||||||
|
let(:filename) { 'test.txt' }
|
||||||
|
let(:options) { ['set backspace=indent,eol,start'] }
|
||||||
|
|
||||||
|
specify "#backspace on first char of the line, then carriage return" do
|
||||||
|
before <<-EOF
|
||||||
|
madec
|
||||||
|
|
||||||
|
antoine
|
||||||
|
andre
|
||||||
|
joseph
|
||||||
|
EOF
|
||||||
|
|
||||||
|
type 'Gvip<C-n>i<BS><cr>'
|
||||||
|
|
||||||
|
after <<-EOF
|
||||||
|
madec
|
||||||
|
|
||||||
|
antoine
|
||||||
|
andre
|
||||||
|
joseph
|
||||||
|
EOF
|
||||||
|
end
|
||||||
|
|
||||||
|
specify "#del at EOL, then carriage return" do
|
||||||
|
before <<-EOF
|
||||||
|
madec
|
||||||
|
antoine
|
||||||
|
joseph
|
||||||
|
|
||||||
|
andre
|
||||||
|
EOF
|
||||||
|
|
||||||
|
type 'vip<C-n>A<DEL><cr>'
|
||||||
|
|
||||||
|
after <<-EOF
|
||||||
|
madec
|
||||||
|
antoine
|
||||||
|
joseph
|
||||||
|
|
||||||
|
andre
|
||||||
|
EOF
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "Multiple Cursors misc" do
|
||||||
let(:filename) { 'test.txt' }
|
let(:filename) { 'test.txt' }
|
||||||
let(:options) { ['set autoindent'] }
|
let(:options) { ['set autoindent'] }
|
||||||
|
|
||||||
|
|
|
@ -100,4 +100,11 @@ snippet todo "TODO comment" bw
|
||||||
`!p snip.rv=get_comment_format()[0]` ${2:TODO}: $0${3: <${4:`!v strftime('%d-%m-%y')`}${5:, `!v g:snips_author`}>} `!p snip.rv=get_comment_format()[2]`
|
`!p snip.rv=get_comment_format()[0]` ${2:TODO}: $0${3: <${4:`!v strftime('%d-%m-%y')`}${5:, `!v g:snips_author`}>} `!p snip.rv=get_comment_format()[2]`
|
||||||
endsnippet
|
endsnippet
|
||||||
|
|
||||||
|
##########
|
||||||
|
# Misc #
|
||||||
|
##########
|
||||||
|
snippet uuid "Random UUID" w
|
||||||
|
`!p if not snip.c: import uuid; snip.rv = uuid.uuid4()`
|
||||||
|
endsnippet
|
||||||
|
|
||||||
# vim:ft=snippets:
|
# vim:ft=snippets:
|
||||||
|
|
733
sources_non_forked/vim-snippets/UltiSnips/plsql.snippets
Normal file
733
sources_non_forked/vim-snippets/UltiSnips/plsql.snippets
Normal file
|
@ -0,0 +1,733 @@
|
||||||
|
###########################################################################
|
||||||
|
# PLSQL SNIPPETS #
|
||||||
|
###########################################################################
|
||||||
|
|
||||||
|
global !p
|
||||||
|
# Import package
|
||||||
|
import datetime
|
||||||
|
|
||||||
|
# Return the doc string for PLSQL script
|
||||||
|
def docstring_plsql(params):
|
||||||
|
comment = ""
|
||||||
|
if params:
|
||||||
|
comment = "/** Parameters\n"
|
||||||
|
# Split the arguments
|
||||||
|
args = [arg.strip() for arg in params.split(',')]
|
||||||
|
for arg in args:
|
||||||
|
comment += "* {0:30} : \n".format(arg.split(' ')[0].upper())
|
||||||
|
comment += "*/\n"
|
||||||
|
# Return the comment string
|
||||||
|
return comment
|
||||||
|
|
||||||
|
def hdr_params(params, level=0, gap=" "):
|
||||||
|
line = level * gap + "-- -----------------------------------------------"
|
||||||
|
comment = line
|
||||||
|
if params:
|
||||||
|
# Split the arguments
|
||||||
|
args = [arg.strip() for arg in params.split(',')]
|
||||||
|
for arg in args:
|
||||||
|
comment += "\n" + level * gap + "-- {0:20} : ".format(arg.split(' ')[0].upper())
|
||||||
|
# comment += line
|
||||||
|
# Return the comment string
|
||||||
|
return comment
|
||||||
|
|
||||||
|
def dyear():
|
||||||
|
""" Returns the current Year in YYYY format
|
||||||
|
"""
|
||||||
|
now = datetime.datetime.now()
|
||||||
|
rv=now.year
|
||||||
|
return rv
|
||||||
|
|
||||||
|
def today():
|
||||||
|
""" Returns the current Date in DD-MON-YYYY format
|
||||||
|
"""
|
||||||
|
now = datetime.datetime.now()
|
||||||
|
rv=now.strftime("%d-%b-%Y")
|
||||||
|
return rv
|
||||||
|
|
||||||
|
def param(var):
|
||||||
|
""" Returns the string name wrapped value """
|
||||||
|
return "'" + var + " : ' || "
|
||||||
|
|
||||||
|
endglobal
|
||||||
|
|
||||||
|
########################################
|
||||||
|
# SQL Snippets #
|
||||||
|
########################################
|
||||||
|
snippet doc "Document comment"
|
||||||
|
/*
|
||||||
|
* ${0: comment ...}
|
||||||
|
*/
|
||||||
|
endsnippet
|
||||||
|
|
||||||
|
snippet hdr "Header Documentation"
|
||||||
|
-- #############################################################################
|
||||||
|
-- # Copyright (c) `!p snip.rv = dyear()` ${1:company}
|
||||||
|
-- # All rights reserved
|
||||||
|
-- #
|
||||||
|
-- ############################################################################
|
||||||
|
-- # Application : ${2:schema}
|
||||||
|
-- # File Name: : ${3:`!p snip.rv=snip.fn`}
|
||||||
|
-- # Type : Table
|
||||||
|
-- # Exec Method : PL/SQL File
|
||||||
|
-- # Description : This script ${5:create} under the schema $2
|
||||||
|
-- #
|
||||||
|
-- # Change History
|
||||||
|
-- # -----------------------------------------------------------------------
|
||||||
|
-- # Version Date Author Remarks
|
||||||
|
-- # ======= =========== ================ ============================
|
||||||
|
-- # 1.0 `!p snip.rv = today()` Amit Maindola Initial Version
|
||||||
|
-- #############################################################################
|
||||||
|
|
||||||
|
endsnippet
|
||||||
|
|
||||||
|
snippet pkggbl "Package Global variables"
|
||||||
|
-- Declare Global Variables
|
||||||
|
g_sysdate DATE := SYSDATE;
|
||||||
|
g_delimiter VARCHAR2( 30 ) := ' ';
|
||||||
|
g_err_length_limit NUMBER := 1500;
|
||||||
|
g_package_name CONSTANT VARCHAR2(30) := '${0}';
|
||||||
|
g_proc_name VARCHAR2(100) := NULL;
|
||||||
|
excp_custom EXCEPTION;
|
||||||
|
|
||||||
|
-- Declare User Global Types
|
||||||
|
|
||||||
|
endsnippet
|
||||||
|
|
||||||
|
snippet flushca "Flush Cache"
|
||||||
|
ALTER SYSTEM FLUSH BUFFER_CACHE;
|
||||||
|
endsnippet
|
||||||
|
|
||||||
|
snippet flushsp "Flush Shared Pool"
|
||||||
|
ALTER SYSTEM FLUSH SHARED_POOL;
|
||||||
|
endsnippet
|
||||||
|
|
||||||
|
snippet err
|
||||||
|
show errors;
|
||||||
|
endsnippet
|
||||||
|
|
||||||
|
snippet sel "Select statement"
|
||||||
|
SELECT ${0:*} FROM ${1} WHERE 1 = 1;
|
||||||
|
endsnippet
|
||||||
|
|
||||||
|
snippet selc "Select statement"
|
||||||
|
SELECT COUNT(1) FROM ${1} WHERE ${0};
|
||||||
|
endsnippet
|
||||||
|
|
||||||
|
snippet wrn "Where ROWNNUM"
|
||||||
|
WHERE ROWNUM <= 10 ${0:AND}
|
||||||
|
endsnippet
|
||||||
|
|
||||||
|
snippet arn "AND ROWNNUM"
|
||||||
|
AND ROWNUM <= 10 ${0:;}
|
||||||
|
endsnippet
|
||||||
|
|
||||||
|
snippet ppram "Retuns param in wrapped format"
|
||||||
|
||`!p snip.rv = param(t[1].upper())`$1 $0
|
||||||
|
endsnippet
|
||||||
|
|
||||||
|
snippet dbo "Show output "
|
||||||
|
DBMS_OUTPUT.put_line('${0}');
|
||||||
|
endsnippet
|
||||||
|
|
||||||
|
snippet dbop "Show Parameter output "
|
||||||
|
DBMS_OUTPUT.put_line(`!p snip.rv = param(t[1].upper())`$1 $0);
|
||||||
|
endsnippet
|
||||||
|
|
||||||
|
snippet dbl "Log message in Log Table, Change procedure as defined by you"
|
||||||
|
DEBUG_LOG_PKG.WRITE_LOG(${1:'Test'},${2:$1} ,$0 );
|
||||||
|
endsnippet
|
||||||
|
|
||||||
|
snippet plog "Print Log output "
|
||||||
|
printlog(`!p snip.rv = param(t[1].upper())`$1 $0);
|
||||||
|
endsnippet
|
||||||
|
|
||||||
|
snippet dut "DBMS_OUTPUT.put_line"
|
||||||
|
DBMS_UTILITY.get_time;
|
||||||
|
endsnippet
|
||||||
|
|
||||||
|
snippet bc "Bulk collect into"
|
||||||
|
bulk collect into ${0}
|
||||||
|
endsnippet
|
||||||
|
|
||||||
|
snippet ei "Execute Immediate"
|
||||||
|
EXECUTE IMMEDIATE '${0:statement}' ;
|
||||||
|
endsnippet
|
||||||
|
|
||||||
|
snippet eitt "Execute Immediate TRUNCATE Table"
|
||||||
|
EXECUTE IMMEDIATE( 'TRUNCATE TABLE ${0:table}');
|
||||||
|
endsnippet
|
||||||
|
|
||||||
|
snippet eitp "Execute Immediate ALTER Table Truncate partition"
|
||||||
|
EXECUTE IMMEDIATE( 'ALTER TABLE ${1:table} TRUNCATE PARTITION ${0:partition}');
|
||||||
|
endsnippet
|
||||||
|
|
||||||
|
snippet prmpt "Prompt message"
|
||||||
|
PROMPT ${1:Creating }...
|
||||||
|
endsnippet
|
||||||
|
|
||||||
|
snippet crseq "Create Sequence"
|
||||||
|
DROP SEQUENCE ${1:schema}.${2:name}_s;
|
||||||
|
|
||||||
|
CREATE SEQUENCE $1.$2_s
|
||||||
|
START WITH ${3:1}
|
||||||
|
MAXVALUE 999999999999999999999999999
|
||||||
|
MINVALUE 1
|
||||||
|
NOCYCLE
|
||||||
|
NOCACHE
|
||||||
|
NOORDER;
|
||||||
|
endsnippet
|
||||||
|
|
||||||
|
snippet crsyn "Create Synonym"
|
||||||
|
|
||||||
|
CREATE OR REPLACE SYNONYM ${1:schema}.${2:name} FOR ${3:target}.${0};
|
||||||
|
|
||||||
|
endsnippet
|
||||||
|
|
||||||
|
snippet crind "Create Index"
|
||||||
|
DROP INDEX $1.$4;
|
||||||
|
|
||||||
|
CREATE INDEX $1.${4:$2_${5}}
|
||||||
|
ON ${1:schema}.${2:table}(${3}) ${6:TABLESPACE ${0} };
|
||||||
|
endsnippet
|
||||||
|
|
||||||
|
########################################
|
||||||
|
# Table Operation #
|
||||||
|
########################################
|
||||||
|
|
||||||
|
snippet drtab "Drop Table"
|
||||||
|
DROP TABLE ${1:schema}.${2:name} CASCADE CONSTRAINTS ${3:PURGE};
|
||||||
|
|
||||||
|
endsnippet
|
||||||
|
|
||||||
|
snippet crtab "Create Table"
|
||||||
|
|
||||||
|
DROP TABLE ${1:schema}.${2:name} CASCADE CONSTRAINTS PURGE;
|
||||||
|
|
||||||
|
CREATE TABLE $1.$2
|
||||||
|
(
|
||||||
|
${0}
|
||||||
|
)
|
||||||
|
${3:TABLESPACE ${4}}
|
||||||
|
;
|
||||||
|
endsnippet
|
||||||
|
|
||||||
|
snippet ccol "Add VARCHAR2 column to table"
|
||||||
|
${1:,} ${2:name} VARCHAR2(${0:100})
|
||||||
|
endsnippet
|
||||||
|
|
||||||
|
snippet dcol "Add DATE column to table"
|
||||||
|
${1:,} ${0:name} DATE
|
||||||
|
endsnippet
|
||||||
|
|
||||||
|
snippet ncol "Add NUMBER column to table"
|
||||||
|
${1:,} ${0:name} NUMBER
|
||||||
|
endsnippet
|
||||||
|
|
||||||
|
snippet at "Alter Table"
|
||||||
|
ALTER TABLE ${1:table} ${0}
|
||||||
|
endsnippet
|
||||||
|
|
||||||
|
|
||||||
|
#########################################
|
||||||
|
# Declare Types and local variable #
|
||||||
|
#########################################
|
||||||
|
|
||||||
|
snippet tr "Type record"
|
||||||
|
TYPE t_${1:rec} IS RECORD (${0:/* columns */} );
|
||||||
|
endsnippet
|
||||||
|
|
||||||
|
snippet tt "Type Table"
|
||||||
|
TYPE t_${1:tbl} IS TABLE OF ${0:table_name}%ROWTYPE INDEX BY BINARY_INTEGER;
|
||||||
|
endsnippet
|
||||||
|
|
||||||
|
snippet tc "Type Cursor"
|
||||||
|
TYPE t_${1:tbl} IS TABLE OF ${0:cur}%ROWTYPE INDEX BY BINARY_INTEGER;
|
||||||
|
endsnippet
|
||||||
|
|
||||||
|
snippet pn
|
||||||
|
p_${1} ${2:IN} NUMBER ${3:DEFAULT ${0:NULL}}
|
||||||
|
endsnippet
|
||||||
|
|
||||||
|
snippet pd
|
||||||
|
p_${1} ${2:IN} DATE ${3:DEFAULT ${0:SYSDATE}}
|
||||||
|
endsnippet
|
||||||
|
|
||||||
|
snippet pc
|
||||||
|
P_${1} ${2:IN} VARCHAR2 ${3:DEFAULT ${0:NULL}}
|
||||||
|
endsnippet
|
||||||
|
|
||||||
|
snippet ln
|
||||||
|
l_${1} NUMBER ${2: := ${3} };
|
||||||
|
endsnippet
|
||||||
|
|
||||||
|
snippet ld
|
||||||
|
l_${1} DATE ${2: := ${3} };
|
||||||
|
endsnippet
|
||||||
|
|
||||||
|
snippet lc
|
||||||
|
l_${1} VARCHAR2(${2:100}) ${3: := ${4} };
|
||||||
|
endsnippet
|
||||||
|
|
||||||
|
snippet gn
|
||||||
|
g_${1} NUMBER ${2: := ${3:10} };
|
||||||
|
endsnippet
|
||||||
|
|
||||||
|
snippet gd
|
||||||
|
g_${1} DATE ${2: := ${3:SYSDATE} };
|
||||||
|
endsnippet
|
||||||
|
|
||||||
|
snippet gc
|
||||||
|
g_${1} VARCHAR2(${2:100}) ${3: := ${4} };
|
||||||
|
endsnippet
|
||||||
|
|
||||||
|
snippet ltbl
|
||||||
|
l_tbl_${1} ${0};
|
||||||
|
endsnippet
|
||||||
|
|
||||||
|
snippet lrec
|
||||||
|
l_rec_${1} ${0};
|
||||||
|
endsnippet
|
||||||
|
|
||||||
|
#########################################
|
||||||
|
# Condition, Loops #
|
||||||
|
#########################################
|
||||||
|
snippet if "If Condition"
|
||||||
|
IF(${1}) THEN
|
||||||
|
${0};
|
||||||
|
END IF;
|
||||||
|
endsnippet
|
||||||
|
|
||||||
|
snippet ife "IF-Else Condition"
|
||||||
|
IF(${1}) THEN
|
||||||
|
${2};
|
||||||
|
ELSIF
|
||||||
|
${0};
|
||||||
|
END IF;
|
||||||
|
endsnippet
|
||||||
|
|
||||||
|
snippet els "Else Condition"
|
||||||
|
ELSIF ${1:condition} THEN
|
||||||
|
${0};
|
||||||
|
endsnippet
|
||||||
|
|
||||||
|
snippet case "Case statement"
|
||||||
|
CASE WHEN (${1}) THEN
|
||||||
|
${2}
|
||||||
|
WHEN (${3}) THEN
|
||||||
|
${4}
|
||||||
|
${0:ELSE}
|
||||||
|
END
|
||||||
|
endsnippet
|
||||||
|
|
||||||
|
snippet while "While Loop"
|
||||||
|
WHILE ${1:a} ${2:condition} ${3:b} LOOP
|
||||||
|
${0};
|
||||||
|
END LOOP;
|
||||||
|
endsnippet
|
||||||
|
|
||||||
|
snippet fori "For Loop"
|
||||||
|
FOR ${1:indx} in ${2:1}..${3:10} LOOP
|
||||||
|
${4};
|
||||||
|
END LOOP;
|
||||||
|
endsnippet
|
||||||
|
|
||||||
|
snippet fort "Table For Loop"
|
||||||
|
FOR ${1:indx} in 1..${2:ttb}.count LOOP
|
||||||
|
${0};
|
||||||
|
END LOOP;
|
||||||
|
endsnippet
|
||||||
|
|
||||||
|
snippet loop "Loop statement"
|
||||||
|
LOOP
|
||||||
|
${0};
|
||||||
|
END LOOP;
|
||||||
|
endsnippet
|
||||||
|
|
||||||
|
snippet fora "For All Loop"
|
||||||
|
IF ( ${1:ttbl}.COUNT > 0 ) THEN
|
||||||
|
BEGIN
|
||||||
|
FORALL ${2:indx} IN 1 .. $1.COUNT
|
||||||
|
-- Insert/Update
|
||||||
|
${0}
|
||||||
|
EXCEPTION --Exception Block
|
||||||
|
WHEN OTHERS THEN
|
||||||
|
l_errmsg := 'Error while Bulk updating, Error : ' || SQLERRM;
|
||||||
|
RAISE excp_custom;
|
||||||
|
END;
|
||||||
|
END IF;
|
||||||
|
endsnippet
|
||||||
|
|
||||||
|
snippet forc "For Cursor Loop"
|
||||||
|
FOR $1_rec IN ${1:cur} ${2:(${3:param})}
|
||||||
|
LOOP
|
||||||
|
${0}
|
||||||
|
END LOOP; -- End $1
|
||||||
|
endsnippet
|
||||||
|
|
||||||
|
#########################################
|
||||||
|
# Cursor Operations #
|
||||||
|
#########################################
|
||||||
|
snippet dcur "Cursor declaration"
|
||||||
|
CURSOR ${1:cur} IS
|
||||||
|
SELECT ${0}
|
||||||
|
FROM $1
|
||||||
|
WHERE 1 = 1;
|
||||||
|
endsnippet
|
||||||
|
|
||||||
|
snippet copen "Open Cursor"
|
||||||
|
OPEN ${1:cursor} ${2:( ${3:param} )};
|
||||||
|
FETCH $1
|
||||||
|
INTO ${4:record};
|
||||||
|
${0}
|
||||||
|
IF ( $1 %NOTFOUND ) THEN
|
||||||
|
CLOSE $1;
|
||||||
|
l_errmsg := 'No records fetched in cursor : $1.';
|
||||||
|
RAISE excp_custom;
|
||||||
|
END IF;
|
||||||
|
CLOSE $1;
|
||||||
|
endsnippet
|
||||||
|
|
||||||
|
snippet copenbc "Open Cursor Bulk collect"
|
||||||
|
OPEN ${1:cursor} ${2:( ${3:param} )};
|
||||||
|
FETCH $1
|
||||||
|
BULK COLLECT INTO ${4:ttbl};
|
||||||
|
CLOSE $1;
|
||||||
|
|
||||||
|
IF ( $4.count = 0 ) THEN
|
||||||
|
l_errmsg := 'No records fetched in cursor : $1.';
|
||||||
|
RAISE excp_custom;{0}
|
||||||
|
END IF;
|
||||||
|
endsnippet
|
||||||
|
|
||||||
|
#########################################
|
||||||
|
# BEGIN/DECLARE Blocks #
|
||||||
|
#########################################
|
||||||
|
snippet decl "Declare Begin block"
|
||||||
|
DECLARE
|
||||||
|
${1}
|
||||||
|
BEGIN
|
||||||
|
${0:null}
|
||||||
|
EXCEPTION --Exception Block
|
||||||
|
WHEN NO_DATA_FOUND THEN
|
||||||
|
dbms_output.put_line('No Data Found');
|
||||||
|
WHEN OTHERS THEN
|
||||||
|
dbms_output.put_line('Error while . Error : '||sqlerrm);
|
||||||
|
END;
|
||||||
|
endsnippet
|
||||||
|
|
||||||
|
snippet begin "Begin block"
|
||||||
|
BEGIN
|
||||||
|
${0}
|
||||||
|
EXCEPTION --Exception Block
|
||||||
|
WHEN NO_DATA_FOUND THEN
|
||||||
|
printlog('No Data Found');
|
||||||
|
WHEN OTHERS THEN
|
||||||
|
printlog('Error while . Error : '||sqlerrm);
|
||||||
|
END;
|
||||||
|
endsnippet
|
||||||
|
|
||||||
|
snippet excp "Exception Block"
|
||||||
|
EXCEPTION --Exception Block
|
||||||
|
${0}
|
||||||
|
WHEN OTHERS THEN
|
||||||
|
${1};
|
||||||
|
END;
|
||||||
|
endsnippet
|
||||||
|
|
||||||
|
snippet rae "Raise Application Error"
|
||||||
|
RAISE_APPLICATION_ERROR(${1:-20000},${0:''});
|
||||||
|
endsnippet
|
||||||
|
|
||||||
|
#########################################
|
||||||
|
# Procedure/Function calling #
|
||||||
|
#########################################
|
||||||
|
snippet crjob "Submit DBMS Job"
|
||||||
|
-- Submit the job to get the output
|
||||||
|
BEGIN
|
||||||
|
DECLARE
|
||||||
|
vjob INTEGER;
|
||||||
|
BEGIN
|
||||||
|
DBMS_JOB.submit( vjob, '${1:procedure}${0:('''')};', SYSDATE );
|
||||||
|
DBMS_OUTPUT.put_line( 'Job id : ' || vjob );
|
||||||
|
COMMIT;
|
||||||
|
END;
|
||||||
|
END;
|
||||||
|
endsnippet
|
||||||
|
|
||||||
|
snippet whilejob "Submit DBMS Job with While Loop"
|
||||||
|
-- Submit the job to get the output
|
||||||
|
|
||||||
|
BEGIN
|
||||||
|
DECLARE
|
||||||
|
vjob INTEGER;
|
||||||
|
BEGIN
|
||||||
|
DBMS_JOB.submit ( vjob , '
|
||||||
|
DECLARE
|
||||||
|
l_start_date DATE := ''${1:01-Jan-2017}'';
|
||||||
|
BEGIN
|
||||||
|
WHILE l_start_date < ''${2:01-Jan-2017}''
|
||||||
|
LOOP
|
||||||
|
${3:Procedure}${0:( to_char(l_start_date,''YYYYMMDD'') )};
|
||||||
|
l_start_date := TRUNC( l_start_date + 1 );
|
||||||
|
END LOOP;
|
||||||
|
EXCEPTION --Exception Block
|
||||||
|
WHEN OTHERS THEN
|
||||||
|
DBMS_OUTPUT.put_line( ''Error while . Error : '' || SQLERRM );
|
||||||
|
END;
|
||||||
|
'
|
||||||
|
, SYSDATE
|
||||||
|
);
|
||||||
|
DBMS_OUTPUT.put_line( 'Job id : ' || vjob );
|
||||||
|
COMMIT;
|
||||||
|
END;
|
||||||
|
END;
|
||||||
|
endsnippet
|
||||||
|
|
||||||
|
|
||||||
|
#########################################
|
||||||
|
# Function creation scripts #
|
||||||
|
#########################################
|
||||||
|
snippet crprintlog "Create Printlog Procedure"
|
||||||
|
------------------------------------------------------------------------------------------------
|
||||||
|
-- PROCEDURE : PRINTLOG
|
||||||
|
-- Description : This procedure is used to print log messages in Log file, Table and Console
|
||||||
|
------------------------------------------------------------------------------------------------
|
||||||
|
PROCEDURE printlog (p_message IN VARCHAR2)
|
||||||
|
IS
|
||||||
|
l_errmsg VARCHAR2 (10000);
|
||||||
|
BEGIN
|
||||||
|
l_errmsg := SUBSTR ( p_message, 1, g_err_length_limit);
|
||||||
|
fnd_file.put_line ( fnd_file.LOG, l_errmsg); -- Debug log file
|
||||||
|
DBMS_OUTPUT.put_line (l_errmsg); -- Console output
|
||||||
|
DEBUG_LOG_PKG.WRITE_LOG(g_package_name,g_proc_name,p_message); -- Debug table
|
||||||
|
END printlog;
|
||||||
|
endsnippet
|
||||||
|
|
||||||
|
snippet crgeterr "Create get_errmsg function"
|
||||||
|
-- Form the error message for when others
|
||||||
|
FUNCTION get_errmsg( p_message IN VARCHAR2 DEFAULT NULL )
|
||||||
|
RETURN VARCHAR2
|
||||||
|
IS
|
||||||
|
BEGIN
|
||||||
|
RETURN 'Error occured in ' || g_package_name || '.' || g_proc_name || '. ' || NVL( p_message, '' ) || ' Error : ' || SQLERRM;
|
||||||
|
EXCEPTION --Exception Block
|
||||||
|
WHEN OTHERS THEN
|
||||||
|
printlog( 'Error while forming messgage. Error : ' || SQLERRM );
|
||||||
|
RETURN NULL;
|
||||||
|
END;
|
||||||
|
endsnippet
|
||||||
|
|
||||||
|
snippet crpksfunc "Create package specification function"
|
||||||
|
------------------------------------------------------------------------------------------------
|
||||||
|
-- Function : `!p snip.rv = t[1].upper()`
|
||||||
|
-- Description : This Function will ${4:description}.
|
||||||
|
`!p snip.rv=hdr_params(t[3]) `
|
||||||
|
------------------------------------------------------------------------------------------------
|
||||||
|
FUNCTION ${1:func} ${2:(${3:params})}
|
||||||
|
RETURN ${0};
|
||||||
|
endsnippet
|
||||||
|
|
||||||
|
snippet crpksproc "Create package specification procedure"
|
||||||
|
------------------------------------------------------------------------------------------------
|
||||||
|
-- PROCEDURE : `!p snip.rv = t[1].upper()`
|
||||||
|
-- Description : This Procedure will ${4:description}.
|
||||||
|
`!p snip.rv=hdr_params(t[3],0) `
|
||||||
|
------------------------------------------------------------------------------------------------
|
||||||
|
PROCEDURE ${1:proc} ${2:(${3:params})} ;
|
||||||
|
endsnippet
|
||||||
|
|
||||||
|
snippet crpkbfunc "Create package body function"
|
||||||
|
------------------------------------------------------------------------------------------------
|
||||||
|
-- Function : `!p snip.rv = t[1].upper()`
|
||||||
|
-- Description : This Function will ${8:description}.
|
||||||
|
`!p snip.rv=hdr_params(t[3],2) `
|
||||||
|
------------------------------------------------------------------------------------------------
|
||||||
|
FUNCTION ${1:func} ${2:(${3:params})}
|
||||||
|
RETURN ${4}
|
||||||
|
IS
|
||||||
|
-- Declare Cursors
|
||||||
|
-- Declare Variables
|
||||||
|
${5:l_} $4 ${6:( ${7:length} )};
|
||||||
|
BEGIN
|
||||||
|
-- Initialize
|
||||||
|
g_proc_name := '`!p snip.rv = t[1].upper()`';
|
||||||
|
${0}
|
||||||
|
-- Return value
|
||||||
|
RETURN $5 ;
|
||||||
|
EXCEPTION
|
||||||
|
WHEN OTHERS
|
||||||
|
THEN
|
||||||
|
RETURN NULL;
|
||||||
|
END $1;
|
||||||
|
endsnippet
|
||||||
|
|
||||||
|
snippet crpkbproc "Create package body procedure"
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------------------------
|
||||||
|
-- PROCEDURE : `!p snip.rv = t[1].upper()`
|
||||||
|
-- Description : This Procedure will ${4:description}.
|
||||||
|
`!p snip.rv=hdr_params(t[3]) `
|
||||||
|
------------------------------------------------------------------------------------------------
|
||||||
|
PROCEDURE ${1:proc} ${2:(${3:params})}
|
||||||
|
IS
|
||||||
|
-- Declare cursors
|
||||||
|
-- Declare Out and exception variables
|
||||||
|
l_errmsg VARCHAR2( 10000 ) := null;
|
||||||
|
excp_skip EXCEPTION;
|
||||||
|
-- Declare Varibales
|
||||||
|
|
||||||
|
BEGIN
|
||||||
|
-- Initializing out parameters
|
||||||
|
g_proc_name := '`!p snip.rv = t[1].upper()`';
|
||||||
|
|
||||||
|
${0}
|
||||||
|
EXCEPTION -- Exception block of Procedure
|
||||||
|
WHEN excp_custom THEN
|
||||||
|
ROLLBACK;
|
||||||
|
printlog( l_errmsg );
|
||||||
|
WHEN OTHERS THEN
|
||||||
|
ROLLBACK;
|
||||||
|
l_errmsg := get_errmsg;
|
||||||
|
printlog( l_errmsg );
|
||||||
|
END $1;
|
||||||
|
|
||||||
|
endsnippet
|
||||||
|
|
||||||
|
snippet crpks "Create Package specification"
|
||||||
|
CREATE OR REPLACE PACKAGE ${1}.${2}
|
||||||
|
AS
|
||||||
|
-- #############################################################################
|
||||||
|
-- # Copyright (c) `!p snip.rv = dyear()` ${3}
|
||||||
|
-- # All rights reserved
|
||||||
|
-- #
|
||||||
|
-- ############################################################################
|
||||||
|
-- #
|
||||||
|
-- # Application : $1
|
||||||
|
-- # File Name: : `!p snip.rv = t[2].upper()`.pks
|
||||||
|
-- # Exec Method : PL/SQL Stored - Procedure
|
||||||
|
-- # Description : Package used for ${4}
|
||||||
|
-- #
|
||||||
|
-- # Change History
|
||||||
|
-- # -----------------------------------------------------------------------
|
||||||
|
-- # Version Date Author Remarks
|
||||||
|
-- # ======= =========== ============= ============================
|
||||||
|
-- # 1.0 `!p snip.rv = today()` Amit Maindola Initial Version
|
||||||
|
-- #
|
||||||
|
-- #
|
||||||
|
-- ############################################################################
|
||||||
|
${0}
|
||||||
|
END $2;
|
||||||
|
/
|
||||||
|
|
||||||
|
SHOW ERROR
|
||||||
|
/
|
||||||
|
endsnippet
|
||||||
|
|
||||||
|
snippet crpkb "Create package body"
|
||||||
|
CREATE OR REPLACE PACKAGE BODY ${1}.${2}
|
||||||
|
IS
|
||||||
|
-- #############################################################################
|
||||||
|
-- # Copyright (c) `!p snip.rv = dyear()` ${3}
|
||||||
|
-- # All rights reserved
|
||||||
|
-- #
|
||||||
|
-- ############################################################################
|
||||||
|
-- #
|
||||||
|
-- # Application : $1
|
||||||
|
-- # File Name: : `!p snip.rv = t[2].upper()`.pkb
|
||||||
|
-- # Exec Method : PL/SQL Stored - Procedure
|
||||||
|
-- # Description : Package used for ${4}
|
||||||
|
-- #
|
||||||
|
-- # Change History
|
||||||
|
-- # -----------------------------------------------------------------------
|
||||||
|
-- # Version Date Author Remarks
|
||||||
|
-- # ======= =========== ============= ============================
|
||||||
|
-- # 1.0 `!p snip.rv = today()` Amit Maindola Initial Version
|
||||||
|
-- #
|
||||||
|
-- #
|
||||||
|
-- ############################################################################
|
||||||
|
-- Declare Global Variables
|
||||||
|
g_sysdate DATE := SYSDATE;
|
||||||
|
g_delimiter VARCHAR2( 30 ) := ' ';
|
||||||
|
g_err_length_limit NUMBER := 1500;
|
||||||
|
g_package_name CONSTANT VARCHAR2(30) := '`!p snip.rv = t[2].upper()`';
|
||||||
|
g_proc_name VARCHAR2(100) := NULL;
|
||||||
|
excp_custom EXCEPTION;
|
||||||
|
|
||||||
|
-- Declare User Global Types
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------------------------
|
||||||
|
-- PROCEDURE : PRINTLOG
|
||||||
|
-- Description : This procedure is used to print log messages
|
||||||
|
------------------------------------------------------------------------------------------------
|
||||||
|
PROCEDURE printlog( p_message IN VARCHAR2 )
|
||||||
|
IS
|
||||||
|
BEGIN
|
||||||
|
DBMS_OUTPUT.PUT_LINE( p_message );
|
||||||
|
DEBUG_LOG_PKG.WRITE_LOG(g_package_name,g_proc_name,p_message);
|
||||||
|
END printlog;
|
||||||
|
|
||||||
|
-- Form the error message for when others
|
||||||
|
FUNCTION get_errmsg( p_message IN VARCHAR2 DEFAULT NULL )
|
||||||
|
RETURN VARCHAR2
|
||||||
|
IS
|
||||||
|
BEGIN
|
||||||
|
RETURN 'Error occured in ' || g_package_name || '.' || g_proc_name || '. ' || NVL( p_message, '' ) || ' Error : ' || SQLERRM;
|
||||||
|
EXCEPTION --Exception Block
|
||||||
|
WHEN OTHERS THEN
|
||||||
|
printlog( 'Error while forming messgage. Error : ' || SQLERRM );
|
||||||
|
RETURN NULL;
|
||||||
|
END;
|
||||||
|
|
||||||
|
END $2;
|
||||||
|
/
|
||||||
|
|
||||||
|
SHOW ERROR
|
||||||
|
/
|
||||||
|
|
||||||
|
endsnippet
|
||||||
|
|
||||||
|
snippet crproc "Create procedure"
|
||||||
|
|
||||||
|
CREATE OR REPLACE PROCEDURE ${1:schema}.${2:name} ${3:( ${4:prams} )}
|
||||||
|
-- #############################################################################
|
||||||
|
-- # Copyright (c) `!p snip.rv = dyear()` ${5}
|
||||||
|
-- # All rights reserved
|
||||||
|
-- #
|
||||||
|
-- ############################################################################
|
||||||
|
-- #
|
||||||
|
-- # Application : $1
|
||||||
|
-- # File Name: : `!p snip.rv = t[2].upper()`.prc
|
||||||
|
-- # Exec Method : PL/SQL Stored - Procedure
|
||||||
|
-- # Description : Package used for ${6}
|
||||||
|
-- #
|
||||||
|
-- # Change History
|
||||||
|
-- # -----------------------------------------------------------------------
|
||||||
|
-- # Version Date Author Remarks
|
||||||
|
-- # ======= =========== ============= ============================
|
||||||
|
-- # 1.0 `!p snip.rv = today()` Amit Maindola Initial Version
|
||||||
|
-- #
|
||||||
|
-- #
|
||||||
|
-- ############################################################################
|
||||||
|
is
|
||||||
|
g_proc_name VARCHAR2(30) := '`!p snip.rv = t[2].upper()`';
|
||||||
|
l_errmsg VARCHAR2( 10000 ) := null;
|
||||||
|
excp_custom EXCEPTION;
|
||||||
|
-- Declare cursors
|
||||||
|
-- Declare Varibales
|
||||||
|
BEGIN
|
||||||
|
-- Initializing out parameters
|
||||||
|
|
||||||
|
${0}
|
||||||
|
EXCEPTION -- Exception block of Procedure
|
||||||
|
WHEN excp_custom THEN
|
||||||
|
ROLLBACK;
|
||||||
|
DEBUG_LOG_PKG.WRITE_LOG(g_proc_name,g_proc_name ,l_errmsg );
|
||||||
|
WHEN OTHERS THEN
|
||||||
|
ROLLBACK;
|
||||||
|
l_errmsg := 'Exception in procedure. '||SQLERRM;
|
||||||
|
DEBUG_LOG_PKG.WRITE_LOG(g_proc_name,g_proc_name ,l_errmsg );
|
||||||
|
END $2;
|
||||||
|
|
||||||
|
endsnippet
|
||||||
|
|
|
@ -29,7 +29,7 @@ Return From Keyword ${1:${optional return value}}
|
||||||
endsnippet
|
endsnippet
|
||||||
|
|
||||||
snippet rfki "Return From Keyword If"
|
snippet rfki "Return From Keyword If"
|
||||||
Return From Keyword If ${1:${condition}} ${2:${optional return value}}
|
Return From Keyword If '\${${1:rc}}' != '${2:abc}' ${3:${optional return value}}
|
||||||
endsnippet
|
endsnippet
|
||||||
|
|
||||||
snippet rk "Run Keyword"
|
snippet rk "Run Keyword"
|
||||||
|
@ -54,7 +54,7 @@ Run Keyword And Return ${1:${kw}} ${2:${args}}
|
||||||
endsnippet
|
endsnippet
|
||||||
|
|
||||||
snippet rkari "Run Keyword And Return If"
|
snippet rkari "Run Keyword And Return If"
|
||||||
Run Keyword And Return If ${1:{condition}} ${2:${kw}} ${3:${args}}
|
Run Keyword And Return If '\${${1:rc}}' != '${2:abc}' ${3:${kw}} ${4:${args}}
|
||||||
endsnippet
|
endsnippet
|
||||||
|
|
||||||
snippet rkars "Run Keyword And Return Status"
|
snippet rkars "Run Keyword And Return Status"
|
||||||
|
@ -62,9 +62,12 @@ snippet rkars "Run Keyword And Return Status"
|
||||||
endsnippet
|
endsnippet
|
||||||
|
|
||||||
snippet rki "Run Keyword If"
|
snippet rki "Run Keyword If"
|
||||||
Run Keyword If ${1:${rc} < 0} ${2:${VISUAL:Some keyword returning a value}}
|
Run Keyword If '\${${1:rc}}' != '${2:abc}'
|
||||||
... ELSE IF ${3:'${str}' == 'abc'} ${4:Another keyword}
|
... ${3:${VISUAL:Some keyword returning a value}}
|
||||||
... ELSE ${5:Final keyword}
|
... ELSE IF '\${${4:str}}' != '${5:def}'
|
||||||
|
... ${6:Another keyword}
|
||||||
|
... ELSE
|
||||||
|
... ${7:Final keyword}
|
||||||
endsnippet
|
endsnippet
|
||||||
|
|
||||||
snippet rkiactf "Run Keyword If Any Critical Tests Failed"
|
snippet rkiactf "Run Keyword If Any Critical Tests Failed"
|
||||||
|
@ -102,7 +105,7 @@ Run Keywords
|
||||||
endsnippet
|
endsnippet
|
||||||
|
|
||||||
snippet rku "Run Keyword Unless"
|
snippet rku "Run Keyword Unless"
|
||||||
Run Keyword Unless ${1:${condition}} ${2:${kw}} ${3:${args}}
|
Run Keyword Unless '\${${1:rc}}' != '${2:abc}' ${3:${kw}} ${4:${args}}
|
||||||
endsnippet
|
endsnippet
|
||||||
|
|
||||||
snippet sgv "Set Global Variable"
|
snippet sgv "Set Global Variable"
|
||||||
|
@ -130,7 +133,9 @@ snippet sv "Set Variable"
|
||||||
endsnippet
|
endsnippet
|
||||||
|
|
||||||
snippet svi "Set Variable If"
|
snippet svi "Set Variable If"
|
||||||
\${${1:var}}= Set Variable If ${2:${condition}} ${3:${value true}} ${4:${value false}}
|
\${${1:var}}= Set Variable If '\${${2:rc}}' != '${3:abc}'
|
||||||
|
`!p snip.rv = '...' + ' ' * (len(t[1]) + 23)` ${4:${value true}}
|
||||||
|
`!p snip.rv = '...' + ' ' * (len(t[1]) + 23)` ${5:${value false}}
|
||||||
endsnippet
|
endsnippet
|
||||||
|
|
||||||
snippet wuks "Wait Until Keyword Succeeds"
|
snippet wuks "Wait Until Keyword Succeeds"
|
||||||
|
|
|
@ -113,28 +113,28 @@ snippet it "Individual item" b
|
||||||
endsnippet
|
endsnippet
|
||||||
|
|
||||||
snippet part "Part" b
|
snippet part "Part" b
|
||||||
\part{${1:part name}}
|
\part{${1:part name}}%
|
||||||
\label{prt:${2:${1/(\w+)|\W+/(?1:\L$0\E:_)/ga}}}
|
\label{prt:${2:${1/(\w+)|\W+/(?1:\L$0\E:_)/ga}}}
|
||||||
|
|
||||||
$0
|
$0
|
||||||
endsnippet
|
endsnippet
|
||||||
|
|
||||||
snippet cha "Chapter" b
|
snippet cha "Chapter" b
|
||||||
\chapter{${1:chapter name}}
|
\chapter{${1:chapter name}}%
|
||||||
\label{cha:${2:${1/\\\w+\{(.*?)\}|\\(.)|(\w+)|([^\w\\]+)/(?4:_:\L$1$2$3\E)/ga}}}
|
\label{cha:${2:${1/\\\w+\{(.*?)\}|\\(.)|(\w+)|([^\w\\]+)/(?4:_:\L$1$2$3\E)/ga}}}
|
||||||
|
|
||||||
$0
|
$0
|
||||||
endsnippet
|
endsnippet
|
||||||
|
|
||||||
snippet sec "Section" b
|
snippet sec "Section" b
|
||||||
\section{${1:section name}}
|
\section{${1:section name}}%
|
||||||
\label{sec:${2:${1/\\\w+\{(.*?)\}|\\(.)|(\w+)|([^\w\\]+)/(?4:_:\L$1$2$3\E)/ga}}}
|
\label{sec:${2:${1/\\\w+\{(.*?)\}|\\(.)|(\w+)|([^\w\\]+)/(?4:_:\L$1$2$3\E)/ga}}}
|
||||||
|
|
||||||
$0
|
$0
|
||||||
endsnippet
|
endsnippet
|
||||||
|
|
||||||
snippet sec* "Section" b
|
snippet sec* "Section" b
|
||||||
\section*{${1:section name}}
|
\section*{${1:section name}}%
|
||||||
\label{sec:${2:${1/\\\w+\{(.*?)\}|\\(.)|(\w+)|([^\w\\]+)/(?4:_:\L$1$2$3\E)/ga}}}
|
\label{sec:${2:${1/\\\w+\{(.*?)\}|\\(.)|(\w+)|([^\w\\]+)/(?4:_:\L$1$2$3\E)/ga}}}
|
||||||
|
|
||||||
${0}
|
${0}
|
||||||
|
@ -142,42 +142,42 @@ endsnippet
|
||||||
|
|
||||||
|
|
||||||
snippet sub "Subsection" b
|
snippet sub "Subsection" b
|
||||||
\subsection{${1:subsection name}}
|
\subsection{${1:subsection name}}%
|
||||||
\label{sub:${2:${1/\\\w+\{(.*?)\}|\\(.)|(\w+)|([^\w\\]+)/(?4:_:\L$1$2$3\E)/ga}}}
|
\label{sub:${2:${1/\\\w+\{(.*?)\}|\\(.)|(\w+)|([^\w\\]+)/(?4:_:\L$1$2$3\E)/ga}}}
|
||||||
|
|
||||||
$0
|
$0
|
||||||
endsnippet
|
endsnippet
|
||||||
|
|
||||||
snippet sub* "Subsection" b
|
snippet sub* "Subsection" b
|
||||||
\subsection*{${1:subsection name}}
|
\subsection*{${1:subsection name}}%
|
||||||
\label{sub:${2:${1/\\\w+\{(.*?)\}|\\(.)|(\w+)|([^\w\\]+)/(?4:_:\L$1$2$3\E)/ga}}}
|
\label{sub:${2:${1/\\\w+\{(.*?)\}|\\(.)|(\w+)|([^\w\\]+)/(?4:_:\L$1$2$3\E)/ga}}}
|
||||||
|
|
||||||
${0}
|
${0}
|
||||||
endsnippet
|
endsnippet
|
||||||
|
|
||||||
snippet ssub "Subsubsection" b
|
snippet ssub "Subsubsection" b
|
||||||
\subsubsection{${1:subsubsection name}}
|
\subsubsection{${1:subsubsection name}}%
|
||||||
\label{ssub:${2:${1/\\\w+\{(.*?)\}|\\(.)|(\w+)|([^\w\\]+)/(?4:_:\L$1$2$3\E)/ga}}}
|
\label{ssub:${2:${1/\\\w+\{(.*?)\}|\\(.)|(\w+)|([^\w\\]+)/(?4:_:\L$1$2$3\E)/ga}}}
|
||||||
|
|
||||||
$0
|
$0
|
||||||
endsnippet
|
endsnippet
|
||||||
|
|
||||||
snippet ssub* "Subsubsection" b
|
snippet ssub* "Subsubsection" b
|
||||||
\subsubsection*{${1:subsubsection name}}
|
\subsubsection*{${1:subsubsection name}}%
|
||||||
\label{ssub:${2:${1/\\\w+\{(.*?)\}|\\(.)|(\w+)|([^\w\\]+)/(?4:_:\L$1$2$3\E)/ga}}}
|
\label{ssub:${2:${1/\\\w+\{(.*?)\}|\\(.)|(\w+)|([^\w\\]+)/(?4:_:\L$1$2$3\E)/ga}}}
|
||||||
|
|
||||||
${0}
|
${0}
|
||||||
endsnippet
|
endsnippet
|
||||||
|
|
||||||
snippet par "Paragraph" b
|
snippet par "Paragraph" b
|
||||||
\paragraph{${1:paragraph name}}
|
\paragraph{${1:paragraph name}}%
|
||||||
\label{par:${2:${1/\\\w+\{(.*?)\}|\\(.)|(\w+)|([^\w\\]+)/(?4:_:\L$1$2$3\E)/ga}}}
|
\label{par:${2:${1/\\\w+\{(.*?)\}|\\(.)|(\w+)|([^\w\\]+)/(?4:_:\L$1$2$3\E)/ga}}}
|
||||||
|
|
||||||
$0
|
$0
|
||||||
endsnippet
|
endsnippet
|
||||||
|
|
||||||
snippet subp "Subparagraph" b
|
snippet subp "Subparagraph" b
|
||||||
\subparagraph{${1:subparagraph name}}
|
\subparagraph{${1:subparagraph name}}%
|
||||||
\label{par:${2:${1/\\\w+\{(.*?)\}|\\(.)|(\w+)|([^\w\\]+)/(?4:_:\L$1$2$3\E)/ga}}}
|
\label{par:${2:${1/\\\w+\{(.*?)\}|\\(.)|(\w+)|([^\w\\]+)/(?4:_:\L$1$2$3\E)/ga}}}
|
||||||
|
|
||||||
$0
|
$0
|
||||||
|
|
|
@ -204,6 +204,8 @@ snippet try
|
||||||
}catch(${1}) {
|
}catch(${1}) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
snippet af auto function
|
||||||
|
auto ${1:name}(${2}) -> ${3:void}
|
||||||
|
{
|
||||||
|
${0}
|
||||||
|
};
|
||||||
|
|
|
@ -4,16 +4,16 @@
|
||||||
# PowerShell Class
|
# PowerShell Class
|
||||||
snippet class
|
snippet class
|
||||||
class {
|
class {
|
||||||
[string] ${0:FirstName}
|
[string] ${1:FirstName}
|
||||||
}
|
}
|
||||||
|
|
||||||
# PowerShell Advanced Function
|
# PowerShell Advanced Function
|
||||||
snippet function
|
snippet function
|
||||||
function {0:name} {
|
function ${1:name} {
|
||||||
[CmdletBinding()]
|
[CmdletBinding()]
|
||||||
param (
|
param (
|
||||||
[Parameter(Mandatory = $true)]
|
[Parameter(Mandatory = $true)]
|
||||||
[string] $Param1
|
[string] ${2:Param}
|
||||||
)
|
)
|
||||||
|
|
||||||
begin {
|
begin {
|
||||||
|
@ -29,30 +29,74 @@ snippet function
|
||||||
# PowerShell Splatting
|
# PowerShell Splatting
|
||||||
snippet splatting
|
snippet splatting
|
||||||
$Params = @{
|
$Params = @{
|
||||||
${0:Param1} = 'Value1'
|
${1:Param1} = '{2:Value1}'
|
||||||
${1:Param2} = 'Value2'
|
${3:Param2} = '{4:Value2}'
|
||||||
}
|
}
|
||||||
${3:CommandName}
|
${5:CommandName} @Params
|
||||||
|
|
||||||
# PowerShell Enumeration
|
# PowerShell Enumeration
|
||||||
snippet enum
|
snippet enum
|
||||||
enum ${0:name} {
|
enum ${1:name} {
|
||||||
${1:item1}
|
${2:item1}
|
||||||
${2:item2}
|
${3:item2}
|
||||||
}
|
}
|
||||||
|
|
||||||
# PowerShell if..then
|
# PowerShell if..then
|
||||||
snippet if
|
snippet if
|
||||||
if (${0:condition}) {
|
if (${1:condition}) {
|
||||||
${1:statement}
|
${2:statement}
|
||||||
|
}
|
||||||
|
|
||||||
|
# PowerShell if..else
|
||||||
|
snippet ife
|
||||||
|
if ( ${1:condition} ) {
|
||||||
|
${2}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
${3}
|
||||||
}
|
}
|
||||||
|
|
||||||
# PowerShell While Loop
|
# PowerShell While Loop
|
||||||
snippet while
|
snippet while
|
||||||
while (${0:condition}) {
|
while (${1:condition}) {
|
||||||
${1:statement}
|
${2:statement}
|
||||||
}
|
}
|
||||||
|
|
||||||
# PowerShell Filter..Sort
|
# PowerShell Filter..Sort
|
||||||
snippet filtersort
|
snippet filtersort
|
||||||
${0:command} | Where-Object -FilterScript { $PSItem.${1:property} -${2:operator} '${3:expression}' } | Sort-Object -Property ${4:sortproperty}
|
${1:command} | Where-Object -FilterScript { $PSItem.${2:property} -${3:operator} '${4:expression}' } | Sort-Object -Property ${5:sortproperty}
|
||||||
|
|
||||||
|
# PowerShell foreach
|
||||||
|
snippet foreach
|
||||||
|
foreach ( $${1:iterator} in $${2:collection} ) {
|
||||||
|
${3:statement}
|
||||||
|
}
|
||||||
|
|
||||||
|
# PowerShell export-csv
|
||||||
|
snippet epcsv
|
||||||
|
Export-CSV -NoTypeInformation -Path ${1:path}
|
||||||
|
|
||||||
|
# Powershell Comment Based Help
|
||||||
|
snippet help
|
||||||
|
<#
|
||||||
|
.SYNOPSIS
|
||||||
|
${1:Short Description}
|
||||||
|
.DESCRIPTION
|
||||||
|
${2:Full Description}
|
||||||
|
.PARAMETER ${3:Param1}
|
||||||
|
${4: $3 usage}
|
||||||
|
.EXAMPLE
|
||||||
|
${5:Example}
|
||||||
|
.NOTES
|
||||||
|
${6:notes}
|
||||||
|
.LINK
|
||||||
|
${7:online help}
|
||||||
|
#>
|
||||||
|
|
||||||
|
# Powershell switch statement
|
||||||
|
snippet switch
|
||||||
|
switch ( ${1:test} ){
|
||||||
|
${2:condition1} { ${3:action} }
|
||||||
|
${4:condition2} { ${5:action} }
|
||||||
|
default { ${6:action} }
|
||||||
|
|
||||||
|
|
|
@ -1,87 +1,60 @@
|
||||||
# Snippets for use with VIM and http://www.vim.org/scripts/script.php?script_id=2540
|
# Snippets for use with VIM and http://www.vim.org/scripts/script.php?script_id=2540
|
||||||
#
|
#
|
||||||
# Please contact R.I.Pienaar <rip@devco.net> for additions and feedback,
|
# Please contact Jorge Vidal <im@jor.ge> for additions and feedback,
|
||||||
# see it in action @ http://www.devco.net/archives/2009/09/22/vim_and_puppet.php
|
# see it in action @ http://www.devco.net/archives/2009/09/22/vim_and_puppet.php
|
||||||
|
# Many thanks to the original author R.I.Pienaar <rip@devco.net>
|
||||||
|
|
||||||
# Header to match http://docs.puppetlabs.com/guides/style_guide.html#puppet-doc
|
# Header using Puppet Strings (YARD tags) https://puppet.com/docs/puppet/latest/modules_documentation.html
|
||||||
|
# More info: https://github.com/puppetlabs/puppet-strings
|
||||||
snippet classheader
|
snippet classheader
|
||||||
# == Class: ${1:`vim_snippets#Filename(expand('%:p:s?.*modules/??:h:h'), 'name')`}
|
# ${1:`vim_snippets#Filename(expand('%:p:s?.*modules/??:h:h'), 'class-name')`}
|
||||||
|
# ${2:A description of what this class does}
|
||||||
#
|
#
|
||||||
# ${2:Full description of class $1 here}
|
# @summary ${3:A short summary of the purpose of this class}
|
||||||
#
|
#
|
||||||
# === Parameters
|
# @param ${4:parameter1} [${5:String}]
|
||||||
|
# ${6:Explanation of what this parameter affects.}
|
||||||
#
|
#
|
||||||
# Document parameters here.
|
# @example Simple use
|
||||||
#
|
# class { '$1': }
|
||||||
# [*parameter1*]
|
|
||||||
# Explanation of what this parameter affects and what it defaults to.
|
|
||||||
# e.g. "Specify one or more upstream ntp servers as an array."
|
|
||||||
#
|
|
||||||
# === Variables
|
|
||||||
#
|
|
||||||
# Here you should define a list of variables that this module would require.
|
|
||||||
#
|
|
||||||
# [*variable1*]
|
|
||||||
# Explanation of how this variable affects the funtion of this class and
|
|
||||||
# if it has a default. e.g. "The parameter enc_ntp_servers must be set by the
|
|
||||||
# External Node Classifier as a comma separated list of hostnames."
|
|
||||||
#
|
|
||||||
# === Examples
|
|
||||||
#
|
#
|
||||||
|
# @example Use with params
|
||||||
# class { '$1':
|
# class { '$1':
|
||||||
# parameter1 => [ 'just', 'an', 'example', ]
|
# $$4 => '${7:undef}',
|
||||||
# }
|
# }
|
||||||
#
|
#
|
||||||
# === Authors
|
# @author ${8:`g:snips_author`} <${9:`g:snips_email`}>
|
||||||
#
|
#
|
||||||
# `g:snips_author` <`g:snips_email`>
|
# @note Copyright `strftime("%Y")` $8
|
||||||
#
|
#
|
||||||
# === Copyright
|
class $1(
|
||||||
#
|
$$4 = undef,
|
||||||
# Copyright `strftime("%Y")` `g:snips_author`
|
) {
|
||||||
#
|
${0}
|
||||||
class $1 (${3}){
|
|
||||||
${4}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
snippet defheader
|
snippet defheader
|
||||||
# == Define: ${1:`vim_snippets#Filename(expand('%:p:s?.*modules/??:r:s?/manifests/?::?'), 'name')`}
|
# ${1:`vim_snippets#Filename(expand('%:p:s?.*modules/??:h:h'), 'define-name')`}
|
||||||
|
# ${2:A description of what this define does}
|
||||||
#
|
#
|
||||||
# ${2:Full description of defined resource type $1 here}
|
# @summary ${3:A short summary of the purpose of this define}
|
||||||
#
|
#
|
||||||
# === Parameters
|
# @param ${4:parameter1} [${5:String}]
|
||||||
#
|
# ${6:Explanation of what this parameter affects.}
|
||||||
# Document parameters here
|
|
||||||
#
|
|
||||||
# [*namevar*]
|
|
||||||
# If there is a parameter that defaults to the value of the title string
|
|
||||||
# when not explicitly set, you must always say so. This parameter can be
|
|
||||||
# referred to as a "namevar," since it's functionally equivalent to the
|
|
||||||
# namevar of a core resource type.
|
|
||||||
#
|
|
||||||
# [*basedir*]
|
|
||||||
# Description of this variable. For example, "This parameter sets the
|
|
||||||
# base directory for this resource type. It should not contain a trailing
|
|
||||||
# slash."
|
|
||||||
#
|
|
||||||
# === Examples
|
|
||||||
#
|
|
||||||
# Provide some examples on how to use this type:
|
|
||||||
#
|
#
|
||||||
|
# @example Simple use
|
||||||
# $1 { 'namevar':
|
# $1 { 'namevar':
|
||||||
# basedir => '/tmp/src',
|
# $$4 => '${7:undef}',
|
||||||
# }
|
# }
|
||||||
#
|
#
|
||||||
# === Authors
|
# @author ${8:`g:snips_author`} <${9:`g:snips_email`}>
|
||||||
#
|
#
|
||||||
# `g:snips_author` <`g:snips_email`>
|
# @note Copyright `strftime("%Y")` $8
|
||||||
#
|
#
|
||||||
# === Copyright
|
define $1(
|
||||||
#
|
$$4 = undef,
|
||||||
# Copyright `strftime("%Y")` `g:snips_author`
|
) {
|
||||||
#
|
${0}
|
||||||
define $1(${3}) {
|
|
||||||
${4}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# Language Constructs
|
# Language Constructs
|
||||||
|
|
|
@ -115,21 +115,21 @@ snippet try Try/Except
|
||||||
${1:${VISUAL}}
|
${1:${VISUAL}}
|
||||||
except ${2:Exception} as ${3:e}:
|
except ${2:Exception} as ${3:e}:
|
||||||
${0:raise $3}
|
${0:raise $3}
|
||||||
snippet try Try/Except/Else
|
snippet trye Try/Except/Else
|
||||||
try:
|
try:
|
||||||
${1:${VISUAL}}
|
${1:${VISUAL}}
|
||||||
except ${2:Exception} as ${3:e}:
|
except ${2:Exception} as ${3:e}:
|
||||||
${4:raise $3}
|
${4:raise $3}
|
||||||
else:
|
else:
|
||||||
${0}
|
${0}
|
||||||
snippet try Try/Except/Finally
|
snippet tryf Try/Except/Finally
|
||||||
try:
|
try:
|
||||||
${1:${VISUAL}}
|
${1:${VISUAL}}
|
||||||
except ${2:Exception} as ${3:e}:
|
except ${2:Exception} as ${3:e}:
|
||||||
${4:raise $3}
|
${4:raise $3}
|
||||||
finally:
|
finally:
|
||||||
${0}
|
${0}
|
||||||
snippet try Try/Except/Else/Finally
|
snippet tryef Try/Except/Else/Finally
|
||||||
try:
|
try:
|
||||||
${1:${VISUAL}}
|
${1:${VISUAL}}
|
||||||
except ${2:Exception} as ${3:e}:
|
except ${2:Exception} as ${3:e}:
|
||||||
|
|
|
@ -42,10 +42,10 @@ snippet defcreate
|
||||||
if @$1.save
|
if @$1.save
|
||||||
flash[:notice] = '$2 was successfully created.'
|
flash[:notice] = '$2 was successfully created.'
|
||||||
format.html { redirect_to(@$1) }
|
format.html { redirect_to(@$1) }
|
||||||
format.xml { render xml: @$1, status: :created, location: @$1 }
|
format.json { render json: @$1, status: :created, location: @$1 }
|
||||||
else
|
else
|
||||||
format.html { render action: 'new' }
|
format.html { render action: 'new' }
|
||||||
format.xml { render xml: @$1.errors, status: :unprocessable_entity }
|
format.json { render json: @$1.errors, status: :unprocessable_entity }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -56,7 +56,7 @@ snippet defdestroy
|
||||||
|
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.html { redirect_to($1s_url) }
|
format.html { redirect_to($1s_url) }
|
||||||
format.xml { head :ok }
|
format.json { head :ok }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
snippet defedit
|
snippet defedit
|
||||||
|
@ -69,7 +69,7 @@ snippet defindex
|
||||||
|
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.html # index.html.erb
|
format.html # index.html.erb
|
||||||
format.xml { render xml: @$1s }
|
format.json { render json: @$1s }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
snippet defnew
|
snippet defnew
|
||||||
|
@ -78,7 +78,7 @@ snippet defnew
|
||||||
|
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.html # new.html.erb
|
format.html # new.html.erb
|
||||||
format.xml { render xml: @$1 }
|
format.json { render json: @$1 }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
snippet defshow
|
snippet defshow
|
||||||
|
@ -87,7 +87,7 @@ snippet defshow
|
||||||
|
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.html # show.html.erb
|
format.html # show.html.erb
|
||||||
format.xml { render xml: @$1 }
|
format.json { render json: @$1 }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
snippet defupdate
|
snippet defupdate
|
||||||
|
@ -98,10 +98,10 @@ snippet defupdate
|
||||||
if @$1.update($1_params)
|
if @$1.update($1_params)
|
||||||
flash[:notice] = '$2 was successfully updated.'
|
flash[:notice] = '$2 was successfully updated.'
|
||||||
format.html { redirect_to(@$1) }
|
format.html { redirect_to(@$1) }
|
||||||
format.xml { head :ok }
|
format.json { head :ok }
|
||||||
else
|
else
|
||||||
format.html { render action: 'edit' }
|
format.html { render action: 'edit' }
|
||||||
format.xml { render xml: @$1.errors, status: :unprocessable_entity }
|
format.json { render json: @$1.errors, status: :unprocessable_entity }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -292,7 +292,9 @@ snippet block block environment
|
||||||
\\begin{block}{${1:title}}
|
\\begin{block}{${1:title}}
|
||||||
${0:${VISUAL}}
|
${0:${VISUAL}}
|
||||||
\\end{block}
|
\\end{block}
|
||||||
snippet alert alertblock environment
|
snippet alert alert text
|
||||||
|
\\alert{${1:${VISUAL:text}}} ${0}
|
||||||
|
snippet alertblock alertblock environment
|
||||||
\\begin{alertblock}{${1:title}}
|
\\begin{alertblock}{${1:title}}
|
||||||
${0:${VISUAL}}
|
${0:${VISUAL}}
|
||||||
\\end{alertblock}
|
\\end{alertblock}
|
||||||
|
@ -309,6 +311,12 @@ snippet col2 two-column environment
|
||||||
${0}
|
${0}
|
||||||
\\end{column}
|
\\end{column}
|
||||||
\\end{columns}
|
\\end{columns}
|
||||||
|
snippet multicol2 two-column environment with multicol
|
||||||
|
\\begin{multicols}{2}
|
||||||
|
${1}
|
||||||
|
\columnbreak
|
||||||
|
${0}
|
||||||
|
\\end{multicols}
|
||||||
snippet \{ \{ \}
|
snippet \{ \{ \}
|
||||||
\\{ ${0} \\}
|
\\{ ${0} \\}
|
||||||
#delimiter
|
#delimiter
|
||||||
|
|
|
@ -146,24 +146,13 @@ let g:go_fmt_command = "goimports"
|
||||||
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||||
" => Syntastic (syntax checker)
|
" => Syntastic (syntax checker)
|
||||||
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||||
" Python
|
let g:ale_linters = {
|
||||||
let g:syntastic_python_checkers=['pyflakes']
|
\ 'javascript': ['jshint'],
|
||||||
|
\ 'python': ['flake8'],
|
||||||
|
\ 'go': ['go', 'golint', 'errcheck']
|
||||||
|
\}
|
||||||
|
|
||||||
" Javascript
|
nmap <silent> <leader>a <Plug>(ale_next_wrap)
|
||||||
let g:syntastic_javascript_checkers = ['jshint']
|
|
||||||
|
|
||||||
" Go
|
|
||||||
let g:syntastic_auto_loc_list = 1
|
|
||||||
let g:syntastic_go_checkers = ['go', 'golint', 'errcheck']
|
|
||||||
|
|
||||||
" Custom CoffeeScript SyntasticCheck
|
|
||||||
func! SyntasticCheckCoffeescript()
|
|
||||||
let l:filename = substitute(expand("%:p"), '\(\w\+\)\.coffee', '.coffee.\1.js', '')
|
|
||||||
execute "tabedit " . l:filename
|
|
||||||
execute "SyntasticCheck"
|
|
||||||
execute "Errors"
|
|
||||||
endfunc
|
|
||||||
nnoremap <silent> <leader>c :call SyntasticCheckCoffeescript()<cr>
|
|
||||||
|
|
||||||
|
|
||||||
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||||
|
|
Loading…
Reference in a new issue