diff --git a/.gitignore b/.gitignore index 66d01465..55273366 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,10 @@ -temp_dirs/undodir* +temp_dirs/undodir/* sources_non_forked/ack.vim/.netrwhist temp_dirs/yankring_history_v2.txt sources_forked/yankring/doc/tags sources_non_forked/tlib/doc/tags +sources_non_forked/ctrlp.vim/doc/tags* +my_plugins/ my_configs.vim tags .DS_Store diff --git a/README.md b/README.md index ab559418..ea93e17d 100644 --- a/README.md +++ b/README.md @@ -1,28 +1,42 @@ +![VIM](https://dnp4pehkvoo6n.cloudfront.net/43c5af597bd5c1a64eb1829f011c208f/as/Ultimate%20Vimrc.svg) + # The Ultimate vimrc -Over the last 8 years I have used and tweaked Vim. This is my Ultimate vimrc. +Over the last 10 years, I have used and tweaked Vim. This configuration is the ultimate vimrc (or at least my version of it). There are two versions: -* **Basic**: If you want something small just copy [basic.vim](https://github.com/amix/vimrc/blob/master/vimrcs/basic.vim) into your ~/.vimrc and you will have a great basic setup -* **Awesome**: This includes a ton of useful plugins, color schemes and configurations +* **The Basic**: If you want something small just copy [basic.vim](https://github.com/amix/vimrc/blob/master/vimrcs/basic.vim) into your ~/.vimrc and you will have a good basic setup +* **The Awesome**: Includes a ton of useful plugins, color schemes, and configurations + +I would, of course, recommend using the awesome version. -I would of course recommend using the awesome version.c ## How to install the Awesome version? -The awesome version includes a lot of great plugins, configurations and color schemes that make Vim a lot better. To install it simply do following: - git clone https://github.com/amix/vimrc.git ~/.vim_runtime - sh ~/.vim_runtime/install_awesome_vimrc.sh +The awesome version includes a lot of great plugins, configurations and color schemes that make Vim a lot better. To install it simply do following from your terminal: + + git clone --depth=1 https://github.com/amix/vimrc.git ~/.vim_runtime + sh ~/.vim_runtime/install_awesome_vimrc.sh + + +## Fonts + +I recommend using [IBM Plex Mono font](https://ibm.github.io/type/) (it's an open-source and awesome font that can make your code beautiful). The Awesome vimrc is already setup to try to use it. + +Some other fonts that Awesome will try to use: + +* [Hack](http://sourcefoundry.org/hack/) +* [Source Code Pro](https://adobe-fonts.github.io/source-code-pro/) -I also recommend using [Source Code Pro font from Adobe](http://store1.adobe.com/cfusion/store/html/index.cfm?event=displayFontPackage&code=1960) (it's free and awesome font for writing and programming). The Awesome vimrc is already setup to try to use it ## How to install the Basic version? -The basic version is basically just one file and no plugins. You can check out [basic.vim](https://github.com/amix/vimrc/blob/master/vimrcs/basic.vim). -This is useful to install on remote servers where you don't need many plugins and you don't do many edits. +The basic version is just one file and no plugins. Just copy [basic.vim](https://github.com/amix/vimrc/blob/master/vimrcs/basic.vim) and paste it into your vimrc. - git clone git://github.com/amix/vimrc.git ~/.vim_runtime +The basic version is useful to install on remote servers where you don't need many plugins, and you don't do many edits. + + git clone --depth=1 git://github.com/amix/vimrc.git ~/.vim_runtime sh ~/.vim_runtime/install_basic_vimrc.sh @@ -31,9 +45,14 @@ This is useful to install on remote servers where you don't need many plugins an Use [msysgit](http://msysgit.github.com/) to checkout the repository and run the installation instructions above. No special instructions needed ;-) +## How to install on Linux + +If you have vim aliased as `vi` instead of `vim`, make sure to either alias it: `alias vi=vim`. Otherwise, `apt-get install vim` + + ## How to update to latest version? -Simply just do a git rebase! +Just do a git rebase! cd ~/.vim_runtime git pull --rebase @@ -42,49 +61,47 @@ Simply just do a git rebase! ## Some screenshots Colors when editing a Python file: -![Screenshot 1](http://files1.wedoist.com/e952fdb343b1e617b90d256e474d0370/as/screenshot_1.png) -Opening recently opened files [mru.vim](https://github.com/vim-scripts/mru.vim): -![Screenshot 2](http://files1.wedoist.com/1967b0e48af40e513d1a464e08196990/as/screenshot_2.png) +![Screenshot 1](https://dnp4pehkvoo6n.cloudfront.net/07583008e4da885801657e8781777844/as/Python%20editing.png) + +Opening recently opened files with the [mru.vim](https://github.com/vim-scripts/mru.vim) plugin: + +![Screenshot 2](https://dnp4pehkvoo6n.cloudfront.net/1d49a88f9bd5d013c025bb1e1272a7d8/as/MRU%20plugin.png) [NERD Tree](https://github.com/scrooloose/nerdtree) plugin in a terminal window: -![Screenshot 3](http://files1.wedoist.com/b1509d7ed9e9f357e8d04797f9fad67b/as/screenshot3.png) - -This vimrc even works on Windows! -![Screenshot 4](http://files1.wedoist.com/4e85163d97b81422240c822c82022f2f/as/screenshot_4.png) +![Screenshot 3](https://dnp4pehkvoo6n.cloudfront.net/ae719203166585d64728f28398f4b1b7/as/Terminal%20usage.png) Distraction free mode using [goyo.vim](https://github.com/junegunn/goyo.vim) and [vim-zenroom2](https://github.com/amix/vim-zenroom2): -![Screenshot 5](https://d2dq6e731uoz0t.cloudfront.net/a5182977c3d6c2a6cd3f9e97398ca8ca/as/zen_mode.jpg) +![Screenshot 4](https://dnp4pehkvoo6n.cloudfront.net/f0dcc4c9739148c56cbf8285a910ac41/as/Zen%20mode.png) ## Included Plugins -I recommend reading the docs of these plugins to understand them better. Each of them provide a much better Vim experience! +I recommend reading the docs of these plugins to understand them better. Each plugin provides a much better Vim experience! -* [pathogen.vim](https://github.com/tpope/vim-pathogen): Manages the runtime path of the plugins -* [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 -* [bufexplorer.zip](https://github.com/vim-scripts/bufexplorer.zip): Buffer Explorer / Browser. This plugin can be opened with `` +* [ack.vim](https://github.com/mileszs/ack.vim): Vim plugin for `the_silver_searcher` (ag) or ack -- a wicked fast grep +* [bufexplorer.zip](https://github.com/vim-scripts/bufexplorer.zip): Quickly and easily switch between buffers. This plugin can be opened with `` +* [ctrlp.vim](https://github.com/ctrlpvim/ctrlp.vim): Fuzzy file, buffer, mru and tag finder. It's mapped to `` +* [goyo.vim](https://github.com/junegunn/goyo.vim) and [vim-zenroom2](https://github.com/amix/vim-zenroom2): +* [lightline.vim](https://github.com/itchyny/lightline.vim): A light and configurable statusline/tabline for Vim * [NERD Tree](https://github.com/scrooloose/nerdtree): A tree explorer plugin for vim -* [ack.vim](https://github.com/mileszs/ack.vim): Vim plugin for the Perl module / CLI script 'ack' -* [ag.vim](https://github.com/rking/ag.vim): A much faster Ack -* [ctrlp.vim](https://github.com/ctrlpvim/ctrlp.vim): Fuzzy file, buffer, mru and tag finder. In my config it's mapped to ``, because `` is used by YankRing -* [mru.vim](https://github.com/vim-scripts/mru.vim): Plugin to manage Most Recently Used (MRU) files. Includes my own fork which adds syntax highlighting to MRU. This plugin can be opened with `` +* [mru.vim](https://github.com/vim-scripts/mru.vim): Plugin to manage Most Recently Used (MRU) files. This plugin can be opened with `` * [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 +* [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 +* [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-fugitive](https://github.com/tpope/vim-fugitive): A Git wrapper so awesome, it should be illegal * [vim-indent-object](https://github.com/michaeljsmith/vim-indent-object): Defines a new text object representing lines of code at the same indent level. Useful for python/vim scripts * [vim-multiple-cursors](https://github.com/terryma/vim-multiple-cursors): Sublime Text style multiple selections for Vim, CTRL+N is remapped to CTRL+S (due to YankRing) -* [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 -* [goyo.vim](https://github.com/junegunn/goyo.vim) and [vim-zenroom2](https://github.com/amix/vim-zenroom2): -Remove all clutter and focus only on the essential. Similar to iA Writer or Write Room [Read more here](http://amix.dk/blog/post/19744) -* [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. -* [syntastic](https://github.com/scrooloose/syntastic): Syntax checking hacks for vim * [vim-yankstack](https://github.com/maxbrunsfeld/vim-yankstack): Maintains a history of previous yanks, changes and deletes -* [lightline.vim](https://github.com/itchyny/lightline.vim): A light and configurable statusline/tabline for Vim +Remove all clutter and focus only on the essential. Similar to iA Writer or Write Room [Read more here](http://amix.dk/blog/post/19744) ## Included color schemes -* [peaksea](https://github.com/vim-scripts/peaksea): My favorite! +* [peaksea](https://github.com/vim-scripts/peaksea): The default * [vim-colors-solarized](https://github.com/altercation/vim-colors-solarized) * [vim-irblack](https://github.com/wgibbs/vim-irblack) * [mayansmoke](https://github.com/vim-scripts/mayansmoke) @@ -103,60 +120,53 @@ Remove all clutter and focus only on the essential. Similar to iA Writer or Writ ## How to include your own stuff? -After you have installed the setup you can create **~/.vim_runtime/my_configs.vim** to fill in any configurations that are important for you. For instance, my **my_configs.vim** looks like this: +After you have installed the setup, you can create **~/.vim_runtime/my_configs.vim** to fill in any configurations that are important for you. For instance, my **my_configs.vim** looks like this: ~/.vim_runtime (master)> cat my_configs.vim map ct :cd ~/Desktop/Todoist/todoist map cw :cd ~/Desktop/Wedoist/wedoist -You can also install your own plugins, for instance, via pathogen we can install [vim-rails](https://github.com/tpope/vim-rails): +You can also install your plugins, for instance, via pathogen you can install [vim-rails](https://github.com/tpope/vim-rails): cd ~/.vim_runtime git clone git://github.com/tpope/vim-rails.git sources_non_forked/vim-rails - -Now you have vim-rails installed ;-) ## Key Mappings +The [leader](http://learnvimscriptthehardway.stevelosh.com/chapters/06.html#leader) is `,`, so whenever you see `` it means `,`. + + ### Plugin related mappings -Open [bufexplorer](https://github.com/vim-scripts/bufexplorer.zip) and see and manage the current buffers: +Open [bufexplorer](https://github.com/vim-scripts/bufexplorer.zip) to see and manage the current buffers (`o`): map o :BufExplorer -Open [MRU.vim](https://github.com/vim-scripts/mru.vim) and see the recently open files: +Open [MRU.vim](https://github.com/vim-scripts/mru.vim) to see the recently open files (`f`): map f :MRU -Open [ctrlp.vim](https://github.com/kien/ctrlp.vim) plugin: +Open [ctrlp.vim](https://github.com/kien/ctrlp.vim) plugin to quickly find a file or a buffer (`j` or `f`): let g:ctrlp_map = '' -Open [PeepOpen](http://topfunky.github.io/PeepOpen/) plugin: - - map j :PeepOpen - -Managing the [NERD Tree](https://github.com/scrooloose/nerdtree) plugin: +[NERD Tree](https://github.com/scrooloose/nerdtree) mappings: map nn :NERDTreeToggle map nb :NERDTreeFromBookmark map nf :NERDTreeFind -[goyo.vim](https://github.com/junegunn/goyo.vim) and [vim-zenroom2](https://github.com/amix/vim-zenroom2) lets you only focus on one thing at a time. It removes all the distractions and centers the content. It has a special look when editing Markdown, reStructuredText and textfiles. It only has one mapping. +[goyo.vim](https://github.com/junegunn/goyo.vim) and [vim-zenroom2](https://github.com/amix/vim-zenroom2) lets you only focus on one thing at a time. It removes all the distractions and centers the content. It has a special look when editing Markdown, reStructuredText and textfiles. It only has one mapping. (`z`) map z :Goyo + ### Normal mode mappings -Fast saving of a buffer: +Fast saving of a buffer (`w`): nmap w :w! - -Treat long lines as break lines (useful when moving around in them): - - map j gj - map k gk Map `` to `/` (search) and `+` to `?` (backwards search): @@ -164,18 +174,18 @@ Map `` to `/` (search) and `+` to `?` (backwards search): map ? map :noh -Disable highlight when `` is pressed: +Disable highlights when you press ``: map :noh -Smart way to move between windows: +Smart way to move between windows (`j` etc.): map j map k map h map l -Closing of current buffer(s): +Closing of the current buffer(s) (`bd` and (`ba`)): " Close current buffer map bd :Bclose @@ -194,22 +204,14 @@ Useful mappings for managing tabs: " Super useful when editing files in the same directory map te :tabedit =expand("%:p:h")/ -Switch CWD to the directory of the open buffer: +Switch [CWD](http://vim.wikia.com/wiki/Set_working_directory_to_the_current_file) to the directory of the open buffer: map cd :cd %:p:h:pwd -Open vimgrep and put the cursor in the right position: +Open `ack.vim` for fast search: - map g :vimgrep // **/*. + map g :Ack -Vimgreps in the current file: - - map :vimgrep // % - -Remove the Windows ^M - when the encodings gets messed up: - - noremap m mmHmt:%s///ge'tzt'm - Quickly open a buffer for scripbble: map q :e ~/buffer @@ -219,6 +221,31 @@ Toggle paste mode on and off: map pp :setlocal paste! +### Visual mode mappings + +Visual mode pressing `*` or `#` searches for the current selection: + + vnoremap * :call VisualSelection('f') + vnoremap # :call VisualSelection('b') + +When you press gv you `Ack.vim` after the selected text: + + vnoremap gv :call VisualSelection('gv', '') + +When you press `r` you can search and replace the selected text: + + vnoremap r :call VisualSelection('replace') + +Surround the visual selection in parenthesis/brackets/etc.: + + vnoremap $1 `>a)` + vnoremap $2 `>a]` + vnoremap $3 `>a}` + vnoremap $$ `>a"` + vnoremap $q `>a'` + vnoremap $e `>a"` + + ### Insert mode mappings Quickly insert parenthesis/brackets/etc.: @@ -236,31 +263,6 @@ Insert the current date and time (useful for timestamps): iab xdate =strftime("%d/%m/%y %H:%M:%S") -### Visual mode mappings - -Visual mode pressing `*` or `#` searches for the current selection: - - vnoremap * :call VisualSelection('f') - vnoremap # :call VisualSelection('b') - -When you press gv you vimgrep after the selected text: - - vnoremap gv :call VisualSelection('gv') - -When you press `r` you can search and replace the selected text: - - vnoremap r :call VisualSelection('replace') - -Surround the visual selection in parenthesis/brackets/etc.: - - vnoremap $1 `>a)` - vnoremap $2 `>a]` - vnoremap $3 `>a}` - vnoremap $$ `>a"` - vnoremap $q `>a'` - vnoremap $e `>a"` - - ### Command line mappings $q is super useful when browsing on the command line. It deletes everything until the last slash: @@ -276,27 +278,28 @@ Bash like keys for the command line: cnoremap cnoremap -Write the file as sudo (only on Unix). Super useful when you open a file and you don't have permissions to save your changes. [Vim tip](http://vim.wikia.com/wiki/Su-write): +Write the file as sudo (works only on Unix). Super useful when you open a file and you don't have permissions to save your changes. [Vim tip](http://vim.wikia.com/wiki/Su-write): :W ### Spell checking -Pressing `ss` will toggle and untoggle spell checking +Pressing `ss` will toggle spell checking: map ss :setlocal spell! -Shortcuts using `` instead of special chars +Shortcuts using `` instead of special characters: map sn ]s map sp [s map sa zg map s? z= -### Cope -Do :help cope if you are unsure what cope is. It's super useful! -When you search with vimgrep, display your results in cope by doing: +### Cope +Query `:help cope` if you are unsure what cope is. It's super useful! + +When you search with `Ack.vim`, display your results in cope by doing: `cc` To go to the next search result do: @@ -305,27 +308,15 @@ To go to the next search result do: To go to the previous search results do: `p` -Vimscript mappings: +Cope mappings: map cc :botright cope map co ggVGy:tabnew:set syntax=qfpgg map n :cn map p :cp -## Useful blog tips regarding my Vim setup - -* [Vim: Annotate strings with gettext (the macro way)](http://amix.dk/blog/post/19678#Vim-Annotate-strings-with-gettext-the-macro-way) -* [vimgrep: Searching through multiple file extensions](http://amix.dk/blog/post/19672#vimgrep-Searching-through-multiple-file-extensions) -* [Filtering through vimgrep results using regular expressions](http://amix.dk/blog/post/19666#Filtering-through-vimgrep-results-using-regular-expressions) -* [PeepOpen - File auto completion for Mac editors](http://amix.dk/blog/post/19601#PeepOpen-File-auto-completion-for-Mac-editors) -* [Vim 7.3: Persistent undo and encryption!](http://amix.dk/blog/post/19548#Vim-7-3-Persistent-undo-and-encryption) -* [Vim tips: Visual Search](http://amix.dk/blog/post/19334#Vim-tips-Visual-Search) -* [Folding in Vim](http://amix.dk/blog/post/19132#Folding-in-Vim) -* [ -Zen room for Vim: Focusing only on the essential](http://amix.dk/blog/post/19744#zenroom-for-Vim-Focsuing-only-on-the-essential) ## How to uninstall -Do following: +Just do following: * Remove `~/.vim_runtime` -* Remove any lines that refernce `.vim_runtime` in your `~/.vimrc` - +* Remove any lines that reference `.vim_runtime` in your `~/.vimrc` diff --git a/install_awesome_vimrc.sh b/install_awesome_vimrc.sh index e8330afc..6b94e519 100644 --- a/install_awesome_vimrc.sh +++ b/install_awesome_vimrc.sh @@ -1,3 +1,6 @@ +#!/bin/sh +set -e + cd ~/.vim_runtime echo 'set runtimepath+=~/.vim_runtime diff --git a/install_basic_vimrc.sh b/install_basic_vimrc.sh index 3478144d..6b3142d1 100644 --- a/install_basic_vimrc.sh +++ b/install_basic_vimrc.sh @@ -1,3 +1,6 @@ +#!/bin/sh +set -e + cd ~/.vim_runtime cat ~/.vim_runtime/vimrcs/basic.vim > ~/.vimrc echo "Installed the Basic Vim configuration successfully! Enjoy :-)" diff --git a/my_plugins/.gitkeep b/my_plugins/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/sources_non_forked/YankRing.vim/README b/sources_non_forked/YankRing.vim/README new file mode 100644 index 00000000..656c2472 --- /dev/null +++ b/sources_non_forked/YankRing.vim/README @@ -0,0 +1,127 @@ +This is a mirror of http://www.vim.org/scripts/script.php?script_id=1234 + +Vim already maintains a list of numbered registers containing the last 9 deletes. These previous deletes can be referenced using [register]p, so "1p will paste the last delete, "2p the 2nd last delete. For more information see |quote_number|. + +Vim does not provide any mechanism to reference previous yanked, deleted or changed text. In Emacs this feature is called the "kill ring". + +The YankRing plugin allows the user to configure the number of yanked, deleted and changed text. A split window can be used to choose which element(s) from the yankring you wish to paste. Alternately after text has been pasted (using p), it can be replaced with a previous value from the yankring with a single key stroke. + +The captured text is stored in a file (location configurable) and is instantly available (also configurable) to any other instance of Vim also running on the same machine. This can especially be useful on *nix machines when you are sshed in running Vim in multiple terminals. + +Storing the capture text in a file allows the text to be shared easily between multiple instances of Vim running in X, Windows, SSH or Screen. + +A tutorial is included to take you through the various features of the plugin. After you have installed the plugin just run: + :h yankring.txt + :h yankring-tutorial + +The yankring can be interacted with in two ways: a GUI or via maps. + +The yankring supports all of Vim motions and text-objects. There are very few new keystrokes the user must learn. One keystroke to open the yankring to choose which item to paste is all that is required. It has been designed work seamlessly with Vim + +All the mappings and behaviours are configurable via global variables you can optionally specify in your vimrc. + +The plugin can be toggled on and off, and supports: + Ranges + Registers + Counts + All visual modes (characterwise, linewise and blockwise) + All motions + All text-objects + +Examples: + yy - Adds the current line to the yankring. + dd - Adds the current line to the yankring and deletes it. + 5yw - Adds 5 words to the yankring. + "ade - Deletes the word, and puts it into both the yankring and the "a register. + cw - Changes the word and stores the previous value in the yankring. +10"zyy - Places 10 lines into both the yankring and the "z register. + :1,4YRYankRange - Similar to 1,4y + :3,$YRDeleteRange - Similar to 3,$d + +If you wish to paste previous values from the yankring and do not want to use the GUI, there are only two additional maps you must learn (these are configurable via your vimrc if needed). The purpose of the yankring is to gain access to previously yanked (or deleted) elements. The YRReplace command will replace the previously pasted text with a different entry from the yankring. By default, I choose (P for previous) to replace the text last pasted while moving backwards through your previous text from the yankring and (N for next) to replace the previous paste while moving forward through the yankring. + +A separate buffer window to allow you to easily interact with the contents of the yankring. The window is similar to many other plugins: TagList, SelectBuf and so on. You can use the mouse or standard Vim keys (p, gp, P, ...). Visual mode is used to support counts, pasting multiple times and reversing the order of pasted elements. + +The GUI significantly simplifies your interaction with the yankring for basic functions. But often it useful to take advantage of the more powerful features of the yankring. + +Here is a small section from the tutorial (using maps) so you have some idea of how you interact with the plugin gaining access to previous yanks. Using the GUI for basic operations is self explanatory. + +:h yankring-tutorial + +---- Partial Tutorial ---- +To understand how to use the yankring, the following example should demonstrate the various features. + +Assume we have this buffer: + one + two + three + four + five + +Now yank (yy) each line separately starting at line 1. Display the +contents of the yankring. + :YRShow + --- YankRing --- + Elem Content + 5 five^@ + 4 four^@ + 3 three^@ + 2 two^@ + 1 one^@ +Since we yanked the text starting at line 1 and finishing at line 5, the most current yankring element is the last one, the contents of line 5. +"five^@" is displayed, the "^@" is a newline character (since we issued a "yy"). + +Now, go to the end of the file and press p. The resulting buffer appears as: + one + two + three + four + five + five +Now press to move backwards through the yankring, this results in: + one + two + three + four + five + four +Now press 2. This would be the same as pressing two times in a row. This results in: + one + two + three + four + five + two +Now press to move forwards through the yankring, this results in: + one + two + three + four + five + three + +You can create a map to display a buffer displaying the yankring's contents: + nnoremap :YRShow + +YRShow creates a new split buffer (you can configure where it should be and it's size) + :YRShow + AutoClose=1;Cmds:,[g]p,[p]P,d,r,a,u,q,;Help=? + --- YankRing --- + Elem Content + 3 three^@ + 2 two^@ + 1 one^@ + 5 five^@ + 4 four^@ +You can simply hit "p", , double click on an item and it will be pasted into your document. The window will automatically close (by default) after you have made a choice. The element will be pasted into the correct buffer if you have multiple split windows. + +You can paste multiple items using visual mode. +You can also remove items from the yankring. + +---- Partial Tutorial ---- + +Concentrating on the last line of the buffer you could see how we were able to replace our pasted text with lines yanked previously. This is a feature Vim only has for deletes, and is limited to 9. This plugin enables the same features for both yanks, deletes and changes, the size of the history is configurable. + + + + diff --git a/sources_non_forked/YankRing.vim/doc/yankring.txt b/sources_non_forked/YankRing.vim/doc/yankring.txt new file mode 100644 index 00000000..dafcba3f --- /dev/null +++ b/sources_non_forked/YankRing.vim/doc/yankring.txt @@ -0,0 +1,1662 @@ +*yankring.txt* For Vim version 7.0. + +Author: David Fishburn July 27, 2015 +Version: 19.0 + +For instructions on installing this file, type + :help add-local-help |add-local-help| inside Vim. + +Homepage: http://vim.sourceforge.net/script.php?script_id=1234 + + +============================================================================== +1. Contents *yankring* *yankring-contents* + + 1. Contents...............................: |yankring-contents| + 2. Description............................: |yankring-description| + 3. Configuration..........................: |yankring-configure| + 3.1 Global Variables...................: |yankring-globals| + 3.2 Default Keys.......................: |yankring-mappings| + 3.3 Customizing Maps...................: |yankring-custom-maps| + 3.4 Customizing Menus..................: |yankring-custom-menus| + 4. Using the YankRing Window..............: |yankring-window| + 5. Commands...............................: |yankring-commands| + 5.1 YRToggle..........................: |:YRToggle| + 5.2 YRClear...........................: |:YRClear| + 5.3 YRShow............................: |:YRShow| + 5.5 YRGetElem.........................: |:YRGetElem| + 5.6 YRGetMultiple.....................: |:YRGetMultiple| + 5.7 YRPush............................: |:YRPush| + 5.8 YRPop.............................: |:YRPop| + 5.9 YRYankCount.......................: |:YRYankCount| + 5.10 YRYankRange.......................: |:YRYankRange| + 5.11 YRDeleteRange.....................: |:YRDeleteRange| + 5.12 YRPaste...........................: |:YRPaste| + 5.13 YRReplace.........................: |:YRReplace| + 5.14 YRMapsCreate......................: |:YRMapsCreate| + 5.15 YRMapsDelete......................: |:YRMapsDelete| + 5.16 YRSearch..........................: |:YRSearch| + 5.17 YRCheckClipboard..................: |:YRCheckClipboard| + 5.18 YRRunAfterMaps....................: |:YRRunAfterMaps| + 6. Tutorial...............................: |yankring-tutorial| + 6.1 YRShow............................: |YRShow-example| + 6.2 YRReplace.........................: |YRReplace-example| + 6.3 YRPush............................: |YRPush-example| + 6.4 YRClear...........................: |YRClear-example| + 6.8 YRPop.............................: |YRPop-example| + 6.9 Visual modes......................: |yankring-visual-example| + 6.10 Using ranges......................: |YRYankRange-example| + 6.11 :global...........................: |global-example| + 6.12 YRSearch..........................: |YRSearch-example| + 7. History................................: |yankring-history| + + +============================================================================== +2. Description *yankring-description* + +Vim already maintains a list of numbered registers containing the last 9 +deletes. These previous deletes can be referenced using [register]p, so +"1p will paste the last delete, "2p the 2nd last delete. For more +information see |quote_number|. + +Vim does not provide any mechanism to reference previously yanked text. +In Emacs this feature is called the "kill ring". + +The YankRing plugin allows the user to configure the number of yanked +and deleted text. After text has been pasted, it can be replaced with +a previous value from the yankring. + +As of version 3.0, the yankring's content will persist (by default) +between starting and stopping Vim. + +The plugin can be toggled on and off, and supports: + Ranges + Registers + Counts + All visual modes + All motions + All text-objects + +If you have any suggestions for the improvement of this plugin, see the +yankring.vim file for my email address. Suggestions / bug reports are +always welcome. + +For details on the changes between versions see |yankring-history|. + + +============================================================================== +3. Configuration *yankring-configure* + +The YankRing allows the user to choose which keys are to be assigned to +the various commands. By default, the YankRing chose keys identical +with Vim's standard behaviour/keys. + +3.1 Global Variables *yankring-globals* + +You can customize the YankRing by setting various global variables in +your |.vimrc|. +> + yankring_max_history +< Default: 100 + Controls how many elements to save in the yankring. > + let g:yankring_max_history = 100 + yankring_min_element_length +< Default: 1 + If the yanked element has a length less than this value + if will not be added to the YankRing. This can be useful if + you want to bypass single letter deletes by adding the + following to your .vimrc: > + let g:yankring_min_element_length = 2 + yankring_max_element_length +< Default: 1048576 (1M) + Will truncate a new entry to the specified maximum. If + g:yankring_max_element_length is set to 0, there is no limit. > + let g:yankring_max_element_length = 4194304 " 4M + yankring_max_display +< Default: 500 + When the YankRing window is opened, each element is displayed on a + separate line. Since each yank could be very large, the display of + the element is limited to the above default. > + let g:yankring_max_display = 70 + yankring_enabled +< Default: 1 + If you do not want to YankRing enabled by default, set this + variable in your |vimrc|. > + let g:yankring_enabled = 0 " Disables the yankring + yankring_persist +< Default: 1 + If you have enabled the storing of global variables in the |viminfo| + file, the YankRing will be default persist the contents of the ring + between starting and stopping Vim. To disable this feature: > + let g:yankring_persist = 0 + yankring_share_between_instances +< Default: 1 + By default, any instance of Vim will share the same yankring + history file. But if want each instance to have their own history + you can set this option to 0. Setting g:yankring_persist = 0 and + g:yankring_share_between_instances = 0 will ensure no 2 instances + of Vim share the same YankRing history AND the history is not + remembered the next time Vim is started. > + let g:yankring_share_between_instances = 0 + yankring_dot_repeat_yank +< Default: Based on the Vim cpoption setting + By default Vim will not repeat (using '.') yanking of text. This can + be controlled via the |'cpoptions'| setting. The YankRing now respects + the cpoptions setting, if 'y' is included and you press '.', the + previous yank command is repeated and added to the yankring. + You can also add this behaviour by setting this in your |vimrc|: > + let g:yankring_dot_repeat_yank = 1 + yankring_ignore_duplicate +< Default: 1 + Duplicates will not be added to the YankRing by default. If a + duplicate is found, that element will be moved to the top of the + yankring. This can be controlled by setting this in your |vimrc|: > + let g:yankring_ignore_duplicate = 0 + yankring_map_dot +< Default: 1 + If the '.' (repeat) command should be mapped by the yankring. Since + most of the normal commands yy,dd,dw,... are mapped by the yankring, + if g:yankring_map_dot is false the . operator will not repeat these + operations. The YankRing tracks several of the internal Vim registers + and decides whether an action was the result of the YankRing or an + action outside of it. If the previous action was a result of the + yankring, it will be executed again. If it was an action outside of + the yankring, it asks Vim to repeat the command. > + let g:yankring_map_dot = 1 + yankring_paste_using_g +< Default: 1 + By default [p] and [P] are mapped to interact with the yankring. This + option controls whether [gp] and [gP] are also mapped. Setting this + option to 0 will not create these maps. > + let g:yankring_paste_using_g = 1 + yankring_window_use_separate +< Default: 1 + This is a new feature as of the 2.0 release. The YankRing now uses a + separate split buffer to display the yankring. There are many buffer + specific maps that allow you to operate over the various elements from + within the yankring. Setting this option to 0, uses the 1.0 + interface. > + let g:yankring_window_use_separate = 0 + yankring_window_auto_close +< Default: 1 + By default once you choose an option in the YankRing buffer, the + action is performed and the buffer window is closed, returning you to + the original buffer. This option can be toggled from within the + YankRing buffer by pressing [a]. The YankRing buffer status line + visually indicates when auto close is enabled or disabled. There are + many times where you need to paste (or delete) many items from the + yankring. Pressing [a], disables auto close, allows you to paste many + items, and finally you can press [a] to re-enable auto close, followed + by [q] to quit the buffer window. > + let g:yankring_window_auto_close = 1 + yankring_record_insert +< Default: 0 + If you want text you insert to be recorded in the YankRing you can + enable this feature two ways. From within the YankRing window you can + press [i]. The YankRing buffer status line visually indicates when + recording inserts is enabled or disabled. To enable this option + at Vim startup, put the following in your .vimrc: > + let g:yankring_record_insert = 1 + yankring_window_use_horiz +< Default: 1 + When the YankRing window is opened, it uses a horizontal split at the + bottom of the Vim window. It can optionally use a vertical split by + setting this option to 0. > + let g:yankring_window_use_horiz = 0 " Use vertical split + yankring_window_height +< Default: 8 + If using a horizontal split, this option controls how high to make + the window. > + let g:yankring_window_height = 8 + yankring_window_width +< Default: 30 + If using a vertical split, this option controls how wide to make the + window. > + let g:yankring_window_width = 30 + yankring_window_use_bottom +< Default: 1 + If using a horizontal split, this option control whether the window is + opened at the top or bottom of the Vim window. Setting this option to + 0 forces the window to open at the top of the Vim window. > + let g:yankring_window_use_bottom = 1 + yankring_window_use_right +< Default: 1 + If using a vertical split, this option control whether the window is + opened on the left or right side of the Vim window. To force the + window to open on the left side, set this option to 0. > + let g:yankring_window_use_right = 1 + yankring_window_increment +< Default: 1 + If using a vertical split the default width of the vertical window may + be too narrow to view enough of the elements. Pressing [] will + increase the size of the window by this number of columns. Pressing + [] again will toggle it back to the original size. > + let g:yankring_window_increment = 50 + yankring_manage_numbered_reg +< Default: 0 + Vim already maintains a list of numbered registers containing the last + yanked item and the previous 9 deletes. These items can be referenced + using [register]p, so "0p will paste the last yank, "1p will paste the + last delete, "2p the 2nd last delete. For more information see + |quote_number|. + If you wish the YankRing to maintain these numbered registers so + the top 10 elements in the YankRing are in the numbered reqisters 0-9 + you can put the following in your |vimrc| > + let g:yankring_manage_numbered_reg = 1 + yankring_ignore_operator +< Default: 'g~ gu gU ! = gq g? > < zf g@' + There are a number of Vim operations which do not change any + registers, and therefore should not be captured by the yankring. + This list is used to ignore the appropriate operators. + You can put the following in your |vimrc| > + let g:yankring_ignore_operator = 'g~ gu gU ! = gq g? > < zf g@' + yankring_history_dir +< Default: $HOME + The YankRing stores the text in a file. This global variable + allows you to customize where the file(s) will be stored. + This can be a comma separated list, which is useful if your + .vimrc is shared across different machines. If multipe directories + are specified, the first valid directory will be used. + You can put the following in your |vimrc| > + let g:yankring_history_dir = '$VIM' + yankring_history_file +< Default: 'yankring_history' + The history filename prefix can be controlled by setting this + variable. + You can put the following in your |vimrc| > + let g:yankring_history_file = 'my_yankring_history_file' + yankring_clipboard_monitor +< Default: 1 + When flipping between applications I find I often copy text + and attempt to use it inside of Vim. This is typically easy + by simply using "+p, but there are times when I will repeatedly + want to use the same text later on. By default, the YankRing + will detect when Vim regains focus and check if the clipboard + has changed since it last checked. If so, it will add the contents + of the clipboard to the YankRing. This is accomplished by the + use of the FocusGained Vim event for the GUI Vim. For console + Vims, the FocusGained event does not fire, so additional logic + is added to deal with it. To disable this feature + you can put the following in your |vimrc| > + let g:yankring_clipboard_monitor = 0 + yankring_manual_clipboard_check +< Default: 0 + If running in console mode, Vim's FocusGained event will not + fire as we flip back and forth between windows. This normally + instructs the YankRing to check for updates to the system + clipboard. When this option is set, the YankRing will check + the clipboard under many different circumstances: + Adding a new entry to the YankRing + Replacing a previous paste + Showing the YankRing window + If the YankRing is setup to check the clipboard and the + GUI is not running, this option will be enabled by default. + To disable this feature you can put the following in your |vimrc| > + let g:yankring_manual_clipboard_check = 0 + yankring_paste_check_default_register +< Default: 1 + If the default register has changed without the YankRing registering + the change the YankRing will paste the top item from the history + rather than what is currently in the default register. + This option allows you to control the behaviour. Plugins can + intentionally change the default buffer which the YankRing has + no way to noticing. To disable this feature you can put the following + in your |vimrc| > + let g:yankring_paste_check_default_register = 0 + yankring_default_menu_mode +< - Menus are useful for a number of reasons: + See a list of available commands. + Remember what the shortcut maps are. + Have a floating menu when using the plugin a lot. + Quick reference guide. + There are four settings that will control the placement + of the menu: + "0": Turns the menu off. + "1": Turns the 'Yankring' menu on with no menu shortcut. + "2": Turns the 'Yankring 'menu on with -y as the shortcut. + "3": Turns the 'Plugin -> YankRing' menu on with -y as + the shortcut. + This option defaults to a value of 3 and can be changed + by adding the following to your .vimrc: > + :let g:yankring_default_menu_mode = 3 + yankring_menu_root +< - Can be used in conjuction with g:yankring_default_menu_mode = 3 but + it also allows you to control the fullname and location of the + YankRing menu. To create the menu: 'MyPlugins -> YankRing' you + can create the following variable: > + :let g:yankring_menu_root = 'MyPlugin.&YankRing' + yankring_menu_priority +< - Menus are created in a documented order by Vim (|menu-priority|). + This option allows you to override the setting and shift the + YankRing menu item to the left between the Edit and Tools menu. > + :let g:yankring_menu_priority = 30 + +< +3.2 Default Keys *yankring-mappings* + +You can choose to override the default keys by creating these global +variables in your |vimrc|. +> + yankring_n_keys +< n - normal mode + Default Vim 7.2: + 'Y D x X' + Default Vim 7.1 and below: + 'x yy dd yw dw ye de yE dE yiw diw yaw daw y$ d$ Y D yG dG ygg dgg' + + With the introduction of some new features in Vim 7.2 it is no longer + necessary to list all cmds which the YankRing will act upon. + The yankring_n_keys only lists actions which an omap cannot be used. + Using the yankring_separator, the above list is parsed and + individual mappings are created. For each of the above normal + commands the YankRing will include the text those commands + acted upon. There are many ways to accomplish the same result + in Vim, if you do not see a common key stroke you regularly use + simply add the following to your |vimrc| with the additional + keys you wished mapped. > + let g:yankring_n_keys = 'Y D x X' + yankring_o_keys +< o - omap mode + Default: + Standard motions: 'b B w W e E d y $ G ;' + Vim text objects: ' iw iW aw aW as is ap ip a] a[ i] i[' + 'a) a( ab i) i( ib a> a< i> i< at it ' + 'a} a{ aB i} i{ iB a" a'' a` i" i'' i`' + + As of Vim 7.2 omaps are used to capture changes to the registers + in Vim. All of the standard motion commands are captured. + New to YankRing 5.0 all default Vim text objects are also + captured. + Using the yankring_separator, the above list is parsed and + individual mappings are created. For each of the above normal + commands the YankRing will include the text those commands + acted upon. There are many ways to accomplish the same result + in Vim, if you do not see a common key stroke you regularly use + simply add the following to your |vimrc| with the additional + keys you wished mapped. > + let g:yankring_o_keys = 'b B w W e E d y $ G ; iw iW aw aW' + yankring_zap_keys +< Default: 'f F t T / ?' + omaps are enough for most operations except for f and t. + These motions prompt the user for a character or string which + they should act upon. These must be treated as a special case + in YankRing. > + let g:yankring_zap_keys = 'f t' + yankring_ignore_operator +< Default: 'g~ gu gU ! = gq g? > < zf g@' + There are certain motions which do not update any registers + in Vim. If the registers are not changed, there is nothing + the YankRing can capture. This list instructs the YankRing + to ignore any action for these keys. > + let g:yankring_ignore_operator = 'g~ gu gU' + yankring_v_key +< v - visual mode + Default: y + Yanks visually select text. > + yankring_del_v_key +< n - normal mode + Default: d + The visually select text is included in the YankRing and deleted. > + yankring_paste_n_bkey +< n - normal mode + b - before + Default: P + The default Vim paste key will retrieve from the yankring. This + will paste the text BEFORE the current position. + There is a special check to see if the text in the default paste + register is the same as what is in the current position of the + yankring. If it is not, we assume the user used some other + mechanism to yank text (ie yt). If this is the case + we paste the text in the default paste buffer. Using the + text can be replaced with the current entry from the yankring. + Since there are many ways to do things in Vim, this provides + the best integration. > + yankring_paste_n_akey +< n - normal mode + a - after + Default: p + The default Vim paste key will retrieve from the yankring. This + will paste the text AFTER the current position. + There is a special check to see if the text in the default paste + register is the same as what is in the current position of the + yankring. If it is not, we assume the user used some other + mechanism to yank text (ie yt). If this is the case + we paste the text in the default paste buffer. Using the + text can be replaced with the current entry from the yankring. + Since there are many ways to do things in Vim, this provides + the best integration. > + yankring_paste_v_key +< n - normal mode + Default: p + This will replace the visually select text with the contents + from the yankring. See yankring_paste_n_akey for additional + details. > + yankring_replace_n_pkey +< n - normal mode + Default: + If you do not want to open the YankRing window to choose your + selection, then you can paste (as usual) then use a YankRing + mapping to cycle through items in the YankRing. This is especially + useful if you know you recently used the text you are looking for. + If you wish to cycle through the yankring, replacing the previously + pasted text with the previous yanked text you can repeatedly press + (or whatever keystroke you choose to map it to). This map + moves backwards through the yankring, so you will retrieve your + most recent yank. + + I prefer not to use since I like using that key to cycle + through all the matches in the QuickFix window. You can add + something similar to this in your |.vimrc| to get similar + functionality. + + On Windows use the ALT-< character to move through the YankRing. + To determine what character # these are go into insert mode + in a new buffer. Press CTRL-V then ALT and the < key. + Leave insert mode, move the cursor onto the character + and press ga. This will display the decimal, hex and octal + representation of the character. In this case it is 172. > + if has('win32') + let g:yankring_replace_n_pkey = '' + let g:yankring_replace_n_nkey = '' + " Instead map these keys to moving through items in the quickfix window. + nnoremap :cp + nnoremap :cn + endif +< Other users have also stated that this will work: > + let g:yankring_replace_n_pkey = '' + let g:yankring_replace_n_nkey = '' + yankring_replace_n_nkey +< n - normal mode + Default: + If you do not want to open the YankRing window to choose your + selection, then you can paste (as usual) then use a YankRing + mapping to cycle through items in the YankRing. This is especially + useful if you know you recently used the text you are looking for. + If you wish to cycle through the yankring, replacing the previously + pasted text with the next yanked text you can repeatedly press + (or whatever keystroke you choose to map it to). This map + moves forwards through the YankRing, so you will retrieve your + most recent yank. + + I prefer not to use since I like using that key to cycle + through all the matches in the QuickFix window. You can add + something similar to this in your |.vimrc| to get similar + functionality. + + On Windows use the ALT-> character to move through the YankRing. + To determine what character # these are go into insert mode + in a new buffer. Press CTRL-V then ALT and the > key. + Leave insert mode, move the cursor onto the character + and press ga. This will display the decimal, hex and octal + representation of the character. In this case it is 174. > + if has('win32') + let g:yankring_replace_n_pkey = '' + let g:yankring_replace_n_nkey = '' + " Instead map these keys to moving through items in the quickfix window. + nnoremap :cp + nnoremap :cn + endif +< Other users have also stated that this will work: > + let g:yankring_replace_n_pkey = '' + let g:yankring_replace_n_nkey = '' + +3.3 Customizing Maps *yankring-custom-maps* + +The YankRing plugin uses the yankring_n_keys global variable to create +a number of defaults maps. The maps are of the form: > + nnoremap Y :YRYankCount 'Y' +< +When capital Y is pressed, the YankRing will execute 'Y' and capture the +output from Vim. But there are cases where you do not want the default +behaviour of Vim, since you have customized some of these maps. + +In this case, I usually map Y to be |y$|, which makes it consistent with +the |D| and |C| operators. The way yankring_n_keys works does not allow +me to customize this behaviour. Since many people may like to customize +the behaviour of these maps the YankRing will check to see if a +function called YRRunAfterMaps() exists. If it does, it will call +this function after it has created the maps. So in my case, I created +the following function in my |vimrc|: > + function! YRRunAfterMaps() + nnoremap Y :YRYankCount 'y$' + endfunction +< +You can do anything you need in this function. > + nnoremap Y :YRYankCount 'y$' +< +This line remaps Y (which the user presses) to the YRYankCount command. The +YRYankCount tells Vim to execute y$ instead. + +3.4 Customizing Menus *yankring-custom-menus* + +There are several global variables which can be created in your .vimrc to +allow you to customize where and what is displayed for the YankRing menu. +Simply look up the following global variables: > + yankring_default_menu_mode + yankring_menu_root + yankring_menu_priority + + +============================================================================== +4. Using the YankRing Window: *yankring-window* + +This is a new feature as of the 2.0 release. The YankRing uses a +separate split buffer to display the yankring. There are many buffer +specific maps that allow you to operate over the various elements from +within the yankring. + +To display the YankRing buffer you can issue the :YRShow command. For +convenience you can map a key, , to this command: > + :nnoremap :YRShow + +Status line~ +The first line in the YankRing window is the status line. > + AutoClose=1;ClipboardMonitor=1;Cmds:[g]p,[g]P,1-9,d,r,s,a,c,u,q,,;Help=? +< +Help=?, pressing [?] will toggle the display of available commands the +yankring window supports. Pressing [?] again will remove the additional +items. + +AutoClose=1 indicates the window will close when an action is performed +against elements within the yankring. If you wish to perform multiple +yankring operations press [a] to toggle the auto close feature off. Use the +commands below and when finished you can press [a] to toggle the option, +yankring_window_auto_close, on and press [q] to close the window. +The Cmds displayed are simply reminders of the available keys. + +ClipboardMonitor=1 indicates the YankRing will monitor the clipboard (+) +during Focus change events. If the clipboard has changed since the YankRing +last checked, the contents are added to the YankRing. Pressing [c] allows +you to quickly toggle the option, yankring_clipboard_monitor, since it may not +be useful at times. + +Inserts=0 indicates the YankRing will recorder newly inserted text +rather than just deletes and changes. Pressing [i] toggles the option +yankring_record_insert. + +YankRing window key list~ +The following table lists the description of the keys that can be used +in the YankRing window. + + Key Description~ + p Puts text after the cursor. In visual mode, all elements + selected will be pasted. + P Puts text before the cursor. In visual mode, all elements + selected will be pasted. + gp Just like "p", but leave the cursor just after the new text. + gP Just like "P", but leave the cursor just after the new text. + Just like "p". + Just like "p". + <2-LeftMouse> Just like "p". Normal mode only. + 1-9 Shortcut to paste the n'th number from the YankRing. + d Removes the element from the yankring. In visual mode all + elements selected will be removed. + r Just like "p", but in visual mode if many lines are selected + it will paste these items in reverse order. + s Prompts you for a regex to search the YankRing and display + only matching items. + a Toggles the g:yankring_window_auto_close setting. + u Updates the YankRing window. + q Closes the YankRing window. + Toggles the width of the vertical window by the + g:yankring_window_increment setting. + ? Toggles the display of the help. + + +============================================================================== +5. Commands: *yankring-commands* + +The predefined mappings call some specific commands with special parameters. +If you are going to create additional maps, it is important you mirror +the same parameters. Most of these commands have been made obsolete by +the YankRing window, since it incorporates the functionality below, but +through maps against a buffer, instead of commands. This makes it much easier +to use. + + +5.1 YRToggle *:YRToggle* + Allows you to enable and disable the YankRing quickly. This + command will remove the default maps and recreate them. + + Examples: > + :YRToggle " Toggles it + :YRToggle 1 " Enables it + :YRToggle 0 " Disables it +< + +5.2 YRClear *:YRClear* + Clears all elements from the yankring. + See also |YRClear-example|. + + +5.3 YRShow *:YRShow* + Similar to |:register|, will display all the entries in the yankring. + The element at the top will be the next element pasted from the + yankring. + + Examples: > + :YRShow " Shows all entries in the yankring + + --- YankRing --- + Elem Content + 1 five^@ + 2 four^@ + 3 three^@ + 4 two^@ + 5 one^@ +< + +5.5 YRGetElem *:YRGetElem* + This command has two modes. If no parameters are provided, it + becomes interactive. It uses YRShow to display the list and + allows you to choose which element to paste. If a parameter + is supplied it will paste that element from the yankring. If the + number specified is outside of the YankRing an error is returned. + You may want to create a separate mapping for this call. > + nnoremap yr :YRGetElem +< See also |YRSearch|. + + Examples: + Assume there are 10 elements in the YankRing and element 6 is + at the top of the ring. > + :YRGetElem " Interactive mode, you choose from a list + :YRGetElem 4 " Will paste element 5. + :YRGetElem 12 " Will paste element 6. + :YRGetElem 99 " Error, invalid choice is reported + :YRGetElem 0 " Error, invalid choice is reported + + +5.6 YRGetMultiple *:YRGetMultiple* + Will paste many elements from the YankRing in one command. + If the number specified is 1 or less, it is assumed you want + just the current element pasted. If the number specified is + greater than or equal to the number of elements in the yankring, + it is assumed you want all elements pasted. If a ! is included + as part of the command, paste the items in reverse order. + See the |yankring-tutorial| for more examples. + + Examples: + Assume there are 10 elements in the YankRing. > + :YRGetMultiple 4 " Will paste elements 1,2,3,4 + :YRGetMultiple! 4 " Will paste elements 4,3,2,1 + :YRGetMultiple " Will paste element 1 + :YRGetMultiple 12 " Will paste elements 1,2,...,10 + :YRGetMultiple 99 " Will paste elements 1,2,...,10 + :YRGetMultiple 0 " Will paste element 1 + + +5.7 YRPush *:YRPush* + Allows the user to "push" additional entries into the yankring. + If you yanked text via a key mapping which does not use the + YankRing (or there is text on the clipboard) you can use this + command to add the text to the yankring. + + Examples: > + :YRPush " Push the " register's contents + :YRPush '*' " Push the "* register's contents (clipboard) + :YRPush '+' " Push the "+ register's contents (clipboard) + :YRPush 'a' " Push the "a register's contents +< See also |YRPush-example|. + + +5.8 YRPop *:YRPop* + Allows you to pop any elements from the yankring. If no parameters + are provided, the 1st element is removed from the yankring. The + command optionally takes a second parameter to specify how many + elements to pop. The default value is 1. + + Examples: > + :YRPop " Removes the highest numbered element from the + yankring + :YRPop 3 " Removes the 3rd element from the yankring + :YRPop 3,5 " Removes 5 elements from the YankRing beginning + at element 3 +< See also |YRPop-example|. + + +5.9 YRYankCount *:YRYankCount* + This command has the most mappings created for it. If you are + in normal mode and you are not specifying a range, this command + will add the text to the yankring. + + The goal of this command is to allow the YankRing to be integrated + as seamlessly as possible with Vim. So it supports counts and + registers. If you create a mapping to it, you must pass as a + parameter the action you want Vim to perform. You could do the + following: > + nnoremap \test :YRYankCount 'dd' +< This map is executed when you hit the '\test' keystrokes, but + it will actually delete the current line and add it to the + yankring. + + The following are the default mappings: > + nnoremap yy :YRYankCount 'yy' + nnoremap dd :YRYankCount 'dd' + nnoremap yw :YRYankCount 'yw' + nnoremap dw :YRYankCount 'dw' + nnoremap ye :YRYankCount 'ye' + nnoremap de :YRYankCount 'de' + nnoremap yiw :YRYankCount 'yiw' + nnoremap diw :YRYankCount 'diw' + nnoremap Y :YRYankCount 'Y' + nnoremap D :YRYankCount 'D' + nnoremap y$ :YRYankCount 'y$' + nnoremap d$ :YRYankCount 'd$' + nnoremap yG :YRYankCount 'yG' + nnoremap dG :YRYankCount 'dG' +< + Examples: + yy - Adds the current line to the yankring. + dd - Adds the current line to the YankRing and deletes it. + 5yw - Adds 5 words to the yankring. + "ade - Deletes the word, and puts it into both the yankring + and the "a register. + 10"zyy - Places 10 lines into both the YankRing and the "z + register. + See also |yankring-tutorial|. + + +5.10 YRYankRange *:YRYankRange* + This command by default is only called in visual mode. All + visual modes (|characterwise-visual|, |linewise-visual|, + |blockwise-visual|) are supported. Any visually selected text + is added to the yankring. You can also call this command + directly using a range. + + Examples: + Visual mode + ----------- + Press v (to enter visual mode), highlight want you want, + press y (to yank the selected area). + Repeat using V and Control-V. + + Normal mode + ----------- > + :5,20YRYankRange " Will yank lines 5-20 into the yankring + :5,20YRDeleteRange " Will delete lines 5-20 and add them to + the yankring +< See also |YRYankRange-example|. + + +5.11 YRDeleteRange *:YRDeleteRange* + This command is identical to YRYankRange, except the range is + also deleted. + + +5.12 YRPaste *:YRPaste* + This command will paste elements from the yankring. By default it has + been mapped to p and P to match Vim's native key strokes. The text + pasted is exactly what was yanked, including newline characters and + blockwise-visual mode behaviours. It supports counts and registers. + + Examples: + p " Paste the current element from the YankRing after the cursor + P " Paste the current element from the YankRing before the cursor + 5p " Paste the current element from the YankRing after the cursor + 5 times + "ap " Ignore the YankRing and paste the contents of register "a + 5"ap " Ignore the YankRing and paste the contents of register "a + 5 times + See also |yankring-tutorial|. + + +5.13 YRReplace *:YRReplace* + The purpose of the YankRing is to gain access to previously yanked + (or deleted) elements. This command will replace the previous + paste with a different entry from the yankring. + By default, I choose (P for previous) to replace the last paste + while moving backwards through the yankring. (N for next) + replaces the last paste while moving forward through the yankring. + + Examples: + See the |yankring-tutorial| for examples. + + On the Windows platform, I use ALT-< and ALT-> to move back and + forwards through the yankring instead of C-P and C-N. ALT-< is + actually ALT-, since I do not press the Shift key to get the <. + + To do this, I added the following to my .vimrc: + " Do not map the default and keys + " These two characters are the ALT-< and ALT->. + " To determine what character # these are go into insert mode + " in a new buffer. Press CTRL-V then ALT and the > key. + " Leave insert mode, move the cursor onto the character + " and press ga. This will display the decimal, hex and octal + " representation of the character. In this case, they are + " 172 and 174. + if has('win32') + let g:yankring_replace_n_pkey = '' + let g:yankring_replace_n_nkey = '' + endif + +5.14 YRMapsCreate *:YRMapsCreate* + This public function is responsible for creating the maps which + enable the yankring. This function is called by the YRToggle + command. + + +5.15 YRMapsDelete *:YRMapsDelete* + This public function removes the YankRing maps and disables + the yankring. This function is called by the YRToggle command. + + +5.16 YRSearch *:YRSearch* + This command is similar to |YRGetElem|. The command takes + one parameter which is a regular expression. Similar to + YRGetElem, it will display all items in the YankRing that match + the regular expression. It is also interactive, and will + prompt you to enter which match you wish pasted. + See also |YRSearch-example|. + +5.17 YRCheckClipboard *:YRCheckClipboard* + Normally the GUI Vims will automatically (via autocmds) + check for changes to the system clipboard and add any new + changes to the YankRing. Most console Vim's do not fire + the required autocmds. This command will perform the check + manually. + +5.18 YRRunAfterMaps *:YRRunAfterMaps* + See the following section |yankring-custom-maps|. + + +============================================================================== +6. Tutorial *yankring-tutorial* + +To understand how to use the yankring, the following example will +demonstrate the various features. Assume you have created the following +mapping: > + nnoremap :YRShow +< + Assume we have this buffer: > + one + two + three + four + five +< *YRShow-example* + Now yank (yy) each line separately starting at line 1. + Display the contents of the YankRing by executing the command + YRShow, or pressing . The contents of the YankRing is + displayed in a new buffer. The size, location and type of buffer + is configurable via various options. See section 3 for more details. > + :YRShow or F11 + --- YankRing --- + Elem Content + 1 five^@ + 2 four^@ + 3 three^@ + 4 two^@ + 5 one^@ +< Since we yanked the text starting at line 1 and finishing at + line 5, the most current YankRing element is the last one, the + contents of line 5. "five^@" is displayed, the "^@" is a + newline character (since we issued a "yy"). + + *yankring-window-example* + At this point, you have two options. You can choose which element + from the YankRing you wish to paste and press or 'p' or 'P' + and a variety of other options, see |yankring-window|. After pressing + the key, the YankRing window will close (default behaviour). Pressing + '?' will display additional help for the commands that are active within + the YankRing window. Pressing '?' will toggle the help. + + You do not need to interact with the YankRing using the YankRing window. + Using the window makes many tasks must easier, but for speed using some + of the other maps can be preferable if you know what you have yanked / + deleted recently. It was designed to work with Vim in the usual manner. + You can press, 'p', to paste the last item in yanked or deleted. + + Close the YankRing window by pressing 'q' or F11 (which toggles it). + + *YRReplace-example* + Now, go to the end of the file and press 'p'. The resulting + buffer appears as: > + one + two + three + four + five + five +< + Assume you did not want "five", but a different entry from within the + yankring. moves backwards through the yankring, it will replace + the previous pasted text with a different item from the yankring. This + allows you to quickly iterate through different elements. is the + default mapping, this can be user defined. See the following options for + more details: > + yankring_replace_n_nkey, yankring_replace_n_pkey +< + After pressing the buffer results in: > + one + two + three + four + five + four +< Now press 2. This would be the same as pressing + two times in a row. This results in: > + one + two + three + four + five + two +< Now press to move forwards through the yankring, + this results in: > + one + two + three + four + five + three +< Display the contents of the yankring. > + :YRShow + --- YankRing --- + Elem Content + 1 five^@ + 2 four^@ + 3 three^@ + 4 two^@ + 5 one^@ +< + Now lets yank some text with a key stroke that has not been + mapped to the yankring. Place your cursor at the start of + line 4. Press 'ytr', yank-to-(to the character r), which yanks + the 'fou' letters (no newline character). Now press p. Here is + the result: > + one + two + three + ffouour + five + three +< This is good, even though the keys 'ytr' has not been mapped + to YRYankCount, the YankRing still pasted the most recently + yanked text. Since the text did not have a newline character + the 'fou' was inserted after the 'f'. + + Now replace that previous paste with the current element from + the YankRing by pressing . This is the result: > + one + two + three + four + one + five + three +< The #1 entry in the YankRing is still the line "five@". When + choosing the next entry, it wraps around to the last entry in + the yankring, element #5. The 'fou' was replaced with 'one^@'. + Since it had a newline character in it (when it was yanked) the + newline is included when it is pasted. + + *YRPush-example* + Assume you need to paste text from the system clipboard, and this + is text you will need routinely. We can simulate this by running + this command (see |quote+|): > + :let @+ = "From the clipboard\n" + :echo @+ + +< With the cursor at the start of the line with the word 'five', press 'p'. + We still have pasted the 'fou' which is in the default paste buffer. > + one + two + three + four + two + ffouive + three +< We have the option of getting the text from the clipboard directly + with the following. > + First undo the previous change - u + Next - "+p +< The line changes since we bypassed the yankring, and specified + which register to get the text from: > + four + five + From the clipboard + three +< replaces this with the #1 entry in the yankring: > + four + five + five + three +< Now add the contents of the clipboard to the yankring: > + :YRPush '+' +< Move the cursor to the last row 'three' and press 'p'. The result is: > + four + five + one + three + From the clipboard +< YRPush '+' adds the value of the register '+' to the yankring, but it + also adds its contents to the default Vim paste buffer. So pressing + 'p' pasted this text. Adding a new value to the YankRing we have + repositioned it which you can see with: > + :YRShow or F11 + --- YankRing --- + Elem Content + 1 From the clipboard^@ + 2 five^@ + 3 four^@ + 4 three^@ + 5 two^@ + 6 one^@ +< *YRClear-example* + Now we will clear the yankring, and begin over again. Delete all lines + from the buffer and replace them with the original rows: > + one + two + three + four + five +< Now run this command to clear the YankRing to start over: > + :YRClear +< + Issue a 'yy' on each of the 5 lines. If you run the YRShow command you + should see the following: > + :YRShow or F11 + --- YankRing --- + Elem Content + 1 five^@ + 2 four^@ + 3 three^@ + 4 two^@ + 5 one^@ +< *any-item-example* + If you need to quickly browse the YankRing to determine which element you + wish to paste you can simply press 'p' or or on any element + displayed in the YankRing window. Press '?' for more detailed description + of the commands available. + + Using the YankRing window can be much faster if you do not want to cycle + through the YankRing using and to find the element. + + As a short cut, when using the YankRing window, you can press the numbers + 1-9 to paste that item directly and close the YankRing window. This can + be faster than navigating to the correct line number and pressing 'p'. + + *multiple-items-example* + There are times when you need to move through a buffer capturing many + different lines (or snippets of code) and eventually want to switch + buffers and paste these elements. With some advance planning you can do + this without the YankRing by issuing commands of the form: > + "ayy + "Ayy +< When specifying the register using UPPERCASE, Vim appends the yanked text + to register "a, instead of replacing it. Many times you forget the + advance planning (or didn't even know about this great feature) you can + use the YankRing window to do this easily. If this is the current + yankring: > + :YRShow or F11 + --- YankRing --- + Elem Content + 1 five^@ + 2 four^@ + 3 three^@ + 4 two^@ + 5 one^@ +< The YankRing works in |visual-mode|. To demonstrate move the cursor in + the buffer to the line with 'two'. Press 'F11' to display the yankring + window. Move the cursor to element 2, press 'V' to enable + |linewise-visual| mode and then press 'j' twice. This should have + visually highlighted elements 2,3,4. Press 'p' to paste all the + highlighted elements: > + one + two + four + three + two + three + four + five +< You can see here it has pasted four, three, two after the second line of + the buffer. Now press 'u' to undo our last change. Leave the cursor + on the second line 'two'. Press 'F11' to show the YankRing again. + Visually select the same lines, but this time press 'r' instead of 'p'. + 'r' is for reverse, so it will paste the following: > + one + two + two + three + four + three + four + five +< + *YRGetMultiple-example* + The same behaviour listed above (by visually selecting items in the + YankRing window) can be achieved using the YRGetMultiple command. + Assume there are 10 elements in the YankRing. > + :YRGetMultiple 4 " Will paste elements 1,2,3,4 + :YRGetMultiple! 4 " Will paste elements 4,3,2,1 + :YRGetMultiple " Will paste element 1 + :YRGetMultiple 12 " Will paste elements 1,2,...,10 + :YRGetMultiple 99 " Will paste elements 1,2,...,10 + :YRGetMultiple 0 " Will paste element 1 +< + *YRSearch-example* + The default size of the YankRing is 100 elements. It can be + tedious searching through the YankRing to find the element you + need. YRSearch is similar to YRShow except it will limit the + items displayed to only those items matching the regex provided. > + :YRShow + --- YankRing --- + Elem Content + 1 Three Mississippi + 2 Two Mississippi + 3 One Mississippi + 4 @", '\\/.*$^~[]' ) + :YRSearch Mississippi + --- YankRing --- + Elem Content + 1 Three Mississippi + 2 Two Mississippi + 3 One Mississippi +< Consider some items which require escaping the search string: > + :YRSearch @", '\\ + --- YankRing --- + Elem Content + 1 @", '\\/.*$^~[]' ) +< Forward slashes and various other symbols require escapes, in this + case the slash was not escaped enough: > + :YRSearch @", '\\/ + --- YankRing --- + Elem Content +< There are enough escapes this time: > + :YRSearch @", '\\\\/ + --- YankRing --- + Elem Content + 1 @", '\\/.*$^~[]' ) +< Period, star, dollar and so on require one slash: > + :YRSearch @", '\\\\/\.\*\$\^\~\[\] + --- YankRing --- + Elem Content + 1 @", '\\/.*$^~[]' ) + +< *YRPop-example* + You can remove any element from the YankRing by pressing pressing 'd' from + within the YankRing window. Visual mode is also supported to remove more + than one element at a time. > + :YRShow + --- YankRing --- + Elem Content + 1 four^@ + 2 three^@ + 3 two^@ + 4 one^@ +< Visually select elements 2,3. Press 'd', the result is: > + :YRShow + --- YankRing --- + Elem Content + 1 four^@ + 2 one^@ + +< *yankring-visual-example* + There are 3 visual modes and all are supported. Any visually selected + text is added to the yankring. You can try the various modes. Move + the cursor to inside the buffer (not the YankRing window). + + |characterwise-visual| + Go to line 1, press 'v' and move using the cursor keys until you have + highlighted some text. Then press y to yank the visually selected + area. Pressing p with paste the yanked region. + + |linewise-visual| + Go to line 2, press 'V' and move using the cursor keys until you have + highlighted some text. Notice the entire line is selected (including + the carriage returns). Then press y to yank the visually selected + area. Pressing p with paste the yanked region. + + |blockwise-visual| + Go to line 3 column 4, press CTRL-V and move to the right using the + cursor keys until you have highlighted some text. Then press y to + yank the visually selected area. Pressing p with paste the yanked + region. Notice the pasted text retained its blockwise visual + characteristics. + + *YRYankRange-example* + YRYankRange is called during visual modes, but it is also possible to + use this via the command line. > + :1,4YRYankRange + :3,$YRDeleteRange + :YRShow +< + *global-example* + Using Vim's |:global| command can be very useful at times. The example + adds all rows (in a buffer) to the YankRing if they have a certain + phrase: > + :g/addme/YRYankCount 'yy' +< This is the breakdown for the above command: > + :g - for each line in the buffer + /addme - check if the string "addme" is in the line + /YRYankCount 'yy' - Ask the YankRing to execute the 'yy' command + + +============================================================================== +7. History *yankring-history* + + 19.0: July 27, 2015 + NF: Updated documentation displayed in the YankRing window when + pressing ? to explain the Insert=0 status (Oskar Kvist). + + 18.0: September 24, 2013 + NF: Handle the @: command (Lingnan Dai). + NF: Added new global option to specify the YankRing buffer name, + g:yankring_buffer_name (tefan Sakalk). + BF: Did not properly highlight new commands in the YankRing + window (Thilo Six). + + 17.0: April 28, 2013 + NF: The yankring_history_dir option can now take a comma separated + list. First valid directory found will be used (Alex Bel). + NF: YankRing can now monitor inserted text and place it in the ring. + This is disabled by default, but can be enabled either through + the YankRing window or via your .vimrc using the new option: + g:yankring_record_insert = 1 (Alexandre Viau). + BF: When g:yankring_persist = 0, the YankRing was still reading + and writing to the yankring file (Vladimir Marek). + BF: The YankRing menu entry, "Replace with Next", was performing + the "Replace with Previous" action (Thilo Six). + + 16.0: January 20, 2013 + BF: YankRing could report "YR: A register cannot be specified in + replace mode" when using clipboard = unnamed or unnamedplus. + This can often happen when fetching previous values from + the YankRing (i.e. or ). + + 15.0: January 2, 2013 + NF: Automatically turn off relativenumber for the YankRing + window (Emma Tramp). + NF: The YankRing window supports 1-9 to choose to paste those + items for quicker access to the top 9 items. + BF: When re-executing a macro using @ and the macro + used f, F, t, T, a "Press ENTER to continue" prompt + was displayed (Greg Sexton). + BF: Some documentation updates and script tweaks (Dominique Pell). + BF: The 0 register was updated during delete operations + (Christian Brabandt). + BF: When running a macro (@a), pressing @ displays a YankRing prompt + (YR:Enter character:) to choose which macro name to run. This + prompt was displayed twice leading to a "Press ENTER or type + command to continue" Vim message. This change suppresses + the "Press ENTER" message (Greg Sexton). + BF: The YankRing prevented you from re-running the last macro + using @@. + BF: YRToggle (to disable / enable the YankRing) did not + unmap @. + BF: When prompted for a macro to run, if an invalid value was + provided, Vim could report "E354: Invalid register name". + BF: When using a Vim instance with < 80 columns and using a + horizontal YankRing window after opening and closing the + YankRing window the Vim window did not shrink back to + its original size (Eric Weir). + BF: Updated documented values of yankring_window_height and + yankring_window_width (Paul). + BF: It was not possible to paste from the * register if the + clipboard option contains unnamedplus before unnamed + (Marcin Szamotulski). + + 14.0: April 1, 2012 + NF: The YankRing window supports 1-9 to choose to paste those + items for quicker access to the top 9 items. + NF: The YankRing now maps the @ key to run macros. Not all actions + performed during the macro are recorded by the YankRing + as a number of items had to be unmapped to support the replay + of actions which can prompt the user for input (i.e. t and f) + (Asis Hallab). + BF: When flipping between applications the system clipboard + was not added to the YankRing in all cases. + BF: The YankRing could report E121: Undefined variable: + g:yankring_manual_clipboard_check (Thilo Six). + BF: The YankRing could report: E132: Function call depth is higher + than 'maxfuncdepth'. When executing a YRClear or YRPop or + when flipping between applications (Marcin Szamotulski). + BF: Strange behaviour when opening the YankRing with + :e [YankRing] instead of :YRShow (Marcin Szamotulski). + + 13.0: February 5, 2012 + NF: [p, ]p, [P, ]P are now supported within the YankRing + window (Alexandre Provencio). + NF: When using the console version of Vim the yankring was not + detecting the "+ register automatically as the FocusGained + event does not fire in console mode. When new elements are + added or the YankRing is shown the clipboard will be + checked for new values (Giuseppe Rota). + NF: Added a new option, g:yankring_manual_clipboard_check which + when enabled will manually check for clipboard changes at + certain times within the YankRing. This option is not used + if the GUI is running as the FocusGained will perform checks + at appropriate times (Erik Westrup). + BF: With clipboard=unnamed replacing the previous paste with a + different value from the YankRing did not work in all cases + (Chris Lott). + BF: Under certain conditions the YankRing would still check + the system clipboard even if g:yankring_clipboard_monitor == 0. + This can lead to delays when attempting to access the + clipboard when running in console mode. Starting Vim with + the -X switch removes the delay (Erik Westrup). + BF: Incorrect syntax setting cpoptions (Thilo Six). + + 12.0: October 15, 2011 + NF: A console Vim does not necessarily react to a FocusGained event + which means as you switch Focus back and forth between a + console Vim, the YankRing's feature to automatically gather + changes to the system clipboard is not triggered. Now special + processing takes place in various spots when you are not running + Vim with a GUI, to check for changes to the clipboard. Those + already running a GUI Vim, are unaffected by this change + (Giuseppe Rota). + NF: New command, YRCheckClipboard, which allows you to force + the YankRing to check the system clipboard and if the + value is not present already in the YankRing, it will add it. + This is typically done automatically, but certain console + Vim's do not receive the necessary events for automation. + BF: Some additional changes were required for the "unnamedplus" + support. + BF: YRGetMultiple reported an error, though typically you would + use YRShow to paste the items. + + 12.0: September 16, 2011 + NF: Added support for the clipboard option "unnamedplus" which was + added after 7.3 (Hong Xu). + NF: When displaying the YankRing using YRShow, a new command "R" + has been added to display all of Vim's registers [0-9a-z]. + BF: YRMapsDelete did not remove the normal mode @ map, which + interferes with recorded macros (Philippe Vaucher). + + 11.0: August 09, 2010 + NF: Documented the global variables to customize the location + of the YankRing menu. + NF: The YankRing menu now shows the maps used for the default + actions to help learn them more easily. + NF: Added g:yankring_menu_root and g:yankring_menu_priority + (David Barsam). + NF: Added a warning indicating a stored value has been truncated + based on g:yankring_max_element_length and a new option to + suppress this warning, g:yankring_warn_on_truncate (Hans-Gnter). + BF: The YRAfterMaps() function (if it exists) was not re-run if + YRToggle was used to disable and enable the YankRing. + BF: Multibyte strings may not have been pasted correctly (Dr. Chip). + BF: When pasting a string of 1111's, and additional -1 could also + be included in the output. + + 10.0: January 31, 2010 + NF: Change the buffer name to [YankRing] to resemble other + non-user buffers. + NF: Added g:yankring_min_element_length which can prevent + items from being added to the YankRing if they are too small. + For example, single character deletes (Vedran M). + BF: When shifting focus back to Vim, the YankRing may incorrectly + report: "YR:Failed to change to the yankring buffer, + please contact author". + BF: When entering Vim for the first time and hitting "p" + nothing was pasted (Mark Huiskes). + BF: When entering Vim for the first time and the + yankring_clipboard_monitor = 1, the clipboard entry + was not automatically added to the yankring. + BF: When overriding the default and setting + g:yankring_window_use_bottom = 0, the YankRing would + report the error (Sergey Khorev): + E21: Cannot make changes, 'modifiable' is off + + 9.0: August 29, 2009: + BF: You cannot execute a macro with ":normal @a". It is still + not possible, but you can execute it with ":normal! @a" + (A S Budden). + BF: When g:yankring_persist = 0 the YankRing could go into + an infinite loop (A S Budden). + BF: When replaying a macro which used any of the zap + keys (f,F,t,T,/,?) you were prompted again for the + string to match on (Ovidiu C). + BF: When checking the clipboard for changes + (g:yankring_clipboard_monitor == 1) only add the item + if it is not already in the ring. Previously, the item + was moved to the top of the YankRing each time you flipped + focus. + + 8.0: December 21, 2008: + NF: Changed the implementation of YRGetSearch() (David Liang). + BF: Under some unknown circumstances, the yankring can fail + to change to the correct buffer. Put in code to double + check and abort. + BF: Yanking and pasting a line which ends in a backslash + resulted in the backslash being replaced by "@@@". + BF: When repeating a command (".") which used any of the zap + keys (f,F,t,T,/,?) you were prompted again for the + string to match on (Vasilii Pascal). + + 7.0: November 14, 2008: + NF: Added support for the / and ? motions so that y/search is + supported (Vasilii Pascal). + NF: When the YankRing window is displayed (or updated) an additional + check is made against the default register. If it has changed + since the YankRing recorded it, the value will be added to the + history. + NF: Added support for more motions h, j, k, l, H, M, L, ^, 0, -, +, _. + And a pile of g motions g_, g^, gm, g$, gk, gj, gg, ge, gE. + NF: The YankRing window will display a message it is operating + in a limited mode if not using Vim 7.2 or the correct patch + level. + BF: Correction to some internal code which could lead to an + endless loop (John Beckett). + BF: Opening and closing the YankRing window with "set report=0" + reported "1 line less" messages (Bill McCarthy). + BF: Changed the default value of g:yankring_paste_check_default_buffer + to check if the default paste buffer has changed when pressing + 'p'. For example, if a plugin has changed the default registers + it will be pasted rather than the top item from the YankRing. + BF: YRMapsDelete did not remove all the maps created by the YankRing. + BF: Under particular circumstances, yanking text with embedded @ + characters were not properly stored and retrieved from the + YankRing (Andrew Long). + BF: Changed to use xmaps instead of vmaps so that the maps only work + in visual mode and not select mode (David Liang). + + 6.1: October 31, 2008: + BF: If the g:yankring_history_dir contains spaces (default on + Windows) an error was reported. A simple work around was to + let g:yankring_history_dir = 'c:\Vim' or no spaces (Matt). + + 6.0: October 25, 2008: + NF: The YankRing now maintains the history in a file. This means + if you are running multiple instances of Vim, they all see + the same yankring. + NF: The location and name of the file is configurable by the user. + NF: The g:yankring_separator is no longer used and has been removed. + NF: The g:yankring_max_element_length can be used to limit the size + of an element in the yankring. + NF: The g:yankring_share_between_instances can be used to indicate + whether each instance of Vim running on a machine should share + the history file or whether each should have their own + individual history file. + NF: The g:yankring_clipboard_monitor can be used to indicate + whether changes to the system clipboard should be added to the + YankRing (default is on). + NF: The YankRing window can toggle the clipboard monitor by pressing + 'c'. See the help in the window by pressing ?. + NF: Added some highlighting to the YankRing window (Marty Grenfell). + + 5.0: September 21, 2008: + NF: The YankRing can recognize certain Vim commands which do not + change the contents of a buffer and not attempt to capture it. + NF: The global variables which allow you to customize the behaviour + are now space separated instead of comma separated. This + provides greater flexibility but will require you to modify + your .vimrc (if you have customized it). (Andy Wokula) + BF: If using from within insert mode, the YankRing inserted + characters into the buffer instead of capturing the changes, + this was fixed by Andy Wokula (Agathoklis Hatzimanikas). + BF: The YankRing did not properly account for all the different + forms of counts "5yy" worked but "y5y" did not (Edwin Shao). + + 4.1: August 9, 2008: + NF: The YankRing now allows you to override which operators should + be ignored (yankring_ignore_operator). By default this is + set for the standard Vim operators which do not modify any + registers (Examples: = and gu) (Andy Wokula). + NF: The YankRing did not map v_x (Matt Tolton). + BF: The expression register (quote=) was not accounted for correctly + (Agathoklis Hatzimanikas). + BF: Using the v:operator variable must be escaped when used in + a regular expression. + + 4.0: June 24, 2008: + NF: The YankRing by default now captures all |text-objects| and + all motions (|motion.txt|) which Vim supports. Version 3.0 only + supported a subset of the basic motion commands. + NF: Prior to this version only predefined maps triggered the + capture of data into the yankring. These maps only supported + yanks and deletes. The YankRing now also supports + operator-pending mode, which allows a greater range of operations + to be automatically captured and added to the yankring. + Operating pending mode functionality requires Vim 7.2 or Vim 7.1 + with patch #205. If using Vim 7.1 you can determine this with: + echo has("patch205") + NF: Prior to this version only yanks and deletes were registered + in the yankring. Changes are now also captured into the + yankring. + NF: The YankRing will also capture the system clipboard when focus is + returned to the vim window. This is useful if you copy text + between applications. + NF: The YankRing window always opened bottom horizontal. Now it + can be opened top or bottom and horizontal or vertically. + This can be controlled via variables in your .vimrc. + BF: The YankRing has an option to persist between instances of Vim by + storing the values in global variables within the viminfo. This + has led to some unusual ordering of items in the ring from + conflicts between instances. This option has been turned off by + default. + BF: Their was an issue with yanking using y$. + + 3.1: September 10, 2007: + NF: YRClear will now unlet all global variables it uses to store + the data if the persist storage is specified (the default). + Large values in the viminfo file could possibly affect other + applications. + + 3.0: September 7, 2007: + NF: Converted the YankRing to use the new Vim7's List object which + means it is no longer compatible with Vim6. + NF: By default the YankRing will now maintain the yankring's items + persistently by default. It does this via the |viminfo| file. + This means the contents of the YankRing rely on the internal + variables of only 1 Vim instance. + BF: YRToggle was not unmapping 'gp' and 'gP'. + BF: YRSearch prompted the user for a regex even if one was provided + on the command line. + BF: If g:yankring_manage_numbered_reg is enabled, the "." operator + did not correctly repeat the previous action (Pedro DeRose). + + 2.2: November 1, 2005: + NF: Added 'x' to the list of yankring_n_keys. This is very useful + in visual mode since it can delete a lot of characters. + + 2.2: October 19, 2005: + BF: If you pressed '?' to toggle the display of the help in the + YankRing window, the window would close. This also applied to + 'a', which allowed you to toggle the autoclose feature. + + 2.1: October 11, 2005: + NF: Added the ability for the YankRing to override Vim's numbered + registers. Instead of the numbered registers holding the last + yanked value, and the 9 previous deletes, they will now reflect + the top 10 items in the yankring. This allows you to reference + them directly with "5p. + + 2.0: August 20, 2005: + NF: Much improved usability, the YankRing now has a "GUI" to service + the yankring. If YRShow or YRSearch is used, a split buffer is + opened which displays all the elements in the yankring. There + are a number of maps that allow you to interact with the + contents. The window can be positioned vertically or + horizontally as well as being sized all through options + specified in your .vimrc. + NF: YRPop can now delete any items from the yankring, rather + that just from the top. + NF: YRSetTop has been removed, it is no longer required as the + internal representation of the YankRing has changed. + BF: If g:yankring_ignore_duplicate is set (which is the default) + you could get some unpredicable results when moving + backwards and forwards ( and ) through the + previous values. + + 1.7: June 10, 2005: + BF: The expression register support added in version 1.6 used + getreg('='), which has the side effect of executing the + expression register. Depending on what was in the register + this could have unusual results. Changed to use histget(). + + 1.6: April 20, 2005: + NF: YRSearch is similar to YRGetElem. Given a regular expression + it will interactively display all the elements in the yankring + that match the regular expression. You can enter the number + of the element to paste it. If you have many elements within + the yankring, this can help you identify them more easily. + NF: Updated the default history size from 30 to 100, which is + partially the reason for the YRSearch command. + NF: By default it supports "gp" and "gP", in addition to "p" and "P". + NF: Added support for the expression register (:h quote=). Here + is an example of how it is used: + "="X"P + + 1.5: March 30, 2005: + NF: The YankRing now respects the cpoptions setting, if 'y' is + included and you press '.', the previous yank command is executed + and added to the yankring. You can also add this behaviour by + setting this in your |vimrc|: > + let g:yankring_dot_repeat_yank = 1 +< NF: Duplicates will not be added to the YankRing by default. If + a duplicate is found, the element will be moved to the top + of the yankring. This can be controlled by setting this in + your |vimrc|: > + let g:yankring_ignore_duplicate = 0 (1 is default) +< BF: Regression from version 1.4, the '.' operator may incorrectly + insert garbage. + + 1.4: March 28, 2005: + NF: YRToggle has been updated. If you toggle the YankRing off + (disable) the maps it creates are removed. Calling YRToggle + again will recreate the maps. This truly disables the yankring, + where the previous version attempted to do this via code. + BF: Using the '.' operator was not correctly replaying operations + that did not move text in some way (g~t_) changed the case + of the text but a '.' did not replay it. + BF: When replacing previously pasted text the YankRing did not + respect what key was used to paste the text originally. + All replaced items were pasted using 'p', even if you had + originally pasted the text with 'P'. + + 1.3: March 16, 2005: + BF: The '.' operator did not handle the <<, >> shift operator. + Pressing '.' would result in the previous YankRing operation + instead of repeating the shift. + + 1.2: March 14, 2005: + NF: Added support for '.' operator to repeat the last change. + NF: Changed YRGetElem to show the contents of the yankring + and allow you to choose which element you want pasted. + It is only interactive if you do not provide a parameter. + NF: Added 'ygg,dgg' default maps by extending the yankring_n_keys + variable. + + 1.1: March 09, 2005: + NF: Added support for the black hole register |quote_|. + NF: Custom Maps allows the user to more finely tune the yankring + maps to perform whatever action they require. This function, + YRRunAfterMaps(), is run automatically after the YankRing + creates it's default mappings. See |yankring-custom-maps|. + NF: Added some more default maps by extending the yankring_n_keys + variable. It now contains: + yy,dd,yw,dw,ye,de,yE,dE,yiw,diw,yaw,daw,y$,d$,Y,D,yG,dG + NOTE: You can easily extend these default mappings by + creating this global variable in your |vimrc|, you do not + have to wait for the plugin to be updated. + NF: Added support for Dr. Chips GetLatestVimScripts plugin. + BF: The check for g:yankring_n_keys was incorrect, so it was not + possible to override the default maps. + + 1.0: March 08, 2005: + NF: Initial release. + +vim: ts=4 ft=help tw=78 diff --git a/sources_non_forked/YankRing.vim/plugin/yankring.vim b/sources_non_forked/YankRing.vim/plugin/yankring.vim new file mode 100644 index 00000000..3cc67806 --- /dev/null +++ b/sources_non_forked/YankRing.vim/plugin/yankring.vim @@ -0,0 +1,2885 @@ +" yankring.vim - Yank / Delete Ring for Vim +" --------------------------------------------------------------- +" Version: 19.0 +" Author: David Fishburn +" Maintainer: David Fishburn +" Last Modified: 2015 Jul 27 +" Script: http://www.vim.org/scripts/script.php?script_id=1234 +" Based On: Mocked up version by Yegappan Lakshmanan +" http://groups.yahoo.com/group/vim/post?act=reply&messageNum=34406 +" License: GPL (Gnu Public License) +" GetLatestVimScripts: 1234 1 :AutoInstall: yankring.vim + +if exists('g:loaded_yankring') + finish +endif + +if v:version < 700 + echomsg 'yankring: You need at least Vim 7.0' + finish +endif + +let g:loaded_yankring = 190 + +" Turn on support for line continuations when creating the script +let s:cpo_save = &cpo +set cpo&vim + +let s:yr_has_voperator = 0 +if v:version > 701 || ( v:version == 701 && has("patch205") ) + let s:yr_has_voperator = 1 +endif + +if !exists('g:yankring_history_dir') + let g:yankring_history_dir = expand('$HOME') +else + " let g:yankring_history_dir = expand(g:yankring_history_dir) + for dir in split(g:yankring_history_dir, ",") + if isdirectory(expand(dir)) + let g:yankring_history_dir = expand(dir) + break + endif + endfor +endif + +if !exists('g:yankring_buffer_name') + let g:yankring_buffer_name = '[YankRing]' +endif + +if !exists('g:yankring_history_file') + let g:yankring_history_file = 'yankring_history' +endif + +" Allow the user to override the # of yanks/deletes recorded +if !exists('g:yankring_max_history') + let g:yankring_max_history = 100 +elseif g:yankring_max_history < 0 + let g:yankring_max_history = 100 +endif + +" Specify the minimum length of 1 entry +if !exists('g:yankring_min_element_length') + let g:yankring_min_element_length = 1 +endif + +" Specify the maximum length of 1 entry (1MB default) +if !exists('g:yankring_max_element_length') + let g:yankring_max_element_length = 1048576 +endif + +" Warn if truncation occurs +if !exists('g:yankring_warn_on_truncate') + let g:yankring_warn_on_truncate = 1 +endif + +" Allow the user to specify if the plugin is enabled or not +if !exists('g:yankring_enabled') + let g:yankring_enabled = 1 +endif + +" Specify max display length for each element for YRShow +if !exists('g:yankring_max_display') + let g:yankring_max_display = 0 +endif + +" Check if yankring should persist between Vim instances +if !exists('g:yankring_persist') + let g:yankring_persist = 1 +endif + +" Check if yankring share 1 file between all instances of Vim +if !exists('g:yankring_share_between_instances') + let g:yankring_share_between_instances = 1 +endif + +" Specify whether the results of the ring should be displayed +" in a separate buffer window instead of the use of echo +if !exists('g:yankring_window_use_separate') + let g:yankring_window_use_separate = 1 +endif + +" Specifies whether the window is closed after an action +" is performed +if !exists('g:yankring_window_auto_close') + let g:yankring_window_auto_close = 1 +endif + +" When displaying the buffer, how many lines should it be +if !exists('g:yankring_window_height') + let g:yankring_window_height = 8 +endif + +" When displaying the buffer, how many columns should it be +if !exists('g:yankring_window_width') + let g:yankring_window_width = 30 +endif + +" When displaying the buffer, where it should be placed +if !exists('g:yankring_window_use_horiz') + let g:yankring_window_use_horiz = 1 +endif + +" When displaying the buffer, where it should be placed +if !exists('g:yankring_window_use_bottom') + let g:yankring_window_use_bottom = 1 +endif + +" When displaying the buffer, where it should be placed +if !exists('g:yankring_window_use_right') + let g:yankring_window_use_right = 1 +endif + +" If the user presses , toggle the width of the window +if !exists('g:yankring_window_increment') + let g:yankring_window_increment = 50 +endif + +" Controls whether the . operator will repeat yank operations +" The default is based on cpoptions: |cpo-y| +" y A yank command can be redone with ".". +if !exists('g:yankring_dot_repeat_yank') + let g:yankring_dot_repeat_yank = (s:cpo_save=~'y'?1:0) +endif + +" Only adds unique items to the yankring. +" If the item already exists, that element is set as the +" top of the yankring. +if !exists('g:yankring_ignore_duplicate') + let g:yankring_ignore_duplicate = 1 +endif + +" Determine whether to record inserted data +if !exists('g:yankring_record_insert') + let g:yankring_record_insert = 0 +endif + +" Vim automatically manages the numbered registers: +" 0 - last yanked text +" 1-9 - last deleted items +" If this option is turned on, the yankring will manage the +" values in them. +if !exists('g:yankring_manage_numbered_reg') + let g:yankring_manage_numbered_reg = 0 +endif + +" Allow the user to specify what characters to use for the mappings. +if !exists('g:yankring_n_keys') + " 7.1.patch205 introduces the v:operator function which was essential + " to gain the omap support. + if s:yr_has_voperator == 1 + " Use omaps for the rest of the functionality + let g:yankring_n_keys = 'Y D x X' + else + let g:yankring_n_keys = 'x yy dd yw dw ye de yE dE yiw diw yaw daw y$ d$ Y D yG dG ygg dgg' + endif +endif + +" Allow the user to specify what operator pending motions to map +if !exists('g:yankring_o_keys') + " o-motions and text objects, without zap-to-char motions + let g:yankring_o_keys = 'b B w W e E d h j k l H M L y G ^ 0 $ , ;' + let g:yankring_o_keys .= ' g_ g^ gm g$ gk gj gg ge gE - + _ ' + let g:yankring_o_keys .= ' iw iW aw aW as is ap ip a] a[ i] i[ a) a( ab i) i( ib a> a< i> i< at it a} a{ aB i} i{ iB a" a'' a` i" i'' i`' +endif + +if !exists('g:yankring_zap_keys') + let g:yankring_zap_keys = 'f F t T / ?' +endif + +" Allow the user to specify what operator pending motions to map +if !exists('g:yankring_ignore_operator') + let g:yankring_ignore_operator = 'g~ gu gU ! = gq g? > < zf g@' +endif +let g:yankring_ignore_operator = ' '.g:yankring_ignore_operator.' ' + +" Whether we should map the . operator +if !exists('g:yankring_map_dot') + let g:yankring_map_dot = 1 +endif + +" Whether we sould map the "g" paste operators +if !exists('g:yankring_paste_using_g') + let g:yankring_paste_using_g = 1 +endif + +if !exists('g:yankring_v_key') + let g:yankring_v_key = 'y' +endif + +if !exists('g:yankring_del_v_key') + let g:yankring_del_v_key = 'd x' +endif + +if !exists('g:yankring_paste_n_bkey') + let g:yankring_paste_n_bkey = 'P' +endif + +if !exists('g:yankring_paste_n_akey') + let g:yankring_paste_n_akey = 'p' +endif + +if !exists('g:yankring_paste_v_bkey') + let g:yankring_paste_v_bkey = 'P' +endif + +if !exists('g:yankring_paste_v_akey') + let g:yankring_paste_v_akey = 'p' +endif + +if exists('g:yankring_paste_check_default_buffer') + let g:yankring_paste_check_default_register = g:yankring_paste_check_default_buffer +endif + +if !exists('g:yankring_paste_check_default_register') + let g:yankring_paste_check_default_register = 1 +endif + +if !exists('g:yankring_replace_n_pkey') + let g:yankring_replace_n_pkey = '' +endif + +if !exists('g:yankring_replace_n_nkey') + let g:yankring_replace_n_nkey = '' +endif + +if !exists('g:yankring_clipboard_monitor') + let g:yankring_clipboard_monitor = (has('clipboard')?1:0) +endif + +if !exists('g:yankring_manual_clipboard_check') + let g:yankring_manual_clipboard_check = 0 + if g:yankring_clipboard_monitor == 1 + if has("gui_running") + " FocusGained event will take care of + " monitoring the clipboard. + let g:yankring_manual_clipboard_check = 0 + else + " If the GUI is not running and the user wants to monitor the + " clipboard, we need to manually check for clipboard entries as + " the FocusGained event does not fire in console mode. + let g:yankring_manual_clipboard_check = 1 + endif + endif +endif + +if !exists('g:yankring_default_menu_mode') + let g:yankring_default_menu_mode = 3 +endif + +" Script variables for the yankring buffer +let s:yr_buffer_last_winnr = -1 +let s:yr_buffer_last = -1 +let s:yr_buffer_id = -1 +let s:yr_search = '' +let s:yr_remove_omap_dot = 0 +let s:yr_history_version = 'v2' +let s:yr_history_v1_nl = '@@@' +let s:yr_history_v1_nl_pat = '\%(\\\)\@ 0 + let new_state = ((a:1 == 1) ? 1 : 0) + endif + + " YRToggle accepts an integer value to specify the state + if new_state == g:yankring_enabled + return + elseif new_state == 1 + call s:YRMapsCreate() + call s:YRWarningMsg('YR: The YankRing is now enabled') + else + call s:YRMapsDelete() + call s:YRWarningMsg('YR: The YankRing is now disabled') + endif +endfunction + +" Enables or disables the yankring +function! s:YRDisplayElem(disp_nbr, script_var) + if g:yankring_max_display == 0 + if g:yankring_window_use_separate == 1 + let max_display = 500 + else + let max_display = g:yankring_window_width + + \ g:yankring_window_increment - + \ 12 + endif + else + let max_display = g:yankring_max_display + endif + + let elem = matchstr(a:script_var, '^.*\ze,.*$') + if s:yr_history_version == 'v1' + " v1 + " let elem = substitute(elem, '\%(\\\)\@max_display)? + \ (strpart(elem,0,max_display). + \ '...'): + \ elem + \ ) + \ ) + + return "" +endfunction + +" Enables or disables the yankring +function! s:YRShow(...) + " Prevent recursion + if exists('s:yankring_showing') && s:yankring_showing == 1 + " call s:YRWarningMsg('YR: YRShow aborting for recursion') + return + endif + + if g:yankring_enabled == 0 + call s:YRWarningMsg('YR: The YankRing is disabled, use YRToggle to re-enable') + return + endif + + " Prevent recursion + let s:yankring_showing = 1 + + " If the GUI is not running, we need to manually check for clipboard + " entries as the FocusGained event does not fire in console mode. + if g:yankring_manual_clipboard_check == 1 + call s:YRCheckClipboard() + endif + + " If no parameter was provided assume the user wants to + " toggle the display. + let toggle = 1 + if a:0 > 0 + let toggle = matchstr(a:1, '\d\+') + endif + + let show_registers = 0 + if a:0 > 1 && a:2 ==# 'R' + let show_registers = 1 + endif + + if toggle == 1 + if bufwinnr(s:yr_buffer_id) > -1 + " If the YankRing window is already open close it + exec bufwinnr(s:yr_buffer_id) . "wincmd w" + " Quit the YankRing + call s:YRWindowAction('q', 'n') + + " Switch back to the window which the YankRing + " window was opened from + if bufwinnr(s:yr_buffer_last) != -1 + " If the buffer is visible, switch to it + exec s:yr_buffer_last_winnr . "wincmd w" + endif + + " Prevent recursion + let s:yankring_showing = 0 + + return + endif + endif + + " Reset the search string, since this is automatically called + " if the yankring window is open. A previous search must be + " cleared since we do not want to show new items. The user can + " always run the search again. + let s:yr_search = "" + + " It is possible for registers to be changed outside of the + " maps of the YankRing. Perform this quick check when we + " show the contents (or when it is refreshed). + if g:yankring_paste_check_default_register == 1 + let save_reg = 0 + let register = ((&clipboard=~'\')?'*':((&clipboard=~'\' && has('unnamedplus'))?'+':'"')) + + if &clipboard =~ '\' && getreg('*') != s:yr_prev_clipboard_star + let save_reg = 1 + endif + if has('unnamedplus') && &clipboard =~ '\' && getreg('+') != s:yr_prev_clipboard_plus + let save_reg = 1 + endif + if register == '"' && getreg('"') != s:yr_prev_reg_unnamed + let save_reg = 1 + endif + + if save_reg == 1 + " The user has performed a yank / delete operation + " outside of the yankring maps. Add this + " value to the yankring. + call YRRecord(register) + endif + endif + + " List is shown in order of replacement + " assuming using previous yanks + let output = "--- YankRing ---\n" + let output = output . (show_registers == 1 ? 'Reg ' : 'Elem')." Content\n" + + if show_registers == 1 + for reg_name in map( range(char2nr('0'), char2nr('9')) + + \ (range(char2nr('a'), char2nr('z'))) + \, 'nr2char(v:val)' + \ ) + let output = output . s:YRDisplayElem(reg_name, getreg(reg_name).',') . "\n" + endfor + else + call s:YRHistoryRead() + let disp_item_nr = 1 + for elem in s:yr_history_list + let output = output . s:YRDisplayElem(disp_item_nr, elem) . "\n" + let disp_item_nr += 1 + endfor + endif + + if g:yankring_window_use_separate == 1 + call s:YRWindowOpen(output) + else + echo output + endif + + " Prevent recursion + let s:yankring_showing = 0 +endfunction + + +" Used in omaps if a following character is required +" like with motions (f,t) +function! s:YRGetChar() + let msg = "YR:Enter character:" + " echomsg msg + echo msg + let c = getchar() + if c =~ '^\d\+$' + let c = nr2char(c) + " echomsg msg.c + echon c + endif + return c +endfunction + + +" Used in omaps if a following string is required +" like with motions (/,?) +" function! s:YRGetSearch() +" " let msg = "YR:Enter string:" +" " echomsg msg +" let str = input("YR:Enter string:") +" " let str = '' +" " while 1==1 +" " let c = getchar() +" " if c =~ '^\d\+$' +" " let c = nr2char(c) +" " if c == "\" +" " return c +" " endif +" " if c == "\" +" " break +" " endif +" " let str = str.c +" " echomsg msg.str +" " else +" " break +" " endif +" " endwhile +" return str +" endfunction + + +" Paste a certain item from the yankring +" If no parameter is provided, this function becomes interactive. It will +" display the list (using YRShow) and allow the user to choose an element. +function! s:YRGetElem(...) + if g:yankring_manual_clipboard_check == 1 + call s:YRCheckClipboard() + endif + + if s:yr_count == 0 + call s:YRWarningMsg('YR: yankring is empty') + return -1 + endif + + let default_buffer = ((&clipboard=~'\')?'*':((&clipboard=~'\' && has('unnamedplus'))?'+':'"')) + + let direction = 'p' + if a:0 > 1 + " If the user indicated to paste above or below + " let direction = ((a:2 ==# 'P') ? 'P' : 'p') + if a:2 =~ '\<\(p\|gp\|P\|gP\)\>' + let direction = a:2 + endif + endif + + " Check to see if a specific value has been provided + let elem = 0 + if a:0 > 0 + " Ensure we get only the numeric value (trim it) + let elem = matchstr(a:1, '\d\+') + let elem = elem - 1 + else + " If no parameter was supplied display the yankring + " and prompt the user to enter the value they want pasted. + call s:YRShow(0) + + if g:yankring_window_use_separate == 1 + " The window buffer is used instead of command line + return + endif + + let elem = input("Enter # to paste:") + + " Ensure we get only the numeric value (trim it) + let elem = matchstr(elem, '\d\+') + + if elem == '' + " They most likely pressed enter without entering a value + return + endif + + let elem = elem - 1 + endif + + if elem < 0 || elem >= s:yr_count + call s:YRWarningMsg("YR: Invalid choice:".elem) + return -1 + endif + + let default_buffer = ((&clipboard=~'\')?'*':((&clipboard=~'\' && has('unnamedplus'))?'+':'"')) + call setreg(default_buffer + \ , s:YRGetValElemNbr((elem), 'v') + \ , s:YRGetValElemNbr((elem), 't') + \ ) + exec 'normal! "'.default_buffer.direction + + " Set the previous action as a paste in case the user + " press . to repeat + call s:YRSetPrevOP('p', '', default_buffer, 'n') + +endfunction + + +" Starting the top of the ring it will paste x items from it +function! s:YRGetMultiple(reverse_order, ...) + if g:yankring_manual_clipboard_check == 1 + call s:YRCheckClipboard() + endif + + if s:yr_count == 0 + call s:YRWarningMsg('YR: yankring is empty') + return + endif + + let max = 1 + if a:0 == 1 + " If the user provided a range, exit after that many + " have been displayed + let max = matchstr(a:1, '\d\+') + endif + if max > s:yr_count + " Default to all items if they specified a very high value + let max = s:yr_count + endif + + " Base the increment on the sort order of the results + let increment = ((a:reverse_order==0)?(1):(-1)) + if a:reverse_order == 0 + let increment = 1 + let elem = 1 + else + let increment = -1 + let elem = max + endif + + if a:0 > 1 + let iter = 1 + while iter <= a:0 + let elem = (a:{iter} - 1) + call s:YRGetElem(elem) + let iter = iter + 1 + endwhile + else + while max > 0 + " Paste the first item, and move on to the next. + call s:YRGetElem(elem) + let elem = elem + increment + let max = max - 1 + endwhile + endif +endfunction + + +" Given a regular expression, check each element within +" the yankring, display only the matching items and prompt +" the user for which item to paste +function! s:YRSearch(...) + if s:yr_count == 0 + call s:YRWarningMsg('YR: yankring is empty') + return + endif + + let s:yr_search = "" + " If the user provided a range, exit after that many + " have been displayed + if a:0 == 0 || (a:0 == 1 && a:1 == "") + let s:yr_search = input('Enter [optional] regex:') + else + let s:yr_search = a:1 + endif + + if s:yr_search == "" + " Show the entire yankring + call s:YRShow(0) + return + endif + + " List is shown in order of replacement + " assuming using previous yanks + let output = "--- YankRing ---\n" + let output = output . "Elem Content\n" + let valid_choices = [] + + let search_result = filter(copy(s:yr_history_list), "v:val =~ '".s:yr_search."'") + + let disp_item_nr = 1 + + for elem in s:yr_history_list + if elem =~ s:yr_search + let output = output . s:YRDisplayElem(disp_item_nr, elem) . "\n" + call add(valid_choices, disp_item_nr.'') + endif + let disp_item_nr += 1 + endfor + + if empty(valid_choices) + let output = output . "Search for [".s:yr_search."] did not match any items " + endif + + if g:yankring_window_use_separate == 1 + call s:YRWindowOpen(output) + else + if !empty(valid_choices) + echo output + let elem = input("Enter # to paste:") + + " Ensure we get only the numeric value (trim it) + let elem = matchstr(elem, '\d\+') + + if elem == '' + " They most likely pressed enter without entering a value + return + endif + + if index(valid_choices, elem) != -1 + exec 'YRGetElem ' . elem + else + " User did not choose one of the elements that were found + " Remove leading , + call s:YRWarningMsg( "YR: Item[" . elem . "] not found, only valid choices are[" . + \ join(valid_choices, ',') . + \ "]" + \ ) + return -1 + endif + + else + call s:YRWarningMsg( "YR: The pattern [" . + \ s:yr_search . + \ "] does not match any items in the yankring" + \ ) + endif + endif + +endfunction + + +" Resets the common script variables for managing the ring. +function! s:YRReset() + call s:YRHistoryDelete() + " Update the history file + call s:YRHistorySave() +endfunction + + +" Clears the yankring by simply setting the # of items in it to 0. +" There is no need physically unlet each variable. +function! s:YRInit(...) + let s:yr_next_idx = 0 + let s:yr_last_paste_idx = 1 + let s:yr_count = 0 + let s:yr_history_last_upd = 0 + let s:yr_history_list = [] + let s:yr_paste_dir = 'p' + + " For the . op support + let s:yr_prev_op_code = '' + let s:yr_prev_op_mode = 'n' + let s:yr_prev_count = '' + let s:yr_prev_reg = '' + let s:yr_prev_reg_unnamed = getreg('"') + let s:yr_prev_reg_small = '' + let s:yr_prev_reg_insert = '' + let s:yr_prev_reg_expres = '' + let s:yr_prev_clipboard_star = '' + let s:yr_prev_clipboard_plus = '' + let s:yr_prev_vis_lstart = 0 + let s:yr_prev_vis_lend = 0 + let s:yr_prev_vis_cstart = 0 + let s:yr_prev_vis_cend = 0 + let s:yr_prev_changenr = 0 + let s:yr_prev_repeating = 0 + + " This is used to determine if the visual selection should be + " reset prior to issuing the YRReplace + let s:yr_prev_vis_mode = 0 + + if a:0 == 0 && g:yankring_persist != 1 + " The user wants the yankring reset each time Vim is started + call s:YRClear() + endif + + call s:YRHistoryRead() +endfunction + + +" Clears the yankring by simply setting the # of items in it to 0. +function! s:YRClear() + call s:YRReset() + call s:YRInit('DoNotClear') + + " If the yankring window is open, refresh it + call s:YRWindowUpdate() +endfunction + + +" Determine which register the user wants to use +" For example the 'a' register: "ayy +function! s:YRRegister() + " v:register can be blank in some (unknown) cases + " so test for this condition and return the + " default register + let user_register = ((v:register=='')?('"'):(v:register)) + let clipboard_default = matchstr( &clipboard, '\' ) + + " clipboard can have a comma separated list of values. + " Depending on which order the unnamed is referenced + " determines which register to use. + " set clipboard=unnamedplus,unnamed + " set clipboard=unnamed,unnamedplus + if clipboard_default == '\' && user_register == '"' + let user_register = '*' + endif + if has('unnamedplus') && clipboard_default == '\' && user_register == '"' + let user_register = '+' + endif + return user_register +endfunction + + +" Allows you to push a new item on the yankring. Useful if something +" is in the clipboard and you want to add it to the yankring. +" Or if you yank something that is not mapped. +function! s:YRPush(...) + let user_register = s:YRRegister() + + if a:0 > 0 + " If no yank command has been supplied, assume it is + " a full line yank + let user_register = ((a:1 == '') ? user_register : a:1) + endif + + " If we are pushing something on to the yankring, add it to + " the default buffer as well so the next item pasted will + " be the item pushed + let default_buffer = ((&clipboard=~'\')?'*':((&clipboard=~'\' && has('unnamedplus'))?'+':'"')) + call setreg(default_buffer, getreg(user_register), + \ getregtype(user_register)) + + call s:YRSetPrevOP('', '', '', 'n') + call YRRecord(user_register) +endfunction + + +" Allows you to pop off any element from the yankring. +" If no parameters are provided the first element is removed. +" If a vcount is provided, that many elements are removed +" from the top. +function! s:YRPop(...) + if s:yr_count == 0 + call s:YRWarningMsg('YR: yankring is empty') + return + endif + + let v_count = 1 + if a:0 > 1 + let v_count = a:2 + endif + + " If the user provided a parameter, remove that element + " from the yankring. + " If no parameter was provided assume the first element. + let elem_index = 0 + if a:0 > 0 + " Get the element # from the parameter + let elem_index = matchstr(a:1, '\d\+') + let elem_index = elem_index - 1 + endif + + " If the user entered a count, then remove that many + " elements from the ring. + while v_count > 0 + call s:YRMRUDel('s:yr_history_list', elem_index) + let v_count = v_count - 1 + endwhile + + " If the yankring window is open, refresh it + call s:YRWindowUpdate() +endfunction + + +" Adds this value to the yankring. +function! YRRecord(...) + + let register = '"' + if a:0 > 0 + " If no yank command has been supplied, assume it is + " a full line yank + let register = ((a:1 == '') ? register : a:1) + endif + + " v:register can be blank in some (unknown) cases + " if v:register == '' || v:register == '_' + if v:register == '_' + " Black hole register, ignore recording the operation + return "" + endif + + let register = ((&clipboard=~'\')?'*':((&clipboard=~'\' && has('unnamedplus'))?'+':register)) + + " let s:yr_prev_changenr = changenr() + if register == '"' + " If the change has occurred via an omap, we must delay + " the capture of the default register until this event + " since register updates are not reflected until the + " omap function completes + let s:yr_prev_reg_unnamed = getreg('"') + let s:yr_prev_reg_small = getreg('-') + endif + + " Add item to list + " This will also account for duplicates. + call s:YRMRUAdd( 's:yr_history_list' + \ , getreg(register) + \ , getregtype(register) + \ ) + + if g:yankring_clipboard_monitor == 1 + let s:yr_prev_clipboard_plus = getreg('+') + let s:yr_prev_clipboard_star = getreg('*') + endif + + " Manage the numbered registers + if g:yankring_manage_numbered_reg == 1 + " Allow the user to define an autocmd to dynamically + " setup their connection information. + silent! doautocmd User YRSetNumberedReg + endif + + " If the yankring window is open, refresh it + call s:YRWindowUpdate() + + " Reset the past paste entry to the top of the ring. + " When the user hits replace last entry it should + " start from the top (not from the last previous + " replace) after capturing a new value in the YankRing. + let s:yr_last_paste_idx = 1 + + return "" +endfunction + + +" Adds this value to the yankring. +function! YRRecord3(...) + let register = '"' + + if a:0 > 0 && a:1 != '' + let register = a:1 + else + " v:register can be blank in some (unknown) cases + " if v:register == '' || v:register == '_' + if v:register == '_' + " Black hole register, ignore recording the operation + return "" + endif + + let register = s:YRRegister() + + if &clipboard =~ '\' && register == '*' + " unnamed A variant of "unnamed" flag which uses the clipboard + " register '*' (|quote|) for all operations except yank. + " Yank shall copy the text into register '*' when "unnamed" + " is included. + " + let register = '*' + + " The + and * registers are not modified by yank operations. + " We do not know what operation triggered this event so do a + " simple check if the register values have changed. + " If not, check it against the " register. Use which ever + " one has changed. + if s:yr_prev_clipboard_star == '' || getreg(register) == s:yr_prev_clipboard_star + if getreg('"') != getreg(register) + let register = '"' + endif + endif + endif + + if has('unnamedplus') && &clipboard =~ '\' && register == '+' + " unnamedplus A variant of "unnamed" flag which uses the clipboard + " register '+' (|quoteplus|) instead of register '*' for all + " operations except yank. Yank shall copy the text into + " register '+' and also into '*' when "unnamed" is included. + " + let register = '+' + + " The + and * registers are not modified by yank operations. + " We do not know what operation triggered this event so do a + " simple check if the register values have changed. + " If not, check it against the " register. Use which ever + " one has changed. + if s:yr_prev_clipboard_plus == '' || getreg(register) == s:yr_prev_clipboard_plus + if getreg('"') != getreg(register) + let register = '"' + endif + endif + endif + endif + + if register == '"' + " If the change has occurred via an omap, we must delay + " the capture of the default register until this event + " since register updates are not reflected until the + " omap function completes + let s:yr_prev_reg_unnamed = getreg('"') + let s:yr_prev_reg_small = getreg('-') + endif + + if s:yr_remove_omap_dot == 1 + call s:YRMapsCreate('add_only_zap_keys') + endif + + " Add item to list + " This will also account for duplicates. + call s:YRMRUAdd( 's:yr_history_list' + \ , getreg(register) + \ , getregtype(register) + \ ) + + if g:yankring_clipboard_monitor == 1 + let s:yr_prev_clipboard_plus = getreg('+') + let s:yr_prev_clipboard_star = getreg('*') + endif + + " Manage the numbered registers + if g:yankring_manage_numbered_reg == 1 + " Allow the user to define an autocmd to dynamically + " setup their connection information. + silent! doautocmd User YRSetNumberedReg + endif + + " If the yankring window is open, refresh it + call s:YRWindowUpdate() + + " Reset the past paste entry to the top of the ring. + " When the user hits replace last entry it should + " start from the top (not from the last previous + " replace) after capturing a new value in the YankRing. + let s:yr_last_paste_idx = 1 + + return "" +endfunction + + +" Record the operation for the dot operator +function! s:YRSetPrevOP(op_code, count, reg, mode) + let s:yr_prev_op_code = a:op_code + let s:yr_prev_op_mode = a:mode + let s:yr_prev_count = a:count + let s:yr_prev_changenr = changenr() + let s:yr_prev_reg = a:reg + let s:yr_prev_reg_unnamed = getreg('"') + let s:yr_prev_reg_small = getreg('-') + let s:yr_prev_reg_insert = getreg('.') + let s:yr_prev_vis_lstart = line("'<") + let s:yr_prev_vis_lend = line("'>") + let s:yr_prev_vis_cstart = col("'<") + let s:yr_prev_vis_cend = col("'>") + let s:yr_prev_reg_expres = histget('=', -1) + + if a:mode == 'n' + " In normal mode, the change has already + " occurred, therefore we can mark the + " actual position of the change. + let s:yr_prev_chg_lstart = line("'[") + let s:yr_prev_chg_lend = line("']") + let s:yr_prev_chg_cstart = col("'[") + let s:yr_prev_chg_cend = col("']") + else + " If in operator pending mode, the change + " has not yet occurred. Therefore we cannot + " use the '[ and ]' markers. But we can + " store the current line position. + let s:yr_prev_chg_lstart = line(".") + let s:yr_prev_chg_lend = line(".") + let s:yr_prev_chg_cstart = col(".") + let s:yr_prev_chg_cend = col(".") + endif + + " If storing the last change position (using '[, ']) + " is not good enough, then another option is to: + " Use :redir on the :changes command + " and grab the last item. Store this value + " and compare it is YRDoRepeat. +endfunction + + +" Adds this value to the yankring. +function! s:YRDoRepeat() + let dorepeat = 0 + + if s:yr_has_voperator == 1 + " Let Vim handle the repeat, just capture the updates + " as usual. + return 0 + endif + + if s:yr_prev_op_code =~ '^c' + " You cannot repeat change operations, let Vim's + " standard mechanism handle these, or the user will + " be prompted again, instead of repeating the + " previous change. + return 0 + endif + + if g:yankring_manage_numbered_reg == 1 + " When resetting the numbered register we are + " must ignore the comparison of the " register. + if s:yr_prev_reg_small == getreg('-') && + \ s:yr_prev_reg_insert == getreg('.') && + \ s:yr_prev_reg_expres == histget('=', -1) && + \ s:yr_prev_vis_lstart == line("'<") && + \ s:yr_prev_vis_lend == line("'>") && + \ s:yr_prev_vis_cstart == col("'<") && + \ s:yr_prev_vis_cend == col("'>") && + \ s:yr_prev_chg_lstart == line("'[") && + \ s:yr_prev_chg_lend == line("']") && + \ s:yr_prev_chg_cstart == col("'[") && + \ s:yr_prev_chg_cend == col("']") + let dorepeat = 1 + endif + else + " Check the previously recorded value of the registers + " if they are the same, we need to reissue the previous + " yankring command. + " If any are different, the user performed a command + " command that did not involve the yankring, therefore + " we should just issue the standard "normal! ." to repeat it. + if s:yr_prev_reg_unnamed == getreg('"') && + \ s:yr_prev_reg_small == getreg('-') && + \ s:yr_prev_reg_insert == getreg('.') && + \ s:yr_prev_reg_expres == histget('=', -1) && + \ s:yr_prev_vis_lstart == line("'<") && + \ s:yr_prev_vis_lend == line("'>") && + \ s:yr_prev_vis_cstart == col("'<") && + \ s:yr_prev_vis_cend == col("'>") + let dorepeat = 1 + endif + if dorepeat == 1 && s:yr_prev_op_mode == 'n' + " Hmm, not sure why I was doing this now + " so I will remove it + " let dorepeat = 0 + " if s:yr_prev_chg_lstart == line("'[") && + " \ s:yr_prev_chg_lend == line("']") && + " \ s:yr_prev_chg_cstart == col("'[") && + " \ s:yr_prev_chg_cend == col("']") + " let dorepeat = 1 + " endif + elseif dorepeat == 1 && s:yr_prev_op_mode == 'o' + " Hmm, not sure why I was doing this now + " so I will remove it + " let dorepeat = 0 + " if s:yr_prev_chg_lstart == line("'[") && + " \ s:yr_prev_chg_lend == line("']") && + " \ s:yr_prev_chg_cstart == col("'[") && + " \ s:yr_prev_chg_cend == col("']") + " let dorepeat = 1 + " endif + endif + endif + + " " If another change has happened that was not part of the + " " yankring we cannot replay it (from the yankring). Use + " " the standard ".". + " " If the previous op was a change, do not use the yankring + " " to repeat it. + " " changenr() is buffer specific, so anytime you move to + " " a different buffer you will definitely perform a + " " standard "." + " " Any previous op that was a change, must be replaced using "." + " " since we do not want the user prompted to enter text again. + " if s:yr_prev_changenr == changenr() && s:yr_prev_op_code !~ '^c' + " let dorepeat = 1 + " endif + + " If we are going to repeat check to see if the + " previous command was a yank operation. If so determine + " if yank operations are allowed to be repeated. + if dorepeat == 1 && s:yr_prev_op_code =~ '^y' + " This value be default is set based on cpoptions. + if g:yankring_dot_repeat_yank == 0 + let dorepeat = 0 + endif + endif + return dorepeat +endfunction + + +" Manages the Vim's numbered registers +function! s:YRSetNumberedReg() + + let i = 0 + + while i <= 10 + if i > s:yr_count + break + endif + + call setreg( (i) + \ , s:YRGetValElemNbr((i),'v') + \ , s:YRGetValElemNbr((i),'t') + \ ) + let i += 1 + endwhile + + " There are a few actions that Vim automatically takes + " when modifying the numbered registers. + " Modifying register 1 - changes the named register. + " It is impossible to set register 2 to a value, since Vim will change it. + + " This will at least preserve the default register + let @" = @0 +endfunction + + +" This internal function will add and subtract values from a starting +" point and return the correct element number. It takes into account +" the circular nature of the yankring. +function! s:YRGetNextElem(start, iter) + + let needed_elem = a:start + a:iter + + " The yankring is a ring, so if an element is + " requested beyond the number of elements, we + " must wrap around the ring. + if needed_elem > s:yr_count + let needed_elem = needed_elem % s:yr_count + endif + + if needed_elem == 0 + " Can happen at the end or beginning of the ring + if a:iter == -1 + " Wrap to the bottom of the ring + let needed_elem = s:yr_count + else + " Wrap to the top of the ring + let needed_elem = 1 + endif + elseif needed_elem < 1 + " As we step backwards through the ring we could ask for a negative + " value, this will wrap it around to the end + let needed_elem = s:yr_count + endif + + return needed_elem + +endfunction + + +" Lets Vim natively perform the operation and then stores what +" was yanked (or deleted) into the yankring. +" Supports this for example - 5"ayy +" +" This is a legacy function now since the release of Vim 7.2 +" and the use of omaps with YankRing 5.0 and above. +" If Vim 7.1 has patch205, then the new omaps and the v:operator +" variable is used instead. +function! s:YRYankCount(...) range + + let user_register = s:YRRegister() + let v_count = v:count + + " Default yank command to the entire line + let op_code = 'yy' + if a:0 > 0 + " If no yank command has been supplied, assume it is + " a full line yank + let op_code = ((a:1 == '') ? op_code : a:1) + endif + + if op_code == '.' + if s:YRDoRepeat() == 1 + if s:yr_prev_op_code != '' + let op_code = s:yr_prev_op_code + let v_count = s:yr_prev_count + let user_register = s:yr_prev_reg + endif + else + " Set this flag so that YRRecord will + " ignore repeats + let s:yr_prev_repeating = 1 + exec "normal! ." + return + endif + else + let s:yr_prev_repeating = 0 + endif + + " Supports this for example - 5"ayy + " A delete operation will still place the items in the + " default registers as well as the named register + exec "normal! ". + \ ((v_count > 0)?(v_count):''). + \ (user_register=='"'?'':'"'.user_register). + \ op_code + + if user_register == '_' + " Black hole register, ignore recording the operation + return + endif + + call s:YRSetPrevOP(op_code, v_count, user_register, 'n') + + call YRRecord(user_register) +endfunction + + +" Handles ranges. There are visual ranges and command line ranges. +" Visual ranges are easy, since we pass through and let Vim deal +" with those directly. +" Command line ranges means we must yank the entire line, and not +" just a portion of it. +function! s:YRYankRange(do_delete_selection, ...) range + + let user_register = s:YRRegister() + let default_buffer = ((&clipboard=~'\')?'*':((&clipboard=~'\' && has('unnamedplus'))?'+':'"')) + + " Default command mode to normal mode 'n' + let cmd_mode = 'n' + if a:0 > 0 + " Change to visual mode, if command executed via + " a visual map + let cmd_mode = ((a:1 == 'v') ? 'v' : 'n') + endif + + if a:do_delete_selection == 1 + " Save register 0 + " Register 0 should only be changed by yank operations + " if we are deleting text, this could inadvertently + " update this register. + let zero_register = [0, getreg(0), getregtype('0')] + endif + + if cmd_mode == 'v' + " We are yanking either an entire line, or a range + " We want to yank the text first (even in a delete) since + " the rules around which registers get updated are a bit + " complicated. For deletes, it depends on how large + " the delete is for which registers get updated. + exec "normal! gv". + \ (user_register==default_buffer?'':'"'.user_register). + \ 'y' + if a:do_delete_selection == 1 + exec "normal! gv". + \ (user_register==default_buffer?'':'"'.user_register). + \ 'd' + endif + else + " In normal mode, always yank the complete line, since this + " command is for a range. YRYankCount is used for parts + " of a single line + if a:do_delete_selection == 1 + exec a:firstline . ',' . a:lastline . 'delete '.user_register + else + exec a:firstline . ',' . a:lastline . 'yank ' . user_register + endif + endif + + if a:do_delete_selection == 1 + " Restore register zero + call call('setreg', zero_register) + endif + + if user_register == '_' + " Black hole register, ignore + return + endif + + call s:YRSetPrevOP('', '', user_register, 'n') + call YRRecord(user_register) +endfunction + + +" Paste from either the yankring or from a specified register +" Optionally a count can be provided, so paste the same value 10 times +function! s:YRPaste(replace_last_paste_selection, nextvalue, direction, ...) + if g:yankring_manual_clipboard_check == 1 + call s:YRCheckClipboard() + endif + + " Disabling the yankring removes the default maps. + " But there are some maps the user can create on their own, and + " these would most likely call this function. So place an extra + " check and display a message. + if g:yankring_enabled == 0 + call s:YRWarningMsg( + \ 'YR: The yankring is currently disabled, use YRToggle.' + \ ) + return + endif + + let user_register = s:YRRegister() + let default_register = ((&clipboard=~'\')?'*':((&clipboard=~'\' && has('unnamedplus'))?'+':'"')) + let default_register = '"' + let clipboard_default = matchstr( &clipboard, '\' ) + if has('unnamedplus') && clipboard_default == '\' && (v:register == '' || v:register == '"') + let default_register = '+' + endif + if clipboard_default =~ '\' && (v:register == '' || v:register == '"') + let default_register = '*' + endif + let v_count = v:count + + " Default command mode to normal mode 'n' + let cmd_mode = 'n' + if a:0 > 0 + " Change to visual mode, if command executed via + " a visual map + let cmd_mode = ((a:1 == 'v') ? 'v' : 'n') + endif + + if a:replace_last_paste_selection == 1 + " Replacing the previous put + let start = line("'[") + let end = line("']") + + if start != line('.') + call s:YRWarningMsg( 'YR: You must paste text first, before you can replace' ) + return + endif + + if start == 0 || end == 0 + return + endif + + " If a count was provided (ie 5), multiply the + " nextvalue accordingly and position the next paste index + " let which_elem = a:nextvalue * ((v_count > 0)?(v_count):1) * -1 + let which_elem = matchstr(a:nextvalue, '-\?\d\+') * ((v_count > 0)?(v_count):1) * -1 + let s:yr_last_paste_idx = s:YRGetNextElem( + \ s:yr_last_paste_idx, which_elem + \ ) + + let save_reg = getreg(default_register) + let save_reg_type = getregtype(default_register) + call setreg( default_register + \ , s:YRGetValElemNbr((s:yr_last_paste_idx-1),'v') + \ , s:YRGetValElemNbr((s:yr_last_paste_idx-1),'t') + \ ) + + " First undo the previous paste + exec "normal! u" + " Check if the visual selection should be reselected + " Next paste the correct item from the ring + " This is done as separate statements since it appeared that if + " there was nothing to undo, the paste never happened. + exec "normal! ". + \ ((s:yr_prev_vis_mode==0) ? "" : "gv"). + \ '"'.default_register. + \ s:yr_paste_dir + call setreg(default_register, save_reg, save_reg_type) + call s:YRSetPrevOP('', '', '', 'n') + + return + endif + + " User has decided to bypass the yankring and specify a specific + " register + if user_register != default_register + " if a:replace_last_paste_selection == 1 + " call s:YRWarningMsg( 'YR: A register cannot be specified in replace mode' ) + " return + " endif + + " Check for the expression register, in this special case + " we must copy it's evaluation into the default buffer and paste + if user_register == '=' + " Save the default register since Vim will only + " allow the expression register to be pasted once + " and will revert back to the default buffer + let save_default_reg = @" + call setreg(default_register, eval(histget('=', -1)) ) + else + let user_register = '"'.user_register + endif + exec "normal! ". + \ ((cmd_mode=='n') ? "" : "gv"). + \ ((v_count > 0)?(v_count):''). + \ ((user_register=='=')?'':user_register). + \ a:direction + if user_register == '=' + let @" = save_default_reg + endif + " In this case, we have bypassed the yankring + " If the user hits next or previous we want the + " next item pasted to be the top of the yankring. + let s:yr_last_paste_idx = 1 + + let s:yr_paste_dir = a:direction + let s:yr_prev_vis_mode = ((cmd_mode=='n') ? 0 : 1) + return + endif + + " Try to second guess the user to make these mappings less intrusive. + " If the user hits paste, compare the contents of the paste register + " to the current entry in the yankring. If they are different, lets + " assume the user wants the contents of the paste register. + " The user could have: + " let @" = 'test string' + " would not be in the yankring as no mapping triggered this action. + if a:replace_last_paste_selection != 1 + " Only check the default buffer is the user wants us to. + " This was necessary prior to version 4.0 since we did not + " capture as many items as 4.0 and above does. (A. Budden) + if g:yankring_paste_check_default_register == 1 + if ( default_register == '"' && getreg(default_register) != s:yr_prev_reg_unnamed ) + " There are only a couple of scenarios where this would happen + " 1. set clipboard = unnamed[plus] + " The user performs an action which changes the + " unnamed register (i.e. x - delete character) + " 2. Any type of direct manipulation of the registers + " let @" = 'something' + " 3. Something changed the system clipboard outside of Vim + if getreg('"') != s:yr_prev_reg_unnamed + let default_register = '"' + endif + + " The user has performed a yank / delete operation + " outside of the yankring maps. First, add this + " value to the yankring. + call YRRecord(default_register) + elseif ( default_register == '+' && + \ !empty(getreg(default_register)) && + \ getreg(default_register) != s:yr_prev_clipboard_plus + \ ) + + " The user has performed a yank / delete operation + " outside of the yankring maps. First, add this + " value to the yankring. + call YRRecord(default_register) + elseif ( default_register == '*' && + \ !empty(getreg(default_register)) && + \ getreg(default_register) != s:yr_prev_clipboard_star + \ ) + + " The user has performed a yank / delete operation + " outside of the yankring maps. First, add this + " value to the yankring. + call YRRecord(default_register) + endif + endif + + exec "normal! ". + \ ((cmd_mode=='n') ? "" : "gv"). + \ ((v_count > 0)?(v_count):''). + \ '"'.default_register. + \ a:direction + let s:yr_paste_dir = a:direction + let s:yr_prev_vis_mode = ((cmd_mode=='n') ? 0 : 1) + return + endif + + " if s:yr_count > 0 || ( + " \ default_register != '"' && + " \ empty(getreg(default_register)) + " \ ) + " " Nothing to paste + " return + " endif + + " User hit p or P + " Supports this for example - 5"ayy + " And restores the current register + let save_reg = getreg(default_register) + let save_reg_type = getregtype(default_register) + let s:yr_last_paste_idx = 1 + call setreg(default_register + \ , s:YRGetValElemNbr(0,'v') + \ , s:YRGetValElemNbr(0,'t') + \ ) + exec "normal! ". + \ ((cmd_mode=='n') ? "" : "gv"). + \ ((v_count > 0)?(v_count):''). + \ '"'.default_register. + \ a:direction + call setreg(default_register, save_reg, save_reg_type) + call s:YRSetPrevOP( + \ a:direction + \ , v_count + \ , default_register + \ , 'n' + \ ) + let s:yr_paste_dir = a:direction + let s:yr_prev_vis_mode = ((cmd_mode=='n') ? 0 : 1) + +endfunction + + +" Handle any omaps +function! YRMapsExpression(sid, motion, ...) + let cmds = a:motion + " echomsg "YRMapsE:".localtime() + " echomsg "YRMapsE 1:".cmds.":".v:operator.":".s:yr_maps_created_zap + + if (a:motion =~ '\.' && s:yr_remove_omap_dot == 1) || a:motion =~ '@' + " If we are repeating a series of commands we must + " unmap the _zap_ keys so that the user is not + " prompted when a command is replayed. + " These maps must be re-instated in YRRecord3() + " after the action of the replay is completed. + call s:YRMapsDelete('remove_only_zap_keys') + endif + + " Check if we are in operator-pending mode + if a:motion =~ '\('.substitute(g:yankring_zap_keys, ' ', '\\|', 'g').'\)' + if a:motion =~ '\(/\|?\)' + let zapto = (a:0==0 ? "" : input("YR:Enter string:")) + if zapto != "" + let zapto = zapto . "\" + else + let zapto = "\" + endif + else + let zapto = (a:0==0 ? "" : s:YRGetChar()) + endif + + if zapto == "\" + " Abort if the user hits Control C + call s:YRWarningMsg( "YR:Aborting command:".v:operator.a:motion ) + return "\" + endif + + let cmds = cmds . zapto + endif + + " There are a variety of commands which do not change the + " registers, so these operators should be ignored when + " determining which operations to record + " Simple example is '=' which simply formats the + " the selected text. + if ' \('.escape(join(split(g:yankring_ignore_operator), '\|'), '/.*~$^[]' ).'\) ' !~ escape(v:operator, '/.*~$^[]') + " Check if we are performing an action that will + " take us into insert mode + if '[cCsS]' !~ escape(v:operator, '/.*~$^[]') && a:motion !~ '@' + " if '[cCsS]' !~ escape(v:operator, '/.*~$^[]') + " If we have not entered insert mode, feed the call + " to record the current change when the function ends. + " This is necessary since omaps do not update registers + " until the function completes. + " The InsertLeave event will handle the motions + " that place us in insert mode and record the + " changes when insert mode ends. + " let cmds .= a:sid. "yrrecord ".a:motion + let cmds .= a:sid. "yrrecord" + endif + endif + + " This will not work since we are already executing an expression + " if a:motion =~ '@' + " let cmds = 'normal! ' . cmds + " endif + + " YRRecord3() will use this value to determine what operation + " the user just initiated. + let s:yr_last_motion = cmds + + " echomsg "YRMapsE 5:".a:motion.":'".cmds."':".s:yr_maps_created_zap + return cmds + +endfunction + + +" Handle macros (@). +function! s:YRMapsMacro(bang, ...) + " If we are repeating a series of commands we must + " unmap the _zap_ keys so that the user is not + " prompted when a command is replayed. + " These maps must be re-instated in YRRecord3() + " after the action of the replay is completed. + call s:YRMapsDelete('remove_only_zap_keys') + + " Greg Sexton indicated the use of nr2char() removes + " a "Press ENTER ..." prompt when executing a macro. + " let zapto = nr2char(getchar()) + " let zapto = (a:0==0 ? "" : s:YRGetChar()) + let zapto = s:YRGetChar() + + if zapto == "\" + " Abort if the user hits Control C + call s:YRWarningMsg( "YR:Aborting macro" ) + return "" + endif + + if zapto !~ '\(\w\|@\|:\)' + " Abort if the user does not specify a register + call s:YRWarningMsg( "YR:No register specified, aborting macro" ) + return "" + endif + + let v_count = v:count + " If no count was specified it will have a value of 0 + " so set it to at least 1 + let v_count = ((v_count > 0)?(v_count):'') + + " let range = '' + " if a:firstline != a:lastline + " let rannge = a:firstline.','.a:lastline + " endif + + " let cmd = range."normal! ".v_count.'@'.zapto + let cmd = "normal! ".v_count.'@'.zapto + " DEBUG + " echomsg cmd + exec cmd + + call s:YRMapsCreate('add_only_zap_keys') +endfunction + + +" Create the default maps +function! s:YRMapsCreate(...) + " 7.1.patch205 introduces the v:operator function which was + " essential to gain the omap support. + if s:yr_has_voperator == 1 + let s:yr_remove_omap_dot = 1 + for key in split(g:yankring_zap_keys) + try + if key != '@' + exec 'omap ' key 'YRMapsExpression("", "'. key. '", 1)' + endif + catch + endtry + endfor + endif + + " silent! nmap @ YRMapsExpression("", "@", "1") + silent! nmap @ :YRMapsMacro + + let s:yr_maps_created_zap = 1 + + if a:0 > 0 + " We have only removed the _zap_ keys temporarily + " so abandon further changes. + return + endif + + " 7.1.patch205 introduces the v:operator function which was essential + " to gain the omap support. + if s:yr_has_voperator == 1 + let s:yr_remove_omap_dot = 1 + " Set option to add and remove _zap_ keys when + " repeating commands + let o_maps = split(g:yankring_o_keys) + " Loop through and prompt the user for all buffer connection parameters. + for key in o_maps + exec 'omap ' key 'YRMapsExpression("", "'. escape(key,'\"'). '")' + endfor + endif + + " Iterate through a space separated list of mappings and create + " calls to the YRYankCount function + let n_maps = split(g:yankring_n_keys) + " Loop through and prompt the user for all buffer connection parameters. + for key in n_maps + " exec 'nnoremap '.key." :YRYankCount '".key."'" + " exec 'nnoremap '.key." :YRYankCount '".key."'" + " Andy Wokula's suggestion + exec 'nmap' key key."yrrecord" + endfor + + if g:yankring_map_dot == 1 + if s:yr_has_voperator == 1 + nmap . YRMapsExpression("", ".") + else + nnoremap . :YRYankCount '.' + endif + endif + + if g:yankring_v_key != '' + exec 'xnoremap '.g:yankring_v_key." :YRYankRange 'v'" + endif + if g:yankring_del_v_key != '' + for v_map in split(g:yankring_del_v_key) + if !empty(v_map) + try + exec 'xnoremap '.v_map." :YRDeleteRange 'v'" + catch + endtry + endif + endfor + endif + if g:yankring_paste_n_bkey != '' + exec 'nnoremap '.g:yankring_paste_n_bkey." :YRPaste 'P'" + if g:yankring_paste_using_g == 1 + exec 'nnoremap g'.g:yankring_paste_n_bkey." :YRPaste 'gP'" + endif + endif + if g:yankring_paste_n_akey != '' + exec 'nnoremap '.g:yankring_paste_n_akey." :YRPaste 'p'" + if g:yankring_paste_using_g == 1 + exec 'nnoremap g'.g:yankring_paste_n_akey." :YRPaste 'gp'" + endif + endif + if g:yankring_paste_v_bkey != '' + exec 'xnoremap '.g:yankring_paste_v_bkey." :YRPaste 'P', 'v'" + endif + if g:yankring_paste_v_akey != '' + exec 'xnoremap '.g:yankring_paste_v_akey." :YRPaste 'p', 'v'" + endif + if g:yankring_replace_n_pkey != '' + exec 'nnoremap '.g:yankring_replace_n_pkey." :YRReplace '-1', P" + endif + if g:yankring_replace_n_nkey != '' + exec 'nnoremap '.g:yankring_replace_n_nkey." :YRReplace '1', p" + endif + + let g:yankring_enabled = 1 + let s:yr_maps_created = 1 + + if exists('*YRRunAfterMaps') + " This will allow you to override the default maps if necessary + call YRRunAfterMaps() + endif +endfunction + + +" Create the default maps +function! s:YRMapsDelete(...) + + let o_maps = split(g:yankring_zap_keys) + for key in o_maps + try + " Why not remove the @ map? + if key != '@' + silent! exec 'ounmap' key + endif + catch + endtry + endfor + + let s:yr_maps_created_zap = 0 + + if a:0 > 0 + " We have only removed the _zap_ keys temporarily + " so abandon further changes. + return + endif + + " Iterate through a space separated list of mappings and create + " calls to an appropriate YankRing function + let n_maps = split(g:yankring_n_keys) + " Loop through and prompt the user for all buffer connection parameters. + for key in n_maps + try + silent! exec 'nunmap' key + catch + endtry + endfor + + let o_maps = split(g:yankring_o_keys) + for key in o_maps + try + silent! exec 'ounmap' key + catch + endtry + endfor + + if g:yankring_map_dot == 1 + silent! exec "nunmap ." + endif + if g:yankring_v_key != '' + silent! exec 'vunmap '.g:yankring_v_key + endif + if g:yankring_del_v_key != '' + for v_map in split(g:yankring_del_v_key) + if !empty(v_map) + try + silent! exec 'vunmap '.v_map + catch + endtry + endif + endfor + endif + if g:yankring_paste_n_bkey != '' + silent! exec 'nunmap '.g:yankring_paste_n_bkey + if g:yankring_paste_using_g == 1 + silent! exec 'nunmap g'.g:yankring_paste_n_bkey + endif + endif + if g:yankring_paste_n_akey != '' + silent! exec 'nunmap '.g:yankring_paste_n_akey + if g:yankring_paste_using_g == 1 + silent! exec 'nunmap g'.g:yankring_paste_n_akey + endif + endif + if g:yankring_paste_v_bkey != '' + silent! exec 'vunmap '.g:yankring_paste_v_bkey + endif + if g:yankring_paste_v_akey != '' + silent! exec 'vunmap '.g:yankring_paste_v_akey + endif + if g:yankring_replace_n_pkey != '' + silent! exec 'nunmap '.g:yankring_replace_n_pkey + endif + if g:yankring_replace_n_nkey != '' + silent! exec 'nunmap '.g:yankring_replace_n_nkey + endif + + silent! exec 'nunmap @' + + let g:yankring_enabled = 0 + let s:yr_maps_created = 0 +endfunction + +function! s:YRGetValElemNbr( position, type ) + let needed_elem = a:position + + " The List which contains the items in the yankring + " history is also ordered, most recent at the top + let elem = s:YRMRUGet('s:yr_history_list', needed_elem) + + if a:type == 't' + let elem = matchstr(elem, '^.*,\zs.*$') + else + let elem = matchstr(elem, '^.*\ze,.*$') + if s:yr_history_version == 'v1' + " Match three @@@ in a row as long as it is not + " preceded by a @@@ + " v1 + let elem = substitute(elem, s:yr_history_v1_nl_pat, "\n", 'g') + let elem = substitute(elem, '\\@', '@', 'g') + else + let elem = substitute(elem, s:yr_history_v2_nl_pat, "\n", 'g') + endif + endif + + return elem +endfunction + +function! s:YRMRUReset( mru_list ) + let {a:mru_list} = [] + + return 1 +endfunction + +function! s:YRMRUSize( mru_list ) + return len({a:mru_list}) +endfunction + +function! s:YRMRUElemFormat( element, element_type ) + let elem = a:element + if g:yankring_max_element_length != 0 + let elem = strpart(a:element, 0, g:yankring_max_element_length) + if (g:yankring_warn_on_truncate > 0) + let bytes = len (a:element) - len(elem) + if (bytes > 0) + call s:YRWarningMsg("Yankring truncated its element by ". + \ bytes. + \ " bytes due to a g:yankring_max_element_length of ". + \ g:yankring_max_element_length + \ ) + endif + endif + endif + if s:yr_history_version == 'v1' + let elem = escape(elem, '@') + let elem = substitute(elem, "\n", s:yr_history_v1_nl, 'g') + else + let elem = substitute(elem, "\n", s:yr_history_v2_nl, 'g') + endif + " Append the regtype to the end so we have it available + let elem = elem.",".a:element_type + + return elem +endfunction + +function! s:YRMRUHas( mru_list, find_str ) + " This function will find a string and return the element # + let find_idx = index({a:mru_list}, a:find_str) + + return find_idx +endfunction + +function! s:YRMRUGet( mru_list, position ) + " This function will return the value of the item at a:position + " Find the value of one element + let value = get({a:mru_list}, a:position, -2) + + return value +endfunction + +function! s:YRMRUAdd( mru_list, element, element_type ) + " Only add new items if they do not already exist in the MRU. + " If the item is found, move it to the start of the MRU. + let found = -1 + " let elem = a:element + " if g:yankring_max_element_length != 0 + " let elem = strpart(a:element, 0, g:yankring_max_element_length) + " endif + " if s:yr_history_version == 'v1' + " let elem = escape(elem, '@') + " let elem = substitute(elem, "\n", s:yr_history_v1_nl, 'g') + " else + " let elem = substitute(elem, "\n", s:yr_history_v2_nl, 'g') + " endif + " " Append the regtype to the end so we have it available + " let elem = elem.",".a:element_type + + if strlen(a:element) < g:yankring_min_element_length + return 1 + endif + + let elem = s:YRMRUElemFormat(a:element, a:element_type) + + " Refresh the List + call s:YRHistoryRead() + + let found = s:YRMRUHas(a:mru_list, elem) + + " Special case for efficiency, if it is first item in the + " List, do nothing + if found != 0 + if found != -1 + " Remove found item since we will add it to the top + call remove({a:mru_list}, found) + endif + call insert({a:mru_list}, elem, 0) + let s:yr_count = len({a:mru_list}) + call s:YRHistorySave() + endif + + return 1 +endfunction + +function! s:YRMRUDel( mru_list, elem_nbr ) + if a:elem_nbr >= 0 && a:elem_nbr < s:yr_count + call remove({a:mru_list}, a:elem_nbr) + let s:yr_count = len({a:mru_list}) + call s:YRHistorySave() + endif + + return 1 +endfunction + +function! s:YRHistoryDelete() + let s:yr_history_list = [] + let s:yr_count = 0 + + if g:yankring_persist != 1 + return + endif + let yr_filename = s:yr_history_file_{s:yr_history_version} + + if filereadable(yr_filename) + let rc = delete(yr_filename) + if rc != 0 + call s:YRErrorMsg( + \ 'YRHistoryDelete: Unable to delete the yankring history file: '. + \ yr_filename + \ ) + endif + endif + + return 0 +endfunction + +function! s:YRHistoryRead() + if g:yankring_persist != 1 + return + endif + let refresh_needed = 1 + let yr_history_list = [] + let yr_filename = s:yr_history_file_{s:yr_history_version} + + if filereadable(yr_filename) + let last_upd = getftime(yr_filename) + + if s:yr_history_last_upd != 0 && last_upd <= s:yr_history_last_upd + let refresh_needed = 0 + endif + + if refresh_needed == 1 + let s:yr_history_list = readfile(yr_filename) + let s:yr_history_last_upd = last_upd + let s:yr_count = len(s:yr_history_list) + return + else + return + endif + else + if s:yr_history_version == 'v2' + " Check to see if an upgrade is required + " else, let the empty yr_history_list be returned. + if filereadable(s:yr_history_file_v1) + " Perform upgrade to v2 of the history file + call s:YRHistoryUpgrade('v1') + return + endif + endif + endif + + let s:yr_history_list = yr_history_list + call s:YRHistorySave() +endfunction + +function! s:YRHistorySave() + + if len(s:yr_history_list) > g:yankring_max_history + " Remove items which exceed the max # specified + call remove(s:yr_history_list, g:yankring_max_history, (len(s:yr_history_list)-1)) + let s:yr_count = len(s:yr_history_list) + endif + + if g:yankring_persist != 1 + return + endif + + let yr_filename = s:yr_history_file_{s:yr_history_version} + let rc = writefile(s:yr_history_list, yr_filename) + + if rc == 0 + let s:yr_history_last_upd = getftime(yr_filename) + else + call s:YRErrorMsg( + \ 'YRHistorySave: Unable to save yankring history file: '. + \ yr_filename + \ ) + endif +endfunction + +function! s:YRHistoryUpgrade(version) + if a:version == 'v1' + if filereadable(s:yr_history_file_v1) + let v1_list = readfile(s:yr_history_file_v1) + let v2_list = [] + for elem in v1_list + " Restore from version 1 + let elem = substitute(elem, s:yr_history_v1_nl_pat, "\n", 'g') + let elem = substitute(elem, '\\@', '@', 'g') + " Encode to version 2 + let elem = substitute(elem, "\n", s:yr_history_v2_nl, 'g') + call add(v2_list, elem) + endfor + let s:yr_history_list = v2_list + call s:YRHistorySave() + call s:YRWarningMsg( + \ "YR:History file:". + \ s:yr_history_file_v1. + \ ' has been upgraded.' + \ ) + endif + endif +endfunction + +" YRWindowUpdate +" Checks if the yankring window is already open. +" If it is, it will refresh it. +function! s:YRWindowUpdate() + let orig_win_bufnr = bufwinnr('%') + + " Switch to the yankring buffer + " only if it is already visible + if bufwinnr(s:yr_buffer_id) != -1 + call s:YRShow(0) + " Switch back to the original buffer + exec orig_win_bufnr . "wincmd w" + endif +endfunction + +" YRWindowStatus +" Displays a brief command list and option settings. +" It also will toggle the Help text. +function! s:YRWindowStatus(show_help) + let full_help = 0 + let orig_win_bufnr = bufwinnr('%') + let yr_win_bufnr = bufwinnr(s:yr_buffer_id) + + if yr_win_bufnr == -1 + " Do not update the window status since the + " yankring is not currently displayed. + return "" + endif + " Switch to the yankring buffer + if orig_win_bufnr != yr_win_bufnr + " If the buffer is visible, switch to it + exec yr_win_bufnr . "wincmd w" + endif + + let msg = 'AutoClose='.g:yankring_window_auto_close. + \ ';ClipboardMonitor='.g:yankring_clipboard_monitor. + \ ';Inserts='.g:yankring_record_insert. + \ ';Cmds:,[g]p,[g]P,1-9,d,r,s,a,c,i,u,R,q,;Help=?'. + \ (s:yr_search==""?"":';SearchRegEx='.s:yr_search) + + if s:yr_has_voperator == 0 + let msg = msg . "\nYankRing has limited functionality without Vim 7.2 or higher" + endif + + " Toggle help by checking the first line of the buffer + if a:show_help == 1 && getline(1) !~ 'selection' + let full_help = 1 + let msg = + \ '" : [p]aste selection'."\n". + \ '" double-click : [p]aste selection'."\n". + \ '" [g]p : [g][p]aste selection'."\n". + \ '" [g]P : [g][P]aste selection'."\n". + \ '" 1-9 : Paste # entry from the YankRing (shortcut for speed)'."\n". + \ '" d : [d]elete item from the YankRing'."\n". + \ '" r : [p]aste selection in reverse order'."\n". + \ '" s : [s]earch the yankring for text'."\n". + \ '" u : [u]pdate display show YankRing'."\n". + \ '" R : [R]egisters display'."\n". + \ '" a : toggle [a]utoclose setting'."\n". + \ '" c : toggle [c]lipboard monitor setting'."\n". + \ '" i : toggle [i]nsert recording'."\n". + \ '" q : [q]uit / close the yankring window'."\n". + \ '" ? : Remove help text'."\n". + \ '" : toggles the width of the window'."\n". + \ '" AutoClose : See yankring.txt, yankring_window_auto_close'."\n". + \ '" ClipboardMonitor: See yankring.txt, yankring_clipboard_monitor'."\n". + \ '" Inserts : See yankring.txt, yankring_record_insert'."\n". + \ '" YankRing Version: '.g:loaded_yankring."\n". + \ msg + endif + + let saveMod = &modifiable + + " Go to the top of the buffer and remove any previous status + " Use the blackhole register so it does not affect the yankring + setlocal modifiable + exec 0 + silent! exec 'norm! "_d/^---'."\n" + call histdel("search", -1) + + silent! 0put =msg + + " Erase it's contents to the blackhole + silent! exec '%g/^\s*$/delete _' + call histdel("search", -1) + + call cursor(1,1) + if full_help == 0 + call search('^\d', 'W') + endif + + let &modifiable = saveMod + + if orig_win_bufnr != s:yr_buffer_id + exec orig_win_bufnr . "wincmd w" + endif +endfunction + +" YRWindowOpen +" Display the Most Recently Used file list in a temporary window. +function! s:YRWindowOpen(results) + + " Setup the cpoptions properly for the maps to work + " and to not set the alternate buffer + let old_cpoptions = &cpoptions + set cpoptions&vim + set cpoptions-=a + set cpoptions-=A + + " Save the current buffer number. The yankring will switch back to + " this buffer when an action is taken. + let s:yr_buffer_last = bufnr('%') + let s:yr_buffer_last_winnr = winnr() + + if bufwinnr(s:yr_buffer_id) == -1 + if g:yankring_window_use_horiz == 1 + if g:yankring_window_use_bottom == 1 + let location = 'botright' + else + let location = 'topleft' + " Creating the new window will offset all other + " window numbers. Account for that so we switch + " back to the correct window. + let s:yr_buffer_last_winnr = s:yr_buffer_last_winnr + 1 + endif + let win_size = g:yankring_window_height + else + " Open a horizontally split window. Increase the window size, if + " needed, to accommodate the new window + if g:yankring_window_width && + \ &columns < (80 + g:yankring_window_width) + " Store the previous window size of the YankRing + let s:yr_winsize_chgd = &columns + " One extra column is needed to include the vertical split + let &columns = &columns + g:yankring_window_width + 1 + else + let s:yr_winsize_chgd = 0 + endif + + if g:yankring_window_use_right == 1 + " Open the window at the rightmost place + let location = 'botright vertical' + else + " Open the window at the leftmost place + let location = 'topleft vertical' + " Creating the new window will offset all other + " window numbers. Account for that so we switch + " back to the correct window. + let s:yr_buffer_last_winnr = s:yr_buffer_last_winnr + 1 + endif + let win_size = g:yankring_window_width + endif + + " Special consideration was involved with these sequence + " of commands. + " First, split the current buffer. + " Second, edit a new file. + " Third record the buffer number. + " If a different sequence is followed when the yankring + " buffer is closed, Vim's alternate buffer is the yanking + " instead of the original buffer before the yankring + " was shown. + let cmd_mod = '' + if v:version >= 700 + let cmd_mod = 'keepalt ' + endif + exec 'silent! ' . cmd_mod . location . ' ' . win_size . 'split ' + + " Using :e and hide prevents the alternate buffer + " from being changed. + exec ":e " . escape(g:yankring_buffer_name, ' ') + " Save buffer id + let s:yr_buffer_id = bufnr('%') + 0 + else + " If the buffer is visible, switch to it + exec bufwinnr(s:yr_buffer_id) . "wincmd w" + endif + + " Perform a double check to ensure we have entered the correct + " buffer since we don't want to do the %d_ in the wrong buffer! + if (bufnr('%') + 0) != s:yr_buffer_id + call s:YRWarningMsg( + \ "YR:Failed to change to the yankring buffer, please contact author id:". + \ s:yr_buffer_id. + \ ' last:'.s:yr_buffer_last + \ ) + return -1 + endif + + " Mark the buffer as scratch + setlocal buftype=nofile + setlocal bufhidden=hide + setlocal noswapfile + setlocal nowrap + setlocal nonumber + setlocal nobuflisted + setlocal noreadonly + setlocal nospell + setlocal modifiable + if v:version >= 703 + setlocal norelativenumber + endif + + " set up syntax highlighting + syn match yankringTitle #^--- YankRing ---$#hs=s+4,he=e-4 + syn match yankringHeaders #^Elem Content$# + syn match yankringItemNumber #^\d\+# + + syn match yankringKey #^AutoClose.*#hs=e-6 + syn match yankringKey #^AutoClose.*\[g\]p#hs=e-3 contains=yankringKey + syn match yankringKey #^AutoClose.*\[g\]P#hs=e-3 contains=yankringKey + syn match yankringKey #^AutoClose.*,d,#hs=e-1,he=e-1 contains=yankringKey + syn match yankringKey #^AutoClose.*,r,#hs=e-1,he=e-1 contains=yankringKey + syn match yankringKey #^AutoClose.*,s,#hs=e-1,he=e-1 contains=yankringKey + syn match yankringKey #^AutoClose.*,a,#hs=e-1,he=e-1 contains=yankringKey + syn match yankringKey #^AutoClose.*,c,#hs=e-1,he=e-1 contains=yankringKey + syn match yankringKey #^AutoClose.*,i,#hs=e-1,he=e-1 contains=yankringKey + syn match yankringKey #^AutoClose.*,u,#hs=e-1,he=e-1 contains=yankringKey + syn match yankringKey #^AutoClose.*,R,#hs=e-1,he=e-1 contains=yankringKey + syn match yankringKey #^AutoClose.*,q,#hs=e-1,he=e-1 contains=yankringKey + syn match yankringKey #^AutoClose.*#hs=e-6 contains=yankringKey + syn match yankringKey #^AutoClose.*?$#hs=e contains=yankringKey + + syn match yankringKey #^".*:#hs=s+1,he=e-1 + syn match yankringHelp #^".*$# contains=yankringKey + + hi link yankringTitle directory + hi link yankringHeaders keyword + hi link yankringItemNumber constant + hi link yankringKey identifier + hi link yankringHelp string + + " Clear all existing maps for this buffer + " We should do this for all maps, but I am not sure how to do + " this for this buffer/window only without affecting all the + " other buffers. + mapclear + " Create a mapping to act upon the yankring + nnoremap <2-LeftMouse> :call YRWindowActionN('p' , 'n') + nnoremap :call YRWindowActionN('p' , 'n') + xnoremap :call YRWindowAction ('p' , 'v') + nnoremap p :call YRWindowActionN('p' , 'n') + nnoremap [p :call YRWindowActionN('[p' , 'n') + nnoremap ]p :call YRWindowActionN(']p' , 'n') + xnoremap p :call YRWindowAction ('p' , 'v') + xnoremap [p :call YRWindowAction ('[p' , 'v') + xnoremap ]p :call YRWindowAction (']p' , 'v') + nnoremap P :call YRWindowActionN('P' , 'n') + nnoremap [P :call YRWindowActionN('[P' , 'n') + nnoremap ]P :call YRWindowActionN(']P' , 'n') + xnoremap P :call YRWindowAction ('P' , 'v') + xnoremap [P :call YRWindowAction ('[P' , 'v') + xnoremap ]P :call YRWindowAction (']P' , 'v') + nnoremap gp :call YRWindowActionN('gp' , 'n') + xnoremap gp :call YRWindowAction ('gp' , 'v') + nnoremap gP :call YRWindowActionN('gP' , 'n') + xnoremap gP :call YRWindowAction ('gP' , 'v') + nnoremap d :call YRWindowActionN('d' , 'n') + xnoremap d :call YRWindowAction ('d' , 'v') + xnoremap r :call YRWindowAction ('r' , 'v') + nnoremap s :call YRWindowAction ('s' , 'n') + nnoremap a :call YRWindowAction ('a' , 'n') + nnoremap c :call YRWindowAction ('c' , 'n') + nnoremap i :call YRWindowAction ('i' , 'n') + nnoremap ? :call YRWindowAction ('?' , 'n') + nnoremap u :call YRWindowAction ('u' , 'n') + nnoremap q :call YRWindowAction ('q' , 'n') + nnoremap R :call YRWindowAction ('R' , 'n') + nnoremap 1 :call YRWindowAction ('q' ,'n'):call YRGetElem(1) + nnoremap 2 :call YRWindowAction ('q' ,'n'):call YRGetElem(2) + nnoremap 3 :call YRWindowAction ('q' ,'n'):call YRGetElem(3) + nnoremap 4 :call YRWindowAction ('q' ,'n'):call YRGetElem(4) + nnoremap 5 :call YRWindowAction ('q' ,'n'):call YRGetElem(5) + nnoremap 6 :call YRWindowAction ('q' ,'n'):call YRGetElem(6) + nnoremap 7 :call YRWindowAction ('q' ,'n'):call YRGetElem(7) + nnoremap 8 :call YRWindowAction ('q' ,'n'):call YRGetElem(8) + nnoremap 9 :call YRWindowAction ('q' ,'n'):call YRGetElem(9) + nnoremap \|:silent exec 'vertical resize '. + \ ( + \ g:yankring_window_use_horiz!=1 && winwidth('.') > g:yankring_window_width + \ ?(g:yankring_window_width) + \ :(winwidth('.') + g:yankring_window_increment) + \ ) + + " Erase it's contents to the blackhole + silent! exec '%delete _' + + " Display the status line / help + call s:YRWindowStatus(0) + exec 'normal! G' + + " Display the contents of the yankring + silent! put =a:results + + if getline('$') == '' + " Erase last blank line + silent! exec '$delete _' + endif + + " Move the cursor to the first line with an element + exec 0 + call search('^\d','W') + + setlocal nomodifiable + " + " Restore the previous cpoptions settings + let &cpoptions = old_cpoptions + +endfunction + +function! s:YRWindowActionN(op, cmd_mode) + let v_count = v:count + " If no count was specified it will have a value of 0 + " so set it to at least 1 + let v_count = ((v_count > 0)?(v_count):1) + + if v_count > 1 + if !exists("b:yankring_show_range_error") + let b:yankring_show_range_error = v_count + else + let b:yankring_show_range_error = b:yankring_show_range_error - 1 + endif + + if b:yankring_show_range_error == 1 + call s:YRWarningMsg("YR:Use visual mode if you need to specify a count") + unlet b:yankring_show_range_error + endif + return + endif + + call s:YRWindowAction(a:op, a:cmd_mode) + let v_count = v_count - 1 + + if g:yankring_window_auto_close == 1 && v_count == 0 && a:op != 'd' + " If autoclose is set close the window unless + " you are removing items from the YankRing + exec 'bdelete '.s:yr_buffer_id + return "" + endif + + return "" +endfunction + +function! s:YRWindowAction(op, cmd_mode) range + let default_buffer = ((&clipboard=~'\')?'*':((&clipboard=~'\' && has('unnamedplus'))?'+':'"')) + let opcode = a:op + let lines = [] + let v_count = v:count + let cmd_mode = a:cmd_mode + let firstline = a:firstline + let lastline = a:lastline + + if a:lastline < a:firstline + let firstline = a:lastline + let lastline = a:firstline + endif + + if cmd_mode == 'n' + let v_count = 1 + " If a count was provided (5p), we want to repeat the paste + " 5 times, but this also alters the a:firstline and a:lastline + " ranges, which while in normal mode we do not want + let lastline = firstline + endif + " If no count was specified it will have a value of 0 + " so set it to at least 1 + let v_count = ((v_count > 0)?(v_count):1) + + if '\<[drP]\>' =~# opcode + " Reverse the order of the lines to act on + let begin = lastline + while begin >= firstline + call add(lines, getline(begin)) + let begin = begin - 1 + endwhile + else + " Process the selected items in order + let begin = firstline + while begin <= lastline + call add(lines, getline(begin)) + let begin = begin + 1 + endwhile + endif + + if opcode ==# 'q' + " Close the yankring window + if s:yr_winsize_chgd > 0 + " Adjust the Vim window width back to the width + " it was before we showed the yankring window + let &columns = s:yr_winsize_chgd + " Reset the indicator the window size was changed + let s:yr_winsize_chgd = 0 + endif + + " Hide the YankRing window + hide + + if bufwinnr(s:yr_buffer_last) != -1 + " If the buffer is visible, switch to it + exec s:yr_buffer_last_winnr . "wincmd w" + endif + + return + elseif opcode ==# 's' + " Switch back to the original buffer + exec s:yr_buffer_last_winnr . "wincmd w" + + call s:YRSearch() + return + elseif opcode ==# 'u' + " Switch back to the original buffer + exec s:yr_buffer_last_winnr . "wincmd w" + + call s:YRShow(0) + return + elseif opcode ==# 'R' + " Switch back to the original buffer + exec s:yr_buffer_last_winnr . "wincmd w" + + call s:YRShow(0, 'R') + return + elseif opcode ==# 'a' + let l:curr_line = line(".") + " Toggle the auto close setting + let g:yankring_window_auto_close = + \ (g:yankring_window_auto_close == 1?0:1) + " Display the status line / help + call s:YRWindowStatus(0) + call cursor(l:curr_line,0) + return + elseif opcode ==# 'c' + let l:curr_line = line(".") + " Toggle the clipboard monitor setting + let g:yankring_clipboard_monitor = + \ (g:yankring_clipboard_monitor == 1?0:1) + " Display the status line / help + call s:YRWindowStatus(0) + call cursor(l:curr_line,0) + return + elseif opcode ==# 'i' + let l:curr_line = line(".") + " Toggle the auto close setting + let g:yankring_record_insert = + \ (g:yankring_record_insert == 1?0:1) + " Display the status line / help + call s:YRWindowStatus(0) + call cursor(l:curr_line,0) + return + elseif opcode ==# '?' + " Display the status line / help + call s:YRWindowStatus(1) + return + endif + + " Switch back to the original buffer + exec s:yr_buffer_last_winnr . "wincmd w" + + " Intentional case insensitive comparison + if opcode =~? 'p' + let cmd = 'YRGetElem ' + let parms = ", '".opcode."' " + elseif opcode ==? 'r' + let opcode = 'p' + let cmd = 'YRGetElem ' + let parms = ", 'p' " + elseif opcode ==# 'd' + let cmd = 'YRPop ' + let parms = "" + endif + + " Only execute this code if we are operating on elements + " within the yankring + if '[auq?]' !~# opcode + while v_count > 0 + " let iter = 0 + " let index = 0 + for line in lines + let elem = matchstr(line, '^\d\+') + if elem > 0 + if elem > 0 && elem <= s:yr_count + " if iter > 0 && opcode =~# 'p' + if opcode =~# 'p' + " Move to the end of the last pasted item + " only if pasting after (not above) + " '] + endif + exec cmd . elem . parms + " let iter += 1 + endif + endif + endfor + let v_count = v_count - 1 + endwhile + + if opcode ==# 'd' + call s:YRShow(0) + " Return the user to their last known position, assuming + " it is still available after the delete + if firstline < line("$") + call cursor(firstline,0) + else + call cursor(line("$"),0) + endif + return "" + endif + + if g:yankring_window_auto_close == 1 && cmd_mode == 'v' + exec 'bdelete '.s:yr_buffer_id + return "" + endif + + endif + + return "" + +endfunction + +function! s:YRWarningMsg(msg) + echohl WarningMsg + echomsg a:msg + echohl None +endfunction + +function! s:YRErrorMsg(msg) + echohl ErrorMsg + echomsg a:msg + echohl None +endfunction + +function! s:YRWinLeave() + " Track which window we are last in. We will use this information + " to determine where we need to paste any contents, or which + " buffer to return to. + + if s:yr_buffer_id < 0 + " The yankring window has never been activated + return + endif + + if winbufnr(winnr()) == s:yr_buffer_id + " Ignore leaving the yankring window + return + endif + + if bufwinnr(s:yr_buffer_id) != -1 + " YankRing window is visible, so save off the previous buffer ids + let s:yr_buffer_last_winnr = winnr() + let s:yr_buffer_last = winbufnr(s:yr_buffer_last_winnr) + " else + " let s:yr_buffer_last_winnr = -1 + " let s:yr_buffer_last = -1 + endif +endfunction + +function! s:YRFocusGained() + " FocusGained is not available in general by console vim. + " There are some terminal windows which support it though. + " This thread on vim_use covers some of it: + " http://groups.google.com/group/vim_use/browse_thread/thread/8dd3fb054ee922c6/59bee226473a9eea?lnk=gst&q=console+FocusGained#59bee226473a9eea + " http://groups.google.com/group/vim_dev/browse_thread/thread/ba58fb493a3cf4ba/dc1a22ba1e92579d?lnk=gst&q=terminal+FocusGained#dc1a22ba1e92579d + " Does not work: + " urxvt terminal + " Works: + " GTK2 GUI, on Fedora 11, both as gvim and as vim in a GNOME Terminal + " + " Simple test, create the following autocmd and gain and loose focus in + " the terminal: + " autocmd FocusLost * echomsg "focus lost" + " autocmd FocusGained * echomsg "focus gained" + call s:YRCheckClipboard() + + " If the yankring window is open, refresh it + call s:YRWindowUpdate() +endfunction + +function! s:YRCheckClipboard() + if g:yankring_clipboard_monitor == 1 + " If the clipboard has changed record it inside the yankring + " echomsg "YRCheckClipboard[".len(@*)."][".@*.']['.s:yr_prev_clipboard_star.']' + if has('unnamedplus') && &clipboard =~ '\' + if !empty(@+) && @+ != s:yr_prev_clipboard_plus + let elem = s:YRMRUElemFormat( + \ getreg('+') + \ , getregtype('+') + \ ) + let found = s:YRMRUHas('s:yr_history_list', elem) + + " Only add the item to the "top" of the ring if it is + " not in the ring already. + if found == -1 + call YRRecord3("+") + endif + let s:yr_prev_clipboard_plus = @+ + endif + else + if !empty(@*) && @* != s:yr_prev_clipboard_star + let elem = s:YRMRUElemFormat( + \ getreg('*') + \ , getregtype('*') + \ ) + let found = s:YRMRUHas('s:yr_history_list', elem) + + " Only add the item to the "top" of the ring if it is + " not in the ring already. + if found == -1 + call YRRecord3("*") + endif + let s:yr_prev_clipboard_star = @* + endif + endif + endif +endfunction + +function! s:YRInsertLeave() + " The YankRing uses omaps to execute the prescribed motion + " and then appends to the motion a call to a YankRing + " function to record the contents of the changed register. + " + " We cannot append a function call to the end of a motion + " that results in Insert mode. For example, any command + " like 'cw' enters insert mode. Appending a function call + " after the w, simply writes out the call as if the user + " typed it. + " + " Using the InsertLeave event, allows us to capture the + " contents of any changed register after it completes. + + call YRRecord(s:YRRegister()) + + " When performing a change (not a yank or delete) + " it is not possible to call yrrecord at the end + " of the command (or it's contents will be inserted + " into the buffer instead of executed). + " So, when using ".", we have to remove the _zap_ + " keys and then re-add them back again after we + " record the updates. + if s:yr_remove_omap_dot == 1 + call s:YRMapsCreate('add_only_zap_keys') + endif + + " Check if we should record inserted text + if g:yankring_record_insert == 1 + if !empty(@.) && @. != s:yr_prev_reg_insert + let elem = s:YRMRUElemFormat( + \ getreg('.') + \ , getregtype('.') + \ ) + let found = s:YRMRUHas('s:yr_history_list', elem) + + " Only add the item to the "top" of the ring if it is + " not in the ring already. + if found == -1 + call YRRecord3(".") + endif + let s:yr_prev_reg_insert = @. + endif + endif + +endfunction + +" Deleting autocommands first is a good idea especially if we want to reload +" the script without restarting vim. +" Call YRFocusGained to check if the clipboard has been updated +augroup YankRing + autocmd! + autocmd VimEnter * :if has('clipboard') | call YRFocusGained() | endif + autocmd WinLeave * :call YRWinLeave() + autocmd FocusGained * :if has('clipboard') | call YRFocusGained() | endif + autocmd InsertLeave * :call YRInsertLeave() + autocmd User YRSetNumberedReg :call YRSetNumberedReg() + " autocmd User YRSetNumberedReg :let i = 0 | while i <= 10 | if i > s:yr_count | break | endif | call setreg( (i), s:YRGetValElemNbr((i),'v'), s:YRGetValElemNbr((i),'t') ) | let i += 1 | endwhile +augroup END + + +" copy register +inoremap + + diff --git a/sources_non_forked/vim-coffee-script/test/test.litcoffee b/sources_non_forked/vim-coffee-script/test/test.litcoffee new file mode 100644 index 00000000..62b99b7d --- /dev/null +++ b/sources_non_forked/vim-coffee-script/test/test.litcoffee @@ -0,0 +1,117 @@ +The **Scope** class regulates lexical scoping within CoffeeScript. As you +generate code, you create a tree of scopes in the same shape as the nested +function bodies. Each scope knows about the variables declared within it, +and has a reference to its parent enclosing scope. In this way, we know which +variables are new and need to be declared with `var`, and which are shared +with external scopes. + +Import the helpers we plan to use. + + {extend, last} = require './helpers' + + exports.Scope = class Scope + +The `root` is the top-level **Scope** object for a given file. + + @root: null + +Initialize a scope with its parent, for lookups up the chain, +as well as a reference to the **Block** node it belongs to, which is +where it should declare its variables, and a reference to the function that +it belongs to. + + constructor: (@parent, @expressions, @method) -> + @variables = [{name: 'arguments', type: 'arguments'}] + @positions = {} + Scope.root = this unless @parent + +Adds a new variable or overrides an existing one. + + add: (name, type, immediate) -> + return @parent.add name, type, immediate if @shared and not immediate + if Object::hasOwnProperty.call @positions, name + @variables[@positions[name]].type = type + else + @positions[name] = @variables.push({name, type}) - 1 + +When `super` is called, we need to find the name of the current method we're +in, so that we know how to invoke the same method of the parent class. This +can get complicated if super is being called from an inner function. +`namedMethod` will walk up the scope tree until it either finds the first +function object that has a name filled in, or bottoms out. + + namedMethod: -> + return @method if @method.name or !@parent + @parent.namedMethod() + +Look up a variable name in lexical scope, and declare it if it does not +already exist. + + find: (name) -> + return yes if @check name + @add name, 'var' + no + +Reserve a variable name as originating from a function parameter for this +scope. No `var` required for internal references. + + parameter: (name) -> + return if @shared and @parent.check name, yes + @add name, 'param' + +Just check to see if a variable has already been declared, without reserving, +walks up to the root scope. + + check: (name) -> + !!(@type(name) or @parent?.check(name)) + +Generate a temporary variable name at the given index. + + temporary: (name, index) -> + if name.length > 1 + '_' + name + if index > 1 then index - 1 else '' + else + '_' + (index + parseInt name, 36).toString(36).replace /\d/g, 'a' + +Gets the type of a variable. + + type: (name) -> + return v.type for v in @variables when v.name is name + null + +If we need to store an intermediate result, find an available name for a +compiler-generated variable. `_var`, `_var2`, and so on... + + freeVariable: (name, reserve=true) -> + index = 0 + index++ while @check((temp = @temporary name, index)) + @add temp, 'var', yes if reserve + temp + +Ensure that an assignment is made at the top of this scope +(or at the top-level scope, if requested). + + assign: (name, value) -> + @add name, {value, assigned: yes}, yes + @hasAssignments = yes + +Does this scope have any declared variables? + + hasDeclarations: -> + !!@declaredVariables().length + +Return the list of variables first declared in this scope. + + declaredVariables: -> + realVars = [] + tempVars = [] + for v in @variables when v.type is 'var' + (if v.name.charAt(0) is '_' then tempVars else realVars).push v.name + realVars.sort().concat tempVars.sort() + +Return the list of assignments that are supposed to be made at the top +of this scope. + + assignedVariables: -> + "#{v.name} = #{v.type.value}" for v in @variables when v.type.assigned + diff --git a/sources_non_forked/vim-colorschemes b/sources_non_forked/vim-colorschemes deleted file mode 160000 index 28a989b2..00000000 --- a/sources_non_forked/vim-colorschemes +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 28a989b28457e38df620e4c7ab23e224aff70efe diff --git a/sources_non_forked/vim-commentary/plugin/commentary.vim b/sources_non_forked/vim-commentary/plugin/commentary.vim index 0bef7cc9..9aa0f324 100644 --- a/sources_non_forked/vim-commentary/plugin/commentary.vim +++ b/sources_non_forked/vim-commentary/plugin/commentary.vim @@ -15,8 +15,11 @@ endfunction function! s:strip_white_space(l,r,line) abort let [l, r] = [a:l, a:r] - if stridx(a:line,l) == -1 && stridx(a:line,l[0:-2]) == 0 && a:line[strlen(a:line)-strlen(r[1:]):-1] == r[1:] - return [l[0:-2], r[1:]] + if l[-1:] == ' ' && stridx(a:line,l) == -1 && stridx(a:line,l[0:-2]) == 0 + let l = l[:-2] + endif + if r[0] == ' ' && a:line[-strlen(r):] != r && a:line[1-strlen(r):] == r[1:] + let r = r[1:] endif return [l, r] endfunction @@ -28,11 +31,11 @@ function! s:go(type,...) abort let [lnum1, lnum2] = [line("'["), line("']")] endif - let [l_, r_] = s:surroundings() + let [l, r] = s:surroundings() let uncomment = 2 for lnum in range(lnum1,lnum2) let line = matchstr(getline(lnum),'\S.*\s\@Commentary') || maparg('gc','n') ==# '' nmap gc Commentary omap gc Commentary nmap gcc CommentaryLine - nmap cgc ChangeCommentary + if maparg('c','n') ==# '' + nmap cgc ChangeCommentary + endif nmap gcu CommentaryCommentary endif diff --git a/sources_non_forked/vim-flake8/README.mdown b/sources_non_forked/vim-flake8/README.mdown index 692baadf..00d49515 100644 --- a/sources_non_forked/vim-flake8/README.mdown +++ b/sources_non_forked/vim-flake8/README.mdown @@ -41,7 +41,7 @@ the `` key if so. For example, to remap it to `` instead, use: For flake8 configuration options please consult the following page: -https://flake8.readthedocs.org/en/latest/config.html +http://flake8.pycqa.org/en/latest/user/configuration.html To customize the location of your flake8 binary, set `g:flake8_cmd`: @@ -108,6 +108,20 @@ This plugin goes well together with the following plugin: and ``) +Max line lengths +---------------- + +One particular customization a lot of people like to make is relaxing the +maximum line length default. This is a config setting that should be set in +flake8 itself. (vim-flake8 "just" invokes it and deals with showing the output +in Vim's quickfix window.) + +To do so, put the following into your `~/.config/flake8` file: + + [flake8] + max-line-length = 120 + + History ------- 1.6: Deprecated configuring flake8 options through Vim settings. Instead, diff --git a/sources_non_forked/vim-fugitive/README.markdown b/sources_non_forked/vim-fugitive/README.markdown index 71b8bc47..fd15cc9a 100644 --- a/sources_non_forked/vim-fugitive/README.markdown +++ b/sources_non_forked/vim-fugitive/README.markdown @@ -20,7 +20,7 @@ changed, or `o` to open it in a split. When you're done, use `:Gedit` in the historic buffer to go back to the work tree version. `:Gmove` does a `git mv` on a file and simultaneously renames the -buffer. `:Gremove` does a `git rm` on a file and simultaneously deletes +buffer. `:Gdelete` does a `git rm` on a file and simultaneously deletes the buffer. Use `:Ggrep` to search the work tree (or any arbitrary commit) with @@ -35,9 +35,15 @@ and you never get any warnings about the file changing outside Vim. making it like `git add` when called from a work tree file and like `git checkout` when called from the index or a blob in history. -Use `:Gbrowse` to open the current file on GitHub, with optional line -range (try it in visual mode!). If your current repository isn't on -GitHub, `git instaweb` will be spun up instead. +Use `:Gbrowse` to open the current file on the web front-end of your favorite +hosting provider, with optional line range (try it in visual mode!). Built-in +support is provided for `git instaweb`, and plugins are available for popular +providers such as [GitHub][rhubarb.vim], [GitLab][fugitive-gitlab.vim], and +[Bitbucket][fubitive.vim]. + +[rhubarb.vim]: https://github.com/tpope/vim-rhubarb +[fugitive-gitlab.vim]: https://github.com/shumphrey/fugitive-gitlab.vim +[fubitive.vim]: https://github.com/tommcdo/vim-fubitive Add `%{fugitive#statusline()}` to `'statusline'` to get an indicator with the current branch in (surprise!) your statusline. @@ -60,7 +66,7 @@ If you don't have a preferred installation method, one option is to install and paste: cd ~/.vim/bundle - git clone git://github.com/tpope/vim-fugitive.git + git clone https://github.com/tpope/vim-fugitive.git vim -u NONE -c "helptags vim-fugitive/doc" -c q If your Vim version is below 7.2, I recommend also installing @@ -84,7 +90,7 @@ directory. Edit a file from the repository. `:Gbrowse` delegates to `git web--browse`, which is less than perfect when it comes to finding the right browser. You can tell it the correct -browser to use with `git config --global web.browser ...`. On OS X, for +browser to use with `git config --global web.browser ...`. On macOS, for example, you might want to set this to `open`. See `git web--browse --help` for details. diff --git a/sources_non_forked/vim-fugitive/doc/fugitive.txt b/sources_non_forked/vim-fugitive/doc/fugitive.txt index 51fc591f..b591803c 100644 --- a/sources_non_forked/vim-fugitive/doc/fugitive.txt +++ b/sources_non_forked/vim-fugitive/doc/fugitive.txt @@ -40,6 +40,7 @@ that are part of Git repositories). |:Gedit| - |:Git| add - |:Git| reset (staged files) + a Show alternative format cA |:Gcommit| --amend --reuse-message=HEAD ca |:Gcommit| --amend cc |:Gcommit| @@ -181,7 +182,9 @@ that are part of Git repositories). to the right or bottom, depending on 'diffopt' and the width of the window relative to 'textwidth'. Use |do| and |dp| and write to the index file to simulate - "git add --patch". + "git add --patch". For the three-way diff, there is + also d2o and d3o pulling the hunk to the middle from + the left or the right window, respectively. *fugitive-:Gsdiff* :Gsdiff [revision] Like |:Gdiff|, but always split horizontally. @@ -195,12 +198,15 @@ that are part of Git repositories). directory except when started with a /, in which case it is relative to the work tree. Add a ! to pass -f. - *fugitive-:Gremove* -:Gremove Wrapper around git-rm that deletes the buffer + *fugitive-:Gdelete* +:Gdelete Wrapper around git-rm that deletes the buffer afterward. When invoked in an index file, --cached is passed. Add a ! to pass -f and forcefully discard the buffer. + *fugitive-:Gremove* +:Gremove Like :Gdelete, but keep the (now empty) buffer around. + *fugitive-:Gblame* :Gblame [flags] Run git-blame on the file and open the results in a scroll bound vertical split. You can give any of @@ -232,9 +238,7 @@ that are part of Git repositories). Upstream providers can be added by installing an appropriate Vim plugin. For example, GitHub can be supported by installing rhubarb.vim, available at - . (Native - support for GitHub is currently included, but that is - slated to be removed.) + . The hosting provider is determined by looking at the remote for the current or specified branch and falls diff --git a/sources_non_forked/vim-fugitive/plugin/fugitive.vim b/sources_non_forked/vim-fugitive/plugin/fugitive.vim index 06d2e87b..13efb307 100644 --- a/sources_non_forked/vim-fugitive/plugin/fugitive.vim +++ b/sources_non_forked/vim-fugitive/plugin/fugitive.vim @@ -68,8 +68,21 @@ function! s:shellslash(path) abort endif endfunction +let s:executables = {} + +function! s:executable(binary) abort + if !has_key(s:executables, a:binary) + let s:executables[a:binary] = executable(a:binary) + endif + return s:executables[a:binary] +endfunction + let s:git_versions = {} +function! s:git_command() abort + return get(g:, 'fugitive_git_command', g:fugitive_git_executable) +endfunction + function! fugitive#git_version(...) abort if !has_key(s:git_versions, g:fugitive_git_executable) let s:git_versions[g:fugitive_git_executable] = matchstr(system(g:fugitive_git_executable.' --version'), "\\S\\+\n") @@ -127,7 +140,12 @@ function! fugitive#extract_git_dir(path) abort if s:shellslash(a:path) =~# '^fugitive://.*//' return matchstr(s:shellslash(a:path), '\C^fugitive://\zs.\{-\}\ze//') endif - let root = s:shellslash(simplify(fnamemodify(a:path, ':p:s?[\/]$??'))) + if isdirectory(a:path) + let path = fnamemodify(a:path, ':p:s?[\/]$??') + else + let path = fnamemodify(a:path, ':p:h:s?[\/]$??') + endif + let root = s:shellslash(resolve(path)) let previous = "" while root !=# previous if root =~# '\v^//%([^/]+/?)?$' @@ -179,6 +197,9 @@ function! fugitive#detect(path) abort let dir = fugitive#extract_git_dir(a:path) if dir !=# '' let b:git_dir = dir + if empty(fugitive#buffer().path()) + silent! exe haslocaldir() ? 'lcd .' : 'cd .' + endif endif endif if exists('b:git_dir') @@ -195,7 +216,7 @@ function! fugitive#detect(path) abort nnoremap y :call setreg(v:register, recall()) endif let buffer = fugitive#buffer() - if expand('%:p') =~# '//' + if expand('%:p') =~# '://' call buffer.setvar('&path', s:sub(buffer.getvar('&path'), '^\.%(,|$)', '')) endif if stridx(buffer.getvar('&tags'), escape(b:git_dir, ', ')) == -1 @@ -286,6 +307,9 @@ endfunction function! s:repo_tree(...) dict abort if self.dir() =~# '/\.git$' let dir = self.dir()[0:-6] + if dir !~# '/' + let dir .= '/' + endif else let dir = s:configured_tree(self.git_dir) endif @@ -374,22 +398,24 @@ endfunction call s:add_methods('repo',['dir','tree','bare','translate','head']) function! s:repo_git_command(...) dict abort - let git = g:fugitive_git_executable . ' --git-dir='.s:shellesc(self.git_dir) + let git = s:git_command() . ' --git-dir='.s:shellesc(self.git_dir) return git.join(map(copy(a:000),'" ".s:shellesc(v:val)'),'') endfunction function! s:repo_git_chomp(...) dict abort - return s:sub(system(call(self.git_command,a:000,self)),'\n$','') + let git = g:fugitive_git_executable . ' --git-dir='.s:shellesc(self.git_dir) + let output = git.join(map(copy(a:000),'" ".s:shellesc(v:val)'),'') + return s:sub(system(output),'\n$','') endfunction function! s:repo_git_chomp_in_tree(...) dict abort - let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd ' + let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd' : 'cd' let dir = getcwd() try - execute cd.'`=s:repo().tree()`' + execute cd s:fnameescape(s:repo().tree()) return call(s:repo().git_chomp, a:000, s:repo()) finally - execute cd.'`=dir`' + execute cd s:fnameescape(dir) endtry endfunction @@ -456,7 +482,7 @@ endfunction call s:add_methods('repo',['dirglob','superglob']) function! s:repo_config(conf) dict abort - return matchstr(system(s:repo().git_command('config').' '.a:conf),"[^\r\n]*") + return matchstr(s:repo().git_chomp('config',a:conf),"[^\r\n]*") endfun function! s:repo_user() dict abort @@ -468,8 +494,8 @@ endfun function! s:repo_aliases() dict abort if !has_key(self,'_aliases') let self._aliases = {} - for line in split(self.git_chomp('config','--get-regexp','^alias[.]'),"\n") - let self._aliases[matchstr(line,'\.\zs\S\+')] = matchstr(line,' \zs.*') + for line in split(self.git_chomp('config','-z','--get-regexp','^alias[.]'),"\1") + let self._aliases[matchstr(line, '\.\zs.\{-}\ze\n')] = matchstr(line, '\n\zs.*') endfor endif return self._aliases @@ -480,9 +506,9 @@ call s:add_methods('repo',['config', 'user', 'aliases']) function! s:repo_keywordprg() dict abort let args = ' --git-dir='.escape(self.dir(),"\\\"' ") if has('gui_running') && !has('win32') - return g:fugitive_git_executable . ' --no-pager' . args . ' log -1' + return s:git_command() . ' --no-pager' . args . ' log -1' else - return g:fugitive_git_executable . args . ' show' + return s:git_command() . args . ' show' endif endfunction @@ -679,13 +705,13 @@ call s:add_methods('buffer',['getvar','setvar','getline','repo','type','spec','n call s:command("-bang -nargs=? -complete=customlist,s:GitComplete Git :execute s:Git(0,)") function! s:ExecuteInTree(cmd) abort - let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd ' + let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd' : 'cd' let dir = getcwd() try - execute cd.'`=s:repo().tree()`' + execute cd s:fnameescape(s:repo().tree()) execute a:cmd finally - execute cd.'`=dir`' + execute cd s:fnameescape(dir) endtry endfunction @@ -693,14 +719,18 @@ function! s:Git(bang, args) abort if a:bang return s:Edit('edit', 1, a:args) endif - let git = g:fugitive_git_executable + let git = s:git_command() if has('gui_running') && !has('win32') let git .= ' --no-pager' endif let args = matchstr(a:args,'\v\C.{-}%($|\\@ `=s:repo().bare() ? s:repo().dir() : s:repo().tree()`") -call s:command("-bar -bang -nargs=? -complete=customlist,s:DirComplete Glcd :lcd `=s:repo().bare() ? s:repo().dir() : s:repo().tree()`") +call s:command("-bar -bang -nargs=? -complete=customlist,s:DirComplete Gcd :exe 'cd' s:fnameescape(s:repo().bare() ? s:repo().dir() : s:repo().tree())") +call s:command("-bar -bang -nargs=? -complete=customlist,s:DirComplete Glcd :exe 'lcd' s:fnameescape(s:repo().bare() ? s:repo().dir() : s:repo().tree())") " Section: Gstatus @@ -859,7 +889,7 @@ function! s:StageUndo() abort let hash = repo.git_chomp('hash-object', '-w', filename) if !empty(hash) if section ==# 'untracked' - call repo.git_chomp_in_tree('clean', '--', filename) + call repo.git_chomp_in_tree('clean', '-f', '--', filename) elseif section ==# 'unmerged' call repo.git_chomp_in_tree('rm', '--', filename) elseif section ==# 'unstaged' @@ -954,11 +984,14 @@ function! s:StageToggle(lnum1,lnum2) abort continue endif execute lnum - if filename =~ ' -> ' - let cmd = ['mv','--'] + reverse(split(filename,' -> ')) - let filename = cmd[-1] - elseif section ==# 'staged' - let cmd = ['reset','-q','--',filename] + if section ==# 'staged' + if filename =~ ' -> ' + let files_to_unstage = split(filename,' -> ') + else + let files_to_unstage = [filename] + endif + let filename = files_to_unstage[-1] + let cmd = ['reset','-q','--'] + files_to_unstage elseif getline(lnum) =~# '^#\tdeleted:' let cmd = ['rm','--',filename] elseif getline(lnum) =~# '^#\tmodified:' @@ -1033,14 +1066,14 @@ call s:command("-nargs=? -complete=customlist,s:CommitComplete Gcommit :execute function! s:Commit(args, ...) abort let repo = a:0 ? a:1 : s:repo() - let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd ' + let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd' : 'cd' let dir = getcwd() let msgfile = repo.dir('COMMIT_EDITMSG') let outfile = tempname() let errorfile = tempname() try try - execute cd.s:fnameescape(repo.tree()) + execute cd s:fnameescape(repo.tree()) if s:winshell() let command = '' let old_editor = $GIT_EDITOR @@ -1056,13 +1089,14 @@ function! s:Commit(args, ...) abort else noautocmd silent execute '!'.command.' > '.outfile.' 2> '.errorfile endif + let error = v:shell_error finally - execute cd.'`=dir`' + execute cd s:fnameescape(dir) endtry if !has('gui_running') redraw! endif - if !v:shell_error + if !error if filereadable(outfile) for line in readfile(outfile) echo line @@ -1099,7 +1133,7 @@ function! s:Commit(args, ...) abort elseif error ==# '!' return s:Status() else - call s:throw(error) + call s:throw(empty(error)?join(errors, ' '):error) endif endif catch /^fugitive:/ @@ -1116,7 +1150,7 @@ endfunction function! s:CommitComplete(A,L,P) abort if a:A =~ '^-' || type(a:A) == type(0) " a:A is 0 on :Gcommit - - let args = ['-C', '-F', '-a', '-c', '-e', '-i', '-m', '-n', '-o', '-q', '-s', '-t', '-u', '-v', '--all', '--allow-empty', '--amend', '--author=', '--cleanup=', '--dry-run', '--edit', '--file=', '--include', '--interactive', '--message=', '--no-verify', '--only', '--quiet', '--reedit-message=', '--reuse-message=', '--signoff', '--template=', '--untracked-files', '--verbose'] + let args = ['-C', '-F', '-a', '-c', '-e', '-i', '-m', '-n', '-o', '-q', '-s', '-t', '-u', '-v', '--all', '--allow-empty', '--amend', '--author=', '--cleanup=', '--dry-run', '--edit', '--file=', '--fixup=', '--include', '--interactive', '--message=', '--no-verify', '--only', '--quiet', '--reedit-message=', '--reuse-message=', '--signoff', '--squash=', '--template=', '--untracked-files', '--verbose'] return filter(args,'v:val[0 : strlen(a:A)-1] ==# a:A') else return s:repo().superglob(a:A) @@ -1206,7 +1240,7 @@ function! s:Merge(cmd, bang, args) abort \ !empty(s:repo().git_chomp('diff-files', '--diff-filter=U'))) let &l:makeprg = g:fugitive_git_executable.' diff-files --name-status --diff-filter=U' else - let &l:makeprg = s:sub(g:fugitive_git_executable . ' ' . a:cmd . + let &l:makeprg = s:sub(s:git_command() . ' ' . a:cmd . \ (a:args =~# ' \%(--no-edit\|--abort\|-m\)\>' ? '' : ' --edit') . \ ' ' . a:args, ' *$', '') endif @@ -1267,10 +1301,10 @@ call s:command("-bar -bang -nargs=* -range=0 -complete=customlist,s:EditComplete function! s:Grep(cmd,bang,arg) abort let grepprg = &grepprg let grepformat = &grepformat - let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd ' + let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd' : 'cd' let dir = getcwd() try - execute cd.'`=s:repo().tree()`' + execute cd s:fnameescape(s:repo().tree()) let &grepprg = s:repo().git_command('--no-pager', 'grep', '-n', '--no-color') let &grepformat = '%f:%l:%m,%m %f match%ts,%f' exe a:cmd.'! '.escape(matchstr(a:arg,'\v\C.{-}%($|[''" ]\@=\|)@='),'|') @@ -1299,7 +1333,7 @@ function! s:Grep(cmd,bang,arg) abort finally let &grepprg = grepprg let &grepformat = grepformat - execute cd.'`=dir`' + execute cd s:fnameescape(dir) endtry endfunction @@ -1327,17 +1361,17 @@ function! s:Log(cmd, line1, line2, ...) abort endif let grepformat = &grepformat let grepprg = &grepprg - let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd ' + let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd' : 'cd' let dir = getcwd() try - execute cd.'`=s:repo().tree()`' + execute cd s:fnameescape(s:repo().tree()) let &grepprg = escape(call(s:repo().git_command,cmd,s:repo()),'%#') let &grepformat = '%Cdiff %.%#,%C--- %.%#,%C+++ %.%#,%Z@@ -%\d%\+\,%\d%\+ +%l\,%\d%\+ @@,%-G-%.%#,%-G+%.%#,%-G %.%#,%A%f::%m,%-G%.%#' exe a:cmd finally let &grepformat = grepformat let &grepprg = grepprg - execute cd.'`=dir`' + execute cd s:fnameescape(dir) endtry endfunction @@ -1366,6 +1400,7 @@ function! s:Edit(cmd,bang,...) abort endif endif endfor + diffoff! endif endif endif @@ -1385,6 +1420,9 @@ function! s:Edit(cmd,bang,...) abort return 'redraw|echo '.string(':!'.git.' '.args) else let temp = resolve(tempname()) + if has('win32') + let temp = fnamemodify(fnamemodify(temp, ':h'), ':p').fnamemodify(temp, ':t') + endif let s:temp_files[s:cpath(temp)] = { 'dir': buffer.repo().dir(), 'args': arglist } silent execute a:cmd.' '.temp if a:cmd =~# 'pedit' @@ -1448,7 +1486,7 @@ call s:command("-bar -bang -nargs=* -complete=customlist,s:EditRunComplete Gpedi call s:command("-bar -bang -nargs=* -complete=customlist,s:EditRunComplete Gsplit :execute s:Edit('split',0,)") call s:command("-bar -bang -nargs=* -complete=customlist,s:EditRunComplete Gvsplit :execute s:Edit('vsplit',0,)") call s:command("-bar -bang -nargs=* -complete=customlist,s:EditRunComplete Gtabedit :execute s:Edit('tabedit',0,)") -call s:command("-bar -bang -nargs=* -count -complete=customlist,s:EditRunComplete Gread :execute s:Edit((! && ? '' : ).'read',0,)") +call s:command("-bar -bang -nargs=* -range=-1 -complete=customlist,s:EditRunComplete Gread :execute s:Edit(( == -1 ? '' : ).'read',0,)") " Section: Gwrite, Gwq @@ -1627,7 +1665,7 @@ function! s:Dispatch(bang, args) try let b:current_compiler = 'git' let &l:errorformat = s:common_efm - let &l:makeprg = g:fugitive_git_executable . ' ' . a:args + let &l:makeprg = substitute(s:git_command() . ' ' . a:args, '\s\+$', '', '') execute cd fnameescape(s:repo().tree()) if exists(':Make') == 2 noautocmd Make @@ -1774,15 +1812,19 @@ function! s:Diff(vert,keepfocus,...) abort elseif (empty(args) || args[0] == ':') && s:buffer().commit() =~# '^[0-1]\=$' && s:repo().git_chomp_in_tree('ls-files', '--unmerged', '--', s:buffer().path()) !=# '' let vert = empty(a:vert) ? s:diff_modifier(3) : a:vert let nr = bufnr('') - execute 'leftabove '.vert.'split `=fugitive#buffer().repo().translate(s:buffer().expand('':2''))`' + execute 'leftabove '.vert.'split' s:fnameescape(fugitive#repo().translate(s:buffer().expand(':2'))) execute 'nnoremap dp :diffput '.nr.'diffupdate' + let nr2 = bufnr('') call s:diffthis() wincmd p - execute 'rightbelow '.vert.'split `=fugitive#buffer().repo().translate(s:buffer().expand('':3''))`' + execute 'rightbelow '.vert.'split' s:fnameescape(fugitive#repo().translate(s:buffer().expand(':3'))) execute 'nnoremap dp :diffput '.nr.'diffupdate' + let nr3 = bufnr('') call s:diffthis() wincmd p call s:diffthis() + execute 'nnoremap d2o :diffget '.nr2.'diffupdate' + execute 'nnoremap d3o :diffget '.nr3.'diffupdate' return post elseif len(args) let arg = join(args, ' ') @@ -1882,7 +1924,7 @@ function! s:MoveComplete(A,L,P) abort endif endfunction -function! s:Remove(force) abort +function! s:Remove(after, force) abort if s:buffer().commit() ==# '' let cmd = ['rm'] elseif s:buffer().commit() ==# '0' @@ -1900,7 +1942,7 @@ function! s:Remove(force) abort return 'echoerr '.string(v:errmsg) else call fugitive#reload_status() - return 'edit'.(a:force ? '!' : '') + return a:after . (a:force ? '!' : '') endif endfunction @@ -1908,7 +1950,8 @@ augroup fugitive_remove autocmd! autocmd User Fugitive if s:buffer().commit() =~# '^0\=$' | \ exe "command! -buffer -bar -bang -nargs=1 -complete=customlist,s:MoveComplete Gmove :execute s:Move(0,)" | - \ exe "command! -buffer -bar -bang Gremove :execute s:Remove(0)" | + \ exe "command! -buffer -bar -bang Gremove :execute s:Remove('edit',0)" | + \ exe "command! -buffer -bar -bang Gdelete :execute s:Remove('bdelete',0)" | \ endif augroup END @@ -1952,12 +1995,12 @@ function! s:Blame(bang,line1,line2,count,args) abort let cmd += ['--contents', '-'] endif let cmd += ['--', s:buffer().path()] - let basecmd = escape(call(s:repo().git_command,cmd,s:repo()),'!') + let basecmd = escape(call(s:repo().git_command,cmd,s:repo()),'!%#') try - let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd ' + let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd' : 'cd' if !s:repo().bare() let dir = getcwd() - execute cd.'`=s:repo().tree()`' + execute cd s:fnameescape(s:repo().tree()) endif if a:count execute 'write !'.substitute(basecmd,' blame ',' blame -L '.a:line1.','.a:line2.' ','g') @@ -1970,7 +2013,7 @@ function! s:Blame(bang,line1,line2,count,args) abort silent! execute '%write !'.basecmd.' > '.temp.' 2> '.error endif if exists('l:dir') - execute cd.'`=dir`' + execute cd s:fnameescape(dir) unlet dir endif if v:shell_error @@ -2002,6 +2045,9 @@ function! s:Blame(bang,line1,line2,count,args) abort endif let top = line('w0') + &scrolloff let current = line('.') + if has('win32') + let temp = fnamemodify(fnamemodify(temp, ':h'), ':p').fnamemodify(temp, ':t') + endif let s:temp_files[s:cpath(temp)] = { 'dir': s:repo().dir(), 'args': cmd } exe 'keepalt leftabove vsplit '.temp let b:fugitive_blamed_bufnr = bufnr @@ -2040,7 +2086,7 @@ function! s:Blame(bang,line1,line2,count,args) abort endif finally if exists('l:dir') - execute cd.'`=dir`' + execute cd s:fnameescape(dir) endif endtry return '' @@ -2134,8 +2180,8 @@ function! s:BlameSyntax() abort let arg = exists('b:fugitive_blame_arguments') ? b:fugitive_blame_arguments : '' syn match FugitiveblameBoundary "^\^" syn match FugitiveblameBlank "^\s\+\s\@=" nextgroup=FugitiveblameAnnotation,fugitiveblameOriginalFile,FugitiveblameOriginalLineNumber skipwhite - syn match FugitiveblameHash "\%(^\^\=\)\@<=\x\{7,40\}\>" nextgroup=FugitiveblameAnnotation,FugitiveblameOriginalLineNumber,fugitiveblameOriginalFile skipwhite - syn match FugitiveblameUncommitted "\%(^\^\=\)\@<=0\{7,40\}\>" nextgroup=FugitiveblameAnnotation,FugitiveblameOriginalLineNumber,fugitiveblameOriginalFile skipwhite + syn match FugitiveblameHash "\%(^\^\=\)\@<=\<\x\{7,40\}\>" nextgroup=FugitiveblameAnnotation,FugitiveblameOriginalLineNumber,fugitiveblameOriginalFile skipwhite + syn match FugitiveblameUncommitted "\%(^\^\=\)\@<=\<0\{7,40\}\>" nextgroup=FugitiveblameAnnotation,FugitiveblameOriginalLineNumber,fugitiveblameOriginalFile skipwhite syn region FugitiveblameAnnotation matchgroup=FugitiveblameDelimiter start="(" end="\%( \d\+\)\@<=)" contained keepend oneline syn match FugitiveblameTime "[0-9:/+-][0-9:/+ -]*[0-9:/+-]\%( \+\d\+)\)\@=" contained containedin=FugitiveblameAnnotation exec 'syn match FugitiveblameLineNumber " *\d\+)\@=" contained containedin=FugitiveblameAnnotation'.conceal @@ -2161,7 +2207,7 @@ function! s:BlameSyntax() abort continue endif let seen[hash] = 1 - if &t_Co > 16 && exists('g:CSApprox_loaded') + if &t_Co > 16 && get(g:, 'CSApprox_loaded') && !empty(findfile('autoload/csapprox/per_component.vim', escape(&rtp, ' '))) \ && empty(get(s:hash_colors, hash)) let [s, r, g, b; __] = map(matchlist(hash, '\(\x\x\)\(\x\x\)\(\x\x\)'), 'str2nr(v:val,16)') let color = csapprox#per_component#Approximate(r, g, b) @@ -2179,7 +2225,7 @@ endfunction function! s:RehighlightBlame() abort for [hash, cterm] in items(s:hash_colors) - if !empty(cterm) || has('gui_running') + if !empty(cterm) || has('gui_running') || has('termguicolors') && &termguicolors exe 'hi FugitiveblameHash'.hash.' guifg=#'.hash.get(s:hash_colors, hash, '') else exe 'hi link FugitiveblameHash'.hash.' Identifier' @@ -2191,6 +2237,8 @@ endfunction call s:command("-bar -bang -range=0 -nargs=* -complete=customlist,s:EditComplete Gbrowse :execute s:Browse(0,,,)") +let s:redirects = {} + function! s:Browse(bang,line1,count,...) abort try let validremote = '\.\|\.\=/.*\|[[:alnum:]_-]\+\%(://.\{-\}\)\=' @@ -2251,10 +2299,11 @@ function! s:Browse(bang,line1,count,...) abort if path =~# '^\.git/refs/remotes/.' if empty(remote) let remote = matchstr(path, '^\.git/refs/remotes/\zs[^/]\+') + let branch = matchstr(path, '^\.git/refs/remotes/[^/]\+/\zs.\+') + else + let merge = matchstr(path, '^\.git/refs/remotes/[^/]\+/\zs.\+') + let path = '.git/refs/heads/'.merge endif - let merge = matchstr(path, '^\.git/refs/remotes/[^/]\+/\zs.\+') - let branch = '' - let path = '.git/refs/heads/'.merge elseif path =~# '^\.git/refs/heads/.' let branch = path[16:-1] elseif !exists('branch') @@ -2291,14 +2340,30 @@ function! s:Browse(bang,line1,count,...) abort if empty(remote) let remote = '.' - let raw = s:repo().git_chomp('config','remote.origin.url') + let remote_for_url = 'origin' else - let raw = s:repo().git_chomp('config','remote.'.remote.'.url') + let remote_for_url = remote + endif + if fugitive#git_version() =~# '^[01]\.\|^2\.[0-6]\.' + let raw = s:repo().git_chomp('config','remote.'.remote_for_url.'.url') + else + let raw = s:repo().git_chomp('remote','get-url',remote_for_url) endif if raw ==# '' let raw = remote endif + if raw =~# '^https\=://' && s:executable('curl') + if !has_key(s:redirects, raw) + let s:redirects[raw] = matchstr(system('curl -I ' . + \ s:shellesc(raw . '/info/refs?service=git-upload-pack')), + \ 'Location: \zs\S\+\ze/info/refs?') + endif + if len(s:redirects[raw]) + let raw = s:redirects[raw] + endif + endif + for Handler in g:fugitive_browse_handlers let url = call(Handler, [{ \ 'repo': s:repo(), @@ -2317,7 +2382,7 @@ function! s:Browse(bang,line1,count,...) abort if empty(url) && raw ==# '.' call s:throw("Instaweb failed to start") elseif empty(url) - call s:throw('"'.remote."' is not a supported remote") + call s:throw("'".remote."' is not a supported remote") endif let url = s:gsub(url, '[ <>]', '\="%".printf("%02X",char2nr(submatch(0)))') @@ -2356,46 +2421,8 @@ function! s:github_url(opts, ...) abort if repo ==# '' return '' endif - let path = substitute(a:opts.path, '^/', '', '') - if index(domains, 'http://' . matchstr(repo, '^[^:/]*')) >= 0 - let root = 'http://' . s:sub(repo,':','/') - else - let root = 'https://' . s:sub(repo,':','/') - endif - if path =~# '^\.git/refs/heads/' - let branch = a:opts.repo.git_chomp('config','branch.'.path[16:-1].'.merge')[11:-1] - if branch ==# '' - return root . '/commits/' . path[16:-1] - else - return root . '/commits/' . branch - endif - elseif path =~# '^\.git/refs/tags/' - return root . '/releases/tag/' . path[15:-1] - elseif path =~# '^\.git/refs/remotes/[^/]\+/.' - return root . '/commits/' . matchstr(path,'remotes/[^/]\+/\zs.*') - elseif path =~# '.git/\%(config$\|hooks\>\)' - return root . '/admin' - elseif path =~# '^\.git\>' - return root - endif - if a:opts.commit =~# '^\d\=$' - let commit = a:opts.repo.rev_parse('HEAD') - else - let commit = a:opts.commit - endif - if get(a:opts, 'type', '') ==# 'tree' || a:opts.path =~# '/$' - let url = substitute(root . '/tree/' . commit . '/' . path, '/$', '', 'g') - elseif get(a:opts, 'type', '') ==# 'blob' || a:opts.path =~# '[^/]$' - let url = root . '/blob/' . commit . '/' . path - if get(a:opts, 'line2') && a:opts.line1 == a:opts.line2 - let url .= '#L' . a:opts.line1 - elseif get(a:opts, 'line2') - let url .= '#L' . a:opts.line1 . '-L' . a:opts.line2 - endif - else - let url = root . '/commit/' . commit - endif - return url + call s:warn('Install rhubarb.vim for GitHub support') + return 'https://github.com/tpope/vim-rhubarb' endfunction function! s:instaweb_url(opts) abort @@ -2513,7 +2540,7 @@ function! s:BufReadIndex() abort call s:ReplaceCmd(s:repo().git_command('ls-files','--stage'),index) set ft=git nospell else - let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd ' + let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd' : 'cd' let dir = getcwd() if fugitive#git_version() =~# '^0\|^1\.[1-7]\.' let cmd = s:repo().git_command('status') @@ -2525,10 +2552,10 @@ function! s:BufReadIndex() abort \ 'status') endif try - execute cd.'`=s:repo().tree()`' + execute cd s:fnameescape(s:repo().tree()) call s:ReplaceCmd(cmd, index) finally - execute cd.'`=dir`' + execute cd s:fnameescape(dir) endtry set ft=gitcommit set foldtext=fugitive#foldtext() @@ -2653,7 +2680,7 @@ function! s:BufReadObject() abort let b:fugitive_type = s:repo().git_chomp('cat-file','-t',hash) endif if b:fugitive_type !~# '^\%(tag\|commit\|tree\|blob\)$' - return "echoerr 'fugitive: unrecognized git type'" + return "echoerr ".string("fugitive: unrecognized git type '".b:fugitive_type."'") endif let firstline = getline('.') if !exists('b:fugitive_display_format') && b:fugitive_type != 'blob' @@ -2840,7 +2867,7 @@ function! s:cfile() abort elseif getline('.') =~# '^#\trenamed:.* -> ' let file = '/'.matchstr(getline('.'),' -> \zs.*') return [file] - elseif getline('.') =~# '^#\t[[:alpha:] ]\+: *.' + elseif getline('.') =~# '^#\t\(\k\| \)\+\p\?: *.' let file = '/'.matchstr(getline('.'),': *\zs.\{-\}\ze\%( ([^()[:digit:]]\+)\)\=$') return [file] elseif getline('.') =~# '^#\t.' @@ -2897,7 +2924,7 @@ function! s:cfile() abort let ref = matchstr(getline('.'),'\x\{40\}') echoerr "warning: unknown context ".matchstr(getline('.'),'^\l*') - elseif getline('.') =~# '^[+-]\{3\} [ab/]' + elseif getline('.') =~# '^[+-]\{3\} [abciow12]\=/' let ref = getline('.')[4:] elseif getline('.') =~# '^[+-]' && search('^@@ -\d\+,\d\+ +\d\+,','bnW') @@ -2911,7 +2938,7 @@ function! s:cfile() abort let lnum -= 1 endwhile let offset += matchstr(getline(lnum), type.'\zs\d\+') - let ref = getline(search('^'.type.'\{3\} [ab]/','bnW'))[4:-1] + let ref = getline(search('^'.type.'\{3\} [abciow12]/','bnW'))[4:-1] let dcmds = [offset, 'normal!zv'] elseif getline('.') =~# '^rename from ' @@ -2920,22 +2947,22 @@ function! s:cfile() abort let ref = 'b/'.getline('.')[10:] elseif getline('.') =~# '^@@ -\d\+,\d\+ +\d\+,' - let diff = getline(search('^diff --git \%(a/.*\|/dev/null\) \%(b/.*\|/dev/null\)', 'bcnW')) + let diff = getline(search('^diff --git \%([abciow12]/.*\|/dev/null\) \%([abciow12]/.*\|/dev/null\)', 'bcnW')) let offset = matchstr(getline('.'), '+\zs\d\+') - let dref = matchstr(diff, '\Cdiff --git \zs\%(a/.*\|/dev/null\)\ze \%(b/.*\|/dev/null\)') - let ref = matchstr(diff, '\Cdiff --git \%(a/.*\|/dev/null\) \zs\%(b/.*\|/dev/null\)') + let dref = matchstr(diff, '\Cdiff --git \zs\%([abciow12]/.*\|/dev/null\)\ze \%([abciow12]/.*\|/dev/null\)') + let ref = matchstr(diff, '\Cdiff --git \%([abciow12]/.*\|/dev/null\) \zs\%([abciow12]/.*\|/dev/null\)') let dcmd = 'Gdiff! +'.offset - elseif getline('.') =~# '^diff --git \%(a/.*\|/dev/null\) \%(b/.*\|/dev/null\)' - let dref = matchstr(getline('.'),'\Cdiff --git \zs\%(a/.*\|/dev/null\)\ze \%(b/.*\|/dev/null\)') - let ref = matchstr(getline('.'),'\Cdiff --git \%(a/.*\|/dev/null\) \zs\%(b/.*\|/dev/null\)') + elseif getline('.') =~# '^diff --git \%([abciow12]/.*\|/dev/null\) \%([abciow12]/.*\|/dev/null\)' + let dref = matchstr(getline('.'),'\Cdiff --git \zs\%([abciow12]/.*\|/dev/null\)\ze \%([abciow12]/.*\|/dev/null\)') + let ref = matchstr(getline('.'),'\Cdiff --git \%([abciow12]/.*\|/dev/null\) \zs\%([abciow12]/.*\|/dev/null\)') let dcmd = 'Gdiff!' - elseif getline('.') =~# '^index ' && getline(line('.')-1) =~# '^diff --git \%(a/.*\|/dev/null\) \%(b/.*\|/dev/null\)' + elseif getline('.') =~# '^index ' && getline(line('.')-1) =~# '^diff --git \%([abciow12]/.*\|/dev/null\) \%([abciow12]/.*\|/dev/null\)' let line = getline(line('.')-1) - let dref = matchstr(line,'\Cdiff --git \zs\%(a/.*\|/dev/null\)\ze \%(b/.*\|/dev/null\)') - let ref = matchstr(line,'\Cdiff --git \%(a/.*\|/dev/null\) \zs\%(b/.*\|/dev/null\)') + let dref = matchstr(line,'\Cdiff --git \zs\%([abciow12]/.*\|/dev/null\)\ze \%([abciow12]/.*\|/dev/null\)') + let ref = matchstr(line,'\Cdiff --git \%([abciow12]/.*\|/dev/null\) \zs\%([abciow12]/.*\|/dev/null\)') let dcmd = 'Gdiff!' elseif line('$') == 1 && getline('.') =~ '^\x\{40\}$' @@ -2948,18 +2975,21 @@ function! s:cfile() abort let ref = '' endif - if myhash ==# '' - let ref = s:sub(ref,'^a/','HEAD:') - let ref = s:sub(ref,'^b/',':0:') - if exists('dref') - let dref = s:sub(dref,'^a/','HEAD:') - endif - else - let ref = s:sub(ref,'^a/',myhash.'^:') - let ref = s:sub(ref,'^b/',myhash.':') - if exists('dref') - let dref = s:sub(dref,'^a/',myhash.'^:') - endif + let prefixes = { + \ '1': '', + \ '2': '', + \ 'b': ':0:', + \ 'i': ':0:', + \ 'o': '', + \ 'w': ''} + + if len(myhash) + let prefixes.a = myhash.'^:' + let prefixes.b = myhash.':' + endif + let ref = substitute(ref, '^\(\w\)/', '\=get(prefixes, submatch(1), "HEAD:")', '') + if exists('dref') + let dref = substitute(dref, '^\(\w\)/', '\=get(prefixes, submatch(1), "HEAD:")', '') endif if ref ==# '/dev/null' @@ -3067,7 +3097,7 @@ function! fugitive#foldtext() abort endif endfor if filename ==# '' - let filename = matchstr(getline(v:foldstart), '^diff .\{-\} a/\zs.*\ze b/') + let filename = matchstr(getline(v:foldstart), '^diff .\{-\} [abciow12]/\zs.*\ze [abciow12]/') endif if filename ==# '' let filename = getline(v:foldstart)[5:-1] diff --git a/sources_non_forked/vim-gitgutter b/sources_non_forked/vim-gitgutter deleted file mode 160000 index 339f8ba0..00000000 --- a/sources_non_forked/vim-gitgutter +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 339f8ba079ed7d465ca442c9032b36bc56c21f61 diff --git a/sources_non_forked/vim-gitgutter/.gitignore b/sources_non_forked/vim-gitgutter/.gitignore new file mode 100644 index 00000000..82fb2537 --- /dev/null +++ b/sources_non_forked/vim-gitgutter/.gitignore @@ -0,0 +1,5 @@ +/doc/tags +/misc +/test/*.actual +*.log + diff --git a/sources_non_forked/vim-gitgutter/LICENCE b/sources_non_forked/vim-gitgutter/LICENCE new file mode 100644 index 00000000..38e2dc2d --- /dev/null +++ b/sources_non_forked/vim-gitgutter/LICENCE @@ -0,0 +1,22 @@ +MIT License + +Copyright (c) Andrew Stewart + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff --git a/sources_non_forked/vim-gitgutter/README.mkd b/sources_non_forked/vim-gitgutter/README.mkd new file mode 100644 index 00000000..83f10c20 --- /dev/null +++ b/sources_non_forked/vim-gitgutter/README.mkd @@ -0,0 +1,564 @@ +## 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. + +Features: + +* 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. +* Ensures signs are always as up to date as possible (but without running more than necessary). +* Quick jumping between blocks of changed lines ("hunks"). +* Stage/undo/preview individual hunks. +* Provides a hunk text object. +* Diffs against index (default) or any commit. +* Handles line endings correctly, even with repos that do CRLF conversion. +* Optional line highlighting. +* Fully customisable (signs, sign column, line highlights, mappings, extra git-diff arguments, etc). +* Can be toggled on/off. +* Preserves signs from other plugins. +* Easy to integrate diff stats into status line; built-in integration with [vim-airline](https://github.com/bling/vim-airline/). +* Works with fish shell (in addition to the usual shells). + +Constraints: + +* Supports git only. + +If you work with other version control systems, I recommend [vim-signify](https://github.com/mhinz/vim-signify). + + +### Screenshot + +![screenshot](https://raw.github.com/airblade/vim-gitgutter/master/screenshot.png) + +In the screenshot above you can see: + +* Line 15 has been modified. +* Lines 21-24 are new. +* A line or lines were removed between lines 25 and 26. + + +### 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. + +You install vim-gitgutter like any other vim plugin. + +##### Pathogen + +``` +cd ~/.vim/bundle +git clone git://github.com/airblade/vim-gitgutter.git +``` + +##### Voom + +Edit your plugin manifest (`voom edit`) and add: + +``` +airblade/vim-gitgutter +``` + +##### VimPlug + +Place this in your .vimrc: + +```viml +Plug 'airblade/vim-gitgutter' +``` + +Then run the following in Vim: + +``` +:source % +:PlugInstall +``` + +##### NeoBundle + +Place this in your .vimrc: + +```viml +NeoBundle 'airblade/vim-gitgutter' +``` + +Then run the following in Vim: + +``` +:source % +:NeoBundleInstall +``` + +##### No plugin manager + +Copy vim-gitgutter's subdirectories into your vim configuration directory: + +``` +cd /tmp && git clone git://github.com/airblade/vim-gitgutter.git +cp -r vim-gitgutter/* ~/.vim/ +``` + +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 + +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). + +You can jump between hunks with `[c` and `]c`. You can preview, stage, and undo hunks with `hp`, `hs`, and `hu` respectively. + +You cannot currently unstage a staged hunk. + + +#### Activation + +You can explicitly turn vim-gitgutter off and on (defaults to on): + +* turn off with `:GitGutterDisable` +* turn on with `:GitGutterEnable` +* toggle with `:GitGutterToggle`. + +You can turn the signs on and off (defaults to on): + +* turn on with `:GitGutterSignsEnable` +* turn off with `:GitGutterSignsDisable` +* toggle with `:GitGutterSignsToggle`. + +And you can turn line highlighting on and off (defaults to off): + +* turn on with `:GitGutterLineHighlightsEnable` +* turn off with `:GitGutterLineHighlightsDisable` +* toggle with `:GitGutterLineHighlightsToggle`. + +Note that if you have line highlighting on and signs off, you will have an empty sign column – more accurately, a sign column with invisible signs. This is because line highlighting requires signs and Vim always shows the sign column even if the signs are invisible. + +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: + +```viml +let g:gitgutter_max_signs = 500 " default value +``` + +#### Hunks + +You can jump between hunks: + +* jump to next hunk (change): `]c` +* jump to previous hunk (change): `[c`. + +Both of those take a preceding count. + +To set your own mappings for these, for example `]h` and `[h`: + +```viml +nmap ]h GitGutterNextHunk +nmap [h GitGutterPrevHunk +``` + +You can stage or undo an individual hunk when your cursor is in it: + +* stage the hunk with `hs` or +* undo it with `hu`. + +See the FAQ if you want to unstage staged changes. + +The `.` command will work with both these if you install [repeat.vim](https://github.com/tpope/vim-repeat). + +To set your own mappings for these, for example if you prefer the mnemonics hunk-add and hunk-revert: + +```viml +nmap ha GitGutterStageHunk +nmap hr GitGutterUndoHunk +``` + +And you can preview a hunk's changes with `hp`. You can of course change this mapping, e.g: + +```viml +nmap hv GitGutterPreviewHunk +``` + +A hunk text object is provided which works in visual and operator-pending modes. + +- `ic` operates on all lines in the current hunk. +- `ac` operates on all lines in the current hunk and any trailing empty lines. + +To re-map these, for example to `ih` and `ah`: + +```viml +omap ih GitGutterTextObjectInnerPending +omap ah GitGutterTextObjectOuterPending +xmap ih GitGutterTextObjectInnerVisual +xmap ah GitGutterTextObjectOuterVisual +``` + +If you don't want vim-gitgutter to set up any mappings at all, use this: + +```viml +let g:gitgutter_map_keys = 0 +``` + +Finally, you can force vim-gitgutter to update its signs across all visible buffers with `:GitGutterAll`. + +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 + +You can customise: + +* The sign column's colours +* Whether or not the sign column is shown when there aren't any signs (defaults to no) +* The signs' colours and symbols +* Line highlights +* The base of the diff +* Extra arguments for `git diff` +* Key mappings +* 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 set in your colorscheme. + + +#### Sign column + +By default vim-gitgutter will make the sign column look like the line number column. + +To customise your sign column's background color, first tell vim-gitgutter to leave it alone: + +```viml +let g:gitgutter_override_sign_column_highlight = 0 +``` + +And then either update your colorscheme's `SignColumn` highlight group or set it in your vimrc: + +```viml +highlight SignColumn ctermbg=whatever " terminal Vim +highlight SignColumn guibg=whatever " gVim/MacVim +``` + +By default the sign column will appear when there are signs to show and disappear when there aren't. To always have the sign column, add to your vimrc: + +```viml +if exists('&signcolumn') " Vim 7.4.2201 + set signcolumn=yes +else + let g:gitgutter_sign_column_always = 1 +endif +``` + + +#### Signs' colours and symbols + +To customise the colours, set up the following highlight groups in your colorscheme or `~/.vimrc`: + +```viml +GitGutterAdd " an added line +GitGutterChange " a changed line +GitGutterDelete " at least one removed line +GitGutterChangeDelete " a changed line followed by at least one removed line +``` + +You can either set these with `highlight GitGutterAdd {key}={arg}...` or link them to existing highlight groups with, say, `highlight link GitGutterAdd DiffAdd`. + +To customise the symbols, add the following to your `~/.vimrc`: + +```viml +let g:gitgutter_sign_added = 'xx' +let g:gitgutter_sign_modified = 'yy' +let g:gitgutter_sign_removed = 'zz' +let g:gitgutter_sign_removed_first_line = '^^' +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`: + +```viml +GitGutterAddLine " default: links to DiffAdd +GitGutterChangeLine " default: links to DiffChange +GitGutterDeleteLine " default: links to DiffDelete +GitGutterChangeDeleteLine " default: links to GitGutterChangeLineDefault, i.e. DiffChange +``` + + +#### The base of the diff + +By default buffers are diffed against the index. However you can diff against any commit by setting: + +```viml +let g:gitgutter_diff_base = '' +``` + + +#### Extra arguments for `git diff` + +If you want to pass extra arguments to `git diff`, for example to ignore whitespace, do so like this: + +```viml +let g:gitgutter_diff_args = '-w' +``` + +#### Key mappings + +To disable all key mappings: + +```viml +let g:gitgutter_map_keys = 0 +``` + +See above for configuring maps for hunk-jumping and staging/undoing. + + +#### Use a custom `grep` command + +If you use an alternative to grep, you can tell vim-gitgutter to use it here. + +```viml +" Default: +let g:gitgutter_grep_command = 'grep' +``` + +#### To turn off vim-gitgutter by default + +Add `let g:gitgutter_enabled = 0` to your `~/.vimrc`. + + +#### To turn off signs by default + +Add `let g:gitgutter_signs = 0` to your `~/.vimrc`. + + +#### To turn on line highlighting by default + +Add `let g:gitgutter_highlight_lines = 1` to your `~/.vimrc`. + + +#### To turn off asynchronous updates + +By default diffs are run asynchronously. To run diffs synchronously instead: + +```viml +let g:gitgutter_async = 0 +``` + + +### Extensions + +#### Operate on every line in a hunk + +You can map an operator to do whatever you want to every line in a hunk. + +Let's say, for example, you want to remove trailing whitespace. + +```viml +function! CleanUp(...) + if a:0 " opfunc + let [first, last] = [line("'["), line("']")] + else + let [first, last] = [line("'<"), line("'>")] + endif + for lnum in range(first, last) + let line = getline(lnum) + + " clean up the text, e.g.: + let line = substitute(line, '\s\+$', '', '') + + call setline(lnum, line) + endfor +endfunction + +nmap x :set opfunc=CleanUpg@ +``` + +Then place your cursor in a hunk and type `\xic` (assuming a leader of `\`). + +Alternatively you could place your cursor in a hunk, type `vic` to select it, then `:call CleanUp()`. + + +#### Operate on every changed line in a file + +You can write a command to do whatever you want to every changed line in a file. + +```viml +function! GlobalChangedLines(ex_cmd) + for hunk in GitGutterGetHunks() + for lnum in range(hunk[2], hunk[2]+hunk[3]-1) + let cursor = getcurpos() + silent! execute lnum.a:ex_cmd + call setpos('.', cursor) + endfor + endfor +endfunction + +command -nargs=1 Glines call GlobalChangedLines() +``` + +Let's say, for example, you want to remove trailing whitespace from all changed lines: + +```viml +:Glines s/\s\+$// +``` + + +#### Cycle through hunks in all buffers + +`]c` and `[c` jump from one hunk to the next in the current buffer. You can use this code to jump to the next hunk no matter which buffer it's in. + +```viml +function! NextHunkAllBuffers() + let line = line('.') + GitGutterNextHunk + if line('.') != line + return + endif + + let bufnr = bufnr('') + while 1 + bnext + if bufnr('') == bufnr + return + endif + if !empty(GitGutterGetHunks()) + normal! 1G + GitGutterNextHunk + return + endif + endwhile +endfunction + +function! PrevHunkAllBuffers() + let line = line('.') + GitGutterPrevHunk + if line('.') != line + return + endif + + let bufnr = bufnr('') + while 1 + bprevious + if bufnr('') == bufnr + return + endif + if !empty(GitGutterGetHunks()) + normal! G + GitGutterPrevHunk + return + endif + endwhile +endfunction + +nmap ]c :call NextHunkAllBuffers() +nmap [c :call PrevHunkAllBuffers() +``` + + +### FAQ + +> 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: + +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? + +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)? + +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? + +Here are some things you can check: + +* `:echo system("git --version")` succeeds. +* Your git config is compatible with the version of git returned by the command above. +* Your Vim supports signs (`:echo has('signs')` should give `1`). +* Your file is being tracked by git and has unstaged changes. +* If you have aliased or configured `grep` to use any flags, add `let g:gitgutter_grep_command = 'grep'` to your `~/.vimrc`. + +> Why is the whole file marked as added when I edit it? + +* If you use zsh, and you set `CDPATH`, make sure `CDPATH` doesn't include the current directory. + + +### Shameless Plug + +If this plugin has helped you, or you'd like to learn more about Vim, why not check out this screencast I wrote for PeepCode: + +* [Smash Into Vim][siv] + +This was one of PeepCode's all-time top three bestsellers and is now available at Pluralsight. + +You can read reviews on my [website][airblade]. + + +### Intellectual Property + +Copyright Andrew Stewart, AirBlade Software Ltd. Released under the MIT licence. + + + [pathogen]: https://github.com/tpope/vim-pathogen + [siv]: http://pluralsight.com/training/Courses/TableOfContents/smash-into-vim + [airblade]: http://airbladesoftware.com/peepcode-vim + [macvim]: http://code.google.com/p/macvim/ diff --git a/sources_non_forked/vim-gitgutter/autoload/gitgutter.vim b/sources_non_forked/vim-gitgutter/autoload/gitgutter.vim new file mode 100644 index 00000000..6e8ca57d --- /dev/null +++ b/sources_non_forked/vim-gitgutter/autoload/gitgutter.vim @@ -0,0 +1,259 @@ +let s:nomodeline = (v:version > 703 || (v:version == 703 && has('patch442'))) ? '' : '' + +" Primary functions {{{ + +function! gitgutter#all() abort + for buffer_id in gitgutter#utility#dedup(tabpagebuflist()) + let file = expand('#' . buffer_id . ':p') + if !empty(file) + call gitgutter#process_buffer(buffer_id, 0) + endif + endfor +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) + if gitgutter#utility#is_active() + if g:gitgutter_sign_column_always + call gitgutter#sign#add_dummy_sign() + endif + try + if !a:realtime || gitgutter#utility#has_fresh_changes() + let diff = gitgutter#diff#run_diff(a:realtime || gitgutter#utility#has_unsaved_changes(), 0) + if diff != 'async' + call gitgutter#handle_diff(diff) + endif + endif + catch /diff failed/ + call gitgutter#debug#log('diff failed') + call gitgutter#hunk#reset() + endtry + execute "silent doautocmd" s:nomodeline "User GitGutter" + else + call gitgutter#hunk#reset() + endif + + call gitgutter#utility#restore_shell() +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 + " get list of all buffers (across all tabs) + let buflist = [] + for i in range(tabpagenr('$')) + call extend(buflist, tabpagebuflist(i + 1)) + endfor + + for buffer_id in gitgutter#utility#dedup(buflist) + let file = expand('#' . buffer_id . ':p') + if !empty(file) + call gitgutter#utility#set_buffer(buffer_id) + call gitgutter#sign#clear_signs() + call gitgutter#sign#remove_dummy_sign(1) + call gitgutter#hunk#reset() + endif + endfor + + let g:gitgutter_enabled = 0 +endfunction + +function! gitgutter#enable() abort + let g:gitgutter_enabled = 1 + call gitgutter#all() +endfunction + +function! gitgutter#toggle() abort + if g:gitgutter_enabled + call gitgutter#disable() + else + call gitgutter#enable() + endif +endfunction + +" }}} + +" Line highlights {{{ + +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 + +function! gitgutter#line_highlights_enable() abort + let old_highlight_lines = g:gitgutter_highlight_lines + + 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 + +function! gitgutter#line_highlights_toggle() abort + if g:gitgutter_highlight_lines + call gitgutter#line_highlights_disable() + else + call gitgutter#line_highlights_enable() + endif +endfunction + +" }}} + +" Signs {{{ + +function! gitgutter#signs_enable() abort + let old_signs = g:gitgutter_signs + + let g:gitgutter_signs = 1 + call gitgutter#highlight#define_sign_text_highlights() + + if !old_signs && !g:gitgutter_highlight_lines + call gitgutter#all() + endif +endfunction + +function! gitgutter#signs_disable() abort + let g:gitgutter_signs = 0 + 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("\GitGutterStageHunk", -1) + 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."\" + else + execute "normal! ".z."\" + endif + endif + + silent! call repeat#set("\GitGutterUndoHunk", -1) + 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 + +" }}} diff --git a/sources_non_forked/vim-gitgutter/autoload/gitgutter/async.vim b/sources_non_forked/vim-gitgutter/autoload/gitgutter/async.vim new file mode 100644 index 00000000..070e00f8 --- /dev/null +++ b/sources_non_forked/vim-gitgutter/autoload/gitgutter/async.vim @@ -0,0 +1,113 @@ +let s:available = has('nvim') || ( + \ has('job') && ( + \ (has('patch-7-4-1826') && !has('gui_running')) || + \ (has('patch-7-4-1850') && has('gui_running')) || + \ (has('patch-7-4-1832') && has('gui_macvim')) + \ ) + \ ) + +function! gitgutter#async#available() + return s:available +endfunction + + +function! gitgutter#async#execute(cmd) abort + let options = { + \ 'stdoutbuffer': [], + \ 'buffer': gitgutter#utility#bufnr() + \ } + let command = s:build_command(a:cmd) + + if has('nvim') + call jobstart(command, extend(options, { + \ 'on_stdout': function('s:on_stdout_nvim'), + \ 'on_stderr': function('s:on_stderr_nvim'), + \ 'on_exit': function('s:on_exit_nvim') + \ })) + else + call job_start(command, { + \ 'out_cb': function('s:on_stdout_vim', options), + \ 'err_cb': function('s:on_stderr_vim', options), + \ 'close_cb': function('s:on_exit_vim', options) + \ }) + endif +endfunction + + +function! s:build_command(cmd) + if has('unix') + return ['sh', '-c', a:cmd] + endif + + if has('win32') + return has('nvim') ? ['cmd.exe', '/c', a:cmd] : 'cmd.exe /c '.a:cmd + endif + + throw 'unknown os' +endfunction + + +function! s:on_stdout_nvim(_job_id, data, _event) dict abort + if empty(self.stdoutbuffer) + let self.stdoutbuffer = a:data + else + let self.stdoutbuffer = self.stdoutbuffer[:-2] + + \ [self.stdoutbuffer[-1] . a:data[0]] + + \ a:data[1:] + endif +endfunction + +function! s:on_stderr_nvim(_job_id, _data, _event) dict abort + " Backward compatibility for nvim < 0.2.0 + 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 + +function! s:on_exit_nvim(_job_id, _data, _event) dict abort + " Backward compatibility for nvim < 0.2.0 + 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#handle_diff(gitgutter#utility#stringify(self.stdoutbuffer)) + 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 + + +function! s:on_stdout_vim(_channel, data) dict abort + call add(self.stdoutbuffer, a:data) +endfunction + +function! s:on_stderr_vim(_channel, _data) dict abort + call s:buffer_exec(self.buffer, function('gitgutter#hunk#reset')) +endfunction + +function! s:on_exit_vim(_channel) dict abort + call s:buffer_exec(self.buffer, function('gitgutter#handle_diff', [gitgutter#utility#stringify(self.stdoutbuffer)])) +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 diff --git a/sources_non_forked/vim-gitgutter/autoload/gitgutter/debug.vim b/sources_non_forked/vim-gitgutter/autoload/gitgutter/debug.vim new file mode 100644 index 00000000..594f044b --- /dev/null +++ b/sources_non_forked/vim-gitgutter/autoload/gitgutter/debug.vim @@ -0,0 +1,119 @@ +let s:plugin_dir = expand(':p:h:h:h').'/' +let s:log_file = s:plugin_dir.'gitgutter.log' +let s:channel_log = s:plugin_dir.'channel.log' +let s:new_log_session = 1 + + +function! gitgutter#debug#debug() + " Open a scratch buffer + vsplit __GitGutter_Debug__ + normal! ggdG + setlocal buftype=nofile + setlocal bufhidden=delete + setlocal noswapfile + + call gitgutter#debug#vim_version() + call gitgutter#debug#separator() + + call gitgutter#debug#git_version() + call gitgutter#debug#separator() + + call gitgutter#debug#grep_version() + call gitgutter#debug#separator() + + call gitgutter#debug#option('updatetime') + call gitgutter#debug#option('shell') + call gitgutter#debug#option('shellcmdflag') + call gitgutter#debug#option('shellpipe') + call gitgutter#debug#option('shellquote') + call gitgutter#debug#option('shellredir') + call gitgutter#debug#option('shellslash') + call gitgutter#debug#option('shelltemp') + call gitgutter#debug#option('shelltype') + call gitgutter#debug#option('shellxescape') + call gitgutter#debug#option('shellxquote') +endfunction + + +function! gitgutter#debug#separator() + call gitgutter#debug#output('') +endfunction + +function! gitgutter#debug#vim_version() + redir => version_info + silent execute 'version' + redir END + call gitgutter#debug#output(split(version_info, '\n')[0:2]) +endfunction + +function! gitgutter#debug#git_version() + let v = system(g:gitgutter_git_executable.' --version') + call gitgutter#debug#output( substitute(v, '\n$', '', '') ) +endfunction + +function! gitgutter#debug#grep_version() + let v = system('grep --version') + call gitgutter#debug#output( substitute(v, '\n$', '', '') ) + + let v = system('grep --help') + call gitgutter#debug#output( substitute(v, '\%x00', '', 'g') ) +endfunction + +function! gitgutter#debug#option(name) + if exists('+' . a:name) + let v = eval('&' . a:name) + call gitgutter#debug#output(a:name . '=' . v) + " redir => output + " silent execute "verbose set " . a:name . "?" + " redir END + " call gitgutter#debug#output(a:name . '=' . output) + else + call gitgutter#debug#output(a:name . ' [n/a]') + end +endfunction + +function! gitgutter#debug#output(text) + call append(line('$'), a:text) +endfunction + +" assumes optional args are calling function's optional args +function! gitgutter#debug#log(message, ...) abort + if g:gitgutter_log + if s:new_log_session && gitgutter#async#available() + if exists('*ch_logfile') + call ch_logfile(s:channel_log, 'w') + endif + endif + + execute 'redir >> '.s:log_file + if s:new_log_session + let s:start = reltime() + silent echo "\n==== start log session ====" + endif + + let elapsed = reltimestr(reltime(s:start)).' ' + silent echo '' + " callers excluding this function + silent echo elapsed.expand('')[:-22].':' + silent echo elapsed.s:format_for_log(a:message) + if a:0 && !empty(a:1) + for msg in a:000 + silent echo elapsed.s:format_for_log(msg) + endfor + endif + redir END + + let s:new_log_session = 0 + endif +endfunction + +function! s:format_for_log(data) abort + if type(a:data) == 1 + return join(split(a:data,'\n'),"\n") + elseif type(a:data) == 3 + return '['.join(a:data,"\n").']' + else + return a:data + endif +endfunction + diff --git a/sources_non_forked/vim-gitgutter/autoload/gitgutter/diff.vim b/sources_non_forked/vim-gitgutter/autoload/gitgutter/diff.vim new file mode 100644 index 00000000..2cf7acf9 --- /dev/null +++ b/sources_non_forked/vim-gitgutter/autoload/gitgutter/diff.vim @@ -0,0 +1,345 @@ +if exists('g:gitgutter_grep_command') + 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:c_flag = gitgutter#utility#git_supports_command_line_config_override() + +let s:temp_index = tempname() +let s:temp_buffer = tempname() + +" Returns a diff of the buffer. +" +" The way to get the diff depends on whether the buffer is saved or unsaved. +" +" * 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 +" +" The first instance is the file in the index which we obtain with: +" +" git show :myfile > myfileA +" +" The second instance is the buffer contents. Ideally we would pass this to +" 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 +" subsequent processing by the plugin. If grep is not available the plugin +" does the filtering instead. +function! gitgutter#diff#run_diff(realtime, preserve_full_diff) abort + " Wrap compound commands in parentheses to make Windows happy. + " bash doesn't mind the parentheses. + let cmd = '(' + + let bufnr = gitgutter#utility#bufnr() + let tracked = gitgutter#utility#getbufvar(bufnr, 'tracked', 0) " i.e. tracked by git + if !tracked + " Don't bother trying to realtime-diff an untracked file. + " NOTE: perhaps we should pull this guard up to the caller? + if a:realtime + throw 'diff failed' + else + let cmd .= g:gitgutter_git_executable.' ls-files --error-unmatch '.gitgutter#utility#shellescape(gitgutter#utility#filename()).' && (' + endif + endif + + if a:realtime + let blob_name = g:gitgutter_diff_base.':'.gitgutter#utility#shellescape(gitgutter#utility#file_relative_to_repo_root()) + let blob_file = s:temp_index + let buff_file = s:temp_buffer + let extension = gitgutter#utility#extension() + if !empty(extension) + let blob_file .= '.'.extension + let buff_file .= '.'.extension + endif + let cmd .= g:gitgutter_git_executable.' show '.blob_name.' > '.blob_file.' && ' + + " Writing the whole buffer resets the '[ and '] marks and also the + " 'modified' flag (if &cpoptions includes '+'). These are unwanted + " side-effects so we save and restore the values ourselves. + let modified = getbufvar(bufnr, "&mod") + let op_mark_start = getpos("'[") + let op_mark_end = getpos("']") + + execute 'keepalt noautocmd silent write!' buff_file + + call setbufvar(bufnr, "&mod", modified) + call setpos("'[", op_mark_start) + call setpos("']", op_mark_end) + endif + + let cmd .= g:gitgutter_git_executable + if s:c_flag + let cmd .= ' -c "diff.autorefreshindex=0"' + let cmd .= ' -c "diff.noprefix=false"' + endif + let cmd .= ' diff --no-ext-diff --no-color -U0 '.g:gitgutter_diff_args.' ' + + if a:realtime + let cmd .= ' -- '.blob_file.' '.buff_file + else + let cmd .= g:gitgutter_diff_base.' -- '.gitgutter#utility#shellescape(gitgutter#utility#filename()) + endif + + if !a:preserve_full_diff && s:grep_available + 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 as non-erroneous behaviour; so we OR the command with one + " which always exits with success (0). + let cmd .= ' || exit 0' + endif + + let cmd .= ')' + + if !tracked + let cmd .= ')' + endif + + let cmd = gitgutter#utility#command_in_directory_of_file(cmd) + + if g:gitgutter_async && gitgutter#async#available() && !a:preserve_full_diff + call gitgutter#async#execute(cmd) + return 'async' + + else + let diff = gitgutter#utility#system(cmd) + + if gitgutter#utility#shell_error() + " A shell error indicates the file is not tracked by git (unless something bizarre is going on). + throw 'diff failed' + endif + + return diff + endif +endfunction + +function! gitgutter#diff#parse_diff(diff) abort + let hunks = [] + for line in split(a:diff, '\n') + let hunk_info = gitgutter#diff#parse_hunk(line) + if len(hunk_info) == 4 + call add(hunks, hunk_info) + endif + endfor + return hunks +endfunction + +function! gitgutter#diff#parse_hunk(line) abort + let matches = matchlist(a:line, s:hunk_re) + if len(matches) > 0 + let from_line = str2nr(matches[1]) + let from_count = (matches[2] == '') ? 1 : str2nr(matches[2]) + let to_line = str2nr(matches[3]) + let to_count = (matches[4] == '') ? 1 : str2nr(matches[4]) + return [from_line, from_count, to_line, to_count] + else + return [] + end +endfunction + +function! gitgutter#diff#process_hunks(hunks) abort + let modified_lines = [] + for hunk in a:hunks + call extend(modified_lines, gitgutter#diff#process_hunk(hunk)) + endfor + return modified_lines +endfunction + +" Returns [ [, ], ...] +function! gitgutter#diff#process_hunk(hunk) abort + let modifications = [] + let from_line = a:hunk[0] + let from_count = a:hunk[1] + let to_line = a:hunk[2] + let to_count = a:hunk[3] + + if gitgutter#diff#is_added(from_count, to_count) + call gitgutter#diff#process_added(modifications, from_count, to_count, to_line) + call gitgutter#hunk#increment_lines_added(to_count) + + elseif gitgutter#diff#is_removed(from_count, to_count) + call gitgutter#diff#process_removed(modifications, from_count, to_count, to_line) + call gitgutter#hunk#increment_lines_removed(from_count) + + elseif gitgutter#diff#is_modified(from_count, to_count) + call gitgutter#diff#process_modified(modifications, from_count, to_count, to_line) + call gitgutter#hunk#increment_lines_modified(to_count) + + elseif gitgutter#diff#is_modified_and_added(from_count, to_count) + call gitgutter#diff#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_modified(from_count) + + elseif gitgutter#diff#is_modified_and_removed(from_count, to_count) + call gitgutter#diff#process_modified_and_removed(modifications, from_count, to_count, to_line) + call gitgutter#hunk#increment_lines_modified(to_count) + call gitgutter#hunk#increment_lines_removed(from_count - to_count) + + endif + return modifications +endfunction + +function! gitgutter#diff#is_added(from_count, to_count) abort + return a:from_count == 0 && a:to_count > 0 +endfunction + +function! gitgutter#diff#is_removed(from_count, to_count) abort + return a:from_count > 0 && a:to_count == 0 +endfunction + +function! gitgutter#diff#is_modified(from_count, to_count) abort + return a:from_count > 0 && a:to_count > 0 && a:from_count == a:to_count +endfunction + +function! gitgutter#diff#is_modified_and_added(from_count, to_count) abort + return a:from_count > 0 && a:to_count > 0 && a:from_count < a:to_count +endfunction + +function! gitgutter#diff#is_modified_and_removed(from_count, to_count) abort + return a:from_count > 0 && a:to_count > 0 && a:from_count > a:to_count +endfunction + +function! gitgutter#diff#process_added(modifications, from_count, to_count, to_line) abort + let offset = 0 + while offset < a:to_count + let line_number = a:to_line + offset + call add(a:modifications, [line_number, 'added']) + let offset += 1 + endwhile +endfunction + +function! gitgutter#diff#process_removed(modifications, from_count, to_count, to_line) abort + if a:to_line == 0 + call add(a:modifications, [1, 'removed_first_line']) + else + call add(a:modifications, [a:to_line, 'removed']) + endif +endfunction + +function! gitgutter#diff#process_modified(modifications, from_count, to_count, to_line) abort + let offset = 0 + while offset < a:to_count + let line_number = a:to_line + offset + call add(a:modifications, [line_number, 'modified']) + let offset += 1 + endwhile +endfunction + +function! gitgutter#diff#process_modified_and_added(modifications, from_count, to_count, to_line) abort + let offset = 0 + while offset < a:from_count + let line_number = a:to_line + offset + call add(a:modifications, [line_number, 'modified']) + let offset += 1 + endwhile + while offset < a:to_count + let line_number = a:to_line + offset + call add(a:modifications, [line_number, 'added']) + let offset += 1 + endwhile +endfunction + +function! gitgutter#diff#process_modified_and_removed(modifications, from_count, to_count, to_line) abort + let offset = 0 + while offset < a:to_count + let line_number = a:to_line + offset + call add(a:modifications, [line_number, 'modified']) + let offset += 1 + endwhile + let a:modifications[-1] = [a:to_line + offset - 1, 'modified_removed'] +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' + let diff_for_hunk = gitgutter#diff#adjust_hunk_summary(diff_for_hunk, a:type == 'stage') + 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 keep_line = a:keep_header + for line in split(a:diff, '\n') + let hunk_info = gitgutter#diff#parse_hunk(line) + if len(hunk_info) == 4 " start of new hunk + let keep_line = gitgutter#hunk#cursor_in_hunk(hunk_info) + endif + if keep_line + call add(modified_diff, line) + endif + endfor + + if a:keep_header + return gitgutter#utility#stringify(modified_diff) + else + " Discard hunk summary too. + return gitgutter#utility#stringify(modified_diff[1:]) + endif +endfunction + +" Adjust hunk summary (from's / to's line number) to ignore changes above/before this one. +" +" diff_for_hunk - a diff containing only the hunk of interest +" staging - truthy if the hunk is to be staged, falsy if it is to be undone +" +" TODO: push this down to #discard_hunks? +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 + call add(adj_diff, line) + endfor + return gitgutter#utility#stringify(adj_diff) +endfunction + diff --git a/sources_non_forked/vim-gitgutter/autoload/gitgutter/highlight.vim b/sources_non_forked/vim-gitgutter/autoload/gitgutter/highlight.vim new file mode 100644 index 00000000..61b0f307 --- /dev/null +++ b/sources_non_forked/vim-gitgutter/autoload/gitgutter/highlight.vim @@ -0,0 +1,115 @@ +function! gitgutter#highlight#define_sign_column_highlight() abort + if g:gitgutter_override_sign_column_highlight + highlight! link SignColumn LineNr + else + highlight default link SignColumn LineNr + endif +endfunction + +function! gitgutter#highlight#define_highlights() abort + let [guibg, ctermbg] = gitgutter#highlight#get_background_colors('SignColumn') + + " Highlights used by the signs. + + execute "highlight GitGutterAddDefault guifg=#009900 guibg=" . guibg . " ctermfg=2 ctermbg=" . ctermbg + execute "highlight GitGutterChangeDefault guifg=#bbbb00 guibg=" . guibg . " ctermfg=3 ctermbg=" . ctermbg + execute "highlight GitGutterDeleteDefault guifg=#ff2222 guibg=" . guibg . " ctermfg=1 ctermbg=" . ctermbg + highlight default link GitGutterChangeDeleteDefault GitGutterChangeDefault + + execute "highlight GitGutterAddInvisible guifg=bg guibg=" . guibg . " ctermfg=" . ctermbg . " ctermbg=" . ctermbg + execute "highlight GitGutterChangeInvisible guifg=bg guibg=" . guibg . " ctermfg=" . ctermbg . " ctermbg=" . ctermbg + execute "highlight GitGutterDeleteInvisible guifg=bg guibg=" . guibg . " ctermfg=" . ctermbg . " ctermbg=" . ctermbg + highlight default link GitGutterChangeDeleteInvisible GitGutterChangeInvisible + + highlight default link GitGutterAdd GitGutterAddDefault + highlight default link GitGutterChange GitGutterChangeDefault + highlight default link GitGutterDelete GitGutterDeleteDefault + highlight default link GitGutterChangeDelete GitGutterChangeDeleteDefault + + " Highlights used for the whole line. + + highlight default link GitGutterAddLine DiffAdd + highlight default link GitGutterChangeLine DiffChange + highlight default link GitGutterDeleteLine DiffDelete + highlight default link GitGutterChangeDeleteLine GitGutterChangeLine +endfunction + +function! gitgutter#highlight#define_signs() abort + sign define GitGutterLineAdded + sign define GitGutterLineModified + sign define GitGutterLineRemoved + sign define GitGutterLineRemovedFirstLine + sign define GitGutterLineModifiedRemoved + sign define GitGutterDummy + + call gitgutter#highlight#define_sign_text() + call gitgutter#highlight#define_sign_text_highlights() + call gitgutter#highlight#define_sign_line_highlights() +endfunction + +function! gitgutter#highlight#define_sign_text() abort + execute "sign define GitGutterLineAdded text=" . g:gitgutter_sign_added + execute "sign define GitGutterLineModified text=" . g:gitgutter_sign_modified + execute "sign define GitGutterLineRemoved text=" . g:gitgutter_sign_removed + execute "sign define GitGutterLineRemovedFirstLine text=" . g:gitgutter_sign_removed_first_line + execute "sign define GitGutterLineModifiedRemoved text=" . g:gitgutter_sign_modified_removed +endfunction + +function! gitgutter#highlight#define_sign_text_highlights() abort + " Once a sign's text attribute has been defined, it cannot be undefined or + " set to an empty value. So to make signs' text disappear (when toggling + " off or disabling) we make them invisible by setting their foreground colours + " to the background's. + if g:gitgutter_signs + sign define GitGutterLineAdded texthl=GitGutterAdd + sign define GitGutterLineModified texthl=GitGutterChange + sign define GitGutterLineRemoved texthl=GitGutterDelete + sign define GitGutterLineRemovedFirstLine texthl=GitGutterDelete + sign define GitGutterLineModifiedRemoved texthl=GitGutterChangeDelete + else + sign define GitGutterLineAdded texthl=GitGutterAddInvisible + sign define GitGutterLineModified texthl=GitGutterChangeInvisible + sign define GitGutterLineRemoved texthl=GitGutterDeleteInvisible + sign define GitGutterLineRemovedFirstLine texthl=GitGutterDeleteInvisible + sign define GitGutterLineModifiedRemoved texthl=GitGutterChangeDeleteInvisible + endif +endfunction + +function! gitgutter#highlight#define_sign_line_highlights() abort + if g:gitgutter_highlight_lines + sign define GitGutterLineAdded linehl=GitGutterAddLine + sign define GitGutterLineModified linehl=GitGutterChangeLine + sign define GitGutterLineRemoved linehl=GitGutterDeleteLine + sign define GitGutterLineRemovedFirstLine linehl=GitGutterDeleteLine + sign define GitGutterLineModifiedRemoved linehl=GitGutterChangeDeleteLine + else + sign define GitGutterLineAdded linehl= + sign define GitGutterLineModified linehl= + sign define GitGutterLineRemoved linehl= + sign define GitGutterLineRemovedFirstLine linehl= + sign define GitGutterLineModifiedRemoved linehl= + endif +endfunction + +function! gitgutter#highlight#get_background_colors(group) abort + redir => highlight + silent execute 'silent highlight ' . a:group + redir END + + let link_matches = matchlist(highlight, 'links to \(\S\+\)') + if len(link_matches) > 0 " follow the link + return gitgutter#highlight#get_background_colors(link_matches[1]) + endif + + let ctermbg = gitgutter#highlight#match_highlight(highlight, 'ctermbg=\([0-9A-Za-z]\+\)') + let guibg = gitgutter#highlight#match_highlight(highlight, 'guibg=\([#0-9A-Za-z]\+\)') + return [guibg, ctermbg] +endfunction + +function! gitgutter#highlight#match_highlight(highlight, pattern) abort + let matches = matchlist(a:highlight, a:pattern) + if len(matches) == 0 + return 'NONE' + endif + return matches[1] +endfunction diff --git a/sources_non_forked/vim-gitgutter/autoload/gitgutter/hunk.vim b/sources_non_forked/vim-gitgutter/autoload/gitgutter/hunk.vim new file mode 100644 index 00000000..5875e0a7 --- /dev/null +++ b/sources_non_forked/vim-gitgutter/autoload/gitgutter/hunk.vim @@ -0,0 +1,143 @@ +function! gitgutter#hunk#set_hunks(hunks) abort + call gitgutter#utility#setbufvar(gitgutter#utility#bufnr(), 'hunks', a:hunks) + call s:reset_summary() +endfunction + +function! gitgutter#hunk#hunks() abort + return gitgutter#utility#getbufvar(gitgutter#utility#bufnr(), 'hunks', []) +endfunction + +function! gitgutter#hunk#reset() abort + call gitgutter#utility#setbufvar(gitgutter#utility#bufnr(), 'hunks', []) + call s:reset_summary() +endfunction + + +function! gitgutter#hunk#summary(bufnr) abort + return gitgutter#utility#getbufvar(a:bufnr, 'summary', [0,0,0]) +endfunction + +function! s:reset_summary() abort + call gitgutter#utility#setbufvar(gitgutter#utility#bufnr(), 'summary', [0,0,0]) +endfunction + +function! gitgutter#hunk#increment_lines_added(count) abort + let bufnr = gitgutter#utility#bufnr() + let summary = gitgutter#hunk#summary(bufnr) + let summary[0] += a:count + call gitgutter#utility#setbufvar(bufnr, 'summary', summary) +endfunction + +function! gitgutter#hunk#increment_lines_modified(count) abort + let bufnr = gitgutter#utility#bufnr() + let summary = gitgutter#hunk#summary(bufnr) + let summary[1] += a:count + call gitgutter#utility#setbufvar(bufnr, 'summary', summary) +endfunction + +function! gitgutter#hunk#increment_lines_removed(count) abort + let bufnr = gitgutter#utility#bufnr() + let summary = gitgutter#hunk#summary(bufnr) + let summary[2] += a:count + call gitgutter#utility#setbufvar(bufnr, 'summary', summary) +endfunction + + +function! gitgutter#hunk#next_hunk(count) abort + if gitgutter#utility#is_active() + let current_line = line('.') + let hunk_count = 0 + for hunk in gitgutter#hunk#hunks() + if hunk[2] > current_line + let hunk_count += 1 + if hunk_count == a:count + execute 'normal!' hunk[2] . 'Gzv' + return + endif + endif + endfor + call gitgutter#utility#warn('No more hunks') + endif +endfunction + +function! gitgutter#hunk#prev_hunk(count) abort + if gitgutter#utility#is_active() + let current_line = line('.') + let hunk_count = 0 + for hunk in reverse(copy(gitgutter#hunk#hunks())) + if hunk[2] < current_line + let hunk_count += 1 + if hunk_count == a:count + let target = hunk[2] == 0 ? 1 : hunk[2] + execute 'normal!' target . 'Gzv' + return + endif + endif + endfor + call gitgutter#utility#warn('No previous hunks') + endif +endfunction + +" Returns the hunk the cursor is currently in or an empty list if the cursor +" isn't in a hunk. +function! gitgutter#hunk#current_hunk() abort + let current_hunk = [] + + for hunk in gitgutter#hunk#hunks() + if gitgutter#hunk#cursor_in_hunk(hunk) + let current_hunk = hunk + break + endif + endfor + + return current_hunk +endfunction + +function! gitgutter#hunk#cursor_in_hunk(hunk) abort + let current_line = line('.') + + if current_line == 1 && a:hunk[2] == 0 + return 1 + endif + + if current_line >= a:hunk[2] && current_line < a:hunk[2] + (a:hunk[3] == 0 ? 1 : a:hunk[3]) + return 1 + endif + + return 0 +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 + let hunk = gitgutter#hunk#current_hunk() + + if empty(hunk) + return + endif + + let [first_line, last_line] = [hunk[2], hunk[2] + hunk[3] - 1] + + if ! a:inner + let lnum = last_line + let eof = line('$') + while lnum < eof && empty(getline(lnum + 1)) + let lnum +=1 + endwhile + let last_line = lnum + endif + + execute 'normal! 'first_line.'GV'.last_line.'G' +endfunction diff --git a/sources_non_forked/vim-gitgutter/autoload/gitgutter/sign.vim b/sources_non_forked/vim-gitgutter/autoload/gitgutter/sign.vim new file mode 100644 index 00000000..cab3d65b --- /dev/null +++ b/sources_non_forked/vim-gitgutter/autoload/gitgutter/sign.vim @@ -0,0 +1,179 @@ +" Vim doesn't namespace sign ids so every plugin shares the same +" namespace. Sign ids are simply integers so to avoid clashes with other +" signs we guess at a clear run. +" +" Note also we currently never reset s:next_sign_id. +let s:first_sign_id = 3000 +let s:next_sign_id = s:first_sign_id +let s:dummy_sign_id = s:first_sign_id - 1 +" Remove-all-signs optimisation requires Vim 7.3.596+. +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#clear_signs() abort + 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') + call gitgutter#sign#remove_signs(sign_ids, 1) + call gitgutter#utility#setbufvar(bufnr, 'gitgutter_signs', {}) +endfunction + + +" Updates gitgutter's signs in the buffer being processed. +" +" modified_lines: list of [, ] +" where name = 'added|removed|modified|modified_removed' +function! gitgutter#sign#update_signs(modified_lines) abort + call gitgutter#sign#find_current_signs() + + 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 flicker_possible = s:remove_all_old_signs && !empty(a:modified_lines) + if flicker_possible + call gitgutter#sign#add_dummy_sign() + endif + + call gitgutter#sign#remove_signs(obsolete_signs, s:remove_all_old_signs) + call gitgutter#sign#upsert_new_gitgutter_signs(a:modified_lines) + + if flicker_possible + call gitgutter#sign#remove_dummy_sign(0) + endif +endfunction + + +function! gitgutter#sign#add_dummy_sign() abort + let bufnr = gitgutter#utility#bufnr() + if !gitgutter#utility#getbufvar(bufnr, 'dummy_sign') + execute "sign place" s:dummy_sign_id "line=" . 9999 "name=GitGutterDummy buffer=" . bufnr + call gitgutter#utility#setbufvar(bufnr, 'dummy_sign', 1) + endif +endfunction + +function! gitgutter#sign#remove_dummy_sign(force) abort + let bufnr = gitgutter#utility#bufnr() + if gitgutter#utility#getbufvar(bufnr, 'dummy_sign') && (a:force || !g:gitgutter_sign_column_always) + execute "sign unplace" s:dummy_sign_id "buffer=" . bufnr + call gitgutter#utility#setbufvar(bufnr, 'dummy_sign', 0) + endif +endfunction + + +" +" Internal functions +" + + +function! gitgutter#sign#find_current_signs() abort + let bufnr = gitgutter#utility#bufnr() + let gitgutter_signs = {} " : {'id': , 'name': } + let other_signs = [] " [ signs + silent execute "sign place buffer=" . bufnr + redir END + + for sign_line in filter(split(signs, '\n')[2:], 'v:val =~# "="') + " Typical sign line: line=88 id=1234 name=GitGutterLineAdded + " We assume splitting is faster than a regexp. + let components = split(sign_line) + let name = split(components[2], '=')[1] + if name =~# 'GitGutterDummy' + let dummy_sign_placed = 1 + else + let line_number = str2nr(split(components[0], '=')[1]) + if name =~# 'GitGutter' + let id = str2nr(split(components[1], '=')[1]) + " Remove orphaned signs (signs placed on lines which have been deleted). + " (When a line is deleted its sign lingers. Subsequent lines' signs' + " line numbers are decremented appropriately.) + if has_key(gitgutter_signs, line_number) + execute "sign unplace" gitgutter_signs[line_number].id + endif + let gitgutter_signs[line_number] = {'id': id, 'name': name} + else + call add(other_signs, line_number) + endif + end + endfor + + call gitgutter#utility#setbufvar(bufnr, 'dummy_sign', dummy_sign_placed) + call gitgutter#utility#setbufvar(bufnr, 'gitgutter_signs', gitgutter_signs) + call gitgutter#utility#setbufvar(bufnr, 'other_signs', other_signs) +endfunction + + +" Returns a list of [, ...] +" Sets `s:remove_all_old_signs` as a side-effect. +function! gitgutter#sign#obsolete_gitgutter_signs_to_remove(new_gitgutter_signs_line_numbers) abort + let bufnr = gitgutter#utility#bufnr() + let signs_to_remove = [] " list of [, ...] + let remove_all_signs = 1 + let old_gitgutter_signs = gitgutter#utility#getbufvar(bufnr, 'gitgutter_signs') + for line_number in keys(old_gitgutter_signs) + if index(a:new_gitgutter_signs_line_numbers, str2nr(line_number)) == -1 + call add(signs_to_remove, old_gitgutter_signs[line_number].id) + else + let remove_all_signs = 0 + endif + endfor + let s:remove_all_old_signs = remove_all_signs + return signs_to_remove +endfunction + + +function! gitgutter#sign#remove_signs(sign_ids, all_signs) abort + let bufnr = gitgutter#utility#bufnr() + if a:all_signs && s:supports_star && empty(gitgutter#utility#getbufvar(bufnr, 'other_signs')) + let dummy_sign_present = gitgutter#utility#getbufvar(bufnr, 'dummy_sign') + execute "sign unplace * buffer=" . bufnr + if dummy_sign_present + execute "sign place" s:dummy_sign_id "line=" . 9999 "name=GitGutterDummy buffer=" . bufnr + endif + else + for id in a:sign_ids + execute "sign unplace" id + endfor + endif +endfunction + + +function! gitgutter#sign#upsert_new_gitgutter_signs(modified_lines) abort + let bufnr = gitgutter#utility#bufnr() + let other_signs = gitgutter#utility#getbufvar(bufnr, 'other_signs') + let old_gitgutter_signs = gitgutter#utility#getbufvar(bufnr, 'gitgutter_signs') + + for line in a:modified_lines + let line_number = line[0] " + if index(other_signs, line_number) == -1 " don't clobber others' signs + let name = gitgutter#utility#highlight_name_for_change(line[1]) + if !has_key(old_gitgutter_signs, line_number) " insert + let id = gitgutter#sign#next_sign_id() + execute "sign place" id "line=" . line_number "name=" . name "buffer=" . bufnr + else " update if sign has changed + let old_sign = old_gitgutter_signs[line_number] + if old_sign.name !=# name + execute "sign place" old_sign.id "name=" . name "buffer=" . bufnr + end + endif + endif + endfor + " At this point b:gitgutter_gitgutter_signs is out of date. +endfunction + + +function! gitgutter#sign#next_sign_id() abort + let next_id = s:next_sign_id + let s:next_sign_id += 1 + return next_id +endfunction + + +" Only for testing. +function! gitgutter#sign#reset() + let s:next_sign_id = s:first_sign_id +endfunction diff --git a/sources_non_forked/vim-gitgutter/autoload/gitgutter/utility.vim b/sources_non_forked/vim-gitgutter/autoload/gitgutter/utility.vim new file mode 100644 index 00000000..e4bc774d --- /dev/null +++ b/sources_non_forked/vim-gitgutter/autoload/gitgutter/utility.vim @@ -0,0 +1,225 @@ +let s:file = '' +let s:using_xolox_shell = -1 +let s:exit_code = 0 + +function! gitgutter#utility#setbufvar(buffer, varname, val) + let dict = get(getbufvar(a:buffer, ''), 'gitgutter', {}) + let dict[a:varname] = a:val + call setbufvar(a:buffer, 'gitgutter', dict) +endfunction + +function! gitgutter#utility#getbufvar(buffer, varname, ...) + let dict = get(getbufvar(a:buffer, ''), 'gitgutter', {}) + if has_key(dict, a:varname) + return dict[a:varname] + else + if a:0 + return a:1 + endif + endif +endfunction + +function! gitgutter#utility#warn(message) abort + echohl WarningMsg + echo 'vim-gitgutter: ' . a:message + echohl None + let v:warningmsg = a:message +endfunction + +function! gitgutter#utility#warn_once(message, key) abort + if empty(gitgutter#utility#getbufvar(s:bufnr, a:key)) + call gitgutter#utility#setbufvar(s:bufnr, a:key, '1') + echohl WarningMsg + redraw | echo 'vim-gitgutter: ' . a:message + echohl None + let v:warningmsg = a:message + endif +endfunction + +" 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. +function! gitgutter#utility#is_active() abort + return g:gitgutter_enabled && + \ !pumvisible() && + \ gitgutter#utility#is_file_buffer() && + \ gitgutter#utility#exists_file() && + \ gitgutter#utility#not_git_dir() +endfunction + +function! gitgutter#utility#not_git_dir() abort + return gitgutter#utility#full_path_to_directory_of_file() !~ '[/\\]\.git\($\|[/\\]\)' +endfunction + +function! gitgutter#utility#is_file_buffer() abort + return empty(getbufvar(s:bufnr, '&buftype')) +endfunction + +" A replacement for the built-in `shellescape(arg)`. +" +" Recent versions of Vim handle shell escaping pretty well. However older +" versions aren't as good. This attempts to do the right thing. +" +" See: +" https://github.com/tpope/vim-fugitive/blob/8f0b8edfbd246c0026b7a2388e1d883d579ac7f6/plugin/fugitive.vim#L29-L37 +function! gitgutter#utility#shellescape(arg) abort + if a:arg =~ '^[A-Za-z0-9_/.-]\+$' + return a:arg + elseif &shell =~# 'cmd' || gitgutter#utility#using_xolox_shell() + return '"' . substitute(substitute(a:arg, '"', '""', 'g'), '%', '"%"', 'g') . '"' + else + return shellescape(a:arg) + endif +endfunction + +function! gitgutter#utility#set_buffer(bufnr) abort + let s:bufnr = a:bufnr + let s:file = resolve(bufname(a:bufnr)) +endfunction + +function! gitgutter#utility#bufnr() + return s:bufnr +endfunction + +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 + +function! gitgutter#utility#system(cmd, ...) abort + call gitgutter#debug#log(a:cmd, a:000) + + if gitgutter#utility#using_xolox_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) + endif + return output +endfunction + +function! gitgutter#utility#file_relative_to_repo_root() abort + let file_path_relative_to_repo_root = gitgutter#utility#getbufvar(s:bufnr, 'repo_relative_path') + if empty(file_path_relative_to_repo_root) + 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')) + let dir_path_relative_to_repo_root = gitgutter#utility#strip_trailing_new_line(dir_path_relative_to_repo_root) + let file_path_relative_to_repo_root = dir_path_relative_to_repo_root . gitgutter#utility#filename() + call gitgutter#utility#setbufvar(s:bufnr, 'repo_relative_path', file_path_relative_to_repo_root) + 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 +endfunction + +" Dedups list in-place. +" Assumes list has no empty entries. +function! gitgutter#utility#dedup(list) + return filter(sort(a:list), 'index(a:list, v:val, v:key + 1) == -1') +endfunction + +function! gitgutter#utility#strip_trailing_new_line(line) abort + return substitute(a:line, '\n$', '', '') +endfunction + +" True for git v1.7.2+. +function! gitgutter#utility#git_supports_command_line_config_override() abort + 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 diff --git a/sources_non_forked/vim-gitgutter/doc/gitgutter.txt b/sources_non_forked/vim-gitgutter/doc/gitgutter.txt new file mode 100644 index 00000000..0065d098 --- /dev/null +++ b/sources_non_forked/vim-gitgutter/doc/gitgutter.txt @@ -0,0 +1,341 @@ +*gitgutter.txt* A Vim plugin which shows a git diff in the gutter. + + + Vim Git Gutter + + +Author: Andy Stewart +Plugin Homepage: + +=============================================================================== +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* + *GitGutter* + +Vim Git Gutter is 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. + +This is a port of the Git Gutter plugin for Sublime Text 2. + +=============================================================================== +2. INSTALLATION *GitGutterInstallation* + +* Pathogen: +> + cd ~/.vim/bundle + git clone git://github.com/airblade/vim-gitgutter.git +< +* Voom: + +Edit your plugin manifest (`voom edit`) and add: +> + airblade/vim-gitgutter +< +* VimPlug: + +Place this in your .vimrc: +> + Plug 'airblade/vim-gitgutter' +< +Then run the following in Vim: +> + :source % + :PlugInstall +< +* NeoBundle: + +Place this in your .vimrc: +> + NeoBundle 'airblade/vim-gitgutter' +< +Then run the following in Vim: +> + :source % + :NeoBundleInstall +< +* No plugin manager: + +Copy vim-gitgutter's subdirectories into your vim configuration directory: +> + cd tmp && git clone git://github.com/airblade/vim-gitgutter.git + cp vim-gitgutter/* ~/.vim/ +< +See |add-global-plugin|. + +=============================================================================== +3. USAGE *GitGutterUsage* + +You don't have to do anything: it just works. + +=============================================================================== +4. COMMANDS *GitGutterCommands* + +Commands for turning Git Gutter on and off: + + :GitGutterDisable *:GitGutterDisable* + Explicitly turn Git Gutter off. + + :GitGutterEnable *:GitGutterEnable* + Explicitly turn Git Gutter on. + + :GitGutterToggle *:GitGutterToggle* + Explicitly turn Git Gutter on if it was off and vice versa. + + :GitGutter *:GitGutter* + Update signs for the current buffer. + + :GitGutterAll *:GitGutterAll* + Update signs across all buffers. + +Commands for turning signs on and off (defaults to on): + + :GitGutterSignsEnable *:GitGutterSignsEnable* + Explicitly turn line signs on. + + :GitGutterSignsDisable *:GitGutterSignsDisable* + Explicitly turn line signs off. + + :GitGutterSignsToggle *:GitGutterSignsToggle* + Explicitly turn line signs on if it was off and vice versa. + +Commands for turning line highlighting on and off (defaults to off): + + :GitGutterLineHighlightsEnable *:GitGutterLineHighlightsEnable* + Explicitly turn line highlighting on. + + :GitGutterLineHighlightsDisable *:GitGutterLineHighlightsDisable* + Explicitly turn line highlighting off. + + :GitGutterLineHighlightsToggle *:GitGutterLineHighlightsToggle* + Explicitly turn line highlighting on if it was off and vice versa. + +Commands for jumping between marked hunks: + + :GitGutterNextHunk *:GitGutterNextHunk* + Jump to the next marked hunk. Takes a count. + + :GitGutterPrevHunk *:GitGutterPrevHunk* + Jump to the previous marked hunk. Takes a count. + +Commands for staging or undoing individual hunks: + + :GitGutterStageHunk *:GitGutterStageHunk* + Stage the hunk the cursor is in. + + :GitGutterUndoHunk *:GitGutterUndoHunk* + Undo the hunk the cursor is in. + + :GitGutterPreviewHunk *:GitGutterPreviewHunk* + Preview the hunk the cursor is in. + Use |:pclose| or |CTRL-W_CTRL-Z| to close the preview window. + +=============================================================================== +5. AUTOCOMMAND *GitGutterAutocmd* + +After updating a buffer's signs vim-gitgutter fires a |User| |autocmd| with the +event GitGutter. You can listen for this event, for example: +> + autocmd User GitGutter call updateMyStatusLine() +< + +=============================================================================== +6. CUSTOMISATION *GitGutterCustomisation* + +You can customise: + +- The sign column's colours +- 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 +set in your colorscheme. + +SIGN COLUMN + +By default vim-gitgutter will 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 +leave it alone: +> + let g:gitgutter_override_sign_column_highlight = 0 +< + +And then either update your colorscheme's |hlSignColumn| highlight group or set +it in your |vimrc|: + + Desired appearance Command ~ + Same as line number column highlight clear SignColumn + User-defined (terminal Vim) highlight SignColumn ctermbg={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 +colorscheme or |vimrc|: + +> + GitGutterAdd " an added line + GitGutterChange " a changed line + GitGutterDelete " at least one removed line + GitGutterChangeDelete " a changed line followed by at least one removed line +< + +You can either set these with `highlight GitGutterAdd {key}={arg}...` or link +them to existing highlight groups with, say: +> + highlight link GitGutterAdd DiffAdd +< + +To customise the symbols, add the following to your |vimrc|: +> + 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|: +> + GitGutterAddLine " default: links to DiffAdd + GitGutterChangeLine " default: links to DiffChange + GitGutterDeleteLine " default: links to DiffDelete + 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 = '' +< + +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 GitGutterPrevHunk + nmap ]c GitGutterNextHunk +< + +To change the hunk-staging/undoing/previewing maps (defaults shown): +> + nmap hs GitGutterStageHunk + nmap hu GitGutterUndoHunk + nmap hp GitGutterPreviewHunk +< + +To change the hunk text object maps (defaults shown): +> + omap ic GitGutterTextObjectInnerPending + omap ac GitGutterTextObjectOuterPending + xmap ic GitGutterTextObjectInnerVisual + xmap ac 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* + +a. Why are the colours in the sign column weird? + + Your colorscheme is configuring the |hl-SignColumn| highlight group weirdly. + Please see |GitGutterCustomisation| on customising the sign column. + +b. 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. diff --git a/sources_non_forked/vim-gitgutter/plugin/gitgutter.vim b/sources_non_forked/vim-gitgutter/plugin/gitgutter.vim new file mode 100644 index 00000000..ad39bc17 --- /dev/null +++ b/sources_non_forked/vim-gitgutter/plugin/gitgutter.vim @@ -0,0 +1,238 @@ +scriptencoding utf-8 + +if exists('g:loaded_gitgutter') || !has('signs') || &cp + finish +endif +let g:loaded_gitgutter = 1 + +" Initialisation {{{ + +" Realtime sign updates require Vim 7.3.105+. +if v:version < 703 || (v:version == 703 && !has("patch105")) + let g:gitgutter_realtime = 0 +endif + +" Eager updates require gettabvar()/settabvar(). +if !exists("*gettabvar") + let g:gitgutter_eager = 0 +endif + +function! s:set(var, default) abort + if !exists(a:var) + if type(a:default) + execute 'let' a:var '=' string(a:default) + else + execute 'let' a:var '=' a:default + endif + endif +endfunction + +call s:set('g:gitgutter_enabled', 1) +call s:set('g:gitgutter_max_signs', 500) +call s:set('g:gitgutter_signs', 1) +call s:set('g:gitgutter_highlight_lines', 0) +call s:set('g:gitgutter_sign_column_always', 0) +if g:gitgutter_sign_column_always && exists('&signcolumn') + set signcolumn=yes + let g:gitgutter_sign_column_always = 0 + call gitgutter#utility#warn('please replace "let g:gitgutter_sign_column_always=1" with "set signcolumn=yes"') +endif +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_modified', '~') +call s:set('g:gitgutter_sign_removed', '_') +try + call s:set('g:gitgutter_sign_removed_first_line', '‾') +catch /E239/ + let g:gitgutter_sign_removed_first_line = '_^' +endtry + +call s:set('g:gitgutter_sign_modified_removed', '~_') +call s:set('g:gitgutter_diff_args', '') +call s:set('g:gitgutter_diff_base', '') +call s:set('g:gitgutter_map_keys', 1) +call s:set('g:gitgutter_avoid_cmd_prompt_on_windows', 1) +call s:set('g:gitgutter_async', 1) +call s:set('g:gitgutter_log', 0) +call s:set('g:gitgutter_git_executable', 'git') + +if !executable(g:gitgutter_git_executable) + call gitgutter#utility#warn('cannot find git. Please set g:gitgutter_git_executable.') +endif + +call gitgutter#highlight#define_sign_column_highlight() +call gitgutter#highlight#define_highlights() +call gitgutter#highlight#define_signs() + +" }}} + +" Primary functions {{{ + +command -bar GitGutterAll call gitgutter#all() +command -bar GitGutter call gitgutter#process_buffer(bufnr(''), 0) + +command -bar GitGutterDisable call gitgutter#disable() +command -bar GitGutterEnable call gitgutter#enable() +command -bar GitGutterToggle call gitgutter#toggle() + +" }}} + +" Line highlights {{{ + +command -bar GitGutterLineHighlightsDisable call gitgutter#line_highlights_disable() +command -bar GitGutterLineHighlightsEnable call gitgutter#line_highlights_enable() +command -bar GitGutterLineHighlightsToggle call gitgutter#line_highlights_toggle() + +" }}} + +" Signs {{{ + +command -bar GitGutterSignsEnable call gitgutter#signs_enable() +command -bar GitGutterSignsDisable call gitgutter#signs_disable() +command -bar GitGutterSignsToggle call gitgutter#signs_toggle() + +" }}} + +" Hunks {{{ + +command -bar -count=1 GitGutterNextHunk call gitgutter#hunk#next_hunk() +command -bar -count=1 GitGutterPrevHunk call gitgutter#hunk#prev_hunk() + +command -bar GitGutterStageHunk call gitgutter#stage_hunk() +command -bar GitGutterUndoHunk call gitgutter#undo_hunk() +command -bar GitGutterRevertHunk echomsg 'GitGutterRevertHunk is deprecated. Use GitGutterUndoHunk'call gitgutter#undo_hunk() +command -bar GitGutterPreviewHunk call gitgutter#preview_hunk() + +" Hunk text object +onoremap GitGutterTextObjectInnerPending :call gitgutter#hunk#text_object(1) +onoremap GitGutterTextObjectOuterPending :call gitgutter#hunk#text_object(0) +xnoremap GitGutterTextObjectInnerVisual :call gitgutter#hunk#text_object(1) +xnoremap GitGutterTextObjectOuterVisual :call gitgutter#hunk#text_object(0) + + +" Returns the git-diff hunks for the file or an empty list if there +" aren't any hunks. +" +" The return value is a list of lists. There is one inner list per hunk. +" +" [ +" [from_line, from_count, to_line, to_count], +" [from_line, from_count, to_line, to_count], +" ... +" ] +" +" where: +" +" `from` - refers to the staged file +" `to` - refers to the working tree's file +" `line` - refers to the line number where the change starts +" `count` - refers to the number of lines the change covers +function! GitGutterGetHunks() + return gitgutter#utility#is_active() ? gitgutter#hunk#hunks() : [] +endfunction + +" Returns an array that contains a summary of the hunk status for the current +" window. The format is [ added, modified, removed ], where each value +" represents the number of lines added/modified/removed respectively. +function! GitGutterGetHunkSummary() + return gitgutter#hunk#summary(winbufnr(0)) +endfunction + +" }}} + +command -bar GitGutterDebug call gitgutter#debug#debug() + +" Maps {{{ + +nnoremap GitGutterNextHunk &diff ? ']c' : ":\execute v:count1 . 'GitGutterNextHunk'\" +nnoremap GitGutterPrevHunk &diff ? '[c' : ":\execute v:count1 . 'GitGutterPrevHunk'\" + +if g:gitgutter_map_keys + if !hasmapto('GitGutterPrevHunk') && maparg('[c', 'n') ==# '' + nmap [c GitGutterPrevHunk + endif + if !hasmapto('GitGutterNextHunk') && maparg(']c', 'n') ==# '' + nmap ]c GitGutterNextHunk + endif +endif + + +nnoremap GitGutterStageHunk :GitGutterStageHunk +nnoremap GitGutterUndoHunk :GitGutterUndoHunk +nnoremap GitGutterPreviewHunk :GitGutterPreviewHunk + +if g:gitgutter_map_keys + if !hasmapto('GitGutterStageHunk') && maparg('hs', 'n') ==# '' + nmap hs GitGutterStageHunk + endif + if !hasmapto('GitGutterUndoHunk') && maparg('hu', 'n') ==# '' + nmap hu GitGutterUndoHunk + nmap hr GitGutterUndoHunk:echomsg 'hr is deprecated. Use hu' + endif + if !hasmapto('GitGutterPreviewHunk') && maparg('hp', 'n') ==# '' + nmap hp GitGutterPreviewHunk + endif + + if !hasmapto('GitGutterTextObjectInnerPending') && maparg('ic', 'o') ==# '' + omap ic GitGutterTextObjectInnerPending + endif + if !hasmapto('GitGutterTextObjectOuterPending') && maparg('ac', 'o') ==# '' + omap ac GitGutterTextObjectOuterPending + endif + if !hasmapto('GitGutterTextObjectInnerVisual') && maparg('ic', 'x') ==# '' + xmap ic GitGutterTextObjectInnerVisual + endif + if !hasmapto('GitGutterTextObjectOuterVisual') && maparg('ac', 'x') ==# '' + xmap ac GitGutterTextObjectOuterVisual + endif +endif + +" }}} + +" Autocommands {{{ + +augroup gitgutter + autocmd! + + if g:gitgutter_realtime + 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 * + \ if gettabvar(tabpagenr(), 'gitgutter_didtabenter') | + \ call settabvar(tabpagenr(), 'gitgutter_didtabenter', 0) | + \ call gitgutter#all() | + \ else | + \ call gitgutter#process_buffer(bufnr(''), 0) | + \ endif + + autocmd TabEnter * call settabvar(tabpagenr(), 'gitgutter_didtabenter', 1) + + " Ensure that all buffers are processed when opening vim with multiple files, e.g.: + " + " vim -o file1 file2 + autocmd VimEnter * if winnr() != winnr('$') | :GitGutterAll | endif + + if !has('gui_win32') + 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() + + " Disable during :vimgrep + autocmd QuickFixCmdPre *vimgrep* let g:gitgutter_enabled = 0 + autocmd QuickFixCmdPost *vimgrep* let g:gitgutter_enabled = 1 +augroup END + +" }}} + +" vim:set et sw=2 fdm=marker: diff --git a/sources_non_forked/vim-gitgutter/screenshot.png b/sources_non_forked/vim-gitgutter/screenshot.png new file mode 100644 index 00000000..6b50f839 Binary files /dev/null and b/sources_non_forked/vim-gitgutter/screenshot.png differ diff --git a/sources_non_forked/vim-gitgutter/test/fixture.txt b/sources_non_forked/vim-gitgutter/test/fixture.txt new file mode 100644 index 00000000..f5c6affe --- /dev/null +++ b/sources_non_forked/vim-gitgutter/test/fixture.txt @@ -0,0 +1,11 @@ +a +b +c +d +e +f +g +h +i +j + diff --git a/sources_non_forked/vim-gitgutter/test/runner.vim b/sources_non_forked/vim-gitgutter/test/runner.vim new file mode 100644 index 00000000..630693c4 --- /dev/null +++ b/sources_non_forked/vim-gitgutter/test/runner.vim @@ -0,0 +1,162 @@ +" +" Adapted from https://github.com/vim/vim/blob/master/src/testdir/runtest.vim +" +" When debugging tests it can help to write debug output: +" call Log('oh noes') +" + +function RunTest(test) + if exists("*SetUp") + call SetUp() + endif + + try + execute 'call '.a:test + catch + call Exception() + let s:errored = 1 + endtry + + if exists("*TearDown") + call TearDown() + endif +endfunction + +function Log(msg) + if type(a:msg) == type('') + call add(s:messages, a:msg) + elseif type(a:msg) == type([]) + call extend(s:messages, a:msg) + else + call add(v:errors, 'Exception: unsupported type: '.type(a:msg)) + endif +endfunction + +function Exception() + call add(v:errors, v:throwpoint.'..'.'Exception: '.v:exception) +endfunction + +" Shuffles list in place. +function Shuffle(list) + " Fisher-Yates-Durstenfeld-Knuth + let n = len(a:list) + if n < 2 + return a:list + endif + for i in range(0, n-2) + let j = Random(0, n-i-1) + let e = a:list[i] + let a:list[i] = a:list[i+j] + let a:list[i+j] = e + endfor + return a:list +endfunction + +" Returns a pseudorandom integer i such that 0 <= i <= max +function Random(min, max) + if has('unix') + let i = system('echo $RANDOM') " 0 <= i <= 32767 + else + let i = system('echo %RANDOM%') " 0 <= i <= 32767 + endif + return i * (a:max - a:min + 1) / 32768 + a:min +endfunction + +function FriendlyName(test_name) + return substitute(a:test_name[5:-3], '_', ' ', 'g') +endfunction + +function Align(left, right) + if type(a:right) == type([]) + let result = [] + for s in a:right + if empty(result) + call add(result, printf('%-'.s:indent.'S', a:left).s) + else + call add(result, printf('%-'.s:indent.'S', '').s) + endif + endfor + return result + endif + + return printf('%-'.s:indent.'S', a:left).a:right +endfunction + +let g:testname = expand('%') +let s:errored = 0 +let s:done = 0 +let s:fail = 0 +let s:errors = 0 +let s:messages = [] +let s:indent = '' + +call Log(g:testname.':') + +" Source the test script. +try + source % +catch + let s:errors += 1 + call Exception() +endtry + +" Locate the test functions. +set nomore +redir @q +silent function /^Test_ +redir END +let s:tests = split(substitute(@q, 'function \(\k*()\)', '\1', 'g')) + +" If there is another argument, filter test-functions' names against it. +if argc() > 1 + let s:tests = filter(s:tests, 'v:val =~ argv(1)') +endif + +let s:indent = max(map(copy(s:tests), {_, val -> len(FriendlyName(val))})) + +" Run the tests in random order. +for test in Shuffle(s:tests) + call RunTest(test) + let s:done += 1 + + let friendly_name = FriendlyName(test) + if len(v:errors) == 0 + call Log(Align(friendly_name, ' - ok')) + else + if s:errored + let s:errors += 1 + let s:errored = 0 + else + let s:fail += 1 + endif + call Log(Align(friendly_name, ' - not ok')) + + let i = 0 + for error in v:errors + if i != 0 + call Log(Align('',' ! ----')) + endif + for trace in reverse(split(error, '\.\.')) + call Log(Align('', ' ! '.trace)) + endfor + let i += 1 + endfor + + let v:errors = [] + endif +endfor + +let summary = [ + \ s:done.( s:done == 1 ? ' test' : ' tests'), + \ s:errors.(s:errors == 1 ? ' error' : ' errors'), + \ s:fail.( s:fail == 1 ? ' failure' : ' failures'), + \ ] +call Log('') +call Log(join(summary, ', ')) + +split messages.log +call append(line('$'), s:messages) +write + +qall! + diff --git a/sources_non_forked/vim-gitgutter/test/test b/sources_non_forked/vim-gitgutter/test/test new file mode 100644 index 00000000..6247a058 --- /dev/null +++ b/sources_non_forked/vim-gitgutter/test/test @@ -0,0 +1,19 @@ +#!/usr/bin/env bash + +VIM="/Applications/MacVim.app/Contents/MacOS/Vim -v" + +$VIM -u NONE -U NONE -N \ + --cmd 'set rtp+=../' \ + --cmd 'let g:gitgutter_async=0' \ + --cmd 'source ../plugin/gitgutter.vim' \ + -S runner.vim \ + test_*.vim \ + $* + +cat messages.log + +grep -q "0 errors, 0 failures" messages.log +status=$? +rm messages.log +exit $status + diff --git a/sources_non_forked/vim-gitgutter/test/test_gitgutter.vim b/sources_non_forked/vim-gitgutter/test/test_gitgutter.vim new file mode 100644 index 00000000..1a65ed8a --- /dev/null +++ b/sources_non_forked/vim-gitgutter/test/test_gitgutter.vim @@ -0,0 +1,400 @@ +let s:current_dir = expand('%:p:h') +let s:test_repo = s:current_dir.'/test-repo' +let s:bufnr = bufnr('') + +" +" Helpers +" + +function s:signs(filename) + redir => signs + silent execute 'sign place' + redir END + + let signs = split(signs, '\n') + + " filter out signs for this test file + " assumes a:filename's signs are last set listed + let i = index(signs, 'Signs for '.a:filename.':') + let signs = (i > -1 ? signs[i+1:] : []) + + call map(signs, {_, v -> substitute(v, ' ', '', '')}) + + return signs +endfunction + +function s:git_diff() + return split(system('git diff -U0 fixture.txt'), '\n') +endfunction + +function s:git_diff_staged() + return split(system('git diff -U0 --staged fixture.txt'), '\n') +endfunction + + +" +" SetUp / TearDown +" + +function SetUp() + call system("git init ".s:test_repo. + \ " && cd ".s:test_repo. + \ " && cp ../fixture.txt .". + \ " && git add . && git commit -m 'initial'") + execute ':cd' s:test_repo + edit! fixture.txt + call gitgutter#sign#reset() +endfunction + +function TearDown() + " delete all buffers except this one + " TODO: move to runner.vim, accounting for multiple test files + if s:bufnr > 1 + silent! execute '1,'.s:bufnr-1.'bdelete!' + endif + silent! execute s:bufnr+1.',$bdelete!' + + execute ':cd' s:current_dir + call system("rm -rf ".s:test_repo) +endfunction + +" +" The tests +" + +function Test_add_lines() + normal ggo* + write + + let expected = ["line=2 id=3000 name=GitGutterLineAdded"] + call assert_equal(expected, s:signs('fixture.txt')) +endfunction + + +function Test_add_lines_fish() + let _shell = &shell + set shell=/usr/local/bin/fish + + normal ggo* + write + + let expected = ["line=2 id=3000 name=GitGutterLineAdded"] + call assert_equal(expected, s:signs('fixture.txt')) + + let &shell = _shell +endfunction + + +function Test_modify_lines() + normal ggi* + write + + let expected = ["line=1 id=3000 name=GitGutterLineModified"] + call assert_equal(expected, s:signs('fixture.txt')) +endfunction + + +function Test_remove_lines() + execute '5d' + write + + let expected = ["line=4 id=3000 name=GitGutterLineRemoved"] + call assert_equal(expected, s:signs('fixture.txt')) +endfunction + + +function Test_remove_first_lines() + execute '1d' + write + + let expected = ["line=1 id=3000 name=GitGutterLineRemovedFirstLine"] + call assert_equal(expected, s:signs('fixture.txt')) +endfunction + + +function Test_edit_file_with_same_name_as_a_branch() + normal 5Gi* + call system('git checkout -b fixture.txt') + write + + let expected = ["line=5 id=3000 name=GitGutterLineModified"] + call assert_equal(expected, s:signs('fixture.txt')) +endfunction + + +function Test_file_added_to_git() + let tmpfile = 'fileAddedToGit.tmp' + call system('touch '.tmpfile.' && git add '.tmpfile) + execute 'edit '.tmpfile + normal ihello + write + + let expected = ["line=1 id=3000 name=GitGutterLineAdded"] + call assert_equal(expected, s:signs('fileAddedToGit.tmp')) +endfunction + + +function Test_filename_with_equals() + call system('touch =fixture=.txt && git add =fixture=.txt') + edit =fixture=.txt + normal ggo* + write + + let expected = [ + \ 'line=1 id=3000 name=GitGutterLineAdded', + \ 'line=2 id=3001 name=GitGutterLineAdded' + \ ] + call assert_equal(expected, s:signs('=fixture=.txt')) +endfunction + + +function Test_filename_with_square_brackets() + call system('touch fix[tu]re.txt && git add fix[tu]re.txt') + edit fix[tu]re.txt + normal ggo* + write + + let expected = [ + \ 'line=1 id=3000 name=GitGutterLineAdded', + \ 'line=2 id=3001 name=GitGutterLineAdded' + \ ] + call assert_equal(expected, s:signs('fix[tu]re.txt')) +endfunction + + +" FIXME: this test fails when it is the first (or only) test to be run +function Test_follow_symlink() + let tmp = 'symlink' + call system('ln -nfs fixture.txt '.tmp) + execute 'edit '.tmp + 6d + write + + let expected = ['line=5 id=3000 name=GitGutterLineRemoved'] + call assert_equal(expected, s:signs('symlink')) +endfunction + + +function Test_keep_alt() + enew + execute "normal! \" + + call assert_equal('fixture.txt', bufname('')) + call assert_equal('', bufname('#')) + + normal ggx + doautocmd CursorHold + + call assert_equal('', bufname('#')) +endfunction + + +function Test_keep_modified() + normal 5Go* + call assert_equal(1, getbufvar('', '&modified')) + + doautocmd CursorHold + + call assert_equal(1, getbufvar('', '&modified')) +endfunction + + +function Test_keep_op_marks() + normal 5Go* + call assert_equal([0,6,1,0], getpos("'[")) + call assert_equal([0,6,2,0], getpos("']")) + + doautocmd CursorHold + + call assert_equal([0,6,1,0], getpos("'[")) + call assert_equal([0,6,2,0], getpos("']")) +endfunction + + +function Test_no_modifications() + call assert_equal([], s:signs('fixture.txt')) +endfunction + + +function Test_orphaned_signs() + execute "normal 5GoX\Y" + write + 6d + write + + let expected = ['line=6 id=3001 name=GitGutterLineAdded'] + call assert_equal(expected, s:signs('fixture.txt')) +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() + let tmp = tempname() + call system('touch '.tmp) + execute 'edit '.tmp + + call assert_equal([], s:signs(tmp)) +endfunction + + +function Test_untracked_file_within_repo() + let tmp = 'untrackedFileWithinRepo.tmp' + call system('touch '.tmp) + execute 'edit '.tmp + normal ggo* + doautocmd CursorHold + + call assert_equal([], s:signs(tmp)) + + call system('rm '.tmp) +endfunction + + +function Test_untracked_file_square_brackets_within_repo() + let tmp = '[un]trackedFileWithinRepo.tmp' + call system('touch '.tmp) + execute 'edit '.tmp + normal ggo* + doautocmd CursorHold + + call assert_equal([], s:signs(tmp)) + + call system('rm '.tmp) +endfunction + + +function Test_hunk_outside_noop() + normal 5G + GitGutterStageHunk + + call assert_equal([], s:signs('fixture.txt')) + call assert_equal([], s:git_diff()) + call assert_equal([], s:git_diff_staged()) + + GitGutterUndoHunk + + call assert_equal([], s:signs('fixture.txt')) + call assert_equal([], s:git_diff()) + call assert_equal([], s:git_diff_staged()) +endfunction + + +function Test_hunk_stage() + let _shell = &shell + set shell=foo + + normal 5Gi* + GitGutterStageHunk + + call assert_equal('foo', &shell) + let &shell = _shell + + call assert_equal([], s:signs('fixture.txt')) + + call assert_equal([], s:git_diff()) + + let expected = [ + \ 'diff --git a/fixture.txt b/fixture.txt', + \ 'index f5c6aff..ae8e546 100644', + \ '--- a/fixture.txt', + \ '+++ b/fixture.txt', + \ '@@ -5 +5 @@ d', + \ '-e', + \ '+*e' + \ ] + call assert_equal(expected, s:git_diff_staged()) +endfunction + + +function Test_hunk_stage_nearby_hunk() + execute "normal! 2Gox\y\z" + normal 2jdd + normal k + GitGutterStageHunk + + let expected = [ + \ 'line=3 id=3000 name=GitGutterLineAdded', + \ 'line=4 id=3001 name=GitGutterLineAdded', + \ 'line=5 id=3002 name=GitGutterLineAdded' + \ ] + call assert_equal(expected, s:signs('fixture.txt')) + + let expected = [ + \ 'diff --git a/fixture.txt b/fixture.txt', + \ 'index 53b13df..8fdfda7 100644', + \ '--- a/fixture.txt', + \ '+++ b/fixture.txt', + \ '@@ -2,0 +3,3 @@ b', + \ '+x', + \ '+y', + \ '+z', + \ ] + 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 + + +function Test_hunk_undo() + let _shell = &shell + set shell=foo + + normal 5Gi* + GitGutterUndoHunk + write " write file so we can verify git diff (--staged) + + call assert_equal('foo', &shell) + let &shell = _shell + + call assert_equal([], s:signs('fixture.txt')) + call assert_equal([], s:git_diff()) + call assert_equal([], s:git_diff_staged()) +endfunction + + +function Test_undo_nearby_hunk() + execute "normal! 2Gox\y\z" + normal 2jdd + normal k + GitGutterUndoHunk + write " write file so we can verify git diff (--staged) + + let expected = [ + \ 'line=3 id=3000 name=GitGutterLineAdded', + \ 'line=4 id=3001 name=GitGutterLineAdded', + \ 'line=5 id=3002 name=GitGutterLineAdded' + \ ] + call assert_equal(expected, s:signs('fixture.txt')) + + let expected = [ + \ 'diff --git a/fixture.txt b/fixture.txt', + \ 'index f5c6aff..3fbde56 100644', + \ '--- a/fixture.txt', + \ '+++ b/fixture.txt', + \ '@@ -2,0 +3,3 @@ b', + \ '+x', + \ '+y', + \ '+z', + \ ] + call assert_equal(expected, s:git_diff()) + + call assert_equal([], s:git_diff_staged()) +endfunction diff --git a/sources_non_forked/vim-go/.dockerignore b/sources_non_forked/vim-go/.dockerignore new file mode 100644 index 00000000..2d2ecd68 --- /dev/null +++ b/sources_non_forked/vim-go/.dockerignore @@ -0,0 +1 @@ +.git/ diff --git a/sources_non_forked/vim-go/.editorconfig b/sources_non_forked/vim-go/.editorconfig new file mode 100644 index 00000000..2c222811 --- /dev/null +++ b/sources_non_forked/vim-go/.editorconfig @@ -0,0 +1,17 @@ +# http://EditorConfig.org + +root = true + +[*] +charset = utf-8 +indent_style = space +indent_size = 2 +trim_trailing_whitespace = true + +[*.go] +indent_style = tab +indent_size = 4 + +[Makefile] +indent_style = tab +indent_size = 8 diff --git a/sources_non_forked/vim-go/.github/CONTRIBUTING.md b/sources_non_forked/vim-go/.github/CONTRIBUTING.md index 7266ccea..edabf915 100644 --- a/sources_non_forked/vim-go/.github/CONTRIBUTING.md +++ b/sources_non_forked/vim-go/.github/CONTRIBUTING.md @@ -1,9 +1,12 @@ Thanks for improving vim-go! Before you dive in please read the following: 1. Please read our - [FAQ](https://github.com/fatih/vim-go/wiki/FAQ-Troubleshooting), it might - have answers for your problem -2. If you add a new feature please don't forget to update the documentation: - [doc/vim-go.txt](doc/vim-go.txt) -3. If it's a breaking change or exceed +100 lines please open an issue first - and describe the changes you want to make. + [Documentation](https://github.com/fatih/vim-go/blob/master/doc/vim-go.txt), + it might have a solution to your problem. +2. If you add a new feature then please don't forget to update the documentation: + [doc/vim-go.txt](https://github.com/fatih/vim-go/blob/master/doc/vim-go.txt). +3. If it's a breaking change or exceeds 100 lines of code then please open an + issue first and describe the changes you want to make. +4. See `:help go-development` for instructions on how to run and write tests. If + you add a new feature be sure you also include a test if feasible. + diff --git a/sources_non_forked/vim-go/.github/ISSUE_TEMPLATE.md b/sources_non_forked/vim-go/.github/ISSUE_TEMPLATE.md index 0adaff3c..dd376ee8 100644 --- a/sources_non_forked/vim-go/.github/ISSUE_TEMPLATE.md +++ b/sources_non_forked/vim-go/.github/ISSUE_TEMPLATE.md @@ -1,28 +1,22 @@ -### Actual behavior +### What did you do? (required. The issue will be **closed** when not provided.) -Write here what's happening ... -### Expected behavior +### What did you expect to happen? -Write here what you're expecting ... -### Steps to reproduce: +### What happened instead? -Please create a reproducible case of your problem. Re produce it -with a minimal `vimrc` with all plugins disabled and only `vim-go` -enabled: -1. -2. -3. +### Configuration (**MUST** fill this out): -### Configuration +* Vim version (first two lines from `:version`): -Add here your current configuration and additional information that might be -useful, such as: +* Go version (`go version`): + +* Go environment (`go env`): + +* vim-go version: + +* `vimrc` you used to reproduce (use a *minimal* vimrc with other plugins disabled; do not link to a 2,000 line vimrc): -* `vimrc` you used to reproduce -* vim version: -* vim-go version -* go version diff --git a/sources_non_forked/vim-go/.gitignore b/sources_non_forked/vim-go/.gitignore index 926ccaaf..bdeb2b82 100644 --- a/sources_non_forked/vim-go/.gitignore +++ b/sources_non_forked/vim-go/.gitignore @@ -1 +1,2 @@ doc/tags +.DS_Store diff --git a/sources_non_forked/vim-go/.travis.yml b/sources_non_forked/vim-go/.travis.yml new file mode 100644 index 00000000..26b0ce00 --- /dev/null +++ b/sources_non_forked/vim-go/.travis.yml @@ -0,0 +1,14 @@ +language: go +notifications: + email: false +matrix: + include: + - env: SCRIPT=test VIM_VERSION=vim-7.4 + - env: SCRIPT=test VIM_VERSION=vim-8.0 + - env: SCRIPT=test VIM_VERSION=nvim + - env: SCRIPT=lint VIM_VERSION=vim-8.0 +install: + - ./scripts/install-vim $VIM_VERSION + - pip install --user vim-vint +script: + - ./scripts/$SCRIPT $VIM_VERSION diff --git a/sources_non_forked/vim-go/.vintrc.yaml b/sources_non_forked/vim-go/.vintrc.yaml new file mode 100644 index 00000000..32d7decf --- /dev/null +++ b/sources_non_forked/vim-go/.vintrc.yaml @@ -0,0 +1,7 @@ +policies: + ProhibitUnnecessaryDoubleQuote: + enabled: false + ProhibitEqualTildeOperator: + enabled: false + ProhibitNoAbortFunction: + enabled: false diff --git a/sources_non_forked/vim-go/CHANGELOG.md b/sources_non_forked/vim-go/CHANGELOG.md index 61b46cd9..fce348d0 100644 --- a/sources_non_forked/vim-go/CHANGELOG.md +++ b/sources_non_forked/vim-go/CHANGELOG.md @@ -1,14 +1,563 @@ -## 1.8 (unplanned) +## unplanned + +BACKWARDS INCOMPATIBILITIES: + +* Display a warning for Vim versions older than 7.4.1689. Older versions may + still work, but are not supported. You can use `let g:go_version_warning = 0` + to disable the warning. + [[GH-1524]](https://github.com/fatih/vim-go/pull/1524). + +BUG FIXES: + +* Fix compatibility with Vim version before 7.4.1546 + [[GH-1498]](https://github.com/fatih/vim-go/pull/1498). +* Don't resize godoc window if it's already visible + [[GH-1488]](https://github.com/fatih/vim-go/pull/1488). +* `:GoTestCompile` produces a test binary again. The test binary will be + written to a temporary directory to avoid polluting the user's working + directory. [[GH-1519]](https://github.com/fatih/vim-go/pull/1519) +* Fix incorrect `:GoSameIdsToggle` behavior when there were match groups + present, but none were goSameId. + [[GH-1538]](https://github.com/fatih/vim-go/pull/1538) +* Fix `gpl` snippet for UltiSnips. + [[GH-1535]](https://github.com/fatih/vim-go/pull/1535) +* Fix test output processing to correctly handle panics and log statements. + [[GH-1513]](https://github.com/fatih/vim-go/pull/1513) IMPROVEMENTS: -* `:GoDoc` accepts arguments now which are passed directly to `godoc`. So usages like `:GoDoc flag` works again (it was changed in previous versions [gh-894] +* `:GoRename` is a bit smarter when automatically pre-filling values, and what + gets pre-filled can be configured with `g:go_gorename_prefill` option. + In addition `:GoRename ` now lists some common options. + [[GH-1465]](https://github.com/fatih/vim-go/pull/1465). +* Disable `g:go_autodetect_gopath` by default. [[GH-1461]](https://github.com/fatih/vim-go/pull/1461). +* Add support for `g:go_build_tags` to the `:GoTest` family of functions. + [[GH-1562]](https://github.com/fatih/vim-go/pull/1562). +* Pass `--tests` to gometalinter when autosaving and when a custom gometalinter + command has not been set. + [[GH-1563]](https://github.com/fatih/vim-go/pull/1563). +* Do not spam messages when command is run in a directory that does not exist. + [[GH-1527]](https://github.com/fatih/vim-go/pull/1527). +* New setting `g:go_test_prepend_name` (off by default) to add the failing test + name to the output of `:GoTest` + [[GH-1578]](https://github.com/fatih/vim-go/pull/1578). + +## 1.15 - (October 3, 2017) + +FEATURES: + +* Add `:GoFillStruct` to fill a struct with all fields; uses + [`fillstruct`](https://github.com/davidrjenni/reftools/tree/master/cmd/fillstruct) + [[GH-1443]](https://github.com/fatih/vim-go/pull/1443). + +IMPROVEMENTS: + +* `:GoAddTags` and `:GoRemoveTags` now continue to process if there are + malformed individual struct tags (run `:GoUpdateBinaries` to update + `gomodifiytags` binary) [[GH-1401]](https://github.com/fatih/vim-go/pull/1401) +* `:GoAddTags` and `:GoRemoveTags` now shows a location list if there are + malformed struct tags (run `:GoUpdateBinaries` to update `gomodifiytags` + binary) [[GH-1401]](https://github.com/fatih/vim-go/pull/1401) +* Add folding of the package-level comment (enabled by default) and/or any + other comments (disabled by default) [[GH-1377]](https://github.com/fatih/vim-go/pull/1377). + [[GH-1428]](https://github.com/fatih/vim-go/pull/1428). +* Allow using :GoImpl on the type and struct parts too. Makes it a wee bit + easier to use [[GH-1386]](https://github.com/fatih/vim-go/pull/1386) +* `:GoDef` sets the path of new buffers as relative to the current directory + when appropriate, instead of always using the full path [[GH-1277]](https://github.com/fatih/vim-go/pull/1277). +* Syntax highlighting for variable declarations and assignments (disabled by default) + [[GH-1426]](https://github.com/fatih/vim-go/pull/1426) and + [[GH-1458]](https://github.com/fatih/vim-go/pull/1458). +* Add support for `:GoDecls[Dir]` in [unite.vim](https://github.com/Shougo/unite.vim) + [[GH-1391]](https://github.com/fatih/vim-go/pull/1391). +* Add support for [fzf.vim](https://github.com/junegunn/fzf.vim) in + `GoDecls[Dir]`. + [[GH-1437]](https://github.com/fatih/vim-go/pull/1437). +* Support relative imports for `:GoImpl` [[GH-1322]](https://github.com/fatih/vim-go/pull/1322). +* A new `g:go_list_type_commands` setting is added to individually set the list type for each command [[GH-1415]](https://github.com/fatih/vim-go/pull/1415). As en example: + + let g:go_list_type_commands = {"GoBuild": "quickfix", "GoTest": "locationlist"} +* Show unexpected errors better by expanding newlines and tabs + [[GH-1456]](https://github.com/fatih/vim-go/pull/1456). +* `:GoInstallBinaries` and `:GoUpdateBinaries` can now install/update only the + selected binaries (e.g. `:GoUpdateBinaries guru golint`) + [[GH-1467]](https://github.com/fatih/vim-go/pull/1467). + +BUG FIXES: + +* `:GoFmt` now (again) uses `locationlist` to show formatting errors instead of + `quickfix`. To change back to `locationlist` you can change it with the + setting `let g:go_list_type_commands = { "GoFmt": locationlist" }` [[GH-1415]](https://github.com/fatih/vim-go/pull/1415) +* Include comments in import block when folding is enabled [[GH-1387]](https://github.com/fatih/vim-go/pull/1387) +* Fix opening definitions in tabs [[GH-1400]](https://github.com/fatih/vim-go/pull/1400) +* Fix accidentally closing quickfix window from other commands if :GoFmt or autosave format was called [[GH-1407]](https://github.com/fatih/vim-go/pull/1407) +* Fix entering into insert mode after for term mode in nvim [[GH-1411]](https://github.com/fatih/vim-go/pull/1411) +* When using :GoImpl on type foo struct{} it would work, but with: + + type foo struct{ + } + + or with a struct with fields, it would create the generated methods inside the + struct [[GH-1386]](https://github.com/fatih/vim-go/pull/1386) +* `:GoImpl` output would include extra newline, and error would include + trailing newline from shell command: `vim-go: invalid receiver: "} *}"<00>`. + Fixed with [[GH-1386]](https://github.com/fatih/vim-go/pull/1386) +* Run `:GoMetaLinter` against the package of the open file [[GH-1414]](https://github.com/fatih/vim-go/pull/1414). +* The `g:go_doc_command` and `g:go_doc_options` to configure the command for + `:GoDoc` were documented but never referenced [[GH-1420]](https://github.com/fatih/vim-go/pull/1420). +* `go#package#FromPath()` didn't work correctly [[GH-1435]](https://github.com/fatih/vim-go/pull/1435). +* Fix race condition for `guru` based commands [[GH-1439]](https://github.com/fatih/vim-go/pull/1439). +* The `gohtmltmpl` filetype now sources the `html` ftplugin, so that `matchit`, + completion, and some other things work better. + [[GH-1442]](https://github.com/fatih/vim-go/pull/1442) +* Fix `:GoBuild` shell escaping [[GH-1450]](https://github.com/fatih/vim-go/pull/1450). +* Ensure fmt list gets closed when title cannot be checked [[GH-1474]](https://github.com/fatih/vim-go/pull/1474). + +BACKWARDS INCOMPATIBILITIES: + +* `:GoMetaLinter` now runs against the package of the open file instead of the + current working directory. This is so all commands behave the same relative + to the current open buffer. [[GH-1414]](https://github.com/fatih/vim-go/pull/1414) + +* `:GoImpl` now requires [`impl`](https://github.com/josharian/impl) version + 3fb19c2c or newer (released June 13, 2017); use `:GoUpdateBinaries` to make + sure that you've got a recent version [[GH-1322]](https://github.com/fatih/vim-go/pull/1322) + +## 1.14 - (August 6, 2017) + +FEATURES: + +* We now have folding support based on Go syntax. To enable it you have to set + the following Vim setting: `set foldmethod=syntax`. Currently it folds blocks + (`{ }`), `import`, `var`, and `const` blocks, and package-level comments. + These can be individually disabled/enabled if desired. For more info please + read the documentation for the `g:go_fold_enable` setting. [[GH-1339]](https://github.com/fatih/vim-go/pull/1339) + [[GH-1377]](https://github.com/fatih/vim-go/pull/1377) +* `:GoFiles` accepts now an argument to change the type of files it can show. + By default it shows`.go source files` but now it can be changed to show + various kind of files. The full list can be seen via `go list --help` under + the `// Source Files` section [[GH-1372]](https://github.com/fatih/vim-go/pull/1372) i.e: + +``` +:GoFiles CgoFiles // shows .go sources files that import "C" +:GoFiles TestGoFiles // shows _test.go files in package +:GoFiles IgnoredGoFiles // shows .go sources ignored due to build constraints +etc.. +``` + +IMPROVEMENTS + +* Files created with `_test.go` extension have a new template with a ready to + go test function. The template can be changed with the + `g:go_template_test_file` setting. [[GH-1318]](https://github.com/fatih/vim-go/pull/1318) +* Improve performance for highly used operations by caching `go env` calls [[GH-1320]](https://github.com/fatih/vim-go/pull/1320) +* `:GoCoverage` can accept arguments now. i.e: `:GoCoverage -run TestFoo` [[GH-1326]](https://github.com/fatih/vim-go/pull/1326) +* `:GoDecls` and `:GoDeclsDir` shows a warning if [ctrlp.vim](https://github.com/ctrlpvim/ctrlp.vim) is not installed +* `:GoBuild` now compiles the package with the `-i` flag added. This means that subsequent calls are much more faster due caching of packages [[GH-1330]](https://github.com/fatih/vim-go/pull/1330) +* `:GoCoverage` echos now the progress if `g:go_echo_command_info` is enabled [[GH-1333]](https://github.com/fatih/vim-go/pull/1333) +* Add `g:go_doc_max_height` setting to control the maximum height of the window created by `:GoDoc` and `K` mapping [[GH-1335]](https://github.com/fatih/vim-go/pull/1335) +* The `af` text object is able to include the assignment variable for anonymous functions. Can be disabled with `g:go_textobj_include_variable = 0` [[GH-1345]](https://github.com/fatih/vim-go/pull/1345) +* Add `g:go_list_autoclose` setting to prevent closing the quickfix/location list after zero items [[GH-1361]](https://github.com/fatih/vim-go/pull/1361) +* Cursor is now adjusted and locked to the correct line when `goimports` is used for autosave [[GH-1367]](https://github.com/fatih/vim-go/pull/1367) +* Complement the path of command for different situations of Cygwin environment [[GH-1394]](https://github.com/fatih/vim-go/pull/1394) +* Show message when using :GoDef and opening a new buffer [[GH-1385]](https://github.com/fatih/vim-go/pull/1385) BUG FIXES: -* Escape `#` characters when opening URL's, as it's handled as alternative file in vim [gh-895] -* Fix typos in `doc/vim-go.txt` about usages of syntax highglightings [gh-897] +* Fix obtaining package's import path for the current directory. This fixes some issues we had if the user was using multiple GOPATH's [[GH-1321]](https://github.com/fatih/vim-go/pull/1321) +* Fix documentation for vim-go & syntastic integration for errcheck using [[GH-1323]](https://github.com/fatih/vim-go/pull/1323) +* Fix showing an output if a test has finished when `:GoTest` is called [[GH-1327]](https://github.com/fatih/vim-go/pull/1327) +* Fix warning when goimports doesn't support srcdir [[GH-1344]](https://github.com/fatih/vim-go/pull/1344) +* Fix broken code folding with go_highlight_types [[GH-1338]](https://github.com/fatih/vim-go/pull/1338) +* Fix blocking the ui when swapfile is enabled and `:GoFmt` is called (either manually or via autosave) [[GH-1362]](https://github.com/fatih/vim-go/pull/1362) +* Fix getting bin paths for binaries if GOPATH was not set and Go version =>1.7 was used [[GH-1363]](https://github.com/fatih/vim-go/pull/1363) +* Fix picking up the correct list type for showing `:GoFmt` errors [[GH-1365]](https://github.com/fatih/vim-go/pull/1365) +* Fix auto detecting of GOPATH for import paths with string 'src' (i.e: `GOPATH/src/github.com/foo/src/bar`) [[GH-1366]](https://github.com/fatih/vim-go/pull/1366) +* Fix showing an empty window if `gogetdoc` was not found [[GH-1379]](https://github.com/fatih/vim-go/pull/1379) +* Fix commands not being executed if paths would include spaces (binary name, GOPATH, file itself, etc..) [[GH-1374]](https://github.com/fatih/vim-go/pull/1374) +* Fix showing correct message when editing a new file [[GH-1371]](https://github.com/fatih/vim-go/pull/1371) +* Fix filepaths in the quickfix list for :GoVet [[GH-1381]](https://github.com/fatih/vim-go/pull/1381) +* Run :GoLint against the package of the open file [[GH-1382]](https://github.com/fatih/vim-go/pull/1382) + +BACKWARDS INCOMPATIBILITIES: + +* `:GoFmt` now uses `quickfix` to show formatting errors instead of + `locationlist`. To change back to `locationlist` you can change it with the + setting `let g:go_list_type = "locationlist"` [[GH-1365]](https://github.com/fatih/vim-go/pull/1365) +* `:GoLint` now runs against the package of the open file instead of the + current working directory. This is so all commands behave the same relative + to the current open buffer. For more info check the [comment + here](https://github.com/fatih/vim-go/issues/1375#issuecomment-317535953) + [[GH-1382]](https://github.com/fatih/vim-go/pull/1382) + + + +## 1.13 - (June 6, 2017) + +FEATURES: + +* New `:GoKeyify` command that turns unkeyed struct literals into keyed struct literals. [[GH-1258]](https://github.com/fatih/vim-go/pull/1258). i.e: + +``` +Example{"foo", "bar", "qux"} +``` + +will be converted to: + +``` +Example{ + foo: "foo", + bar: "bar", + qux: "qux", +} +``` + +Checkout the demo here: https://twitter.com/fatih/status/860410299714764802 + + +* New `g:go_addtags_transform` setting to change the transform rule (snakecase, camelcase, etc..) for `:GoAddTags` command [[GH-1275]](https://github.com/fatih/vim-go/pull/1275) +* New snippet shortcut assigned to `ife` that expands to `if err := foo(); err != nil { ... }` [[GH-1268]](https://github.com/fatih/vim-go/pull/1268) + +IMPROVEMENTS + +* :GoMetaLinter can now exclude linters with the new `g:go_metalinter_excludes` option [[GH-1253]](https://github.com/fatih/vim-go/pull/1253) +* Override `` mapping so `:GoDef` is used by default (as we do the same for `CTRL-]`, `gd`, etc. [[GH-1264]](https://github.com/fatih/vim-go/pull/1264) +* add support for `go_list_type` setting in `:GoFmt` and `:GoImports` commands [[GH-1304]](https://github.com/fatih/vim-go/pull/1304) +* add support for `go_list_type` setting in `:GoMetaLinter` commands [[GH-1309]](https://github.com/fatih/vim-go/pull/1309) +* `go_fmt_options` can be now a dictionary to allow us to specifcy the + options for multiple binaries [[GH-1308]](https://github.com/fatih/vim-go/pull/1308). i.e: + +``` + let g:go_fmt_options = { + \ 'gofmt': '-s', + \ 'goimports': '-local mycompany.com', + \ } +``` +* If win-vim(x64) with Cygwin is used, `cygpath` is used for constructing the paths [[GH-1092]](https://github.com/fatih/vim-go/pull/1092) + +BUG FIXES: + +* job: fix race between channel close and job exit [[GH-1247]](https://github.com/fatih/vim-go/pull/1247) +* internal: fix system calls when using tcsh [[GH-1276]](https://github.com/fatih/vim-go/pull/1276) +* path: return the unmodified GOPATH if autodetect is disabled [[GH-1280]](https://github.com/fatih/vim-go/pull/1280) +* fix jumping to quickfix window when autom gometalinter on save was enabled [[GH-1293]](https://github.com/fatih/vim-go/pull/1293) +* fix highlighting for `interface` and `structs` words when `go_highlight_types` is enabled [[GH-1301]](https://github.com/fatih/vim-go/pull/1301) +* fix cwd for running `:GoRun` when used with neovim [[GH-1296]](https://github.com/fatih/vim-go/pull/1296) +* `:GoFmt` handles files that are symlinked into GOPATH better (note that this behaviour is discouraged, but we're trying our best to handle all edge case :)) [[GH-1310]](https://github.com/fatih/vim-go/pull/1310) +* `:GoTest` is able to parse error messages that include a colon `:` [[GH-1316]](https://github.com/fatih/vim-go/pull/1316) +* `:GoTestCompile` under the hood doesn't produces a test binary anymore. Sometimes a race condition would happen which would not delete the test binary. [[GH-1317]](https://github.com/fatih/vim-go/pull/1317) +* `:GoDef` jumps now to definition for build tags defined with `:GoBuildTags` (only guru) [[GH-1319]](https://github.com/fatih/vim-go/pull/1319) + +BACKWARDS INCOMPATIBILITIES: + +* `:GoLint` works on the whole directory instead of the current file. To use it for the current file give it as an argument, i.e `:GoLint foo.go` [[GH-1295]](https://github.com/fatih/vim-go/pull/1295) +* `go_snippet_case_type` is removed in favor of the new `go_addtags_transform` setting [[GH-1299]](https://github.com/fatih/vim-go/pull/1299) +* `go_imports_bin` is removed to avoid confusion as it would lead to race + conditions when set to `gofmt` along with the usage of `go_fmt_command` + [[GH-1212]](https://github.com/fatih/vim-go/pull/1212) [[GH-1308]](https://github.com/fatih/vim-go/pull/1308) +* commands such as `:GoTest` has been refactored for easy maintainability. If + you use any custom script that was using the function `go#cmd#Test`, it + should be renamed to `go#test#Test` + +## 1.12 - (March 29, 2017) + +FEATURES: + +* New `:GoAddTags` and `:GoRemoveTags` command based on the tool + [gomodifytags](https://github.com/fatih/gomodifytags). This fixes many old + bugs that were due prior regexp based implementation. For the usage please + read the docs and checkout the demo at: + https://github.com/fatih/vim-go/pull/1204 [[GH-1204]](https://github.com/fatih/vim-go/pull/1204) +* Add new `errl` snippet that expands to [[GH-1185]](https://github.com/fatih/vim-go/pull/1185): + +``` +if err != nil { + log.Fatal(err) +} +``` +* New `:GoBuildTags` command to change build tags for tools such as `guru`, + `gorename`, etc ... There is also a new setting called `g:go_build_tags` + [[GH-1232]](https://github.com/fatih/vim-go/pull/1232) + +IMPROVEMENTS: + +* vim-go works now even if GOPATH is not set (starting with Go 1.8) [[GH-1248]](https://github.com/fatih/vim-go/pull/1248) +* Lowercase `` in mappings examples for consistent documentation across the README [[GH-1192]](https://github.com/fatih/vim-go/pull/1192) +* All of files should be written in utf-8 if the file will be passed to external command. [[GH-1184]](https://github.com/fatih/vim-go/pull/1184) +* `:GoAddTags` is now able to add options to existing tags with the syntax + `:GoAddTags key,option`, i.e: `:GoAddTags json,omitempty` [[GH-985]](https://github.com/fatih/vim-go/pull/985) +* Document 'noshowmode' requirement for echo_go_info [[GH-1197]](https://github.com/fatih/vim-go/pull/1197) +* Improve godoc view for vertical splits [[GH-1195]](https://github.com/fatih/vim-go/pull/1195) +* Set GOPATH for both possible go guru execution paths (sync and async) [[GH-1193]](https://github.com/fatih/vim-go/pull/1193) +* Improve docs for :GoDef usage [[GH-1242]](https://github.com/fatih/vim-go/pull/1242) +* Highlight trimming syntax for Go templates [[GH-1235]](https://github.com/fatih/vim-go/pull/1235) + +BUG FIXES: + +* Honor `g:go_echo_command_info` when dispatching builds in neovim [[GH-1176]](https://github.com/fatih/vim-go/pull/1176) +* Fix `:GoBuild` error in neovim due to invalid jobcontrol handler function + signatures (`s:on_stdout`, `s:on_stderr`)[[GH-1176]](https://github.com/fatih/vim-go/pull/1176) +* Update statusline before and after `go#jobcontrol#Spawn` command is executed [[GH-1176]](https://github.com/fatih/vim-go/pull/1176) +* Correctly report the value of the 'g:go_guru_tags' variable [[GH-1177]](https://github.com/fatih/vim-go/pull/1177) +* Ensure no trailing `:` exist in GOPATH detection if initial GOPATH is not set [[GH-1194]](https://github.com/fatih/vim-go/pull/1194) +* Fix `:GoAddTags` to allow modifying existing comments [[GH-984]](https://github.com/fatih/vim-go/pull/984) +* Fix `:GoAddTags` to work with nested structs [[GH-990]](https://github.com/fatih/vim-go/pull/990) +* Fix `:GoAddTags` adding tags twice for existing tags [[GH-1064]](https://github.com/fatih/vim-go/pull/1064) +* Fix `:GoAddTags` not working for fields of types `interface{}` [[GH-1091]](https://github.com/fatih/vim-go/pull/1091) +* Fix `:GoAddTags` not working for fields with one line comments [[GH-1181]](https://github.com/fatih/vim-go/pull/1181) +* Fix `:GoAddTags` not working if any field comment would contain `{}` [[GH-1189]](https://github.com/fatih/vim-go/pull/1189) +* Respect go_fmt_options when running goimports [[GH-1211]](https://github.com/fatih/vim-go/pull/1211) +* Set the filename in the location-list when there is an error with :GoFmt [[GH-1199]](https://github.com/fatih/vim-go/pull/1199) +* Fix `:GoInstall` to accept additional arguments if async mode was enabled [[GH-1246]](https://github.com/fatih/vim-go/pull/1246) + +BACKWARDS INCOMPATIBILITIES: + +* The command `:GoGuruTags` is removed in favour of the new command + `:GoBuildTags`. This command will be used now not just for `guru`, also for + all new commands such as `gorename` [[GH-1232]](https://github.com/fatih/vim-go/pull/1232) +* The setting `g:go_guru_tags` is removed in favour of the new setting + `g:go_build_tags` [[GH-1232]](https://github.com/fatih/vim-go/pull/1232) + + +## 1.11 - (January 9, 2017) + +FEATURES: + +* Travis test integration has been added. Now any file that is added as + `_test.vim` will be automatically tested in for every Pull Request + (just like how we add tests to Go with `_test.go`). Going forward this will + tremendously increase the stability and decrease the maintenance burden of + vim-go. [[GH-1157]](https://github.com/fatih/vim-go/pull/1157) +* Add new `g:go_updatetime` setting to change the default updatetime (which was hardcoded previously) [[GH-1055]](https://github.com/fatih/vim-go/pull/1055) +* Add new `g:go_template_use_pkg` setting to enable to use cwd as package name instead of basic template file [[GH-1124]](https://github.com/fatih/vim-go/pull/1124) + +IMPROVEMENTS: + +* Add `statusline` support for `:GoMetaLinter` [[GH-1120]](https://github.com/fatih/vim-go/pull/1120) +* Quickfix and Location lists contain now a descriptive title (requires at least Vim `7.4.2200`)[[GH-1004]](https://github.com/fatih/vim-go/pull/1004) +* Check `go env GOPATH` as well for `:GoInstallBinaries` as Go has now a default path for GOPATH ("~/go")starting with 1.8 [[GH-1152]](https://github.com/fatih/vim-go/pull/1152) +* `:GoDocBrowser` now also works on import paths [[GH-1174]](https://github.com/fatih/vim-go/pull/1174) + +BUG FIXES: + +* Always use full path to detect packages to be shown in statusline [[GH-1121]](https://github.com/fatih/vim-go/pull/1121) +* Use `echom` to persist errors in case of multiple echos [[GH-1122]](https://github.com/fatih/vim-go/pull/1122) +* Fix a race condition where a quickfix window was not closed if a job has succeeded [[GH-1123]](https://github.com/fatih/vim-go/pull/1123) +* Do not expand coverage arguments for non job execution of `:GoCoverage` [[GH-1127]](https://github.com/fatih/vim-go/pull/1127) +* `:GoCoverage` doesn't mess up custom syntax anymore [[GH-1128]](https://github.com/fatih/vim-go/pull/1128) +* Disable autoformat for `asm` files as they might be non Go ASM format [[GH-1141]](https://github.com/fatih/vim-go/pull/1141) +* Fix indentation broken when using a action with a minus sign like `{{-` [[GH-1143]](https://github.com/fatih/vim-go/pull/1143) +* Fix breaking Neovim change of passing less arguments to callbacks [[GH-1145]](https://github.com/fatih/vim-go/pull/1145) +* Fix `guru` commands if custom build tags were set [[GH-1136]](https://github.com/fatih/vim-go/pull/1136) +* Fix referencing a non defined variable for async commands when bang (!) was used +* Fix `:GoDef` failing for a modified buffer if `hidden` was not set [[GH-1132]](https://github.com/fatih/vim-go/pull/1132) +* Fix `:GoDefStack` to allow popping from jump list when buffer is modified [[GH-1133]](https://github.com/fatih/vim-go/pull/1133) +* Improve internal defining of functions and referencing them for async operations [[GH-1155]](https://github.com/fatih/vim-go/pull/1155) +* Fix `:GoMetaLinter` failing if `go_metalinter_command` is set. [[GH-1160]](https://github.com/fatih/vim-go/pull/1160) +* Fix `:GoMetaLinter`'s `go_metalinter_deadline` setting for async mode [[GH-1146]](https://github.com/fatih/vim-go/pull/1146) + +BACKWARDS INCOMPATIBILITIES: + +* The following syntax options are now disabled by default. If you're using them be sure to set them in your .vimrc [[GH-1167]](https://github.com/fatih/vim-go/pull/1167) + +```viml +g:go_highlight_array_whitespace_error +g:go_highlight_chan_whitespace_error +g:go_highlight_extra_types +g:go_highlight_space_tab_error +g:go_highlight_trailing_whitespace_error +``` + + + +## 1.10 (November 24, 2016) + +FEATURES: + +* **Vim 8.0 support!** This is the initial version to add Vim 8.0 based support to + all basic commands (check out below for more information). With time we'll + going to extend it to other commands. All the features are only enabled if + you have at least Vim 8.0.0087. Backwards compatible with Vim 7.4.x. + If you see any problems, please open an issue. + +* We have now a [logo for vim-go](https://github.com/fatih/vim-go/blob/master/assets/vim-go.png)! Thanks to @egonelbre for his work on this. +* `:GoBuild`, `:GoTest`, `:GoTestCompile`, `:GoInstall` commands are now fully + async. Async means it doesn't block your UI anymore. If the command finished + it echoes the status. For a better experience use the statusline information + (more info below) + +* `:GoCoverage` and `:GoCoverageBrowser` commands are fully async. +* `:GoDef` is fully async if `guru` is used as command. +* `:GoRename` is fully async . + +* `:GoMetaLinter` is fully asnyc. Also works with the current autosave linting + feature. As a reminder, to enable auto linting on save either call + `:GoMetaLinterAutoSaveToggle` (temporary) or add `let + g:go_metalinter_autosave = 1` (persistent) to your virmc). + +* All `guru` commands run asynchronously if Vim 8.0 is being used. Current + Commands: + * GoImplements + * GoWhicherrs + * GoCallees + * GoDescribe + * GoCallers + * GoCallstack + * GoFreevars + * GoChannelPeers + * GoReferrers + +* `:GoSameIds` also runs asynchronously. This makes it useful especially for + auto sameids mode. In this mode it constantly evaluates the identifier under the + cursor whenever it's in hold position and then calls :GoSameIds. As a + reminder, to enable auto info either call `:GoSameIdsAutoToggle`(temporary) + or add `let g:go_auto_sameids = 1` (persistent) to your vimrc. + +* `:GoInfo` is now non blocking and works in async mode if `guru` is used in + `g:go_info_mode`. This makes it useful especially for autoinfo mode. In this + mode it constantly evaluates the identifier under the cursor whenever it's in + hold position and then calls :GoInfo. As a reminder, to enable auto info + either call `:GoAutoTypeInfoToggle`(temporary) or add `let + g:go_auto_type_info = 1` (persistent) to your vimrc. To use `guru` instead of + `gocode` add following to your vimrc: `let g:go_info_mode = 'guru'` + + The `guru` is more accurate and reliabed due the usage of `guru` describe. It + doesn't rely on `pkg/` folder like `gocode` does. However it's slower than + `gocode` as there is no caching mechanism in `guru` yet. + +* **New**: Statusline function: `go#statusline#Show()` which can be plugged into + the statusline bar. Works only with vim 8.0. It shows all asynchronously + called functions status real time. Checkout it in action: + https://twitter.com/fatih/status/800473735467847680. To enable it add the + following to your `vimrc`. If you use lightline, airline, .. check out their + respective documentation on how to add a custom function: + +```viml +" go command status (requires vim-go) +set statusline+=%#goStatuslineColor# +set statusline+=%{go#statusline#Show()} +set statusline+=%* +``` + +IMPROVEMENTS: + +* **:GoDocBrowser** is now capable to to understand the identifier under the cursor (just like :GoDoc) +* Function calls are now highlighted as well when `g:go_highlight_functions` is enabled [[GH-1048]](https://github.com/fatih/vim-go/pull/1048) +* Add completion support for un-imported packages. This allows to complete even + if the package is not imported. By default it's disabled, enable by adding + `let g:go_gocode_unimported_packages = 1` [[GH-1084]](https://github.com/fatih/vim-go/pull/1084) +* Tools that embeds GOROOT into their binaries do not work when people update + their Go version and the GOROOT contains the vesion as part of their path + (i.e: `/usr/local/Cellar/go/1.7.2/libexec`, [more + info](https://blog.filippo.io/stale-goroot-and-gorebuild/)) . This is now + fixed by introducing automatic GOROOT set/unset before each tool invoke. + [[GH-954]](https://github.com/fatih/vim-go/pull/954) +* Added new setting `g:go_echo_go_info` to enable/disable printing identifier + information when completion is done [[GH-1101]](https://github.com/fatih/vim-go/pull/1101) +* Added new `go_echo_command_info` setting is added, which is enabled by + default. It's just a switch for disabling messages of commands, such as + `:GoBuild`, `:GoTest`, etc.. Useful to *disable* if `go#statusline#Show()` is + being used in Statusline, to prevent to see duplicates notifications. +* goSameId highlighting is now linked to `Search`, which is much more clear as + it changes according to the users colorscheme +* Add plug mapping `(go-lint)` for :GoLint [[GH-1089]](https://github.com/fatih/vim-go/pull/1089) + + +BUG FIXES: + +* Change back nil and iota highlighting color to the old type [[GH-1049]](https://github.com/fatih/vim-go/pull/1049) +* Fix passing arguments to `:GoBuild` while using NeoVim [[GH-1062]](https://github.com/fatih/vim-go/pull/1062) +* Do not open a split if `:GoDef` is used on a modified file [[GH-1083]](https://github.com/fatih/vim-go/pull/1083) +* Highlight nested structs correctly [[GH-1075]](https://github.com/fatih/vim-go/pull/1075) +* Highlight builtin functions correctly if `g:go_highlight_functions` is enabled [[GH-1070]](https://github.com/fatih/vim-go/pull/1070) +* Fix `:GoSameIds` highlighting if a new buffer is opened in the same window [[GH-1067]](https://github.com/fatih/vim-go/pull/1067) +* Internal: add `abort` to all vim function to return in case of errors [[GH-1100]](https://github.com/fatih/vim-go/pull/1100) +* Fix `:GoCoverage` to be executed if working dir is not inside the test dir [[GH-1033]](https://github.com/fatih/vim-go/pull/1033) + +BACKWARDS INCOMPATIBILITIES: + +* remove vim-dispatch and vimproc.vim support. vim 8.0 has now the necessary + API to invoke async jobs and timers. Going forward we should use those. Also + this will remove the burden to maintain compatibility with those plugins. + +* `go#jobcontrol#Statusline()` is removed in favor of the new, global and + extensible `go#statusline#Show()` + +## 1.9 (September 13, 2016) + +IMPROVEMENTS: + +* **guru** uses now the `-modified` flag, which allows us use guru on modified + buffers as well. This affects all commands where `guru` is used. Such as + `:GoDef`, `:GoReferrers`, etc.. [[GH-944]](https://github.com/fatih/vim-go/pull/944) +* **:GoDoc** uses now the `-modified` flag under the hood (for `gogetdoc), which allows us to get documentation for the identifier under the cursor ina modified buffer. [[GH-1014]](https://github.com/fatih/vim-go/pull/1014) +* Cleanup and improve documentation [[GH-987]](https://github.com/fatih/vim-go/pull/987) +* Add new `g:go_gocode_socket_type` setting to change the underlying socket type passed to `gocode`. Useful to fallback to `tcp` on cases such as Bash on Windows [[GH-1000]](https://github.com/fatih/vim-go/pull/1000) +* `:GoSameIds` is now automatically re-evaluated in cases of buffer reloads (such as `:GoRename`) [[GH-998]](https://github.com/fatih/vim-go/pull/998) +* Improve docs about `go_auto_sameids` [[GH-1017]](https://github.com/fatih/vim-go/pull/1017) +* Improve error message by printing the full path if an incompatible `goimports` is being used [[GH-1006]](https://github.com/fatih/vim-go/pull/1006) +* `iota` and `nil` are now highlighted correctly and are not treated as booleans [[GH-1030]](https://github.com/fatih/vim-go/pull/1030) + +BUG FIXES: + +* Fix system calls on Windows [[GH-988]](https://github.com/fatih/vim-go/pull/988) +* Fix :GoSameIds and :GoCoverage for light background and after changing color schemes [[GH-983]](https://github.com/fatih/vim-go/pull/983) +* Fix TagBar and `GoCallers` for Windows user [[GH-999]](https://github.com/fatih/vim-go/pull/999) +* Set updatetime for for `auto_sameids` feature as well [[GH-1016]](https://github.com/fatih/vim-go/pull/1016) +* Update docs about missing `go_highlight_generate_tags` setting [[GH-1023]](https://github.com/fatih/vim-go/pull/1023) +* Fix updating the jumplist if `:GoDef` is used [[GH-1029]](https://github.com/fatih/vim-go/pull/1029) +* Fix highlighting literal percent sign (`%%`) in strings [[GH-1011]](https://github.com/fatih/vim-go/pull/1011) +* Fix highlighting of nested fields [[GH-1007]](https://github.com/fatih/vim-go/pull/1007) +* Fix checking for `exepath` feature for the upcoming vim 8.0 release [[GH-1046]](https://github.com/fatih/vim-go/pull/1046) + +BACKWARDS INCOMPATIBILITIES: + +* Rename `GoMetalinterAutoSaveToggle` to `GoMetaLinterAutoSaveToggle` to make it compatible with the existing `:GoMetaLinter` command [[GH-1020]](https://github.com/fatih/vim-go/pull/1020) + +## 1.8 (July 31, 2016) + +FEATURES: +* New **`:GoAddTags`** command that adds field tags for the fields of a struct automatically based on the field names. Checkout the demo to see it in action: https://twitter.com/fatih/status/759822857773907968 [[GH-971]](https://github.com/fatih/vim-go/pull/971) +* The snippet expansion `json` is now much more smarter. It pre populates the placeholder according to the first word and it also applies `snake_case` or `camelCase` conversion. Together with `:GoAddTags` it gives `vim-go` users flexible ways of populating a field tag. Checkout the demo to see it in action: https://twitter.com/fatih/status/754477622042689536 [[GH-927]](https://github.com/fatih/vim-go/pull/927) +* New **`:GoSameIds`** command. When called highlights all same identifiers in the current file. Can be also enabled to highlight identifiers automatically (with `:GoSameIdsAutoToggle` or `g:go_auto_sameids`). Checkout the demo to see it in action: https://twitter.com/fatih/status/753673709278339072. [[GH-936]](https://github.com/fatih/vim-go/pull/936) +* New **`:GoWhicherrs`** command. It shows all possible values of the selected error variable. [[GH-948]](https://github.com/fatih/vim-go/pull/948) +* Add new `errp` snippet to expand an `if err != nil { panic() }` clause [[GH-926]](https://github.com/fatih/vim-go/pull/926) +* If you open a new buffer with a Go filename it get automatically populated based on the directory. If there are no Go files a simple main package is created, otherwise the file will include the package declaration line based on the package in the current directory. Checkout the demo to see it in action: https://twitter.com/fatih/status/748333086643994624. This is enabled by default. Can be disabled with `let g:go_template_autocreate = 0`. You can use your own template with `let g:go_template_file = "foo.go"` and putting the file under the `templates/` folder. [[GH-918]](https://github.com/fatih/vim-go/pull/918) +* Added new toggle commands to enable/disable feature that run for your + automatic. For example if you have `let g:go_auto_type_info = 1` enabled, you + can now easily enable/disable it on the fly. Support added with the following + commands: `:GoAutoTypeInfoToggle`, `:GoFmtAutoSaveToggle`, + `:GoAsmFmtAutoSaveToggle`, `:GoMetalinterAutoSaveToggle`, + `:GoTemplateAutoCreateToggle` [[GH-945]](https://github.com/fatih/vim-go/pull/945) + + +IMPROVEMENTS: +* `:GoDoc` accepts arguments now which are passed directly to `godoc`. So usages like `:GoDoc flag` works again (it was changed in previous versions [[GH-894]](https://github.com/fatih/vim-go/pull/894) +* `:GoDef` works now for modified files as well [[GH-910]](https://github.com/fatih/vim-go/pull/910) +* Internal: pass filename to the `--srcdir` flag to enable upcoming `goimports` features [[GH-957]](https://github.com/fatih/vim-go/pull/957) +* Internal: fix indentations on all files to **2-spaces/no tabs**. This is now the default vim-go style across all VimL files [[GH-915]](https://github.com/fatih/vim-go/pull/915) +* Internal: autocmd settings can be now dynamically enabled/disabled [[GH-939]](https://github.com/fatih/vim-go/pull/939) +* Internal: automatically detect `GOPATH` for :GoInstall [[GH-980]](https://github.com/fatih/vim-go/pull/980) +* Internal: shell executions uses now by default `sh` and then resets it back to the user preference. [[GH-967]](https://github.com/fatih/vim-go/pull/967) +* Syntax: improved syntax highglighting performance for methods, fields, structs and interface type declarations [[GH-917]](https://github.com/fatih/vim-go/pull/917) +* Syntax: moved `:GoCoverage` highlight definition into go's syntax file for more customizability [[GH-962]](https://github.com/fatih/vim-go/pull/962) + + +BUG FIXES: + +* Escape `#` characters when opening URL's, as it's handled as alternative file in vim [[GH-895]](https://github.com/fatih/vim-go/pull/895) +* Fix typos in `doc/vim-go.txt` about usages of syntax highglightings [[GH-897]](https://github.com/fatih/vim-go/pull/897) +* Fix `:GoCoverage` not running for Neovim [[GH-899]](https://github.com/fatih/vim-go/pull/899) +* Fix `:GoFmt` not picking up `-srcdir` if the command was set to use `goimports` [[GH-904]](https://github.com/fatih/vim-go/pull/904) +* Fix `:GoTestCompile` to not leave behind artifacts if the cwd and the test files's directory do not match [[GH-909]](https://github.com/fatih/vim-go/pull/909) +* Fix `:GoDocBrowser` to not fail if godoc doesn't exist [[GH-920]](https://github.com/fatih/vim-go/pull/920) +* Fix `:GoFmt` to not change the permissions of saved file. Now original file permissions are restored [[GH-922]](https://github.com/fatih/vim-go/pull/922) + +BACKWARDS INCOMPATIBILITIES: + +* `g:go_highlight_structs` and `g:go_highlight_interface` are removed in favor of `g:go_highlight_types` [[GH-917]](https://github.com/fatih/vim-go/pull/917) + ## 1.7.1 (June 7, 2016) @@ -19,39 +568,39 @@ BUG FIXES: FEATURES: -* New **`:GoImpl`** command that generates method stubs for implementing an interface. Checkout the [demo](https://twitter.com/fatih/status/729991365581545472) to see how it works. [gh-846] -* `godef` support is added back as an optional setting. By default `:GoDef` still uses `guru`, but can be changed to `godef` by adding the option: `let g:go_def_mode = 'godef'` [gh-888] -* New `` and `]>` shortcuts to split current window and jumpt to the identifier under cursor. [gh-838] -* New syntax setting" `g:go_highlight_fields` that highlights struct field references [gh-854] +* New **`:GoImpl`** command that generates method stubs for implementing an interface. Checkout the [demo](https://twitter.com/fatih/status/729991365581545472) to see how it works. [[GH-846]](https://github.com/fatih/vim-go/pull/846) +* `godef` support is added back as an optional setting. By default `:GoDef` still uses `guru`, but can be changed to `godef` by adding the option: `let g:go_def_mode = 'godef'` [[GH-888]](https://github.com/fatih/vim-go/pull/888) +* New `` and `]>` shortcuts to split current window and jumpt to the identifier under cursor. [[GH-838]](https://github.com/fatih/vim-go/pull/838) +* New syntax setting" `g:go_highlight_fields` that highlights struct field references [[GH-854]](https://github.com/fatih/vim-go/pull/854) IMPROVEMENTS: -* Invoking `:GoRename` now reloads all files to reflect new changes automatically [gh-855] -* Calling `:GoTestCompile` does not create any temporary binary file anymore [gh-879] +* Invoking `:GoRename` now reloads all files to reflect new changes automatically [[GH-855]](https://github.com/fatih/vim-go/pull/855) +* Calling `:GoTestCompile` does not create any temporary binary file anymore [[GH-879]](https://github.com/fatih/vim-go/pull/879) * Enable passing the `-tags` flag to `:GoDef`. Now you can pass build tags to `:GoDef` via `:GoGuruTags` or `g:go_guru_tags` -* Internal refactoring to use custom `system()` function that wraps both the standard `system()` call and `vimproc`. Now all system calls will take advantage and will use `vimproc` if installed. [gh-801] -* Completion enables now `gocode`'s `autobuild` and `propose-builtins` flags automatically. With these settings packages will be automatically build to get the freshest completion candidates and builtin keywords will be showed as well. By defaults these settings are enabled. Settings can be disabled/enabled via `g:go_gocode_autobuild` and `g:go_gocode_propose_builtins`. [gh-815] -* Added new `http.HandlerFunc` snippets with `hf` and `hhf` shortcuts [gh-816] -* Added new `Example` and `Benchmark` snippets with `example` and `benchmark` shortcuts [gh-836] -* Search tool binaries first in `GOBIN` and then in `PATH` as most of vim-go users installs it to `GOBIN` mostly [gh-823] -* Improve `guru` based commands by providing automatically detected GOPATHS, such as `gb`, `godep` to be used if possible [gh-861] -* Add `(go-imports)` mapping to make it assignable to other keys [gh-878] -* Increase compatibility with tcsh [gh-869] -* Improve `:GoInstallBinaries` for GOPATH's which don't have packages that work well with `go get -u`. We have a new `g:go_get_update` setting to disable it. By default it's enabled. [gh-883] +* Internal refactoring to use custom `system()` function that wraps both the standard `system()` call and `vimproc`. Now all system calls will take advantage and will use `vimproc` if installed. [[GH-801]](https://github.com/fatih/vim-go/pull/801) +* Completion enables now `gocode`'s `autobuild` and `propose-builtins` flags automatically. With these settings packages will be automatically build to get the freshest completion candidates and builtin keywords will be showed as well. By defaults these settings are enabled. Settings can be disabled/enabled via `g:go_gocode_autobuild` and `g:go_gocode_propose_builtins`. [[GH-815]](https://github.com/fatih/vim-go/pull/815) +* Added new `http.HandlerFunc` snippets with `hf` and `hhf` shortcuts [[GH-816]](https://github.com/fatih/vim-go/pull/816) +* Added new `Example` and `Benchmark` snippets with `example` and `benchmark` shortcuts [[GH-836]](https://github.com/fatih/vim-go/pull/836) +* Search tool binaries first in `GOBIN` and then in `PATH` as most of vim-go users installs it to `GOBIN` mostly [[GH-823]](https://github.com/fatih/vim-go/pull/823) +* Improve `guru` based commands by providing automatically detected GOPATHS, such as `gb`, `godep` to be used if possible [[GH-861]](https://github.com/fatih/vim-go/pull/861) +* Add `(go-imports)` mapping to make it assignable to other keys [[GH-878]](https://github.com/fatih/vim-go/pull/878) +* Increase compatibility with tcsh [[GH-869]](https://github.com/fatih/vim-go/pull/869) +* Improve `:GoInstallBinaries` for GOPATH's which don't have packages that work well with `go get -u`. We have a new `g:go_get_update` setting to disable it. By default it's enabled. [[GH-883]](https://github.com/fatih/vim-go/pull/883) BUG FIXES: -* Fix `(go-freevars)` plug mapping to work as in visual mode instead of noncompatible normal mode [gh-832] +* Fix `(go-freevars)` plug mapping to work as in visual mode instead of noncompatible normal mode [[GH-832]](https://github.com/fatih/vim-go/pull/832) * Commands based on guru now shows a more meaningful error message instead of just showing the exit status (-1) -* Fix `:GoCoverage` accidently enabling syntax highlighting for users who don't use syntax (i.e syntax off) [gh-827] -* Fix `:GoCoverage` colors to work for xterm as well [gh-863] -* Fix commenting out block of texts for Go templates (filetype gothtmltmpl) [gh-813] +* Fix `:GoCoverage` accidentally enabling syntax highlighting for users who don't use syntax (i.e syntax off) [[GH-827]](https://github.com/fatih/vim-go/pull/827) +* Fix `:GoCoverage` colors to work for xterm as well [[GH-863]](https://github.com/fatih/vim-go/pull/863) +* Fix commenting out block of texts for Go templates (filetype gothtmltmpl) [[GH-813]](https://github.com/fatih/vim-go/pull/813) * Fix `:GoImplements` failing because of an empty scope definition. Now we default to current package to make it usable. -* Fix `:GoPlay` posting to non HTTPS url. [gh-847] -* Fix escaping the filenames for lint and motion commands [gh-862] -* Fix escaping the filename to `:GoDef` completely for tcsh [gh-868] -* Fix showing SUCCESS for `go test` related commands if no test files are available [gh-859] +* Fix `:GoPlay` posting to non HTTPS url. [[GH-847]](https://github.com/fatih/vim-go/pull/847) +* Fix escaping the filenames for lint and motion commands [[GH-862]](https://github.com/fatih/vim-go/pull/862) +* Fix escaping the filename to `:GoDef` completely for tcsh [[GH-868]](https://github.com/fatih/vim-go/pull/868) +* Fix showing SUCCESS for `go test` related commands if no test files are available [[GH-859]](https://github.com/fatih/vim-go/pull/859) @@ -66,15 +615,15 @@ FEATURES: annotation. Use `:GoCoverageClear` to clear the coverage annotation. This is a pretty good addition to vim-go and I suggest to check out the gif that shows it in action: https://twitter.com/fatih/status/716722650383564800 - [gh-786] + [[GH-786]](https://github.com/fatih/vim-go/pull/786) * **`:GoCoverageToggle`** just like `:GoCoverage` but acts as a toggle. If run again it clears the annotation. * **`:GoCoverageBrowser`** opens a new annotated HTML page. This is the old - `:GoCoverage` behavior [gh-786] + `:GoCoverage` behavior [[GH-786]](https://github.com/fatih/vim-go/pull/786) * **`:GoDoc`** uses now [gogetdoc](https://github.com/zmb3/gogetdoc) to lookup and display the comment documentation for the identifier under the cursor. This is more superior as it support looking up dot imports, named - imports and imports where package name and file name are different [gh-782] + imports and imports where package name and file name are different [[GH-782]](https://github.com/fatih/vim-go/pull/782) * **`guru support`**: `oracle` is replaced by the new tool `guru`. `oracle.vim` is therefore renamed to `guru.vim`. I've also refactored the code to make it much more easier to maintain and add additional features in future (such as @@ -90,21 +639,21 @@ FEATURES: `:GoDefPop` or the mapping `CTRL-t`. To see the stack and jump between entries you can use the new command `:GoDefStack`, which shows the list of all stack entries. To reset the stack list anytime you can call `:GoDefStackClear` - [gh-776] + [[GH-776]](https://github.com/fatih/vim-go/pull/776) IMPROVEMENTS: -* **`:GoCoverage`** is executed asynchronously when used within Neovim [gh-686] -* **`:GoTestFunc`** supports now testable examples [gh-794] +* **`:GoCoverage`** is executed asynchronously when used within Neovim [[GH-686]](https://github.com/fatih/vim-go/pull/686) +* **`:GoTestFunc`** supports now testable examples [[GH-794]](https://github.com/fatih/vim-go/pull/794) * **`:GoDef`** can jump to existing buffers instead of opening a new window (split, vsplit or tab). By default it's disabled to not break the old behavior, can be enabled with `let g:go_def_reuse_buffer = 1` BUG FIXES: -* Fix not showing documentation for dot, named and package/file name being different imports [gh-332] -* Term mode: fix closing location list if result is successful after a failed attempt [gh-768] -* Syntax: fix gotexttmpl identifier highlighting [gh-778] +* Fix not showing documentation for dot, named and package/file name being different imports [[GH-332]](https://github.com/fatih/vim-go/pull/332) +* Term mode: fix closing location list if result is successful after a failed attempt [[GH-768]](https://github.com/fatih/vim-go/pull/768) +* Syntax: fix gotexttmpl identifier highlighting [[GH-778]](https://github.com/fatih/vim-go/pull/778) * Doc: fix wrong wording for `go-run` mapping. It's for the whole main package, not for the current file @@ -120,7 +669,380 @@ BACKWARDS INCOMPATIBILITIES: i.g: `let g:go_guru_scope = ["github.com/fatih/structs", "golang.org/x/tools/..."]` -## Previous releases +## 1.5 (Mar 16, 2016) -Previous changelogs can be found here: https://github.com/fatih/vim-go/releases +FEATURES: +* Introducing code name "motion". A new whole way of moving + around and navigating [[GH-765]](https://github.com/fatih/vim-go/pull/765). Checkout the following new changes: + * A vim-go specific tool, called [motion](https://github.com/fatih/motion) is being developed which + provides us the underlying foundation for the following and upcoming + new features. + * `]]` and `[[` motions can be used to jump between functions + * `if` and `af` are improved and implement from scratch. It has now + support for literal functions, comments of functions, better cursor + position support and more stable. + * New `:GoDecls` and `:GoDeclsDir` commands that are available if + `ctrlp.vim` is installed. Once called one can easily jump to any generic declaration available. + * I wrote two blog posts about these new features in more detail. I recommend you to read it: [Treating Go types as objects in Vim](https://medium.com/@farslan/treating-go-types-as-objects-in-vim-ed6b3fad9287#.mbwaisevp) and [Navigation between functions and types in vim-go](https://medium.com/@farslan/navigation-between-functions-and-types-in-vim-go-f9dd7de8ca37#.2sdf8tbbe) +* A new `:GoAlternate` command that toggles to the test + file of the current file. It also has new appropriate mappings to open the + alternate file in split or tabs. [[GH-704]](https://github.com/fatih/vim-go/pull/704) +* Now commands can choose whether they want to open a + `quickfix` or a `location list` via the setting `g:go_list_type`. Also all + the commands have now some sensible settings, some will open a qf window, + some will open a location list [[GH-700]](https://github.com/fatih/vim-go/pull/700) +IMPROVEMENTS: + +* Add support for goimport's new `-srcdir`. Goimports now succesfully suports `vendor/` folders with this release. [[GH-735]](https://github.com/fatih/vim-go/pull/735) +* Add `g:go_gorename_prefill` setting which disabled pre filling the argument for `:GoRename` [[GH-711]](https://github.com/fatih/vim-go/pull/711) +* Improve `:GoRun` to complete to filenames [[GH-742]](https://github.com/fatih/vim-go/pull/742) +* Highlight `//go:generate` comment directives [[GH-757]](https://github.com/fatih/vim-go/pull/757) +* Indent code in Go HTML templates [[GH-709]](https://github.com/fatih/vim-go/pull/709) +* Improve negative numbers of all types, octals, imaginary numbers with exponents [[GH-752]](https://github.com/fatih/vim-go/pull/752) +* Improved internal usage of retrieving offsets [[GH-762]](https://github.com/fatih/vim-go/pull/762) +* Improve by substitute all backslashes to slashes for filename [[GH-703]](https://github.com/fatih/vim-go/pull/703) +* Improve internal Go package path function [[GH-702]](https://github.com/fatih/vim-go/pull/702) +* Improved typo and grammar errors in docs [[GH-714]](https://github.com/fatih/vim-go/pull/714) +* Improved internal `:GoInfo` automatic call [[GH-759]](https://github.com/fatih/vim-go/pull/759) + +BUG FIXES: + +* Fix oracle scope not working if trailing slash exists in scope [[GH-751]](https://github.com/fatih/vim-go/pull/751) +* Fix `:GoErrCheck` checking abspath [[GH-671]](https://github.com/fatih/vim-go/pull/671) +* Fix `:GoInstall` correctly parsing errors [[GH-692]](https://github.com/fatih/vim-go/pull/692) +* Fix `:GoInstall` correctly parsing errors [[GH-692]](https://github.com/fatih/vim-go/pull/692) +* Fix `:GoTestFunc` for neovim [[GH-695]](https://github.com/fatih/vim-go/pull/695) +* Fix `:GoRun` accepting arguments for neovim [[GH-730]](https://github.com/fatih/vim-go/pull/730) +* Fix `go run` mappings not working [[GH-542]](https://github.com/fatih/vim-go/pull/542) +* Fix autodetect gopath picking up non existing GB vendor folder +* Fix gofmt errors showing per buffer instead of per script [[GH-721]](https://github.com/fatih/vim-go/pull/721) +* Fix some of the neosnippet snippets + +## 1.4 (Jan 18, 2016) + +FEATURES: + +* You waited for it for a long time. And here you have it: **Neovim support!** + This is a huge feature. It's fully compatible with Vim and kicks only in if + vim-go is being used within Neovim. Checkout the full list of changes + [[GH-607]](https://github.com/fatih/vim-go/pull/607): + * An async launcher and base foundation was implemented for the `go` command. + This will be used in the future for all upcoming subcommands of the `go` + tool. + * `:GoBuild` is now called asynchronously (it doesn't block the UI anymore). + * A new `go#jobcontrol#Statusline()` can be used to plug into the statusline. + This will show the status of the job running asynchronously. The statusline + is improved to show the status per package instead of file. Assume you have + three files open, all belonging to the same package, if the package build + (`:GoBuild`) is successful, all statusline's will be empty (means SUCCESS), + if it fails all files statusline's will show `FAILED`. + * `:GoRun` opens a new vertical terminal emulator inside Neovim and runs the + command there. The terminal mode can be changed with `g:go_term_mode`, + which is by default `vsplit`. Current options are `vsplit, split or tab`. + We also have three new mappings to open `:GoRun` command in different + terminal split modes: `(go-run-vertical)`, `(go-run-split)` + and `(go-run-tab)` + * `:GoTest`, `:GoTestFunc` and `:GoTestCompile` opens and runs in a new + terminal. The view mode (split,vertical, tab) is defined with + `g:go_term_mode`. The `g:go_term_enabled` setting can be use to change the + behavior of `:GoTestXXX` commands .If set to `1`, it opens the test + commands inside a terminal, if not it runs them in background just like + `:GoBuild` and displays the result in the statusline. + * We have two settings for terminal sizes: `g:go_term_height` and + `g:go_term_width`. By default a vertical or horizontal view is equally + splitted by vim automatically. However with these settings we can for + example have a terminal with a smaller height when we split it + horizontally. + * If a command inside the term fails (such as `go run`, `go test` ...) we + parse now the errors and list them inside a location list. +* Instead of quickfix window, vim-go now uses the `location list` feature of + Vim. These are associated with each window independently of each other. This + enables us to have multiple, independent location lists per window (example + usages: `:GoBuild` with errors that needs to be fixed, `:GoLint` with + warnings that we want to check, `:GoReferrers` with a list of referred + identifiers) [[GH-626]](https://github.com/fatih/vim-go/pull/626) +* a new **`:AsmFmt`** command which is integrated to work with [asmfmt](https://github.com/klauspost/asmfmt) [[GH-673]](https://github.com/fatih/vim-go/pull/673) +* the full identifier information of a completed identifier is echoed in + statusline. This is very useful to see a function signatures arguments. + [[GH-685]](https://github.com/fatih/vim-go/pull/685) + +IMPROVEMENTS: + +* Improve `:GoFmt` by checking if the binary is indeed installed on the system [[GH-617]](https://github.com/fatih/vim-go/pull/617) +* Improve `:GoMetaLinter` by adding the option to run the metalinter on save + and adding the option to limit the output to the currently active buffer. Set + `let g:go_metalinter_autosave = 1` to enable autosave and use `let + g:go_metalinter_autosave_enabled = ['vet', 'golint']` to change your options. + [[GH-631]](https://github.com/fatih/vim-go/pull/631) +* Improved `:GoDef`. If `vimproc` is installed `godef` will make use of it [[GH-670]](https://github.com/fatih/vim-go/pull/670) +* Improve completion of godoce when vimproc is used [[GH-620]](https://github.com/fatih/vim-go/pull/620) +* Improve internal error matching prodecure to not match false positives [[GH-618]](https://github.com/fatih/vim-go/pull/618) +* A new option to highlight interface variables with `go_highlight_interfaces` [[GH-681]](https://github.com/fatih/vim-go/pull/681) + +BUG FIXES + +* Fix `:GoFmt` changing the fileformat of the current buffer [[GH-615]](https://github.com/fatih/vim-go/pull/615) +* Fix `:GoRename` to output the original error if parsing fails [[GH-675]](https://github.com/fatih/vim-go/pull/675) +* Fix `:GoTest` to output the original error if parsing fails [[GH-676]](https://github.com/fatih/vim-go/pull/676) +* Fixed `fmt.Fprintln` not to highlight as builtin [[GH-628]](https://github.com/fatih/vim-go/pull/628) +* Fixed wrong highlighting of channels of channels [[GH-678]](https://github.com/fatih/vim-go/pull/678) + +## 1.3 (Nov 22, 2015) + +FEATURES: + +* A new `:GoOracleTags` command was added to pass build tags to Oracle's `-tags` flag. [[GH-573]](https://github.com/fatih/vim-go/pull/573) + +IMPROVEMENTS: + +* Change `:GoTest` command to timeout after 10 seconds. Vim UI is blocking and + tests with large running times makes Vim blocking for a long time. This is + also customizable with the new option `g:go_test_timeout`. [[GH-578]](https://github.com/fatih/vim-go/pull/578) +* Improve `:GoRename` to collect and populate quickfix window with errors. + [[GH-577]](https://github.com/fatih/vim-go/pull/577) +* Improve `:GoRun` by dropping bad filenames from quickfix window. This allows + us to have only valid entries which can be jumped to [[GH-547]](https://github.com/fatih/vim-go/pull/547) +* Improve `:GoMetaLinter` quickfix output by using absolute paths. This enables + us to jump to errors for all cases. [[GH-565]](https://github.com/fatih/vim-go/pull/565) +* Improve `:GoMetaLinter` command by adding a new option + `g:go_metalinter_deadline` which cancels the linters after 5 seconds + (previous default). [[GH-576]](https://github.com/fatih/vim-go/pull/576) +* Improve `:GoMetaLinter` by jumping to the first encountered error from the quickfix window. +* Automatically resize quickfix window based on the number of errors [[GH-602]](https://github.com/fatih/vim-go/pull/602) +* Improve build constraints to show invalid cases (such as `// +buildfoo`, not + having an empty line between the package statement, etc..). Also add missing + `GOARCH` values sucha s `arm64`. There are many other useful improvements, + for more detail please have a look at + [[GH-589]](https://github.com/fatih/vim-go/pull/589) +* Add support for all values of `GOARCH` [[GH-601]](https://github.com/fatih/vim-go/pull/601) +* Add note about Syntastic usage as this problem comes up a lot [[GH-580]](https://github.com/fatih/vim-go/pull/580) +* Add note about `:GoUpdateBinaries` [[GH-606]](https://github.com/fatih/vim-go/pull/606) + +BUG FIXES: + +* Fixed `:GoErrCheck` showing the correct output when executed inside the source folder [[GH-564]](https://github.com/fatih/vim-go/pull/564) +* Fixed `:GoBuild` by not using `/dev/null` anymore for build output (not + supported by `go`). We pass a temporary file now. [[GH-567]](https://github.com/fatih/vim-go/pull/567) +* Fixed `:GoFmt` passing `g:go_fmt_options` options to `goimports`. This option + is only valid with `gofmt`. [[GH-590]](https://github.com/fatih/vim-go/pull/590) +* Fix vim-go for `cygwin` users. [[GH-575]](https://github.com/fatih/vim-go/pull/575) +* Fixed identifier in template files to be highlighted correctly [[GH-559]](https://github.com/fatih/vim-go/pull/559) +* Fixed character region in template files to be highlighted correctly [[GH-603]](https://github.com/fatih/vim-go/pull/603) +* Fixed variables in template files to be highlighted correctly [[GH-611]](https://github.com/fatih/vim-go/pull/611) +* Do not treat builtins as keywords. Now `make` will not highlighted but + `make()` will be highlighted (gh-605) + +## 1.2 (Oct 2, 2015) + +FEATURES: + +* A new `:GoMetaLinter` command which invokes [gometalinter](https://github.com/alecthomas/gometalinter). Please check the PR [[GH-553]](https://github.com/fatih/vim-go/pull/553) for more detail on customizing and usage of `:GoMetaLinter`. + +IMPROVEMENTS: + +* Improve `:GoImport` to trim spaces when including import paths of form `"fmt "` +* Avoid setting `filetype` twice. Previously it was doing it twice, which was expensive +* Improve handling of GOPATH's with trailing `/` characters, such as `/home/user/go/` +* Add a new `g:go_highlight_string_spellcheck` feature, which is enabled by feature. Now if spell is enabled, go strings are also checked. +* Specify our limited but functional [gb](http://getgb.io/) support + +BUG FIXES: +* Fixed `:GoRun` to display errors when `g:go_dispatch_enabled` was enabled +* Fixed `:GoDrop` displaying "Not enough arguments" (regression) +* Fixed `:GoErrCheck` not showing `PASS` message if the command was successful +* Fixed `:GoErrCheck` not executing in the directory of the currently edited file +* Close quickfix window after a successful second round of `:GoInstall` +* Fix passing files rather than packages to certain oracle commands. +* Escape files passed to oracle command. This could lead to some serious things. +* Clear `g:go_oracle_scope` when the scope was reseted. Previously it was set to empty string, which was causing false positives. +* Correct various misspellings. + +## 1.1 (Jul 25, 2015) + +With this release the version will now increase in `minor` levels. So the next +release will be `1.2`, the other one `1.3`, etc.. This provides us more +flexibility (like releasing patch versions if needed). + +FEATURES: +* A new `:GoGenerate` command is now available which can be used to invoke `go generate` within vim +* Vim-go didn't had any license, now we use BSD 3-Clause License (the same as Go). This is needed for Linux distributions to package vim-go and is also something that people asked for. + +IMPROVEMENTS: +* Improve commands `GoRun, GoTest{,Func,Compile}, GoCoverage, + GoGenerate, GoErrcheck, GoLint, and GoVet` to handle multiple arguments. + Previously this feature was limited to only certain commands. What this means + is, for example `:GoVet . -all` will invoke `go tool vet . -all` + automatically instead of plan `go vet`. This is one of the big changes in + this release, so give it a try :) +* Improved `:GoFmt` command, which now uses the `-w` flag to + write to the source code directly, instead of outputting it to stdout. This + makes `:GoFmt` much more faster than the current implementation. This is one + of the big changes in this release, so feedback is welcome! +* Improve `:GoImport` to have a `!` feature. Now when when called + with a `!` appended it will go get it. i.e: `:GoImport! + github.com/fatih/color`. Useful if `:GoImport` fails and you want to download + it. +* Automatic GOPATH detections can now detect `gb` vendored folders. Some commands should now work without any problem when invoked on a `gb` project. +* All command arguments are now properly escaped for shell invocation. +* Added the `-f` flag to :GoInstallBinaries command to support `git url..insteadOf` configuration +* Improve width and precision highlighting, such as `%s %5s %-5s %5.5f %.5f` +* Show an error if a region is not selected when `:GoFreeVars` is called + +BUG FIXES: +* Fix`:GoDef` for files containing spaces. We know escape the files before passing to `:GoDef` +* Fix `:GoFmt` not picking up the correct GOPATH when the fmt command was set to `goimports` +* Fix and simplify README.md, add Wiki reference +* Fixed tagbar integration to show correct imports. + + +## 1.0.5 (May 26, 2015) + +FEATURES: +* A new `:GoOracleScope` is added to change the oracle scope on-the-fly. It + accepts import paths as arguments. If no arguments are passed it prints the + current custom oracle scope. `:GoOracleScope` also supports completion of + import paths, so it's very fast and handy to use. `:GoOracleScope ""` clears + the current custom scope. +* A new `:GoPath` command that displays the current `GOPATH`. A path can be + passed to change the `GOPATH` (i.e `:GoPath ~/foo/src`). `:GoPath ""` clears + and resets the `GOPATH` to the initial value. +* A new "autodetect GOPATH" feature is added. This automatically detects if the + project is using `godep` or is under a `src` root directory which is not in + `GOPATH` and changes/modifies the `GOPATH` so all commands work based on this + GOPATH. What this means is, commands such as `:GoDef`, `:GoBuild`, etc.. will + include the Godeps folder. For example any go-to-definition via `:GoDef` will + jump to the source code inside Godeps. This is enabled by default, but can + disabled with `let g:go_autodetect_gopath = 0`. This new feature is also the + foundation for other tools such as `gb` or `wgo`. + +IMPROVEMENTS: +* Improve `:GoFmt` (gofmt and goimports) speed. Now it's 2x faster than the previous implementation. +* Add Dispatch support for `:GoBuild` and `:GoRun`. For more info about + dispatch see https://github.com/tpope/vim-dispatch . By default it's + disabled, to enable it add `let g:go_dispatch_enabled = 1` to your vimrc. +* Add support for the bang `!` attribute for all `go` tool commands. What this + does it, if `:GoBuild` is called it will jump to the error. But `:GoBuild!` + will not jump to any error. This has the same behavior as the internal + `:make` command in vim. We had this feature already for `:GoBuild` and + `:GoRun`. But not for `:GoInstall`, `:GoTest`, etc.. Now all commands are + unified. +* Add autojump to error for `:GoInstall`. +* Add autowrite feature for `:GoInstall`, `:GoTestXXX` functions and `:GoVet` +* Support `git url..insteadOf` and custom import paths of binaries. This + improves the commands `:GoInstallBinaries` and `:GoUpdateBinaries`. +* Add support for highlighting go templates with `*.tmpl` extensions. Based on + the work from @cespare from https://github.com/cespare/vim-go-templates + +BUG FIXES: +* Fix clearing the status bar when `:GoErrCheck` is called +* Fix godocNotFound to not match 'os' pkg contents. This improves the command + `:GoDoc` +* Fix parsing and jumping to error locations when used Vim from a different + directory than the current buffer's directory +* Fix completion showing duplicates paths for completion results, such as + github.com/fatih/color and github.com/fatih/color/. + +## 1.0.4 (Apr 28, 2015) + +FEATURES: + +* A new `:GoTestFunc` command (with appropriate + mappings) is added. Run tests function which surrounds the current cursor + location. Useful to test single tests. +* Highlight all Go operators. Previously not all + operators were highlighted. As previously, to highlight options, enable it + with by setting `g:go_highlight_operators` to 1 in your vimrc. + +IMPROVEMENTS: + +* Improved certain `:GoDoc` usages to show a better error message +* Improved `:GoRename` to have a default value for rename input. Avoids retyping similar words. +* Synced with latest Oracle version. `callgraph` is removed. +* Removed our custom referrers mode. New version of oracle now displays the matching lines. + +BUG FIXES: + +* Fixed the internal `executeInDir` function which was failing when ignorelist was not set properly. +* Fixed trailing slash for package completion with `:GoImport` +* Fixed paths in error list for Windows users. +* Fixed not showing "import cycle not allowed" error message when called `:GoBuild` or `:GoRun` +* Fixed users using vimproc requiring arguments to functions to be escaped. +* Fixed depth for test snippets +* Fixed neosnippet support loading snippet files the second time if necessary. + +## 1.0.3 (Mar 7, 2015) + +FEATURES: +* A new `:GoTestCompile` command (with appropriate mappings) is added. Useful to compile a test binary or show/fix compile errors in quickfix window + +IMPROVEMENTS: +* `referrer` mode is improved to show referring lines in the quickfix window +* A new `errt` snippet is added, which expands to `if err != nil { t.Fatal(err) }` +* A new `errh` snippet is added, useful to be used in a `http.Handler` +* UltiSnips snippets are improved to take advance of Vim's `Visual` mode. For example selecting a block and typing `if` will create an if scope around the block. +* Cleanup README.md + +BUG FIXES: +* Fix trimming brackets if completion was invoked on a previous completion +* Fix Oracle scope settings. Added docs about usage. +* Fixed previously broken `var` and `vars` snippets +* Fix duplicate docs +* Fix fallback binary path for Windows users. The fallback mechanism is used to discover the necessary Go tools, such as `godef`, `gocode`, etc... + +## 1.0.2 (Feb 17, 2015) + +FEATURES: + +* New snippets are added, mostly for testing ( [changes](https://github.com/fatih/vim-go/pull/321/files)) + +IMPROVEMENTS: + +* Enable all Oracle commands. Docs, mappings and commands are also added. It uses Quickfix list instead of a custom UI. +* Clarify installation process in Readme, add instructions for vim-plug, NeoBundle and manual. + +BUG FIXES: + +* Fix shiftwidth parsing, it was broken in the previous release for old Vim versions +* Fix experimantal mode + + +## 1.0.1 (Feb 9, 2015) + +FEATURES: + +* New feature to highlight build constraints (disabled by default) + +IMPROVEMENTS: + +* Updated godef import path +* Updated Readme for possible problems with `csh` +* Documentation for text objects are updated, typo fixes are merged +* If vimproc is installed, Windows users will use it for autocompletion +* Improve UltiSnips snippets to pick Visual selection (demo: http://quick.as/0dvigz5) +* Packages with extensions, like "gopkg.in/yaml.v2" can be now displayed +* Packages with different import paths, like "github.com/bitly/go-simplejson" can be now displayed + +BUG FIXES: + +* Fatal errors are now parsed successfully and populated to quickfix list +* Shiftwidth is changed to use shiftwidth() function. Fixes usage with plugins like vim-sleuth and possible mis usage (like setting shiftwidth to zero) +* Added a new [Donation](https://github.com/fatih/vim-go#donations) section to Readme, for those who ask for it. +* Fix parsing of errcheck error syntax +* Fix consistency between Neosnippet and UltiSnips snippets + + +## 1.0 (Dec 24, 2014) + +We don't tag any changes or releases, so let's start with `1.0`. Our Windows +support is now in a good shape, tons of bugs are fixed, many new features and +improvements is being added and it's getting better with each day (thanks to +the community contributions). + +## 0.0 (Mar 24, 2014) + +Initial commit: https://github.com/fatih/vim-go/commit/78c5caa82c111c50e9c219f222d65b07694f8f5a + + diff --git a/sources_non_forked/vim-go/Dockerfile b/sources_non_forked/vim-go/Dockerfile new file mode 100644 index 00000000..1b23bea8 --- /dev/null +++ b/sources_non_forked/vim-go/Dockerfile @@ -0,0 +1,19 @@ +FROM golang:1.9.1 + +RUN apt-get update -y && \ + apt-get install -y build-essential curl git libncurses5-dev python3-pip && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* + +RUN useradd -ms /bin/bash -d /vim-go vim-go +USER vim-go + +COPY . /vim-go/ +WORKDIR /vim-go + +RUN scripts/install-vim vim-7.4 +RUN scripts/install-vim vim-8.0 +RUN scripts/install-vim nvim +RUN pip3 install vim-vint + +ENTRYPOINT ["make"] diff --git a/sources_non_forked/vim-go/LICENSE b/sources_non_forked/vim-go/LICENSE index e9cc0dcd..d9493d4f 100644 --- a/sources_non_forked/vim-go/LICENSE +++ b/sources_non_forked/vim-go/LICENSE @@ -25,7 +25,7 @@ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - + This software includes some portions from Go. Go is used under the terms of the BSD like license. @@ -56,3 +56,5 @@ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The Go gopher was designed by Renee French. http://reneefrench.blogspot.com/ The design is licensed under the Creative Commons 3.0 Attributions license. Read this article for more details: https://blog.golang.org/gopher diff --git a/sources_non_forked/vim-go/Makefile b/sources_non_forked/vim-go/Makefile new file mode 100644 index 00000000..3645c324 --- /dev/null +++ b/sources_non_forked/vim-go/Makefile @@ -0,0 +1,28 @@ +all: install test lint + +install: + @echo "==> Installing Vims" + @./scripts/install-vim vim-7.4 + @./scripts/install-vim vim-8.0 + @./scripts/install-vim nvim + +test: + @echo "==> Running tests" + @./scripts/test vim-7.4 + @./scripts/test vim-8.0 + @./scripts/test nvim + +lint: + @echo "==> Running linting tools" + @./scripts/lint vim-8.0 + +docker: + @echo "==> Building/starting Docker container" + @./scripts/docker-test + +clean: + @echo "==> Cleaning /tmp/vim-go-test" + @rm -rf /tmp/vim-go-test + + +.PHONY: all test install clean lint docker diff --git a/sources_non_forked/vim-go/README.md b/sources_non_forked/vim-go/README.md index e8dc40a5..8566224a 100644 --- a/sources_non_forked/vim-go/README.md +++ b/sources_non_forked/vim-go/README.md @@ -1,302 +1,71 @@ -# vim-go +# vim-go [![Build Status](http://img.shields.io/travis/fatih/vim-go.svg?style=flat-square)](https://travis-ci.org/fatih/vim-go) -Go (golang) support for Vim, which comes with pre-defined sensible settings (like -auto gofmt on save), with autocomplete, snippet support, improved syntax -highlighting, go toolchain commands, and more. If needed vim-go installs all -necessary binaries for providing seamless Vim integration with current -commands. It's highly customizable and each individual feature can be -disabled/enabled easily. - -![vim-go](https://dl.dropboxusercontent.com/u/174404/vim-go-2.png) +

+ Vim-go logo +

## Features -* Improved Syntax highlighting with items such as Functions, Operators, Methods. -* Auto completion support via `gocode` -* Better `gofmt` on save, which keeps cursor position and doesn't break your undo - history -* Go to symbol/declaration with `:GoDef` -* Look up documentation with `:GoDoc` inside Vim or open it in browser -* Automatically import packages via `:GoImport` or plug it into autosave -* Compile your package with `:GoBuild`, install it with `:GoInstall` or test - them with `:GoTest` (also supports running single tests via `:GoTestFunc`) -* Quickly execute your current file/files with `:GoRun` -* Automatic `GOPATH` detection based on the directory structure (i.e. `gb` - projects, `godep` vendored projects) -* Change or display `GOPATH` with `:GoPath` -* Create a coverage profile and display annotated source code to see which - functions are covered with `:GoCoverage` -* Call `gometalinter` with `:GoMetaLinter`, which invokes all possible linters - (golint, vet, errcheck, deadcode, etc..) and shows the warnings/errors -* Lint your code with `:GoLint` -* Run your code through `:GoVet` to catch static errors -* Advanced source analysis tools utilizing guru, such as `:GoImplements`, - `:GoCallees`, and `:GoReferrers` -* Precise type-safe renaming of identifiers with `:GoRename` -* List all source files and dependencies -* Unchecked error checking with `:GoErrCheck` -* Integrated and improved snippets, supporting `ultisnips` or `neosnippet` -* Share your current code to [play.golang.org](http://play.golang.org) with `:GoPlay` -* On-the-fly type information about the word under the cursor. Plug it into - your custom vim function. -* Go asm formatting on save -* Tagbar support to show tags of the source code in a sidebar with `gotags` -* Custom vim text objects such as `a function` or `inner function` - list. -* Jump to function or type declarations with `:GoDecls` or `:GoDeclsDir` -* A async launcher for the go command is implemented for Neovim, fully async - building and testing (beta). -* Integrated with the Neovim terminal, launch `:GoRun` and other go commands - in their own new terminal. (beta) -* Alternate between implementation and test code with `:GoAlternate` +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 + with `:GoTest`. Run a single tests with `:GoTestFunc`). +* Quickly execute your current file(s) with `:GoRun`. +* Improved syntax highlighting and folding. +* Completion support via `gocode`. +* `gofmt` or `goimports` on save keeps the cursor position and undo history. +* Go to symbol/declaration with `:GoDef`. +* Look up documentation with `:GoDoc` or `:GoDocBrowser`. +* Easily import packages via `:GoImport`, remove them via `:GoDrop`. +* Automatic `GOPATH` detection which works with `gb` and `godep`. Change or + display `GOPATH` with `:GoPath`. +* See which code is covered by tests with `:GoCoverage`. +* Add or remove tags on struct fields with `:GoAddTags` and `:GoRemoveTags`. +* Call `gometalinter` with `:GoMetaLinter` to invoke all possible linters + (`golint`, `vet`, `errcheck`, `deadcode`, etc.) and put the result in the + quickfix or location list. +* Lint your code with `:GoLint`, run your code through `:GoVet` to catch static + errors, or make sure errors are checked with `:GoErrCheck`. +* Advanced source analysis tools utilizing `guru`, such as `:GoImplements`, + `: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 + information. ## Install -Master branch is supposed to be a development branch. So stuff here can break and change. -Please try use always the [latest release](https://github.com/fatih/vim-go/releases/latest) +The [**latest stable release**](https://github.com/fatih/vim-go/releases/latest) is the +recommended version to use. If you choose to use the master branch instead, +please do so with caution; it is a _development_ branch. -Vim-go follows the standard runtime path structure, so I highly recommend to -use a common and well known plugin manager to install vim-go. Do not use vim-go -with other Go oriented vim plugins. For Pathogen just clone the repo. For other -plugin managers add the appropriate lines and execute the plugin's install -command. +vim-go follows the standard runtime path structure. Below are some helper lines +for popular package managers: -* [Pathogen](https://github.com/tpope/vim-pathogen) +* [Vim 8 packages](http://vimhelp.appspot.com/repeat.txt.html#packages) + * `git clone https://github.com/fatih/vim-go.git ~/.vim/pack/plugins/start/vim-go` +* [Pathogen](https://github.com/tpope/vim-pathogen) * `git clone https://github.com/fatih/vim-go.git ~/.vim/bundle/vim-go` -* [vim-plug](https://github.com/junegunn/vim-plug) +* [vim-plug](https://github.com/junegunn/vim-plug) * `Plug 'fatih/vim-go'` -* [NeoBundle](https://github.com/Shougo/neobundle.vim) - * `NeoBundle 'fatih/vim-go'` -* [Vundle](https://github.com/gmarik/vundle) - * `Plugin 'fatih/vim-go'` -Please be sure all necessary binaries are installed (such as `gocode`, `godef`, -`goimports`, etc.). You can easily install them with the included -`:GoInstallBinaries` command. If invoked, all necessary binaries will be -automatically downloaded and installed to your `$GOBIN` environment (if not set -it will use `$GOPATH/bin`). Note that this command requires `git` for fetching -the individual Go packages. Additionally, use `:GoUpdateBinaries` to update the -installed binaries. +You will also need to install all the necessary binaries. vim-go makes it easy +to install all of them by providing a command, `:GoInstallBinaries`, which will +`go get` all the required binaries. -### Optional - -* Autocompletion is enabled by default via ``. To get real-time -completion (completion by type) install: -[neocomplete](https://github.com/Shougo/neocomplete.vim) for Vim or -[deoplete](https://github.com/Shougo/deoplete.nvim) and -[deoplete-go](https://github.com/zchee/deoplete-go) for NeoVim -* To display source code tag information on a sidebar install -[tagbar](https://github.com/majutsushi/tagbar). -* For snippet features install: -[neosnippet](https://github.com/Shougo/neosnippet.vim) or -[ultisnips](https://github.com/SirVer/ultisnips). -* Screenshot color scheme is a slightly modified molokai: - [fatih/molokai](https://github.com/fatih/molokai). -* For a better documentation viewer checkout: - [go-explorer](https://github.com/garyburd/go-explorer). +Check out the Install section in [the documentation](doc/vim-go.txt) for more +detailed instructions (`:help go-install`). ## Usage -Many of the plugin's [features](#features) are enabled by default. There are no -additional settings needed. All usages and commands are listed in -`doc/vim-go.txt`. Note that help tags needs to be populated. Check your plugin -manager settings to generate the documentation (some do it automatically). -After that just open the help page to see all commands: +The full documentation can be found at [doc/vim-go.txt](doc/vim-go.txt). You can +display it from within Vim with `:help vim-go`. - :help vim-go +Depending on your installation method, you may have to generate the plugin's +[`help tags`](http://vimhelp.appspot.com/helphelp.txt.html#%3Ahelptags) +manually (e.g. `:helptags ALL`). -## Example Mappings - -vim-go has several `` mappings which can be used to create custom -mappings. Unless otherwise specified, none of these mappings are enabled -by default. Here some examples you might find useful: - -Run commands such as `go run` for the current file with `r` or `go -build` and `go test` for the current package with `b` and `t` -respectively. Display beautifully annotated source code to see which functions -are covered with `c`. - -```vim -au FileType go nmap r (go-run) -au FileType go nmap b (go-build) -au FileType go nmap t (go-test) -au FileType go nmap c (go-coverage) -``` - -By default the mapping `gd` is enabled, which opens the target identifier in -current buffer. You can also open the definition/declaration, in a new vertical, -horizontal, or tab, for the word under your cursor: - -```vim -au FileType go nmap ds (go-def-split) -au FileType go nmap dv (go-def-vertical) -au FileType go nmap dt (go-def-tab) -``` - -Open the relevant Godoc for the word under the cursor with `gd` or open -it vertically with `gv` - -```vim -au FileType go nmap gd (go-doc) -au FileType go nmap gv (go-doc-vertical) -``` - -Or open the Godoc in browser - -```vim -au FileType go nmap gb (go-doc-browser) -``` - -Show a list of interfaces which is implemented by the type under your cursor -with `s` - -```vim -au FileType go nmap s (go-implements) -``` - -Show type info for the word under your cursor with `i` (useful if you -have disabled auto showing type info via `g:go_auto_type_info`) - -```vim -au FileType go nmap i (go-info) -``` - -Rename the identifier under the cursor to a new name - -```vim -au FileType go nmap e (go-rename) -``` - -More `` mappings can be seen with `:he go-mappings`. Also these are just -recommendations, you are free to create more advanced mappings or functions -based on `:he go-commands`. - -## Settings -Below are some settings you might find useful. For the full list see `:he -go-settings`. - -By default syntax-highlighting for Functions, Methods and Structs is disabled. -To change it: -```vim -let g:go_highlight_functions = 1 -let g:go_highlight_methods = 1 -let g:go_highlight_fields = 1 -let g:go_highlight_structs = 1 -let g:go_highlight_interfaces = 1 -let g:go_highlight_operators = 1 -let g:go_highlight_build_constraints = 1 -``` - -Enable goimports to automatically insert import paths instead of gofmt: - -```vim -let g:go_fmt_command = "goimports" -``` - -By default vim-go shows errors for the fmt command, to disable it: - -```vim -let g:go_fmt_fail_silently = 1 -``` - -Disable auto fmt on save: - -```vim -let g:go_fmt_autosave = 0 -``` - -Disable opening browser after posting your snippet to `play.golang.org`: - -```vim -let g:go_play_open_browser = 0 -``` - -By default when `:GoInstallBinaries` is called, the binaries are installed to -`$GOBIN` or `$GOPATH/bin`. To change it: - -```vim -let g:go_bin_path = expand("~/.gotools") -let g:go_bin_path = "/home/fatih/.mypath" "or give absolute path -``` - -Disable updating dependencies when installing/updating binaries: -```vim -let g:go_get_update = 0 -``` - -### Using with Neovim (beta) - -Note: Neovim currently is not a first class citizen for vim-go. You are free -to open bugs but I'm not going to look at them. Even though I'm using Neovim -myself, Neovim itself is still alpha. So vim-go might not work well as good as -in Vim. I'm happy to accept pull requests or very detailed bug reports. - - -Run `:GoRun` in a new tab, horizontal split or vertical split terminal - -```vim -au FileType go nmap rt (go-run-tab) -au FileType go nmap rs (go-run-split) -au FileType go nmap rv (go-run-vertical) -``` - -By default new terminals are opened in a vertical split. To change it - -```vim -let g:go_term_mode = "split" -``` - -By default the testing commands run asynchronously in the background and -display results with `go#jobcontrol#Statusline()`. To make them run in a new -terminal - -```vim -let g:go_term_enabled = 1 -``` - -### Using with Syntastic -Sometimes when using both `vim-go` and `syntastic` Vim will start lagging while -saving and opening files. The following fixes this: - -```vim -let g:syntastic_go_checkers = ['golint', 'govet', 'errcheck'] -let g:syntastic_mode_map = { 'mode': 'active', 'passive_filetypes': ['go'] } -``` - -Another issue with `vim-go` and `syntastic` is that the location list window -that contains the output of commands such as `:GoBuild` and `:GoTest` might not appear. -To resolve this: - -```vim -let g:go_list_type = "quickfix" -``` - - -## More info - -Check out the [Wiki](https://github.com/fatih/vim-go/wiki) page for more -information. It includes -[Screencasts](https://github.com/fatih/vim-go/wiki/Screencasts), an [FAQ -section](https://github.com/fatih/vim-go/wiki/FAQ-Troubleshooting), and many -other [various pieces](https://github.com/fatih/vim-go/wiki) of information. - -## Donation - -People have asked for this for a long time, now you can be a fully supporter by -[being a patron](https://www.patreon.com/fatih)! This is fully optional and is -just a way to support vim-go's ongoing development directly. Thanks! - -[https://www.patreon.com/fatih](https://www.patreon.com/fatih) - -## Credits - -* Go Authors for official vim plugins -* Gocode, Godef, Golint, Guru, Goimports, Gotags, Errcheck projects and - authors of those projects. -* Other vim-plugins, thanks for inspiration (vim-golang, go.vim, vim-gocode, - vim-godef) -* [Contributors](https://github.com/fatih/vim-go/graphs/contributors) of vim-go +We also have an [official vim-go tutorial](https://github.com/fatih/vim-go-tutorial). ## License -The BSD 3-Clause License - see `LICENSE` for more details +The BSD 3-Clause License - see [`LICENSE`](LICENSE) for more details diff --git a/sources_non_forked/vim-go/Rakefile b/sources_non_forked/vim-go/Rakefile deleted file mode 100644 index 64346ff0..00000000 --- a/sources_non_forked/vim-go/Rakefile +++ /dev/null @@ -1,13 +0,0 @@ -#!/usr/bin/env rake - -task :ci => [:dump, :test] - -task :dump do - sh 'vim --version' -end - -# Firstly, `bundle install; bundle install --deployment` -# Then, `rake test` -task :test do - sh 'bundle exec vim-flavor test' -end diff --git a/sources_non_forked/vim-go/assets/screenshot.png b/sources_non_forked/vim-go/assets/screenshot.png new file mode 100644 index 00000000..8b2923d7 Binary files /dev/null and b/sources_non_forked/vim-go/assets/screenshot.png differ diff --git a/sources_non_forked/vim-go/assets/vim-go.png b/sources_non_forked/vim-go/assets/vim-go.png new file mode 100644 index 00000000..cb26e2c0 Binary files /dev/null and b/sources_non_forked/vim-go/assets/vim-go.png differ diff --git a/sources_non_forked/vim-go/assets/vim-go.svg b/sources_non_forked/vim-go/assets/vim-go.svg new file mode 100644 index 00000000..8471db59 --- /dev/null +++ b/sources_non_forked/vim-go/assets/vim-go.svg @@ -0,0 +1,821 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sources_non_forked/vim-go/autoload/ctrlp/decls.vim b/sources_non_forked/vim-go/autoload/ctrlp/decls.vim index 5a625317..00ecb89a 100644 --- a/sources_non_forked/vim-go/autoload/ctrlp/decls.vim +++ b/sources_non_forked/vim-go/autoload/ctrlp/decls.vim @@ -1,26 +1,26 @@ let s:go_decls_var = { - \ 'init': 'ctrlp#decls#init()', - \ 'exit': 'ctrlp#decls#exit()', - \ 'enter': 'ctrlp#decls#enter()', - \ 'accept': 'ctrlp#decls#accept', - \ 'lname': 'declarations', - \ 'sname': 'decls', - \ 'type': 'tabs', - \} + \ 'init': 'ctrlp#decls#init()', + \ 'exit': 'ctrlp#decls#exit()', + \ 'enter': 'ctrlp#decls#enter()', + \ 'accept': 'ctrlp#decls#accept', + \ 'lname': 'declarations', + \ 'sname': 'decls', + \ 'type': 'tabs', + \} if exists('g:ctrlp_ext_vars') && !empty(g:ctrlp_ext_vars) - let g:ctrlp_ext_vars = add(g:ctrlp_ext_vars, s:go_decls_var) + let g:ctrlp_ext_vars = add(g:ctrlp_ext_vars, s:go_decls_var) else - let g:ctrlp_ext_vars = [s:go_decls_var] + let g:ctrlp_ext_vars = [s:go_decls_var] endif -function! ctrlp#decls#init() - cal s:enable_syntax() - return s:decls +function! ctrlp#decls#init() abort + cal s:enable_syntax() + return s:decls endfunction -function! ctrlp#decls#exit() - unlet! s:decls s:current_dir s:target +function! ctrlp#decls#exit() abort + unlet! s:decls s:current_dir s:target endfunction " The action to perform on the selected string @@ -28,131 +28,128 @@ endfunction " a:mode the mode that has been chosen by pressing or " the values are 'e', 'v', 't' and 'h', respectively " a:str the selected string -function! ctrlp#decls#accept(mode, str) - let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd ' - let dir = getcwd() - try - " we jump to the file directory so we can get the fullpath via fnamemodify - " below - execute cd . s:current_dir +function! ctrlp#decls#accept(mode, str) abort + let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd ' + let dir = getcwd() + try + " we jump to the file directory so we can get the fullpath via fnamemodify + " below + execute cd . s:current_dir - let vals = matchlist(a:str, '|\(.\{-}\):\(\d\+\):\(\d\+\)\s*\(.*\)|') + let vals = matchlist(a:str, '|\(.\{-}\):\(\d\+\):\(\d\+\)\s*\(.*\)|') - " i.e: main.go - let filename = vals[1] - let line = vals[2] - let col = vals[3] + " i.e: main.go + let filename = vals[1] + let line = vals[2] + let col = vals[3] - " i.e: /Users/fatih/vim-go/main.go - let filepath = fnamemodify(filename, ":p") + " i.e: /Users/fatih/vim-go/main.go + let filepath = fnamemodify(filename, ":p") - " acceptile is a very versatile method, - call ctrlp#acceptfile(a:mode, filepath) - call cursor(line, col) - silent! norm! zvzz - finally - "jump back to old dir - execute cd . fnameescape(dir) - endtry + " acceptile is a very versatile method, + call ctrlp#acceptfile(a:mode, filepath) + call cursor(line, col) + silent! norm! zvzz + finally + "jump back to old dir + execute cd . fnameescape(dir) + endtry endfunction -function! ctrlp#decls#enter() - let s:current_dir = fnameescape(expand('%:p:h')) - let s:decls = [] +function! ctrlp#decls#enter() abort + let s:current_dir = fnameescape(expand('%:p:h')) + let s:decls = [] - let bin_path = go#path#CheckBinPath('motion') - if empty(bin_path) - return - endif - let command = printf("%s -format vim -mode decls", bin_path) - let command .= " -include ". get(g:, "go_decls_includes", "func,type") + let bin_path = go#path#CheckBinPath('motion') + if empty(bin_path) + return + endif + let command = printf("%s -format vim -mode decls", bin_path) + let command .= " -include ". get(g:, "go_decls_includes", "func,type") - call go#cmd#autowrite() + call go#cmd#autowrite() - if s:mode == 0 - " current file mode - let fname = expand("%:p") - if exists('s:target') - let fname = s:target - endif + if s:mode == 0 + " current file mode + let fname = expand("%:p") + if exists('s:target') + let fname = s:target + endif - let command .= printf(" -file %s", fname) - else - " all functions mode - let dir = expand("%:p:h") - if exists('s:target') - let dir = s:target - endif + let command .= printf(" -file %s", fname) + else + " all functions mode + let dir = expand("%:p:h") + if exists('s:target') + let dir = s:target + endif - let command .= printf(" -dir %s", dir) - endif + let command .= printf(" -dir %s", dir) + endif - let out = go#util#System(command) - if go#util#ShellError() != 0 - call go#util#EchoError(out) - return - endif + let out = go#util#System(command) + if go#util#ShellError() != 0 + call go#util#EchoError(out) + return + endif - if exists("l:tmpname") - call delete(l:tmpname) - endif + let result = eval(out) + if type(result) != 4 || !has_key(result, 'decls') + return + endif - let result = eval(out) - if type(result) != 4 || !has_key(result, 'decls') - return - endif + let decls = result.decls - let decls = result.decls + " find the maximum function name + let max_len = 0 + for decl in decls + if len(decl.ident)> max_len + let max_len = len(decl.ident) + endif + endfor - " find the maximum function name - let max_len = 0 - for decl in decls - if len(decl.ident)> max_len - let max_len = len(decl.ident) - endif - endfor + for decl in decls + " paddings + let space = " " + for i in range(max_len - len(decl.ident)) + let space .= " " + endfor - for decl in decls - " paddings - let space = " " - for i in range(max_len - len(decl.ident)) - let space .= " " - endfor - - call add(s:decls, printf("%s\t%s |%s:%s:%s|\t%s", - \ decl.ident . space, - \ decl.keyword, - \ fnamemodify(decl.filename, ":t"), - \ decl.line, - \ decl.col, - \ decl.full, - \)) - endfor + call add(s:decls, printf("%s\t%s |%s:%s:%s|\t%s", + \ decl.ident . space, + \ decl.keyword, + \ fnamemodify(decl.filename, ":t"), + \ decl.line, + \ decl.col, + \ decl.full, + \)) + endfor endfunc -function! s:enable_syntax() - if !(has('syntax') && exists('g:syntax_on')) - return - endif +function! s:enable_syntax() abort + if !(has('syntax') && exists('g:syntax_on')) + return + endif - syntax match CtrlPIdent '\zs\h\+\ze\s' - syntax match CtrlPKeyword '\zs[^\t|]\+\ze|[^|]\+:\d\+:\d\+|' - syntax match CtrlPFilename '|\zs[^|]\+:\d\+:\d\+\ze|' - syntax match CtrlPSignature '\zs\t.*\ze$' contains=CtrlPKeyWord,CtrlPFilename + syntax match CtrlPIdent '\zs\h\+\ze\s' + syntax match CtrlPKeyword '\zs[^\t|]\+\ze|[^|]\+:\d\+:\d\+|' + syntax match CtrlPFilename '|\zs[^|]\+:\d\+:\d\+\ze|' + syntax match CtrlPSignature '\zs\t.*\ze$' contains=CtrlPKeyWord,CtrlPFilename - highlight link CtrlPIdent Function - highlight link CtrlPKeyword Keyword - highlight link CtrlPFilename SpecialComment - highlight link CtrlPSignature Comment + highlight link CtrlPIdent Function + highlight link CtrlPKeyword Keyword + highlight link CtrlPFilename SpecialComment + highlight link CtrlPSignature Comment endfunction let s:id = g:ctrlp_builtins + len(g:ctrlp_ext_vars) -function! ctrlp#decls#cmd(mode, ...) - let s:mode = a:mode - if a:0 && !empty(a:1) - let s:target = a:1 - endif - return s:id +function! ctrlp#decls#cmd(mode, ...) abort + let s:mode = a:mode + if a:0 && !empty(a:1) + let s:target = a:1 + endif + return s:id endfunction +" vim: sw=2 ts=2 et diff --git a/sources_non_forked/vim-go/autoload/fzf/decls.vim b/sources_non_forked/vim-go/autoload/fzf/decls.vim new file mode 100644 index 00000000..255320ec --- /dev/null +++ b/sources_non_forked/vim-go/autoload/fzf/decls.vim @@ -0,0 +1,150 @@ +function! s:code(group, attr) abort + let code = synIDattr(synIDtrans(hlID(a:group)), a:attr, "cterm") + if code =~ '^[0-9]\+$' + return code + endif +endfunction + +function! s:color(str, group) abort + let fg = s:code(a:group, "fg") + let bg = s:code(a:group, "bg") + let bold = s:code(a:group, "bold") + let italic = s:code(a:group, "italic") + let reverse = s:code(a:group, "reverse") + let underline = s:code(a:group, "underline") + let color = (empty(fg) ? "" : ("38;5;".fg)) . + \ (empty(bg) ? "" : (";48;5;".bg)) . + \ (empty(bold) ? "" : ";1") . + \ (empty(italic) ? "" : ";3") . + \ (empty(reverse) ? "" : ";7") . + \ (empty(underline) ? "" : ";4") + return printf("\x1b[%sm%s\x1b[m", color, a:str) +endfunction + +function! s:sink(str) abort + if len(a:str) < 2 + return + endif + let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd ' + let dir = getcwd() + try + " we jump to the file directory so we can get the fullpath via fnamemodify + " below + execute cd . fnameescape(s:current_dir) + + let vals = matchlist(a:str[1], '|\(.\{-}\):\(\d\+\):\(\d\+\)\s*\(.*\)|') + + " i.e: main.go + let filename = vals[1] + let line = vals[2] + let col = vals[3] + + " i.e: /Users/fatih/vim-go/main.go + let filepath = fnamemodify(filename, ":p") + + let cmd = get({'ctrl-x': 'split', + \ 'ctrl-v': 'vertical split', + \ 'ctrl-t': 'tabe'}, a:str[0], 'e') + execute cmd fnameescape(filepath) + call cursor(line, col) + silent! norm! zvzz + finally + "jump back to old dir + execute cd . fnameescape(dir) + endtry +endfunction + +function! s:source(mode,...) abort + let s:current_dir = expand('%:p:h') + let ret_decls = [] + + let bin_path = go#path#CheckBinPath('motion') + if empty(bin_path) + return + endif + let command = printf("%s -format vim -mode decls", bin_path) + let command .= " -include ". get(g:, "go_decls_includes", "func,type") + + call go#cmd#autowrite() + + if a:mode == 0 + " current file mode + let fname = expand("%:p") + if a:0 && !empty(a:1) + let fname = a:1 + endif + + let command .= printf(" -file %s", shellescape(fname)) + else + " all functions mode + if a:0 && !empty(a:1) + let s:current_dir = a:1 + endif + + let command .= printf(" -dir %s", shellescape(s:current_dir)) + endif + + let out = go#util#System(command) + if go#util#ShellError() != 0 + call go#util#EchoError(out) + return + endif + + let result = eval(out) + if type(result) != 4 || !has_key(result, 'decls') + return ret_decls + endif + + let decls = result.decls + + " find the maximum function name + let max_len = 0 + for decl in decls + if len(decl.ident)> max_len + let max_len = len(decl.ident) + endif + endfor + + for decl in decls + " paddings + let space = " " + for i in range(max_len - len(decl.ident)) + let space .= " " + endfor + + let pos = printf("|%s:%s:%s|", + \ fnamemodify(decl.filename, ":t"), + \ decl.line, + \ decl.col + \) + call add(ret_decls, printf("%s\t%s %s\t%s", + \ s:color(decl.ident . space, "Function"), + \ s:color(decl.keyword, "Keyword"), + \ s:color(pos, "SpecialComment"), + \ s:color(decl.full, "Comment"), + \)) + endfor + + return ret_decls +endfunc + +function! fzf#decls#cmd(...) abort + let normal_fg = s:code("Normal", "fg") + let normal_bg = s:code("Normal", "bg") + let cursor_fg = s:code("CursorLine", "fg") + let cursor_bg = s:code("CursorLine", "bg") + let colors = printf(" --color %s%s%s%s%s", + \ &background, + \ empty(normal_fg) ? "" : (",fg:".normal_fg), + \ empty(normal_bg) ? "" : (",bg:".normal_bg), + \ empty(cursor_fg) ? "" : (",fg+:".cursor_fg), + \ empty(cursor_bg) ? "" : (",bg+:".cursor_bg), + \) + call fzf#run(fzf#wrap('GoDecls', { + \ 'source': call('source', a:000), + \ 'options': '-n 1 --ansi --prompt "GoDecls> " --expect=ctrl-t,ctrl-v,ctrl-x'.colors, + \ 'sink*': function('s:sink') + \ })) +endfunction + +" vim: sw=2 ts=2 et diff --git a/sources_non_forked/vim-go/autoload/go/alternate.vim b/sources_non_forked/vim-go/autoload/go/alternate.vim index 1de6a699..f2cb210f 100644 --- a/sources_non_forked/vim-go/autoload/go/alternate.vim +++ b/sources_non_forked/vim-go/autoload/go/alternate.vim @@ -4,7 +4,7 @@ if !exists("g:go_alternate_mode") endif " Test alternates between the implementation of code and the test code. -function! go#alternate#Switch(bang, cmd) +function! go#alternate#Switch(bang, cmd) abort let file = expand('%') if empty(file) call go#util#EchoError("no buffer name") @@ -28,3 +28,5 @@ function! go#alternate#Switch(bang, cmd) execute ":" . a:cmd . " " . alt_file endif endfunction + +" vim: sw=2 ts=2 et diff --git a/sources_non_forked/vim-go/autoload/go/asmfmt.vim b/sources_non_forked/vim-go/autoload/go/asmfmt.vim index 7fb52670..cc8acd3b 100644 --- a/sources_non_forked/vim-go/autoload/go/asmfmt.vim +++ b/sources_non_forked/vim-go/autoload/go/asmfmt.vim @@ -11,7 +11,7 @@ " " Options: " -" g:go_asmfmt_autosave [default=1] +" g:go_asmfmt_autosave [default=0] " " Flag to automatically call :Fmt when file is saved. @@ -19,13 +19,13 @@ let s:got_fmt_error = 0 " This is a trimmed-down version of the logic in fmt.vim. -function! go#asmfmt#Format() +function! go#asmfmt#Format() abort " Save state. let l:curw = winsaveview() " Write the current buffer to a tempfile. let l:tmpname = tempname() - call writefile(getline(1, '$'), l:tmpname) + call writefile(go#util#GetLines(), l:tmpname) " Run asmfmt. let path = go#path#CheckBinPath("asmfmt") @@ -41,7 +41,11 @@ function! go#asmfmt#Format() " Replace the current file with the temp file; then reload the buffer. let old_fileformat = &fileformat + " save old file permissions + let original_fperm = getfperm(expand('%')) call rename(l:tmpname, expand('%')) + " restore old file permissions + call setfperm(expand('%'), original_fperm) silent edit! let &fileformat = old_fileformat let &syntax = &syntax @@ -50,3 +54,16 @@ function! go#asmfmt#Format() " Restore the cursor/window positions. call winrestview(l:curw) endfunction + +function! go#asmfmt#ToggleAsmFmtAutoSave() abort + if get(g:, "go_asmfmt_autosave", 0) + let g:go_asmfmt_autosave = 1 + call go#util#EchoProgress("auto asmfmt enabled") + return + end + + let g:go_asmfmt_autosave = 0 + call go#util#EchoProgress("auto asmfmt disabled") +endfunction + +" vim: sw=2 ts=2 et diff --git a/sources_non_forked/vim-go/autoload/go/cmd.vim b/sources_non_forked/vim-go/autoload/go/cmd.vim index b31466a2..e6fdac54 100644 --- a/sources_non_forked/vim-go/autoload/go/cmd.vim +++ b/sources_non_forked/vim-go/autoload/go/cmd.vim @@ -1,361 +1,331 @@ -if !exists("g:go_dispatch_enabled") - let g:go_dispatch_enabled = 0 -endif - -function! go#cmd#autowrite() - if &autowrite == 1 - silent wall - endif +function! go#cmd#autowrite() abort + if &autowrite == 1 + silent! wall + endif endfunction - -" Build builds the source code without producting any output binary. We live in +" Build builds the source code without producing any output binary. We live in " an editor so the best is to build it to catch errors and fix them. By " default it tries to call simply 'go build', but it first tries to get all " dependent files for the current folder and passes it to go build. -function! go#cmd#Build(bang, ...) - " expand all wildcards(i.e: '%' to the current file name) - let goargs = map(copy(a:000), "expand(v:val)") +function! go#cmd#Build(bang, ...) abort + " Create our command arguments. go build discards any results when it + " compiles multiple packages. So we pass the `errors` package just as an + " placeholder with the current folder (indicated with '.'). We also pass -i + " that tries to install the dependencies, this has the side effect that it + " caches the build results, so every other build is faster. + let args = + \ ["build"] + + \ map(copy(a:000), "expand(v:val)") + + \ ["-i", ".", "errors"] - " escape all shell arguments before we pass it to make - let goargs = go#util#Shelllist(goargs, 1) - - " create our command arguments. go build discards any results when it - " compiles multiple packages. So we pass the `errors` package just as an - " placeholder with the current folder (indicated with '.') - let args = ["build"] + goargs + [".", "errors"] - - " if we have nvim, call it asynchronously and return early ;) - if has('nvim') - call go#util#EchoProgress("building dispatched ...") - call go#jobcontrol#Spawn(a:bang, "build", args) - return + " Vim async. + if go#util#has_job() + if get(g:, 'go_echo_command_info', 1) + call go#util#EchoProgress("building dispatched ...") endif + call s:cmd_job({ + \ 'cmd': ['go'] + args, + \ 'bang': a:bang, + \ 'for': 'GoBuild', + \}) + + " Nvim async. + elseif has('nvim') + if get(g:, 'go_echo_command_info', 1) + call go#util#EchoProgress("building dispatched ...") + endif + + call go#jobcontrol#Spawn(a:bang, "build", "GoBuild", args) + + " Vim 7.4 without async + else let old_gopath = $GOPATH let $GOPATH = go#path#Detect() let default_makeprg = &makeprg - let &makeprg = "go " . join(args, ' ') + let &makeprg = "go " . join(go#util#Shelllist(args), ' ') - let l:listtype = go#list#Type("quickfix") + let l:listtype = go#list#Type("GoBuild") " execute make inside the source folder so we can parse the errors " correctly let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd ' let dir = getcwd() try - execute cd . fnameescape(expand("%:p:h")) - if g:go_dispatch_enabled && exists(':Make') == 2 - call go#util#EchoProgress("building dispatched ...") - silent! exe 'Make' - elseif l:listtype == "locationlist" - silent! exe 'lmake!' - else - silent! exe 'make!' - endif - redraw! + execute cd . fnameescape(expand("%:p:h")) + if l:listtype == "locationlist" + silent! exe 'lmake!' + else + silent! exe 'make!' + endif + redraw! finally - execute cd . fnameescape(dir) + execute cd . fnameescape(dir) endtry let errors = go#list#Get(l:listtype) call go#list#Window(l:listtype, len(errors)) - - if !empty(errors) - if !a:bang - call go#list#JumpToFirst(l:listtype) - endif + if !empty(errors) && !a:bang + call go#list#JumpToFirst(l:listtype) else - call go#util#EchoSuccess("[build] SUCCESS") + call go#util#EchoSuccess("[build] SUCCESS") endif let &makeprg = default_makeprg let $GOPATH = old_gopath + endif +endfunction + + +" BuildTags sets or shows the current build tags used for tools +function! go#cmd#BuildTags(bang, ...) abort + if a:0 + if a:0 == 1 && a:1 == '""' + unlet g:go_build_tags + call go#util#EchoSuccess("build tags are cleared") + else + let g:go_build_tags = a:1 + call go#util#EchoSuccess("build tags are changed to: ". a:1) + endif + + return + endif + + if !exists('g:go_build_tags') + call go#util#EchoSuccess("build tags are not set") + else + call go#util#EchoSuccess("current build tags: ". g:go_build_tags) + endif endfunction " Run runs the current file (and their dependencies if any) in a new terminal. -function! go#cmd#RunTerm(bang, mode, files) - if empty(a:files) - let cmd = "go run ". go#util#Shelljoin(go#tool#Files()) - else - let cmd = "go run ". go#util#Shelljoin(map(copy(a:files), "expand(v:val)"), 1) - endif - call go#term#newmode(a:bang, cmd, a:mode) +function! go#cmd#RunTerm(bang, mode, files) abort + if empty(a:files) + let cmd = "go run ". go#util#Shelljoin(go#tool#Files()) + else + let cmd = "go run ". go#util#Shelljoin(map(copy(a:files), "expand(v:val)"), 1) + endif + call go#term#newmode(a:bang, cmd, a:mode) endfunction " Run runs the current file (and their dependencies if any) and outputs it. -" This is intented to test small programs and play with them. It's not +" This is intended to test small programs and play with them. It's not " suitable for long running apps, because vim is blocking by default and " calling long running apps will block the whole UI. -function! go#cmd#Run(bang, ...) - if has('nvim') - call go#cmd#RunTerm(a:bang, '', a:000) - return - endif +function! go#cmd#Run(bang, ...) abort + if has('nvim') + call go#cmd#RunTerm(a:bang, '', a:000) + return + endif - let old_gopath = $GOPATH - let $GOPATH = go#path#Detect() + if go#util#has_job() + " NOTE(arslan): 'term': 'open' case is not implement for +jobs. This means + " executions waiting for stdin will not work. That's why we don't do + " anything. Once this is implemented we're going to make :GoRun async + endif - if go#util#IsWin() - exec '!go run ' . go#util#Shelljoin(go#tool#Files()) - if v:shell_error - redraws! | echon "vim-go: [run] " | echohl ErrorMsg | echon "FAILED"| echohl None - else - redraws! | echon "vim-go: [run] " | echohl Function | echon "SUCCESS"| echohl None - endif + let old_gopath = $GOPATH + let $GOPATH = go#path#Detect() - let $GOPATH = old_gopath - return - endif - - " :make expands '%' and '#' wildcards, so they must also be escaped - let default_makeprg = &makeprg - if a:0 == 0 - let &makeprg = 'go run ' . go#util#Shelljoin(go#tool#Files(), 1) + if go#util#IsWin() + exec '!go run ' . go#util#Shelljoin(go#tool#Files()) + if v:shell_error + redraws! | echon "vim-go: [run] " | echohl ErrorMsg | echon "FAILED"| echohl None else - let &makeprg = "go run " . go#util#Shelljoin(map(copy(a:000), "expand(v:val)"), 1) - endif - - let l:listtype = go#list#Type("quickfix") - - if g:go_dispatch_enabled && exists(':Make') == 2 - silent! exe 'Make' - elseif l:listtype == "locationlist" - exe 'lmake!' - else - exe 'make!' - endif - - let items = go#list#Get(l:listtype) - let errors = go#tool#FilterValids(items) - - call go#list#Populate(l:listtype, errors) - call go#list#Window(l:listtype, len(errors)) - if !empty(errors) && !a:bang - call go#list#JumpToFirst(l:listtype) + redraws! | echon "vim-go: [run] " | echohl Function | echon "SUCCESS"| echohl None endif let $GOPATH = old_gopath - let &makeprg = default_makeprg + return + endif + + " :make expands '%' and '#' wildcards, so they must also be escaped + let default_makeprg = &makeprg + if a:0 == 0 + let &makeprg = 'go run ' . go#util#Shelljoin(go#tool#Files(), 1) + else + let &makeprg = "go run " . go#util#Shelljoin(map(copy(a:000), "expand(v:val)"), 1) + endif + + let l:listtype = go#list#Type("GoRun") + + if l:listtype == "locationlist" + exe 'lmake!' + else + exe 'make!' + endif + + let items = go#list#Get(l:listtype) + let errors = go#tool#FilterValids(items) + + call go#list#Populate(l:listtype, errors, &makeprg) + call go#list#Window(l:listtype, len(errors)) + if !empty(errors) && !a:bang + call go#list#JumpToFirst(l:listtype) + endif + + let $GOPATH = old_gopath + let &makeprg = default_makeprg endfunction " Install installs the package by simple calling 'go install'. If any argument -" is given(which are passed directly to 'go install') it tries to install those -" packages. Errors are populated in the location window. -function! go#cmd#Install(bang, ...) - let default_makeprg = &makeprg +" is given(which are passed directly to 'go install') it tries to install +" those packages. Errors are populated in the location window. +function! go#cmd#Install(bang, ...) abort + " use vim's job functionality to call it asynchronously + if go#util#has_job() + " expand all wildcards(i.e: '%' to the current file name) + let goargs = map(copy(a:000), "expand(v:val)") - " :make expands '%' and '#' wildcards, so they must also be escaped - let goargs = go#util#Shelljoin(map(copy(a:000), "expand(v:val)"), 1) - let &makeprg = "go install " . goargs + if get(g:, 'go_echo_command_info', 1) + call go#util#EchoProgress("installing dispatched ...") + endif - let l:listtype = go#list#Type("quickfix") - " execute make inside the source folder so we can parse the errors - " correctly - let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd ' - let dir = getcwd() - try - execute cd . fnameescape(expand("%:p:h")) - if g:go_dispatch_enabled && exists(':Make') == 2 - call go#util#EchoProgress("building dispatched ...") - silent! exe 'Make' - elseif l:listtype == "locationlist" - silent! exe 'lmake!' - else - silent! exe 'make!' - endif - redraw! - finally - execute cd . fnameescape(dir) - endtry + call s:cmd_job({ + \ 'cmd': ['go', 'install'] + goargs, + \ 'bang': a:bang, + \ 'for': 'GoInstall', + \}) + return + endif - let errors = go#list#Get(l:listtype) - call go#list#Window(l:listtype, len(errors)) - if !empty(errors) - if !a:bang - call go#list#JumpToFirst(l:listtype) - endif + let old_gopath = $GOPATH + let $GOPATH = go#path#Detect() + let default_makeprg = &makeprg + + " :make expands '%' and '#' wildcards, so they must also be escaped + let goargs = go#util#Shelljoin(map(copy(a:000), "expand(v:val)"), 1) + let &makeprg = "go install " . goargs + + let l:listtype = go#list#Type("GoInstall") + " execute make inside the source folder so we can parse the errors + " correctly + let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd ' + let dir = getcwd() + try + execute cd . fnameescape(expand("%:p:h")) + if l:listtype == "locationlist" + silent! exe 'lmake!' else - redraws! | echon "vim-go: " | echohl Function | echon "installed to ". $GOPATH | echohl None + silent! exe 'make!' endif + redraw! + finally + execute cd . fnameescape(dir) + endtry - let &makeprg = default_makeprg -endfunction + let errors = go#list#Get(l:listtype) + call go#list#Window(l:listtype, len(errors)) + if !empty(errors) && !a:bang + call go#list#JumpToFirst(l:listtype) + else + call go#util#EchoSuccess("installed to ". go#path#Detect()) + endif -" Test runs `go test` in the current directory. If compile is true, it'll -" compile the tests instead of running them (useful to catch errors in the -" test files). Any other argument is appendend to the final `go test` command -function! go#cmd#Test(bang, compile, ...) - let args = ["test"] - - " don't run the test, only compile it. Useful to capture and fix errors or - " to create a test binary. - if a:compile - let compile_file = "vim-go-test-compile" - call extend(args, ["-c", "-o", compile_file]) - endif - - if a:0 - " expand all wildcards(i.e: '%' to the current file name) - let goargs = map(copy(a:000), "expand(v:val)") - let goargs = go#util#Shelllist(goargs, 1) - - call extend(args, goargs, 1) - else - " only add this if no custom flags are passed - let timeout = get(g:, 'go_test_timeout', '10s') - call add(args, printf("-timeout=%s", timeout)) - endif - - if a:compile - echon "vim-go: " | echohl Identifier | echon "compiling tests ..." | echohl None - else - echon "vim-go: " | echohl Identifier | echon "testing ..." | echohl None - endif - - if has('nvim') - if get(g:, 'go_term_enabled', 0) - let id = go#term#new(a:bang, ["go"] + args) - else - let id = go#jobcontrol#Spawn(a:bang, "test", args) - endif - - if a:compile - call go#jobcontrol#AddHandler(function('s:test_compile_handler')) - let s:test_compile_handlers[id] = compile_file - endif - return id - endif - - call go#cmd#autowrite() - redraw - - let command = "go " . join(args, ' ') - - let out = go#tool#ExecuteInDir(command) - - let l:listtype = "quickfix" - - if a:compile - call delete(compile_file) - endif - - if go#util#ShellError() != 0 - let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd ' - let dir = getcwd() - try - execute cd fnameescape(expand("%:p:h")) - let errors = go#tool#ParseErrors(split(out, '\n')) - let errors = go#tool#FilterValids(errors) - finally - execute cd . fnameescape(dir) - endtry - - call go#list#Populate(l:listtype, errors) - call go#list#Window(l:listtype, len(errors)) - if !empty(errors) && !a:bang - call go#list#JumpToFirst(l:listtype) - elseif empty(errors) - " failed to parse errors, output the original content - call go#util#EchoError(out) - endif - echon "vim-go: " | echohl ErrorMsg | echon "[test] FAIL" | echohl None - else - call go#list#Clean(l:listtype) - call go#list#Window(l:listtype) - - if a:compile - echon "vim-go: " | echohl Function | echon "[test] SUCCESS" | echohl None - else - echon "vim-go: " | echohl Function | echon "[test] PASS" | echohl None - endif - endif -endfunction - -" Testfunc runs a single test that surrounds the current cursor position. -" Arguments are passed to the `go test` command. -function! go#cmd#TestFunc(bang, ...) - " search flags legend (used only) - " 'b' search backward instead of forward - " 'c' accept a match at the cursor position - " 'n' do Not move the cursor - " 'W' don't wrap around the end of the file - " - " for the full list - " :help search - let test = search('func \(Test\|Example\)', "bcnW") - - if test == 0 - echo "vim-go: [test] no test found immediate to cursor" - return - end - - let line = getline(test) - let name = split(split(line, " ")[1], "(")[0] - let args = [a:bang, 0, "-run", name . "$"] - - if a:0 - call extend(args, a:000) - endif - - call call('go#cmd#Test', args) + let $GOPATH = old_gopath + let &makeprg = default_makeprg endfunction " Generate runs 'go generate' in similar fashion to go#cmd#Build() -function! go#cmd#Generate(bang, ...) - let default_makeprg = &makeprg +function! go#cmd#Generate(bang, ...) abort + let default_makeprg = &makeprg - let old_gopath = $GOPATH - let $GOPATH = go#path#Detect() + let old_gopath = $GOPATH + let $GOPATH = go#path#Detect() - " :make expands '%' and '#' wildcards, so they must also be escaped - let goargs = go#util#Shelljoin(map(copy(a:000), "expand(v:val)"), 1) - if go#util#ShellError() != 0 - let &makeprg = "go generate " . goargs - else - let gofiles = go#util#Shelljoin(go#tool#Files(), 1) - let &makeprg = "go generate " . goargs . ' ' . gofiles + " :make expands '%' and '#' wildcards, so they must also be escaped + let goargs = go#util#Shelljoin(map(copy(a:000), "expand(v:val)"), 1) + if go#util#ShellError() != 0 + let &makeprg = "go generate " . goargs + else + let gofiles = go#util#Shelljoin(go#tool#Files(), 1) + let &makeprg = "go generate " . goargs . ' ' . gofiles + endif + + let l:listtype = go#list#Type("GoGenerate") + + echon "vim-go: " | echohl Identifier | echon "generating ..."| echohl None + if l:listtype == "locationlist" + silent! exe 'lmake!' + else + silent! exe 'make!' + endif + redraw! + + let errors = go#list#Get(l:listtype) + call go#list#Window(l:listtype, len(errors)) + if !empty(errors) + if !a:bang + call go#list#JumpToFirst(l:listtype) endif + else + redraws! | echon "vim-go: " | echohl Function | echon "[generate] SUCCESS"| echohl None + endif - let l:listtype = go#list#Type("quickfix") - - echon "vim-go: " | echohl Identifier | echon "generating ..."| echohl None - if g:go_dispatch_enabled && exists(':Make') == 2 - silent! exe 'Make' - elseif l:listtype == "locationlist" - silent! exe 'lmake!' - else - silent! exe 'make!' - endif - redraw! - - let errors = go#list#Get(l:listtype) - call go#list#Window(l:listtype, len(errors)) - if !empty(errors) - if !a:bang - call go#list#JumpToFirst(l:listtype) - endif - else - redraws! | echon "vim-go: " | echohl Function | echon "[generate] SUCCESS"| echohl None - endif - - let &makeprg = default_makeprg - let $GOPATH = old_gopath + let &makeprg = default_makeprg + let $GOPATH = old_gopath endfunction +" --------------------- +" | Vim job callbacks | +" --------------------- -" ----------------------- -" | Neovim job handlers | -" ----------------------- -let s:test_compile_handlers = {} +function s:cmd_job(args) abort + let status_dir = expand('%:p:h') + let started_at = reltime() -function! s:test_compile_handler(job, exit_status, data) - if !has_key(s:test_compile_handlers, a:job.id) - return + call go#statusline#Update(status_dir, { + \ 'desc': "current status", + \ 'type': a:args.cmd[1], + \ 'state': "started", + \}) + + " autowrite is not enabled for jobs + call go#cmd#autowrite() + + function! s:error_info_cb(job, exit_status, data) closure abort + let status = { + \ 'desc': 'last status', + \ 'type': a:args.cmd[1], + \ 'state': "success", + \ } + + if a:exit_status + let status.state = "failed" endif - let l:compile_file = s:test_compile_handlers[a:job.id] - call delete(l:compile_file) - unlet s:test_compile_handlers[a:job.id] + + let elapsed_time = reltimestr(reltime(started_at)) + " strip whitespace + let elapsed_time = substitute(elapsed_time, '^\s*\(.\{-}\)\s*$', '\1', '') + let status.state .= printf(" (%ss)", elapsed_time) + + call go#statusline#Update(status_dir, status) + endfunction + + let a:args.error_info_cb = funcref('s:error_info_cb') + let callbacks = go#job#Spawn(a:args) + + let start_options = { + \ 'callback': callbacks.callback, + \ 'exit_cb': callbacks.exit_cb, + \ } + + " modify GOPATH if needed + let old_gopath = $GOPATH + let $GOPATH = go#path#Detect() + + " pre start + let dir = getcwd() + let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd ' + let jobdir = fnameescape(expand("%:p:h")) + execute cd . jobdir + + call job_start(a:args.cmd, start_options) + + " post start + execute cd . fnameescape(dir) + let $GOPATH = old_gopath endfunction -" vim:ts=4:sw=4:et +" vim: sw=2 ts=2 et diff --git a/sources_non_forked/vim-go/autoload/go/complete.vim b/sources_non_forked/vim-go/autoload/go/complete.vim index d7a66be5..e5cb14c7 100644 --- a/sources_non_forked/vim-go/autoload/go/complete.vim +++ b/sources_non_forked/vim-go/autoload/go/complete.vim @@ -1,156 +1,172 @@ -function! s:gocodeCurrentBuffer() - let buf = getline(1, '$') +let s:sock_type = (has('win32') || has('win64')) ? 'tcp' : 'unix' + +function! s:gocodeCurrentBuffer() 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") + if empty(bin_path) + return + endif + + " we might hit cache problems, as gocode doesn't handle well different + " GOPATHS: https://github.com/nsf/gocode/issues/239 + let old_gopath = $GOPATH + let old_goroot = $GOROOT + let $GOPATH = go#path#Detect() + let $GOROOT = go#util#env("goroot") + + let socket_type = get(g:, 'go_gocode_socket_type', s:sock_type) + let cmd = printf('%s -sock %s %s %s %s', + \ go#util#Shellescape(bin_path), + \ socket_type, + \ join(a:preargs), + \ go#util#Shellescape(a:cmd), + \ join(a:args) + \ ) + + let result = go#util#System(cmd) + let $GOPATH = old_gopath + let $GOROOT = old_goroot + + if go#util#ShellError() != 0 + return "[\"0\", []]" + else if &encoding != 'utf-8' - let buf = map(buf, 'iconv(v:val, &encoding, "utf-8")') + let result = iconv(result, 'utf-8', &encoding) endif - if &l:fileformat == 'dos' - " XXX: line2byte() depend on 'fileformat' option. - " so if fileformat is 'dos', 'buf' must include '\r'. - let buf = map(buf, 'v:val."\r"') - endif - let file = tempname() - call writefile(buf, file) - - return file + return result + endif endfunction -function! s:gocodeCommand(cmd, preargs, args) - 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") - if empty(bin_path) - return - endif - - " we might hit cache problems, as gocode doesn't handle well different - " GOPATHS: https://github.com/nsf/gocode/issues/239 - let old_gopath = $GOPATH - let $GOPATH = go#path#Detect() - - let result = go#util#System(printf('%s %s %s %s', go#util#Shellescape(bin_path), join(a:preargs), go#util#Shellescape(a:cmd), join(a:args))) - - let $GOPATH = old_gopath - - if go#util#ShellError() != 0 - return "[\"0\", []]" - else - if &encoding != 'utf-8' - let result = iconv(result, 'utf-8', &encoding) - endif - return result - endif -endfunction - -function! s:gocodeCurrentBufferOpt(filename) - return '-in=' . a:filename +function! s:gocodeCurrentBufferOpt(filename) abort + return '-in=' . a:filename endfunction let s:optionsEnabled = 0 -function! s:gocodeEnableOptions() - if s:optionsEnabled - return - endif +function! s:gocodeEnableOptions() abort + if s:optionsEnabled + return + endif - let bin_path = go#path#CheckBinPath("gocode") - if empty(bin_path) - return - endif + let bin_path = go#path#CheckBinPath("gocode") + if empty(bin_path) + return + endif - let s:optionsEnabled = 1 + let s:optionsEnabled = 1 - call go#util#System(printf('%s set propose-builtins %s', go#util#Shellescape(bin_path), s:toBool(get(g:, 'go_gocode_propose_builtins', 1)))) - call go#util#System(printf('%s set autobuild %s', go#util#Shellescape(bin_path), s:toBool(get(g:, 'go_gocode_autobuild', 1)))) + call go#util#System(printf('%s set propose-builtins %s', go#util#Shellescape(bin_path), s:toBool(get(g:, 'go_gocode_propose_builtins', 1)))) + call go#util#System(printf('%s set autobuild %s', go#util#Shellescape(bin_path), s:toBool(get(g:, 'go_gocode_autobuild', 1)))) + call go#util#System(printf('%s set unimported-packages %s', go#util#Shellescape(bin_path), s:toBool(get(g:, 'go_gocode_unimported_packages', 0)))) endfunction -function! s:toBool(val) - if a:val | return 'true ' | else | return 'false' | endif +function! s:toBool(val) abort + if a:val | return 'true ' | else | return 'false' | endif endfunction -function! s:gocodeAutocomplete() - call s:gocodeEnableOptions() +function! s:gocodeAutocomplete() abort + call s:gocodeEnableOptions() - let filename = s:gocodeCurrentBuffer() - let result = s:gocodeCommand('autocomplete', - \ [s:gocodeCurrentBufferOpt(filename), '-f=vim'], - \ [expand('%:p'), go#util#OffsetCursor()]) - call delete(filename) - return result + let filename = s:gocodeCurrentBuffer() + let result = s:gocodeCommand('autocomplete', + \ [s:gocodeCurrentBufferOpt(filename), '-f=vim'], + \ [expand('%:p'), go#util#OffsetCursor()]) + call delete(filename) + return result endfunction -function! go#complete#GetInfo() - let offset = go#util#OffsetCursor()+1 - let filename = s:gocodeCurrentBuffer() - let result = s:gocodeCommand('autocomplete', - \ [s:gocodeCurrentBufferOpt(filename), '-f=godit'], - \ [expand('%:p'), offset]) - call delete(filename) +function! go#complete#GetInfo() abort + let offset = go#util#OffsetCursor()+1 + 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 candiate 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("") . '\>' - " 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 + " 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("") . '\>' + " 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 -function! go#complete#Info(auto) - " auto is true if we were called by g:go_auto_type_info's autocmd - let result = go#complete#GetInfo() - if !empty(result) - " if auto, and the result is a PANIC by gocode, hide it - if a:auto && result ==# 'PANIC PANIC PANIC' | return | endif - echo "vim-go: " | echohl Function | echon result | echohl None - endif -endfunction - -function! s:trim_bracket(val) - let a:val.word = substitute(a:val.word, '[(){}\[\]]\+$', '', '') - return a:val -endfunction - -function! go#complete#Complete(findstart, base) - "findstart = 1 when we need to get the text length - if a:findstart == 1 - execute "silent let g:gocomplete_completions = " . s:gocodeAutocomplete() - return col('.') - g:gocomplete_completions[0] - 1 - "findstart = 0 when we need to return the list of completions - else - let s = getline(".")[col('.') - 1] - if s =~ '[(){}\{\}]' - return map(copy(g:gocomplete_completions[1]), 's:trim_bracket(v:val)') - endif - return g:gocomplete_completions[1] +function! go#complete#Info(auto) abort + " auto is true if we were called by g:go_auto_type_info's autocmd + let result = go#complete#GetInfo() + if !empty(result) + " if auto, and the result is a PANIC by gocode, hide it + if a:auto && result ==# 'PANIC PANIC PANIC' | return | endif + echo "vim-go: " | echohl Function | echon result | echohl None + endif +endfunction + +function! s:trim_bracket(val) abort + let a:val.word = substitute(a:val.word, '[(){}\[\]]\+$', '', '') + return a:val +endfunction + +function! go#complete#Complete(findstart, base) abort + "findstart = 1 when we need to get the text length + if a:findstart == 1 + execute "silent let g:gocomplete_completions = " . s:gocodeAutocomplete() + return col('.') - g:gocomplete_completions[0] - 1 + "findstart = 0 when we need to return the list of completions + else + let s = getline(".")[col('.') - 1] + if s =~ '[(){}\{\}]' + return map(copy(g:gocomplete_completions[1]), 's:trim_bracket(v:val)') endif + return g:gocomplete_completions[1] + endif endf -" vim:ts=4:sw=4:et +function! go#complete#ToggleAutoTypeInfo() abort + if get(g:, "go_auto_type_info", 0) + let g:go_auto_type_info = 0 + call go#util#EchoProgress("auto type info disabled") + return + end + + let g:go_auto_type_info = 1 + call go#util#EchoProgress("auto type info enabled") +endfunction + + +" vim: sw=2 ts=2 et diff --git a/sources_non_forked/vim-go/autoload/go/coverage.vim b/sources_non_forked/vim-go/autoload/go/coverage.vim index 2a45e523..f5872351 100644 --- a/sources_non_forked/vim-go/autoload/go/coverage.vim +++ b/sources_non_forked/vim-go/autoload/go/coverage.vim @@ -3,250 +3,344 @@ let s:toggle = 0 " Buffer creates a new cover profile with 'go test -coverprofile' and changes " the current buffers highlighting to show covered and uncovered sections of " the code. If run again it clears the annotation. -function! go#coverage#BufferToggle(bang, ...) - if s:toggle - call go#coverage#Clear() - return - endif +function! go#coverage#BufferToggle(bang, ...) abort + if s:toggle + call go#coverage#Clear() + return + endif - if a:0 == 0 - return call(function('go#coverage#Buffer'), [a:bang]) - endif + if a:0 == 0 + return call(function('go#coverage#Buffer'), [a:bang]) + endif - return call(function('go#coverage#Buffer'), [a:bang] + a:000) + return call(function('go#coverage#Buffer'), [a:bang] + a:000) endfunction " Buffer creates a new cover profile with 'go test -coverprofile' and changes -" teh current buffers highlighting to show covered and uncovered sections of +" the current buffers highlighting to show covered and uncovered sections of " the code. Calling it again reruns the tests and shows the last updated " coverage. -function! go#coverage#Buffer(bang, ...) - " 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 - if !exists("*matchaddpos") - call go#util#EchoError("GoCoverage is supported with Vim version 7.4-330 or later") - return -1 +function! go#coverage#Buffer(bang, ...) abort + " 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 + if !exists("*matchaddpos") + call go#util#EchoError("GoCoverage is supported with Vim version 7.4-330 or later") + return -1 + endif + + " check if there is any test file, if not we just return + let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd ' + let dir = getcwd() + try + execute cd . fnameescape(expand("%:p:h")) + if empty(glob("*_test.go")) + call go#util#EchoError("no test files available") + return endif + finally + execute cd . fnameescape(dir) + endtry - " check if there is any test file, if not we just return - let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd ' - let dir = getcwd() - try - execute cd . fnameescape(expand("%:p:h")) - if empty(glob("*_test.go")) - call go#util#EchoError("no tests files available") - return - endif - finally - execute cd . fnameescape(dir) - endtry + let s:toggle = 1 + let l:tmpname = tempname() - let s:toggle = 1 - let l:tmpname = tempname() - let args = [a:bang, 0, "-coverprofile", l:tmpname] + if get(g:, 'go_echo_command_info', 1) + echon "vim-go: " | echohl Identifier | echon "testing ..." | echohl None + endif - if a:0 - call extend(args, a:000) - endif + if go#util#has_job() + call s:coverage_job({ + \ 'cmd': ['go', 'test', '-coverprofile', l:tmpname] + a:000, + \ 'custom_cb': function('s:coverage_callback', [l:tmpname]), + \ 'bang': a:bang, + \ 'for': 'GoTest', + \ }) + return + endif - let disabled_term = 0 - if get(g:, 'go_term_enabled') - let disabled_term = 1 - let g:go_term_enabled = 0 - endif + let args = [a:bang, 0, "-coverprofile", l:tmpname] + if a:0 + call extend(args, a:000) + endif - let id = call('go#cmd#Test', args) + let disabled_term = 0 + if get(g:, 'go_term_enabled') + let disabled_term = 1 + let g:go_term_enabled = 0 + endif - if disabled_term - let g:go_term_enabled = 1 - endif + let id = call('go#test#Test', args) - if has('nvim') - call go#jobcontrol#AddHandler(function('s:coverage_handler')) - let s:coverage_handler_jobs[id] = l:tmpname - return - endif + if disabled_term + let g:go_term_enabled = 1 + endif - if go#util#ShellError() == 0 - call go#coverage#overlay(l:tmpname) - endif + if has('nvim') + call go#jobcontrol#AddHandler(function('s:coverage_handler')) + let s:coverage_handler_jobs[id] = l:tmpname + return + endif - call delete(l:tmpname) + if go#util#ShellError() == 0 + call go#coverage#overlay(l:tmpname) + endif + + call delete(l:tmpname) endfunction " Clear clears and resets the buffer annotation matches -function! go#coverage#Clear() - " only reset the syntax if the user has syntax enabled - if !empty(&syntax) - if exists("g:syntax_on") | syntax enable | endif - endif +function! go#coverage#Clear() abort + call clearmatches() - if exists("s:toggle") | let s:toggle = 0 | endif + if exists("s:toggle") | let s:toggle = 0 | endif - " remove the autocmd we defined - if exists("#BufWinLeave#") - autocmd! BufWinLeave - endif - - call clearmatches() + " remove the autocmd we defined + augroup vim-go-coverage + autocmd! + augroup end endfunction " Browser creates a new cover profile with 'go test -coverprofile' and opens " a new HTML coverage page from that profile in a new browser -function! go#coverage#Browser(bang, ...) - let l:tmpname = tempname() - let args = [a:bang, 0, "-coverprofile", l:tmpname] +function! go#coverage#Browser(bang, ...) abort + let l:tmpname = tempname() + if go#util#has_job() + call s:coverage_job({ + \ 'cmd': ['go', 'test', '-coverprofile', l:tmpname], + \ 'custom_cb': function('s:coverage_browser_callback', [l:tmpname]), + \ 'bang': a:bang, + \ 'for': 'GoTest', + \ }) + return + endif - if a:0 - call extend(args, a:000) - endif - let id = call('go#cmd#Test', args) - if has('nvim') - call go#jobcontrol#AddHandler(function('s:coverage_browser_handler')) - let s:coverage_browser_handler_jobs[id] = l:tmpname - return - endif - if go#util#ShellError() == 0 - let openHTML = 'go tool cover -html='.l:tmpname - call go#tool#ExecuteInDir(openHTML) - endif + let args = [a:bang, 0, "-coverprofile", l:tmpname] + if a:0 + call extend(args, a:000) + endif - call delete(l:tmpname) + let id = call('go#test#Test', args) + if has('nvim') + call go#jobcontrol#AddHandler(function('s:coverage_browser_handler')) + let s:coverage_browser_handler_jobs[id] = l:tmpname + return + endif + + + if go#util#ShellError() == 0 + let openHTML = 'go tool cover -html='.l:tmpname + call go#tool#ExecuteInDir(openHTML) + endif + + call delete(l:tmpname) endfunction " Parses a single line from the cover file generated via go test -coverprofile " and returns a single coverage profile block. -function! go#coverage#parsegocoverline(line) - " file:startline.col,endline.col numstmt count - let mx = '\([^:]\+\):\(\d\+\)\.\(\d\+\),\(\d\+\)\.\(\d\+\)\s\(\d\+\)\s\(\d\+\)' - let tokens = matchlist(a:line, mx) - let ret = {} - let ret.file = tokens[1] - let ret.startline = str2nr(tokens[2]) - let ret.startcol = str2nr(tokens[3]) - let ret.endline = str2nr(tokens[4]) - let ret.endcol = str2nr(tokens[5]) - let ret.numstmt = tokens[6] - let ret.cnt = tokens[7] - return ret +function! go#coverage#parsegocoverline(line) abort + " file:startline.col,endline.col numstmt count + let mx = '\([^:]\+\):\(\d\+\)\.\(\d\+\),\(\d\+\)\.\(\d\+\)\s\(\d\+\)\s\(\d\+\)' + let tokens = matchlist(a:line, mx) + let ret = {} + let ret.file = tokens[1] + let ret.startline = str2nr(tokens[2]) + let ret.startcol = str2nr(tokens[3]) + let ret.endline = str2nr(tokens[4]) + let ret.endcol = str2nr(tokens[5]) + let ret.numstmt = tokens[6] + let ret.cnt = tokens[7] + return ret endfunction " Generates matches to be added to matchaddpos for the given coverage profile " block -function! go#coverage#genmatch(cov) - let color = 'covered' - if a:cov.cnt == 0 - let color = 'uncover' - endif +function! go#coverage#genmatch(cov) abort + let color = 'goCoverageCovered' + if a:cov.cnt == 0 + let color = 'goCoverageUncover' + endif - let matches = [] + let matches = [] - " if start and end are the same, also specify the byte length - " example: foo.go:92.2,92.65 1 0 - if a:cov.startline == a:cov.endline - call add(matches, { - \ 'group': color, - \ 'pos': [[a:cov.startline, a:cov.startcol, a:cov.endcol - a:cov.startcol]], - \ 'priority': 2, - \ }) - return matches - endif - - " add start columns. Because we don't know the length of the of - " the line, we assume it is at maximum 200 bytes. I know this is hacky, - " but that's only way of fixing the issue + " if start and end are the same, also specify the byte length + " example: foo.go:92.2,92.65 1 0 + if a:cov.startline == a:cov.endline call add(matches, { - \ 'group': color, - \ 'pos': [[a:cov.startline, a:cov.startcol, 200]], - \ 'priority': 2, - \ }) - - " and then the remaining lines - let start_line = a:cov.startline - while start_line < a:cov.endline - let start_line += 1 - call add(matches, { - \ 'group': color, - \ 'pos': [[start_line]], - \ 'priority': 2, - \ }) - endwhile - - " finally end columns - call add(matches, { - \ 'group': color, - \ 'pos': [[a:cov.endline, a:cov.endcol-1]], - \ 'priority': 2, - \ }) - + \ 'group': color, + \ 'pos': [[a:cov.startline, a:cov.startcol, a:cov.endcol - a:cov.startcol]], + \ 'priority': 2, + \ }) return matches + endif + + " add start columns. Because we don't know the length of the of + " the line, we assume it is at maximum 200 bytes. I know this is hacky, + " but that's only way of fixing the issue + call add(matches, { + \ 'group': color, + \ 'pos': [[a:cov.startline, a:cov.startcol, 200]], + \ 'priority': 2, + \ }) + + " and then the remaining lines + let start_line = a:cov.startline + while start_line < a:cov.endline + let start_line += 1 + call add(matches, { + \ 'group': color, + \ 'pos': [[start_line]], + \ 'priority': 2, + \ }) + endwhile + + " finally end columns + call add(matches, { + \ 'group': color, + \ 'pos': [[a:cov.endline, a:cov.endcol-1]], + \ 'priority': 2, + \ }) + + return matches endfunction " Reads the given coverprofile file and annotates the current buffer -function! go#coverage#overlay(file) - if !filereadable(a:file) - return - endif - let lines = readfile(a:file) +function! go#coverage#overlay(file) abort + if !filereadable(a:file) + return + endif + let lines = readfile(a:file) - " cover mode, by default it's 'set'. Just here for debugging purposes - let mode = lines[0] + " cover mode, by default it's 'set'. Just here for debugging purposes + let mode = lines[0] - " contains matches for matchaddpos() - let matches = [] + " contains matches for matchaddpos() + let matches = [] - " first mark all lines as normaltext. We use a custom group to not - " interfere with other buffers highlightings. Because the priority is - " lower than the cover and uncover matches, it'll be overriden. - let cnt = 1 - while cnt <= line('$') - call add(matches, {'group': 'normaltext', 'pos': [cnt], 'priority': 1}) - let cnt += 1 - endwhile + " first mark all lines as goCoverageNormalText. We use a custom group to not + " interfere with other buffers highlightings. Because the priority is + " lower than the cover and uncover matches, it'll be overridden. + let cnt = 1 + while cnt <= line('$') + call add(matches, {'group': 'goCoverageNormalText', 'pos': [cnt], 'priority': 1}) + let cnt += 1 + endwhile - let fname = expand('%:t') + let fname = expand('%') - " when called for a _test.go file, run the coverage for the actuall file - " file - if fname =~# '^\f\+_test\.go$' - let l:root = split(fname, '_test.go$')[0] - let fname = l:root . ".go" + " when called for a _test.go file, run the coverage for the actuall file + " file + if fname =~# '^\f\+_test\.go$' + let l:root = split(fname, '_test.go$')[0] + let fname = l:root . ".go" - if !filereadable(fname) - call go#util#EchoError("couldn't find ".fname) - return - endif - - " open the alternate file to show the coverage - exe ":edit ". fnamemodify(fname, ":p") + if !filereadable(fname) + call go#util#EchoError("couldn't find ".fname) + return endif - for line in lines[1:] - let cov = go#coverage#parsegocoverline(line) + " open the alternate file to show the coverage + exe ":edit ". fnamemodify(fname, ":p") + endif - " TODO(arslan): for now only include the coverage for the current - " buffer - if fname != fnamemodify(cov.file, ':t') - continue - endif + " cov.file includes only the filename itself, without full path + let fname = fnamemodify(fname, ":t") - call extend(matches, go#coverage#genmatch(cov)) - endfor + for line in lines[1:] + let cov = go#coverage#parsegocoverline(line) - syntax manual - highlight normaltext term=bold ctermfg=darkgrey guifg=#75715E - highlight covered term=bold ctermfg=green guifg=#A6E22E - highlight uncover term=bold ctermfg=red guifg=#F92672 + " TODO(arslan): for now only include the coverage for the current + " buffer + if fname != fnamemodify(cov.file, ':t') + continue + endif - " clear the matches if we leave the buffer + call extend(matches, go#coverage#genmatch(cov)) + endfor + + " clear the matches if we leave the buffer + augroup vim-go-coverage + autocmd! autocmd BufWinLeave call go#coverage#Clear() + augroup end - for m in matches - call matchaddpos(m.group, m.pos) - endfor + for m in matches + call matchaddpos(m.group, m.pos) + endfor endfunction +" --------------------- +" | Vim job callbacks | +" --------------------- +" +function s:coverage_job(args) + " autowrite is not enabled for jobs + call go#cmd#autowrite() + + let status_dir = expand('%:p:h') + function! s:error_info_cb(job, exit_status, data) closure + let status = { + \ 'desc': 'last status', + \ 'type': "coverage", + \ 'state': "finished", + \ } + + if a:exit_status + let status.state = "failed" + endif + + call go#statusline#Update(status_dir, status) + endfunction + + let a:args.error_info_cb = funcref('s:error_info_cb') + let callbacks = go#job#Spawn(a:args) + + let start_options = { + \ 'callback': callbacks.callback, + \ 'exit_cb': callbacks.exit_cb, + \ } + + " modify GOPATH if needed + let old_gopath = $GOPATH + let $GOPATH = go#path#Detect() + + " pre start + let dir = getcwd() + let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd ' + let jobdir = fnameescape(expand("%:p:h")) + execute cd . jobdir + + call go#statusline#Update(status_dir, { + \ 'desc': "current status", + \ 'type': "coverage", + \ 'state': "started", + \}) + + call job_start(a:args.cmd, start_options) + + " post start + execute cd . fnameescape(dir) + let $GOPATH = old_gopath +endfunction + +" coverage_callback is called when the coverage execution is finished +function! s:coverage_callback(coverfile, job, exit_status, data) + if a:exit_status == 0 + call go#coverage#overlay(a:coverfile) + endif + + call delete(a:coverfile) +endfunction + +function! s:coverage_browser_callback(coverfile, job, exit_status, data) + if a:exit_status == 0 + let openHTML = 'go tool cover -html='.a:coverfile + call go#tool#ExecuteInDir(openHTML) + endif + + call delete(a:coverfile) +endfunction + " ----------------------- " | Neovim job handlers | " ----------------------- @@ -254,33 +348,33 @@ endfunction let s:coverage_handler_jobs = {} let s:coverage_browser_handler_jobs = {} -function! s:coverage_handler(job, exit_status, data) - if !has_key(s:coverage_handler_jobs, a:job.id) - return - endif - let l:tmpname = s:coverage_handler_jobs[a:job.id] - if a:exit_status == 0 - call go#coverage#overlay(l:tmpname) - endif +function! s:coverage_handler(job, exit_status, data) abort + if !has_key(s:coverage_handler_jobs, a:job.id) + return + endif + let l:tmpname = s:coverage_handler_jobs[a:job.id] + if a:exit_status == 0 + call go#coverage#overlay(l:tmpname) + endif - call delete(l:tmpname) - unlet s:coverage_handler_jobs[a:job.id] + call delete(l:tmpname) + unlet s:coverage_handler_jobs[a:job.id] endfunction -function! s:coverage_browser_handler(job, exit_status, data) - if !has_key(s:coverage_browser_handler_jobs, a:job.id) - return - endif +function! s:coverage_browser_handler(job, exit_status, data) abort + if !has_key(s:coverage_browser_handler_jobs, a:job.id) + return + endif - let l:tmpname = s:coverage_browser_handler_jobs[a:job.id] - if a:exit_status == 0 - let openHTML = 'go tool cover -html='.l:tmpname - call go#tool#ExecuteInDir(openHTML) - endif + let l:tmpname = s:coverage_browser_handler_jobs[a:job.id] + if a:exit_status == 0 + let openHTML = 'go tool cover -html='.l:tmpname + call go#tool#ExecuteInDir(openHTML) + endif - call delete(l:tmpname) - unlet s:coverage_browser_handler_jobs[a:job.id] + call delete(l:tmpname) + unlet s:coverage_browser_handler_jobs[a:job.id] endfunction -" vim:ts=4:sw=4:et +" vim: sw=2 ts=2 et diff --git a/sources_non_forked/vim-go/autoload/go/decls.vim b/sources_non_forked/vim-go/autoload/go/decls.vim new file mode 100644 index 00000000..493bbd37 --- /dev/null +++ b/sources_non_forked/vim-go/autoload/go/decls.vim @@ -0,0 +1,21 @@ +if !exists('g:go_decls_mode') + let g:go_decls_mode = '' +endif + +function! go#decls#Decls(mode, ...) abort + if g:go_decls_mode == 'ctrlp' + call ctrlp#init(call("ctrlp#decls#cmd", [a:mode] + a:000)) + elseif g:go_decls_mode == 'fzf' + call call("fzf#decls#cmd", [a:mode] + a:000) + else + if globpath(&rtp, 'plugin/ctrlp.vim') != "" + call ctrlp#init(call("ctrlp#decls#cmd", [a:mode] + a:000)) + elseif globpath(&rtp, 'plugin/fzf.vim') != "" + call call("fzf#decls#cmd", [a:mode] + a:000) + else + call go#util#EchoError("neither ctrlp.vim nor fzf.vim are installed. Please install either one") + end + end +endfunction + +" vim: sw=2 ts=2 et diff --git a/sources_non_forked/vim-go/autoload/go/def.vim b/sources_non_forked/vim-go/autoload/go/def.vim index 323fa69d..fb4b4166 100644 --- a/sources_non_forked/vim-go/autoload/go/def.vim +++ b/sources_non_forked/vim-go/autoload/go/def.vim @@ -1,228 +1,323 @@ let s:go_stack = [] let s:go_stack_level = 0 -function! go#def#Jump(mode) - let old_gopath = $GOPATH - let $GOPATH = go#path#Detect() +function! go#def#Jump(mode) abort + let old_gopath = $GOPATH + let $GOPATH = go#path#Detect() - let fname = fnamemodify(expand("%"), ':p:gs?\\?/?') + let fname = fnamemodify(expand("%"), ':p:gs?\\?/?') - " so guru right now is slow for some people. previously we were using - " godef which also has it's own quirks. But this issue come up so many - " times I've decided to support both. By default we still use guru as it - " covers all edge cases, but now anyone can switch to godef if they wish - let bin_name = get(g:, 'go_def_mode', 'guru') - if bin_name == 'godef' - let bin_path = go#path#CheckBinPath("godef") - if empty(bin_path) - let $GOPATH = old_gopath - return - endif - let command = printf("%s -f=%s -o=%s -t", bin_path, fname, go#util#OffsetCursor()) - let out = go#util#System(command) + " so guru right now is slow for some people. previously we were using + " godef which also has it's own quirks. But this issue come up so many + " times I've decided to support both. By default we still use guru as it + " covers all edge cases, but now anyone can switch to godef if they wish + let bin_name = get(g:, 'go_def_mode', 'guru') + if bin_name == 'godef' + if &modified + " Write current unsaved buffer to a temp file and use the modified content + let l:tmpname = tempname() + call writefile(go#util#GetLines(), l:tmpname) + let fname = l:tmpname + endif - " append the type information to the same line so our - " jump_to_declaration() function can parse it. This makes it - " compatible with guru definition as well too - let out = join(split(out, '\n'), ':') - elseif bin_name == 'guru' - let bin_path = go#path#CheckBinPath("guru") - if empty(bin_path) - let $GOPATH = old_gopath - return - endif + let bin_path = go#path#CheckBinPath("godef") + if empty(bin_path) + let $GOPATH = old_gopath + return + endif + let command = printf("%s -f=%s -o=%s -t", go#util#Shellescape(bin_path), + \ go#util#Shellescape(fname), go#util#OffsetCursor()) + let out = go#util#System(command) + if exists("l:tmpname") + call delete(l:tmpname) + endif + elseif bin_name == 'guru' + let bin_path = go#path#CheckBinPath("guru") + if empty(bin_path) + let $GOPATH = old_gopath + return + endif - let flags = "" - if exists('g:go_guru_tags') - let tags = get(g:, 'go_guru_tags') - let flags = printf(" -tags %s", tags) - endif + let cmd = [bin_path] + let stdin_content = "" - let fname = shellescape(fname.':#'.go#util#OffsetCursor()) - let command = printf("%s %s definition %s", bin_path, flags, fname) - let out = go#util#System(command) + if &modified + let content = join(go#util#GetLines(), "\n") + let stdin_content = fname . "\n" . strlen(content) . "\n" . content + call add(cmd, "-modified") + endif + + if exists('g:go_build_tags') + let tags = get(g:, 'go_build_tags') + call extend(cmd, ["-tags", tags]) + endif + + let fname = fname.':#'.go#util#OffsetCursor() + call extend(cmd, ["definition", fname]) + + if go#util#has_job() + let l:spawn_args = { + \ 'cmd': cmd, + \ 'custom_cb': function('s:jump_to_declaration_cb', [a:mode, bin_name]), + \ } + + if &modified + let l:spawn_args.input = stdin_content + endif + + call go#util#EchoProgress("searching declaration ...") + + call s:def_job(spawn_args) + return + endif + + let command = join(cmd, " ") + if &modified + let out = go#util#System(command, stdin_content) else - call go#util#EchoError('go_def_mode value: '. bin_name .' is not valid. Valid values are: [godef, guru]') - return + let out = go#util#System(command) endif + else + call go#util#EchoError('go_def_mode value: '. bin_name .' is not valid. Valid values are: [godef, guru]') + return + endif - if go#util#ShellError() != 0 - call go#util#EchoError(out) - return - endif + if go#util#ShellError() != 0 + call go#util#EchoError(out) + return + endif - call s:jump_to_declaration(out, a:mode) - let $GOPATH = old_gopath + call go#def#jump_to_declaration(out, a:mode, bin_name) + let $GOPATH = old_gopath endfunction -function! s:jump_to_declaration(out, mode) - " strip line ending - let out = split(a:out, go#util#LineEnding())[0] - if go#util#IsWin() - let parts = split(out, '\(^[a-zA-Z]\)\@,:navigate :jump ,q:exit'] - - let i = 0 - while i < len(s:go_stack) - let entry = s:go_stack[i] - let prefix = "" - - if i == s:go_stack_level - let prefix = ">" + tab split else - let prefix = " " + let cmd = 'sbuf' endif + elseif a:mode == "split" + split + elseif a:mode == "vsplit" + vsplit + endif - call add(stackOut, printf("%s %d %s|%d col %d|%s", - \ prefix, i+1, entry["file"], entry["line"], entry["col"], entry["ident"])) - let i += 1 - endwhile - - if s:go_stack_level == i - call add(stackOut, "> ") + " open the file and jump to line and column + exec cmd fnameescape(fnamemodify(filename, ':.')) endif + endif + call cursor(line, col) - call go#ui#OpenWindow("GoDef Stack", stackOut, "godefstack") + " also align the line to middle of the view + normal! zz - noremap :call go#def#SelectStackEntry() - noremap :call go#ui#CloseWindow() - noremap q :call go#ui#CloseWindow() + let &switchbuf = old_switchbuf endfunction -function! go#def#StackClear(...) - let s:go_stack = [] - let s:go_stack_level = 0 +function! go#def#SelectStackEntry() abort + let target_window = go#ui#GetReturnWindow() + if empty(target_window) + let target_window = winnr() + endif + + let highlighted_stack_entry = matchstr(getline("."), '^..\zs\(\d\+\)') + if !empty(highlighted_stack_entry) + execute target_window . "wincmd w" + call go#def#Stack(str2nr(highlighted_stack_entry)) + endif + + call go#ui#CloseWindow() endfunction -function! go#def#StackPop(...) - if len(s:go_stack) == 0 - call go#util#EchoError("godef stack empty") - return - endif +function! go#def#StackUI() abort + if len(s:go_stack) == 0 + call go#util#EchoError("godef stack empty") + return + endif - if s:go_stack_level == 0 - call go#util#EchoError("at bottom of the godef stack") - return - endif + let stackOut = ['" ,:navigate :jump ,q:exit'] - if !len(a:000) - let numPop = 1 + let i = 0 + while i < len(s:go_stack) + let entry = s:go_stack[i] + let prefix = "" + + if i == s:go_stack_level + let prefix = ">" else - let numPop = a:1 + let prefix = " " endif - let newLevel = str2nr(s:go_stack_level) - str2nr(numPop) - call go#def#Stack(newLevel + 1) + call add(stackOut, printf("%s %d %s|%d col %d|%s", + \ prefix, i+1, entry["file"], entry["line"], entry["col"], entry["ident"])) + let i += 1 + endwhile + + if s:go_stack_level == i + call add(stackOut, "> ") + endif + + call go#ui#OpenWindow("GoDef Stack", stackOut, "godefstack") + + noremap :call go#def#SelectStackEntry() + noremap :call go#ui#CloseWindow() + noremap q :call go#ui#CloseWindow() endfunction -function! go#def#Stack(...) - if len(s:go_stack) == 0 - call go#util#EchoError("godef stack empty") - return - endif - - if !len(a:000) - " Display interactive stack - call go#def#StackUI() - return - else - let jumpTarget = a:1 - endif - - if jumpTarget !~ '^\d\+$' - if jumpTarget !~ '^\s*$' - call go#util#EchoError("location must be a number") - endif - return - endif - - let jumpTarget = str2nr(jumpTarget) - 1 - - if jumpTarget >= 0 && jumpTarget < len(s:go_stack) - let s:go_stack_level = jumpTarget - let target = s:go_stack[s:go_stack_level] - - " jump - exec 'edit '.target["file"] - call cursor(target["line"], target["col"]) - normal! zz - else - call go#util#EchoError("invalid location. Try :GoDefStack to see the list of valid entries") - endif +function! go#def#StackClear(...) abort + let s:go_stack = [] + let s:go_stack_level = 0 endfunction +function! go#def#StackPop(...) abort + if len(s:go_stack) == 0 + call go#util#EchoError("godef stack empty") + return + endif + + if s:go_stack_level == 0 + call go#util#EchoError("at bottom of the godef stack") + return + endif + + if !len(a:000) + let numPop = 1 + else + let numPop = a:1 + endif + + let newLevel = str2nr(s:go_stack_level) - str2nr(numPop) + call go#def#Stack(newLevel + 1) +endfunction + +function! go#def#Stack(...) abort + if len(s:go_stack) == 0 + call go#util#EchoError("godef stack empty") + return + endif + + if !len(a:000) + " Display interactive stack + call go#def#StackUI() + return + else + let jumpTarget = a:1 + endif + + if jumpTarget !~ '^\d\+$' + if jumpTarget !~ '^\s*$' + call go#util#EchoError("location must be a number") + endif + return + endif + + let jumpTarget = str2nr(jumpTarget) - 1 + + if jumpTarget >= 0 && jumpTarget < len(s:go_stack) + let s:go_stack_level = jumpTarget + let target = s:go_stack[s:go_stack_level] + + " jump + if expand('%:p') != target["file"] + if &modified + exec 'hide edit' target["file"] + else + exec 'edit' target["file"] + endif + endif + call cursor(target["line"], target["col"]) + normal! zz + else + call go#util#EchoError("invalid location. Try :GoDefStack to see the list of valid entries") + endif +endfunction + +function s:def_job(args) abort + function! s:error_info_cb(job, exit_status, data) closure + " do not print anything during async definition search&jump + endfunction + + let a:args.error_info_cb = funcref('s:error_info_cb') + let callbacks = go#job#Spawn(a:args) + + let start_options = { + \ 'callback': callbacks.callback, + \ 'exit_cb': callbacks.exit_cb, + \ } + + if &modified + let l:tmpname = tempname() + call writefile(split(a:args.input, "\n"), l:tmpname, "b") + let l:start_options.in_io = "file" + let l:start_options.in_name = l:tmpname + endif + + call job_start(a:args.cmd, start_options) +endfunction + +" vim: sw=2 ts=2 et diff --git a/sources_non_forked/vim-go/autoload/go/def_test.vim b/sources_non_forked/vim-go/autoload/go/def_test.vim new file mode 100644 index 00000000..7e69b12e --- /dev/null +++ b/sources_non_forked/vim-go/autoload/go/def_test.vim @@ -0,0 +1,37 @@ +func! Test_jump_to_declaration_guru() abort + try + let l:filename = 'def/jump.go' + let lnum = 5 + let col = 6 + let l:tmp = gotest#load_fixture(l:filename) + + let guru_out = printf("%s:%d:%d: defined here as func main", filename, lnum, col) + call go#def#jump_to_declaration(guru_out, "", 'guru') + + call assert_equal(filename, bufname("%")) + call assert_equal(lnum, getcurpos()[1]) + call assert_equal(col, getcurpos()[2]) + finally + call delete(l:tmp, 'rf') + endtry +endfunc + +func! Test_jump_to_declaration_godef() abort + try + let filename = 'def/jump.go' + let lnum = 5 + let col = 6 + let l:tmp = gotest#load_fixture(l:filename) + + let godef_out = printf("%s:%d:%d\ndefined here as func main", filename, lnum, col) + call go#def#jump_to_declaration(godef_out, "", 'godef') + + call assert_equal(filename, bufname("%")) + call assert_equal(lnum, getcurpos()[1]) + call assert_equal(col, getcurpos()[2]) + finally + call delete(l:tmp, 'rf') + endtry +endfunc + +" vim: sw=2 ts=2 et diff --git a/sources_non_forked/vim-go/autoload/go/doc.vim b/sources_non_forked/vim-go/autoload/go/doc.vim index a380f0aa..58213c1c 100644 --- a/sources_non_forked/vim-go/autoload/go/doc.vim +++ b/sources_non_forked/vim-go/autoload/go/doc.vim @@ -5,151 +5,213 @@ let s:buf_nr = -1 if !exists("g:go_doc_command") - let g:go_doc_command = "godoc" + let g:go_doc_command = ["godoc"] endif -if !exists("g:go_doc_options") - let g:go_doc_options = "" -endif +function! go#doc#OpenBrowser(...) abort + " check if we have gogetdoc as it gives us more and accurate information. + " Only supported if we have json_decode as it's not worth to parse the plain + " non-json output of gogetdoc + let bin_path = go#path#CheckBinPath('gogetdoc') + if !empty(bin_path) && exists('*json_decode') + let json_out = s:gogetdoc(1) + if go#util#ShellError() != 0 + call go#util#EchoError(json_out) + return + endif + + let out = json_decode(json_out) + if type(out) != type({}) + call go#util#EchoError("gogetdoc output is malformed") + endif + + let import = out["import"] + let name = out["name"] + let decl = out["decl"] + + let godoc_url = "https://godoc.org/" . import + if decl !~ "^package" + let godoc_url .= "#" . name + endif + + echo godoc_url + + call go#tool#OpenBrowser(godoc_url) + return + endif + + let pkgs = s:godocWord(a:000) + if empty(pkgs) + return + endif + + let pkg = pkgs[0] + let exported_name = pkgs[1] + + " example url: https://godoc.org/github.com/fatih/set#Set + let godoc_url = "https://godoc.org/" . pkg . "#" . exported_name + call go#tool#OpenBrowser(godoc_url) +endfunction + +function! go#doc#Open(newmode, mode, ...) abort + " With argument: run "godoc [arg]". + if len(a:000) + if empty(go#path#CheckBinPath(g:go_doc_command[0])) + return + endif + + let command = printf("%s %s", go#util#Shelljoin(g:go_doc_command), join(a:000, ' ')) + let out = go#util#System(command) + " Without argument: run gogetdoc on cursor position. + else + let out = s:gogetdoc(0) + if out == -1 + return + endif + endif + + if go#util#ShellError() != 0 + call go#util#EchoError(out) + return + endif + + call s:GodocView(a:newmode, a:mode, out) +endfunction + +function! s:GodocView(newposition, position, content) abort + " reuse existing buffer window if it exists otherwise create a new one + let is_visible = bufexists(s:buf_nr) && bufwinnr(s:buf_nr) != -1 + if !bufexists(s:buf_nr) + execute a:newposition + sil file `="[Godoc]"` + let s:buf_nr = bufnr('%') + elseif bufwinnr(s:buf_nr) == -1 + execute a:position + execute s:buf_nr . 'buffer' + elseif bufwinnr(s:buf_nr) != bufwinnr('%') + execute bufwinnr(s:buf_nr) . 'wincmd w' + endif + + " if window was not visible then resize it + if !is_visible + if a:position == "split" + " cap window height to 20, but resize it for smaller contents + let max_height = get(g:, "go_doc_max_height", 20) + let content_height = len(split(a:content, "\n")) + if content_height > max_height + exe 'resize ' . max_height + else + exe 'resize ' . content_height + endif + else + " set a sane maximum width for vertical splits. In this case the minimum + " that fits the godoc for package http without extra linebreaks and line + " numbers on + exe 'vertical resize 84' + endif + endif + + setlocal filetype=godoc + setlocal bufhidden=delete + setlocal buftype=nofile + setlocal noswapfile + setlocal nobuflisted + setlocal nocursorline + setlocal nocursorcolumn + setlocal iskeyword+=: + setlocal iskeyword-=- + + setlocal modifiable + %delete _ + call append(0, split(a:content, "\n")) + sil $delete _ + setlocal nomodifiable + sil normal! gg + + " close easily with or enter + noremap :close + noremap :close +endfunction + +function! s:gogetdoc(json) abort + " check if we have 'gogetdoc' and use it automatically + let bin_path = go#path#CheckBinPath('gogetdoc') + if empty(bin_path) + return -1 + endif + + let cmd = [go#util#Shellescape(bin_path)] + + let offset = go#util#OffsetCursor() + let fname = expand("%:p:gs!\\!/!") + let pos = shellescape(fname.':#'.offset) + + let cmd += ["-pos", pos] + if a:json + let cmd += ["-json"] + endif + + let command = join(cmd, " ") + + if &modified + let command .= " -modified" + let out = go#util#System(command, go#util#archive()) + else + let out = go#util#System(command) + endif + + return out +endfunction " returns the package and exported name. exported name might be empty. " ie: fmt and Println " ie: github.com/fatih/set and New -function! s:godocWord(args) - if !executable('godoc') - let msg = "godoc command not found." - let msg .= " install with: go get golang.org/x/tools/cmd/godoc" - call go#util#echoWarning(msg) - return [] - endif +function! s:godocWord(args) abort + if !executable('godoc') + let msg = "godoc command not found." + let msg .= " install with: go get golang.org/x/tools/cmd/godoc" + call go#util#EchoWarning(msg) + return [] + endif - if !len(a:args) - let oldiskeyword = &iskeyword - setlocal iskeyword+=. - let word = expand('') - let &iskeyword = oldiskeyword - let word = substitute(word, '[^a-zA-Z0-9\\/._~-]', '', 'g') - let words = split(word, '\.\ze[^./]\+$') - else - let words = a:args - endif + if !len(a:args) + let oldiskeyword = &iskeyword + setlocal iskeyword+=. + let word = expand('') + let &iskeyword = oldiskeyword + let word = substitute(word, '[^a-zA-Z0-9\\/._~-]', '', 'g') + let words = split(word, '\.\ze[^./]\+$') + else + let words = a:args + endif - if !len(words) - return [] - endif + if !len(words) + return [] + endif - let pkg = words[0] - if len(words) == 1 - let exported_name = "" - else - let exported_name = words[1] - endif + let pkg = words[0] + if len(words) == 1 + let exported_name = "" + else + let exported_name = words[1] + endif - let packages = go#tool#Imports() + let packages = go#tool#Imports() - if has_key(packages, pkg) - let pkg = packages[pkg] - endif + if has_key(packages, pkg) + let pkg = packages[pkg] + endif - return [pkg, exported_name] + return [pkg, exported_name] endfunction -function! s:godocNotFound(content) - if len(a:content) == 0 - return 1 - endif +function! s:godocNotFound(content) abort + if len(a:content) == 0 + return 1 + endif - return a:content =~# '^.*: no such file or directory\n$' + return a:content =~# '^.*: no such file or directory\n$' endfunction -function! go#doc#OpenBrowser(...) - let pkgs = s:godocWord(a:000) - if empty(pkgs) - return - endif - let pkg = pkgs[0] - let exported_name = pkgs[1] - - " example url: https://godoc.org/github.com/fatih/set#Set - let godoc_url = "https://godoc.org/" . pkg . "#" . exported_name - call go#tool#OpenBrowser(godoc_url) -endfunction - -function! go#doc#Open(newmode, mode, ...) - if len(a:000) - " check if we have 'godoc' and use it automatically - let bin_path = go#path#CheckBinPath('godoc') - if empty(bin_path) - return - endif - - let command = printf("%s %s", bin_path, join(a:000, ' ')) - else - " check if we have 'gogetdoc' and use it automatically - let bin_path = go#path#CheckBinPath('gogetdoc') - if empty(bin_path) - return - endif - - let offset = go#util#OffsetCursor() - let fname = expand("%:p:gs!\\!/!") - let pos = shellescape(fname.':#'.offset) - - let command = printf("%s -pos %s", bin_path, pos) - endif - - let out = go#util#System(command) - if go#util#ShellError() != 0 - call go#util#EchoError(out) - return - endif - - call s:GodocView(a:newmode, a:mode, out) -endfunction - -function! s:GodocView(newposition, position, content) - " reuse existing buffer window if it exists otherwise create a new one - if !bufexists(s:buf_nr) - execute a:newposition - sil file `="[Godoc]"` - let s:buf_nr = bufnr('%') - elseif bufwinnr(s:buf_nr) == -1 - execute a:position - execute s:buf_nr . 'buffer' - elseif bufwinnr(s:buf_nr) != bufwinnr('%') - execute bufwinnr(s:buf_nr) . 'wincmd w' - endif - - " cap buffer height to 20, but resize it for smaller contents - let max_height = 20 - let content_height = len(split(a:content, "\n")) - if content_height > max_height - exe 'resize ' . max_height - else - exe 'resize ' . content_height - endif - - setlocal filetype=godoc - setlocal bufhidden=delete - setlocal buftype=nofile - setlocal noswapfile - setlocal nobuflisted - setlocal nocursorline - setlocal nocursorcolumn - setlocal iskeyword+=: - setlocal iskeyword-=- - - setlocal modifiable - %delete _ - call append(0, split(a:content, "\n")) - sil $delete _ - setlocal nomodifiable - sil normal! gg - - " close easily with or enter - noremap :close - noremap :close -endfunction - -" vim:ts=2:sw=2:et +" vim: sw=2 ts=2 et diff --git a/sources_non_forked/vim-go/autoload/go/fillstruct.vim b/sources_non_forked/vim-go/autoload/go/fillstruct.vim new file mode 100644 index 00000000..926dc225 --- /dev/null +++ b/sources_non_forked/vim-go/autoload/go/fillstruct.vim @@ -0,0 +1,52 @@ +function! go#fillstruct#FillStruct() abort + let l:cmd = ['fillstruct', + \ '-file', bufname(''), + \ '-offset', go#util#OffsetCursor()] + + " Read from stdin if modified. + if &modified + call add(l:cmd, '-modified') + let [l:out, l:err] = go#util#Exec(l:cmd, go#util#archive()) + else + let [l:out, l:err] = go#util#Exec(l:cmd) + endif + + if l:err + call go#util#EchoError(l:out) + return + endif + + try + let l:json = json_decode(l:out) + catch + call go#util#EchoError(l:out) + return + endtry + + let l:code = split(l:json['code'], "\n") + let l:pos = getpos('.') + + try + " Add any code before/after the struct. + exe l:json['start'] . 'go' + let l:code[0] = getline('.')[:col('.')-1] . l:code[0] + exe l:json['end'] . 'go' + let l:code[len(l:code)-1] .= getline('.')[col('.'):] + + " Indent every line except the first one; makes it look nice. + let l:indent = repeat("\t", indent('.') / &ts) + for i in range(1, len(l:code)-1) + let l:code[l:i] = l:indent . l:code[i] + endfor + + " Out with the old ... + exe 'normal! ' . l:json['start'] . 'gov' . l:json['end'] . 'gox' + " ... in with the new. + call setline('.', l:code[0]) + call append('.', l:code[1:]) + finally + call setpos('.', l:pos) + endtry +endfunction + +" vim: sw=2 ts=2 et diff --git a/sources_non_forked/vim-go/autoload/go/fillstruct_test.vim b/sources_non_forked/vim-go/autoload/go/fillstruct_test.vim new file mode 100644 index 00000000..634f6350 --- /dev/null +++ b/sources_non_forked/vim-go/autoload/go/fillstruct_test.vim @@ -0,0 +1,19 @@ +func! Test_fillstruct() abort + try + let l:tmp = gotest#write_file('a/a.go', [ + \ 'package a', + \ 'import "net/mail"', + \ 'var addr = mail.Address{}']) + + call go#fillstruct#FillStruct() + call gotest#assert_buffer(1, [ + \ 'var addr = mail.Address{', + \ '\tName: "",', + \ '\tAddress: "",', + \ '}']) + finally + call delete(l:tmp, 'rf') + endtry +endfunc + +" vim: sw=2 ts=2 et diff --git a/sources_non_forked/vim-go/autoload/go/fmt.vim b/sources_non_forked/vim-go/autoload/go/fmt.vim index 65303c91..8682a37c 100644 --- a/sources_non_forked/vim-go/autoload/go/fmt.vim +++ b/sources_non_forked/vim-go/autoload/go/fmt.vim @@ -2,48 +2,26 @@ " Use of this source code is governed by a BSD-style " license that can be found in the LICENSE file. " -" fmt.vim: Vim command to format Go files with gofmt. -" -" This filetype plugin add a new commands for go buffers: -" -" :Fmt -" -" Filter the current Go buffer through gofmt. -" It tries to preserve cursor position and avoids -" replacing the buffer with stderr output. -" -" Options: -" -" g:go_fmt_command [default="gofmt"] -" -" Flag naming the gofmt executable to use. -" -" g:go_fmt_autosave [default=1] -" -" Flag to auto call :Fmt when saved file -" +" fmt.vim: Vim command to format Go files with gofmt (and gofmt compatible +" toorls, such as goimports). if !exists("g:go_fmt_command") - let g:go_fmt_command = "gofmt" -endif - -if !exists("g:go_goimports_bin") - let g:go_goimports_bin = "goimports" -endif - -if !exists('g:go_fmt_fail_silently') - let g:go_fmt_fail_silently = 0 + let g:go_fmt_command = "gofmt" endif if !exists('g:go_fmt_options') - let g:go_fmt_options = '' + let g:go_fmt_options = '' +endif + +if !exists('g:go_fmt_fail_silently') + let g:go_fmt_fail_silently = 0 endif if !exists("g:go_fmt_experimental") - let g:go_fmt_experimental = 0 + let g:go_fmt_experimental = 0 endif -" we have those problems : +" we have those problems : " http://stackoverflow.com/questions/12741977/prevent-vim-from-updating-its-undo-tree " http://stackoverflow.com/questions/18532692/golang-formatter-and-vim-how-to-destroy-history-record?rq=1 " @@ -51,163 +29,248 @@ endif " it doesn't undo changes and break undo history. If you are here reading " this and have VimL experience, please look at the function for " improvements, patches are welcome :) -function! go#fmt#Format(withGoimport) - if g:go_fmt_experimental == 1 - " Using winsaveview to save/restore cursor state has the problem of - " closing folds on save: - " https://github.com/fatih/vim-go/issues/502 - " One fix is to use mkview instead. Unfortunately, this sometimes causes - " other bad side effects: - " https://github.com/fatih/vim-go/issues/728 - " and still closes all folds if foldlevel>0: - " https://github.com/fatih/vim-go/issues/732 - let l:curw = {} - try - mkview! - catch - let l:curw = winsaveview() - endtry +function! go#fmt#Format(withGoimport) abort + if g:go_fmt_experimental == 1 + " Using winsaveview to save/restore cursor state has the problem of + " closing folds on save: + " https://github.com/fatih/vim-go/issues/502 + " One fix is to use mkview instead. Unfortunately, this sometimes causes + " other bad side effects: + " https://github.com/fatih/vim-go/issues/728 + " and still closes all folds if foldlevel>0: + " https://github.com/fatih/vim-go/issues/732 + let l:curw = {} + try + mkview! + catch + let l:curw = winsaveview() + endtry + + " save our undo file to be restored after we are done. This is needed to + " prevent an additional undo jump due to BufWritePre auto command and also + " restore 'redo' history because it's getting being destroyed every + " BufWritePre + let tmpundofile = tempname() + exe 'wundo! ' . tmpundofile + else + " Save cursor position and many other things. + let l:curw = winsaveview() + endif + + " Write current unsaved buffer to a temp file + let l:tmpname = tempname() + call writefile(go#util#GetLines(), l:tmpname) + if go#util#IsWin() + let l:tmpname = tr(l:tmpname, '\', '/') + endif + + let bin_name = g:go_fmt_command + if a:withGoimport == 1 + let bin_name = "goimports" + endif + + let current_col = col('.') + let out = go#fmt#run(bin_name, l:tmpname, expand('%')) + let diff_offset = len(readfile(l:tmpname)) - line('$') + + if go#util#ShellError() == 0 + call go#fmt#update_file(l:tmpname, expand('%')) + elseif g:go_fmt_fail_silently == 0 + let errors = s:parse_errors(expand('%'), out) + call s:show_errors(errors) + endif + + " We didn't use the temp file, so clean up + call delete(l:tmpname) + + if g:go_fmt_experimental == 1 + " restore our undo history + silent! exe 'rundo ' . tmpundofile + call delete(tmpundofile) + + " Restore our cursor/windows positions, folds, etc. + if empty(l:curw) + silent! loadview else - " Save cursor position and many other things. - let l:curw = winsaveview() + call winrestview(l:curw) endif + else + " Restore our cursor/windows positions. + call winrestview(l:curw) + endif - " Write current unsaved buffer to a temp file - let l:tmpname = tempname() - call writefile(getline(1, '$'), l:tmpname) - - if g:go_fmt_experimental == 1 - " save our undo file to be restored after we are done. This is needed to - " prevent an additional undo jump due to BufWritePre auto command and also - " restore 'redo' history because it's getting being destroyed every - " BufWritePre - let tmpundofile = tempname() - exe 'wundo! ' . tmpundofile - endif - - " get the command first so we can test it - let fmt_command = g:go_fmt_command - if a:withGoimport == 1 - let fmt_command = g:go_goimports_bin - endif - - " check if the user has installed command binary. - " For example if it's goimports, let us check if it's installed, - " if not the user get's a warning via go#path#CheckBinPath() - let bin_path = go#path#CheckBinPath(fmt_command) - if empty(bin_path) - return - endif - - if fmt_command != "gofmt" - " change GOPATH too, so goimports can pick up the correct library - let old_gopath = $GOPATH - let $GOPATH = go#path#Detect() - - let fmt_command = bin_path - endif - - " populate the final command with user based fmt options - let command = fmt_command . ' -w ' - if a:withGoimport != 1 - let command = command . g:go_fmt_options - endif - - if fmt_command == "goimports" - if !exists('b:goimports_vendor_compatible') - let out = go#util#System(bin_path . " --help") - if out !~ "-srcdir" - call go#util#EchoWarning("vim-go: goimports does not support srcdir. update with: :GoUpdateBinaries") - else - let b:goimports_vendor_compatible = 1 - endif - endif - - if exists('b:goimports_vendor_compatible') && b:goimports_vendor_compatible - let ssl_save = &shellslash - set noshellslash - let command = command . '-srcdir ' . shellescape(expand("%:p:h")) - let &shellslash = ssl_save - endif - endif - - " execute our command... - if go#util#IsWin() - let l:tmpname = tr(l:tmpname, '\', '/') - endif - let out = go#util#System(command . " " . l:tmpname) - - if fmt_command != "gofmt" - let $GOPATH = old_gopath - endif - - let l:listtype = "locationlist" - "if there is no error on the temp file replace the output with the current - "file (if this fails, we can always check the outputs first line with: - "splitted =~ 'package \w\+') - if go#util#ShellError() == 0 - " remove undo point caused via BufWritePre - try | silent undojoin | catch | endtry - - " Replace current file with temp file, then reload buffer - let old_fileformat = &fileformat - call rename(l:tmpname, expand('%')) - silent edit! - let &fileformat = old_fileformat - let &syntax = &syntax - - " clean up previous location list, but only if it's due to fmt - if exists('b:got_fmt_error') && b:got_fmt_error - let b:got_fmt_error = 0 - call go#list#Clean(l:listtype) - call go#list#Window(l:listtype) - endif - elseif g:go_fmt_fail_silently == 0 - let splitted = split(out, '\n') - "otherwise get the errors and put them to location list - let errors = [] - for line in splitted - let tokens = matchlist(line, '^\(.\{-}\):\(\d\+\):\(\d\+\)\s*\(.*\)') - if !empty(tokens) - call add(errors, {"filename": @%, - \"lnum": tokens[2], - \"col": tokens[3], - \"text": tokens[4]}) - endif - endfor - if empty(errors) - % | " Couldn't detect gofmt error format, output errors - endif - if !empty(errors) - call go#list#Populate(l:listtype, errors) - echohl Error | echomsg "Gofmt returned error" | echohl None - endif - - let b:got_fmt_error = 1 - call go#list#Window(l:listtype, len(errors)) - - " We didn't use the temp file, so clean up - call delete(l:tmpname) - endif - - if g:go_fmt_experimental == 1 - " restore our undo history - silent! exe 'rundo ' . tmpundofile - call delete(tmpundofile) - endif - - if g:go_fmt_experimental == 1 - " Restore our cursor/windows positions, folds, etc. - if empty(l:curw) - silent! loadview - else - call winrestview(l:curw) - endif - else - " Restore our cursor/windows positions. - call winrestview(l:curw) - endif + " be smart and jump to the line the new statement was added/removed + call cursor(line('.') + diff_offset, current_col) endfunction +" update_file updates the target file with the given formatted source +function! go#fmt#update_file(source, target) + " remove undo point caused via BufWritePre + try | silent undojoin | catch | endtry -" vim:ts=4:sw=4:et + let old_fileformat = &fileformat + if exists("*getfperm") + " save file permissions + let original_fperm = getfperm(a:target) + endif + + call rename(a:source, a:target) + + " restore file permissions + if exists("*setfperm") && original_fperm != '' + call setfperm(a:target , original_fperm) + endif + + " reload buffer to reflect latest changes + silent edit! + + let &fileformat = old_fileformat + let &syntax = &syntax + + let l:listtype = go#list#Type("GoFmt") + + " the title information was introduced with 7.4-2200 + " https://github.com/vim/vim/commit/d823fa910cca43fec3c31c030ee908a14c272640 + if has('patch-7.4.2200') + " clean up previous list + if l:listtype == "quickfix" + let l:list_title = getqflist({'title': 1}) + else + let l:list_title = getloclist(0, {'title': 1}) + endif + else + " can't check the title, so assume that the list was for go fmt. + let l:list_title = {'title': 'Format'} + endif + + if has_key(l:list_title, "title") && l:list_title['title'] == "Format" + call go#list#Clean(l:listtype) + call go#list#Window(l:listtype) + endif +endfunction + +" run runs the gofmt/goimport command for the given source file and returns +" the the output of the executed command. Target is the real file to be +" formated. +function! go#fmt#run(bin_name, source, target) + let cmd = s:fmt_cmd(a:bin_name, a:source, a:target) + if empty(cmd) + return + endif + + if cmd[0] == "goimports" + " change GOPATH too, so goimports can pick up the correct library + let old_gopath = $GOPATH + let $GOPATH = go#path#Detect() + endif + + let command = join(cmd, " ") + + " execute our command... + let out = go#util#System(command) + + if cmd[0] == "goimports" + let $GOPATH = old_gopath + endif + + return out +endfunction + +" fmt_cmd returns a dict that contains the command to execute gofmt (or +" goimports). args is dict with +function! s:fmt_cmd(bin_name, source, target) + " check if the user has installed command binary. + " For example if it's goimports, let us check if it's installed, + " if not the user get's a warning via go#path#CheckBinPath() + let bin_path = go#path#CheckBinPath(a:bin_name) + if empty(bin_path) + return [] + endif + + " start constructing the command + let bin_path = go#util#Shellescape(bin_path) + let cmd = [bin_path] + call add(cmd, "-w") + + " add the options for binary (if any). go_fmt_options was by default of type + " string, however to allow customization it's now a dictionary of binary + " name mapping to options. + let opts = g:go_fmt_options + if type(g:go_fmt_options) == type({}) + let opts = has_key(g:go_fmt_options, a:bin_name) ? g:go_fmt_options[a:bin_name] : "" + endif + call extend(cmd, split(opts, " ")) + + if a:bin_name == "goimports" + " lazy check if goimports support `-srcdir`. We should eventually remove + " this in the future + if !exists('b:goimports_vendor_compatible') + let out = go#util#System(bin_path . " --help") + if out !~ "-srcdir" + call go#util#EchoWarning(printf("vim-go: goimports (%s) does not support srcdir. Update with: :GoUpdateBinaries", bin_path)) + else + let b:goimports_vendor_compatible = 1 + endif + endif + + if exists('b:goimports_vendor_compatible') && b:goimports_vendor_compatible + let ssl_save = &shellslash + set noshellslash + " use the filename without the fully qualified name if the tree is + " symlinked into the GOPATH, goimports won't work properly. + call extend(cmd, ["-srcdir", shellescape(a:target)]) + let &shellslash = ssl_save + endif + endif + + call add(cmd, a:source) + return cmd +endfunction + +" parse_errors parses the given errors and returns a list of parsed errors +function! s:parse_errors(filename, content) abort + let splitted = split(a:content, '\n') + + " list of errors to be put into location list + let errors = [] + for line in splitted + let tokens = matchlist(line, '^\(.\{-}\):\(\d\+\):\(\d\+\)\s*\(.*\)') + if !empty(tokens) + call add(errors,{ + \"filename": a:filename, + \"lnum": tokens[2], + \"col": tokens[3], + \"text": tokens[4], + \ }) + endif + endfor + + return errors +endfunction + +" show_errors opens a location list and shows the given errors. If the given +" errors is empty, it closes the the location list +function! s:show_errors(errors) abort + let l:listtype = go#list#Type("GoFmt") + if !empty(a:errors) + call go#list#Populate(l:listtype, a:errors, 'Format') + echohl Error | echomsg "Gofmt returned error" | echohl None + endif + + " this closes the window if there are no errors or it opens + " it if there is any + call go#list#Window(l:listtype, len(a:errors)) +endfunction + +function! go#fmt#ToggleFmtAutoSave() abort + if get(g:, "go_fmt_autosave", 1) + let g:go_fmt_autosave = 0 + call go#util#EchoProgress("auto fmt disabled") + return + end + + let g:go_fmt_autosave = 1 + call go#util#EchoProgress("auto fmt enabled") +endfunction + +" vim: sw=2 ts=2 et diff --git a/sources_non_forked/vim-go/autoload/go/fmt_test.vim b/sources_non_forked/vim-go/autoload/go/fmt_test.vim new file mode 100644 index 00000000..2adbfba0 --- /dev/null +++ b/sources_non_forked/vim-go/autoload/go/fmt_test.vim @@ -0,0 +1,49 @@ +func! Test_run_fmt() abort + let actual_file = tempname() + call writefile(readfile("test-fixtures/fmt/hello.go"), actual_file) + + let expected = join(readfile("test-fixtures/fmt/hello_golden.go"), "\n") + + " run our code + call go#fmt#run("gofmt", actual_file, "test-fixtures/fmt/hello.go") + + " this should now contain the formatted code + let actual = join(readfile(actual_file), "\n") + + call assert_equal(expected, actual) +endfunc + +func! Test_update_file() abort + let expected = join(readfile("test-fixtures/fmt/hello_golden.go"), "\n") + let source_file = tempname() + call writefile(readfile("test-fixtures/fmt/hello_golden.go"), source_file) + + let target_file = tempname() + call writefile([""], target_file) + + " update_file now + call go#fmt#update_file(source_file, target_file) + + " this should now contain the formatted code + let actual = join(readfile(target_file), "\n") + + call assert_equal(expected, actual) +endfunc + +func! Test_goimports() abort + let $GOPATH = 'test-fixtures/fmt/' + let actual_file = tempname() + call writefile(readfile("test-fixtures/fmt/src/imports/goimports.go"), actual_file) + + let expected = join(readfile("test-fixtures/fmt/src/imports/goimports_golden.go"), "\n") + + " run our code + call go#fmt#run("goimports", actual_file, "test-fixtures/fmt/src/imports/goimports.go") + + " this should now contain the formatted code + let actual = join(readfile(actual_file), "\n") + + call assert_equal(expected, actual) +endfunc + +" vim: sw=2 ts=2 et diff --git a/sources_non_forked/vim-go/autoload/go/guru.vim b/sources_non_forked/vim-go/autoload/go/guru.vim index 72e36b65..47eb2881 100644 --- a/sources_non_forked/vim-go/autoload/go/guru.vim +++ b/sources_non_forked/vim-go/autoload/go/guru.vim @@ -1,304 +1,634 @@ " guru.vim -- Vim integration for the Go guru. -func! s:RunGuru(mode, format, selected, needs_scope) range abort - "return with a warning if the binary doesn't exist - let bin_path = go#path#CheckBinPath("guru") - if empty(bin_path) - return {'err': "bin path not found"} +" guru_cmd returns a dict that contains the command to execute guru. args +" is dict with following options: +" mode : guru mode, such as 'implements' +" format : output format, either 'plain' or 'json' +" needs_scope : if 1, adds the current package to the scope +" selected : if 1, means it's a range of selection, otherwise it picks up the +" offset under the cursor +" example output: +" {'cmd' : ['guru', '-json', 'implements', 'demo/demo.go:#66']} +function! s:guru_cmd(args) range abort + let mode = a:args.mode + let format = a:args.format + let needs_scope = a:args.needs_scope + let selected = a:args.selected + + let result = {} + let pkg = go#package#ImportPath() + + " this is important, check it! + if pkg == -1 && needs_scope + return {'err': "current directory is not inside of a valid GOPATH"} + endif + + "return with a warning if the binary doesn't exist + let bin_path = go#path#CheckBinPath("guru") + if empty(bin_path) + return {'err': "bin path not found"} + endif + + " start constructing the command + let cmd = [bin_path] + + let filename = fnamemodify(expand("%"), ':p:gs?\\?/?') + if &modified + let result.stdin_content = go#util#archive() + call add(cmd, "-modified") + endif + + " enable outputting in json format + if format == "json" + call add(cmd, "-json") + endif + + " check for any tags + if exists('g:go_build_tags') + let tags = get(g:, 'go_build_tags') + call extend(cmd, ["-tags", tags]) + let result.tags = tags + endif + + " some modes require scope to be defined (such as callers). For these we + " choose a sensible setting, which is using the current file's package + let scopes = [] + if needs_scope + let scopes = [pkg] + endif + + " check for any user defined scope setting. users can define the scope, + " in package pattern form. examples: + " golang.org/x/tools/cmd/guru # a single package + " golang.org/x/tools/... # all packages beneath dir + " ... # the entire workspace. + if exists('g:go_guru_scope') + " check that the setting is of type list + if type(get(g:, 'go_guru_scope')) != type([]) + return {'err' : "go_guru_scope should of type list"} endif - let filename = expand('%:p') - let dirname = expand('%:p:h') - let pkg = go#package#ImportPath(dirname) + let scopes = get(g:, 'go_guru_scope') + endif - " this is important, check it! - if pkg == -1 && a:needs_scope - return {'err': "current directory is not inside of a valid GOPATH"} + " now add the scope to our command if there is any + if !empty(scopes) + " strip trailing slashes for each path in scoped. bug: + " https://github.com/golang/go/issues/14584 + let scopes = go#util#StripTrailingSlash(scopes) + + " create shell-safe entries of the list + if !go#util#has_job() | let scopes = go#util#Shelllist(scopes) | endif + + " guru expect a comma-separated list of patterns, construct it + let l:scope = join(scopes, ",") + let result.scope = l:scope + call extend(cmd, ["-scope", l:scope]) + endif + + let pos = printf("#%s", go#util#OffsetCursor()) + if selected != -1 + " means we have a range, get it + let pos1 = go#util#Offset(line("'<"), col("'<")) + let pos2 = go#util#Offset(line("'>"), col("'>")) + let pos = printf("#%s,#%s", pos1, pos2) + endif + + let filename .= ':'.pos + call extend(cmd, [mode, filename]) + + let result.cmd = cmd + return result +endfunction + +" sync_guru runs guru in sync mode with the given arguments +function! s:sync_guru(args) abort + let result = s:guru_cmd(a:args) + if has_key(result, 'err') + call go#util#EchoError(result.err) + return -1 + endif + + if !has_key(a:args, 'disable_progress') + if a:args.needs_scope + call go#util#EchoProgress("analysing with scope ". result.scope . + \ " (see ':help go-guru-scope' if this doesn't work)...") + elseif a:args.mode !=# 'what' + " the query might take time, let us give some feedback + call go#util#EchoProgress("analysing ...") endif + endif - " start constructing the 'command' variable - let command = bin_path - " enable outputting in json format - if a:format == "json" - let command .= " -json" - endif - - " check for any tags - if exists('g:go_guru_tags') - let tags = get(g:, 'go_guru_tags') - let command .= printf(" -tags %s", tags) - endif - - " some modes require scope to be defined (such as callers). For these we - " choose a sensible setting, which is using the current file's package - let scopes = [] - if a:needs_scope - let scopes = [pkg] - endif - - " check for any user defined scope setting. users can define the scope, - " in package pattern form. examples: - " golang.org/x/tools/cmd/guru # a single package - " golang.org/x/tools/... # all packages beneath dir - " ... # the entire workspace. - if exists('g:go_guru_scope') - " check that the setting is of type list - if type(get(g:, 'go_guru_scope')) != type([]) - return {'err' : "go_guru_scope should of type list"} - endif - - let scopes = get(g:, 'go_guru_scope') - endif - - " now add the scope to our command if there is any - if !empty(scopes) - " strip trailing slashes for each path in scoped. bug: - " https://github.com/golang/go/issues/14584 - let scopes = go#util#StripTrailingSlash(scopes) - - " create shell-safe entries of the list - let scopes = go#util#Shelllist(scopes) - - " guru expect a comma-separated list of patterns, construct it - let scope = join(scopes, ",") - let command .= printf(" -scope %s", scope) - endif - - let pos = printf("#%s", go#util#OffsetCursor()) - if a:selected != -1 - " means we have a range, get it - let pos1 = go#util#Offset(line("'<"), col("'<")) - let pos2 = go#util#Offset(line("'>"), col("'>")) - let pos = printf("#%s,#%s", pos1, pos2) - endif - - " this is our final command - let filename .= ':'.pos - let command .= printf(' %s %s', a:mode, shellescape(filename)) - - let old_gopath = $GOPATH - let $GOPATH = go#path#Detect() - - " the query might take time, let us give some feedback - call go#util#EchoProgress("analysing ...") - - " run, forrest run!!! + " run, forrest run!!! + let command = join(result.cmd, " ") + if has_key(result, 'stdin_content') + let out = go#util#System(command, result.stdin_content) + else let out = go#util#System(command) + endif - let $GOPATH = old_gopath - if go#util#ShellError() != 0 - " the output contains the error message - return {'err' : out} + if has_key(a:args, 'custom_parse') + call a:args.custom_parse(go#util#ShellError(), out) + else + call s:parse_guru_output(go#util#ShellError(), out, a:args.mode) + endif + + return out +endfunc + +" async_guru runs guru in async mode with the given arguments +function! s:async_guru(args) abort + let result = s:guru_cmd(a:args) + if has_key(result, 'err') + call go#util#EchoError(result.err) + return + endif + + let status_dir = expand('%:p:h') + let statusline_type = printf("%s", a:args.mode) + + if !has_key(a:args, 'disable_progress') + if a:args.needs_scope + call go#util#EchoProgress("analysing with scope " . result.scope . + \ " (see ':help go-guru-scope' if this doesn't work)...") + endif + endif + + let messages = [] + function! s:callback(chan, msg) closure + call add(messages, a:msg) + endfunction + + let status = {} + let exitval = 0 + + function! s:exit_cb(job, exitval) closure + let status = { + \ 'desc': 'last status', + \ 'type': statusline_type, + \ 'state': "finished", + \ } + + if a:exitval + let exitval = a:exitval + let status.state = "failed" endif - return {'out': out} + call go#statusline#Update(status_dir, status) + endfunction + + function! s:close_cb(ch) closure + let out = join(messages, "\n") + + if has_key(a:args, 'custom_parse') + call a:args.custom_parse(exitval, out) + else + call s:parse_guru_output(exitval, out, a:args.mode) + endif + endfunction + + let start_options = { + \ 'callback': funcref("s:callback"), + \ 'exit_cb': funcref("s:exit_cb"), + \ 'close_cb': funcref("s:close_cb"), + \ } + + if has_key(result, 'stdin_content') + let l:tmpname = tempname() + call writefile(split(result.stdin_content, "\n"), l:tmpname, "b") + let l:start_options.in_io = "file" + let l:start_options.in_name = l:tmpname + endif + + call go#statusline#Update(status_dir, { + \ 'desc': "current status", + \ 'type': statusline_type, + \ 'state': "analysing", + \}) + + return job_start(result.cmd, start_options) endfunc +" run_guru runs the given guru argument +function! s:run_guru(args) abort + let old_gopath = $GOPATH + let $GOPATH = go#path#Detect() + if go#util#has_job() + let res = s:async_guru(a:args) + else + let res = s:sync_guru(a:args) + endif + + let $GOPATH = old_gopath + + return res +endfunction + +" Show 'implements' relation for selected package +function! go#guru#Implements(selected) abort + let args = { + \ 'mode': 'implements', + \ 'format': 'plain', + \ 'selected': a:selected, + \ 'needs_scope': 1, + \ } + + call s:run_guru(args) +endfunction + +" Report the possible constants, global variables, and concrete types that may +" appear in a value of type error +function! go#guru#Whicherrs(selected) abort + let args = { + \ 'mode': 'whicherrs', + \ 'format': 'plain', + \ 'selected': a:selected, + \ 'needs_scope': 1, + \ } + + + " TODO(arslan): handle empty case for both sync/async + " if empty(out.out) + " call go#util#EchoSuccess("no error variables found. Try to change the scope with :GoGuruScope") + " return + " endif + call s:run_guru(args) +endfunction + +" Describe selected syntax: definition, methods, etc +function! go#guru#Describe(selected) abort + let args = { + \ 'mode': 'describe', + \ 'format': 'plain', + \ 'selected': a:selected, + \ 'needs_scope': 1, + \ } + + call s:run_guru(args) +endfunction + +function! go#guru#DescribeInfo() abort + " json_encode() and friends are introduced with this patch (7.4.1304) + " vim: https://groups.google.com/d/msg/vim_dev/vLupTNhQhZ8/cDGIk0JEDgAJ + " nvim: https://github.com/neovim/neovim/pull/4131 + if !exists("*json_decode") + call go#util#EchoError("requires 'json_decode'. Update your Vim/Neovim version.") + return + endif + + function! s:info(exit_val, output) + if a:exit_val != 0 + return + endif + + if a:output[0] !=# '{' + return + endif + + if empty(a:output) || type(a:output) != type("") + return + endif + + let result = json_decode(a:output) + if type(result) != type({}) + call go#util#EchoError(printf("malformed output from guru: %s", a:output)) + return + endif + + if !has_key(result, 'detail') + " if there is no detail check if there is a description and print it + if has_key(result, "desc") + call go#util#EchoInfo(result["desc"]) + return + endif + + call go#util#EchoError("detail key is missing. Please open a bug report on vim-go repo.") + return + endif + + let detail = result['detail'] + let info = "" + + " guru gives different information based on the detail mode. Let try to + " extract the most useful information + + if detail == "value" + if !has_key(result, 'value') + call go#util#EchoError("value key is missing. Please open a bug report on vim-go repo.") + return + endif + + let val = result["value"] + if !has_key(val, 'type') + call go#util#EchoError("type key is missing (value.type). Please open a bug report on vim-go repo.") + return + endif + + let info = val["type"] + elseif detail == "type" + if !has_key(result, 'type') + call go#util#EchoError("type key is missing. Please open a bug report on vim-go repo.") + return + endif + + let type = result["type"] + if !has_key(type, 'type') + call go#util#EchoError("type key is missing (type.type). Please open a bug report on vim-go repo.") + return + endif + + let info = type["type"] + elseif detail == "package" + if !has_key(result, 'package') + call go#util#EchoError("package key is missing. Please open a bug report on vim-go repo.") + return + endif + + let package = result["package"] + if !has_key(package, 'path') + call go#util#EchoError("path key is missing (package.path). Please open a bug report on vim-go repo.") + return + endif + + let info = printf("package %s", package["path"]) + elseif detail == "unknown" + let info = result["desc"] + else + call go#util#EchoError(printf("unknown detail mode found '%s'. Please open a bug report on vim-go repo", detail)) + return + endif + + call go#util#EchoInfo(info) + endfunction + + let args = { + \ 'mode': 'describe', + \ 'format': 'json', + \ 'selected': -1, + \ 'needs_scope': 1, + \ 'custom_parse': function('s:info'), + \ 'disable_progress': 1, + \ } + + call s:run_guru(args) +endfunction + +" Show possible targets of selected function call +function! go#guru#Callees(selected) abort + let args = { + \ 'mode': 'callees', + \ 'format': 'plain', + \ 'selected': a:selected, + \ 'needs_scope': 1, + \ } + + call s:run_guru(args) +endfunction + +" Show possible callers of selected function +function! go#guru#Callers(selected) abort + let args = { + \ 'mode': 'callers', + \ 'format': 'plain', + \ 'selected': a:selected, + \ 'needs_scope': 1, + \ } + + call s:run_guru(args) +endfunction + +" Show path from callgraph root to selected function +function! go#guru#Callstack(selected) abort + let args = { + \ 'mode': 'callstack', + \ 'format': 'plain', + \ 'selected': a:selected, + \ 'needs_scope': 1, + \ } + + call s:run_guru(args) +endfunction + +" Show free variables of selection +function! go#guru#Freevars(selected) abort + " Freevars requires a selection + if a:selected == -1 + call go#util#EchoError("GoFreevars requires a selection (range) of code") + return + endif + + let args = { + \ 'mode': 'freevars', + \ 'format': 'plain', + \ 'selected': 1, + \ 'needs_scope': 0, + \ } + + call s:run_guru(args) +endfunction + +" Show send/receive corresponding to selected channel op +function! go#guru#ChannelPeers(selected) abort + let args = { + \ 'mode': 'peers', + \ 'format': 'plain', + \ 'selected': a:selected, + \ 'needs_scope': 1, + \ } + + call s:run_guru(args) +endfunction + +" Show all refs to entity denoted by selected identifier +function! go#guru#Referrers(selected) abort + let args = { + \ 'mode': 'referrers', + \ 'format': 'plain', + \ 'selected': a:selected, + \ 'needs_scope': 0, + \ } + + call s:run_guru(args) +endfunction + +function! go#guru#SameIdsTimer() abort + call timer_start(200, function('go#guru#SameIds'), {'repeat': -1}) +endfunction + +function! go#guru#SameIds() abort + " 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 + if !exists("*matchaddpos") + call go#util#EchoError("GoSameIds requires 'matchaddpos'. Update your Vim/Neovim version.") + return + endif + + " json_encode() and friends are introduced with this patch (7.4.1304) + " vim: https://groups.google.com/d/msg/vim_dev/vLupTNhQhZ8/cDGIk0JEDgAJ + " nvim: https://github.com/neovim/neovim/pull/4131 + if !exists("*json_decode") + call go#util#EchoError("GoSameIds requires 'json_decode'. Update your Vim/Neovim version.") + return + endif + + let args = { + \ 'mode': 'what', + \ 'format': 'json', + \ 'selected': -1, + \ 'needs_scope': 0, + \ 'custom_parse': function('s:same_ids_highlight'), + \ } + + call s:run_guru(args) +endfunction + +function! s:same_ids_highlight(exit_val, output) abort + call go#guru#ClearSameIds() " run after calling guru to reduce flicker. + + if a:output[0] !=# '{' + if !get(g:, 'go_auto_sameids', 0) + call go#util#EchoError(a:output) + endif + return + endif + + let result = json_decode(a:output) + if type(result) != type({}) && !get(g:, 'go_auto_sameids', 0) + call go#util#EchoError("malformed output from guru") + return + endif + + if !has_key(result, 'sameids') + if !get(g:, 'go_auto_sameids', 0) + call go#util#EchoError("no same_ids founds for the given identifier") + endif + return + endif + + let poslen = 0 + for enclosing in result['enclosing'] + if enclosing['desc'] == 'identifier' + let poslen = enclosing['end'] - enclosing['start'] + break + endif + endfor + + " return when there's no identifier to highlight. + if poslen == 0 + return + endif + + let same_ids = result['sameids'] + " highlight the lines + for item in same_ids + let pos = split(item, ':') + call matchaddpos('goSameId', [[str2nr(pos[-2]), str2nr(pos[-1]), str2nr(poslen)]]) + endfor + + if get(g:, "go_auto_sameids", 0) + " re-apply SameIds at the current cursor position at the time the buffer + " is redisplayed: e.g. :edit, :GoRename, etc. + augroup vim-go-sameids + autocmd! + autocmd BufWinEnter nested call go#guru#SameIds() + augroup end + endif +endfunction + +" ClearSameIds returns 0 when it removes goSameId groups and non-zero if no +" goSameId groups are found. +function! go#guru#ClearSameIds() abort + let l:cleared = 0 + + let m = getmatches() + for item in m + if item['group'] == 'goSameId' + call matchdelete(item['id']) + let l:cleared = 1 + endif + endfor + + if !l:cleared + return 1 + endif + + " remove the autocmds we defined + augroup vim-go-sameids + autocmd! + augroup end + + return 0 +endfunction + +function! go#guru#ToggleSameIds() abort + if go#guru#ClearSameIds() != 0 + call go#guru#SameIds() + endif +endfunction + +function! go#guru#AutoToogleSameIds() abort + if get(g:, "go_auto_sameids", 0) + call go#util#EchoProgress("sameids auto highlighting disabled") + call go#guru#ClearSameIds() + let g:go_auto_sameids = 0 + return + endif + + call go#util#EchoSuccess("sameids auto highlighting enabled") + let g:go_auto_sameids = 1 +endfunction + + +"""""""""""""""""""""""""""""""""""""""" +"" HELPER FUNCTIONS +"""""""""""""""""""""""""""""""""""""""" + " This uses Vim's errorformat to parse the output from Guru's 'plain output " and put it into location list. I believe using errorformat is much more " easier to use. If we need more power we can always switch back to parse it -" via regex. -func! s:loclistSecond(output) - " backup users errorformat, will be restored once we are finished - let old_errorformat = &errorformat +" via regex. Match two possible styles of errorformats: +" +" 'file:line.col-line2.col2: message' +" 'file:line:col: message' +" +" We discard line2 and col2 for the first errorformat, because it's not +" useful and location only has the ability to show one line and column +" number +function! s:parse_guru_output(exit_val, output, title) abort + if a:exit_val + call go#util#EchoError(a:output) + return + endif - " match two possible styles of errorformats: - " - " 'file:line.col-line2.col2: message' - " 'file:line:col: message' - " - " We discard line2 and col2 for the first errorformat, because it's not - " useful and location only has the ability to show one line and column - " number - let errformat = "%f:%l.%c-%[%^:]%#:\ %m,%f:%l:%c:\ %m" - call go#list#ParseFormat("locationlist", errformat, split(a:output, "\n")) + let old_errorformat = &errorformat + let errformat = "%f:%l.%c-%[%^:]%#:\ %m,%f:%l:%c:\ %m" + let l:listtype = go#list#Type("_guru") + call go#list#ParseFormat(l:listtype, errformat, a:output, a:title) + let &errorformat = old_errorformat - let errors = go#list#Get("locationlist") - call go#list#Window("locationlist", len(errors)) + let errors = go#list#Get(l:listtype) + call go#list#Window(l:listtype, len(errors)) endfun - -function! go#guru#Scope(...) - if a:0 - if a:0 == 1 && a:1 == '""' - unlet g:go_guru_scope - call go#util#EchoSuccess("guru scope is cleared") - else - let g:go_guru_scope = a:000 - call go#util#EchoSuccess("guru scope changed to: ". join(a:000, ",")) - endif - - return - endif - - if !exists('g:go_guru_scope') - call go#util#EchoError("guru scope is not set") +function! go#guru#Scope(...) abort + if a:0 + if a:0 == 1 && a:1 == '""' + unlet g:go_guru_scope + call go#util#EchoSuccess("guru scope is cleared") else - call go#util#EchoSuccess("current guru scope: ". join(g:go_guru_scope, ",")) + let g:go_guru_scope = a:000 + call go#util#EchoSuccess("guru scope changed to: ". join(a:000, ",")) endif + + return + endif + + if !exists('g:go_guru_scope') + call go#util#EchoError("guru scope is not set") + else + call go#util#EchoSuccess("current guru scope: ". join(g:go_guru_scope, ",")) + endif endfunction -function! go#guru#Tags(...) - if a:0 - if a:0 == 1 && a:1 == '""' - unlet g:go_guru_tags - call go#util#EchoSuccess("guru tags is cleared") - else - let g:go_guru_tags = a:1 - call go#util#EchoSuccess("guru tags changed to: ". a:1) - endif - - return - endif - - if !exists('g:go_guru_tags') - call go#util#EchoSuccess("guru tags is not set") - else - call go#util#EchoSuccess("current guru tags: ". a:1) - endif -endfunction - -" Show 'implements' relation for selected package -function! go#guru#Implements(selected) - let out = s:RunGuru('implements', 'plain', a:selected, 1) - if has_key(out, 'err') - call go#util#EchoError(out.err) - return - endif - - call s:loclistSecond(out.out) -endfunction - -" Describe selected syntax: definition, methods, etc -function! go#guru#Describe(selected) - let out = s:RunGuru('describe', 'plain', a:selected, 0) - if has_key(out, 'err') - call go#util#EchoError(out.err) - return - endif - - call s:loclistSecond(out.out) -endfunction - -" Show possible targets of selected function call -function! go#guru#Callees(selected) - let out = s:RunGuru('callees', 'plain', a:selected, 1) - if has_key(out, 'err') - call go#util#EchoError(out.err) - return - endif - - call s:loclistSecond(out.out) -endfunction - -" Show possible callers of selected function -function! go#guru#Callers(selected) - let out = s:RunGuru('callers', 'plain', a:selected, 1) - if has_key(out, 'err') - call go#util#EchoError(out.err) - return - endif - - call s:loclistSecond(out.out) -endfunction - -" Show path from callgraph root to selected function -function! go#guru#Callstack(selected) - let out = s:RunGuru('callstack', 'plain', a:selected, 1) - if has_key(out, 'err') - call go#util#EchoError(out.err) - return - endif - - call s:loclistSecond(out.out) -endfunction - -" Show free variables of selection -function! go#guru#Freevars(selected) - " Freevars requires a selection - if a:selected == -1 - call go#util#EchoError("GoFreevars requires a selection (range) of code") - return - endif - - let out = s:RunGuru('freevars', 'plain', a:selected, 0) - if has_key(out, 'err') - call go#util#EchoError(out.err) - return - endif - - call s:loclistSecond(out.out) -endfunction - -" Show send/receive corresponding to selected channel op -function! go#guru#ChannelPeers(selected) - let out = s:RunGuru('peers', 'plain', a:selected, 1) - if has_key(out, 'err') - call go#util#EchoError(out.err) - return - endif - - call s:loclistSecond(out.out) -endfunction - -" Show all refs to entity denoted by selected identifier -function! go#guru#Referrers(selected) - let out = s:RunGuru('referrers', 'plain', a:selected, 0) - if has_key(out, 'err') - call go#util#EchoError(out.err) - return - endif - - call s:loclistSecond(out.out) -endfunction - -function! go#guru#What(selected) - " nvim doesn't have JSON support, though they work on it: - " https://github.com/neovim/neovim/pull/4131 - if has('nvim') - return {'err': "GoWhat is not supported in Neovim"} - endif - - " json_encode() and friends are introduced with this patch - " https://groups.google.com/d/msg/vim_dev/vLupTNhQhZ8/cDGIk0JEDgAJ - if !has('patch-7.4.1304') - return {'err': "GoWhat is supported with Vim version 7.4-1304 or later"} - endif - - let out = s:RunGuru('what', 'json', a:selected, 0) - if has_key(out, 'err') - return out.err - endif - - call s:loclistSecond(out.out) - let result = json_decode(out.out) - - if type(result) != type({}) - return {'err': "malformed output from guru"} - endif - - if !has_key(result, 'what') - return {'err': "no what query found for the given identifier"} - endif - - return {'out': result.what} -endfunction - -function! go#guru#SameIds(selected) - let result = go#guru#What(a:selected) - if has_key(out, 'err') - call go#util#EchoError(out.err) - return - endif - - if !has_key(result.out, 'sameids') - call go#util#EchoError("no same_ids founds for the given identifier") - return -1 - endif - - let same_ids = result.what.sameids - echo same_ids -endfunction - -" vim:ts=4:sw=4:et +" vim: sw=2 ts=2 et diff --git a/sources_non_forked/vim-go/autoload/go/impl.vim b/sources_non_forked/vim-go/autoload/go/impl.vim index 678b078e..2a10437f 100644 --- a/sources_non_forked/vim-go/autoload/go/impl.vim +++ b/sources_non_forked/vim-go/autoload/go/impl.vim @@ -1,124 +1,148 @@ -function! go#impl#Impl(...) - let binpath = go#path#CheckBinPath('impl') - if empty(binpath) - return +function! go#impl#Impl(...) abort + let binpath = go#path#CheckBinPath('impl') + if empty(binpath) + return + endif + + let recv = "" + let iface = "" + let interactive = 0 + + let pos = getpos('.') + + if a:0 == 0 + " Interactive mode if user didn't pass any arguments. + let recv = s:getReceiver() + let iface = input("vim-go: generating method stubs for interface: ") + redraw! + if empty(iface) + call go#util#EchoError('usage: interface type is not provided') + return endif + elseif a:0 == 1 + " we assume the user only passed the interface type, + " i.e: ':GoImpl io.Writer' + let recv = s:getReceiver() + let iface = a:1 + elseif a:0 > 2 + " user passed receiver and interface type both, + " i.e: 'GoImpl f *Foo io.Writer' + let recv = join(a:000[:-2], ' ') + let iface = a:000[-1] + else + call go#util#EchoError('usage: GoImpl {receiver} {interface}') + return + endif - let recv = "" - let iface = "" + " Make sure we put the generated code *after* the struct. + if getline(".") =~ "struct " + normal! $% + endif - if a:0 == 0 - " user didn't passed anything, just called ':GoImpl' - let receiveType = expand("") - let recv = printf("%s *%s", tolower(receiveType)[0], receiveType) - let iface = input("vim-go: generating method stubs for interface: ") - redraw! - if empty(iface) - call go#util#EchoError('usage: interface type is not provided') - return - endif - elseif a:0 == 1 - " we assume the user only passed the interface type, - " i.e: ':GoImpl io.Writer' - let receiveType = expand("") - let recv = printf("%s *%s", tolower(receiveType)[0], receiveType) - let iface = a:1 - elseif a:0 > 2 - " user passed receiver and interface type both, - " i.e: 'GoImpl f *Foo io.Writer' - let recv = join(a:000[:-2], ' ') - let iface = a:000[-1] - else - call go#util#EchoError('usage: GoImpl {receiver} {interface}') - return - endif - - let result = go#util#System(printf("%s '%s' '%s'", binpath, recv, iface)) + try + let dirname = fnameescape(expand('%:p:h')) + let result = go#util#System(join(go#util#Shelllist([binpath, '-dir', dirname, recv, iface], ' '))) + let result = substitute(result, "\n*$", "", "") if go#util#ShellError() != 0 - call go#util#EchoError(result) - return + call go#util#EchoError(result) + return endif if result ==# '' - return + return end - let pos = getpos('.') - put ='' + put ='' put =result + finally call setpos('.', pos) + endtry +endfunction + +function! s:getReceiver() + let receiveType = expand("") + if receiveType == "type" + normal! w + let receiveType = expand("") + elseif receiveType == "struct" + normal! ge + let receiveType = expand("") + endif + return printf("%s *%s", tolower(receiveType)[0], receiveType) endfunction if exists('*uniq') - function! s:uniq(list) - return uniq(a:list) - endfunction + function! s:uniq(list) + return uniq(a:list) + endfunction else - " Note: Believe that the list is sorted - function! s:uniq(list) - let i = len(a:list) - 1 - while 0 < i - if a:list[i-1] ==# a:list[i] - call remove(a:list, i) - let i -= 2 - else - let i -= 1 - endif - endwhile - return a:list - endfunction + " Note: Believe that the list is sorted + function! s:uniq(list) + let i = len(a:list) - 1 + while 0 < i + if a:list[i-1] ==# a:list[i] + call remove(a:list, i) + let i -= 2 + else + let i -= 1 + endif + endwhile + return a:list + endfunction endif -function! s:root_dirs() - let dirs = [] - let root = go#util#GOROOT() - if root !=# '' && isdirectory(root) - call add(dirs, root) - endif +function! s:root_dirs() abort + let dirs = [] + let root = go#util#env("goroot") + if root !=# '' && isdirectory(root) + call add(dirs, root) + endif - let paths = map(split(go#util#GOPATH(), go#util#PathListSep()), "substitute(v:val, '\\\\', '/', 'g')") - if go#util#ShellError() - return [] - endif + let paths = map(split(go#util#env("gopath"), go#util#PathListSep()), "substitute(v:val, '\\\\', '/', 'g')") + if go#util#ShellError() + return [] + endif - if !empty(filter(paths, 'isdirectory(v:val)')) - call extend(dirs, paths) - endif + if !empty(filter(paths, 'isdirectory(v:val)')) + call extend(dirs, paths) + endif - return dirs + return dirs endfunction -function! s:go_packages(dirs) - let pkgs = [] - for d in a:dirs - let pkg_root = expand(d . '/pkg/' . go#util#OSARCH()) - call extend(pkgs, split(globpath(pkg_root, '**/*.a', 1), "\n")) - endfor - return map(pkgs, "fnamemodify(v:val, ':t:r')") +function! s:go_packages(dirs) abort + let pkgs = [] + for d in a:dirs + let pkg_root = expand(d . '/pkg/' . go#util#osarch()) + call extend(pkgs, split(globpath(pkg_root, '**/*.a', 1), "\n")) + endfor + return map(pkgs, "fnamemodify(v:val, ':t:r')") endfunction -function! s:interface_list(pkg) - let contents = split(go#util#System('go doc ' . a:pkg), "\n") - if go#util#ShellError() - return [] - endif +function! s:interface_list(pkg) abort + let contents = split(go#util#System('go doc ' . a:pkg), "\n") + if go#util#ShellError() + return [] + endif - call filter(contents, 'v:val =~# ''^type\s\+\h\w*\s\+interface''') - return map(contents, 'a:pkg . "." . matchstr(v:val, ''^type\s\+\zs\h\w*\ze\s\+interface'')') + call filter(contents, 'v:val =~# ''^type\s\+\h\w*\s\+interface''') + return map(contents, 'a:pkg . "." . matchstr(v:val, ''^type\s\+\zs\h\w*\ze\s\+interface'')') endfunction " Complete package and interface for {interface} -function! go#impl#Complete(arglead, cmdline, cursorpos) - let words = split(a:cmdline, '\s\+', 1) - if words[-1] ==# '' - return s:uniq(sort(s:go_packages(s:root_dirs()))) - elseif words[-1] =~# '^\h\w*$' - return s:uniq(sort(filter(s:go_packages(s:root_dirs()), 'stridx(v:val, words[-1]) == 0'))) - elseif words[-1] =~# '^\h\w*\.\%(\h\w*\)\=$' - let [pkg, interface] = split(words[-1], '\.', 1) - echomsg pkg - return s:uniq(sort(filter(s:interface_list(pkg), 'v:val =~? words[-1]'))) - else - return [] - endif +function! go#impl#Complete(arglead, cmdline, cursorpos) abort + let words = split(a:cmdline, '\s\+', 1) + if words[-1] ==# '' + return s:uniq(sort(s:go_packages(s:root_dirs()))) + elseif words[-1] =~# '^\h\w*$' + return s:uniq(sort(filter(s:go_packages(s:root_dirs()), 'stridx(v:val, words[-1]) == 0'))) + elseif words[-1] =~# '^\h\w*\.\%(\h\w*\)\=$' + let [pkg, interface] = split(words[-1], '\.', 1) + echomsg pkg + return s:uniq(sort(filter(s:interface_list(pkg), 'v:val =~? words[-1]'))) + else + return [] + endif endfunction + +" vim: sw=2 ts=2 et diff --git a/sources_non_forked/vim-go/autoload/go/import.vim b/sources_non_forked/vim-go/autoload/go/import.vim index f5a6f372..8d9e8d4c 100644 --- a/sources_non_forked/vim-go/autoload/go/import.vim +++ b/sources_non_forked/vim-go/autoload/go/import.vim @@ -4,210 +4,210 @@ " " Check out the docs for more information at /doc/vim-go.txt " -function! go#import#SwitchImport(enabled, localname, path, bang) - let view = winsaveview() - let path = substitute(a:path, '^\s*\(.\{-}\)\s*$', '\1', '') +function! go#import#SwitchImport(enabled, localname, path, bang) abort + let view = winsaveview() + let path = substitute(a:path, '^\s*\(.\{-}\)\s*$', '\1', '') - " Quotes are not necessary, so remove them if provided. - if path[0] == '"' - let path = strpart(path, 1) - endif - if path[len(path)-1] == '"' - let path = strpart(path, 0, len(path) - 1) + " Quotes are not necessary, so remove them if provided. + if path[0] == '"' + let path = strpart(path, 1) + endif + if path[len(path)-1] == '"' + let path = strpart(path, 0, len(path) - 1) + endif + + " if given a trailing slash, eg. `github.com/user/pkg/`, remove it + if path[len(path)-1] == '/' + let path = strpart(path, 0, len(path) - 1) + endif + + if path == '' + call s:Error('Import path not provided') + return + endif + + if a:bang == "!" + let out = go#util#System("go get -u -v ".shellescape(path)) + if go#util#ShellError() != 0 + call s:Error("Can't find import: " . path . ":" . out) endif + endif + let exists = go#tool#Exists(path) + if exists == -1 + call s:Error("Can't find import: " . path) + return + endif - " if given a trailing slash, eg. `github.com/user/pkg/`, remove it - if path[len(path)-1] == '/' - let path = strpart(path, 0, len(path) - 1) - endif + " Extract any site prefix (e.g. github.com/). + " If other imports with the same prefix are grouped separately, + " we will add this new import with them. + " Only up to and including the first slash is used. + let siteprefix = matchstr(path, "^[^/]*/") - if path == '' - call s:Error('Import path not provided') - return - endif + let qpath = '"' . path . '"' + if a:localname != '' + let qlocalpath = a:localname . ' ' . qpath + else + let qlocalpath = qpath + endif + let indentstr = 0 + let packageline = -1 " Position of package name statement + let appendline = -1 " Position to introduce new import + let deleteline = -1 " Position of line with existing import + let linesdelta = 0 " Lines added/removed - if a:bang == "!" - let out = go#util#System("go get -u -v ".shellescape(path)) - if go#util#ShellError() != 0 - call s:Error("Can't find import: " . path . ":" . out) - endif - endif - let exists = go#tool#Exists(path) - if exists == -1 - call s:Error("Can't find import: " . path) - return - endif + " Find proper place to add/remove import. + let line = 0 + while line <= line('$') + let linestr = getline(line) - " Extract any site prefix (e.g. github.com/). - " If other imports with the same prefix are grouped separately, - " we will add this new import with them. - " Only up to and including the first slash is used. - let siteprefix = matchstr(path, "^[^/]*/") + if linestr =~# '^package\s' + let packageline = line + let appendline = line - let qpath = '"' . path . '"' - if a:localname != '' - let qlocalpath = a:localname . ' ' . qpath - else - let qlocalpath = qpath - endif - let indentstr = 0 - let packageline = -1 " Position of package name statement - let appendline = -1 " Position to introduce new import - let deleteline = -1 " Position of line with existing import - let linesdelta = 0 " Lines added/removed - - " Find proper place to add/remove import. - let line = 0 - while line <= line('$') - let linestr = getline(line) - - if linestr =~# '^package\s' - let packageline = line - let appendline = line - - elseif linestr =~# '^import\s\+(' - let appendstr = qlocalpath - let indentstr = 1 - let appendline = line - let firstblank = -1 - let lastprefix = "" - while line <= line("$") - let line = line + 1 - let linestr = getline(line) - let m = matchlist(getline(line), '^\()\|\(\s\+\)\(\S*\s*\)"\(.\+\)"\)') - if empty(m) - if siteprefix == "" && a:enabled - " must be in the first group - break - endif - " record this position, but keep looking - if firstblank < 0 - let firstblank = line - endif - continue - endif - if m[1] == ')' - " if there's no match, add it to the first group - if appendline < 0 && firstblank >= 0 - let appendline = firstblank - endif - break - endif - let lastprefix = matchstr(m[4], "^[^/]*/") - if a:localname != '' && m[3] != '' - let qlocalpath = printf('%-' . (len(m[3])-1) . 's %s', a:localname, qpath) - endif - let appendstr = m[2] . qlocalpath - let indentstr = 0 - if m[4] == path - let appendline = -1 - let deleteline = line - break - elseif m[4] < path - " don't set candidate position if we have a site prefix, - " we've passed a blank line, and this doesn't share the same - " site prefix. - if siteprefix == "" || firstblank < 0 || match(m[4], "^" . siteprefix) >= 0 - let appendline = line - endif - elseif siteprefix != "" && match(m[4], "^" . siteprefix) >= 0 - " first entry of site group - let appendline = line - 1 - break - endif - endwhile - break - - elseif linestr =~# '^import ' - if appendline == packageline - let appendstr = 'import ' . qlocalpath - let appendline = line - 1 - endif - let m = matchlist(linestr, '^import\(\s\+\)\(\S*\s*\)"\(.\+\)"') - if !empty(m) - if m[3] == path - let appendline = -1 - let deleteline = line - break - endif - if m[3] < path - let appendline = line - endif - if a:localname != '' && m[2] != '' - let qlocalpath = printf("%s %" . len(m[2])-1 . "s", a:localname, qpath) - endif - let appendstr = 'import' . m[1] . qlocalpath - endif - - elseif linestr =~# '^\(var\|const\|type\|func\)\>' - break - - endif + elseif linestr =~# '^import\s\+(' + let appendstr = qlocalpath + let indentstr = 1 + let appendline = line + let firstblank = -1 + let lastprefix = "" + while line <= line("$") let line = line + 1 - endwhile - - " Append or remove the package import, as requested. - if a:enabled - if deleteline != -1 - call s:Error(qpath . ' already being imported') - elseif appendline == -1 - call s:Error('No package line found') - else - if appendline == packageline - call append(appendline + 0, '') - call append(appendline + 1, 'import (') - call append(appendline + 2, ')') - let appendline += 2 - let linesdelta += 3 - let appendstr = qlocalpath - let indentstr = 1 - endif - call append(appendline, appendstr) - execute appendline + 1 - if indentstr - execute 'normal! >>' - endif - let linesdelta += 1 + let linestr = getline(line) + let m = matchlist(getline(line), '^\()\|\(\s\+\)\(\S*\s*\)"\(.\+\)"\)') + if empty(m) + if siteprefix == "" && a:enabled + " must be in the first group + break + endif + " record this position, but keep looking + if firstblank < 0 + let firstblank = line + endif + continue endif + if m[1] == ')' + " if there's no match, add it to the first group + if appendline < 0 && firstblank >= 0 + let appendline = firstblank + endif + break + endif + let lastprefix = matchstr(m[4], "^[^/]*/") + if a:localname != '' && m[3] != '' + let qlocalpath = printf('%-' . (len(m[3])-1) . 's %s', a:localname, qpath) + endif + let appendstr = m[2] . qlocalpath + let indentstr = 0 + if m[4] == path + let appendline = -1 + let deleteline = line + break + elseif m[4] < path + " don't set candidate position if we have a site prefix, + " we've passed a blank line, and this doesn't share the same + " site prefix. + if siteprefix == "" || firstblank < 0 || match(m[4], "^" . siteprefix) >= 0 + let appendline = line + endif + elseif siteprefix != "" && match(m[4], "^" . siteprefix) >= 0 + " first entry of site group + let appendline = line - 1 + break + endif + endwhile + break + + elseif linestr =~# '^import ' + if appendline == packageline + let appendstr = 'import ' . qlocalpath + let appendline = line - 1 + endif + let m = matchlist(linestr, '^import\(\s\+\)\(\S*\s*\)"\(.\+\)"') + if !empty(m) + if m[3] == path + let appendline = -1 + let deleteline = line + break + endif + if m[3] < path + let appendline = line + endif + if a:localname != '' && m[2] != '' + let qlocalpath = printf("%s %" . len(m[2])-1 . "s", a:localname, qpath) + endif + let appendstr = 'import' . m[1] . qlocalpath + endif + + elseif linestr =~# '^\(var\|const\|type\|func\)\>' + break + + endif + let line = line + 1 + endwhile + + " Append or remove the package import, as requested. + if a:enabled + if deleteline != -1 + call s:Error(qpath . ' already being imported') + elseif appendline == -1 + call s:Error('No package line found') else - if deleteline == -1 - call s:Error(qpath . ' not being imported') - else - execute deleteline . 'd' - let linesdelta -= 1 - - if getline(deleteline-1) =~# '^import\s\+(' && getline(deleteline) =~# '^)' - " Delete empty import block - let deleteline -= 1 - execute deleteline . "d" - execute deleteline . "d" - let linesdelta -= 2 - endif - - if getline(deleteline) == '' && getline(deleteline - 1) == '' - " Delete spacing for removed line too. - execute deleteline . "d" - let linesdelta -= 1 - endif - endif + if appendline == packageline + call append(appendline + 0, '') + call append(appendline + 1, 'import (') + call append(appendline + 2, ')') + let appendline += 2 + let linesdelta += 3 + let appendstr = qlocalpath + let indentstr = 1 + endif + call append(appendline, appendstr) + execute appendline + 1 + if indentstr + execute 'normal! >>' + endif + let linesdelta += 1 endif + else + if deleteline == -1 + call s:Error(qpath . ' not being imported') + else + execute deleteline . 'd' + let linesdelta -= 1 - " Adjust view for any changes. - let view.lnum += linesdelta - let view.topline += linesdelta - if view.topline < 0 - let view.topline = 0 + if getline(deleteline-1) =~# '^import\s\+(' && getline(deleteline) =~# '^)' + " Delete empty import block + let deleteline -= 1 + execute deleteline . "d" + execute deleteline . "d" + let linesdelta -= 2 + endif + + if getline(deleteline) == '' && getline(deleteline - 1) == '' + " Delete spacing for removed line too. + execute deleteline . "d" + let linesdelta -= 1 + endif endif + endif - " Put buffer back where it was. - call winrestview(view) + " Adjust view for any changes. + let view.lnum += linesdelta + let view.topline += linesdelta + if view.topline < 0 + let view.topline = 0 + endif + + " Put buffer back where it was. + call winrestview(view) endfunction -function! s:Error(s) - echohl Error | echo a:s | echohl None +function! s:Error(s) abort + echohl Error | echo a:s | echohl None endfunction -" vim:ts=4:sw=4:et +" vim: sw=2 ts=2 et diff --git a/sources_non_forked/vim-go/autoload/go/job.vim b/sources_non_forked/vim-go/autoload/go/job.vim new file mode 100644 index 00000000..965f20d3 --- /dev/null +++ b/sources_non_forked/vim-go/autoload/go/job.vim @@ -0,0 +1,102 @@ +" Spawn returns callbacks to be used with job_start. It's abstracted to be +" used with various go command, such as build, test, install, etc.. This avoid +" us to write the same callback over and over for some commands. It's fully +" customizable so each command can change it to it's own logic. +function go#job#Spawn(args) + let cbs = { + \ 'winnr': winnr(), + \ 'dir': getcwd(), + \ 'jobdir': fnameescape(expand("%:p:h")), + \ 'messages': [], + \ 'args': a:args.cmd, + \ 'bang': 0, + \ 'for': "_job", + \ } + + if has_key(a:args, 'bang') + let cbs.bang = a:args.bang + endif + + if has_key(a:args, 'for') + let cbs.for = a:args.for + endif + + " add final callback to be called if async job is finished + " The signature should be in form: func(job, exit_status, messages) + if has_key(a:args, 'custom_cb') + let cbs.custom_cb = a:args.custom_cb + endif + + if has_key(a:args, 'error_info_cb') + let cbs.error_info_cb = a:args.error_info_cb + endif + + function cbs.callback(chan, msg) dict + call add(self.messages, a:msg) + endfunction + + function cbs.exit_cb(job, exitval) dict + if has_key(self, 'error_info_cb') + call self.error_info_cb(a:job, a:exitval, self.messages) + endif + + if get(g:, 'go_echo_command_info', 1) + if a:exitval == 0 + call go#util#EchoSuccess("SUCCESS") + else + call go#util#EchoError("FAILED") + endif + endif + + if has_key(self, 'custom_cb') + call self.custom_cb(a:job, a:exitval, self.messages) + endif + + let l:listtype = go#list#Type(self.for) + if a:exitval == 0 + call go#list#Clean(l:listtype) + call go#list#Window(l:listtype) + return + endif + + call self.show_errors(l:listtype) + endfunction + + function cbs.show_errors(listtype) dict + let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd ' + try + execute cd self.jobdir + let errors = go#tool#ParseErrors(self.messages) + let errors = go#tool#FilterValids(errors) + finally + execute cd . fnameescape(self.dir) + endtry + + if !len(errors) + " failed to parse errors, output the original content + call go#util#EchoError(self.messages + [self.dir]) + return + endif + + if self.winnr == winnr() + call go#list#Populate(a:listtype, errors, join(self.args)) + call go#list#Window(a:listtype, len(errors)) + if !empty(errors) && !self.bang + call go#list#JumpToFirst(a:listtype) + endif + endif + endfunction + + " override callback handler if user provided it + if has_key(a:args, 'callback') + let cbs.callback = a:args.callback + endif + + " override exit callback handler if user provided it + if has_key(a:args, 'exit_cb') + let cbs.exit_cb = a:args.exit_cb + endif + + return cbs +endfunction +" vim: sw=2 ts=2 et diff --git a/sources_non_forked/vim-go/autoload/go/jobcontrol.vim b/sources_non_forked/vim-go/autoload/go/jobcontrol.vim index 17bd198f..2dd20fbc 100644 --- a/sources_non_forked/vim-go/autoload/go/jobcontrol.vim +++ b/sources_non_forked/vim-go/autoload/go/jobcontrol.vim @@ -9,39 +9,16 @@ let s:handlers = {} " Spawn is a wrapper around s:spawn. It can be executed by other files and " scripts if needed. Desc defines the description for printing the status " during the job execution (useful for statusline integration). -function! go#jobcontrol#Spawn(bang, desc, args) +function! go#jobcontrol#Spawn(bang, desc, for, args) abort " autowrite is not enabled for jobs call go#cmd#autowrite() - let job = s:spawn(a:bang, a:desc, a:args) + let job = s:spawn(a:bang, a:desc, a:for, a:args) return job.id endfunction -" Statusline returns the current status of the job -function! go#jobcontrol#Statusline() abort - if empty(s:jobs) - return '' - endif - - let import_path = go#package#ImportPath(expand('%:p:h')) - - for job in values(s:jobs) - if job.importpath != import_path - continue - endif - - if job.state == "SUCCESS" - return '' - endif - - return printf("%s ... [%s]", job.desc, job.state) - endfor - - return '' -endfunction - " AddHandler adds a on_exit callback handler and returns the id. -function! go#jobcontrol#AddHandler(handler) +function! go#jobcontrol#AddHandler(handler) abort let i = len(s:handlers) while has_key(s:handlers, string(i)) let i += 1 @@ -52,7 +29,7 @@ function! go#jobcontrol#AddHandler(handler) endfunction " RemoveHandler removes a callback handler by id. -function! go#jobcontrol#RemoveHandler(id) +function! go#jobcontrol#RemoveHandler(id) abort unlet s:handlers[a:id] endfunction @@ -60,18 +37,32 @@ endfunction " a job is started a reference will be stored inside s:jobs. spawn changes the " GOPATH when g:go_autodetect_gopath is enabled. The job is started inside the " current files folder. -function! s:spawn(bang, desc, args) - let job = { - \ 'desc': a:desc, - \ 'bang': a:bang, +function! s:spawn(bang, desc, for, args) abort + let status_type = a:args[0] + let status_dir = expand('%:p:h') + let started_at = reltime() + + call go#statusline#Update(status_dir, { + \ 'desc': "current status", + \ 'type': status_type, + \ 'state': "started", + \}) + + let job = { + \ 'desc': a:desc, + \ 'bang': a:bang, \ 'winnr': winnr(), - \ 'importpath': go#package#ImportPath(expand('%:p:h')), + \ 'importpath': go#package#ImportPath(), \ 'state': "RUNNING", \ 'stderr' : [], \ 'stdout' : [], \ 'on_stdout': function('s:on_stdout'), \ 'on_stderr': function('s:on_stderr'), \ 'on_exit' : function('s:on_exit'), + \ 'status_type' : status_type, + \ 'status_dir' : status_dir, + \ 'started_at' : started_at, + \ 'for' : a:for, \ } " modify GOPATH if needed @@ -113,31 +104,57 @@ endfunction " references and also displaying errors in the quickfix window collected by " on_stderr handler. If there are no errors and a quickfix window is open, " it'll be closed. -function! s:on_exit(job_id, exit_status) +function! s:on_exit(job_id, exit_status, event) dict abort + let status = { + \ 'desc': 'last status', + \ 'type': self.status_type, + \ 'state': "success", + \ } + + if a:exit_status + let status.state = "failed" + endif + + let elapsed_time = reltimestr(reltime(self.started_at)) + " strip whitespace + let elapsed_time = substitute(elapsed_time, '^\s*\(.\{-}\)\s*$', '\1', '') + let status.state .= printf(" (%ss)", elapsed_time) + + call go#statusline#Update(self.status_dir, status) + let std_combined = self.stderr + self.stdout + + let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd ' + let dir = getcwd() + execute cd self.dir + call s:callback_handlers_on_exit(s:jobs[a:job_id], a:exit_status, std_combined) + let l:listtype = go#list#Type(self.for) if a:exit_status == 0 - call go#list#Clean(0) - call go#list#Window(0) + call go#list#Clean(l:listtype) + call go#list#Window(l:listtype) let self.state = "SUCCESS" - call go#util#EchoSuccess("SUCCESS") + + if get(g:, 'go_echo_command_info', 1) + call go#util#EchoSuccess("[" . self.status_type . "] SUCCESS") + endif + + execute cd . fnameescape(dir) return endif let self.state = "FAILED" - call go#util#EchoError("FAILED") - let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd ' - let dir = getcwd() - try - execute cd self.dir - let errors = go#tool#ParseErrors(std_combined) - let errors = go#tool#FilterValids(errors) - finally - execute cd . fnameescape(dir) - endtry + if get(g:, 'go_echo_command_info', 1) + call go#util#EchoError("[" . self.status_type . "] FAILED") + endif + + let errors = go#tool#ParseErrors(std_combined) + let errors = go#tool#FilterValids(errors) + + execute cd . fnameescape(dir) if !len(errors) " failed to parse errors, output the original content @@ -147,8 +164,7 @@ function! s:on_exit(job_id, exit_status) " if we are still in the same windows show the list if self.winnr == winnr() - let l:listtype = "locationlist" - call go#list#Populate(l:listtype, errors) + call go#list#Populate(l:listtype, errors, self.desc) call go#list#Window(l:listtype, len(errors)) if !empty(errors) && !self.bang call go#list#JumpToFirst(l:listtype) @@ -157,7 +173,7 @@ function! s:on_exit(job_id, exit_status) endfunction " callback_handlers_on_exit runs all handlers for job on exit event. -function! s:callback_handlers_on_exit(job, exit_status, data) +function! s:callback_handlers_on_exit(job, exit_status, data) abort if empty(s:handlers) return endif @@ -168,45 +184,15 @@ function! s:callback_handlers_on_exit(job, exit_status, data) endfunction " on_stdout is the stdout handler for jobstart(). It collects the output of -" stderr and stores them to the jobs internal stdout list. -function! s:on_stdout(job_id, data) +" stderr and stores them to the jobs internal stdout list. +function! s:on_stdout(job_id, data, event) dict abort call extend(self.stdout, a:data) endfunction " on_stderr is the stderr handler for jobstart(). It collects the output of " stderr and stores them to the jobs internal stderr list. -function! s:on_stderr(job_id, data) +function! s:on_stderr(job_id, data, event) dict abort call extend(self.stderr, a:data) endfunction -" abort_all aborts all current jobs created with s:spawn() -function! s:abort_all() - if empty(s:jobs) - return - endif - - for id in keys(s:jobs) - if id > 0 - silent! call jobstop(id) - endif - endfor - - let s:jobs = {} -endfunction - -" abort aborts the job with the given name, where name is the first argument -" passed to s:spawn() -function! s:abort(path) - if empty(s:jobs) - return - endif - - for job in values(s:jobs) - if job.importpath == path && job.id > 0 - silent! call jobstop(job.id) - unlet s:jobs['job.id'] - endif - endfor -endfunction - -" vim:ts=2:sw=2:et +" vim: sw=2 ts=2 et diff --git a/sources_non_forked/vim-go/autoload/go/keyify.vim b/sources_non_forked/vim-go/autoload/go/keyify.vim new file mode 100644 index 00000000..10555514 --- /dev/null +++ b/sources_non_forked/vim-go/autoload/go/keyify.vim @@ -0,0 +1,61 @@ +function! go#keyify#Keyify() + let old_gopath = $GOPATH + let $GOPATH = go#path#Detect() + let bin_path = go#path#CheckBinPath("keyify") + let fname = fnamemodify(expand("%"), ':p:gs?\\?/?') + + if empty(bin_path) || !exists('*json_decode') + let $GOPATH = old_gopath + return + endif + + " Get result of command as json, that contains `start`, `end` and `replacement` + let command = printf("%s -json %s:#%s", go#util#Shellescape(bin_path), + \ go#util#Shellescape(fname), go#util#OffsetCursor()) + let output = go#util#System(command) + silent! let result = json_decode(output) + + " We want to output the error message in case the result isn't a JSON + if type(result) != type({}) + call go#util#EchoError(s:chomp(output)) + let $GOPATH = old_gopath + return + endif + + " Because keyify returns the byte before the region we want, we goto the + " byte after that + execute "goto" result.start + 1 + let start = getpos('.') + execute "goto" result.end + let end = getpos('.') + + let vis_start = getpos("'<") + let vis_end = getpos("'>") + + " Replace contents between start and end with `replacement` + call setpos("'<", start) + call setpos("'>", end) + + let select = 'gv' + + " Make sure the visual mode is 'v', to avoid some bugs + normal! gv + if mode() !=# 'v' + let select .= 'v' + endif + + silent! execute "normal!" select."\"=result.replacement\p" + + " Replacement text isn't aligned, so it needs fix + normal! '= + + call setpos("'<", vis_start) + call setpos("'>", vis_end) + let $GOPATH = old_gopath +endfunction + +function! s:chomp(string) + return substitute(a:string, '\n\+$', '', '') +endfunction + +" vim: sw=2 ts=2 et diff --git a/sources_non_forked/vim-go/autoload/go/lint.vim b/sources_non_forked/vim-go/autoload/go/lint.vim index 34ff7f6f..3fdd8ec3 100644 --- a/sources_non_forked/vim-go/autoload/go/lint.vim +++ b/sources_non_forked/vim-go/autoload/go/lint.vim @@ -1,199 +1,326 @@ if !exists("g:go_metalinter_command") - let g:go_metalinter_command = "" + let g:go_metalinter_command = "" endif if !exists("g:go_metalinter_autosave_enabled") - let g:go_metalinter_autosave_enabled = ['vet', 'golint'] + let g:go_metalinter_autosave_enabled = ['vet', 'golint'] endif if !exists("g:go_metalinter_enabled") - let g:go_metalinter_enabled = ['vet', 'golint', 'errcheck'] + let g:go_metalinter_enabled = ['vet', 'golint', 'errcheck'] endif -if !exists("g:go_metalinter_deadline") - let g:go_metalinter_deadline = "5s" +if !exists("g:go_metalinter_excludes") + let g:go_metalinter_excludes = [] endif if !exists("g:go_golint_bin") - let g:go_golint_bin = "golint" + let g:go_golint_bin = "golint" endif if !exists("g:go_errcheck_bin") - let g:go_errcheck_bin = "errcheck" + let g:go_errcheck_bin = "errcheck" endif function! go#lint#Gometa(autosave, ...) abort - if a:0 == 0 - let goargs = shellescape(expand('%:p:h')) - else - let goargs = go#util#Shelljoin(a:000) + if a:0 == 0 + let goargs = shellescape(expand('%:p:h')) + else + let goargs = go#util#Shelljoin(a:000) + endif + + let bin_path = go#path#CheckBinPath("gometalinter") + if empty(bin_path) + return + endif + + let cmd = [bin_path] + let cmd += ["--disable-all"] + + if a:autosave || empty(g:go_metalinter_command) + " linters + let linters = a:autosave ? g:go_metalinter_autosave_enabled : g:go_metalinter_enabled + for linter in linters + let cmd += ["--enable=".linter] + endfor + + for exclude in g:go_metalinter_excludes + let cmd += ["--exclude=".exclude] + endfor + + " gometalinter has a --tests flag to tell its linters whether to run + " against tests. While not all of its linters respect this flag, for those + " that do, it means if we don't pass --tests, the linter won't run against + " test files. One example of a linter that will not run against tests if + " we do not specify this flag is errcheck. + let cmd += ["--tests"] + + " path + let cmd += [expand('%:p:h')] + else + " the user wants something else, let us use it. + let cmd += split(g:go_metalinter_command, " ") + endif + + " gometalinter has a default deadline of 5 seconds. + " + " For async mode (s:lint_job), we want to override the default deadline only + " if we have a deadline configured. + " + " For sync mode (go#util#System), always explicitly pass the 5 seconds + " deadline if there is no other deadline configured. If a deadline is + " configured, then use it. + + " Call gometalinter asynchronously. + if go#util#has_job() && has('lambda') + let deadline = get(g:, 'go_metalinter_deadline', 0) + if deadline != 0 + let cmd += ["--deadline=" . deadline] endif - let meta_command = "gometalinter --disable-all" - if a:autosave || empty(g:go_metalinter_command) - let bin_path = go#path#CheckBinPath("gometalinter") - if empty(bin_path) - return - endif + call s:lint_job({'cmd': cmd}) + return + endif - if a:autosave - " include only messages for the active buffer - let meta_command .= " --include='^" . expand('%:p') . ".*$'" - endif + " We're calling gometalinter synchronously. - " linters - let linters = a:autosave ? g:go_metalinter_autosave_enabled : g:go_metalinter_enabled - for linter in linters - let meta_command .= " --enable=".linter - endfor + let cmd += ["--deadline=" . get(g:, 'go_metalinter_deadline', "5s")] - " deadline - let meta_command .= " --deadline=" . g:go_metalinter_deadline + if a:autosave + " include only messages for the active buffer + let cmd += ["--include='^" . expand('%:p') . ".*$'"] + endif - " path - let meta_command .= " " . goargs - else - " the user wants something else, let us use it. - let meta_command = g:go_metalinter_command - endif - - " comment out the following two lines for debugging - " echo meta_command - " return - - let out = go#tool#ExecuteInDir(meta_command) - - let l:listtype = "quickfix" - if go#util#ShellError() == 0 - redraw | echo - call go#list#Clean(l:listtype) - call go#list#Window(l:listtype) - echon "vim-go: " | echohl Function | echon "[metalinter] PASS" | echohl None - else - " GoMetaLinter can output one of the two, so we look for both: - " ::[]: () - " ::: () - " This can be defined by the following errorformat: - let errformat = "%f:%l:%c:%t%*[^:]:\ %m,%f:%l::%t%*[^:]:\ %m" - - " Parse and populate our location list - call go#list#ParseFormat(l:listtype, errformat, split(out, "\n")) - - let errors = go#list#Get(l:listtype) - call go#list#Window(l:listtype, len(errors)) - - if !a:autosave - call go#list#JumpToFirst(l:listtype) - endif + + let meta_command = join(cmd, " ") + + let out = go#util#System(meta_command) + + let l:listtype = go#list#Type("GoMetaLinter") + if go#util#ShellError() == 0 + redraw | echo + call go#list#Clean(l:listtype) + call go#list#Window(l:listtype) + echon "vim-go: " | echohl Function | echon "[metalinter] PASS" | echohl None + else + " GoMetaLinter can output one of the two, so we look for both: + " ::[]: () + " ::: () + " This can be defined by the following errorformat: + let errformat = "%f:%l:%c:%t%*[^:]:\ %m,%f:%l::%t%*[^:]:\ %m" + + " Parse and populate our location list + call go#list#ParseFormat(l:listtype, errformat, split(out, "\n"), 'GoMetaLinter') + + let errors = go#list#Get(l:listtype) + call go#list#Window(l:listtype, len(errors)) + + if !a:autosave + call go#list#JumpToFirst(l:listtype) endif + endif endfunction " Golint calls 'golint' on the current directory. Any warnings are populated in " the location list function! go#lint#Golint(...) abort - let bin_path = go#path#CheckBinPath(g:go_golint_bin) - if empty(bin_path) - return - endif + let bin_path = go#path#CheckBinPath(g:go_golint_bin) + if empty(bin_path) + return + endif + let bin_path = go#util#Shellescape(bin_path) - if a:0 == 0 - let goargs = shellescape(expand('%')) - else - let goargs = go#util#Shelljoin(a:000) - endif + if a:0 == 0 + let out = go#util#System(bin_path . " " . go#util#Shellescape(go#package#ImportPath())) + else + let out = go#util#System(bin_path . " " . go#util#Shelljoin(a:000)) + endif - let out = go#util#System(bin_path . " " . goargs) - if empty(out) - echon "vim-go: " | echohl Function | echon "[lint] PASS" | echohl None - return - endif + if empty(out) + echon "vim-go: " | echohl Function | echon "[lint] PASS" | echohl None + return + endif - let l:listtype = "quickfix" - call go#list#Parse(l:listtype, out) - let errors = go#list#Get(l:listtype) - call go#list#Window(l:listtype, len(errors)) - call go#list#JumpToFirst(l:listtype) + let l:listtype = go#list#Type("GoLint") + call go#list#Parse(l:listtype, out) + let errors = go#list#Get(l:listtype) + call go#list#Window(l:listtype, len(errors)) + call go#list#JumpToFirst(l:listtype) endfunction " Vet calls 'go vet' on the current directory. Any warnings are populated in " the location list -function! go#lint#Vet(bang, ...) - call go#cmd#autowrite() - echon "vim-go: " | echohl Identifier | echon "calling vet..." | echohl None - if a:0 == 0 - let out = go#tool#ExecuteInDir('go vet') - else - let out = go#tool#ExecuteInDir('go tool vet ' . go#util#Shelljoin(a:000)) - endif +function! go#lint#Vet(bang, ...) abort + call go#cmd#autowrite() + echon "vim-go: " | echohl Identifier | echon "calling vet..." | echohl None + if a:0 == 0 + let out = go#util#System('go vet ' . go#util#Shellescape(go#package#ImportPath())) + else + let out = go#util#System('go tool vet ' . go#util#Shelljoin(a:000)) + endif - let l:listtype = "quickfix" - if go#util#ShellError() != 0 - let errors = go#tool#ParseErrors(split(out, '\n')) - call go#list#Populate(l:listtype, errors) - call go#list#Window(l:listtype, len(errors)) - if !empty(errors) && !a:bang - call go#list#JumpToFirst(l:listtype) - endif - echon "vim-go: " | echohl ErrorMsg | echon "[vet] FAIL" | echohl None - else - call go#list#Clean(l:listtype) - call go#list#Window(l:listtype) - redraw | echon "vim-go: " | echohl Function | echon "[vet] PASS" | echohl None + let l:listtype = go#list#Type("GoVet") + if go#util#ShellError() != 0 + let errors = go#tool#ParseErrors(split(out, '\n')) + call go#list#Populate(l:listtype, errors, 'Vet') + call go#list#Window(l:listtype, len(errors)) + if !empty(errors) && !a:bang + call go#list#JumpToFirst(l:listtype) endif + echon "vim-go: " | echohl ErrorMsg | echon "[vet] FAIL" | echohl None + else + call go#list#Clean(l:listtype) + call go#list#Window(l:listtype) + redraw | echon "vim-go: " | echohl Function | echon "[vet] PASS" | echohl None + endif endfunction " ErrCheck calls 'errcheck' for the given packages. Any warnings are populated in " the location list function! go#lint#Errcheck(...) abort - if a:0 == 0 - let goargs = go#package#ImportPath(expand('%:p:h')) - if goargs == -1 - echohl Error | echomsg "vim-go: package is not inside GOPATH src" | echohl None - return - endif - else - let goargs = go#util#Shelljoin(a:000) + if a:0 == 0 + let import_path = go#package#ImportPath() + if import_path == -1 + echohl Error | echomsg "vim-go: package is not inside GOPATH src" | echohl None + return + endif + else + let import_path = go#util#Shelljoin(a:000) + endif + + let bin_path = go#path#CheckBinPath(g:go_errcheck_bin) + if empty(bin_path) + return + endif + + echon "vim-go: " | echohl Identifier | echon "errcheck analysing ..." | echohl None + redraw + + let command = go#util#Shellescape(bin_path) . ' -abspath ' . import_path + let out = go#tool#ExecuteInDir(command) + + let l:listtype = go#list#Type("GoErrCheck") + if go#util#ShellError() != 0 + let errformat = "%f:%l:%c:\ %m, %f:%l:%c\ %#%m" + + " Parse and populate our location list + call go#list#ParseFormat(l:listtype, errformat, split(out, "\n"), 'Errcheck') + + let errors = go#list#Get(l:listtype) + if empty(errors) + echohl Error | echomsg "GoErrCheck returned error" | echohl None + echo out + return endif - let bin_path = go#path#CheckBinPath(g:go_errcheck_bin) - if empty(bin_path) - return - endif - - echon "vim-go: " | echohl Identifier | echon "errcheck analysing ..." | echohl None - redraw - - let command = bin_path . ' -abspath ' . goargs - let out = go#tool#ExecuteInDir(command) - - let l:listtype = "quickfix" - if go#util#ShellError() != 0 - let errformat = "%f:%l:%c:\ %m, %f:%l:%c\ %#%m" - - " Parse and populate our location list - call go#list#ParseFormat(l:listtype, errformat, split(out, "\n")) - - let errors = go#list#Get(l:listtype) - - if empty(errors) - echohl Error | echomsg "GoErrCheck returned error" | echohl None - echo out - return - endif - - if !empty(errors) - call go#list#Populate(l:listtype, errors) - call go#list#Window(l:listtype, len(errors)) - if !empty(errors) - call go#list#JumpToFirst(l:listtype) - endif - endif - else - call go#list#Clean(l:listtype) - call go#list#Window(l:listtype) - echon "vim-go: " | echohl Function | echon "[errcheck] PASS" | echohl None + if !empty(errors) + echohl Error | echomsg "GoErrCheck found errors" | echohl None + call go#list#Populate(l:listtype, errors, 'Errcheck') + call go#list#Window(l:listtype, len(errors)) + if !empty(errors) + call go#list#JumpToFirst(l:listtype) + endif endif + else + call go#list#Clean(l:listtype) + call go#list#Window(l:listtype) + echon "vim-go: " | echohl Function | echon "[errcheck] PASS" | echohl None + endif endfunction -" vim:ts=4:sw=4:et +function! go#lint#ToggleMetaLinterAutoSave() abort + if get(g:, "go_metalinter_autosave", 0) + let g:go_metalinter_autosave = 0 + call go#util#EchoProgress("auto metalinter disabled") + return + end + + let g:go_metalinter_autosave = 1 + call go#util#EchoProgress("auto metalinter enabled") +endfunction + +function s:lint_job(args) + let status_dir = expand('%:p:h') + let started_at = reltime() + + call go#statusline#Update(status_dir, { + \ 'desc': "current status", + \ 'type': "gometalinter", + \ 'state': "analysing", + \}) + + " autowrite is not enabled for jobs + call go#cmd#autowrite() + + let l:listtype = go#list#Type("GoMetaLinter") + let l:errformat = '%f:%l:%c:%t%*[^:]:\ %m,%f:%l::%t%*[^:]:\ %m' + + function! s:callback(chan, msg) closure + let old_errorformat = &errorformat + let &errorformat = l:errformat + if l:listtype == "locationlist" + lad a:msg + elseif l:listtype == "quickfix" + caddexpr a:msg + endif + let &errorformat = old_errorformat + + " TODO(jinleileiking): give a configure to jump or not + let l:winnr = winnr() + + let errors = go#list#Get(l:listtype) + call go#list#Window(l:listtype, len(errors)) + + exe l:winnr . "wincmd w" + endfunction + + function! s:exit_cb(job, exitval) closure + let status = { + \ 'desc': 'last status', + \ 'type': "gometaliner", + \ 'state': "finished", + \ } + + if a:exitval + let status.state = "failed" + endif + + let elapsed_time = reltimestr(reltime(started_at)) + " strip whitespace + let elapsed_time = substitute(elapsed_time, '^\s*\(.\{-}\)\s*$', '\1', '') + let status.state .= printf(" (%ss)", elapsed_time) + + call go#statusline#Update(status_dir, status) + + let errors = go#list#Get(l:listtype) + if empty(errors) + call go#list#Window(l:listtype, len(errors)) + elseif has("patch-7.4.2200") + if l:listtype == 'quickfix' + call setqflist([], 'a', {'title': 'GoMetaLinter'}) + else + call setloclist(0, [], 'a', {'title': 'GoMetaLinter'}) + endif + endif + + if get(g:, 'go_echo_command_info', 1) + call go#util#EchoSuccess("linting finished") + endif + endfunction + + let start_options = { + \ 'callback': funcref("s:callback"), + \ 'exit_cb': funcref("s:exit_cb"), + \ } + + call job_start(a:args.cmd, start_options) + + call go#list#Clean(l:listtype) + + if get(g:, 'go_echo_command_info', 1) + call go#util#EchoProgress("linting started ...") + endif +endfunction + +" vim: sw=2 ts=2 et diff --git a/sources_non_forked/vim-go/autoload/go/list.vim b/sources_non_forked/vim-go/autoload/go/list.vim index d91cfb12..78eacf35 100644 --- a/sources_non_forked/vim-go/autoload/go/list.vim +++ b/sources_non_forked/vim-go/autoload/go/list.vim @@ -1,126 +1,167 @@ if !exists("g:go_list_type") - let g:go_list_type = "" + let g:go_list_type = "" +endif + +if !exists("g:go_list_type_commands") + let g:go_list_type_commands = {} endif " Window opens the list with the given height up to 10 lines maximum. -" Otherwise g:go_loclist_height is used. If no or zero height is given it -" closes the window -function! go#list#Window(listtype, ...) - let l:listtype = go#list#Type(a:listtype) - " we don't use lwindow to close the location list as we need also the - " ability to resize the window. So, we are going to use lopen and lclose - " for a better user experience. If the number of errors in a current - " location list increases/decreases, cwindow will not resize when a new - " updated height is passed. lopen in the other hand resizes the screen. - if !a:0 || a:1 == 0 - if l:listtype == "locationlist" - lclose - else - cclose - endif - return +" Otherwise g:go_loclist_height is used. +" +" If no or zero height is given it closes the window by default. +" To prevent this, set g:go_list_autoclose = 0 +function! go#list#Window(listtype, ...) abort + " we don't use lwindow to close the location list as we need also the + " ability to resize the window. So, we are going to use lopen and lclose + " for a better user experience. If the number of errors in a current + " location list increases/decreases, cwindow will not resize when a new + " updated height is passed. lopen in the other hand resizes the screen. + if !a:0 || a:1 == 0 + let autoclose_window = get(g:, 'go_list_autoclose', 1) + if autoclose_window + if a:listtype == "locationlist" + lclose + else + cclose + endif endif + return + endif - let height = get(g:, "go_list_height", 0) - if height == 0 - " prevent creating a large location height for a large set of numbers - if a:1 > 10 - let height = 10 - else - let height = a:1 - endif - endif - - if l:listtype == "locationlist" - exe 'lopen ' . height + let height = get(g:, "go_list_height", 0) + if height == 0 + " prevent creating a large location height for a large set of numbers + if a:1 > 10 + let height = 10 else - exe 'copen ' . height + let height = a:1 endif + endif + + if a:listtype == "locationlist" + exe 'lopen ' . height + else + exe 'copen ' . height + endif endfunction -" Get returns the current list of items from the location list -function! go#list#Get(listtype) - let l:listtype = go#list#Type(a:listtype) - if l:listtype == "locationlist" - return getloclist(0) - else - return getqflist() - endif +" Get returns the current items from the list +function! go#list#Get(listtype) abort + if a:listtype == "locationlist" + return getloclist(0) + else + return getqflist() + endif endfunction -" Populate populate the location list with the given items -function! go#list#Populate(listtype, items) - let l:listtype = go#list#Type(a:listtype) - if l:listtype == "locationlist" - call setloclist(0, a:items, 'r') - else - call setqflist(a:items, 'r') - endif +" Populate populate the list with the given items +function! go#list#Populate(listtype, items, title) abort + if a:listtype == "locationlist" + call setloclist(0, a:items, 'r') + + " The last argument ({what}) is introduced with 7.4.2200: + " https://github.com/vim/vim/commit/d823fa910cca43fec3c31c030ee908a14c272640 + if has("patch-7.4.2200") | call setloclist(0, [], 'a', {'title': a:title}) | endif + else + call setqflist(a:items, 'r') + if has("patch-7.4.2200") | call setqflist([], 'a', {'title': a:title}) | endif + endif endfunction -function! go#list#PopulateWin(winnr, items) - call setloclist(a:winnr, a:items, 'r') -endfunction +" Parse parses the given items based on the specified errorformat and +" populates the list. +function! go#list#ParseFormat(listtype, errformat, items, title) abort + " backup users errorformat, will be restored once we are finished + let old_errorformat = &errorformat -" Parse parses the given items based on the specified errorformat nad -" populates the location list. -function! go#list#ParseFormat(listtype, errformat, items) - let l:listtype = go#list#Type(a:listtype) - " backup users errorformat, will be restored once we are finished - let old_errorformat = &errorformat + " parse and populate the location list + let &errorformat = a:errformat + if a:listtype == "locationlist" + 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 - " parse and populate the location list - let &errorformat = a:errformat - if l:listtype == "locationlist" - lgetexpr a:items - else - cgetexpr a:items - endif - - "restore back - let &errorformat = old_errorformat + "restore back + let &errorformat = old_errorformat endfunction " Parse parses the given items based on the global errorformat and -" populates the location list. -function! go#list#Parse(listtype, items) - let l:listtype = go#list#Type(a:listtype) - if l:listtype == "locationlist" - lgetexpr a:items - else - cgetexpr a:items - endif +" populates the list. +function! go#list#Parse(listtype, items) abort + if a:listtype == "locationlist" + lgetexpr a:items + else + cgetexpr a:items + endif endfunction " JumpToFirst jumps to the first item in the location list -function! go#list#JumpToFirst(listtype) - let l:listtype = go#list#Type(a:listtype) - if l:listtype == "locationlist" - ll 1 - else - cc 1 - endif +function! go#list#JumpToFirst(listtype) abort + if a:listtype == "locationlist" + ll 1 + else + cc 1 + endif endfunction " Clean cleans the location list -function! go#list#Clean(listtype) - let l:listtype = go#list#Type(a:listtype) - if l:listtype == "locationlist" - lex [] - else - cex [] - endif +function! go#list#Clean(listtype) abort + if a:listtype == "locationlist" + lex [] + else + cex [] + endif endfunction -function! go#list#Type(listtype) - if g:go_list_type == "locationlist" - return "locationlist" - elseif g:go_list_type == "quickfix" - return "quickfix" - else - return a:listtype - endif +function! s:listtype(listtype) abort + if g:go_list_type == "locationlist" + return "locationlist" + elseif g:go_list_type == "quickfix" + return "quickfix" + endif + + return a:listtype endfunction -" vim:ts=4:sw=4:et +" s:default_list_type_commands is the defaults that will be used for each of +" the supported commands (see documentation for g:go_list_type_commands). When +" defining a default, quickfix should be used if the command operates on +" multiple files, while locationlist should be used if the command operates on a +" single file or buffer. Keys that begin with an underscore are not supported +" in g:go_list_type_commands. +let s:default_list_type_commands = { + \ "GoBuild": "quickfix", + \ "GoErrCheck": "quickfix", + \ "GoFmt": "locationlist", + \ "GoGenerate": "quickfix", + \ "GoInstall": "quickfix", + \ "GoLint": "quickfix", + \ "GoMetaLinter": "quickfix", + \ "GoModifyTags": "locationlist", + \ "GoRename": "quickfix", + \ "GoRun": "quickfix", + \ "GoTest": "quickfix", + \ "GoVet": "quickfix", + \ "_guru": "locationlist", + \ "_term": "locationlist", + \ "_job": "locationlist", + \ } + +function! go#list#Type(for) abort + let l:listtype = s:listtype(get(s:default_list_type_commands, a:for)) + if l:listtype == "0" + call go#util#EchoError(printf( + \ "unknown list type command value found ('%s'). Please open a bug report in the vim-go repo.", + \ a:for)) + let l:listtype = "quickfix" + endif + + return get(g:go_list_type_commands, a:for, l:listtype) +endfunction + +" vim: sw=2 ts=2 et diff --git a/sources_non_forked/vim-go/autoload/go/package.vim b/sources_non_forked/vim-go/autoload/go/package.vim index 4f756135..9ced9138 100644 --- a/sources_non_forked/vim-go/autoload/go/package.vim +++ b/sources_non_forked/vim-go/autoload/go/package.vim @@ -9,120 +9,124 @@ let s:goos = $GOOS let s:goarch = $GOARCH if len(s:goos) == 0 - if exists('g:golang_goos') - let s:goos = g:golang_goos - elseif has('win32') || has('win64') - let s:goos = 'windows' - elseif has('macunix') - let s:goos = 'darwin' - else - let s:goos = '*' - endif + if exists('g:golang_goos') + let s:goos = g:golang_goos + elseif has('win32') || has('win64') + let s:goos = 'windows' + elseif has('macunix') + let s:goos = 'darwin' + else + let s:goos = '*' + endif endif if len(s:goarch) == 0 - if exists('g:golang_goarch') - let s:goarch = g:golang_goarch - else - let s:goarch = '*' - endif + if exists('g:golang_goarch') + let s:goarch = g:golang_goarch + else + let s:goarch = '*' + endif endif -function! go#package#Paths() - let dirs = [] +function! go#package#Paths() abort + let dirs = [] - if !exists("s:goroot") - if executable('go') - let s:goroot = substitute(go#util#System('go env GOROOT'), '\n', '', 'g') - if go#util#ShellError() != 0 - echomsg '''go env GOROOT'' failed' - endif - else - let s:goroot = $GOROOT - endif - endif - - if len(s:goroot) != 0 && isdirectory(s:goroot) - let dirs += [s:goroot] - endif - - let workspaces = split(go#path#Detect(), go#util#PathListSep()) - if workspaces != [] - let dirs += workspaces - endif - - return dirs -endfunction - -function! go#package#ImportPath(arg) - let path = fnamemodify(resolve(a:arg), ':p') - let dirs = go#package#Paths() - - for dir in dirs - if len(dir) && match(path, dir) == 0 - let workspace = dir - endif - endfor - - if !exists('workspace') - return -1 - endif - - let srcdir = substitute(workspace . '/src/', '//', '/', '') - return substitute(path, srcdir, '', '') -endfunction - -function! go#package#FromPath(arg) - let path = fnamemodify(resolve(a:arg), ':p') - let dirs = go#package#Paths() - - for dir in dirs - if len(dir) && match(path, dir) == 0 - let workspace = dir - endif - endfor - - if !exists('workspace') - return -1 - endif - - if isdirectory(path) - return substitute(path, workspace . 'src/', '', '') + if !exists("s:goroot") + if executable('go') + let s:goroot = go#util#env("goroot") + if go#util#ShellError() != 0 + echomsg '''go env GOROOT'' failed' + endif else - return substitute(substitute(path, workspace . 'src/', '', ''), - \ '/' . fnamemodify(path, ':t'), '', '') + let s:goroot = $GOROOT endif + endif + + if len(s:goroot) != 0 && isdirectory(s:goroot) + let dirs += [s:goroot] + endif + + let workspaces = split(go#path#Detect(), go#util#PathListSep()) + if workspaces != [] + let dirs += workspaces + endif + + return dirs endfunction -function! go#package#CompleteMembers(package, member) - silent! let content = go#util#System('godoc ' . a:package) - if go#util#ShellError() || !len(content) - return [] - endif - let lines = filter(split(content, "\n"),"v:val !~ '^\\s\\+$'") - try - let mx1 = '^\s\+\(\S+\)\s\+=\s\+.*' - let mx2 = '^\%(const\|var\|type\|func\) \([A-Z][^ (]\+\).*' - let candidates = map(filter(copy(lines), 'v:val =~ mx1'), - \ 'substitute(v:val, mx1, "\\1", "")') - \ + map(filter(copy(lines), 'v:val =~ mx2'), - \ 'substitute(v:val, mx2, "\\1", "")') - return filter(candidates, '!stridx(v:val, a:member)') - catch - return [] - endtry +" ImportPath returns the import path in the current directory it was executed +function! go#package#ImportPath() abort + let out = go#tool#ExecuteInDir("go list") + if go#util#ShellError() != 0 + return -1 + endif + + let import_path = split(out, '\n')[0] + + " go list returns '_CURRENTDIRECTORY' if the directory is not inside GOPATH. + " Check it and retun an error if that is the case + if import_path[0] ==# '_' + return -1 + endif + + return import_path endfunction -function! go#package#Complete(ArgLead, CmdLine, CursorPos) - let words = split(a:CmdLine, '\s\+', 1) - " do not complete package members for these commands - let neglect_commands = ["GoImportAs", "GoGuruScope"] +function! go#package#FromPath(arg) abort + let path = fnamemodify(resolve(a:arg), ':p') + let dirs = go#package#Paths() - if len(words) > 2 && index(neglect_commands, words[0]) == -1 - " Complete package members - return go#package#CompleteMembers(words[1], words[2]) + for dir in dirs + if len(dir) && match(path, dir) == 0 + let workspace = dir + break endif + endfor + + if !exists('workspace') + return -1 + endif + + let path = substitute(path, '/*$', '', '') + let workspace = substitute(workspace . '/src/', '/+', '', '') + if isdirectory(path) + return substitute(path, workspace, '', '') + else + return substitute(substitute(path, workspace, '', ''), + \ '/' . fnamemodify(path, ':t'), '', '') + endif +endfunction + +function! go#package#CompleteMembers(package, member) abort + silent! let content = go#util#System('godoc ' . a:package) + if go#util#ShellError() || !len(content) + return [] + endif + let lines = filter(split(content, "\n"),"v:val !~ '^\\s\\+$'") + try + let mx1 = '^\s\+\(\S+\)\s\+=\s\+.*' + let mx2 = '^\%(const\|var\|type\|func\) \([A-Z][^ (]\+\).*' + let candidates = map(filter(copy(lines), 'v:val =~ mx1'), + \ 'substitute(v:val, mx1, "\\1", "")') + \ + map(filter(copy(lines), 'v:val =~ mx2'), + \ 'substitute(v:val, mx2, "\\1", "")') + return filter(candidates, '!stridx(v:val, a:member)') + catch + return [] + endtry +endfunction + +function! go#package#Complete(ArgLead, CmdLine, CursorPos) abort + let words = split(a:CmdLine, '\s\+', 1) + + " do not complete package members for these commands + let neglect_commands = ["GoImportAs", "GoGuruScope"] + + if len(words) > 2 && index(neglect_commands, words[0]) == -1 + " Complete package members + return go#package#CompleteMembers(words[1], words[2]) + endif let dirs = go#package#Paths() @@ -157,4 +161,4 @@ function! go#package#Complete(ArgLead, CmdLine, CursorPos) return sort(keys(ret)) endfunction -" vim:sw=4:et +" vim: sw=2 ts=2 et diff --git a/sources_non_forked/vim-go/autoload/go/path.vim b/sources_non_forked/vim-go/autoload/go/path.vim index 8afe8f16..91141e28 100644 --- a/sources_non_forked/vim-go/autoload/go/path.vim +++ b/sources_non_forked/vim-go/autoload/go/path.vim @@ -8,168 +8,195 @@ let s:initial_go_path = "" " echoes the current GOPATH, if an argument is passed it replaces the current " GOPATH with it. If two double quotes are passed (the empty string in go), " it'll clear the GOPATH and will restore to the initial GOPATH. -function! go#path#GoPath(...) - " we have an argument, replace GOPATH - if len(a:000) - " clears the current manually set GOPATH and restores it to the - " initial GOPATH, which was set when Vim was started. - if len(a:000) == 1 && a:1 == '""' - if !empty(s:initial_go_path) - let $GOPATH = s:initial_go_path - let s:initial_go_path = "" - endif +function! go#path#GoPath(...) abort + " no argument, show GOPATH + if len(a:000) == 0 + echo go#path#Detect() + return + endif - echon "vim-go: " | echohl Function | echon "GOPATH restored to ". $GOPATH | echohl None - return - endif - - echon "vim-go: " | echohl Function | echon "GOPATH changed to ". a:1 | echohl None - let s:initial_go_path = $GOPATH - let $GOPATH = a:1 - return + " we have an argument, replace GOPATH + " clears the current manually set GOPATH and restores it to the + " initial GOPATH, which was set when Vim was started. + if len(a:000) == 1 && a:1 == '""' + if !empty(s:initial_go_path) + let $GOPATH = s:initial_go_path + let s:initial_go_path = "" endif - echo go#path#Detect() + echon "vim-go: " | echohl Function | echon "GOPATH restored to ". $GOPATH | echohl None + return + endif + + echon "vim-go: " | echohl Function | echon "GOPATH changed to ". a:1 | echohl None + let s:initial_go_path = $GOPATH + let $GOPATH = a:1 endfunction -" Default returns the default GOPATH. If there is a single GOPATH it returns -" it. For multiple GOPATHS separated with a the OS specific separator, only -" the first one is returned -function! go#path#Default() - let go_paths = split($GOPATH, go#util#PathListSep()) +" Default returns the default GOPATH. If GOPATH is not set, it uses the +" default GOPATH set starting with Go 1.8. This GOPATH can be retrieved via +" 'go env GOPATH' +function! go#path#Default() abort + if $GOPATH == "" + " use default GOPATH via go env + return go#util#env("gopath") + endif - if len(go_paths) == 1 - return $GOPATH - endif - - return go_paths[0] + return $GOPATH endfunction " HasPath checks whether the given path exists in GOPATH environment variable " or not -function! go#path#HasPath(path) - let go_paths = split($GOPATH, go#util#PathListSep()) - let last_char = strlen(a:path) - 1 +function! go#path#HasPath(path) abort + let go_paths = split(go#path#Default(), go#util#PathListSep()) + let last_char = strlen(a:path) - 1 - " check cases of '/foo/bar/' and '/foo/bar' - if a:path[last_char] == go#util#PathSep() - let withSep = a:path - let noSep = strpart(a:path, 0, last_char) - else - let withSep = a:path . go#util#PathSep() - let noSep = a:path - endif + " check cases of '/foo/bar/' and '/foo/bar' + if a:path[last_char] == go#util#PathSep() + let withSep = a:path + let noSep = strpart(a:path, 0, last_char) + else + let withSep = a:path . go#util#PathSep() + let noSep = a:path + endif - let hasA = index(go_paths, withSep) != -1 - let hasB = index(go_paths, noSep) != -1 - return hasA || hasB + let hasA = index(go_paths, withSep) != -1 + let hasB = index(go_paths, noSep) != -1 + return hasA || hasB endfunction " Detect returns the current GOPATH. If a package manager is used, such as " Godeps, GB, it will modify the GOPATH so those directories take precedence " over the current GOPATH. It also detects diretories whose are outside " GOPATH. -function! go#path#Detect() - let gopath = $GOPATH - - " don't lookup for godeps if autodetect is disabled. - if !get(g:, "go_autodetect_gopath", 1) - return gopath - endif - - let current_dir = fnameescape(expand('%:p:h')) - - " TODO(arslan): this should be changed so folders or files should be - " fetched from a customizable list. The user should define any new package - " management tool by it's own. - - " src folder outside $GOPATH - let src_root = finddir("src", current_dir .";") - if !empty(src_root) - let src_path = fnamemodify(src_root, ':p:h:h') . go#util#PathSep() - - " gb vendor plugin - " (https://github.com/constabulary/gb/tree/master/cmd/gb-vendor) - let gb_vendor_root = src_path . "vendor" . go#util#PathSep() - if isdirectory(gb_vendor_root) && !go#path#HasPath(gb_vendor_root) - let gopath = gb_vendor_root . go#util#PathListSep() . gopath - endif - - if !go#path#HasPath(src_path) - let gopath = src_path . go#util#PathListSep() . gopath - endif - endif - - " Godeps - let godeps_root = finddir("Godeps", current_dir .";") - if !empty(godeps_root) - let godeps_path = join([fnamemodify(godeps_root, ':p:h:h'), "Godeps", "_workspace" ], go#util#PathSep()) - - if !go#path#HasPath(godeps_path) - let gopath = godeps_path . go#util#PathListSep() . gopath - endif - endif +function! go#path#Detect() abort + let gopath = go#path#Default() + " don't lookup for godeps if autodetect is disabled. + if !get(g:, "go_autodetect_gopath", 0) return gopath + endif + + let current_dir = fnameescape(expand('%:p:h')) + + " TODO(arslan): this should be changed so folders or files should be + " fetched from a customizable list. The user should define any new package + " management tool by it's own. + + " src folders outside $GOPATH + let src_roots = finddir("src", current_dir .";", -1) + + " for cases like GOPATH/src/foo/src/bar, pick up GOPATH/src instead of + " GOPATH/src/foo/src + let src_root = "" + if len(src_roots) > 0 + let src_root = src_roots[-1] + endif + + if !empty(src_root) + let src_path = fnamemodify(src_root, ':p:h:h') . go#util#PathSep() + + " gb vendor plugin + " (https://github.com/constabulary/gb/tree/master/cmd/gb-vendor) + let gb_vendor_root = src_path . "vendor" . go#util#PathSep() + if isdirectory(gb_vendor_root) && !go#path#HasPath(gb_vendor_root) + let gopath = gb_vendor_root . go#util#PathListSep() . gopath + endif + + if !go#path#HasPath(src_path) + let gopath = src_path . go#util#PathListSep() . gopath + endif + endif + + " Godeps + let godeps_root = finddir("Godeps", current_dir .";") + if !empty(godeps_root) + let godeps_path = join([fnamemodify(godeps_root, ':p:h:h'), "Godeps", "_workspace" ], go#util#PathSep()) + + if !go#path#HasPath(godeps_path) + let gopath = godeps_path . go#util#PathListSep() . gopath + endif + endif + + " Fix up the case where initial $GOPATH is empty, + " and we end up with a trailing : + let gopath = substitute(gopath, ":$", "", "") + return gopath endfunction " BinPath returns the binary path of installed go tools. -function! go#path#BinPath() - let bin_path = "" +function! go#path#BinPath() abort + let bin_path = "" - " check if our global custom path is set, if not check if $GOBIN is set so - " we can use it, otherwise use $GOPATH + '/bin' - if exists("g:go_bin_path") - let bin_path = g:go_bin_path - elseif $GOBIN != "" - let bin_path = $GOBIN - elseif $GOPATH != "" - let bin_path = expand(go#path#Default() . "/bin/") - else - " could not find anything + " check if our global custom path is set, if not check if $GOBIN is set so + " we can use it, otherwise use default GOPATH + if exists("g:go_bin_path") + let bin_path = g:go_bin_path + elseif $GOBIN != "" + let bin_path = $GOBIN + else + let go_paths = split(go#path#Default(), go#util#PathListSep()) + if len(go_paths) == 0 + return "" "nothing found endif + let bin_path = expand(go_paths[0] . "/bin/") + endif - return bin_path + return bin_path endfunction " CheckBinPath checks whether the given binary exists or not and returns the " path of the binary. It returns an empty string doesn't exists. -function! go#path#CheckBinPath(binpath) - " remove whitespaces if user applied something like 'goimports ' - let binpath = substitute(a:binpath, '^\s*\(.\{-}\)\s*$', '\1', '') - " save off original path - let old_path = $PATH +function! go#path#CheckBinPath(binpath) abort + " remove whitespaces if user applied something like 'goimports ' + let binpath = substitute(a:binpath, '^\s*\(.\{-}\)\s*$', '\1', '') + " save off original path + let old_path = $PATH - " check if we have an appropriate bin_path - let go_bin_path = go#path#BinPath() - if !empty(go_bin_path) - " append our GOBIN and GOPATH paths and be sure they can be found there... - " let us search in our GOBIN and GOPATH paths - let $PATH = go_bin_path . go#util#PathListSep() . $PATH + " check if we have an appropriate bin_path + let go_bin_path = go#path#BinPath() + if !empty(go_bin_path) + " append our GOBIN and GOPATH paths and be sure they can be found there... + " let us search in our GOBIN and GOPATH paths + let $PATH = go_bin_path . go#util#PathListSep() . $PATH + endif + + " if it's in PATH just return it + if executable(binpath) + if exists('*exepath') + let binpath = exepath(binpath) endif - - " if it's in PATH just return it - if executable(binpath) - if v:version == 704 && has('patch235') - let binpath = exepath(binpath) - endif - let $PATH = old_path - return binpath - endif - - " just get the basename - let basename = fnamemodify(binpath, ":t") - if !executable(basename) - echo "vim-go: could not find '" . basename . "'. Run :GoInstallBinaries to fix it." - " restore back! - let $PATH = old_path - return "" - endif - let $PATH = old_path - return go_bin_path . go#util#PathSep() . basename + if go#util#IsUsingCygwinShell() == 1 + return go#path#CygwinPath(binpath) + endif + + return binpath + endif + + " just get the basename + let basename = fnamemodify(binpath, ":t") + if !executable(basename) + call go#util#EchoError(printf("could not find '%s'. Run :GoInstallBinaries to fix it", basename)) + + " restore back! + let $PATH = old_path + return "" + endif + + let $PATH = old_path + + if go#util#IsUsingCygwinShell() == 1 + return go#path#CygwinPath(a:binpath) + endif + + return go_bin_path . go#util#PathSep() . basename endfunction -" vim:ts=4:sw=4:et +function! go#path#CygwinPath(path) + return substitute(a:path, '\\', '/', "g") +endfunction + +" vim: sw=2 ts=2 et diff --git a/sources_non_forked/vim-go/autoload/go/play.vim b/sources_non_forked/vim-go/autoload/go/play.vim index 6a136379..2cf5009d 100644 --- a/sources_non_forked/vim-go/autoload/go/play.vim +++ b/sources_non_forked/vim-go/autoload/go/play.vim @@ -1,94 +1,73 @@ if !exists("g:go_play_open_browser") - let g:go_play_open_browser = 1 + let g:go_play_open_browser = 1 endif -function! go#play#Share(count, line1, line2) - if !executable('curl') - echohl ErrorMsg | echomsg "vim-go: require 'curl' command" | echohl None - return - endif +function! go#play#Share(count, line1, line2) abort + if !executable('curl') + echohl ErrorMsg | echomsg "vim-go: require 'curl' command" | echohl None + return + endif - let content = join(getline(a:line1, a:line2), "\n") - let share_file = tempname() - call writefile(split(content, "\n"), share_file, "b") + let content = join(getline(a:line1, a:line2), "\n") + let share_file = tempname() + call writefile(split(content, "\n"), share_file, "b") - let command = "curl -s -X POST https://play.golang.org/share --data-binary '@".share_file."'" - let snippet_id = go#util#System(command) + let command = "curl -s -X POST https://play.golang.org/share --data-binary '@".share_file."'" + let snippet_id = go#util#System(command) - " we can remove the temp file because it's now posted. - call delete(share_file) + " we can remove the temp file because it's now posted. + call delete(share_file) - if go#util#ShellError() != 0 - echo 'A error has occured. Run this command to see what the problem is:' - echo command - return - endif + if go#util#ShellError() != 0 + echo 'A error has occurred. Run this command to see what the problem is:' + echo command + return + endif - let url = "http://play.golang.org/p/".snippet_id + let url = "http://play.golang.org/p/".snippet_id - " copy to clipboard - if has('unix') && !has('xterm_clipboard') && !has('clipboard') - let @" = url - else - let @+ = url - endif + " copy to clipboard + if has('unix') && !has('xterm_clipboard') && !has('clipboard') + let @" = url + else + let @+ = url + endif - if g:go_play_open_browser != 0 - call go#tool#OpenBrowser(url) - endif + if g:go_play_open_browser != 0 + call go#tool#OpenBrowser(url) + endif - echo "vim-go: snippet uploaded: ".url + echo "vim-go: snippet uploaded: ".url endfunction -function! s:get_visual_content() - let save_regcont = @" - let save_regtype = getregtype('"') - silent! normal! gvy - let content = @" - call setreg('"', save_regcont, save_regtype) - return content +function! s:get_visual_content() abort + let save_regcont = @" + let save_regtype = getregtype('"') + silent! normal! gvy + let content = @" + call setreg('"', save_regcont, save_regtype) + return content endfunction " modified version of " http://stackoverflow.com/questions/1533565/how-to-get-visually-selected-text-in-vimscript " another function that returns the content of visual selection, it's not used " but might be useful in the future -function! s:get_visual_selection() - let [lnum1, col1] = getpos("'<")[1:2] - let [lnum2, col2] = getpos("'>")[1:2] +function! s:get_visual_selection() abort + let [lnum1, col1] = getpos("'<")[1:2] + let [lnum2, col2] = getpos("'>")[1:2] - " check if the the visual mode is used before - if lnum1 == 0 || lnum2 == 0 || col1 == 0 || col2 == 0 - return - endif + " check if the the visual mode is used before + if lnum1 == 0 || lnum2 == 0 || col1 == 0 || col2 == 0 + return + endif - let lines = getline(lnum1, lnum2) - let lines[-1] = lines[-1][: col2 - (&selection == 'inclusive' ? 1 : 2)] - let lines[0] = lines[0][col1 - 1:] - return join(lines, "\n") + let lines = getline(lnum1, lnum2) + let lines[-1] = lines[-1][: col2 - (&selection == 'inclusive' ? 1 : 2)] + let lines[0] = lines[0][col1 - 1:] + return join(lines, "\n") endfunction -" following two functions are from: https://github.com/mattn/gist-vim -" thanks @mattn -function! s:get_browser_command() - let go_play_browser_command = get(g:, 'go_play_browser_command', '') - if go_play_browser_command == '' - if has('win32') || has('win64') - let go_play_browser_command = '!start rundll32 url.dll,FileProtocolHandler %URL%' - elseif has('mac') || has('macunix') || has('gui_macvim') || go#util#System('uname') =~? '^darwin' - let go_play_browser_command = 'open %URL%' - elseif executable('xdg-open') - let go_play_browser_command = 'xdg-open %URL%' - elseif executable('firefox') - let go_play_browser_command = 'firefox %URL% &' - else - let go_play_browser_command = '' - endif - endif - return go_play_browser_command -endfunction - - -" vim:ts=4:sw=4:et +" vim: sw=2 ts=2 et diff --git a/sources_non_forked/vim-go/autoload/go/rename.vim b/sources_non_forked/vim-go/autoload/go/rename.vim index cb92dc9f..b8b97de3 100644 --- a/sources_non_forked/vim-go/autoload/go/rename.vim +++ b/sources_non_forked/vim-go/autoload/go/rename.vim @@ -1,78 +1,166 @@ if !exists("g:go_gorename_bin") - let g:go_gorename_bin = "gorename" + let g:go_gorename_bin = "gorename" endif -if !exists("g:go_gorename_prefill") - let g:go_gorename_prefill = 1 -endif +" Set the default value. A value of "1" is a shortcut for this, for +" compatibility reasons. +function! s:default() abort + if !exists("g:go_gorename_prefill") || g:go_gorename_prefill == 1 + let g:go_gorename_prefill = 'expand("") =~# "^[A-Z]"' . + \ '? go#util#pascalcase(expand(""))' . + \ ': go#util#camelcase(expand(""))' + endif +endfunction +call s:default() -function! go#rename#Rename(bang, ...) - let to = "" - if a:0 == 0 - let from = expand("") - let ask = printf("vim-go: rename '%s' to: ", from) - if g:go_gorename_prefill - let to = input(ask, from) - else - let to = input(ask) - endif - redraw! - if empty(to) - return - endif +function! go#rename#Rename(bang, ...) abort + call s:default() + + let to_identifier = "" + if a:0 == 0 + let ask = printf("vim-go: rename '%s' to: ", expand("")) + if g:go_gorename_prefill != '' + let to_identifier = input(ask, eval(g:go_gorename_prefill)) else - let to = a:1 + let to_identifier = input(ask) endif - - "return with a warning if the bin doesn't exist - let bin_path = go#path#CheckBinPath(g:go_gorename_bin) - if empty(bin_path) - return + redraw! + if empty(to_identifier) + return endif + else + let to_identifier = a:1 + endif - let fname = expand('%:p') - let pos = go#util#OffsetCursor() - let cmd = printf('%s -offset %s -to %s', shellescape(bin_path), shellescape(printf('%s:#%d', fname, pos)), shellescape(to)) + " return with a warning if the bin doesn't exist + let bin_path = go#path#CheckBinPath(g:go_gorename_bin) + if empty(bin_path) + return + endif - let out = go#tool#ExecuteInDir(cmd) + let fname = expand('%:p') + let pos = go#util#OffsetCursor() + let offset = printf('%s:#%d', fname, pos) - " reload all files to reflect the new changes. We explicitly call - " checktime to trigger a reload of all files. See - " http://www.mail-archive.com/vim@vim.org/msg05900.html for more info - " about the autoread bug - let current_autoread = &autoread - set autoread - silent! checktime - let &autoread = current_autoread + " no need to escape for job call + let bin_path = go#util#has_job() ? bin_path : shellescape(bin_path) + let offset = go#util#has_job() ? offset : shellescape(offset) + let to_identifier = go#util#has_job() ? to_identifier : shellescape(to_identifier) - " strip out newline on the end that gorename puts. If we don't remove, it - " will trigger the 'Hit ENTER to continue' prompt - let clean = split(out, '\n') + let cmd = [bin_path, "-offset", offset, "-to", to_identifier] - let l:listtype = "quickfix" - if go#util#ShellError() != 0 - let errors = go#tool#ParseErrors(split(out, '\n')) - call go#list#Populate(l:listtype, errors) - call go#list#Window(l:listtype, len(errors)) - if !empty(errors) && !a:bang - call go#list#JumpToFirst(l:listtype) - elseif empty(errors) - " failed to parse errors, output the original content - call go#util#EchoError(out) - endif - return - else - call go#list#Clean(l:listtype) - call go#list#Window(l:listtype) - redraw | echon "vim-go: " | echohl Function | echon clean[0] | echohl None - endif + " check for any tags + if exists('g:go_build_tags') + let tags = get(g:, 'go_build_tags') + call extend(cmd, ["-tags", tags]) + endif - " refresh the buffer so we can see the new content - " TODO(arslan): also find all other buffers and refresh them too. For this - " we need a way to get the list of changes from gorename upon an success - " change. - silent execute ":e" + if go#util#has_job() + call go#util#EchoProgress(printf("renaming to '%s' ...", to_identifier)) + call s:rename_job({ + \ 'cmd': cmd, + \ 'bang': a:bang, + \}) + return + endif + + let command = join(cmd, " ") + let out = go#tool#ExecuteInDir(command) + + let splitted = split(out, '\n') + call s:parse_errors(go#util#ShellError(), a:bang, splitted) endfunction -" vim:ts=4:sw=4:et -" +function s:rename_job(args) + let messages = [] + function! s:callback(chan, msg) closure + call add(messages, a:msg) + endfunction + + let status_dir = expand('%:p:h') + + function! s:exit_cb(job, exitval) closure + let status = { + \ 'desc': 'last status', + \ 'type': "gorename", + \ 'state': "finished", + \ } + + if a:exitval + let status.state = "failed" + endif + + call go#statusline#Update(status_dir, status) + + call s:parse_errors(a:exitval, a:args.bang, messages) + endfunction + + let start_options = { + \ 'callback': funcref("s:callback"), + \ 'exit_cb': funcref("s:exit_cb"), + \ } + + " modify GOPATH if needed + let old_gopath = $GOPATH + let $GOPATH = go#path#Detect() + + call go#statusline#Update(status_dir, { + \ 'desc': "current status", + \ 'type': "gorename", + \ 'state': "started", + \}) + + call job_start(a:args.cmd, start_options) + + let $GOPATH = old_gopath +endfunction + +function s:parse_errors(exit_val, bang, out) + " reload all files to reflect the new changes. We explicitly call + " checktime to trigger a reload of all files. See + " http://www.mail-archive.com/vim@vim.org/msg05900.html for more info + " about the autoread bug + let current_autoread = &autoread + set autoread + silent! checktime + let &autoread = current_autoread + + let l:listtype = go#list#Type("GoRename") + if a:exit_val != 0 + call go#util#EchoError("FAILED") + let errors = go#tool#ParseErrors(a:out) + call go#list#Populate(l:listtype, errors, 'Rename') + call go#list#Window(l:listtype, len(errors)) + if !empty(errors) && !a:bang + call go#list#JumpToFirst(l:listtype) + elseif empty(errors) + " failed to parse errors, output the original content + call go#util#EchoError(a:out) + endif + + return + endif + + " strip out newline on the end that gorename puts. If we don't remove, it + " will trigger the 'Hit ENTER to continue' prompt + call go#list#Clean(l:listtype) + call go#list#Window(l:listtype) + call go#util#EchoSuccess(a:out[0]) + + " refresh the buffer so we can see the new content + " TODO(arslan): also find all other buffers and refresh them too. For this + " we need a way to get the list of changes from gorename upon an success + " change. + silent execute ":e" +endfunction + +" Commandline completion: original, unexported camelCase, and exported +" CamelCase. +function! go#rename#Complete(lead, cmdline, cursor) + let l:word = expand('') + return filter(uniq(sort( + \ [l:word, go#util#camelcase(l:word), go#util#pascalcase(l:word)])), + \ 'strpart(v:val, 0, len(a:lead)) == a:lead') +endfunction + +" vim: sw=2 ts=2 et diff --git a/sources_non_forked/vim-go/autoload/go/statusline.vim b/sources_non_forked/vim-go/autoload/go/statusline.vim new file mode 100644 index 00000000..6a4f0bf0 --- /dev/null +++ b/sources_non_forked/vim-go/autoload/go/statusline.vim @@ -0,0 +1,112 @@ +" Statusline +"""""""""""""""""""""""""""""""" + +" s:statuses is a global reference to all statuses. It stores the statuses per +" import paths (map[string]status), where each status is unique per its +" type. Current status dict is in form: +" { +" 'desc' : 'Job description', +" 'state' : 'Job state, such as success, failure, etc..', +" 'type' : 'Job type, such as build, test, etc..' +" 'created_at' : 'Time it was created as seconds since 1st Jan 1970' +" } +let s:statuses = {} + +" timer_id for cleaner +let s:timer_id = 0 + +" last_status stores the last generated text per status +let s:last_status = "" + +" Show returns the current status of the job for 20 seconds (configurable). It +" displays it in form of 'desc: [type|state]' if there is any state available, +" if not it returns an empty string. This function should be plugged directly +" into the statusline. +function! go#statusline#Show() abort + " lazy initialiation of the cleaner + if !s:timer_id + " clean every 60 seconds all statuses + let interval = get(g:, 'go_statusline_duration', 60000) + let s:timer_id = timer_start(interval, function('go#statusline#Clear'), {'repeat': -1}) + endif + + " nothing to show + if empty(s:statuses) + return '' + endif + + let status_dir = expand('%:p:h') + + if !has_key(s:statuses, status_dir) + return '' + endif + + let status = s:statuses[status_dir] + if !has_key(status, 'desc') || !has_key(status, 'state') || !has_key(status, 'type') + return '' + endif + + let status_text = printf("[%s|%s]", status.type, status.state) + if empty(status_text) + return '' + endif + + " only update highlight if status has changed. + if status_text != s:last_status + if status.state =~ "success" || status.state =~ "finished" || status.state =~ "pass" + hi goStatusLineColor cterm=bold ctermbg=76 ctermfg=22 + elseif status.state =~ "started" || status.state =~ "analysing" || status.state =~ "compiling" + hi goStatusLineColor cterm=bold ctermbg=208 ctermfg=88 + elseif status.state =~ "failed" + hi goStatusLineColor cterm=bold ctermbg=196 ctermfg=52 + endif + endif + + let s:last_status = status_text + return status_text +endfunction + +" Update updates (adds) the statusline for the given status_dir with the +" given status dict. It overrides any previously set status. +function! go#statusline#Update(status_dir, status) abort + let a:status.created_at = reltime() + let s:statuses[a:status_dir] = a:status + + " force to update the statusline, otherwise the user needs to move the + " cursor + exe 'let &ro = &ro' + + " before we stop the timer, check if we have any previous jobs to be cleaned + " up. Otherwise every job will reset the timer when this function is called + " and thus old jobs will never be cleaned + call go#statusline#Clear(0) + + " also reset the timer, so the user has time to see it in the statusline. + " Setting the timer_id to 0 will trigger a new cleaner routine. + call timer_stop(s:timer_id) + let s:timer_id = 0 +endfunction + +" Clear clears all currently stored statusline data. The timer_id argument is +" just a placeholder so we can pass it to a timer_start() function if needed. +function! go#statusline#Clear(timer_id) abort + for [status_dir, status] in items(s:statuses) + let elapsed_time = reltimestr(reltime(status.created_at)) + " strip whitespace + let elapsed_time = substitute(elapsed_time, '^\s*\(.\{-}\)\s*$', '\1', '') + + if str2nr(elapsed_time) > 10 + call remove(s:statuses, status_dir) + endif + endfor + + if len(s:statuses) == 0 + let s:statuses = {} + endif + + " force to update the statusline, otherwise the user needs to move the + " cursor + exe 'let &ro = &ro' +endfunction + +" vim: sw=2 ts=2 et diff --git a/sources_non_forked/vim-go/autoload/go/tags.vim b/sources_non_forked/vim-go/autoload/go/tags.vim new file mode 100644 index 00000000..af030d21 --- /dev/null +++ b/sources_non_forked/vim-go/autoload/go/tags.vim @@ -0,0 +1,214 @@ +" mapped to :GoAddTags +function! go#tags#Add(start, end, count, ...) abort + let fname = fnamemodify(expand("%"), ':p:gs?\\?/?') + let offset = 0 + if a:count == -1 + let offset = go#util#OffsetCursor() + endif + + let test_mode = 0 + call call("go#tags#run", [a:start, a:end, offset, "add", fname, test_mode] + a:000) +endfunction + +" mapped to :GoRemoveTags +function! go#tags#Remove(start, end, count, ...) abort + let fname = fnamemodify(expand("%"), ':p:gs?\\?/?') + let offset = 0 + if a:count == -1 + let offset = go#util#OffsetCursor() + endif + + let test_mode = 0 + call call("go#tags#run", [a:start, a:end, offset, "remove", fname, test_mode] + a:000) +endfunction + +" run runs gomodifytag. This is an internal test so we can test it +function! go#tags#run(start, end, offset, mode, fname, test_mode, ...) abort + " do not split this into multiple lines, somehow tests fail in that case + let args = {'mode': a:mode,'start': a:start,'end': a:end,'offset': a:offset,'fname': a:fname,'cmd_args': a:000} + + if &modified + let args["modified"] = 1 + endif + + let result = s:create_cmd(args) + if has_key(result, 'err') + call go#util#EchoError(result.err) + return -1 + endif + + let command = join(result.cmd, " ") + + if &modified + let filename = expand("%:p:gs!\\!/!") + let content = join(go#util#GetLines(), "\n") + let in = filename . "\n" . strlen(content) . "\n" . content + let out = go#util#System(command, in) + else + let out = go#util#System(command) + endif + + if go#util#ShellError() != 0 + call go#util#EchoError(out) + return + endif + + if a:test_mode + exe 'edit ' . a:fname + endif + + call s:write_out(out) + + if a:test_mode + exe 'write! ' . a:fname + endif +endfunc + + +" write_out writes back the given output to the current buffer +func s:write_out(out) abort + " not a json output + if a:out[0] !=# '{' + return + endif + + " nothing to do + if empty(a:out) || type(a:out) != type("") + return + endif + + let result = json_decode(a:out) + if type(result) != type({}) + call go#util#EchoError(printf("malformed output from gomodifytags: %s", a:out)) + return + endif + + let lines = result['lines'] + let start_line = result['start'] + let end_line = result['end'] + + let index = 0 + for line in range(start_line, end_line) + call setline(line, lines[index]) + let index += 1 + endfor + + if has_key(result, 'errors') + let l:winnr = winnr() + let l:listtype = go#list#Type("GoModifyTags") + call go#list#ParseFormat(l:listtype, "%f:%l:%c:%m", result['errors'], "gomodifytags") + call go#list#Window(l:listtype, len(result['errors'])) + + "prevent jumping to quickfix list + exe l:winnr . "wincmd w" + endif +endfunc + + +" create_cmd returns a dict that contains the command to execute gomodifytags +func s:create_cmd(args) abort + if !exists("*json_decode") + return {'err': "requires 'json_decode'. Update your Vim/Neovim version."} + endif + + let bin_path = go#path#CheckBinPath('gomodifytags') + if empty(bin_path) + return {'err': "gomodifytags does not exist"} + endif + let bin_path = go#util#Shellescape(bin_path) + + let l:start = a:args.start + let l:end = a:args.end + let l:offset = a:args.offset + let l:mode = a:args.mode + let l:cmd_args = a:args.cmd_args + let l:modifytags_transform = get(g:, 'go_addtags_transform', "snakecase") + + " start constructing the command + let cmd = [bin_path] + call extend(cmd, ["-format", "json"]) + call extend(cmd, ["-file", go#util#Shellescape(a:args.fname)]) + call extend(cmd, ["-transform", l:modifytags_transform]) + + if has_key(a:args, "modified") + call add(cmd, "-modified") + endif + + if l:offset != 0 + call extend(cmd, ["-offset", l:offset]) + else + let range = printf("%d,%d", l:start, l:end) + call extend(cmd, ["-line", range]) + endif + + if l:mode == "add" + let l:tags = [] + let l:options = [] + + if !empty(l:cmd_args) + for item in l:cmd_args + let splitted = split(item, ",") + + " tag only + if len(splitted) == 1 + call add(l:tags, splitted[0]) + endif + + " options only + if len(splitted) == 2 + call add(l:tags, splitted[0]) + call add(l:options, printf("%s=%s", splitted[0], splitted[1])) + endif + endfor + endif + + " construct options + if !empty(l:options) + call extend(cmd, ["-add-options", join(l:options, ",")]) + else + " default value + if empty(l:tags) + let l:tags = ["json"] + endif + + " construct tags + call extend(cmd, ["-add-tags", join(l:tags, ",")]) + endif + elseif l:mode == "remove" + if empty(l:cmd_args) + call add(cmd, "-clear-tags") + else + let l:tags = [] + let l:options = [] + for item in l:cmd_args + let splitted = split(item, ",") + + " tag only + if len(splitted) == 1 + call add(l:tags, splitted[0]) + endif + + " options only + if len(splitted) == 2 + call add(l:options, printf("%s=%s", splitted[0], splitted[1])) + endif + endfor + + " construct tags + if !empty(l:tags) + call extend(cmd, ["-remove-tags", join(l:tags, ",")]) + endif + + " construct options + if !empty(l:options) + call extend(cmd, ["-remove-options", join(l:options, ",")]) + endif + endif + else + return {'err': printf("unknown mode: %s", l:mode)} + endif + + return {'cmd': cmd} +endfunc + +" vim: sw=2 ts=2 et diff --git a/sources_non_forked/vim-go/autoload/go/tags_test.vim b/sources_non_forked/vim-go/autoload/go/tags_test.vim new file mode 100644 index 00000000..7d4d32bc --- /dev/null +++ b/sources_non_forked/vim-go/autoload/go/tags_test.vim @@ -0,0 +1,22 @@ +func! Test_add_tags() abort + try + let l:tmp = gotest#load_fixture('tags/add_all_input.go') + silent call go#tags#run(0, 0, 40, "add", bufname(''), 1) + call gotest#assert_fixture('tags/add_all_golden.go') + finally + call delete(l:tmp, 'rf') + endtry +endfunc + + +func! Test_remove_tags() abort + try + let l:tmp = gotest#load_fixture('tags/remove_all_input.go') + silent call go#tags#run(0, 0, 40, "remove", bufname(''), 1) + call gotest#assert_fixture('tags/remove_all_golden.go') + finally + call delete(l:tmp, 'rf') + endtry +endfunc + +" vim:ts=2:sts=2:sw=2:et diff --git a/sources_non_forked/vim-go/autoload/go/template.vim b/sources_non_forked/vim-go/autoload/go/template.vim new file mode 100644 index 00000000..8fe9d1d5 --- /dev/null +++ b/sources_non_forked/vim-go/autoload/go/template.vim @@ -0,0 +1,50 @@ +let s:current_file = expand("") + +function! go#template#create() abort + let l:go_template_use_pkg = get(g:, 'go_template_use_pkg', 0) + let l:root_dir = fnamemodify(s:current_file, ':h:h:h') + + let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd ' + let dir = getcwd() + execute cd . fnameescape(expand("%:p:h")) + + let l:package_name = go#tool#PackageName() + + " if we can't figure out any package name(no Go files or non Go package + " files) from the directory create the template or use the cwd + " as the name + if l:package_name == -1 && l:go_template_use_pkg != 1 + let l:filename = fnamemodify(expand("%"), ':t') + if l:filename =~ "_test.go$" + let l:template_file = get(g:, 'go_template_test_file', "hello_world_test.go") + else + let l:template_file = get(g:, 'go_template_file', "hello_world.go") + endif + let l:template_path = go#util#Join(l:root_dir, "templates", l:template_file) + silent exe '0r ' . fnameescape(l:template_path) + elseif l:package_name == -1 && l:go_template_use_pkg == 1 + " cwd is now the dir of the package + let l:path = fnamemodify(getcwd(), ':t') + let l:content = printf("package %s", l:path) + call append(0, l:content) + else + let l:content = printf("package %s", l:package_name) + call append(0, l:content) + endif + $delete _ + + execute cd . fnameescape(dir) +endfunction + +function! go#template#ToggleAutoCreate() abort + if get(g:, "go_template_autocreate", 1) + let g:go_template_autocreate = 0 + call go#util#EchoProgress("auto template create disabled") + return + end + + let g:go_template_autocreate = 1 + call go#util#EchoProgress("auto template create enabled") +endfunction + +" vim: sw=2 ts=2 et diff --git a/sources_non_forked/vim-go/autoload/go/term.vim b/sources_non_forked/vim-go/autoload/go/term.vim index f6fe150e..fa232be7 100644 --- a/sources_non_forked/vim-go/autoload/go/term.vim +++ b/sources_non_forked/vim-go/autoload/go/term.vim @@ -1,5 +1,5 @@ if has('nvim') && !exists("g:go_term_mode") - let g:go_term_mode = 'vsplit' + let g:go_term_mode = 'vsplit' endif " s:jobs is a global reference to all jobs started with new() @@ -7,122 +7,129 @@ let s:jobs = {} " 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 -function! go#term#new(bang, cmd) - return go#term#newmode(a:bang, a:cmd, g:go_term_mode) +function! go#term#new(bang, cmd) abort + return go#term#newmode(a:bang, a:cmd, g:go_term_mode) endfunction " new creates a new terminal with the given command and window mode. -function! go#term#newmode(bang, cmd, mode) - let mode = a:mode - if empty(mode) - let mode = g:go_term_mode - endif +function! go#term#newmode(bang, cmd, mode) abort + let mode = a:mode + if empty(mode) + let mode = g:go_term_mode + endif - " modify GOPATH if needed - let old_gopath = $GOPATH - let $GOPATH = go#path#Detect() + " modify GOPATH if needed + let old_gopath = $GOPATH + let $GOPATH = go#path#Detect() - " execute go build in the files directory - let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd ' - let dir = getcwd() + " execute go build in the files directory + let l:winnr = winnr() + let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd ' + let dir = getcwd() - execute cd . fnameescape(expand("%:p:h")) + execute cd . fnameescape(expand("%:p:h")) - execute mode.' __go_term__' + execute mode.' __go_term__' - setlocal filetype=goterm - setlocal bufhidden=delete - setlocal winfixheight - setlocal noswapfile - setlocal nobuflisted + setlocal filetype=goterm + setlocal bufhidden=delete + setlocal winfixheight + setlocal noswapfile + setlocal nobuflisted - let job = { - \ 'stderr' : [], - \ 'stdout' : [], - \ 'bang' : a:bang, - \ 'on_stdout': function('s:on_stdout'), - \ 'on_stderr': function('s:on_stderr'), - \ 'on_exit' : function('s:on_exit'), - \ } + let job = { + \ 'stderr' : [], + \ 'stdout' : [], + \ '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 id = termopen(a:cmd, job) - execute cd . fnameescape(dir) + if l:winnr !=# winnr() + exe l:winnr . "wincmd w" + endif - " restore back GOPATH - let $GOPATH = old_gopath + execute cd . fnameescape(dir) - let job.id = id - startinsert + " restore back GOPATH + let $GOPATH = old_gopath - " resize new term if needed. - let height = get(g:, 'go_term_height', winheight(0)) - let width = get(g:, 'go_term_width', winwidth(0)) + let job.id = id + let job.cmd = a:cmd + startinsert - " we are careful how to resize. for example it's vertical we don't change - " the height. The below command resizes the buffer - if a:mode == "split" - exe 'resize ' . height - elseif a:mode == "vertical" - exe 'vertical resize ' . width - endif + " resize new term if needed. + let height = get(g:, 'go_term_height', winheight(0)) + let width = get(g:, 'go_term_width', winwidth(0)) - " we also need to resize the pty, so there you go... - call jobresize(id, width, height) + " we are careful how to resize. for example it's vertical we don't change + " the height. The below command resizes the buffer + if a:mode == "split" + exe 'resize ' . height + elseif a:mode == "vertical" + exe 'vertical resize ' . width + endif - let s:jobs[id] = job - return id + " we also need to resize the pty, so there you go... + call jobresize(id, width, height) + + let s:jobs[id] = job + stopinsert + return id endfunction -function! s:on_stdout(job_id, data) - if !has_key(s:jobs, a:job_id) - return - endif - let job = s:jobs[a:job_id] +function! s:on_stdout(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.stdout, a:data) + call extend(job.stdout, a:data) endfunction -function! s:on_stderr(job_id, data) - if !has_key(s:jobs, a:job_id) - return - endif - let job = s:jobs[a:job_id] +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) + call extend(job.stderr, a:data) endfunction -function! s:on_exit(job_id, exit_status) - if !has_key(s:jobs, a:job_id) - return - endif - let job = s:jobs[a:job_id] - - let l:listtype = "locationlist" - - " usually there is always output so never branch into this clause - if empty(job.stdout) - call go#list#Clean(l:listtype) - call go#list#Window(l:listtype) - unlet s:jobs[a:job_id] - return - endif - - let errors = go#tool#ParseErrors(job.stdout) - let errors = go#tool#FilterValids(errors) - - if !empty(errors) - " close terminal we don't need it anymore - close - - call go#list#Populate(l:listtype, errors) - call go#list#Window(l:listtype, len(errors)) - if !self.bang - call go#list#JumpToFirst(l:listtype) - endif - unlet s:jobs[a:job_id] - return +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") + + " usually there is always output so never branch into this clause + if empty(job.stdout) + call go#list#Clean(l:listtype) + call go#list#Window(l:listtype) + unlet s:jobs[a:job_id] + return + endif + + let errors = go#tool#ParseErrors(job.stdout) + let errors = go#tool#FilterValids(errors) + + if !empty(errors) + " close terminal we don't need it anymore + close + + call go#list#Populate(l:listtype, errors, job.cmd) + call go#list#Window(l:listtype, len(errors)) + if !self.bang + call go#list#JumpToFirst(l:listtype) endif + unlet s:jobs[a:job_id] + return + endif " tests are passing clean the list and close the list. But we only can " close them from a normal view, so jump back, close the list and then @@ -135,4 +142,4 @@ function! s:on_exit(job_id, exit_status) unlet s:jobs[a:job_id] endfunction -" vim:ts=4:sw=4:et +" vim: sw=2 ts=2 et diff --git a/sources_non_forked/vim-go/autoload/go/test-fixtures/def/jump.go b/sources_non_forked/vim-go/autoload/go/test-fixtures/def/jump.go new file mode 100644 index 00000000..50e8d8d3 --- /dev/null +++ b/sources_non_forked/vim-go/autoload/go/test-fixtures/def/jump.go @@ -0,0 +1,7 @@ +package main + +import "fmt" + +func main() { + fmt.Println("vim-go") +} diff --git a/sources_non_forked/vim-go/autoload/go/test-fixtures/fmt/hello.go b/sources_non_forked/vim-go/autoload/go/test-fixtures/fmt/hello.go new file mode 100644 index 00000000..3be42f6a --- /dev/null +++ b/sources_non_forked/vim-go/autoload/go/test-fixtures/fmt/hello.go @@ -0,0 +1,7 @@ +package main + +import "fmt" + + func main() { +fmt.Println("vim-go") +} diff --git a/sources_non_forked/vim-go/autoload/go/test-fixtures/fmt/hello_golden.go b/sources_non_forked/vim-go/autoload/go/test-fixtures/fmt/hello_golden.go new file mode 100644 index 00000000..50e8d8d3 --- /dev/null +++ b/sources_non_forked/vim-go/autoload/go/test-fixtures/fmt/hello_golden.go @@ -0,0 +1,7 @@ +package main + +import "fmt" + +func main() { + fmt.Println("vim-go") +} diff --git a/sources_non_forked/vim-go/autoload/go/test-fixtures/fmt/imports/goimports.go b/sources_non_forked/vim-go/autoload/go/test-fixtures/fmt/imports/goimports.go new file mode 100644 index 00000000..eec47f82 --- /dev/null +++ b/sources_non_forked/vim-go/autoload/go/test-fixtures/fmt/imports/goimports.go @@ -0,0 +1,13 @@ +package main + +import ( + "fmt" +) + +func Foo(log *logging.TestLogger) { +log.Debug("vim-go") +} + +func main() { + fmt.Println("vim-go") +} diff --git a/sources_non_forked/vim-go/autoload/go/test-fixtures/fmt/imports/goimports_golden.go b/sources_non_forked/vim-go/autoload/go/test-fixtures/fmt/imports/goimports_golden.go new file mode 100644 index 00000000..3719f6b3 --- /dev/null +++ b/sources_non_forked/vim-go/autoload/go/test-fixtures/fmt/imports/goimports_golden.go @@ -0,0 +1,15 @@ +package main + +import ( + "fmt" + + logging "gh.com/gi/foo-logging" +) + +func Foo(log *logging.TestLogger) { + log.Debug("vim-go") +} + +func main() { + fmt.Println("vim-go") +} diff --git a/sources_non_forked/vim-go/autoload/go/test-fixtures/fmt/imports/vendor/gh.com/gi/foo-logging/logger.go b/sources_non_forked/vim-go/autoload/go/test-fixtures/fmt/imports/vendor/gh.com/gi/foo-logging/logger.go new file mode 100644 index 00000000..13960188 --- /dev/null +++ b/sources_non_forked/vim-go/autoload/go/test-fixtures/fmt/imports/vendor/gh.com/gi/foo-logging/logger.go @@ -0,0 +1,12 @@ +package logging + +import "fmt" + +type TestLogger struct { + Value string +} + +func (l *TestLogger) Debug(msg string) { + fmt.Println(msg) + fmt.Println(l.Value) +} diff --git a/sources_non_forked/vim-go/autoload/go/test-fixtures/fmt/src/imports b/sources_non_forked/vim-go/autoload/go/test-fixtures/fmt/src/imports new file mode 100644 index 00000000..60ee2537 --- /dev/null +++ b/sources_non_forked/vim-go/autoload/go/test-fixtures/fmt/src/imports @@ -0,0 +1 @@ +../imports/ \ No newline at end of file diff --git a/sources_non_forked/vim-go/autoload/go/test.vim b/sources_non_forked/vim-go/autoload/go/test.vim new file mode 100644 index 00000000..945a6399 --- /dev/null +++ b/sources_non_forked/vim-go/autoload/go/test.vim @@ -0,0 +1,347 @@ +" Test runs `go test` in the current directory. If compile is true, it'll +" compile the tests instead of running them (useful to catch errors in the +" test files). Any other argument is appendend to the final `go test` command +function! go#test#Test(bang, compile, ...) abort + let args = ["test"] + + " don't run the test, only compile it. Useful to capture and fix errors. + if a:compile + let testfile = tempname() . ".vim-go.test" + call extend(args, ["-c", "-o", testfile]) + endif + + if exists('g:go_build_tags') + let tags = get(g:, 'go_build_tags') + call extend(args, ["-tags", tags]) + endif + + if a:0 + let goargs = a:000 + + " do not expand for coverage mode as we're passing the arg ourself + if a:1 != '-coverprofile' + " expand all wildcards(i.e: '%' to the current file name) + let goargs = map(copy(a:000), "expand(v:val)") + endif + + if !(has('nvim') || go#util#has_job()) + let goargs = go#util#Shelllist(goargs, 1) + endif + + call extend(args, goargs, 1) + else + " only add this if no custom flags are passed + let timeout = get(g:, 'go_test_timeout', '10s') + call add(args, printf("-timeout=%s", timeout)) + endif + + if get(g:, 'go_echo_command_info', 1) + if a:compile + call go#util#EchoProgress("compiling tests ...") + else + call go#util#EchoProgress("testing...") + endif + endif + + if go#util#has_job() + " use vim's job functionality to call it asynchronously + let job_args = { + \ 'cmd': ['go'] + args, + \ 'bang': a:bang, + \ 'winnr': winnr(), + \ 'dir': getcwd(), + \ 'compile_test': a:compile, + \ 'jobdir': fnameescape(expand("%:p:h")), + \ } + + call s:test_job(job_args) + return + elseif has('nvim') + " use nvims's job functionality + if get(g:, 'go_term_enabled', 0) + let id = go#term#new(a:bang, ["go"] + args) + else + let id = go#jobcontrol#Spawn(a:bang, "test", "GoTest", args) + endif + + return id + endif + + call go#cmd#autowrite() + redraw + + let command = "go " . join(args, ' ') + let out = go#tool#ExecuteInDir(command) + + let l:listtype = go#list#Type("GoTest") + + let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd ' + let dir = getcwd() + execute cd fnameescape(expand("%:p:h")) + + if go#util#ShellError() != 0 + let errors = s:parse_errors(split(out, '\n')) + let errors = go#tool#FilterValids(errors) + + call go#list#Populate(l:listtype, errors, command) + call go#list#Window(l:listtype, len(errors)) + if !empty(errors) && !a:bang + call go#list#JumpToFirst(l:listtype) + elseif empty(errors) + " failed to parse errors, output the original content + call go#util#EchoError(out) + endif + call go#util#EchoError("[test] FAIL") + else + call go#list#Clean(l:listtype) + call go#list#Window(l:listtype) + + if a:compile + call go#util#EchoSuccess("[test] SUCCESS") + else + call go#util#EchoSuccess("[test] PASS") + endif + endif + execute cd . fnameescape(dir) +endfunction + +" Testfunc runs a single test that surrounds the current cursor position. +" Arguments are passed to the `go test` command. +function! go#test#Func(bang, ...) abort + " search flags legend (used only) + " 'b' search backward instead of forward + " 'c' accept a match at the cursor position + " 'n' do Not move the cursor + " 'W' don't wrap around the end of the file + " + " for the full list + " :help search + let test = search('func \(Test\|Example\)', "bcnW") + + if test == 0 + echo "vim-go: [test] no test found immediate to cursor" + return + end + + let line = getline(test) + let name = split(split(line, " ")[1], "(")[0] + let args = [a:bang, 0, "-run", name . "$"] + + if a:0 + call extend(args, a:000) + endif + + call call('go#test#Test', args) +endfunction + +function s:test_job(args) abort + let status_dir = expand('%:p:h') + let started_at = reltime() + + let status = { + \ 'desc': 'current status', + \ 'type': "test", + \ 'state': "started", + \ } + + if a:args.compile_test + let status.state = "compiling" + endif + + call go#statusline#Update(status_dir, status) + + " autowrite is not enabled for jobs + call go#cmd#autowrite() + + let messages = [] + function! s:callback(chan, msg) closure + call add(messages, a:msg) + endfunction + + function! s:exit_cb(job, exitval) closure + let status = { + \ 'desc': 'last status', + \ 'type': "test", + \ 'state': "pass", + \ } + + if a:args.compile_test + let status.state = "success" + endif + + if a:exitval + let status.state = "failed" + endif + + if get(g:, 'go_echo_command_info', 1) + if a:exitval == 0 + if a:args.compile_test + call go#util#EchoSuccess("[test] SUCCESS") + else + call go#util#EchoSuccess("[test] PASS") + endif + else + call go#util#EchoError("[test] FAIL") + endif + endif + + let elapsed_time = reltimestr(reltime(started_at)) + " strip whitespace + let elapsed_time = substitute(elapsed_time, '^\s*\(.\{-}\)\s*$', '\1', '') + let status.state .= printf(" (%ss)", elapsed_time) + + call go#statusline#Update(status_dir, status) + + let l:listtype = go#list#Type("GoTest") + if a:exitval == 0 + call go#list#Clean(l:listtype) + call go#list#Window(l:listtype) + return + endif + + call s:show_errors(a:args, a:exitval, messages) + endfunction + + let start_options = { + \ 'callback': funcref("s:callback"), + \ 'exit_cb': funcref("s:exit_cb"), + \ } + + " modify GOPATH if needed + let old_gopath = $GOPATH + let $GOPATH = go#path#Detect() + + " pre start + let dir = getcwd() + let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd ' + let jobdir = fnameescape(expand("%:p:h")) + execute cd . jobdir + + call job_start(a:args.cmd, start_options) + + " post start + execute cd . fnameescape(dir) + let $GOPATH = old_gopath +endfunction + +" show_errors parses the given list of lines of a 'go test' output and returns +" a quickfix compatible list of errors. It's intended to be used only for go +" test output. +function! s:show_errors(args, exit_val, messages) abort + let l:listtype = go#list#Type("GoTest") + + let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd ' + try + execute cd a:args.jobdir + let errors = s:parse_errors(a:messages) + let errors = go#tool#FilterValids(errors) + finally + execute cd . fnameescape(a:args.dir) + endtry + + if !len(errors) + " failed to parse errors, output the original content + call go#util#EchoError(a:messages) + call go#util#EchoError(a:args.dir) + return + endif + + if a:args.winnr == winnr() + call go#list#Populate(l:listtype, errors, join(a:args.cmd)) + call go#list#Window(l:listtype, len(errors)) + if !empty(errors) && !a:args.bang + call go#list#JumpToFirst(l:listtype) + endif + endif +endfunction + +function! s:parse_errors(lines) abort + let errors = [] + let paniced = 0 " signals whether all remaining lines should be included in errors. + let test = '' + + " NOTE(arslan): once we get JSON output everything will be easier :) + " https://github.com/golang/go/issues/2981 + for line in a:lines + let fatalerrors = matchlist(line, '^\(\(fatal error\|panic\):.*\)$') + if !empty(fatalerrors) + let paniced = 1 + call add(errors, {"text": line}) + continue + endif + + if !paniced + " Matches failure lines. These lines always have zero or more leading spaces followed by '-- FAIL: ', following by the test name followed by a space the duration of the test in parentheses + " e.g.: + " '--- FAIL: TestSomething (0.00s)' + let failure = matchlist(line, '^ *--- FAIL: \(.*\) (.*)$') + if get(g:, 'go_test_prepend_name', 0) + if !empty(failure) + let test = failure[1] . ': ' + continue + endif + endif + endif + + let tokens = [] + if paniced + " Matches lines in stacktraces produced by panic. The lines always have + " one or more leading tabs, followed by the path to the file. The file + " path is followed by a colon and then the line number within the file + " where the panic occurred. After that there's a space and hexadecimal + " number. + " + " e.g.: + " '\t/usr/local/go/src/time.go:1313 +0x5d' + let tokens = matchlist(line, '^\t\+\(.\{-}\.go\):\(\d\+\) \(+0x.*\)') + else + " matches lines produced by `go test`. All lines produced by `go test` + " that we're interested in start with zero or more spaces (increasing + " depth of subtests is represented by a similar increase in the number + " of spaces at the start of output lines. Top level tests start with + " zero leading spaces). Lines that indicate test status (e.g. RUN, FAIL, + " PASS) start after the spaces. Lines that indicate test failure + " location or test log message location (e.g. "testing.T".Log) begin + " with the appropriate number of spaces for the current test level, + " followed by a tab, a filename , a colon, the line number, another + " colon, a space, and the failure or log message. + " + " e.g.: + " '\ttime_test.go:30: Likely problem: the time zone files have not been installed.' + let tokens = matchlist(line, '^ *\t\+\(.\{-}\.go\):\(\d\+\):\s*\(.*\)') + endif + + if !empty(tokens) " Check whether the line may refer to a file. + " strip endlines of form ^M + let out = substitute(tokens[3], '\r$', '', '') + let file = fnamemodify(tokens[1], ':p') + + " Preserve the line when the filename is not readable. This is an + " unusual case, but possible; any test that produces lines that match + " the pattern used in the matchlist assigned to tokens is a potential + " source of this condition. For instance, github.com/golang/mock/gomock + " will sometimes produce lines that satisfy this condition. + if !filereadable(file) + call add(errors, {"text": test . line}) + continue + endif + + call add(errors, { + \ "filename" : file, + \ "lnum" : tokens[2], + \ "text" : test . out, + \ }) + elseif paniced + call add(errors, {"text": line}) + elseif !empty(errors) + " Preserve indented lines. This comes up especially with multi-line test output. + if match(line, '^ *\t\+') >= 0 + call add(errors, {"text": line}) + endif + endif + endfor + + return errors +endfunction + +" vim: sw=2 ts=2 et diff --git a/sources_non_forked/vim-go/autoload/go/textobj.vim b/sources_non_forked/vim-go/autoload/go/textobj.vim index ba1d03ee..62a70427 100644 --- a/sources_non_forked/vim-go/autoload/go/textobj.vim +++ b/sources_non_forked/vim-go/autoload/go/textobj.vim @@ -6,6 +6,10 @@ if !exists("g:go_textobj_include_function_doc") let g:go_textobj_include_function_doc = 1 endif +if !exists("g:go_textobj_include_variable") + let g:go_textobj_include_variable = 1 +endif + " ( ) motions " { } motions " s for sentence @@ -13,14 +17,14 @@ endif " < > " t for tag -function! go#textobj#Function(mode) +function! go#textobj#Function(mode) abort let offset = go#util#OffsetCursor() let fname = shellescape(expand("%:p")) if &modified " Write current unsaved buffer to a temp file and use the modified content let l:tmpname = tempname() - call writefile(getline(1, '$'), l:tmpname) + call writefile(go#util#GetLines(), l:tmpname) let fname = l:tmpname endif @@ -60,6 +64,16 @@ function! go#textobj#Function(mode) " want's to include doc comments for function declarations if has_key(info, 'doc') && g:go_textobj_include_function_doc call cursor(info.doc.line, info.doc.col) + elseif info['sig']['name'] == '' && g:go_textobj_include_variable + " one liner anonymous functions + if info.lbrace.line == info.rbrace.line + " jump to first nonblack char, to get the correct column + call cursor(info.lbrace.line, 0 ) + normal! ^ + call cursor(info.func.line, col(".")) + else + call cursor(info.func.line, info.rbrace.col) + endif else call cursor(info.func.line, info.func.col) endif @@ -67,7 +81,7 @@ function! go#textobj#Function(mode) normal! v call cursor(info.rbrace.line, info.rbrace.col) return - endif + endif " rest is inner mode, a:mode == 'i' @@ -84,7 +98,7 @@ function! go#textobj#Function(mode) call cursor(info.rbrace.line-1, 1) endfunction -function! go#textobj#FunctionJump(mode, direction) +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. @@ -107,7 +121,7 @@ function! go#textobj#FunctionJump(mode, direction) if &modified " Write current unsaved buffer to a temp file and use the modified content let l:tmpname = tempname() - call writefile(getline(1, '$'), l:tmpname) + call writefile(go#util#GetLines(), l:tmpname) let fname = l:tmpname endif @@ -177,4 +191,4 @@ function! go#textobj#FunctionJump(mode, direction) keepjumps call cursor(info.func.line, 1) endfunction -" vim:ts=2:sw=2:et +" vim: sw=2 ts=2 et diff --git a/sources_non_forked/vim-go/autoload/go/tool.vim b/sources_non_forked/vim-go/autoload/go/tool.vim index a3c80172..9ea1eac1 100644 --- a/sources_non_forked/vim-go/autoload/go/tool.vim +++ b/sources_non_forked/vim-go/autoload/go/tool.vim @@ -1,134 +1,201 @@ -function! go#tool#Files() - if go#util#IsWin() - let format = '{{range $f := .GoFiles}}{{$.Dir}}\{{$f}}{{printf \"\n\"}}{{end}}{{range $f := .CgoFiles}}{{$.Dir}}\{{$f}}{{printf \"\n\"}}{{end}}' - else - let format = "{{range $f := .GoFiles}}{{$.Dir}}/{{$f}}{{printf \"\\n\"}}{{end}}{{range $f := .CgoFiles}}{{$.Dir}}/{{$f}}{{printf \"\\n\"}}{{end}}" - endif - let command = 'go list -f '.shellescape(format) - let out = go#tool#ExecuteInDir(command) - return split(out, '\n') +" From "go list -h". +function! go#tool#ValidFiles(...) + let l:list = ["GoFiles", "CgoFiles", "IgnoredGoFiles", "CFiles", "CXXFiles", + \ "MFiles", "HFiles", "FFiles", "SFiles", "SwigFiles", "SwigCXXFiles", + \ "SysoFiles", "TestGoFiles", "XTestGoFiles"] + + " Used as completion + if len(a:000) > 0 + let l:list = filter(l:list, 'strpart(v:val, 0, len(a:1)) == a:1') + endif + + return l:list endfunction -function! go#tool#Deps() - if go#util#IsWin() - let format = '{{range $f := .Deps}}{{$f}}{{printf \"\n\"}}{{end}}' - else - let format = "{{range $f := .Deps}}{{$f}}\n{{end}}" +function! go#tool#Files(...) abort + if len(a:000) > 0 + let source_files = a:000 + else + let source_files = ['GoFiles'] + endif + + let combined = '' + for sf in source_files + " Strip dot in case people used ":GoFiles .GoFiles". + let sf = substitute(sf, '^\.', '', '') + + " Make sure the passed options are valid. + if index(go#tool#ValidFiles(), sf) == -1 + echoerr "unknown source file variable: " . sf endif - let command = 'go list -f '.shellescape(format) - let out = go#tool#ExecuteInDir(command) - return split(out, '\n') + + if go#util#IsWin() + let combined .= '{{range $f := .' . sf . '}}{{$.Dir}}\{{$f}}{{printf \"\n\"}}{{end}}{{range $f := .CgoFiles}}{{$.Dir}}\{{$f}}{{printf \"\n\"}}{{end}}' + else + let combined .= "{{range $f := ." . sf . "}}{{$.Dir}}/{{$f}}{{printf \"\\n\"}}{{end}}{{range $f := .CgoFiles}}{{$.Dir}}/{{$f}}{{printf \"\\n\"}}{{end}}" + endif + endfor + + let out = go#tool#ExecuteInDir('go list -f ' . shellescape(combined)) + return split(out, '\n') endfunction -function! go#tool#Imports() - let imports = {} - if go#util#IsWin() - let format = '{{range $f := .Imports}}{{$f}}{{printf \"\n\"}}{{end}}' - else - let format = "{{range $f := .Imports}}{{$f}}{{printf \"\\n\"}}{{end}}" - endif - let command = 'go list -f '.shellescape(format) - let out = go#tool#ExecuteInDir(command) - if go#util#ShellError() != 0 - echo out - return imports - endif - - for package_path in split(out, '\n') - let cmd = "go list -f '{{.Name}}' " . shellescape(package_path) - let package_name = substitute(go#tool#ExecuteInDir(cmd), '\n$', '', '') - let imports[package_name] = package_path - endfor +function! go#tool#Deps() abort + if go#util#IsWin() + let format = '{{range $f := .Deps}}{{$f}}{{printf \"\n\"}}{{end}}' + else + let format = "{{range $f := .Deps}}{{$f}}\n{{end}}" + endif + let command = 'go list -f '.shellescape(format) + let out = go#tool#ExecuteInDir(command) + return split(out, '\n') +endfunction +function! go#tool#Imports() abort + let imports = {} + if go#util#IsWin() + let format = '{{range $f := .Imports}}{{$f}}{{printf \"\n\"}}{{end}}' + else + let format = "{{range $f := .Imports}}{{$f}}{{printf \"\\n\"}}{{end}}" + endif + let command = 'go list -f '.shellescape(format) + let out = go#tool#ExecuteInDir(command) + if go#util#ShellError() != 0 + echo out return imports + endif + + for package_path in split(out, '\n') + let cmd = "go list -f '{{.Name}}' " . shellescape(package_path) + let package_name = substitute(go#tool#ExecuteInDir(cmd), '\n$', '', '') + let imports[package_name] = package_path + endfor + + return imports endfunction -function! go#tool#ParseErrors(lines) - let errors = [] +function! go#tool#Info(auto) abort + let l:mode = get(g:, 'go_info_mode', 'gocode') + if l:mode == 'gocode' + call go#complete#Info(a:auto) + elseif l:mode == 'guru' + call go#guru#DescribeInfo() + else + call go#util#EchoError('go_info_mode value: '. l:mode .' is not valid. Valid values are: [gocode, guru]') + endif +endfunction - for line in a:lines - let fatalerrors = matchlist(line, '^\(fatal error:.*\)$') - let tokens = matchlist(line, '^\s*\(.\{-}\):\(\d\+\):\s*\(.*\)') +function! go#tool#PackageName() abort + let command = "go list -f \"{{.Name}}\"" + let out = go#tool#ExecuteInDir(command) + if go#util#ShellError() != 0 + return -1 + endif - if !empty(fatalerrors) - call add(errors, {"text": fatalerrors[1]}) - elseif !empty(tokens) - " strip endlines of form ^M - let out = substitute(tokens[3], '\r$', '', '') + return split(out, '\n')[0] +endfunction - call add(errors, { - \ "filename" : fnamemodify(tokens[1], ':p'), - \ "lnum" : tokens[2], - \ "text" : out, - \ }) - elseif !empty(errors) - " Preserve indented lines. - " This comes up especially with multi-line test output. - if match(line, '^\s') >= 0 - call add(errors, {"text": line}) - endif - endif - endfor +function! go#tool#ParseErrors(lines) abort + let errors = [] - return errors + for line in a:lines + let fatalerrors = matchlist(line, '^\(fatal error:.*\)$') + let tokens = matchlist(line, '^\s*\(.\{-}\):\(\d\+\):\s*\(.*\)') + + if !empty(fatalerrors) + call add(errors, {"text": fatalerrors[1]}) + elseif !empty(tokens) + " strip endlines of form ^M + let out = substitute(tokens[3], '\r$', '', '') + + call add(errors, { + \ "filename" : fnamemodify(tokens[1], ':p'), + \ "lnum" : tokens[2], + \ "text" : out, + \ }) + elseif !empty(errors) + " Preserve indented lines. + " This comes up especially with multi-line test output. + if match(line, '^\s') >= 0 + call add(errors, {"text": line}) + endif + endif + endfor + + return errors endfunction "FilterValids filters the given items with only items that have a valid "filename. Any non valid filename is filtered out. -function! go#tool#FilterValids(items) - " Remove any nonvalid filename from the location list to avoid opening an - " empty buffer. See https://github.com/fatih/vim-go/issues/287 for - " details. - let filtered = [] - let is_readable = {} +function! go#tool#FilterValids(items) abort + " Remove any nonvalid filename from the location list to avoid opening an + " empty buffer. See https://github.com/fatih/vim-go/issues/287 for + " details. + let filtered = [] + let is_readable = {} - for item in a:items - if has_key(item, 'bufnr') - let filename = bufname(item.bufnr) - elseif has_key(item, 'filename') - let filename = item.filename - else - " nothing to do, add item back to the list - call add(filtered, item) - continue - endif + for item in a:items + if has_key(item, 'bufnr') + let filename = bufname(item.bufnr) + elseif has_key(item, 'filename') + let filename = item.filename + else + " nothing to do, add item back to the list + call add(filtered, item) + continue + endif - if !has_key(is_readable, filename) - let is_readable[filename] = filereadable(filename) - endif - if is_readable[filename] - call add(filtered, item) - endif - endfor + if !has_key(is_readable, filename) + let is_readable[filename] = filereadable(filename) + endif + if is_readable[filename] + call add(filtered, item) + endif + endfor - for k in keys(filter(is_readable, '!v:val')) - echo "vim-go: " | echohl Identifier | echon "[run] Dropped " | echohl Constant | echon '"' . k . '"' - echohl Identifier | echon " from location list (nonvalid filename)" | echohl None - endfor + for k in keys(filter(is_readable, '!v:val')) + echo "vim-go: " | echohl Identifier | echon "[run] Dropped " | echohl Constant | echon '"' . k . '"' + echohl Identifier | echon " from location list (nonvalid filename)" | echohl None + endfor - return filtered + return filtered endfunction function! go#tool#ExecuteInDir(cmd) abort - let old_gopath = $GOPATH - let $GOPATH = go#path#Detect() + " Verify that the directory actually exists. If the directory does not + " exist, then assume that the a:cmd should not be executed. Callers expect + " to check v:shell_error (via go#util#ShellError()), so execute a command + " that will return an error as if a:cmd was run and exited with an error. + " This helps avoid errors when working with plugins that use virtual files + " that don't actually exist on the file system (e.g. vim-fugitive's + " GitDiff). + if !isdirectory(expand("%:p:h")) + let [out, err] = go#util#Exec(["false"]) + return '' + endif - let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd ' - let dir = getcwd() - try - execute cd . fnameescape(expand("%:p:h")) - let out = go#util#System(a:cmd) - finally - execute cd . fnameescape(dir) - endtry + let old_gopath = $GOPATH + let old_goroot = $GOROOT + let $GOPATH = go#path#Detect() + let $GOROOT = go#util#env("goroot") - let $GOPATH = old_gopath - return out + let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd ' + let dir = getcwd() + try + execute cd . fnameescape(expand("%:p:h")) + let out = go#util#System(a:cmd) + finally + execute cd . fnameescape(dir) + endtry + + let $GOROOT = old_goroot + let $GOPATH = old_gopath + return out endfunction " Exists checks whether the given importpath exists or not. It returns 0 if " the importpath exists under GOPATH. -function! go#tool#Exists(importpath) +function! go#tool#Exists(importpath) abort let command = "go list ". a:importpath let out = go#tool#ExecuteInDir(command) @@ -139,20 +206,21 @@ function! go#tool#Exists(importpath) return 0 endfunction - -" following two functions are from: https://github.com/mattn/gist-vim +" following two functions are from: https://github.com/mattn/gist-vim " thanks @mattn -function! s:get_browser_command() +function! s:get_browser_command() abort let go_play_browser_command = get(g:, 'go_play_browser_command', '') if go_play_browser_command == '' if go#util#IsWin() let go_play_browser_command = '!start rundll32 url.dll,FileProtocolHandler %URL%' - elseif has('mac') || has('macunix') || has('gui_macvim') || go#util#System('uname') =~? '^darwin' + elseif go#util#IsMac() let go_play_browser_command = 'open %URL%' elseif executable('xdg-open') let go_play_browser_command = 'xdg-open %URL%' elseif executable('firefox') let go_play_browser_command = 'firefox %URL% &' + elseif executable('chromium') + let go_play_browser_command = 'chromium %URL% &' else let go_play_browser_command = '' endif @@ -160,7 +228,7 @@ function! s:get_browser_command() return go_play_browser_command endfunction -function! go#tool#OpenBrowser(url) +function! go#tool#OpenBrowser(url) abort let cmd = s:get_browser_command() if len(cmd) == 0 redraw @@ -182,4 +250,4 @@ function! go#tool#OpenBrowser(url) endif endfunction -" vim:ts=4:sw=4:et +" vim: sw=2 ts=2 et diff --git a/sources_non_forked/vim-go/autoload/go/tool_test.vim b/sources_non_forked/vim-go/autoload/go/tool_test.vim new file mode 100644 index 00000000..1af3b7b9 --- /dev/null +++ b/sources_non_forked/vim-go/autoload/go/tool_test.vim @@ -0,0 +1,23 @@ +func! Test_ExecuteInDir() abort + let l:tmp = gotest#write_file('a/a.go', ['package a']) + try + let l:out = go#tool#ExecuteInDir("pwd") + call assert_equal(l:tmp . "/src/a\n", l:out) + finally + call delete(l:tmp, 'rf') + endtry +endfunc + +func! Test_ExecuteInDir_nodir() abort + let l:tmp = go#util#tempdir("executeindir") + exe ':e ' . l:tmp . '/new-dir/a' + + try + let l:out = go#tool#ExecuteInDir("pwd") + call assert_equal('', l:out) + finally + call delete(l:tmp, 'rf') + endtry +endfunc + +" vim: sw=2 ts=2 et diff --git a/sources_non_forked/vim-go/autoload/go/ui.vim b/sources_non_forked/vim-go/autoload/go/ui.vim index c4f7abe6..3f612576 100644 --- a/sources_non_forked/vim-go/autoload/go/ui.vim +++ b/sources_non_forked/vim-go/autoload/go/ui.vim @@ -1,113 +1,114 @@ let s:buf_nr = -1 "OpenWindow opens a new scratch window and put's the content into the window -function! go#ui#OpenWindow(title, content, filetype) - " Ensure there's only one return window in this session/tabpage - call go#util#Windo("unlet! w:vim_go_return_window") - " Mark the window we're leaving as such - let w:vim_go_return_window = 1 +function! go#ui#OpenWindow(title, content, filetype) abort + " Ensure there's only one return window in this session/tabpage + call go#util#Windo("unlet! w:vim_go_return_window") + " Mark the window we're leaving as such + let w:vim_go_return_window = 1 - " reuse existing buffer window if it exists otherwise create a new one - if !bufexists(s:buf_nr) - execute 'botright new' - file `="[" . a:title . "]"` - let s:buf_nr = bufnr('%') - elseif bufwinnr(s:buf_nr) == -1 - execute 'botright new' - execute s:buf_nr . 'buffer' - elseif bufwinnr(s:buf_nr) != bufwinnr('%') - execute bufwinnr(s:buf_nr) . 'wincmd w' - endif + " reuse existing buffer window if it exists otherwise create a new one + if !bufexists(s:buf_nr) + execute 'botright new' + file `="[" . a:title . "]"` + let s:buf_nr = bufnr('%') + elseif bufwinnr(s:buf_nr) == -1 + execute 'botright new' + execute s:buf_nr . 'buffer' + elseif bufwinnr(s:buf_nr) != bufwinnr('%') + execute bufwinnr(s:buf_nr) . 'wincmd w' + endif - " Resize window to content length - exe 'resize' . len(a:content) + " Resize window to content length + exe 'resize' . len(a:content) - execute "setlocal filetype=".a:filetype + execute "setlocal filetype=".a:filetype - " some sane default values for a readonly buffer - setlocal bufhidden=delete - setlocal buftype=nofile - setlocal noswapfile - setlocal nobuflisted - setlocal winfixheight - setlocal cursorline " make it easy to distinguish - setlocal nonumber - setlocal norelativenumber - setlocal showbreak="" + " some sane default values for a readonly buffer + setlocal bufhidden=delete + setlocal buftype=nofile + setlocal noswapfile + setlocal nobuflisted + setlocal winfixheight + setlocal cursorline " make it easy to distinguish + setlocal nonumber + setlocal norelativenumber + setlocal showbreak="" - " we need this to purge the buffer content - setlocal modifiable + " we need this to purge the buffer content + setlocal modifiable - "delete everything first from the buffer - %delete _ + "delete everything first from the buffer + %delete _ - " add the content - call append(0, a:content) + " add the content + call append(0, a:content) - " delete last line that comes from the append call - $delete _ + " delete last line that comes from the append call + $delete _ - " set it back to non modifiable - setlocal nomodifiable + " set it back to non modifiable + setlocal nomodifiable - " Remove the '... [New File]' message line from the command line - echon + " Remove the '... [New File]' message line from the command line + echon endfunction -function! go#ui#GetReturnWindow() - for l:wn in range(1, winnr("$")) - if !empty(getwinvar(l:wn, "vim_go_return_window")) - return l:wn - endif - endfor +function! go#ui#GetReturnWindow() abort + for l:wn in range(1, winnr("$")) + if !empty(getwinvar(l:wn, "vim_go_return_window")) + return l:wn + endif + endfor endfunction " CloseWindow closes the current window -function! go#ui#CloseWindow() - " Close any window associated with the ui buffer, if it's there - if bufexists(s:buf_nr) - let ui_window_number = bufwinnr(s:buf_nr) - if ui_window_number != -1 - execute ui_window_number . 'close' - endif +function! go#ui#CloseWindow() abort + " Close any window associated with the ui buffer, if it's there + if bufexists(s:buf_nr) + let ui_window_number = bufwinnr(s:buf_nr) + if ui_window_number != -1 + execute ui_window_number . 'close' endif + endif - "return to original window, if it's there - let l:rw = go#ui#GetReturnWindow() - if !empty(l:rw) - execute l:rw . 'wincmd w' - unlet! w:vim_go_return_window - endif + "return to original window, if it's there + let l:rw = go#ui#GetReturnWindow() + if !empty(l:rw) + execute l:rw . 'wincmd w' + unlet! w:vim_go_return_window + endif endfunction " OpenDefinition parses the current line and jumps to it by openening a new " tab -function! go#ui#OpenDefinition(filter) - let curline = getline('.') +function! go#ui#OpenDefinition(filter) abort + let curline = getline('.') - " don't touch our first line or any blank line - if curline =~ a:filter || curline =~ "^$" - " suppress information about calling this function - echo "" - return - endif + " don't touch our first line or any blank line + if curline =~ a:filter || curline =~ "^$" + " suppress information about calling this function + echo "" + return + endif - " format: 'interface file:lnum:coln' - let mx = '^\(^\S*\)\s*\(.\{-}\):\(\d\+\):\(\d\+\)' + " format: 'interface file:lnum:coln' + let mx = '^\(^\S*\)\s*\(.\{-}\):\(\d\+\):\(\d\+\)' - " parse it now into the list - let tokens = matchlist(curline, mx) + " parse it now into the list + let tokens = matchlist(curline, mx) - " convert to: 'file:lnum:coln' - let expr = tokens[2] . ":" . tokens[3] . ":" . tokens[4] + " convert to: 'file:lnum:coln' + let expr = tokens[2] . ":" . tokens[3] . ":" . tokens[4] - " jump to it in a new tab, we use explicit lgetexpr so we can later change - " the behaviour via settings (like opening in vsplit instead of tab) - lgetexpr expr - tab split - ll 1 + " jump to it in a new tab, we use explicit lgetexpr so we can later change + " the behaviour via settings (like opening in vsplit instead of tab) + lgetexpr expr + tab split + ll 1 - " center the word - norm! zz + " center the word + norm! zz endfunction +" vim: sw=2 ts=2 et diff --git a/sources_non_forked/vim-go/autoload/go/util.vim b/sources_non_forked/vim-go/autoload/go/util.vim index ca0e512c..bf72dadd 100644 --- a/sources_non_forked/vim-go/autoload/go/util.vim +++ b/sources_non_forked/vim-go/autoload/go/util.vim @@ -1,209 +1,398 @@ " PathSep returns the appropriate OS specific path separator. -function! go#util#PathSep() - if go#util#IsWin() - return '\' - endif - return '/' +function! go#util#PathSep() abort + if go#util#IsWin() + return '\' + endif + return '/' endfunction " PathListSep returns the appropriate OS specific path list separator. -function! go#util#PathListSep() - if go#util#IsWin() - return ";" - endif - return ":" +function! go#util#PathListSep() abort + if go#util#IsWin() + return ";" + endif + return ":" endfunction " LineEnding returns the correct line ending, based on the current fileformat -function! go#util#LineEnding() - if &fileformat == 'dos' - return "\r\n" - elseif &fileformat == 'mac' - return "\r" - endif +function! go#util#LineEnding() abort + if &fileformat == 'dos' + return "\r\n" + elseif &fileformat == 'mac' + return "\r" + endif - return "\n" + return "\n" +endfunction + +" Join joins any number of path elements into a single path, adding a +" Separator if necessary and returns the result +function! go#util#Join(...) abort + return join(a:000, go#util#PathSep()) endfunction " IsWin returns 1 if current OS is Windows or 0 otherwise -function! go#util#IsWin() - let win = ['win16', 'win32', 'win64', 'win95'] - for w in win - if (has(w)) - return 1 - endif - endfor - - return 0 -endfunction - -function! go#util#GOARCH() - return substitute(go#util#System('go env GOARCH'), '\n', '', 'g') -endfunction - -function! go#util#GOOS() - return substitute(go#util#System('go env GOOS'), '\n', '', 'g') -endfunction - -function! go#util#GOROOT() - return substitute(go#util#System('go env GOROOT'), '\n', '', 'g') -endfunction - -function! go#util#GOPATH() - return substitute(go#util#System('go env GOPATH'), '\n', '', 'g') -endfunction - -function! go#util#OSARCH() - return go#util#GOOS() . '_' . go#util#GOARCH() -endfunction - - -"Check if has vimproc -function! s:has_vimproc() - if !exists('g:go#use_vimproc') - if go#util#IsWin() - try - call vimproc#version() - let exists_vimproc = 1 - catch - let exists_vimproc = 0 - endtry - else - let exists_vimproc = 0 - endif - - let g:go#use_vimproc = exists_vimproc +function! go#util#IsWin() abort + let win = ['win16', 'win32', 'win64', 'win95'] + for w in win + if (has(w)) + return 1 endif + endfor - return g:go#use_vimproc + return 0 endfunction -if s:has_vimproc() - let s:vim_system = get(g:, 'gocomplete#system_function', 'vimproc#system2') - let s:vim_shell_error = get(g:, 'gocomplete#shell_error_function', 'vimproc#get_last_status') -else - let s:vim_system = get(g:, 'gocomplete#system_function', 'system') - let s:vim_shell_error = '' -endif - -function! go#util#System(str, ...) - return call(s:vim_system, [a:str] + a:000) +" IsMac returns 1 if current OS is macOS or 0 otherwise. +function! go#util#IsMac() abort + return has('mac') || + \ has('macunix') || + \ has('gui_macvim') || + \ go#util#System('uname') =~? '^darwin' endfunction -function! go#util#ShellError() - if empty(s:vim_shell_error) - return v:shell_error + " Checks if using: + " 1) Windows system, + " 2) And has cygpath executable, + " 3) And uses *sh* as 'shell' +function! go#util#IsUsingCygwinShell() + return go#util#IsWin() && executable('cygpath') && &shell =~ '.*sh.*' +endfunction + +function! go#util#has_job() abort + " job was introduced in 7.4.xxx however there are multiple bug fixes and one + " of the latest is 8.0.0087 which is required for a stable async API. + return has('job') && has("patch-8.0.0087") +endfunction + +let s:env_cache = {} + +" env returns the go environment variable for the given key. Where key can be +" GOARCH, GOOS, GOROOT, etc... It caches the result and returns the cached +" version. +function! go#util#env(key) abort + let l:key = tolower(a:key) + if has_key(s:env_cache, l:key) + return s:env_cache[l:key] + endif + + if executable('go') + let l:var = call('go#util#'.l:key, []) + if go#util#ShellError() != 0 + call go#util#EchoError(printf("'go env %s' failed", toupper(l:key))) + return '' endif - return call(s:vim_shell_error, []) + else + let l:var = eval("$".toupper(a:key)) + endif + + let s:env_cache[l:key] = l:var + return l:var endfunction +" goarch returns 'go env GOARCH'. This is an internal function and shouldn't +" be used. Instead use 'go#util#env("goarch")' +function! go#util#goarch() abort + return substitute(go#util#System('go env GOARCH'), '\n', '', 'g') +endfunction + +" goos returns 'go env GOOS'. This is an internal function and shouldn't +" be used. Instead use 'go#util#env("goos")' +function! go#util#goos() abort + return substitute(go#util#System('go env GOOS'), '\n', '', 'g') +endfunction + +" goroot returns 'go env GOROOT'. This is an internal function and shouldn't +" be used. Instead use 'go#util#env("goroot")' +function! go#util#goroot() abort + return substitute(go#util#System('go env GOROOT'), '\n', '', 'g') +endfunction + +" gopath returns 'go env GOPATH'. This is an internal function and shouldn't +" be used. Instead use 'go#util#env("gopath")' +function! go#util#gopath() abort + return substitute(go#util#System('go env GOPATH'), '\n', '', 'g') +endfunction + +function! go#util#osarch() abort + return go#util#env("goos") . '_' . go#util#env("goarch") +endfunction + +" Run a shell command. +" +" It will temporary set the shell to /bin/sh for Unix-like systems if possible, +" so that we always use a standard POSIX-compatible Bourne shell (and not e.g. +" csh, fish, etc.) See #988 and #1276. +function! s:system(cmd, ...) abort + " Preserve original shell and shellredir values + let l:shell = &shell + let l:shellredir = &shellredir + + if !go#util#IsWin() && executable('/bin/sh') + set shell=/bin/sh shellredir=>%s\ 2>&1 + endif + + try + return call('system', [a:cmd] + a:000) + finally + " Restore original values + let &shell = l:shell + let &shellredir = l:shellredir + endtry +endfunction + +" System runs a shell command "str". Every arguments after "str" is passed to +" stdin. +function! go#util#System(str, ...) abort + return call('s:system', [a:str] + a:000) +endfunction + +" Exec runs a shell command "cmd", which must be a list, one argument per item. +" Every list entry will be automatically shell-escaped +" Every other argument is passed to stdin. +function! go#util#Exec(cmd, ...) abort + if len(a:cmd) == 0 + call go#util#EchoError("go#util#Exec() called with empty a:cmd") + return + endif + + " CheckBinPath will show a warning for us. + let l:bin = go#path#CheckBinPath(a:cmd[0]) + if empty(l:bin) + return ["", 1] + endif + + let l:out = call('s:system', [go#util#Shelljoin([l:bin] + a:cmd[1:])] + a:000) + return [l:out, go#util#ShellError()] +endfunction + +function! go#util#ShellError() abort + return v:shell_error +endfunction " StripPath strips the path's last character if it's a path separator. " example: '/foo/bar/' -> '/foo/bar' -function! go#util#StripPathSep(path) - let last_char = strlen(a:path) - 1 - if a:path[last_char] == go#util#PathSep() - return strpart(a:path, 0, last_char) - endif +function! go#util#StripPathSep(path) abort + let last_char = strlen(a:path) - 1 + if a:path[last_char] == go#util#PathSep() + return strpart(a:path, 0, last_char) + endif - return a:path + return a:path endfunction " StripTrailingSlash strips the trailing slash from the given path list. " example: ['/foo/bar/'] -> ['/foo/bar'] -function! go#util#StripTrailingSlash(paths) +function! go#util#StripTrailingSlash(paths) abort return map(copy(a:paths), 'go#util#StripPathSep(v:val)') endfunction " Shelljoin returns a shell-safe string representation of arglist. The " {special} argument of shellescape() may optionally be passed. -function! go#util#Shelljoin(arglist, ...) - try - let ssl_save = &shellslash - set noshellslash - if a:0 - return join(map(copy(a:arglist), 'shellescape(v:val, ' . a:1 . ')'), ' ') - endif +function! go#util#Shelljoin(arglist, ...) abort + try + let ssl_save = &shellslash + set noshellslash + if a:0 + return join(map(copy(a:arglist), 'shellescape(v:val, ' . a:1 . ')'), ' ') + endif - return join(map(copy(a:arglist), 'shellescape(v:val)'), ' ') - finally - let &shellslash = ssl_save - endtry + return join(map(copy(a:arglist), 'shellescape(v:val)'), ' ') + finally + let &shellslash = ssl_save + endtry endfunction fu! go#util#Shellescape(arg) - if s:has_vimproc() - return vimproc#shellescape(a:arg) - endif - try - let ssl_save = &shellslash - set noshellslash - return shellescape(a:arg) - finally - let &shellslash = ssl_save - endtry + try + let ssl_save = &shellslash + set noshellslash + return shellescape(a:arg) + finally + let &shellslash = ssl_save + endtry endf " Shelllist returns a shell-safe representation of the items in the given " arglist. The {special} argument of shellescape() may optionally be passed. -function! go#util#Shelllist(arglist, ...) - try - let ssl_save = &shellslash - set noshellslash - if a:0 - return map(copy(a:arglist), 'shellescape(v:val, ' . a:1 . ')') - endif - return map(copy(a:arglist), 'shellescape(v:val)') - finally - let &shellslash = ssl_save - endtry +function! go#util#Shelllist(arglist, ...) abort + try + let ssl_save = &shellslash + set noshellslash + if a:0 + return map(copy(a:arglist), 'shellescape(v:val, ' . a:1 . ')') + endif + return map(copy(a:arglist), 'shellescape(v:val)') + finally + let &shellslash = ssl_save + endtry endfunction " Returns the byte offset for line and column -function! go#util#Offset(line, col) - if &encoding != 'utf-8' - let sep = go#util#LineEnding() - let buf = a:line == 1 ? '' : (join(getline(1, a:line-1), sep) . sep) - let buf .= a:col == 1 ? '' : getline('.')[:a:col-2] - return len(iconv(buf, &encoding, 'utf-8')) - endif - return line2byte(a:line) + (a:col-2) +function! go#util#Offset(line, col) abort + if &encoding != 'utf-8' + let sep = go#util#LineEnding() + let buf = a:line == 1 ? '' : (join(getline(1, a:line-1), sep) . sep) + let buf .= a:col == 1 ? '' : getline('.')[:a:col-2] + return len(iconv(buf, &encoding, 'utf-8')) + endif + return line2byte(a:line) + (a:col-2) endfunction " " Returns the byte offset for the cursor -function! go#util#OffsetCursor() - return go#util#Offset(line('.'), col('.')) +function! go#util#OffsetCursor() abort + return go#util#Offset(line('.'), col('.')) endfunction " Windo is like the built-in :windo, only it returns to the window the command " was issued from -function! go#util#Windo(command) - let s:currentWindow = winnr() - try - execute "windo " . a:command - finally - execute s:currentWindow. "wincmd w" - unlet s:currentWindow - endtry +function! go#util#Windo(command) abort + let s:currentWindow = winnr() + try + execute "windo " . a:command + finally + execute s:currentWindow. "wincmd w" + unlet s:currentWindow + endtry endfunction -" TODO(arslan): I couldn't parameterize the highlight types. Check if we can -" simplify the following functions +" snippetcase converts the given word to given preferred snippet setting type +" case. +function! go#util#snippetcase(word) abort + let l:snippet_case = get(g:, 'go_addtags_transform', "snakecase") + if l:snippet_case == "snakecase" + return go#util#snakecase(a:word) + elseif l:snippet_case == "camelcase" + return go#util#camelcase(a:word) + else + return a:word " do nothing + endif +endfunction + +" snakecase converts a string to snake case. i.e: FooBar -> foo_bar +" Copied from tpope/vim-abolish +function! go#util#snakecase(word) abort + let word = substitute(a:word, '::', '/', 'g') + let word = substitute(word, '\(\u\+\)\(\u\l\)', '\1_\2', 'g') + let word = substitute(word, '\(\l\|\d\)\(\u\)', '\1_\2', 'g') + let word = substitute(word, '[.-]', '_', 'g') + let word = tolower(word) + return word +endfunction + +" camelcase converts a string to camel case. e.g. FooBar or foo_bar will become +" fooBar. +" Copied from tpope/vim-abolish. +function! go#util#camelcase(word) abort + let word = substitute(a:word, '-', '_', 'g') + if word !~# '_' && word =~# '\l' + return substitute(word, '^.', '\l&', '') + else + return substitute(word, '\C\(_\)\=\(.\)', '\=submatch(1)==""?tolower(submatch(2)) : toupper(submatch(2))','g') + endif +endfunction + +" pascalcase converts a string to 'PascalCase'. e.g. fooBar or foo_bar will +" become FooBar. +function! go#util#pascalcase(word) abort + let word = go#util#camelcase(a:word) + return toupper(word[0]) . word[1:] +endfunction + +" Echo a message to the screen and highlight it with the group in a:hi. +" +" The message can be a list or string; every line with be :echomsg'd separately. +function! s:echo(msg, hi) + let l:msg = [] + if type(a:msg) != type([]) + let l:msg = split(a:msg, "\n") + else + let l:msg = a:msg + endif + + " Tabs display as ^I or <09>, so manually expand them. + let l:msg = map(l:msg, 'substitute(v:val, "\t", " ", "")') + + exe 'echohl ' . a:hi + for line in l:msg + echom "vim-go: " . line + endfor + echohl None +endfunction function! go#util#EchoSuccess(msg) - redraws! | echon "vim-go: " | echohl Function | echon a:msg | echohl None + call s:echo(a:msg, 'Function') endfunction - function! go#util#EchoError(msg) - redraws! | echon "vim-go: " | echohl ErrorMsg | echon a:msg | echohl None + call s:echo(a:msg, 'ErrorMsg') endfunction - function! go#util#EchoWarning(msg) - redraws! | echon "vim-go: " | echohl WarningMsg | echon a:msg | echohl None + call s:echo(a:msg, 'WarningMsg') endfunction - function! go#util#EchoProgress(msg) - redraws! | echon "vim-go: " | echohl Identifier | echon a:msg | echohl None + call s:echo(a:msg, 'Identifier') +endfunction +function! go#util#EchoInfo(msg) + call s:echo(a:msg, 'Debug') endfunction -" vim:ts=4:sw=4:et +" Get all lines in the buffer as a a list. +function! go#util#GetLines() + let buf = getline(1, '$') + if &encoding != 'utf-8' + let buf = map(buf, 'iconv(v:val, &encoding, "utf-8")') + endif + if &l:fileformat == 'dos' + " XXX: line2byte() depend on 'fileformat' option. + " so if fileformat is 'dos', 'buf' must include '\r'. + let buf = map(buf, 'v:val."\r"') + endif + return buf +endfunction + +" Convert the current buffer to the "archive" format of +" golang.org/x/tools/go/buildutil: +" https://godoc.org/golang.org/x/tools/go/buildutil#ParseOverlayArchive +" +" > The archive consists of a series of files. Each file consists of a name, a +" > decimal file size and the file contents, separated by newlinews. No newline +" > follows after the file contents. +function! go#util#archive() + let l:buffer = join(go#util#GetLines(), "\n") + return expand("%:p:gs!\\!/!") . "\n" . strlen(l:buffer) . "\n" . l:buffer +endfunction + + +" Make a named temporary directory which starts with "prefix". +" +" Unfortunately Vim's tempname() is not portable enough across various systems; +" see: https://github.com/mattn/vim-go/pull/3#discussion_r138084911 +function! go#util#tempdir(prefix) abort + " See :help tempfile + if go#util#IsWin() + let l:dirs = [$TMP, $TEMP, 'c:\tmp', 'c:\temp'] + else + let l:dirs = [$TMPDIR, '/tmp', './', $HOME] + endif + + let l:dir = '' + for l:d in dirs + if !empty(l:d) && filewritable(l:d) == 2 + let l:dir = l:d + break + endif + endfor + + if l:dir == '' + echoerr 'Unable to find directory to store temporary directory in' + return + endif + + " Not great randomness, but "good enough" for our purpose here. + let l:rnd = sha256(printf('%s%s', localtime(), fnamemodify(bufname(''), ":p"))) + let l:tmp = printf("%s/%s%s", l:dir, a:prefix, l:rnd) + call mkdir(l:tmp, 'p', 0700) + return l:tmp +endfunction + +" vim: sw=2 ts=2 et diff --git a/sources_non_forked/vim-go/autoload/gotest.vim b/sources_non_forked/vim-go/autoload/gotest.vim new file mode 100644 index 00000000..5a4df1f2 --- /dev/null +++ b/sources_non_forked/vim-go/autoload/gotest.vim @@ -0,0 +1,106 @@ +" Write a Go file to a temporary directory and append this directory to $GOPATH. +" +" The file will written to a:path, which is relative to the temporary directory, +" and this file will be loaded as the current buffer. +" +" The cursor will be placed on the character before any 0x1f byte. +" +" The full path to the created directory is returned, it is the caller's +" responsibility to clean that up! +fun! gotest#write_file(path, contents) abort + let l:dir = go#util#tempdir("vim-go-test/testrun/") + let $GOPATH .= ':' . l:dir + let l:full_path = l:dir . '/src/' . a:path + + call mkdir(fnamemodify(l:full_path, ':h'), 'p') + call writefile(a:contents, l:full_path) + exe 'cd ' . l:dir . '/src' + silent exe 'e ' . a:path + + " Set cursor. + let l:lnum = 1 + for l:line in a:contents + let l:m = match(l:line, '') + if l:m > -1 + call setpos('.', [0, l:lnum, l:m, 0]) + call setline('.', substitute(getline('.'), '', '', '')) + break + endif + + let l:lnum += 1 + endfor + + return l:dir +endfun + +" Load a fixture file from test-fixtures. +" +" The file will be copied to a new GOPATH-compliant temporary directory and +" loaded as the current buffer. +fun! gotest#load_fixture(path) abort + let l:dir = go#util#tempdir("vim-go-test/testrun/") + let $GOPATH .= ':' . l:dir + let l:full_path = l:dir . '/src/' . a:path + + call mkdir(fnamemodify(l:full_path, ':h'), 'p') + exe 'cd ' . l:dir . '/src' + silent exe 'noautocmd e ' . a:path + silent exe printf('read %s/test-fixtures/%s', g:vim_go_root, a:path) + silent noautocmd w! + + return l:dir +endfun + +" Diff the contents of the current buffer to a:want, which should be a list. +" If a:skipHeader is true we won't bother with the package and import +" declarations; so e.g.: +" +" let l:diff = s:diff_buffer(1, ['_ = mail.Address{}']) +" +" will pass, whereas otherwise you'd have to: +" +" let l:diff = s:diff_buffer(0, ['package main', 'import "net/mail", '_ = mail.Address{}']) +fun! gotest#assert_buffer(skipHeader, want) abort + let l:buffer = go#util#GetLines() + + if a:skipHeader + for l:lnum in range(0, len(l:buffer) - 1) + " Bit rudimentary, but works reasonably well. + if match(l:buffer[l:lnum], '^\v(func|var|const|import \(|\))') > -1 + " vint bug: https://github.com/Kuniwak/vint/issues/179 + " vint: -ProhibitUsingUndeclaredVariable + let l:buffer = l:buffer[l:lnum:len(l:buffer)] + break + endif + endfor + endif + + " Using ' is often easier so we don't have to escape ". + let l:want = map(a:want, 'substitute(v:val, "\\\\t", "\t", "")') + + let l:tmp = go#util#tempdir('assert_buffer') + try + call writefile(l:buffer, l:tmp . '/have') + call writefile(l:want, l:tmp . '/want') + call go#fmt#run('gofmt', l:tmp . '/have', l:tmp . '/have') + call go#fmt#run('gofmt', l:tmp . '/want', l:tmp . '/want') + let [l:out, l:err] = go#util#Exec(["diff", "-u", l:tmp . '/have', l:tmp . '/want']) + finally + call delete(l:tmp . '/have') + call delete(l:tmp . '/want') + call delete(l:tmp, 'd') + endtry + + if l:err || l:out != '' + let v:errors = extend(v:errors, split(l:out, "\n")) + endif +endfun + +" Diff the contents of the current buffer to the fixture file in a:path. +fun! gotest#assert_fixture(path) abort + let l:want = readfile(printf('%s/test-fixtures/%s', g:vim_go_root, a:path)) + call gotest#assert_buffer(0, l:want) +endfun + + +" vim: sw=2 ts=2 et diff --git a/sources_non_forked/vim-go/autoload/unite/sources/decls.vim b/sources_non_forked/vim-go/autoload/unite/sources/decls.vim new file mode 100644 index 00000000..b4d5da80 --- /dev/null +++ b/sources_non_forked/vim-go/autoload/unite/sources/decls.vim @@ -0,0 +1,70 @@ +let s:save_cpo = &cpoptions +set cpoptions&vim + +let s:source = { + \ 'name': 'decls', + \ 'description': 'GoDecls implementation for unite', + \ 'syntax': 'uniteSource__Decls', + \ 'action_table': {}, + \ 'hooks': {}, + \ } + +function! unite#sources#decls#define() + return s:source +endfunction + +function! s:source.gather_candidates(args, context) abort + let l:bin_path = go#path#CheckBinPath('motion') + if empty(l:bin_path) + return [] + endif + + let l:path = expand(get(a:args, 0, '%:p:h')) + if isdirectory(l:path) + let l:mode = 'dir' + elseif filereadable(l:path) + let l:mode = 'file' + else + return [] + endif + + let l:include = get(g:, 'go_decls_includes', 'func,type') + let l:command = printf('%s -format vim -mode decls -include %s -%s %s', l:bin_path, l:include, l:mode, shellescape(l:path)) + let l:candidates = [] + try + let l:result = eval(unite#util#system(l:command)) + let l:candidates = get(l:result, 'decls', []) + catch + call unite#print_source_error(['command returned invalid response.', v:exception], s:source.name) + endtry + + return map(l:candidates, "{ + \ 'word': printf('%s :%d :%s', fnamemodify(v:val.filename, ':~:.'), v:val.line, v:val.full), + \ 'kind': 'jump_list', + \ 'action__path': v:val.filename, + \ 'action__line': v:val.line, + \ 'action__col': v:val.col, + \ }") +endfunction + +function! s:source.hooks.on_syntax(args, context) abort + syntax match uniteSource__Decls_Filepath /[^:]*\ze:/ contained containedin=uniteSource__Decls + syntax match uniteSource__Decls_Line /\d\+\ze :/ contained containedin=uniteSource__Decls + syntax match uniteSource__Decls_WholeFunction /\vfunc %(\([^)]+\) )?[^(]+/ contained containedin=uniteSource__Decls + syntax match uniteSource__Decls_Function /\S\+\ze(/ contained containedin=uniteSource__Decls_WholeFunction + syntax match uniteSource__Decls_WholeType /type \S\+/ contained containedin=uniteSource__Decls + syntax match uniteSource__Decls_Type /\v( )@<=\S+/ contained containedin=uniteSource__Decls_WholeType + highlight default link uniteSource__Decls_Filepath Comment + highlight default link uniteSource__Decls_Line LineNr + highlight default link uniteSource__Decls_Function Function + highlight default link uniteSource__Decls_Type Type + + syntax match uniteSource__Decls_Separator /:/ contained containedin=uniteSource__Decls conceal + syntax match uniteSource__Decls_SeparatorFunction /func / contained containedin=uniteSource__Decls_WholeFunction conceal + syntax match uniteSource__Decls_SeparatorType /type / contained containedin=uniteSource__Decls_WholeType conceal +endfunction + +let &cpoptions = s:save_cpo +unlet s:save_cpo + +" vim: sw=2 ts=2 et diff --git a/sources_non_forked/vim-go/compiler/go.vim b/sources_non_forked/vim-go/compiler/go.vim index 7b5a0255..523cb282 100644 --- a/sources_non_forked/vim-go/compiler/go.vim +++ b/sources_non_forked/vim-go/compiler/go.vim @@ -4,10 +4,10 @@ " " compiler/go.vim: Vim compiler file for Go. -if exists("current_compiler") +if exists("g:current_compiler") finish endif -let current_compiler = "go" +let g:current_compiler = "go" if exists(":CompilerSet") != 2 command -nargs=* CompilerSet setlocal @@ -16,9 +16,9 @@ endif let s:save_cpo = &cpo set cpo-=C if filereadable("makefile") || filereadable("Makefile") - CompilerSet makeprg=make + CompilerSet makeprg=make else - CompilerSet makeprg=go\ build + CompilerSet makeprg=go\ build endif " Define the patterns that will be recognized by QuickFix when parsing the @@ -38,4 +38,4 @@ CompilerSet errorformat+=%-G%.%# " All lines not matching a let &cpo = s:save_cpo unlet s:save_cpo -" vim:ts=4:sw=4:et +" vim: sw=2 ts=2 et diff --git a/sources_non_forked/vim-go/doc/vim-go.txt b/sources_non_forked/vim-go/doc/vim-go.txt index 15279445..616bb1c3 100644 --- a/sources_non_forked/vim-go/doc/vim-go.txt +++ b/sources_non_forked/vim-go/doc/vim-go.txt @@ -1,18 +1,18 @@ *vim-go.txt* Go development plugin *vim-go* -=============================================================================== -# # -# ## ## #### ## ## ###### ####### # -# ## ## ## ### ### ## ## ## ## # -# ## ## ## #### #### ## ## ## # -# ## ## ## ## ### ## ####### ## #### ## ## # -# ## ## ## ## ## ## ## ## ## # -# ## ## ## ## ## ## ## ## ## # -# ### #### ## ## ###### ####### # -# # -=============================================================================== -CONTENTS *go-contents* +============================================================================== +# # +# ## ## #### ## ## ###### ####### # +# ## ## ## ### ### ## ## ## ## # +# ## ## ## #### #### ## ## ## # +# ## ## ## ## ### ## ####### ## #### ## ## # +# ## ## ## ## ## ## ## ## ## # +# ## ## ## ## ## ## ## ## ## # +# ### #### ## ## ###### ####### # +# # +============================================================================== +CONTENTS *go-contents* 1. Intro........................................|go-intro| 2. Install......................................|go-install| @@ -21,120 +21,146 @@ CONTENTS *go-contents* 5. Text Objects.................................|go-text-objects| 6. Functions....................................|go-functions| 7. Settings.....................................|go-settings| - 8. Troubleshooting..............................|go-troubleshooting| - 9. Credits......................................|go-credits| + 8. Syntax highlighting..........................|go-syntax| + 9. FAQ/Troubleshooting..........................|go-troubleshooting| + 10. Development..................................|go-development| + 11. Donation.....................................|go-donation| + 12. Credits......................................|go-credits| -=============================================================================== -INTRO *go-intro* +============================================================================== +INTRO *go-intro* -Go (golang) support for Vim. vim-go installs automatically all necessary -binaries for providing seamless Vim integration. It comes with pre-defined -sensible settings (like auto gofmt on save), has autocomplete, snippet -support, improved syntax highlighting, go toolchain commands, etc... It's -highly customizable and each individual feature can be disabled/enabled -easily. +Go (golang) support for Vim. vim-go comes with sensible predefined settings +(e.g. automatic `gofmt` on save), has autocomplete, snippet support, improved +syntax highlighting, go toolchain commands, etc. It is highly customizable, +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. - * Improved Syntax highlighting with items such as Functions, Operators, Methods. - * Auto completion support via `gocode` - * Better `gofmt` on save, which keeps cursor position and doesn't break your undo - history - * Go to symbol/declaration with `:GoDef` - * Look up documentation with `:GoDoc` inside Vim or open it in browser - * Automatically import packages via `:GoImport` or plug it into autosave - * Compile your package with `:GoBuild`, install it with `:GoInstall` or test - them with `:GoTest` (also supports running single tests via `:GoTestFunc`) - * Quickly execute your current file/files with `:GoRun` - * Automatic `GOPATH` detection based on the directory structure (i.e. `gb` - projects, `godep` vendored projects) - * Change or display `GOPATH` with `:GoPath` - * Create a coverage profile and display annotated source code in to see - which functions are covered with `:GoCoverage` - * Call `gometalinter` with `:GoMetaLinter`, which invokes all possible linters - (golint, vet, errcheck, deadcode, etc..) and shows the warnings/errors - * Lint your code with `:GoLint` - * Run your code through `:GoVet` to catch static errors - * Advanced source analysis tools utilizing guru, such as `:GoImplements`, - `:GoCallees`, and `:GoReferrers` - * Precise type-safe renaming of identifiers with `:GoRename` - * List all source files and dependencies - * Unchecked error checking with `:GoErrCheck` - * Integrated and improved snippets, supporting `ultisnips` or `neosnippet` - * Share your current code to [play.golang.org](http://play.golang.org) with `:GoPlay` - * On-the-fly type information about the word under the cursor. Plug it into - your custom vim function. - * Go asm formatting on save - * Tagbar support to show tags of the source code in a sidebar with `gotags` - * Custom vim text objects such as `a function` or `inner function` - * A async launcher for the go command is implemented for neovim, fully async + * Compile your package with |:GoBuild|, install it with |:GoInstall| or + test it with |:GoTest|. Run a single tests with |:GoTestFunc|). + * Quickly execute your current file(s) with |:GoRun|. + * Improved syntax highlighting and folding. + * Completion support via `gocode`. + * `gofmt` or `goimports` on save keeps the cursor position and undo history. + * Go to symbol/declaration with |:GoDef|. + * Look up documentation with |:GoDoc| or |:GoDocBrowser|. + * Easily import packages via |:GoImport|, remove them via |:GoDrop|. + * Automatic `GOPATH` detection which works with `gb` and `godep`. Change or + display `GOPATH` with |:GoPath|. + * See which code is covered by tests with |:GoCoverage|. + * Add or remove tags on struct fields with |:GoAddTags| and |:GoRemoveTags|. + * Call `gometalinter` with |:GoMetaLinter| to invoke all possible linters + (`golint`, `vet`, `errcheck`, `deadcode`, etc.) and put the result in the + quickfix or location list. + * Lint your code with |:GoLint|, run your code through |:GoVet| to catch + static errors, or make sure errors are checked with |:GoErrCheck|. + * Advanced source analysis tools utilizing `guru`, such as |:GoImplements|, + |:GoCallees|, and |:GoReferrers|. + * Precise type-safe renaming of identifiers with |:GoRename|. + * Integrated and improved snippets, supporting `ultisnips` or `neosnippet`. + * Share your current code to play.golang.org with |:GoPlay|. + * On-the-fly information about the word under the cursor. Plug it into your + custom Vim function. + * Text objects such as "a function" (|go-af|) or "inner function" (|go-if|). + * Most commands are run asynchronous in Neovim and Vim 8. Fully async building and testing. - * Integrated with the neovim terminal, launch `:GoRun` and other go commands - in their own new terminal. - * Alternate between implementation and test code with `:GoAlternate` + * Integrated with the Neovim terminal, launch |:GoRun| and other Go commands + in a terminal buffer. + * Switch between `file.go` and `file_test.go` code with |:GoAlternate|. + * Supports integration with the Tagbar and ctrlp.vim plugins. + * ...and more... -=============================================================================== +============================================================================== INSTALL *go-install* -Vim-go follows the standard runtime path structure, so I highly recommend to use -a common and well known plugin manager to install vim-go. Do not use vim-go with -other Go plugins. For Pathogen just clone the repo, for other plugin managers -add the appropriate lines and execute the plugin's install command. +The latest stable release, https://github.com/fatih/vim-go/releases/latest, is +the recommended version to use. If you choose to use the master branch +instead, please do so with caution; it is a _development_ branch. + +vim-go follows the standard runtime path structure and should work with any of +the major plugin managers. + +For Pathogen or Vim |packages|, just clone the repo. For other plugin managers +you may also need to add the lines to your vimrc to execute the plugin +manager's install command. + +* Vim 8 |packages| +> + git clone https://github.com/fatih/vim-go.git \ + ~/.vim/pack/plugins/start/vim-go * https://github.com/tpope/vim-pathogen > git clone https://github.com/fatih/vim-go.git ~/.vim/bundle/vim-go < - * https://github.com/junegunn/vim-plug > Plug 'fatih/vim-go' -< * https://github.com/Shougo/neobundle.vim > NeoBundle 'fatih/vim-go' < - * https://github.com/gmarik/vundle > Plugin 'fatih/vim-go' - < -* Manual > +* Manual (not recommended) > Copy all of the files into your `~/.vim` directory < +You will also need to install all the necessary binaries. vim-go makes it easy +to install all of them by providing a command, |:GoInstallBinaries|, to +`go get` all the required binaries. The binaries will be installed to $GOBIN +or $GOPATH/bin (default: $HOME/go/bin). It requires `git`. -Please be sure all necessary binaries are installed (such as `gocode`, `godef`, -`goimports`, etc..). You can easily install them with the included -|GoInstallBinaries| command. If you invoke it, all necessary binaries will be -automatically downloaded and installed to your `$GOBIN` environment (if not set -it will use `$GOPATH/bin`). It requires `git` for fetching the individual Go -packages. +Depending on your installation method, you may have to generate the plugin's +|:helptags| manually (e.g. `:helptags ALL`). -* Autocompletion is enabled by default via ``, to get real-time -completion (completion by type) install: -https://github.com/Shougo/neocomplete.vim for Vim or -https://github.com/Shougo/deoplete.nvim and -https://github.com/zchee/deoplete-go for Neovim -* To get displayed source code tag informations on a sidebar install -https://github.com/majutsushi/tagbar. -* For snippet feature install: -https://github.com/Shougo/neosnippet.vim or -https://github.com/SirVer/ultisnips. -* For a better documentation viewer checkout: https://github.com/garyburd/go-explorer +Autocompletion is enabled by default via 'omnifunc', which you can trigger +with |i_CTRL-X_CTRL-O| (``). -=============================================================================== -COMMANDS *go-commands* +Supported Go plugins~ *vim-go-plugins* - *:GoPath* +The following plugins are supported for use with vim-go: + +* Real-time completion (Vim): + https://github.com/Shougo/neocomplete.vim + +* Real-time completion (Neovim): + https://github.com/Shougo/deoplete.nvim and + https://github.com/zchee/deoplete-go + +* Display source code navigation in a sidebar: + https://github.com/majutsushi/tagbar + +* Snippets: + https://github.com/Shougo/neosnippet.vim or + https://github.com/SirVer/ultisnips + +* For a better documentation viewer check out: + https://github.com/garyburd/go-explorer + +* Integration with `delve` (Neovim only): + https://github.com/jodosha/vim-godebug + +* Interactive |:GoDecls| and |:GoDeclsDir|: + https://github.com/ctrlpvim/ctrlp.vim or + https://github.com/junegunn/fzf.vim or + https://github.com/Shougo/unite.vim + +============================================================================== +COMMANDS *go-commands* + + *:GoPath* :GoPath [path] GoPath sets and overrides GOPATH with the given {path}. If no {path} is given it shows the current GOPATH. If `""` is given as path, it clears - current `GOPATH` which was set with |GoPath| and restores `GOPATH` back to - the initial value which was sourced when Vim was started. + current `GOPATH` which was set with |:GoPath| and restores `GOPATH` back + to the initial value which was sourced when Vim was started. - *:GoImport* + *:GoImport* :GoImport[!] [path] Import ensures that the provided package {path} is imported in the current @@ -143,36 +169,37 @@ COMMANDS *go-commands* If [!] is given it will download the package with `go get` - *:GoImportAs* + *:GoImportAs* :GoImportAs [localname] [path] Same as Import, but uses a custom local name for the package. - *:GoDrop* + *:GoDrop* :GoDrop [path] Remove the import line for the provided package {path}, if present in the current Go buffer. If {path} is not being imported, an error will be displayed and the buffer will be untouched. - *:GoLint* + *:GoLint* :GoLint [packages] - Run golint for the current Go file, or for given packages. + Run golint for the directory under your current file, or for the given + packages. - *:GoDoc* + *:GoDoc* :GoDoc [word] Open the relevant GoDoc in split window for either the word[s] passed to the command or by default, the word under the cursor. - *:GoDocBrowser* + *:GoDocBrowser* :GoDocBrowser [word] Open the relevant GoDoc in browser for either the word[s] passed to the command or by default, the word under the cursor. - *:GoFmt* + *:GoFmt* :GoFmt Filter the current Go buffer through gofmt. It tries to preserve cursor @@ -183,7 +210,7 @@ COMMANDS *go-commands* Filter the current Go buffer through goimports (needs to be installed). `goimports` automatically discards/add import path based on the code. Like - |GoFmt|, It tries to preserve cursor position and avoids replacing the + |:GoFmt|, It tries to preserve cursor position and avoids replacing the buffer with stderr output. *:GoPlay* @@ -194,14 +221,14 @@ COMMANDS *go-commands* is copied to system clipboard if Vim is compiled with 'clipboard' or 'xterm-clipboard' otherwise it's get yanked into the `""` register. - *:GoVet* + *:GoVet* :GoVet[!] [options] Run `go vet` for the directory under your current file. Vet examines Go source code and reports suspicious constructs, such as Printf calls whose - arguments do not align with the format string. Vet uses heuristics that do not - guarantee all reports are genuine problems, but it can find errors not caught - by the compilers. + arguments do not align with the format string. Vet uses heuristics that do + not guarantee all reports are genuine problems, but it can find errors not + caught by the compilers. You may optionally pass any valid go tool vet flags/options. In this case, `go tool vet` is run in place of `go vet`. For a full list please see @@ -209,75 +236,78 @@ COMMANDS *go-commands* If [!] is not given the first error is jumped to. - *:GoDef* -:GoDef [identifier] + *:GoDef* +:GoDef gd CTRL-] +g + - Goto declaration/definition for the given [identifier]. If no argument is - given, it will jump to the declaration under the cursor. By default the - CTRL-] key and the mapping `gd` are enabled to invoke :GoDef for the - identifier under the cursor. See |g:go_def_mapping_enabled| to disable them. + Goto declaration/definition for the declaration under the cursor. By + default the CTRL-] shortcut, the mapping `gd` and , + g are enabled to invoke :GoDef for the identifier under the + cursor. See |'g:go_def_mapping_enabled'| to disable them. No explicit + arguments are supported. - vim-go also keeps a per-window location stack, roughly analagous to how - vim's internal |tags| functionality works. This is pushed to every time a - jump is made using the GoDef functionality. In essence, this is a LIFO list - of file locations you have visited with :GoDef that is retained to help you - navigate software. For more information on displaying the stack, see - |:GoDefJump| + vim-go also keeps a per-window location stack, roughly analogous to how + Vim's internal |tags| functionality works. This is pushed to every time a + jump is made using the GoDef functionality. In essence, this is a LIFO + list of file locations you have visited with :GoDef that is retained to + help you navigate software. - *:GoDefStack* + *:GoDefStack* :GoDefStack [number] - This command Jumps to a given location in the jumpstack, retaining all other - entries. Jumps to non-existent entries will print an informative message, - but are otherwise a noop. + This command Jumps to a given location in the jumpstack, retaining all + other entries. Jumps to non-existent entries will print an informative + message, but are otherwise a noop. - If no argument is given, it will print out an interactive list of all items - in the stack. Its output looks like this: + If no argument is given, it will print out an interactive list of all + items in the stack. Its output looks like this: - 1 /path/to/first/file.go|1187 col 16|AddThing func(t *Thing) - > 2 /path/to/thing/thing.go|624 col 19|String() string - 3 /path/to/thing/thing.go|744 col 6|func Sprintln(a ...interface{}) string + 1 /path/first/file.go|1187 col 16|AddThing func(t *Thing) + > 2 /path/thing/thing.go|624 col 19|String() string + 3 /path/thing/thing.go|744 col 6|func Sprintln(a ...interface{}) string This list shows the identifiers that you jumped to and the file and cursor - position before that jump. The older jumps are at the top, the newer at the - bottom. + position before that jump. The older jumps are at the top, the newer at + the bottom. - The '>' points to the active entry. This entry and any newer entries below - it will be replaced if |:GoDef| is done from this location. The CTRL-t and - |:GoDefPop| command will jump to the position above the active entry. + The '>' points to the active entry. This entry and any newer entries + below it will be replaced if |:GoDef| is done from this location. The + CTRL-t and |:GoDefPop| command will jump to the position above the active + entry. Jumps to non-existent entries will print an informative message, but are otherwise a noop. *:GoDefStackClear* -:GoDefStackClear +:GoDefStackClear Clears the current stack list and resets it. - *:GoDefPop* + *:GoDefPop* :GoDefPop [count] CTRL-t - Navigate to the [count] earlier entry in the jump stack, retaining the newer - entries. If no argument is given, it will jump to the next most recent entry - (`:GoDefPop 1`). If [count] is greater than the number of prior entries, - an error will be printed and no jump will be performed. + Navigate to the [count] earlier entry in the jump stack, retaining the + newer entries. If no argument is given, it will jump to the next most + recent entry (`:GoDefPop 1`). If [count] is greater than the number of + prior entries, an error will be printed and no jump will be performed. If you have used :GoDefPop to jump to an earlier location, and you issue another :GoDef command, the current entry will be replaced, and all newer entries will be removed, effectively resuming the stack at that location. - By default [count]CTRL-t is enabled to invoke :GoDefPop. Similarly, hitting - CTRL-t without a prior count is equivalent to `:GoDefPop 1`. See - |g:go_def_mapping_enabled| to disable this. + By default [count]CTRL-t is enabled to invoke :GoDefPop. Similarly, + hitting CTRL-t without a prior count is equivalent to `:GoDefPop 1`. See + |'g:go_def_mapping_enabled'| to disable this. - *:GoRun* + *:GoRun* :GoRun[!] [expand] Build and run your current main package. By default all main files for the - current file is used. If an argument is passed, 'expand' is used as file + current file is used. If an argument is passed, [expand] is used as file selector. For example use `:GoRun %` to select the current file only. You may optionally pass any valid go run flags/options. For a full list @@ -286,73 +316,75 @@ CTRL-t If [!] is not given the first error is jumped to. If using neovim then `:GoRun` will run in a new terminal according to - |g:go_term_mode|. + |'g:go_term_mode'|. - *:GoBuild* + *:GoBuild* :GoBuild[!] [expand] Build your package with `go build`. Errors are populated in the quickfix window. It automatically builds only the files that depends on the current file. `:GoBuild` doesn't produce a result file. - Use 'make' to create a result file. + Use |:make| to create a result file. You may optionally pass any valid go build flags/options. For a full list - please see `go help build`. Options are expanded with 'expand'. + please see `go help build`. Options are expanded with [expand]. If [!] is not given the first error is jumped to. If using neovim then this command is fully async, it does not block the UI. - *:GoGenerate* + *:GoGenerate* :GoGenerate[!] [expand] Creates or updates your auto-generated source files by running `go generate`. - You may optionally pass any valid go generate flags/options. For a full list - please see `go help generate`. Options are expanded with 'expand'. + You may optionally pass any valid go generate flags/options. For a full + list please see `go help generate`. Options are expanded with [expand]. If [!] is not given the first error is jumped to. - *:GoInfo* + *:GoInfo* :GoInfo Show type information about the identifier under the cursor. For example putting it above a function call is going to show the full function - signature. It uses gocode to get the type informations. + signature. By default it uses `gocode` to get the type informations. To + change the underlying tool from `gocode` to another tool, see + |'g:go_info_mode'|. - *:GoInstall* + *:GoInstall* :GoInstall[!] [options] Install your package with `go install`. - You may optionally pass any valid go install flags/options. For a full list - please see `go help install`. + You may optionally pass any valid go install flags/options. For a full + list please see `go help install`. If [!] is not given the first error is jumped to. - *:GoTest* + *:GoTest* :GoTest[!] [expand] Run the tests on your _test.go files via in your current directory. Errors - are populated in the quickfix window. If an argument is passed, 'expand' + are populated in the quickfix window. If an argument is passed, [expand] is used as file selector (useful for cases like `:GoTest ./...`). You may optionally pass any valid go test flags/options. For a full list please see `go help test`. GoTest timesout automatically after 10 seconds. To customize the timeout - use |g:go_test_timeout|. This feature is disabled if any arguments are + use |'g:go_test_timeout'|. This feature is disabled if any arguments are passed to the `:GoTest` command. If [!] is not given the first error is jumped to. If using neovim `:GoTest` will run in a new terminal or run asynchronously - in the background according to |g:go_term_enabled|. You can set the mode of - the new terminal with |g:go_term_mode|. + in the background according to |'g:go_term_enabled'|. You can set the mode + of the new terminal with |'g:go_term_mode'|. - *:GoTestFunc* + *:GoTestFunc* :GoTestFunc[!] [expand] Runs :GoTest, but only on the single test function immediate to your @@ -364,15 +396,15 @@ CTRL-t If [!] is not given the first error is jumped to. - If using neovim `:GoTestFunc` will run in a new terminal or run asynchronously - in the background according to |g:go_term_enabled|. You can set the mode of - the new terminal with |g:go_term_mode|. + If using neovim `:GoTestFunc` will run in a new terminal or run + asynchronously in the background according to |'g:go_term_enabled'|. You + can set the mode of the new terminal with |'g:go_term_mode'|. *:GoTestCompile* :GoTestCompile[!] [expand] Compile your _test.go files via in your current directory. Errors are - populated in the quickfix window. If an argument is passed, 'expand' is + populated in the quickfix window. If an argument is passed, [expand] is used as file selector (useful for cases like `:GoTest ./...`). Useful to not run the tests and capture/fix errors before running the tests or to create test binary. @@ -380,10 +412,10 @@ CTRL-t If [!] is not given the first error is jumped to. If using neovim `:GoTestCompile` will run in a new terminal or run - asynchronously in the background according to |g:go_term_enabled|. You can - set the mode of the new terminal with |g:go_term_mode|. + asynchronously in the background according to |'g:go_term_enabled'|. You + can set the mode of the new terminal with |'g:go_term_mode'|. - *:GoCoverage* + *:GoCoverage* :GoCoverage[!] [options] Create a coverage profile and annotates the current file's source code. If @@ -391,7 +423,7 @@ CTRL-t If [!] is not given the first error is jumped to. - *:GoCoverageToggle* + *:GoCoverageToggle* :GoCoverageToggle[!] [options] Create a coverage profile and annotates the current file's source code. If @@ -399,7 +431,7 @@ CTRL-t If [!] is not given the first error is jumped to. - *:GoCoverageClear* + *:GoCoverageClear* :GoCoverageClear [options] Clears the coverage annotation. @@ -416,46 +448,56 @@ CTRL-t If [!] is not given the first error is jumped to. - *:GoErrCheck* + *:GoErrCheck* :GoErrCheck [options] Check for unchecked errors in you current package. Errors are populated in the quickfix window. - You may optionally pass any valid errcheck flags/options. For a full list - please see `errcheck -h`. + You may optionally pass any valid errcheck flags/options. See + `errcheck -h` for a full list. - *:GoFiles* -:GoFiles + *:GoFiles* +:GoFiles [source_files] - Show source files that depends for the current package + Show source files for the current package. The [source_files] specifies + which file types to list. See the "// Source files" section of + `go list -h` for possible values; multiple values are accepted. + Command-line completion also works for this command. + The default is to use `GoFiles` if no arguments are given. - *:GoDeps* + *:GoDeps* :GoDeps - Show dependencies for the current package + Show dependencies for the current package. *:GoInstallBinaries* -:GoInstallBinaries +:GoInstallBinaries [binaries] - Download and Install all necessary Go tool binaries such as `godef`, - `goimports`, `gocode`, etc.. under `g:go_bin_path`. Set |g:go_get_update| - to disable updating dependencies. + Download and install all necessary Go tool binaries such as `godef`, + `goimports`, `gocode`, etc. under |'g:go_bin_path'|. If [binaries] is + supplied, then only the specified binaries will be installed. The default + is to install everything. - *:GoUpdateBinaries* -:GoUpdateBinaries + Set |'g:go_get_update'| to disable updating dependencies. - Download and Update previously installed Go tool binaries such as `godef`, - `goimports`, `gocode`, etc.. under `g:go_bin_path`. This can be used to - update the necessary Go binaries. + *:GoUpdateBinaries* +:GoUpdateBinaries [binaries] - *:GoImplements* + Download and update previously installed Go tool binaries such as `godef`, + `goimports`, `gocode`, etc. under |'g:go_bin_path'|. If [binaries] is + supplied, then only the specified binaries will be updated. The default is + to update everything. + + Set |'g:go_get_update'| to disable updating dependencies. + + *:GoImplements* :GoImplements - Show 'implements' relation for a selected package. A list of interfaces + Show "implements" relation for a selected package. A list of interfaces for the type that implements an interface under the cursor (or selected package) is shown in a location list. - *:GoRename* + *:GoRename* :GoRename[!] [to] Rename the identifier under the cursor to the desired new name. If no @@ -464,13 +506,13 @@ CTRL-t If [!] is not given the first error is jumped to. - *:GoGuruScope* + *:GoGuruScope* :GoGuruScope [pattern] [pattern2] ... [patternN] - Changes the custom |g:go_guru_scope| setting and overrides it with the + Changes the custom |'g:go_guru_scope'| setting and overrides it with the given package patterns. The custom scope is cleared (unset) if `""` is given as the only path. If no arguments is given it prints the current - custom scope. Example patterns are: + custom scope. Example patterns are: > golang.org/x/tools/cmd/guru # a single package golang.org/x/tools/... # all packages beneath dir @@ -488,21 +530,23 @@ CTRL-t Under the hood, the patterns are all joined to a comma-separated list and passed to `guru`'s `-scope` flag. - *:GoCallees* + Also see |go-guru-scope|. + + *:GoCallees* :GoCallees - Show 'callees' relation for a selected package. A list of possible call + Show "callees" relation for a selected package. A list of possible call targets for the type under the cursor (or selected package) is shown in a location list. - *:GoCallers* + *:GoCallers* :GoCallers - Show 'callers' relation for a selected function. A list of possible + Show "callers" relation for a selected function. A list of possible callers for the selected function under the cursor is shown in a location list. - *:GoDescribe* + *:GoDescribe* :GoDescribe Shows various properties of the selected syntax: its syntactic kind, its @@ -511,116 +555,160 @@ CTRL-t identifier), etc. Almost any piece of syntax may be described, and the guru will try to print all the useful information it can. - *:GoCallstack* + *:GoCallstack* :GoCallstack - Shows 'callstack' relation for the selected function. An arbitrary path + Shows "callstack" relation for the selected function. An arbitrary path from the root of the callgraph to the selected function is shown in a location list. This may be useful to understand how the function is reached in a given program. - *:GoFreevars* + *:GoFreevars* :GoFreevars - Enumerates the free variables of the selection. “Free variables” is a + Enumerates the free variables of the selection. "Free variables" is a technical term meaning the set of variables that are referenced but not defined within the selection, or loosely speaking, its inputs. - This information is useful if you’re considering whether to refactor the + This information is useful when considering whether to refactor the selection into a function of its own, as the free variables would be the - necessary parameters of that function. It’s also useful when you want to + necessary parameters of that function. It's also useful when you want to understand what the inputs are to a complex block of code even if you don’t plan to change it. - *:GoChannelPeers* + *:GoChannelPeers* :GoChannelPeers Shows the set of possible sends/receives on the channel operand of the - selected send or receive operation; the selection must be a <- token. + selected send or receive operation; the selection must be a `<-` token. For example, visually select a channel operand in the form of: - - "done <- true" - - and call |GoChannelPeers| on it. It will show where it was allocated, and +> + done <- true +< + And call |:GoChannelPeers| on it. It will show where it was allocated, and the sending and receiving endings. - *:GoReferrers* + *:GoReferrers* :GoReferrers The referrers query shows the set of identifiers that refer to the same object as does the selected identifier, within any package in the analysis scope. - *:GoMetaLinter* + *:GoSameIds* +:GoSameIds + + Highlights all identifiers that are equivalent to the identifier under the + cursor. + + *:GoSameIdsClear* +:GoSameIdsClear + + Clears all SameIds highlights from a |:GoSameIds| call. + + *:GoSameIdsToggle* +:GoSameIdsToggle + + Toggle between |:GoSameIds| and |:GoSameIdsClear|. + + *:GoSameIdsAutoToggle* +:GoSameIdsAutoToggle + + Enables or disables automatic highlighting of |:GoSameIds| while moving + the cursor. This basically toggles the option |'g:go_auto_sameids'| + on/off. + If enabled it starts highlighting whenever your cursor is staying at the + same position for a configurable period of time (see 'updatetime'). If + disabled it clears and stops automatic highlighting. + + *:GoMetaLinter* :GoMetaLinter [path] Calls the underlying `gometalinter` tool and displays all warnings and - errors in the quickfix window. By default the following linters are - enabled: "'vet', 'golint', 'errcheck'". This can be changed with the - |g:go_metalinter_enabled| variable. To override the command completely use - the variable |g:go_metalinter_command|. To override the maximum linters - execution time use |g:go_metalinter_deadline| variable. + errors in the |quickfix| window. By default the following linters are + enabled: `vet`, `golint`, and `errcheck`. This can be changed with the + |'g:go_metalinter_enabled'| variable. To override the command completely + use the variable |'g:go_metalinter_command'|. To override the maximum + linters execution time use |'g:go_metalinter_deadline'| variable. - *:GoGuruTags* -:GoGuruTags [tags] + *:GoBuildTags* +:GoBuildTags [tags] - Changes the custom |g:go_guru_tags| setting and overrides it with the - given build tags. This command cooperate with GoReferrers command when - there exist mulitiple build tags in your project, then you can set one - of the build tags for GoReferrers to find more accurate. - The custom build tags is cleared (unset) if `""` is given. If no arguments - is given it prints the current custom build tags. + Changes the build tags for various commands. If you have any file that + uses a custom build tag, such as `//+build integration` , this command can + be used to pass it to all tools that accepts tags, such as guru, gorename, + etc.. + + The build tags is cleared (unset) if `""` is given. If no arguments is + given it prints the current custom build tags. *:AsmFmt* :AsmFmt - Filter the current Go asm buffer through asmfmt. It tries to preserve cursor - position and avoids replacing the buffer with stderr output. + Filter the current Go asm buffer through asmfmt. It tries to preserve + cursor position and avoids replacing the buffer with stderr output. - - *:GoAlternate* + *:GoAlternate* :GoAlternate[!] - Alternates between the implementation and test code. For example if in main.go, - switch to main_test.go. Uses the |g:go_alternate_mode| setting as the command - to open the file. + Alternates between the implementation and test code. For example if in + main.go, switch to main_test.go. Uses the |'g:go_alternate_mode'| setting + as the command to open the file. - If [!] is given then it switches to the new file even if it does not exist. + If [!] is given then it switches to the new file even if it does not + exist. - If you would like to override the traditional commands for alternating, add - the following to your .vimrc: + If you would like to override the traditional commands for alternating, + add the following to your .vimrc: > augroup go autocmd! - autocmd Filetype go command! -bang A call go#alternate#Switch(0, 'edit') - autocmd Filetype go command! -bang AV call go#alternate#Switch(0, 'vsplit') - autocmd Filetype go command! -bang AS call go#alternate#Switch(0, 'split') + autocmd Filetype go + \ command! -bang A call go#alternate#Switch(0, 'edit') + \| command! -bang AV call go#alternate#Switch(0, 'vsplit') + \| command! -bang AS call go#alternate#Switch(0, 'split') augroup END < - *:GoDecls* + *:GoWhicherrs* +:GoWhicherrs + + Show the list of possible constants, global variables, and concrete types + for the error type under the cursor in a location list. + + *:GoDecls* :GoDecls [file] - - Only enabled if `ctrlp.vim` is installed. If run shows all function and - type declarations for the current file. If [file] is non empty it parses - the given file. - By default `type` and `func` declarations are being showed. This can be - changed via |g:go_decls_includes|, which accepts a comma delimited list of - definitions. By default set to: `"func,type"`. Possible options are: - `{func,type}` - *:GoDeclsDir* + Show all function and type declarations for the current file. If + [file] is non empty it parses the given file. + Requires `ctrlp.vim` or `fzf`; it will autodetect the plugin if installed, + but you can use |'g:go_decls_mode'| to force using one or the other. + By default `type` and `func` declarations are shown. This can be changed + via |'g:go_decls_includes'|. Also see |unite-decls|. + + *:GoDeclsDir* :GoDeclsDir [dir] - - Only enabled if `ctrlp.vim` is installed. If run shows all function and - type declarations for the current directory. If [dir] is given it parses - the given directory. - By default `type` and `func` declarations are being showed. This can be - changed via |g:go_decls_includes|, which accepts a comma delimited list of - definitions. By default set to: `"func,type"`. Possible options are: - `{func,type}` - *:GoImpl* + Show all function and type declarations for the current directory. If + [dir] is given it parses the given directory. + + *unite-decls* +:Unite decls[:file or dir] + + Only enabled if `unite.vim` is installed. Show declarations for all + functions and types on the current file or directory. If [:file or dir] + is non empty, it parses the given one. +> + " show declarations on the parent directory of the current file + :Unite decls + + " show declarations on the file + :Unite decls:foo/bar.go + + " show declarations on the directory + :Unite decls:foo +< + *:GoImpl* :GoImpl [receiver] [interface] Generates method stubs for implementing an interface. If no arguments is @@ -629,16 +717,121 @@ CTRL-t receiver and the interface needs to be specified. Example usages: > :GoImpl f *Foo io.Writer - :GoImpl T io.ReadWriteCloser + :GoImpl t Type io.ReadWriteCloser < - + *:GoAddTags* +:[range]GoAddTags [key],[option] [key1],[option] ... -=============================================================================== + Adds field tags for the fields of a struct. If called inside a struct it + automatically add field tags with the `json` key and the value + automatically generated based on the field name. An error message is given + if it's called outside a struct definition or if the file is not correctly + formatted. + + If [range] is given, only the selected fields will be changed. + + The default `json` can be changed by providing one or more [key] + arguments. An example of adding `xml` and `db` would be: +> + :GoAddTags xml db +< + If [option] is passed it'll either add a new tag with an option or will + modify existing tags. An example of adding `omitempty` to all `json` + fields would be: +> + :GoAddTags json,omitempty +< + You can define a constant value instead of the default field based value. + For example the following command will add ``valid:"1"`` to all fields. +> + :GoAddTags valid=1 +< + *:GoRemoveTags* +:[range]GoRemoveTags [key],[option] [key1],[option1] ... + + Rmove field tags for the fields of a struct. If called inside a struct it + automatically remove all field tags. An error message is given if it's + called outside a struct definition or if the file is not correctly + formatted + + If [range] is given, only the selected fields will be changed. + + If [key] is given, it will only remove those keys. Example: +> + :GoRemoveTags json +< + If [option] is passed with a [key], it will only remove the options. + Example, this will only remove `omitempty` options from fields containing + `json`: +> + :GoRemoveTags json,omitempty +< + *:GoAutoTypeInfoToggle* +:GoAutoTypeInfoToggle + + Toggles |'g:go_auto_type_info'|. + + *:GoFmtAutoSaveToggle* +:GoFmtAutoSaveToggle + + Toggles |'g:go_fmt_autosave'|. + + *:GoAsmFmtAutoSaveToggle* +:GoAsmFmtAutoSaveToggle + + Toggles |'g:go_asmfmt_autosave'|. + + *:GoMetaLinterAutoSaveToggle* +:GoMetaLinterAutoSaveToggle + + Toggles |'g:go_metalinter_autosave'|. + + *:GoTemplateAutoCreateToggle* +:GoTemplateAutoCreateToggle + + Toggles |'g:go_template_autocreate'|. + + *:GoKeyify* +:GoKeyify + + Uses `keyify` to turn unkeyed struct literals into keyed ones. + + For example: +> + Person{"John", "Smith"} +< + Becomes: +> + Person{ + Name: "John", + Surname: "Smith", + } +< + *:GoFillStruct* +:GoFillStruct + + Use `fillstruct` to fill a struct literal with default values. Existing + values (if any) are preserved. The cursor must be on the struct you wish + to fill. + + For example: +> + addr := net.Address{Name: "Ford Prefect"} +< + Becomes: +> + addr := net.Address{ + Name: "Ford Prefect", + Email: "", + } +< + +============================================================================== MAPPINGS *go-mappings* vim-go has several keys which can be used to create custom mappings -For example, to create a mapping that `go run` for the current package, create -a mapping for the `(go-run)`: > +For example, to create a mapping that calls `go run` for the current package, +create a mapping for the `(go-run)`: > au FileType go nmap r (go-run) @@ -646,11 +839,11 @@ As always one is free to create more advanced mappings or functions based with |go-commands|. For more information please check out the mappings command documentation in the |go-commands| section. Available keys are: - *(go-run)* + *(go-run)* Calls `go run` for the current main package - *(go-run-tab)* + *(go-run-tab)* Calls `go run` for the current file in a new terminal tab This option is neovim only. @@ -660,117 +853,118 @@ This option is neovim only. Calls `go run` for the current file in a new terminal horizontal split This option is neovim only. - *(go-run-vertical)* + *(go-run-vertical)* Calls `go run` for the current file in a new terminal vertical split This option is neovim only. - - *(go-build)* + *(go-build)* Calls `go build` for the current package - *(go-generate)* + *(go-generate)* Calls `go generate` for the current package - *(go-info)* + *(go-info)* Shows type information for the word under the cursor - *(go-install)* + *(go-install)* Calls `go install` for the current package - *(go-test)* + *(go-test)* Calls `go test` for the current package - *(go-test-func)* + *(go-test-func)* Calls `go test -run '...'` for the test function immediate to cursor - *(go-test-compile)* + *(go-test-compile)* Calls `go test -c` for the current package - *(go-coverage)* + *(go-coverage)* Calls `go test -coverprofile-temp.out` for the current package and shows the coverage annotation. - *(go-coverage-clear)* + *(go-coverage-clear)* Clears the coverage annotation *(go-coverage-toggle)* Calls `go test -coverprofile-temp.out` for the current package and shows the -coverage annotation. If run agains it acts as a toggle and clears the +coverage annotation. If run again it acts as a toggle and clears the annotation. *(go-imports)* Calls `goimports` for the current package - *(go-vet)* + *(go-lint)* + +Calls `golint` for the current package + + *(go-vet)* Calls `go vet` for the current package - *(go-files)* + *(go-files)* Show source files that depends for the current package - *(go-deps)* + *(go-deps)* Show dependencies for the current package - *(go-doc)* + *(go-doc)* Show the relevant GoDoc for the word under the cursor in a split window leftabove (default mode). - *(go-doc-split)* + *(go-doc-split)* Show the relevant GoDoc for the word under the cursor in a split window. - *(go-doc-vertical)* + *(go-doc-vertical)* Show the relevant GoDoc for the word under the cursor in a vertical split window. - - *(go-doc-tab)* + *(go-doc-tab)* Show the relevant GoDoc for the word under the cursor in a tab window. - *(go-doc-browser)* + *(go-doc-browser)* Show the relevant GoDoc for the word under in browser - *(go-def)* + *(go-def)* Goto declaration/definition. Results are shown in the current buffer. + *(go-def-split)* - *(go-def-split)* +Goto declaration/definition. Results are shown in a split window. +Jumps to an existing buffer if |'g:go_def_reuse_buffer'| is enabled. -Goto declaration/definition. Results are shown in a split window. -Jumps to an existing buffer if |g:go_def_reuse_buffer| is enabled. - - *(go-def-vertical)* + *(go-def-vertical)* Goto declaration/definition. Results are shown in a vertical split window. -Jumps to an existing buffer if |g:go_def_reuse_buffer| is enabled. +Jumps to an existing buffer if |'g:go_def_reuse_buffer'| is enabled. - *(go-def-tab)* + *(go-def-tab)* Goto declaration/definition. Results are shown in a tab window. -Jumps to an existing buffer if |g:go_def_reuse_buffer| is enabled. +Jumps to an existing buffer if |'g:go_def_reuse_buffer'| is enabled. *(go-def-stack)* @@ -778,81 +972,82 @@ Shows the godef tag stack *(go-def-stack-clear)* -Resets and clers the tasg stack +Resets and clears the tag stack - *(go-def-pop)* + *(go-def-pop)* Jump to previous entry in the tag stack - *(go-implements)* + *(go-implements)* Show the interfaces that the type under the cursor implements. - *(go-rename)* + *(go-rename)* Rename the identifier under the cursor to the desired new name - *(go-callees)* + *(go-callees)* Show the call targets for the type under the cursor - *(go-callers)* + *(go-callers)* Show possible callers of selected function - *(go-describe)* + *(go-describe)* Describe selected syntax: definition, methods, etc - - *(go-callstack)* + *(go-callstack)* Show path from callgraph root to selected function - *(go-freevars)* + *(go-freevars)* Show free variables of selection - *(go-channelpeers)* + *(go-channelpeers)* Show send/receive corresponding to selected channel op - *(go-referrers)* + *(go-referrers)* Show all refs to entity denoted by selected identifier - *(go-metalinter)* + *(go-metalinter)* Calls `go-metalinter` for the current directory - *(go-alternate-edit)* + *(go-alternate-edit)* Alternates between the implementation and test code in the current window - *(go-alternate-split)* + *(go-alternate-split)* Alternates between the implementation and test code in a new horizontal split - *(go-alternate-vertical)* + *(go-alternate-vertical)* Alternates between the implementation and test code in a new vertical split - *(go-import)* + *(go-import)* Calls `:GoImport` for the current package -=============================================================================== +============================================================================== TEXT OBJECTS *go-text-objects* vim-go comes with several custom |text-objects| that can be used to operate upon regions of text. vim-go currently defines the following text objects: *go-v_af* *go-af* -af "a function", select contents from a function definition to the - closing bracket. If |g:go_textobj_include_function_doc| is +af "a function", select contents from a function definition to the + closing bracket. If |'g:go_textobj_include_function_doc'| is enabled it also includes the comment doc for a function declaration. This text-object also supports literal functions. + If |'g:go_textobj_include_variable'| is enabled it also + includes the variable of an function assignment *go-v_if* *go-if* if "inside a function", select contents of a function, @@ -863,9 +1058,9 @@ if "inside a function", select contents of a function, vim-go also defines the following text motion objects: *go-v_]]* *go-]]* -]] [count] forward to next function declaration. If - |g:go_textobj_include_function_doc| is enabled and if your - on a comment, it skips the function which the comment +]] [count] forward to next function declaration. If + |'g:go_textobj_include_function_doc'| is enabled and if your + on a comment, it skips the function which the comment belongs and forwards to the next function declaration. *go-v_[[* *go-[[* @@ -873,59 +1068,99 @@ vim-go also defines the following text motion objects: -=============================================================================== +============================================================================== FUNCTIONS *go-functions* - *go#jobcontrol#Statusline()* + *go#statusline#Show()* Shows the status of a job running asynchronously. Can be used to plug into the statusline. It works to show the status per package instead of per -file. Assume you have three files open, all belonging to the same package, -if the package build (`:GoBuild`) is successful, all statusline's will be empty -(means SUCCESS), if you it fails all file's statusline will show FAILED. +file. Assume you have three files open, all belonging to the same package, if +the package build (`:GoBuild`) is successful, all statusline's will show +`success`, if you it fails all file's statusline will show `failed`. - *go#complete#GetInfo()* +To avoid always showing old status information, the status information is +cleaned for each package after `60` seconds. This can be changed with the +|'g:go_statusline_duration'| setting. + + *go#complete#GetInfo()* 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. This function is also used for |'g:go_auto_type_info'|. -=============================================================================== +============================================================================== SETTINGS *go-settings* - *'g:go_test_timeout'* + *'g:go_test_prepend_name'* + +Prepend the name of the failed test to each test message generated by a failed +test. By default it is disabled. +> + let g:go_test_prepend_name = 0 +< + + *'g:go_test_timeout'* Use this option to change the test timeout of |:GoTest|. By default it is set to 10 seconds . > let g:go_test_timeout= '10s' < + *'g:go_play_browser_command'* - *'g:go_play_browser_command'* +Browser to use for |:GoPlay| or |:GoDocBrowser|. The url must be added with +`%URL%`, and it's advisable to include `&` to make sure the shell returns. For +example: +> + let g:go_play_browser_command = 'firefox-developer %URL% &' +< -Use this option to change the browser that is used to open the snippet url -posted to play.golang.org with |:GoPlay| or for the relevant documentation -used with |:GoDocBrowser|. By default it tries to find it automatically for -the current OS. > +By default it tries to find it automatically for the current OS. > let g:go_play_browser_command = '' < - *'g:go_play_open_browser'* + *'g:go_play_open_browser'* Use this option to open browser after posting the snippet to play.golang.org with |:GoPlay|. By default it's enabled. > let g:go_play_open_browser = 1 < - *'g:go_auto_type_info'* - -Use this option to show the type info (|:GoInfo|) for the word under the cursor -automatically. Whenever the cursor changes the type info will be updated. -By default it's disabled > + *'g:go_auto_type_info'* +Use this option to show the type info (|:GoInfo|) for the word under the +cursor automatically. Whenever the cursor changes the type info will be +updated. By default it's disabled. The delay can be configured with the +'g:go_updatetime' setting. +> let g:go_auto_type_info = 0 < - *'g:go_jump_to_error'* + *'g:go_info_mode'* + +Use this option to define the command to be used for |:GoInfo|. By default +`gocode` is being used as it's the fastest option. But one might also use +`guru` as it's covers more cases and is more accurate. Current valid options +are: `[gocode, guru]` > + + let g:go_info_mode = 'gocode' +< + *'g:go_auto_sameids'* + +Use this option to highlight all uses of the identifier under the cursor +(:GoSameIds) automatically. By default it's disabled. The delay can be +configured with the 'g:go_updatetime' setting. +> + let g:go_auto_sameids = 0 +< + *'g:go_updatetime'* + +Use this option to configure the a custom 'updatetime' for Go source files. If +set to 0, no custom time will be configured. By default it's set to 800ms. +> + let g:go_updatetime = 800 +< + *'g:go_jump_to_error'* Use this option to enable/disable passing the bang attribute to the mappings |(go-build)|, |(go-run)|, etc.. When enabled it will jump to the first error @@ -936,36 +1171,47 @@ changing the behaviour of our custom static mappings. By default it's enabled. > let g:go_jump_to_error = 1 < - *'g:go_fmt_autosave'* + *'g:go_fmt_autosave'* Use this option to auto |:GoFmt| on save. By default it's enabled > let g:go_fmt_autosave = 1 < - *'g:go_fmt_command'* + *'g:go_fmt_command'* Use this option to define which tool is used to gofmt. By default `gofmt` is used > let g:go_fmt_command = "gofmt" < - *'g:go_fmt_options'* - -Use this option to add additional options to the |g:go_fmt_command|. Default -is empty. > + *'g:go_fmt_options'* +Use this option to add additional options to the |'g:go_fmt_command'|. It's +value type can be either a string or a dictionary. This is due backwards +compatibility. The string version will be removed in the future so please use +the dictionary version. Default is empty. +> let g:go_fmt_options = '' + + or + + let g:go_fmt_options = {} < +The dictionary version allows you to define options for multiple binaries: +> + let g:go_fmt_options = { + \ 'gofmt': '-s', + \ 'goimports': '-local mycompany.com', + \ } +< + *'g:go_fmt_fail_silently'* - *'g:go_fmt_fail_silently'* - -Use this option to disable showing a location list when |g:go_fmt_command| +Use this option to disable showing a location list when |'g:go_fmt_command'| fails. By default the location list is shown. > let g:go_fmt_fail_silently = 0 < - - *'g:go_fmt_experimental'* + *'g:go_fmt_experimental'* Use this option to enable fmt's experimental mode. This experimental mode is superior to the current mode as it fully saves the undo history, so undo/redo @@ -974,27 +1220,36 @@ it's causing problems on some Vim versions. By default it's disabled. > let g:go_fmt_experimental = 0 < - *'g:go_doc_keywordprg_enabled'* + *'g:go_doc_keywordprg_enabled'* -Use this option to run `godoc` on words under the cursor with the default -K , keywordprg shortcut. Usually this shortcut is set to use the program `man`. -In Go, using `godoc` is more idiomatic. Default is enabled. > +Use this option to run `godoc` on words under the cursor with |K|; this will +normally run the `man` program, but for Go using `godoc` is more idiomatic. It +will not override the |'keywordprg'| setting, but will run |:GoDoc|. Default +is enabled. > let g:go_doc_keywordprg_enabled = 1 < - *'g:go_def_mode'* + *'g:go_doc_height'* + +Maximum height for the GoDoc window created with |:GoDoc|. Default is 20. > + + let g:go_doc_max_height = 20 +< + + *'g:go_def_mode'* Use this option to define the command to be used for |:GoDef|. By default `guru` is being used as it covers all edge cases. But one might also use -`godef` as it's more faster. Current valid options are: `[guru, godef]` > +`godef` as it's faster. Current valid options are: `[guru, godef]` > let g:go_def_mode = 'guru' < - *'g:go_def_mapping_enabled'* + *'g:go_def_mapping_enabled'* -Use this option to enable/disable the default mapping of CTRL-] and (`gd`) for -GoDef and CTRL-t for :GoDefPop. Disabling it allows you to map something else to -these keys or mappings. Default is enabled. > +Use this option to enable/disable the default mapping of CTRL-], +, g and (`gd`) for GoDef and CTRL-t for :GoDefPop. +Disabling it allows you to map something else to these keys or mappings. +Default is enabled. > let g:go_def_mapping_enabled = 1 < @@ -1005,198 +1260,121 @@ mappings of |:GoDef|. By default it's disabled. > let g:go_def_reuse_buffer = 0 < + *'g:go_doc_command'* - *'g:go_dispatch_enabled'* +Command to use for |:GoDoc|; only used when invoked with a package name. The +`gogetdoc` command is always used when |:GoDoc| is used on the identifier +under the cursor (i.e. without argument or from |K|). > -Use this option to enable/disable the use of Dispatch to execute the -`:GoRun`, `:GoBuild` and `:GoGenerate` commands. More information about Dispatch -is available at https://github.com/tpope/vim-dispatch. Default is disabled. > - - let g:go_dispatch_enabled = 0 -< - *'g:go_doc_command'* - -Use this option to define which tool is used to godoc. By default `godoc` is -used > - - let g:go_doc_command = "godoc" -< - *'g:go_doc_options'* - -Use this option to add additional options to the |g:go_doc_command|. Default -is empty. > - - let g:go_doc_options = '' + let g:go_doc_command = ["godoc"] < *'g:go_bin_path'* Use this option to change default path for vim-go tools when using -|GoInstallBinaries| and |GoUpdateBinaries|. If not set `$GOBIN` or +|:GoInstallBinaries| and |:GoUpdateBinaries|. If not set `$GOBIN` or `$GOPATH/bin` is used. > let g:go_bin_path = "" < - *'g:go_snippet_engine'* + *'g:go_snippet_engine'* Use this option to define the default snippet engine. By default "ultisnips" is used. Use "neosnippet" for neosnippet.vim: > let g:go_snippet_engine = "ultisnips" < + *'g:go_get_update'* - *'g:go_get_update'* - -Use this option to disable updating dependencies with |GoInstallBinaries|. By +Use this option to disable updating dependencies with |:GoInstallBinaries|. By default this is enabled. > let g:go_get_update = 1 < - - *'g:go_guru_scope'* + *'g:go_guru_scope'* Use this option to define the scope of the analysis to be passed for guru -related commands, such as |GoImplements|, |GoCallers|, etc.You can change it -on-the-fly with |GoGuruScope|. The input should be a a list of package +related commands, such as |:GoImplements|, |:GoCallers|, etc. You can change +it on-the-fly with |:GoGuruScope|. The input should be a a list of package pattern. An example input might be: -`["github.com/fatih/color","github.com/fatih/structs"]` By default it's not set, -so the relevant commands defaults are being used. +`["github.com/fatih/color","github.com/fatih/structs"]` + +Also see |go-guru-scope|. + +By default it's not set, so the relevant commands defaults are being used. > let g:go_guru_scope = [] < + *'g:go_build_tags'* - *'g:go_highlight_array_whitespace_error'* - -Highlights white space after "[]". > - - let g:go_highlight_array_whitespace_error = 1 +These options that will be automatically passed to the `-tags` option of +various tools, such as `guru`, `gorename`, etc... This is a permanent +setting. A more useful way is to use |:GoBuildTags| to dynamically change or +remove build tags. By default it's not set. +> + let g:go_build_tags = '' < - - *'g:go_highlight_chan_whitespace_error'* - -Highlights white space around the communications operator (`<-`) that doesn't -follow the standard style. > - - let g:go_highlight_chan_whitespace_error = 1 -< - - *'g:go_highlight_extra_types'* - -Highlights commonly used library types (io.Reader, etc.). > - - let g:go_highlight_extra_types = 1 -< - - *'g:go_highlight_space_tab_error'* - -Highlights instances of tabs following spaces. > - - let g:go_highlight_space_tab_error = 1 -< - *'g:go_highlight_trailing_whitespace_error'* - -Highlights trailing white space. > - - let g:go_highlight_trailing_whitespace_error = 1 - -< - *'g:go_highlight_operators'* - -Highlights operators such as `:=` , `==`, `-=`, etc. By default it's -disabled. > - - let g:go_highlight_operators = 0 -< - *'g:go_highlight_functions'* - -Highlights function names. By default it's disabled. > - - let g:go_highlight_functions = 0 -< - *'g:go_highlight_methods'* - -Highlights method names. By default it's disabled. > - - let g:go_highlight_methods = 0 -< - *'g:go_highlight_structs'* - -Highlights struct names. By default it's disabled. > - - let g:go_highlight_structs = 0 -< - *'g:go_highlight_fields'* - -Highlights field names. By default it's disabled. > - - let g:go_highlight_fields = 0 -< - *'g:go_highlight_interfaces'* - -Highlights interface names. By default it's disabled. > - - let g:go_highlight_interfaces = 0 -< - *'g:go_highlight_build_constraints'* - -Highlights build constraints. By default it's disabled. > - - let g:go_highlight_build_constraints = 0 -< - *'g:go_highlight_string_spellcheck* - -Use this option to highlight spelling errors in strings when |spell| is -also enabled. By default it's enabled. > - - let g:go_highlight_string_spellcheck = 1 -< - *'g:go_highlight_format_strings* - -Use this option to highlight printf-style operators inside string literals. -By default it's enabled. > - - let g:go_highlight_format_strings = 1 -< - *'g:go_autodetect_gopath'* + *'g:go_autodetect_gopath'* Automatically modifies GOPATH for certain directory structures, such as for the tool `godep` which has his own dependencies via the `Godeps` folder. What this means is that all tools are now working with the newly modified GOPATH. -So |GoDef| for example jumps to the source inside the `Godeps` (vendored) +So |:GoDef| for example jumps to the source inside the `Godeps` (vendored) source. Currently `godep` and `gb` is supported, in the near future more tool -supports will be added. By default it's enabled. > +supports will be added. By default it's disabled. > - let g:go_autodetect_gopath = 1 + let g:go_autodetect_gopath = 0 < - *'g:go_textobj_enabled'* + *'g:go_textobj_enabled'* Adds custom text objects. By default it's enabled. > - let g:go_textobj_enabled = 1 + let g:go_textobj_enabled = 1 < - *'g:go_metalinter_autosave'* + *'g:go_textobj_include_function_doc'* + +Consider the comment above a function to be part of the function when using +the `af` text object and `[[` motion. By default it's enabled. > + + let g:go_textobj_include_function_doc = 1 +< + *'g:go_textobj_include_variable'* + +Consider the variable of an function assignment to be part of the anonymous +function when using the `af` text object. By default it's enabled. > + + let g:go_textobj_include_variable = 1 +< + *'g:go_metalinter_autosave'* Use this option to auto |:GoMetaLinter| on save. Only linter messages for the active buffer will be shown. By default it's disabled > let g:go_metalinter_autosave = 0 < - *'g:go_metalinter_autosave_enabled'* + *'g:go_metalinter_autosave_enabled'* -Specifies the enabled linters for auto |GoMetaLinter| on save. By +Specifies the enabled linters for auto |:GoMetaLinter| on save. By default it's using `vet` and `golint`. > let g:go_metalinter_autosave_enabled = ['vet', 'golint'] < - *'g:go_metalinter_enabled'* + *'g:go_metalinter_enabled'* -Specifies the currently enabled linters for the |GoMetaLinter| command. By +Specifies the currently enabled linters for the |:GoMetaLinter| command. By default it's using `vet`, `golint` and `errcheck`. > let g:go_metalinter_enabled = ['vet', 'golint', 'errcheck'] < - *'g:go_metalinter_command'* + *'g:go_metalinter_excludes'* -Overrides the command to be executed when |GoMetaLinter| is called. This is +Specifies the linters to be excluded from the |:GoMetaLinter| command. By +default it's empty +> + let g:go_metalinter_excludes = [] +< + *'g:go_metalinter_command'* + +Overrides the command to be executed when |:GoMetaLinter| is called. This is an advanced settings and is for users who want to have a complete control over how `gometalinter` should be executed. By default it's empty. > @@ -1209,7 +1387,7 @@ seconds. > let g:go_metalinter_deadline = "5s" < - *'g:go_list_height'* + *'g:go_list_height'* Specifies the window height for the quickfix and location list windows. The default value (empty) automatically sets the height to the number of items @@ -1218,21 +1396,52 @@ explicitly overrides this behavior. For standard Vim behavior, set it to 10. > let g:go_list_height = 0 < - *'g:go_list_type'* - -Specifies the type of list to use. The default value (empty) will use the -appropriate kind of list for the command that was called. Supported values are -"", "quickfix", and "locationlist". > + *'g:go_list_type'* +Specifies the type of list to use for command outputs (such as errors from +builds, results from static analysis commands, etc...). The list type for +specific commands can be overridden with |'g:go_list_type_commands'|. The +default value (empty) will use the appropriate kind of list for the command +that was called. Supported values are "", "quickfix", and "locationlist". +> let g:go_list_type = "" < - *'g:go_asmfmt_autosave'* -Use this option to auto |:AsmFmt| on save. By default it's enabled. > + *'g:go_list_type_commands'* - let g:go_asmfmt_autosave = 1 +Specifies the type of list to use for command outputs (such as errors from +builds, results from static analysis commands, etc...). When an expected key +is not present in the dictionary, |'g:go_list_type'| will be used instead. +Supported keys are "GoBuild", "GoErrCheck", "GoFmt", "GoInstall", "GoLint", +"GoMetaLinter", "GoModifyTags" (used for both :GoAddTags and :GoRemoveTags), +"GoRename", "GoRun", and "GoTest". Supported values for each command are +"quickfix" and "locationlist". +> + let g:go_list_type_commands = {} < - *g:go_term_mode* +As an example, the following settings will change all list types to +`locationlist` except for `:GoBuild` where `quickfix` is used: +> + let g:go_list_type = "locationlist" + let g:go_list_type_commands = {"GoBuild": "quickfix"} +< + + *'g:go_list_autoclose'* + +Specifies whether the quickfix/location list should be closed automatically +in the absence of errors. The default value is 1. +If you prefer to keep a long running error window open, you can disable +this by setting the value to 0. +> + let g:go_list_autoclose = 1 +< + *'g:go_asmfmt_autosave'* + +Use this option to auto |:AsmFmt| on save. By default it's disabled. > + + let g:go_asmfmt_autosave = 0 +< + *'g:go_term_mode'* This option is Neovim only. Use it to change the default command used to open a new terminal for go commands such as |:GoRun|. @@ -1240,8 +1449,8 @@ The default is vsplit. > let g:go_term_mode = "vsplit" < - *g:go_term_height* - *g:go_term_width* + *'g:go_term_height'* + *'g:go_term_width'* These options are Neovim only. Use them to control the height and width of a terminal split. By default these are not set, meaning that the height and @@ -1253,96 +1462,519 @@ For example here is how to set each to 30. let g:go_term_height = 30 let g:go_term_width = 30 < - *g:go_term_enabled* + *'g:go_term_enabled'* This option is Neovim only. Use it to change the behavior of the test commands. If set to 1 it opens the test commands inside a new terminal -according to |g:go_term_mode|, otherwise it will run them in the background -just like `:GoBuild` and then display the status with |go#jobcontrol#Statusline()|. -By default it is disabled. +according to |'g:go_term_mode'|, otherwise it will run them in the background +just like `:GoBuild`. By default it is disabled. > let g:go_term_enabled = 0 < - *g:go_alternate_mode* + *'g:go_alternate_mode'* Specifies the command that |:GoAlternate| uses to open the alternate file. By default it is set to edit. > let g:go_alternate_mode = "edit" < - *g:go_gorename_prefill* + *'g:go_gorename_prefill'* -Specifies whether |:GoRename| prefills the new identifier name with the -word under the cursor. By default it is enabled. +Expression to prefill the new identifier when using |:GoRename| without any +arguments. Use an empty string if you don't want to prefill anything. By +default it converts the identifier to camel case but preserves the +capitalisation of the first letter to ensure that the exported state stays the +same. > - let g:go_gorename_prefill = 1 + let g:go_gorename_prefill = 'expand("") =~# "^[A-Z]"' . + \ '? go#util#pascalcase(expand(""))' . + \ ': go#util#camelcase(expand(""))' < - *g:go_gocode_autobuild* + *'g:go_gocode_autobuild'* Specifies whether `gocode` should automatically build out-of-date packages -when their source fiels are modified, in order to obtahin the freshes +when their source fields are modified, in order to obtain the freshest autocomplete results for them. By default it is enabled. > let g:go_gocode_autobuild = 1 < - *g:go_gocode_propose_builtins* + *'g:go_gocode_propose_builtins'* Specifies whether `gocode` should add built-in types, functions and constants to an autocompletion proposals. By default it is enabled. > let g:go_gocode_propose_builtins = 1 - - -=============================================================================== -TROUBLESHOOTING *go-troubleshooting* - -I'm using Fish shell but have some problems using vim-go~ - -First environment variables in Fish are applied differently, it should be like: -> - set -x GOPATH /your/own/gopath < -Second, Vim needs a POSIX compatible shell (more info here: -https://github.com/dag/vim-fish#teach-a-vim-to-fish). If you use Fish to open -Vim, it will make certain shell based commands fail (means vim-go will fail -too). To overcome this problem change the default shell by adding the -following into your .vimrc (on the top of the file): -> - if $SHELL =~ 'fish' - set shell='/bin/sh' - endif -< -or -> - set shell='/bin/sh' -> + *'g:go_gocode_unimported_packages'* -I'm seeing weird errors during installation of binaries with -GoInstallBinaries: +Specifies whether `gocode` should include suggestions from unimported +packages. By default it is disabled. +> + let g:go_gocode_unimported_packages = 0 +< + + *'g:go_gocode_socket_type'* + +Specifies whether `gocode` should use a different socket type. By default +`unix` is enabled. Possible values: `unix`, `tcp` +> + let g:go_gocode_socket_type = 'unix' +< + *'g:go_template_autocreate'* + +When a new Go file is created, vim-go automatically fills the buffer content +with a Go code template. By default, the templates under the `templates` +folder are used. This can be changed with the |'g:go_template_file'| and +|'g:go_template_test_file'| settings. + +If the new file is created in an already prepopulated package (with other Go +files), in this case a Go code template with only the Go package declaration +(which is automatically determined according to the current package) is added. + +To always use the package name instead of the template, enable the +|'g:go_template_use_pkg'| setting. + +By default it is enabled. +> + let g:go_template_autocreate = 1 +< + *'g:go_template_file'* + +Specifies the file under the `templates` folder that is used if a new Go file +is created. Checkout |'g:go_template_autocreate'| for more info. By default +the `hello_world.go` file is used. +> + let g:go_template_file = "hello_world.go" +< + *'g:go_template_test_file'* + +Specifies the file under the `templates` folder that is used if a new Go test +file is created. Checkout |'g:go_template_autocreate'| for more info. By +default the `hello_world_test.go` file is used. +> + let g:go_template_test_file = "hello_world_test.go" +< + *'g:go_template_use_pkg'* + +Specifies that, rather than using a template, the package name is used if a +new Go file is created. Checkout |'g:go_template_autocreate'| for more info. +By default the template file specified by |'g:go_template_file'| is used. + +> + let g:go_template_use_pkg = 0 +< + *'g:go_decls_includes'* + +Only useful if `ctrlp.vim`, `unite.vim` or `fzf` are installed. This sets +which declarations to show for |:GoDecls| (`ctrp.vim`) and |unite-decls| +(`unite.vim`). It is a Comma delimited list Possible options are: +{func,type}. The default is: > + + let g:go_decls_includes = 'func,type' +< + *'g:go_decls_mode'* + +Define the tool to be used for |:GoDecls|. Valid options are `ctrlp.vim`, +`fzf`, or an empty string; in which case it will try to autodetect either +`ctrlp.vim` or `fzf`. +> + let g:go_decls_mode = '' +< + *'g:go_echo_command_info'* + +Echoes information about various Go commands, such as `:GoBuild`, `:GoTest`, +`:GoCoverage`, etc... Useful to disable if you use the statusline integration, +i.e: |go#statusline#Show()|. By default it's enabled +> + let g:go_echo_command_info = 1 +< + *'g:go_echo_go_info'* + +Use this option to show the identifier information when completion is done. By +default it's enabled > + + let g:go_echo_go_info = 1 +< +Please note that 'noshowmode' must be set for this feature to work correctly. + + *'g:go_statusline_duration'* + +Specifies the duration of statusline information being showed per package. By +default it's 60 seconds. Must be in milliseconds. +> + let g:go_statusline_duration = 60000 +< + *'g:go_addtags_transform'* + +Sets the `transform` option for `gomodifytags` when using |:GoAddTags| or if +it's being used for snippet expansion of single fields. Possible options are: +`snakecase`, `camelcase`. For the following case, if `snakecase` is used the +field will be transformed to: +> + type T struct { + FooBarQuz string `json:"foo_bar_quz" + } +< + +If "camelcase" is used: +> + type T struct { + FooBarQuz string `json:"fooBarQuz" + } +< +By default "snakecase" is used. Current values are: ["snakecase", +"camelcase"]. +> + let g:go_addtags_transform = 'snakecase' +< + +============================================================================== +SYNTAX HIGHLIGHTING *ft-go-syntax* *go-syntax* + +vim-go comes with an enhanced version of Vim's Go syntax highlighting. It +comes with a number of features, most of which are disabled by default. + +The recommended settings are the default values. If you're experiencing +slowdowns in Go files and you enabled some of these options then try disabling +them; some can be resource intensive. + + *'g:go_fold_enable'* + +Control syntax-based folding which takes effect when 'foldmethod' is set to +`syntax`. +You can enable specific fold regions by setting an array. Possible values are: + + block `{` .. `}` blocks. + import `import` block. + varconst `var` and `const` blocks. + package_comment The package comment. + comment Any comment that is not the package comment. + +By default all except "comment" are enabled: +> + let g:go_fold_enable = ['block', 'import', 'varconst', 'package_comment'] +< +Enable folding of only imports: +> + let g:go_fold_enable = ['import'] +< +Disable everything (same as not setting 'foldmethod' to `syntax`): +> + let g:go_fold_enable = [] +< + *'g:go_highlight_array_whitespace_error'* + +Highlight white space after `[]`. > + + let g:go_highlight_array_whitespace_error = 0 +< + *'g:go_highlight_chan_whitespace_error'* + +Highlight white space around the receive operator (`<-`) that doesn't follow +the standard style. > + + let g:go_highlight_chan_whitespace_error = 0 +< + *'g:go_highlight_extra_types'* + +Highlight commonly used library types (`io.Reader`, etc.). > + + let g:go_highlight_extra_types = 0 +< + *'g:go_highlight_space_tab_error'* + +Highlight instances of tabs following spaces. > + + let g:go_highlight_space_tab_error = 0 +< + *'g:go_highlight_trailing_whitespace_error'* + +Highlight trailing white space. > + + let g:go_highlight_trailing_whitespace_error = 0 +< + *'g:go_highlight_operators'* + +Highlight operators such as `:=` , `==`, `-=`, etc. +> + let g:go_highlight_operators = 0 +< + *'g:go_highlight_functions'* + +Highlight function names. +> + let g:go_highlight_functions = 0 +< + *'g:go_highlight_methods'* + +Highlight method names. +> + let g:go_highlight_methods = 0 +< + *'g:go_highlight_types'* + +Highlight struct and interface names. +> + let g:go_highlight_types = 0 +< + *'g:go_highlight_fields'* + +Highlight struct field names. +> + let g:go_highlight_fields = 0 +< + *'g:go_highlight_build_constraints'* + +Highlights build constraints. +> + let g:go_highlight_build_constraints = 0 +< + *'g:go_highlight_generate_tags'* + +Highlight go:generate directives. +> + let g:go_highlight_generate_tags = 0 +< + *'g:go_highlight_string_spellcheck'* + +Highlight spelling errors in strings when |spell| is enabled. +> + let g:go_highlight_string_spellcheck = 1 +< + *'g:go_highlight_format_strings'* + +Highlight printf-style formatting verbs inside string literals. +> + let g:go_highlight_format_strings = 1 +< + *'g:go_highlight_variable_declarations'* + +Highlight variable names in variable declarations (`x` in ` x :=`). +> + let g:go_highlight_variable_declarations = 0 +< + *'g:go_highlight_variable_assignments'* + +Highlight variable names in variable assignments (`x` in `x =`). +> + let g:go_highlight_variable_assignments = 0 +< + +============================================================================== + *gohtmltmpl* *ft-gohtmltmpl-syntax* + *gotexttmpl* *ft-gotexttmpl-syntax* +Go template syntax~ + +The `gotexttmpl` 'filetype' provides syntax highlighting and indentation for +Go's `text/template` package. + +The `gohtmltmpl` filetype is for use with the `html/template` package and is +identical to `gotexttmpl` except that it will also load the standard `html` +filetype. + +The `gohtmltmpl` filetype is automatically set for `*.tmpl` files; the +`gotexttmpl` is never automatically set and needs to be set manually. + + +============================================================================== +FAQ TROUBLESHOOTING *go-troubleshooting* + +I get "not an editor command" error when I invoke :GoXXX~ + +This happens if vim-go is not installed properly. Be sure you have added this +line into your vimrc: +> + filetype plugin indent on +< + +I get a "command not found" error when I invoke :GoXXX~ + +If you try to call |:GoDef|, |:GoInfo| and get a command not found, check that +you have the binaries installed by using |:GoInstallBinaries|. + +Before opening vim, check your current $PATH: +> + echo $PATH +< +After opening vim, run `:echo $PATH`, the output must be your current `$PATH` +plus `$GOPATH/bin` (the location where |:GoInstallBinaries| installed the +binaries). + + *go-guru-scope* +What is the guru scope and how do I set it?~ + +Many vim-go commands use the `guru` commandline tool to get information. Some +`guru` commands require an expensive analysis of the source code. To still get +a reasonable amount of performance `guru` limits this analysis to a selected +list of packages. This is known as the "guru scope". + +The default is to use the package the curent buffer belongs to, but this may +not always be correct. For example for the file `guthub.com/user/pkg/a/a.go` +the scope will be set to `github.com/user/pkg/a`, but you probably want +`github.com/user/pkg` + +Guessing what package(s) you do want is not easy so you may need to set this +manually, usually from an |autocommand|: +> + autocmd BufRead /home/martin/go/src/github.com/user/pkg/*.go + \ :GoGuruScope github.com/user/pkg +< + +If you have a lot of packages with the same prefix (`github.com/user`) you can +use a single autocommand: +> + autocmd BufRead /home/martin/go/src/*.go + \ let s:tmp = matchlist(expand('%:p'), + \ '/home/martin/go/src/\(github.com/user/[^/]\+\)') + \| if len(s:tmp) > 1 | exe 'silent :GoGuruScope ' . s:tmp[1] | endif + \| unlet s:tmp +< +Also see |:GoGuruScope| and |'g:go_guru_scope'|. + + +Vim becomes slow while editing Go files~ + +This is usually caused by `g:go_highlight_*` options. Try disabling them if +you've enabled some of them. + +Other common culprits are |'g:go_auto_sameids'| and |go#statusline#Show()|. + + +I get errors when using GoInstallBinaries~ If you see errors like this: > - Error installing code.google.com/p/go.tools/cmd/goimports: - Error installing code.google.com/p/rog-go/exp/cmd/godef: + Error installing golang.org/x/tools/cmd/goimports < -that means your local Go setup is broken or the remote website is down. For -example sometimes code.google.com times out. To test, just execute a simple go -get: - +that means your local Go setup is broken or the remote website is down. For +example sometimes code.google.com times out. To test, just execute a simple +`go get`: > - go get code.google.com/p/go.tools/cmd/goimports + go get golang.org/x/tools/cmd/goimports < You'll see a more detailed error. If this works, vim-go will work too. -=============================================================================== + +I want to use a different binary name than "go", can I do this?~ + +There is no way to directly configure the binary name; but you can use a +wrapper script; for example if you would like to run `goapp` instead of `go`: + +1. In `~/gobin/go` (remember to make it executable): +> + #!/bin/sh + # Remove gobin from PATH and run goapp. + PATH=${PATH#$HOME/gobin} goapp "$@" +< +2. Start Vim with `~/gobin` as the first `PATH` entry so it will use the + wrapper script: +> + PATH="$HOME/gobin/:$PATH" vim +< + Alternatively you you could set `$PATH` in your vimrc with an |:autocmd|. + + +How do I use vim-go with syntastic?~ + +Sometimes when using both `vim-go` and `syntastic` Vim will start lagging +while saving and opening files. The following fixes this: +> + let g:syntastic_go_checkers = ['golint', 'govet'] + let g:syntastic_mode_map = { 'mode': 'active', 'passive_filetypes': ['go'] } +< +If you want to add errcheck you can use gometalinter as a wrapper +> + let g:syntastic_go_checkers = ['golint', 'govet', 'gometalinter'] + let g:syntastic_go_gometalinter_args = ['--disable-all', '--enable=errcheck'] + let g:syntastic_mode_map = { 'mode': 'active', 'passive_filetypes': ['go'] } +< +Another issue with `vim-go` and `syntastic` is that the location list window +that contains the output of commands such as `:GoBuild` and `:GoTest` might +not appear. To resolve this: +> + let g:go_list_type = "quickfix" +< + +How do I run focused ginkgo tests?~ + +You must set this environment variable in your `.vimrc`: +> + let $GINKGO_EDITOR_INTEGRATION = "true" +< + +Using with NeoVim~ + +Note: Neovim currently is not a first class citizen for vim-go. You are free +to open bug, however I'm not using Neovim so it's hard for me to test it. +vim-go might not work well as good as in Vim. I'm happy to accept pull +requests or very detailed bug reports. If you're interested to improve the +state of Neovim in vim-go you're always welcome! + +Run `:GoRun` in a new tab, horizontal split or vertical split terminal +> + au FileType go nmap rt (go-run-tab) + au FileType go nmap rs (go-run-split) + au FileType go nmap rv (go-run-vertical) +< +By default new terminals are opened in a vertical split. To change it +> + let g:go_term_mode = "split" +> + +============================================================================== +DEVELOPMENT *go-development* + +vim-go supports test files written in VimScript; the way they're run is +roughly similar to Go tests: + +- A `*.vim` file has a corresponding `*_test.vim`. +- All functions starting with `Test_` are run as test. +- A test is considered to be "failed" if |v:errors| has any entries. You can + use one of the |test-functions| to set this, or append to it directly. + +A simple example: +> + function Test_run_fmt() + call assert_equal(expected, actual) + ... + endfunction +< +To run tests vim-go comes with three small helper scripts: + + `scripts/install-vim` Install a pristine Vim to `/tmp/vim-go-test/`. + `scripts/run-vim` Run a Vim version from `/tmp/vim-go-test/`. + `scripts/test` Run all tests with a Vim from `/tmp/vim-go-test/`. + +All scripts accept a Vim version as the first argument, which can be +`vim-7.4`, `vim-8.0`, or `nvim`. You will need to install a Vim version with +`install-vim` before you can use `run-vim` or `test`. + +You can install and test all Vim versions by running `make`. + + +============================================================================== +DONATION *go-donation* + +People have asked for this for a long time, now you can be a fully supporter +by being a patreon at: https://www.patreon.com/fatih + +By being a patron, you are enabling vim-go to grow and mature, helping me to +invest in bug fixes, new documentation, and improving both current and future +features. It's completely optional and is just a direct way to support +vim-go's ongoing development. Thanks! + +Check it out: https://www.patreon.com/fatih + + +============================================================================== CREDITS *go-credits* -* Go Authors for official vim plugins +* Go Authors for official Vim plugins. * Gocode, Godef, Golint, Guru, Goimports, Errcheck projects and authors of those projects. * Other vim-plugins, thanks for inspiration (vim-golang, go.vim, vim-gocode, - vim-godef) -* vim-go contributors: https://github.com/fatih/vim-go/graphs/contributors + vim-godef). +* vim-go contributors: https://github.com/fatih/vim-go/graphs/contributors. -vim:ft=help:et:ts=2:sw=2:sts=2:norl + vim: ft=help tw=78 et ts=2 sw=2 sts=2 norl diff --git a/sources_non_forked/vim-go/ftdetect/gofiletype.vim b/sources_non_forked/vim-go/ftdetect/gofiletype.vim index b5578a6e..bc47776a 100644 --- a/sources_non_forked/vim-go/ftdetect/gofiletype.vim +++ b/sources_non_forked/vim-go/ftdetect/gofiletype.vim @@ -6,26 +6,29 @@ let s:current_fileencodings = '' " define fileencodings to open as utf-8 encoding even if it's ascii. function! s:gofiletype_pre(type) - let s:current_fileformats = &g:fileformats - let s:current_fileencodings = &g:fileencodings - set fileencodings=utf-8 fileformats=unix - let &l:filetype = a:type + let s:current_fileformats = &g:fileformats + let s:current_fileencodings = &g:fileencodings + set fileencodings=utf-8 fileformats=unix + let &l:filetype = a:type endfunction " restore fileencodings as others function! s:gofiletype_post() - let &g:fileformats = s:current_fileformats - let &g:fileencodings = s:current_fileencodings + let &g:fileformats = s:current_fileformats + let &g:fileencodings = s:current_fileencodings endfunction -au BufNewFile *.go setfiletype go | setlocal fileencoding=utf-8 fileformat=unix -au BufRead *.go call s:gofiletype_pre("go") -au BufReadPost *.go call s:gofiletype_post() +augroup vim-go-filetype + autocmd! + au BufNewFile *.go setfiletype go | setlocal fileencoding=utf-8 fileformat=unix + au BufRead *.go call s:gofiletype_pre("go") + au BufReadPost *.go call s:gofiletype_post() -au BufNewFile *.s setfiletype asm | setlocal fileencoding=utf-8 fileformat=unix -au BufRead *.s call s:gofiletype_pre("asm") -au BufReadPost *.s call s:gofiletype_post() + au BufNewFile *.s setfiletype asm | setlocal fileencoding=utf-8 fileformat=unix + au BufRead *.s call s:gofiletype_pre("asm") + au BufReadPost *.s call s:gofiletype_post() -au BufRead,BufNewFile *.tmpl set filetype=gohtmltmpl + au BufRead,BufNewFile *.tmpl set filetype=gohtmltmpl +augroup end -" vim:ts=4:sw=4:et +" vim: sw=2 ts=2 et diff --git a/sources_non_forked/vim-go/ftplugin/asm.vim b/sources_non_forked/vim-go/ftplugin/asm.vim index 0ac3594b..99996aac 100644 --- a/sources_non_forked/vim-go/ftplugin/asm.vim +++ b/sources_non_forked/vim-go/ftplugin/asm.vim @@ -1,7 +1,7 @@ " asm.vim: Vim filetype plugin for Go assembler. if exists("b:did_ftplugin") - finish + finish endif let b:did_ftplugin = 1 @@ -15,3 +15,5 @@ setlocal commentstring=//\ %s setlocal noexpandtab command! -nargs=0 AsmFmt call go#asmfmt#Format() + +" vim: sw=2 ts=2 et diff --git a/sources_non_forked/vim-go/ftplugin/go.vim b/sources_non_forked/vim-go/ftplugin/go.vim index f322ea39..a0ecd324 100644 --- a/sources_non_forked/vim-go/ftplugin/go.vim +++ b/sources_non_forked/vim-go/ftplugin/go.vim @@ -5,7 +5,7 @@ " go.vim: Vim filetype plugin for Go. if exists("b:did_ftplugin") - finish + finish endif let b:did_ftplugin = 1 @@ -24,40 +24,110 @@ compiler go setlocal omnifunc=go#complete#Complete if get(g:, "go_doc_keywordprg_enabled", 1) - " keywordprg doesn't allow to use vim commands, override it - nnoremap K :GoDoc + " keywordprg doesn't allow to use vim commands, override it + nnoremap K :GoDoc endif if get(g:, "go_def_mapping_enabled", 1) - " these are default Vim mappings, we're overriding them to make them - " useful again for Go source code - nnoremap gd :GoDef - nnoremap :GoDef - nnoremap :call go#def#Jump("split") - nnoremap ] :call go#def#Jump("split") - nnoremap :call go#def#StackPop(v:count1) + " these are default Vim mappings, we're overriding them to make them + " useful again for Go source code + nnoremap gd :GoDef + nnoremap :GoDef + nnoremap :GoDef + nnoremap g :GoDef + nnoremap :call go#def#Jump("split") + nnoremap ] :call go#def#Jump("split") + nnoremap :call go#def#StackPop(v:count1) endif if get(g:, "go_textobj_enabled", 1) - onoremap af :call go#textobj#Function('a') - onoremap if :call go#textobj#Function('i') + onoremap af :call go#textobj#Function('a') + onoremap if :call go#textobj#Function('i') - xnoremap af :call go#textobj#Function('a') - xnoremap if :call go#textobj#Function('i') + xnoremap af :call go#textobj#Function('a') + xnoremap if :call go#textobj#Function('i') - " Remap ]] and [[ to jump betweeen functions as they are useless in Go - nnoremap ]] :call go#textobj#FunctionJump('n', 'next') - nnoremap [[ :call go#textobj#FunctionJump('n', 'prev') + " Remap ]] and [[ to jump betweeen functions as they are useless in Go + nnoremap ]] :call go#textobj#FunctionJump('n', 'next') + nnoremap [[ :call go#textobj#FunctionJump('n', 'prev') - onoremap ]] :call go#textobj#FunctionJump('o', 'next') - onoremap [[ :call go#textobj#FunctionJump('o', 'prev') + onoremap ]] :call go#textobj#FunctionJump('o', 'next') + onoremap [[ :call go#textobj#FunctionJump('o', 'prev') - xnoremap ]] :call go#textobj#FunctionJump('v', 'next') - xnoremap [[ :call go#textobj#FunctionJump('v', 'prev') + xnoremap ]] :call go#textobj#FunctionJump('v', 'next') + xnoremap [[ :call go#textobj#FunctionJump('v', 'prev') endif -if get(g:, "go_auto_type_info", 0) - setlocal updatetime=800 +if get(g:, "go_auto_type_info", 0) || get(g:, "go_auto_sameids", 0) + let &l:updatetime= get(g:, "go_updatetime", 800) endif -" vim:ts=4:sw=4:et +" NOTE(arslan): experimental, disabled by default, doesn't work well. No +" documentation as well. If anyone feels adventurous, enable the following and +" try to search for Go identifiers ;) +" +" if get(g:, "go_sameid_search_enabled", 0) +" autocmd FileType go nnoremap * :call Sameids_search(0) +" autocmd FileType go nnoremap # :call Sameids_search(1) +" autocmd FileType go nnoremap n :call Sameids_repeat(0) +" autocmd FileType go nnoremap N :call Sameids_repeat(1) +" autocmd FileType go cabbrev nohlsearch =Sameids_nohlsearch() +" endif + +" " mode 0: next 1: prev +" function! Sameids_repeat(mode) +" let matches = getmatches() +" if empty(matches) +" return +" endif +" let cur_offset = go#util#OffsetCursor() + +" " reverse list to make it easy to find the prev occurrence +" if a:mode +" call reverse(matches) +" endif + +" for m in matches +" if !has_key(m, "group") +" return +" endif + +" if m.group != "goSameId" +" return +" endif + +" let offset = go#util#Offset(m.pos1[0], m.pos1[1]) + +" if a:mode && cur_offset > offset +" call cursor(m.pos1[0], m.pos1[1]) +" return +" elseif !a:mode && cur_offset < offset +" call cursor(m.pos1[0], m.pos1[1]) +" return +" endif +" endfor + +" " reached start/end, jump to the end/start +" let initial_match = matches[0] +" if !has_key(initial_match, "group") +" return +" endif + +" if initial_match.group != "goSameId" +" return +" endif + +" call cursor(initial_match.pos1[0], initial_match.pos1[1]) +" endfunction + +" function! Sameids_search(mode) +" call go#guru#SameIds() +" call Sameids_repeat(a:mode) +" endfunction + +" function! Sameids_nohlsearch() +" call go#guru#ClearSameIds() +" return "nohlsearch" +" endfunction + +" vim: sw=2 ts=2 et diff --git a/sources_non_forked/vim-go/ftplugin/go/commands.vim b/sources_non_forked/vim-go/ftplugin/go/commands.vim index 44db45a3..0ab6d25a 100644 --- a/sources_non_forked/vim-go/ftplugin/go/commands.vim +++ b/sources_non_forked/vim-go/ftplugin/go/commands.vim @@ -1,9 +1,10 @@ " -- gorename -command! -nargs=? GoRename call go#rename#Rename(0,) +command! -nargs=? -complete=customlist,go#rename#Complete GoRename call go#rename#Rename(0, ) " -- guru command! -nargs=* -complete=customlist,go#package#Complete GoGuruScope call go#guru#Scope() command! -range=% GoImplements call go#guru#Implements() +command! -range=% GoWhicherrs call go#guru#Whicherrs() command! -range=% GoCallees call go#guru#Callees() command! -range=% GoDescribe call go#guru#Describe() command! -range=% GoCallers call go#guru#Callers() @@ -11,24 +12,33 @@ command! -range=% GoCallstack call go#guru#Callstack() command! -range=% GoFreevars call go#guru#Freevars() command! -range=% GoChannelPeers call go#guru#ChannelPeers() command! -range=% GoReferrers call go#guru#Referrers() -command! -nargs=? GoGuruTags call go#guru#Tags() -" TODO(arslan): enable this once the function is implemented -" command! -range=% GoSameIds call go#guru#SameIds() +command! -range=0 GoSameIds call go#guru#SameIds() +command! -range=0 GoSameIdsClear call go#guru#ClearSameIds() +command! -range=0 GoSameIdsToggle call go#guru#ToggleSameIds() +command! -range=0 GoSameIdsAutoToggle call go#guru#AutoToogleSameIds() + +" -- tags +command! -nargs=* -range GoAddTags call go#tags#Add(, , , ) +command! -nargs=* -range GoRemoveTags call go#tags#Remove(, , , ) " -- tool -command! -nargs=0 GoFiles echo go#tool#Files() +command! -nargs=* -complete=customlist,go#tool#ValidFiles GoFiles echo go#tool#Files() command! -nargs=0 GoDeps echo go#tool#Deps() -command! -nargs=* GoInfo call go#complete#Info(0) +command! -nargs=* GoInfo call go#tool#Info(0) +command! -nargs=0 GoAutoTypeInfoToggle call go#complete#ToggleAutoTypeInfo() " -- cmd command! -nargs=* -bang GoBuild call go#cmd#Build(0,) +command! -nargs=? -bang GoBuildTags call go#cmd#BuildTags(0, ) command! -nargs=* -bang GoGenerate call go#cmd#Generate(0,) command! -nargs=* -bang -complete=file GoRun call go#cmd#Run(0,) command! -nargs=* -bang GoInstall call go#cmd#Install(0, ) -command! -nargs=* -bang GoTest call go#cmd#Test(0, 0, ) -command! -nargs=* -bang GoTestFunc call go#cmd#TestFunc(0, ) -command! -nargs=* -bang GoTestCompile call go#cmd#Test(0, 1, ) + +" -- test +command! -nargs=* -bang GoTest call go#test#Test(0, 0, ) +command! -nargs=* -bang GoTestFunc call go#test#Func(0, ) +command! -nargs=* -bang GoTestCompile call go#test#Test(0, 1, ) " -- cover command! -nargs=* -bang GoCoverage call go#coverage#Buffer(0, ) @@ -51,8 +61,12 @@ command! -nargs=* -range -complete=customlist,go#package#Complete GoDocBrowser c " -- fmt command! -nargs=0 GoFmt call go#fmt#Format(-1) +command! -nargs=0 GoFmtAutoSaveToggle call go#fmt#ToggleFmtAutoSave() command! -nargs=0 GoImports call go#fmt#Format(1) +" -- asmfmt +command! -nargs=0 GoAsmFmtAutoSaveToggle call go#asmfmt#ToggleAsmFmtAutoSave() + " -- import command! -nargs=? -complete=customlist,go#package#Complete GoDrop call go#import#SwitchImport(0, '', , '') command! -nargs=1 -bang -complete=customlist,go#package#Complete GoImport call go#import#SwitchImport(1, '', , '') @@ -60,6 +74,7 @@ command! -nargs=* -bang -complete=customlist,go#package#Complete GoImportAs call " -- linters command! -nargs=* GoMetaLinter call go#lint#Gometa(0, ) +command! -nargs=0 GoMetaLinterAutoSaveToggle call go#lint#ToggleMetaLinterAutoSave() command! -nargs=* GoLint call go#lint#Golint() command! -nargs=* -bang GoVet call go#lint#Vet(0, ) command! -nargs=* -complete=customlist,go#package#Complete GoErrCheck call go#lint#Errcheck() @@ -67,13 +82,20 @@ command! -nargs=* -complete=customlist,go#package#Complete GoErrCheck call go#li " -- alternate command! -bang GoAlternate call go#alternate#Switch(0, '') -" -- ctrlp -if globpath(&rtp, 'plugin/ctrlp.vim') != "" - command! -nargs=? -complete=file GoDecls call ctrlp#init(ctrlp#decls#cmd(0, )) - command! -nargs=? -complete=dir GoDeclsDir call ctrlp#init(ctrlp#decls#cmd(1, )) -endif +" -- decls +command! -nargs=? -complete=file GoDecls call go#decls#Decls(0, ) +command! -nargs=? -complete=dir GoDeclsDir call go#decls#Decls(1, ) " -- impl command! -nargs=* -buffer -complete=customlist,go#impl#Complete GoImpl call go#impl#Impl() -" vim:ts=4:sw=4:et +" -- template +command! -nargs=0 GoTemplateAutoCreateToggle call go#template#ToggleAutoCreate() + +" -- keyify +command! -nargs=0 GoKeyify call go#keyify#Keyify() + +" -- fillstruct +command! -nargs=0 GoFillStruct call go#fillstruct#FillStruct() + +" vim: sw=2 ts=2 et diff --git a/sources_non_forked/vim-go/ftplugin/go/mappings.vim b/sources_non_forked/vim-go/ftplugin/go/mappings.vim index 70d56eaa..4cb82789 100644 --- a/sources_non_forked/vim-go/ftplugin/go/mappings.vim +++ b/sources_non_forked/vim-go/ftplugin/go/mappings.vim @@ -5,24 +5,24 @@ " which by default is enabled. For commands the user has the ability to pass " the '!', such as :GoBuild or :GoBuild! if !exists("g:go_jump_to_error") - let g:go_jump_to_error = 1 + let g:go_jump_to_error = 1 endif " Some handy plug mappings nnoremap (go-run) :call go#cmd#Run(!g:go_jump_to_error) if has("nvim") - nnoremap (go-run-vertical) :call go#cmd#RunTerm(!g:go_jump_to_error, 'vsplit', []) - nnoremap (go-run-split) :call go#cmd#RunTerm(!g:go_jump_to_error, 'split', []) - nnoremap (go-run-tab) :call go#cmd#RunTerm(!g:go_jump_to_error, 'tabe', []) + nnoremap (go-run-vertical) :call go#cmd#RunTerm(!g:go_jump_to_error, 'vsplit', []) + nnoremap (go-run-split) :call go#cmd#RunTerm(!g:go_jump_to_error, 'split', []) + nnoremap (go-run-tab) :call go#cmd#RunTerm(!g:go_jump_to_error, 'tabe', []) endif nnoremap (go-build) :call go#cmd#Build(!g:go_jump_to_error) nnoremap (go-generate) :call go#cmd#Generate(!g:go_jump_to_error) nnoremap (go-install) :call go#cmd#Install(!g:go_jump_to_error) -nnoremap (go-test) :call go#cmd#Test(!g:go_jump_to_error, 0) -nnoremap (go-test-func) :call go#cmd#TestFunc(!g:go_jump_to_error) -nnoremap (go-test-compile) :call go#cmd#Test(!g:go_jump_to_error, 1) +nnoremap (go-test) :call go#test#Test(!g:go_jump_to_error, 0) +nnoremap (go-test-func) :call go#test#Func(!g:go_jump_to_error) +nnoremap (go-test-compile) :call go#test#Test(!g:go_jump_to_error, 1) nnoremap (go-coverage) :call go#coverage#Buffer(!g:go_jump_to_error) nnoremap (go-coverage-clear) :call go#coverage#Clear() @@ -31,7 +31,7 @@ nnoremap (go-coverage-browser) :call go#coverage#Browser(!g: nnoremap (go-files) :call go#tool#Files() nnoremap (go-deps) :call go#tool#Deps() -nnoremap (go-info) :call go#complete#Info(0) +nnoremap (go-info) :call go#tool#Info(0) nnoremap (go-import) :call go#import#SwitchImport(1, '', expand(''), '') nnoremap (go-imports) :call go#fmt#Format(1) @@ -43,9 +43,9 @@ nnoremap (go-callstack) :call go#guru#Callstack(-1) xnoremap (go-freevars) :call go#guru#Freevars(0) nnoremap (go-channelpeers) :call go#guru#ChannelPeers(-1) nnoremap (go-referrers) :call go#guru#Referrers(-1) - -" TODO(arslan): enable this once the function is implemented -" nnoremap (go-sameids) :call go#guru#SameIds(-1) +nnoremap (go-sameids) :call go#guru#SameIds() +nnoremap (go-whicherrs) :call go#guru#Whicherrs(-1) +nnoremap (go-sameids-toggle) :call go#guru#ToggleSameIds() nnoremap (go-rename) :call go#rename#Rename(!g:go_jump_to_error) @@ -65,8 +65,11 @@ nnoremap (go-doc-split) :call go#doc#Open("new", "split") (go-doc-browser) :call go#doc#OpenBrowser() nnoremap (go-metalinter) :call go#lint#Gometa(0) +nnoremap (go-lint) :call go#lint#Golint() nnoremap (go-vet) :call go#lint#Vet(!g:go_jump_to_error) nnoremap (go-alternate-edit) :call go#alternate#Switch(0, "edit") nnoremap (go-alternate-vertical) :call go#alternate#Switch(0, "vsplit") nnoremap (go-alternate-split) :call go#alternate#Switch(0, "split") + +" vim: sw=2 ts=2 et diff --git a/sources_non_forked/vim-go/ftplugin/go/snippets.vim b/sources_non_forked/vim-go/ftplugin/go/snippets.vim index 3bf13d2c..56c0811d 100644 --- a/sources_non_forked/vim-go/ftplugin/go/snippets.vim +++ b/sources_non_forked/vim-go/ftplugin/go/snippets.vim @@ -5,42 +5,44 @@ let g:go_loaded_gosnippets = 1 " by default UltiSnips if !exists("g:go_snippet_engine") - let g:go_snippet_engine = "ultisnips" + let g:go_snippet_engine = "ultisnips" endif function! s:GoUltiSnips() - if globpath(&rtp, 'plugin/UltiSnips.vim') == "" - return - endif + if globpath(&rtp, 'plugin/UltiSnips.vim') == "" + return + endif - if !exists("g:UltiSnipsSnippetDirectories") - let g:UltiSnipsSnippetDirectories = ["gosnippets/UltiSnips"] - else - let g:UltiSnipsSnippetDirectories += ["gosnippets/UltiSnips"] - endif + if !exists("g:UltiSnipsSnippetDirectories") + let g:UltiSnipsSnippetDirectories = ["gosnippets/UltiSnips"] + else + let g:UltiSnipsSnippetDirectories += ["gosnippets/UltiSnips"] + endif endfunction function! s:GoNeosnippet() - if globpath(&rtp, 'plugin/neosnippet.vim') == "" - return - endif + if globpath(&rtp, 'plugin/neosnippet.vim') == "" + return + endif - let g:neosnippet#enable_snipmate_compatibility = 1 + let g:neosnippet#enable_snipmate_compatibility = 1 - let gosnippets_dir = globpath(&rtp, 'gosnippets/snippets') - if type(g:neosnippet#snippets_directory) == type([]) - let g:neosnippet#snippets_directory += [gosnippets_dir] - elseif type(g:neosnippet#snippets_directory) == type("") - if strlen(g:neosnippet#snippets_directory) > 0 - let g:neosnippet#snippets_directory = g:neosnippet#snippets_directory . "," . gosnippets_dir - else - let g:neosnippet#snippets_directory = gosnippets_dir - endif - endif + let gosnippets_dir = globpath(&rtp, 'gosnippets/snippets') + if type(g:neosnippet#snippets_directory) == type([]) + let g:neosnippet#snippets_directory += [gosnippets_dir] + elseif type(g:neosnippet#snippets_directory) == type("") + if strlen(g:neosnippet#snippets_directory) > 0 + let g:neosnippet#snippets_directory = g:neosnippet#snippets_directory . "," . gosnippets_dir + else + let g:neosnippet#snippets_directory = gosnippets_dir + endif + endif endfunction if g:go_snippet_engine == "ultisnips" - call s:GoUltiSnips() + call s:GoUltiSnips() elseif g:go_snippet_engine == "neosnippet" - call s:GoNeosnippet() + call s:GoNeosnippet() endif + +" vim: sw=2 ts=2 et diff --git a/sources_non_forked/vim-go/ftplugin/go/tagbar.vim b/sources_non_forked/vim-go/ftplugin/go/tagbar.vim index ca5b1844..2d22fd7c 100644 --- a/sources_non_forked/vim-go/ftplugin/go/tagbar.vim +++ b/sources_non_forked/vim-go/ftplugin/go/tagbar.vim @@ -4,52 +4,54 @@ " Also make sure the ctags command exists " if !executable('ctags') - finish + finish elseif globpath(&rtp, 'plugin/tagbar.vim') == "" - finish + finish endif if !exists("g:go_gotags_bin") - let g:go_gotags_bin = "gotags" + let g:go_gotags_bin = "gotags" endif function! s:SetTagbar() - let bin_path = go#path#CheckBinPath(g:go_gotags_bin) - if empty(bin_path) - return - endif + let bin_path = go#path#CheckBinPath(g:go_gotags_bin) + if empty(bin_path) + return + endif - if !exists("g:tagbar_type_go") - let g:tagbar_type_go = { - \ 'ctagstype' : 'go', - \ 'kinds' : [ - \ 'p:package', - \ 'i:imports', - \ 'c:constants', - \ 'v:variables', - \ 't:types', - \ 'n:interfaces', - \ 'w:fields', - \ 'e:embedded', - \ 'm:methods', - \ 'r:constructor', - \ 'f:functions' - \ ], - \ 'sro' : '.', - \ 'kind2scope' : { - \ 't' : 'ctype', - \ 'n' : 'ntype' - \ }, - \ 'scope2kind' : { - \ 'ctype' : 't', - \ 'ntype' : 'n' - \ }, - \ 'ctagsbin' : expand(bin_path), - \ 'ctagsargs' : '-sort -silent' - \ } - endif + if !exists("g:tagbar_type_go") + let g:tagbar_type_go = { + \ 'ctagstype' : 'go', + \ 'kinds' : [ + \ 'p:package', + \ 'i:imports', + \ 'c:constants', + \ 'v:variables', + \ 't:types', + \ 'n:interfaces', + \ 'w:fields', + \ 'e:embedded', + \ 'm:methods', + \ 'r:constructor', + \ 'f:functions' + \ ], + \ 'sro' : '.', + \ 'kind2scope' : { + \ 't' : 'ctype', + \ 'n' : 'ntype' + \ }, + \ 'scope2kind' : { + \ 'ctype' : 't', + \ 'ntype' : 'n' + \ }, + \ 'ctagsbin' : bin_path, + \ 'ctagsargs' : '-sort -silent' + \ } + endif endfunction call s:SetTagbar() + +" vim: sw=2 ts=2 et diff --git a/sources_non_forked/vim-go/ftplugin/gohtmltmpl.vim b/sources_non_forked/vim-go/ftplugin/gohtmltmpl.vim index 56d414ff..ea0aacff 100644 --- a/sources_non_forked/vim-go/ftplugin/gohtmltmpl.vim +++ b/sources_non_forked/vim-go/ftplugin/gohtmltmpl.vim @@ -1,6 +1,7 @@ if exists("b:did_ftplugin") - finish + finish endif -let b:did_ftplugin = 1 -setlocal commentstring= +runtime! ftplugin/html.vim + +" vim: sw=2 ts=2 et diff --git a/sources_non_forked/vim-go/gosnippets/UltiSnips/go.snippets b/sources_non_forked/vim-go/gosnippets/UltiSnips/go.snippets index 905d1d42..1a78a04d 100644 --- a/sources_non_forked/vim-go/gosnippets/UltiSnips/go.snippets +++ b/sources_non_forked/vim-go/gosnippets/UltiSnips/go.snippets @@ -110,7 +110,7 @@ snippet gpl * You should have received a copy of the GNU General Public License * along with this program; if not, see . * -* Copyright (C) ${1:Author}, `strftime("%Y")` +* Copyright (C) ${1:Author}, `!v strftime("%Y")` */ ${0} endsnippet @@ -143,6 +143,13 @@ else { } endsnippet +# if inline error +snippet ife "If with inline erro" +if err := ${1:condition}; err != nil { + ${0:${VISUAL}} +} +endsnippet + # error snippet snippet errn "Error return " !b if err != nil { @@ -151,14 +158,15 @@ if err != nil { ${0} endsnippet -# error snippet -snippet errt "Error test fatal " !b +# error log snippet +snippet errl "Error with log.Fatal(err)" !b if err != nil { - t.Fatal(err) + log.Fatal(err) } ${0} endsnippet +# error multiple return snippet errn, "Error return with two return values" !b if err != nil { return ${1:nil}, err @@ -166,6 +174,23 @@ if err != nil { ${0} endsnippet +# error panic +snippet errp "Error panic" !b +if err != nil { + panic(${1}) +} +${0} +endsnippet + +# error test +snippet errt "Error test fatal " !b +if err != nil { + t.Fatal(err) +} +${0} +endsnippet + +# error handle snippet errh "Error handle and return" !b if err != nil { ${1} @@ -174,8 +199,14 @@ if err != nil { ${0} endsnippet +# json field tag snippet json "\`json:key\`" -\`json:"${1:keyName}"\` +\`json:"${1:`!v go#util#snippetcase(matchstr(getline("."), '\w\+'))`}"\` +endsnippet + +# yaml field tag +snippet yaml "\`yaml:key\`" +\`yaml:"${1:`!v go#util#snippetcase(matchstr(getline("."), '\w\+'))`}"\` endsnippet # fallthrough diff --git a/sources_non_forked/vim-go/gosnippets/snippets/go.snip b/sources_non_forked/vim-go/gosnippets/snippets/go.snip index c24d2750..9a480b07 100644 --- a/sources_non_forked/vim-go/gosnippets/snippets/go.snip +++ b/sources_non_forked/vim-go/gosnippets/snippets/go.snip @@ -118,6 +118,14 @@ snippet else else { ${0} } + +# if inline error +snippet ife +abbr if err := ...; err != nil { ... } + if err := ${1:condition}; err != nil { + ${0} + } + # error snippet snippet errn abbr if err != nil { ... } @@ -132,6 +140,13 @@ abbr if err != nil { ... } t.Fatal(err) } +# error snippet in log.Fatal +snippet errl +abbr if err != nil { ... } + if err != nil { + log.Fatal(err) + } + # error snippet with two return values snippet errn, abbr if err != nil { return [...], err } @@ -149,11 +164,24 @@ abbr if err != nil { return } } ${0} +# error snippet with panic +snippet errp +abbr if err != nil { ... } + if err != nil { + panic(${1}) + } + ${0} + # json snippet snippet json abbr \`json:key\` \`json:"${1:keyName}"\` +# yaml snippet +snippet yaml +abbr \`yaml:key\` + \`yaml:"${1:keyName}"\` + # fallthrough snippet ft abbr fallthrough diff --git a/sources_non_forked/vim-go/indent/go.vim b/sources_non_forked/vim-go/indent/go.vim index a3fa2b7a..ba99d54d 100644 --- a/sources_non_forked/vim-go/indent/go.vim +++ b/sources_non_forked/vim-go/indent/go.vim @@ -9,7 +9,7 @@ " - general line splits (line ends in an operator) if exists("b:did_indent") - finish + finish endif let b:did_indent = 1 @@ -21,58 +21,58 @@ setlocal indentexpr=GoIndent(v:lnum) setlocal indentkeys+=<:>,0=},0=) if exists("*GoIndent") - finish + finish endif " use shiftwidth function only if it's available if exists('*shiftwidth') - func s:sw() - return shiftwidth() - endfunc + func s:sw() + return shiftwidth() + endfunc else - func s:sw() - return &sw - endfunc + func s:sw() + return &sw + endfunc endif function! GoIndent(lnum) - let prevlnum = prevnonblank(a:lnum-1) - if prevlnum == 0 - " top of file - return 0 - endif + let prevlnum = prevnonblank(a:lnum-1) + if prevlnum == 0 + " top of file + return 0 + endif - " grab the previous and current line, stripping comments. - let prevl = substitute(getline(prevlnum), '//.*$', '', '') - let thisl = substitute(getline(a:lnum), '//.*$', '', '') - let previ = indent(prevlnum) + " grab the previous and current line, stripping comments. + let prevl = substitute(getline(prevlnum), '//.*$', '', '') + let thisl = substitute(getline(a:lnum), '//.*$', '', '') + let previ = indent(prevlnum) - let ind = previ + let ind = previ - if prevl =~ '[({]\s*$' - " previous line opened a block - let ind += s:sw() - endif - if prevl =~# '^\s*\(case .*\|default\):$' - " previous line is part of a switch statement - let ind += s:sw() - endif - " TODO: handle if the previous line is a label. + if prevl =~ '[({]\s*$' + " previous line opened a block + let ind += s:sw() + endif + if prevl =~# '^\s*\(case .*\|default\):$' + " previous line is part of a switch statement + let ind += s:sw() + endif + " TODO: handle if the previous line is a label. - if thisl =~ '^\s*[)}]' - " this line closed a block - let ind -= s:sw() - endif + if thisl =~ '^\s*[)}]' + " this line closed a block + let ind -= s:sw() + endif - " Colons are tricky. - " We want to outdent if it's part of a switch ("case foo:" or "default:"). - " We ignore trying to deal with jump labels because (a) they're rare, and - " (b) they're hard to disambiguate from a composite literal key. - if thisl =~# '^\s*\(case .*\|default\):$' - let ind -= s:sw() - endif + " Colons are tricky. + " We want to outdent if it's part of a switch ("case foo:" or "default:"). + " We ignore trying to deal with jump labels because (a) they're rare, and + " (b) they're hard to disambiguate from a composite literal key. + if thisl =~# '^\s*\(case .*\|default\):$' + let ind -= s:sw() + endif - return ind + return ind endfunction -" vim:ts=4:sw=4:et +" vim: sw=2 ts=2 et diff --git a/sources_non_forked/vim-go/indent/gohtmltmpl.vim b/sources_non_forked/vim-go/indent/gohtmltmpl.vim index 94ea135a..864913df 100644 --- a/sources_non_forked/vim-go/indent/gohtmltmpl.vim +++ b/sources_non_forked/vim-go/indent/gohtmltmpl.vim @@ -30,15 +30,17 @@ function! GetGoHTMLTmplIndent(lnum) " If need to indent based on last line let last_line = getline(a:lnum-1) - if last_line =~ '^\s*{{\s*\%(if\|else\|range\|with\|define\|block\).*}}' + if last_line =~ '^\s*{{-\=\s*\%(if\|else\|range\|with\|define\|block\).*}}' let ind += sw endif " End of FuncMap block let current_line = getline(a:lnum) - if current_line =~ '^\s*{{\s*\%(else\|end\).*}}' + if current_line =~ '^\s*{{-\=\s*\%(else\|end\).*}}' let ind -= sw endif return ind endfunction + +" vim: sw=2 ts=2 et diff --git a/sources_non_forked/vim-go/plugin/go.vim b/sources_non_forked/vim-go/plugin/go.vim index 779f4e1b..65fdb26a 100644 --- a/sources_non_forked/vim-go/plugin/go.vim +++ b/sources_non_forked/vim-go/plugin/go.vim @@ -1,177 +1,265 @@ " install necessary Go tools if exists("g:go_loaded_install") - finish + finish endif let g:go_loaded_install = 1 +" Not using the has('patch-7.4.1689') syntax because that wasn't added until +" 7.4.237, and we want to be sure this works for everyone (this is also why +" we're not using utils#EchoError()). +" +" Version 7.4.1689 was chosen because that's what the most recent Ubuntu LTS +" release (16.04) uses. +if + \ get(g:, 'go_version_warning', 1) != 0 && + \ (v:version < 704 || (v:version == 704 && !has('patch1689'))) + \ && !has('nvim') + echohl Error + echom "vim-go requires Vim 7.4.1689 or Neovim, but you're using an older version." + echom "Please update your Vim for the best vim-go experience." + echom "If you really want to continue you can set this to make the error go away:" + echom " let g:go_version_warning = 0" + echom "Note that some features may error out or behave incorrectly." + echom "Please do not report bugs unless you're using Vim 7.4.1689 or newer." + echohl None + + " Make sure people see this. + sleep 2 +endif + " these packages are used by vim-go and can be automatically installed if " needed by the user with GoInstallBinaries -let s:packages = [ - \ "github.com/nsf/gocode", - \ "github.com/alecthomas/gometalinter", - \ "golang.org/x/tools/cmd/goimports", - \ "golang.org/x/tools/cmd/guru", - \ "golang.org/x/tools/cmd/gorename", - \ "github.com/golang/lint/golint", - \ "github.com/rogpeppe/godef", - \ "github.com/kisielk/errcheck", - \ "github.com/jstemmer/gotags", - \ "github.com/klauspost/asmfmt/cmd/asmfmt", - \ "github.com/fatih/motion", - \ "github.com/zmb3/gogetdoc", - \ "github.com/josharian/impl", - \ ] +let s:packages = { + \ 'asmfmt': ['github.com/klauspost/asmfmt/cmd/asmfmt'], + \ 'errcheck': ['github.com/kisielk/errcheck'], + \ 'fillstruct': ['github.com/davidrjenni/reftools/cmd/fillstruct'], + \ 'gocode': ['github.com/nsf/gocode', {'windows': '-ldflags -H=windowsgui'}], + \ 'godef': ['github.com/rogpeppe/godef'], + \ 'gogetdoc': ['github.com/zmb3/gogetdoc'], + \ 'goimports': ['golang.org/x/tools/cmd/goimports'], + \ 'golint': ['github.com/golang/lint/golint'], + \ 'gometalinter': ['github.com/alecthomas/gometalinter'], + \ 'gomodifytags': ['github.com/fatih/gomodifytags'], + \ 'gorename': ['golang.org/x/tools/cmd/gorename'], + \ 'gotags': ['github.com/jstemmer/gotags'], + \ 'guru': ['golang.org/x/tools/cmd/guru'], + \ 'impl': ['github.com/josharian/impl'], + \ 'keyify': ['github.com/dominikh/go-tools/cmd/keyify'], + \ 'motion': ['github.com/fatih/motion'], +\ } " These commands are available on any filetypes -command! GoInstallBinaries call s:GoInstallBinaries(-1) -command! GoUpdateBinaries call s:GoInstallBinaries(1) +command! -nargs=* -complete=customlist,s:complete GoInstallBinaries call s:GoInstallBinaries(-1, ) +command! -nargs=* -complete=customlist,s:complete GoUpdateBinaries call s:GoInstallBinaries(1, ) command! -nargs=? -complete=dir GoPath call go#path#GoPath() +fun! s:complete(lead, cmdline, cursor) + return filter(keys(s:packages), 'strpart(v:val, 0, len(a:lead)) == a:lead') +endfun -" GoInstallBinaries downloads and install all necessary binaries stated in the -" packages variable. It uses by default $GOBIN or $GOPATH/bin as the binary -" target install directory. GoInstallBinaries doesn't install binaries if they -" exist, to update current binaries pass 1 to the argument. -function! s:GoInstallBinaries(updateBinaries) - if $GOPATH == "" - echohl Error - echomsg "vim.go: $GOPATH is not set" - echohl None +" GoInstallBinaries downloads and installs binaries defined in s:packages to +" $GOBIN or $GOPATH/bin. GoInstallBinaries will update already installed +" binaries only if updateBinaries = 1. By default, all packages in s:packages +" will be installed, but the set can be limited by passing the desired +" packages in the unnamed arguments. +function! s:GoInstallBinaries(updateBinaries, ...) + let err = s:CheckBinaries() + if err != 0 + return + endif + + if go#path#Default() == "" + echohl Error + echomsg "vim.go: $GOPATH is not set and 'go env GOPATH' returns empty" + echohl None + return + endif + + let go_bin_path = go#path#BinPath() + + " change $GOBIN so go get can automatically install to it + let $GOBIN = go_bin_path + + " old_path is used to restore users own path + let old_path = $PATH + + " vim's executable path is looking in PATH so add our go_bin path to it + let $PATH = go_bin_path . go#util#PathListSep() . $PATH + + " when shellslash is set on MS-* systems, shellescape puts single quotes + " around the output string. cmd on Windows does not handle single quotes + " correctly. Unsetting shellslash forces shellescape to use double quotes + " instead. + let resetshellslash = 0 + if has('win32') && &shellslash + let resetshellslash = 1 + set noshellslash + endif + + let cmd = "go get -v " + if get(g:, "go_get_update", 1) != 0 + let cmd .= "-u " + endif + + let s:go_version = matchstr(go#util#System("go version"), '\d.\d.\d') + + " https://github.com/golang/go/issues/10791 + if s:go_version > "1.4.0" && s:go_version < "1.5.0" + let cmd .= "-f " + endif + + " Filter packages from arguments (if any). + let l:packages = {} + if a:0 > 0 + for l:bin in a:000 + let l:pkg = get(s:packages, l:bin, []) + if len(l:pkg) == 0 + call go#util#EchoError('unknown binary: ' . l:bin) return - endif - - let err = s:CheckBinaries() - if err != 0 - return - endif - - let go_bin_path = go#path#BinPath() - - " change $GOBIN so go get can automatically install to it - let $GOBIN = go_bin_path - - " old_path is used to restore users own path - let old_path = $PATH - - " vim's executable path is looking in PATH so add our go_bin path to it - let $PATH = go_bin_path . go#util#PathListSep() . $PATH - - " when shellslash is set on MS-* systems, shellescape puts single quotes - " around the output string. cmd on Windows does not handle single quotes - " correctly. Unsetting shellslash forces shellescape to use double quotes - " instead. - let resetshellslash = 0 - if has('win32') && &shellslash - let resetshellslash = 1 - set noshellslash - endif - - let cmd = "go get -v " - if get(g:, "go_get_update", 1) != 0 - let cmd .= "-u " - endif - - let s:go_version = matchstr(go#util#System("go version"), '\d.\d.\d') - - " https://github.com/golang/go/issues/10791 - if s:go_version > "1.4.0" && s:go_version < "1.5.0" - let cmd .= "-f " - endif - - for pkg in s:packages - let basename = fnamemodify(pkg, ":t") - let binname = "go_" . basename . "_bin" - - let bin = basename - if exists("g:{binname}") - let bin = g:{binname} - endif - - if !executable(bin) || a:updateBinaries == 1 - if a:updateBinaries == 1 - echo "vim-go: Updating ". basename .". Reinstalling ". pkg . " to folder " . go_bin_path - else - echo "vim-go: ". basename ." not found. Installing ". pkg . " to folder " . go_bin_path - endif - - - let out = go#util#System(cmd . shellescape(pkg)) - if go#util#ShellError() != 0 - echo "Error installing ". pkg . ": " . out - endif - endif + endif + let l:packages[l:bin] = l:pkg endfor + else + let l:packages = s:packages + endif - " restore back! - let $PATH = old_path - if resetshellslash - set shellslash + let l:platform = '' + if go#util#IsWin() + let l:platform = 'windows' + endif + + for [binary, pkg] in items(l:packages) + let l:importPath = pkg[0] + let l:goGetFlags = len(pkg) > 1 ? get(pkg[1], l:platform, '') : '' + + let binname = "go_" . binary . "_bin" + + let bin = binary + if exists("g:{binname}") + let bin = g:{binname} endif + + if !executable(bin) || a:updateBinaries == 1 + if a:updateBinaries == 1 + echo "vim-go: Updating " . binary . ". Reinstalling ". importPath . " to folder " . go_bin_path + else + echo "vim-go: ". binary ." not found. Installing ". importPath . " to folder " . go_bin_path + endif + + let out = go#util#System(cmd . l:goGetFlags . shellescape(importPath)) + if go#util#ShellError() != 0 + echom "Error installing " . importPath . ": " . out + endif + endif + endfor + + " restore back! + let $PATH = old_path + if resetshellslash + set shellslash + endif endfunction " CheckBinaries checks if the necessary binaries to install the Go tool " commands are available. function! s:CheckBinaries() - if !executable('go') - echohl Error | echomsg "vim-go: go executable not found." | echohl None - return -1 - endif + if !executable('go') + echohl Error | echomsg "vim-go: go executable not found." | echohl None + return -1 + endif - if !executable('git') - echohl Error | echomsg "vim-go: git executable not found." | echohl None - return -1 - endif + if !executable('git') + echohl Error | echomsg "vim-go: git executable not found." | echohl None + return -1 + endif endfunction " Autocommands " ============================================================================ " function! s:echo_go_info() - if !exists('v:completed_item') || empty(v:completed_item) - return - endif - let item = v:completed_item + if !get(g:, "go_echo_go_info", 1) + return + endif - if !has_key(item, "info") - return - endif + if !exists('v:completed_item') || empty(v:completed_item) + return + endif + let item = v:completed_item - if empty(item.info) - return - endif + if !has_key(item, "info") + return + endif - redraws! | echo "vim-go: " | echohl Function | echon item.info | echohl None + if empty(item.info) + return + endif + + redraws! | echo "vim-go: " | echohl Function | echon item.info | echohl None +endfunction + +function! s:auto_type_info() + " GoInfo automatic update + if get(g:, "go_auto_type_info", 0) + call go#tool#Info(1) + endif +endfunction + +function! s:auto_sameids() + " GoSameId automatic update + if get(g:, "go_auto_sameids", 0) + call go#guru#SameIds() + endif +endfunction + +function! s:fmt_autosave() + " Go code formatting on save + if get(g:, "go_fmt_autosave", 1) + call go#fmt#Format(-1) + endif +endfunction + +function! s:asmfmt_autosave() + " Go asm formatting on save + if get(g:, "go_asmfmt_autosave", 0) + call go#asmfmt#Format() + endif +endfunction + +function! s:metalinter_autosave() + " run gometalinter on save + if get(g:, "go_metalinter_autosave", 0) + call go#lint#Gometa(1) + endif +endfunction + +function! s:template_autocreate() + " create new template from scratch + if get(g:, "go_template_autocreate", 1) + call go#template#create() + endif endfunction augroup vim-go - autocmd! + autocmd! - " GoInfo automatic update - if get(g:, "go_auto_type_info", 0) - autocmd CursorHold *.go nested call go#complete#Info(1) - endif + autocmd CursorHold *.go call s:auto_type_info() + autocmd CursorHold *.go call s:auto_sameids() - " Echo the identifier information when completion is done. Useful to see - " the signature of a function, etc... - if exists('##CompleteDone') - autocmd CompleteDone *.go nested call s:echo_go_info() - endif + " Echo the identifier information when completion is done. Useful to see + " the signature of a function, etc... + if exists('##CompleteDone') + autocmd CompleteDone *.go call s:echo_go_info() + endif - " Go code formatting on save - if get(g:, "go_fmt_autosave", 1) - autocmd BufWritePre *.go call go#fmt#Format(-1) - endif - - " Go asm formatting on save - if get(g:, "go_asmfmt_autosave", 1) - autocmd BufWritePre *.s call go#asmfmt#Format() - endif - - " run gometalinter on save - if get(g:, "go_metalinter_autosave", 0) - autocmd BufWritePost *.go call go#lint#Gometa(1) - endif + autocmd BufWritePre *.go call s:fmt_autosave() + autocmd BufWritePre *.s call s:asmfmt_autosave() + autocmd BufWritePost *.go call s:metalinter_autosave() + autocmd BufNewFile *.go call s:template_autocreate() + " clear SameIds when the buffer is unloaded so that loading another buffer + " in the same window doesn't highlight the most recently matched + " identifier's positions. + autocmd BufWinEnter *.go call go#guru#ClearSameIds() augroup END - -" vim:ts=4:sw=4:et +" vim: sw=2 ts=2 et diff --git a/sources_non_forked/vim-go/scripts/docker-test b/sources_non_forked/vim-go/scripts/docker-test new file mode 100644 index 00000000..2b56ad87 --- /dev/null +++ b/sources_non_forked/vim-go/scripts/docker-test @@ -0,0 +1,13 @@ +#!/bin/sh +# +# Run all tests inside a Docker container +# + +set -euC +vimgodir=$(cd -P "$(dirname "$0")/.." > /dev/null && pwd) +cd "$vimgodir" + +docker build --tag vim-go-test . +docker run --rm vim-go-test + +# vim:ts=2:sts=2:sw=2:et diff --git a/sources_non_forked/vim-go/scripts/install-vim b/sources_non_forked/vim-go/scripts/install-vim new file mode 100644 index 00000000..7b4e7a44 --- /dev/null +++ b/sources_non_forked/vim-go/scripts/install-vim @@ -0,0 +1,112 @@ +#!/bin/sh +# +# Install and setup a Vim or Neovim for running tests. +# This should work on both Travis and people's desktop computers, and be 100% +# independent from any system installed Vim. +# +# It will echo the full path to a Vim binary, e.g.: +# /some/path/src/vim + +set -euC + +vimgodir=$(cd -P "$(dirname "$0")/.." > /dev/null && pwd) +cd "$vimgodir" + +vim=${1:-} + +case "$vim" in + "vim-7.4") + # This is what the most recent Ubuntu LTS (16.04) ships with. + tag="v7.4.1689" + giturl="https://github.com/vim/vim" + ;; + + "vim-8.0") + # This follows the version in Arch Linux. Vim's master branch isn't always + # stable, and we don't want to have the build fail because Vim introduced a + # bug. + tag="v8.0.1176" + giturl="https://github.com/vim/vim" + ;; + + "nvim") + # Use latest stable version. + tag="v0.2.0" + giturl="https://github.com/neovim/neovim" + ;; + + *) + echo "unknown version: '${1:-}'" + echo "First argument must be 'vim-7.4', 'vim-8.0', or 'nvim'." + exit 1 + ;; +esac + +srcdir="/tmp/vim-go-test/$1-src" +installdir="/tmp/vim-go-test/$1-install" + +# Use cached installdir. +if [ -d "$installdir" ]; then + echo "$installdir exists; skipping build." + + # The ./scripts/test script relies on this. + echo "installed to: $installdir" + exit 0 +fi + +mkdir -p "$srcdir" +cd "$srcdir" + +# Neovim build requires more deps than Vim and is annoying, so we use the +# binary. +# 0.2.0 doesn't have a binary build for Linux, so we use 0.2.1-dev for now. +if [ "$1" = "nvim" ]; then + + # TODO: Use macOS binaries on macOS + curl -Ls https://github.com/neovim/neovim/releases/download/nightly/nvim-linux64.tar.gz | + tar xzf - -C /tmp/vim-go-test/ + mv /tmp/vim-go-test/nvim-linux64 /tmp/vim-go-test/nvim-install + mkdir -p "$installdir/share/nvim/runtime/pack/vim-go/start" + ln -s "$vimgodir" "$installdir/share/nvim/runtime/pack/vim-go/start/vim-go" + + # Consistent paths makes calling things easier. + mv "$installdir/bin/nvim" "$installdir/bin/vim" + mkdir -p "$installdir/share/vim/vimgo/pack" + ln -s "$installdir/share/nvim/runtime/pack/vim-go" "$installdir/share/vim/vimgo/pack/vim-go" + +# Build Vim from source. +else + if [ -d "$srcdir/.git" ]; then + echo "Skipping clone as $srcdir/.git exists" + else + echo "Cloning $tag from $giturl" + git clone --branch "$tag" --depth 1 "$giturl" "$srcdir" + fi + + ./configure --prefix="$installdir" --with-features=huge --disable-gui + make install + mkdir -p "$installdir/share/vim/vimgo/pack/vim-go/start" + ln -s "$vimgodir" "$installdir/share/vim/vimgo/pack/vim-go/start/vim-go" +fi + +# Make sure all Go tools and other dependencies are installed. +echo "Installing Go binaries" +export GOPATH=$installdir +export PATH=${GOPATH}/bin:$PATH +"$vimgodir/scripts/run-vim" $vim +':silent :GoUpdateBinaries' +':qa' + +echo "Installing lint tools" +( + mkdir -p "$installdir/share/vim/vimgo/pack/vim-go/start/" + cd "$installdir/share/vim/vimgo/pack/vim-go/start/" + [ -d "vim-vimhelplint" ] || git clone --depth 1 --quiet https://github.com/machakann/vim-vimhelplint + [ -d "vim-vimlparser" ] || git clone --depth 1 --quiet https://github.com/ynkdir/vim-vimlparser + [ -d "vim-vimlint" ] || git clone --depth 1 --quiet https://github.com/syngan/vim-vimlint +) + +# Don't really need source after successful install. +rm -rf "$srcdir" + +echo "installed to: $installdir" + +# vim:ts=2:sts=2:sw=2:et diff --git a/sources_non_forked/vim-go/scripts/lint b/sources_non_forked/vim-go/scripts/lint new file mode 100644 index 00000000..553413a4 --- /dev/null +++ b/sources_non_forked/vim-go/scripts/lint @@ -0,0 +1,88 @@ +#!/bin/sh +# +# Run all linting tools. +# + +set -euC +vimgodir=$(cd -P "$(dirname "$0")/.." > /dev/null && pwd) +cd "$vimgodir" + +### Setup Vim and other dependencies. +##################################### +if [ -z "${1:-}" ]; then + echo "unknown version: '${1:-}'" + echo "First argument must be 'vim-7.4', 'vim-8.0', or 'nvim'." + exit 1 +fi + +vim=$1 +vimdir="/tmp/vim-go-test/$vim-install" +export GOPATH=$vimdir +export PATH=${GOPATH}/bin:$PATH + +if [ ! -f "$vimdir/bin/vim" ]; then + echo "$vimdir/bin/vim doesn't exist; did you install it with the install-vim script?" + exit 1 +fi + +### Run vint +############ +failed=0 +printf "Running vint ... " +if [ -x "$(command -v vint)" ]; then + lint=$(vint "$vimgodir" 2>&1 ||:) + if [ -n "$lint" ]; then + echo "FAILED" + echo "$lint" + echo + failed=6 + else + echo "PASSED" + fi +else + echo "SKIPPED" + echo "'vint' binary not found; use 'pip install vim-vint' to install it." +fi + +### Run vim-vimlint +################### +printf "Running vim-vimlint ... " +lint=$(sh "$vimdir/share/vim/vimgo/pack/vim-go/start/vim-vimlint/bin/vimlint.sh" \ + -p "$vimdir/share/vim/vimgo/pack/vim-go/start/vim-vimlparser" \ + -l "$vimdir/share/vim/vimgo/pack/vim-go/start/vim-vimlint" \ + -u \ + -c func_abort=1 \ + -e EVL110=1 -e EVL103=1 -e EVL104=1 -e EVL102=1 \ + "$vimgodir" \ + 2>&1 ||:) +if [ -n "$lint" ]; then + echo "FAILED" + echo "$lint" + echo + failed=6 +else + echo "PASSED" +fi + +### Run vimhelplint. +#################### +printf "Running vimhelplint ... " + +# set modeline explicitly so that the modeline will be respected when run as root. +lint=$($vimdir/bin/vim -esNR \ + --cmd "set rtp+=$vimdir/share/vim/vimgo/pack/vim-go/start/vim-vimhelplint/" \ + --cmd 'set modeline' \ + +'filetype plugin on' \ + +"e $vimgodir/doc/vim-go.txt" \ + +'verbose VimhelpLintEcho' \ + +q \ + 2>&1 ||:) +if [ "$lint" ]; then + echo "FAILED" + echo "$lint" + failed=6 +else + echo "PASSED" +fi + +exit "$failed" diff --git a/sources_non_forked/vim-go/scripts/run-vim b/sources_non_forked/vim-go/scripts/run-vim new file mode 100644 index 00000000..baf0be3e --- /dev/null +++ b/sources_non_forked/vim-go/scripts/run-vim @@ -0,0 +1,33 @@ +#!/bin/sh +# +# Run a "bare" Vim with just vim-go and ignoring ~/.vim +# + +set -euC +vimgodir=$(cd -P "$(dirname "$0")/.." > /dev/null && pwd) +cd "$vimgodir" + +if [ -z "${1:-}" ]; then + echo "unknown version: '${1:-}'" + echo "First argument must be 'vim-7.4', 'vim-8.0', or 'nvim'." + exit 1 +fi + +dir="/tmp/vim-go-test/$1-install" +export GOPATH=$dir +export PATH=${GOPATH}/bin:$PATH +shift + +if [ ! -f "$dir/bin/vim" ]; then + echo "$dir/bin/vim doesn't exist; did you install it with the install-vim script?" + exit 1 +fi + +$dir/bin/vim --noplugin -u NONE -N \ + +"set shm+=WAFI rtp=$dir/share/vim/vimgo packpath=$dir/share/vim/vimgo,$vimgodir" \ + +'filetype plugin indent on' \ + +'packloadall!' \ + "$@" + + +# vim:ts=2:sts=2:sw=2:et diff --git a/sources_non_forked/vim-go/scripts/runtest.vim b/sources_non_forked/vim-go/scripts/runtest.vim new file mode 100644 index 00000000..2199a457 --- /dev/null +++ b/sources_non_forked/vim-go/scripts/runtest.vim @@ -0,0 +1,87 @@ +" Make sure some options are set to sane defaults and output all messages in +" English. + +" vint: -ProhibitSetNoCompatible +set nocompatible nomore shellslash encoding=utf-8 shortmess+=WIF +lang mess C + +" Initialize variables. +let s:total_started = reltime() +let s:fail = 0 +let s:done = 0 +let s:logs = [] +let s:gopath = $GOPATH + +" Source the passed test file. +source % + +" cd into the folder of the test file. +let s:cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd ' +let s:testfile = expand('%:t') +execute s:cd . expand('%:p:h') + +" Export root path to vim-go dir. +let g:vim_go_root = fnamemodify(getcwd(), ':p') + +" Get a list of all Test_ functions for the given file. +redir @q + silent function /^Test_ +redir END +let s:tests = split(substitute(@q, 'function \(\k*()\)', '\1', 'g')) + +" Iterate over all tests and execute them. +for s:test in sort(s:tests) + " Since we extract the tests from a regexp the "abort" keyword is also in the + " list, which is not a test name :-) + if s:test == 'abort' + continue + endif + + let s:started = reltime() + call add(s:logs, printf("=== RUN %s", s:test[:-3])) + exe 'call ' . s:test + + " Restore GOPATH after each test. + let $GOPATH = s:gopath + + let s:elapsed_time = substitute(reltimestr(reltime(s:started)), '^\s*\(.\{-}\)\s*$', '\1', '') + let s:done += 1 + + if len(v:errors) > 0 + let s:fail += 1 + call add(s:logs, printf("--- FAIL %s (%ss)", s:test[:-3], s:elapsed_time)) + call extend(s:logs, map(v:errors, '" ". v:val')) + + " Reset so we can capture failures of the next test. + let v:errors = [] + else + call add(s:logs, printf("--- PASS %s (%ss)", s:test[:-3], s:elapsed_time)) + endif +endfor + +" Create an empty fail to indicate that at least one test failed. +if s:fail > 0 + split /tmp/vim-go-test/FAILED + silent write +endif + +let s:total_elapsed_time = substitute(reltimestr(reltime(s:total_started)), '^\s*\(.\{-}\)\s*$', '\1', '') + +" Add all messages (usually errors). +redir => s:mess + silent messages +redir END +let s:logs = s:logs + filter(split(s:mess, "\n"), 'v:val !~ "^Messages maintainer"') + +" Also store all internal messages from s:logs as well. +silent! split /tmp/vim-go-test/test.tmp +call append(line('$'), s:logs) +call append(line('$'), printf("%s%s %s / %s tests", + \ (s:fail > 0 ? 'FAIL ' : 'ok '), + \ s:testfile, s:total_elapsed_time, s:done)) +silent! write + +" Our work here is done. +qall! + +" vim:ts=2:sts=2:sw=2:et diff --git a/sources_non_forked/vim-go/scripts/test b/sources_non_forked/vim-go/scripts/test new file mode 100644 index 00000000..8676505f --- /dev/null +++ b/sources_non_forked/vim-go/scripts/test @@ -0,0 +1,51 @@ +#!/bin/sh +# +# Run all tests. +# + +set -euC +vimgodir=$(cd -P "$(dirname "$0")/.." > /dev/null && pwd) +cd "$vimgodir" + +### Setup Vim and other dependencies. +##################################### +if [ -z "${1:-}" ]; then + echo "unknown version: '${1:-}'" + echo "First argument must be 'vim-7.4', 'vim-8.0', or 'nvim'." + exit 1 +fi + +vim=$1 +vimdir="/tmp/vim-go-test/$vim-install" +export GOPATH=$vimdir +export PATH=${GOPATH}/bin:$PATH + +if [ ! -f "$vimdir/bin/vim" ]; then + echo "$vimdir/bin/vim doesn't exist; did you install it with the install-vim script?" + exit 1 +fi + +### Run tests. +############## +# Clean stale log file. +[ -f '/tmp/vim-go-test/test.log' ] && rm '/tmp/vim-go-test/test.log' +[ -f '/tmp/vim-go-test/FAILED' ] && rm '/tmp/vim-go-test/FAILED' + +# Run the actual tests. +fail=0 +for test_file in "$vimgodir"/autoload/go/*_test.vim; do + "$vimgodir/scripts/run-vim" $vim -e +"silent e $test_file" -S ./scripts/runtest.vim + + # Append logs + cat '/tmp/vim-go-test/test.tmp' | tee '/tmp/vim-go-test/test.log' + rm '/tmp/vim-go-test/test.tmp' +done + +echo +if [ -f "/tmp/vim-go-test/FAILED" ]; then + echo 2>&1 "Some tests FAILED" + exit 1 +fi +echo 2>&1 "All tests PASSED" + +# vim:ts=2:sts=2:sw=2:et diff --git a/sources_non_forked/vim-go/scripts/test.sh b/sources_non_forked/vim-go/scripts/test.sh deleted file mode 100644 index d8a5b895..00000000 --- a/sources_non_forked/vim-go/scripts/test.sh +++ /dev/null @@ -1,78 +0,0 @@ -#!/bin/bash -e -# -# Copyright 2012 The Go Authors. All rights reserved. -# Use of this source code is governed by a BSD-style -# license that can be found in the LICENSE file. -# -# Tests for import.vim. - -cd $(dirname $0) - -cat > base.go <&1 -n "$1: " - vim -e -s -u /dev/null -U /dev/null --noplugin -c "source import.vim" \ - -c "$1" -c 'wq! test.go' base.go - # ensure blank lines are treated correctly - if ! gofmt test.go | cmp test.go -; then - echo 2>&1 "gofmt conflict" - gofmt test.go | diff -u test.go - | sed "s/^/ /" 2>&1 - fail=1 - return - fi - if ! [[ $(cat test.go) =~ $2 ]]; then - echo 2>&1 "$2 did not match" - cat test.go | sed "s/^/ /" 2>&1 - fail=1 - return - fi - echo 2>&1 "ok" -} - -# Tests for Import - -test_one "Import baz" '"baz".*"bytes"' -test_one "Import io/ioutil" '"io".*"io/ioutil".*"net"' -test_one "Import myc" '"io".*"myc".*"net"' # prefix of a site prefix -test_one "Import nat" '"io".*"nat".*"net"' -test_one "Import net/http" '"net".*"net/http".*"mycorp/foo"' -test_one "Import zoo" '"net".*"zoo".*"mycorp/foo"' -test_one "Import mycorp/bar" '"net".*"mycorp/bar".*"mycorp/foo"' -test_one "Import mycorp/goo" '"net".*"mycorp/foo".*"mycorp/goo"' - -# Tests for Drop - -cat > base.go <&1 "FAIL" - exit 1 -fi -echo 2>&1 "PASS" diff --git a/sources_non_forked/vim-go/syntax/go.vim b/sources_non_forked/vim-go/syntax/go.vim index f9cd2cba..783912d5 100644 --- a/sources_non_forked/vim-go/syntax/go.vim +++ b/sources_non_forked/vim-go/syntax/go.vim @@ -3,56 +3,31 @@ " license that can be found in the LICENSE file. " " go.vim: Vim syntax file for Go. -" -" Options: -" There are some options for customizing the highlighting; the recommended -" settings are the default values, but you can write: -" let OPTION_NAME = 0 -" in your ~/.vimrc file to disable particular options. You can also write: -" let OPTION_NAME = 1 -" to enable particular options. -" At present, all options default to on, except highlight of: -" functions, methods, structs, operators, build constraints and interfaces. -" -" - go_highlight_array_whitespace_error -" Highlights white space after "[]". -" - go_highlight_chan_whitespace_error -" Highlights white space around the communications operator that don't follow -" the standard style. -" - go_highlight_extra_types -" Highlights commonly used library types (io.Reader, etc.). -" - go_highlight_space_tab_error -" Highlights instances of tabs following spaces. -" - go_highlight_trailing_whitespace_error -" Highlights trailing white space. -" - go_highlight_string_spellcheck -" Specifies that strings should be spell checked -" - go_highlight_format_strings -" Highlights printf-style operators inside string literals. " Quit when a (custom) syntax file was already loaded if exists("b:current_syntax") finish endif +" Set settings to default values. if !exists("g:go_highlight_array_whitespace_error") - let g:go_highlight_array_whitespace_error = 1 + let g:go_highlight_array_whitespace_error = 0 endif if !exists("g:go_highlight_chan_whitespace_error") - let g:go_highlight_chan_whitespace_error = 1 + let g:go_highlight_chan_whitespace_error = 0 endif if !exists("g:go_highlight_extra_types") - let g:go_highlight_extra_types = 1 + let g:go_highlight_extra_types = 0 endif if !exists("g:go_highlight_space_tab_error") - let g:go_highlight_space_tab_error = 1 + let g:go_highlight_space_tab_error = 0 endif if !exists("g:go_highlight_trailing_whitespace_error") - let g:go_highlight_trailing_whitespace_error = 1 + let g:go_highlight_trailing_whitespace_error = 0 endif if !exists("g:go_highlight_operators") @@ -68,15 +43,11 @@ if !exists("g:go_highlight_methods") endif if !exists("g:go_highlight_fields") - let g:go_highlight_fields = 0 + let g:go_highlight_fields = 0 endif -if !exists("g:go_highlight_structs") - let g:go_highlight_structs = 0 -endif - -if !exists("g:go_highlight_interfaces") - let g:go_highlight_interfaces = 0 +if !exists("g:go_highlight_types") + let g:go_highlight_types = 0 endif if !exists("g:go_highlight_build_constraints") @@ -95,15 +66,53 @@ if !exists("g:go_highlight_generate_tags") let g:go_highlight_generate_tags = 0 endif +if !exists("g:go_highlight_variable_assignments") + let g:go_highlight_variable_assignments = 0 +endif + +if !exists("g:go_highlight_variable_declarations") + let g:go_highlight_variable_declarations = 0 +endif + +let s:fold_block = 1 +let s:fold_import = 1 +let s:fold_varconst = 1 +let s:fold_package_comment = 1 +let s:fold_comment = 0 + +if exists("g:go_fold_enable") + " Enabled by default. + if index(g:go_fold_enable, 'block') == -1 + let s:fold_block = 0 + endif + if index(g:go_fold_enable, 'import') == -1 + let s:fold_import = 0 + endif + if index(g:go_fold_enable, 'varconst') == -1 + let s:fold_varconst = 0 + endif + if index(g:go_fold_enable, 'package_comment') == -1 + let s:fold_package_comment = 0 + endif + + " Disabled by default. + if index(g:go_fold_enable, 'comment') > -1 + let s:fold_comment = 1 + endif +endif + syn case match -syn keyword goDirective package import -syn keyword goDeclaration var const type -syn keyword goDeclType struct interface +syn keyword goPackage package +syn keyword goImport import contained +syn keyword goVar var contained +syn keyword goConst const contained -hi def link goDirective Statement +hi def link goPackage Statement +hi def link goImport Statement +hi def link goVar Keyword +hi def link goConst Keyword hi def link goDeclaration Keyword -hi def link goDeclType Keyword " Keywords within functions syn keyword goStatement defer go goto return break continue fallthrough @@ -129,24 +138,28 @@ hi def link goUnsignedInts Type hi def link goFloats Type hi def link goComplexes Type -" Treat func specially: it's a declaration at the start of a line, but a type -" elsewhere. Order matters here. -syn match goDeclaration /\/ - " Predefined functions and values -syn match goBuiltins /\<\v(append|cap|close|complex|copy|delete|imag|len)\ze\(/ -syn match goBuiltins /\<\v(make|new|panic|print|println|real|recover)\ze\(/ -syn keyword goBoolean iota true false nil +syn match goBuiltins /\<\v(append|cap|close|complex|copy|delete|imag|len)\ze\(/ +syn match goBuiltins /\<\v(make|new|panic|print|println|real|recover)\ze\(/ +syn keyword goBoolean true false +syn keyword goPredefinedIdentifiers nil iota -hi def link goBuiltins Keyword -hi def link goBoolean Boolean +hi def link goBuiltins Keyword +hi def link goBoolean Boolean +hi def link goPredefinedIdentifiers goBoolean " Comments; their contents syn keyword goTodo contained TODO FIXME XXX BUG syn cluster goCommentGroup contains=goTodo -syn region goComment start="/\*" end="\*/" contains=@goCommentGroup,@Spell + syn region goComment start="//" end="$" contains=goGenerate,@goCommentGroup,@Spell +if s:fold_comment + syn region goComment start="/\*" end="\*/" contains=@goCommentGroup,@Spell fold + syn match goComment "\v(^\s*//.*\n)+" contains=goGenerate,@goCommentGroup,@Spell fold +else + syn region goComment start="/\*" end="\*/" contains=@goCommentGroup,@Spell +endif hi def link goComment Comment hi def link goTodo Todo @@ -185,7 +198,7 @@ else endif if g:go_highlight_format_strings != 0 - syn match goFormatSpecifier /%[-#0 +]*\%(\*\|\d\+\)\=\%(\.\%(\*\|\d\+\)\)*[vTtbcdoqxXUeEfgGsp]/ contained containedin=goString + syn match goFormatSpecifier /\([^%]\(%%\)*\)\@<=%[-#0 +]*\%(\*\|\d\+\)\=\%(\.\%(\*\|\d\+\)\)*[vTtbcdoqxXUeEfgGsp]/ contained containedin=goString hi def link goFormatSpecifier goSpecialString endif @@ -199,8 +212,35 @@ syn region goCharacter start=+'+ skip=+\\\\\|\\'+ end=+'+ contains= hi def link goCharacter Character " Regions -syn region goBlock start="{" end="}" transparent fold syn region goParen start='(' end=')' transparent +if s:fold_block + syn region goBlock start="{" end="}" transparent fold +else + syn region goBlock start="{" end="}" transparent +endif + +" import +if s:fold_import + syn region goImport start='import (' end=')' transparent fold contains=goImport,goString,goComment +else + syn region goImport start='import (' end=')' transparent contains=goImport,goString,goComment +endif + +" var, const +if s:fold_varconst + syn region goVar start='var (' end='^\s*)$' transparent fold + \ contains=ALLBUT,goParen,goBlock,goFunction,goTypeName,goReceiverType,goReceiverVar + syn region goConst start='const (' end='^\s*)$' transparent fold + \ contains=ALLBUT,goParen,goBlock,goFunction,goTypeName,goReceiverType,goReceiverVar +else + syn region goVar start='var (' end='^\s*)$' transparent + \ contains=ALLBUT,goParen,goBlock,goFunction,goTypeName,goReceiverType,goReceiverVar + syn region goConst start='const (' end='^\s*)$' transparent + \ contains=ALLBUT,goParen,goBlock,goFunction,goTypeName,goReceiverType,goReceiverVar +endif + +" Single-line var, const, and import. +syn match goSingleDecl /\(import\|var\|const\) [^(]\@=/ contains=goImport,goVar,goConst " Integers syn match goDecimalInt "\<-\=\d\+\%([Ee][-+]\=\d\+\)\=\>" @@ -281,6 +321,7 @@ hi def link goSpaceError Error syn keyword goTodo contained NOTE hi def link goTodo Todo +syn match goVarArgs /\.\.\./ " Operators; if g:go_highlight_operators != 0 @@ -295,78 +336,123 @@ if g:go_highlight_operators != 0 " match remaining two-char operators: := && || <- ++ -- syn match goOperator /:=\|||\|<-\|++\|--/ " match ... - syn match goOperator /\.\.\./ + + hi def link goPointerOperator goOperator + hi def link goVarArgs goOperator endif hi def link goOperator Operator " Functions; if g:go_highlight_functions != 0 - syn match goFunction /\(func\s\+\)\@<=\w\+\((\)\@=/ - syn match goFunction /\()\s\+\)\@<=\w\+\((\)\@=/ + syn match goDeclaration /\/ nextgroup=goReceiver,goFunction skipwhite skipnl + syn match goReceiver /(\(\w\|[ *]\)\+)/ contained nextgroup=goFunction contains=goReceiverVar skipwhite skipnl + syn match goReceiverVar /\w\+/ nextgroup=goPointerOperator,goReceiverType skipwhite skipnl contained + syn match goPointerOperator /\*/ nextgroup=goReceiverType contained skipwhite skipnl + syn match goReceiverType /\w\+/ contained + syn match goFunction /\w\+/ contained + syn match goFunctionCall /\w\+\ze(/ contains=GoBuiltins,goDeclaration +else + syn keyword goDeclaration func endif hi def link goFunction Function +hi def link goFunctionCall Type " Methods; if g:go_highlight_methods != 0 - syn match goMethod /\(\.\)\@<=\w\+\((\)\@=/ + syn match goMethodCall /\.\w\+\ze(/hs=s+1 endif -hi def link goMethod Type +hi def link goMethodCall Type " Fields; if g:go_highlight_fields != 0 - syn match goField /\(\.\)\@<=\a\+\([\ \n\r\:\)]\)\@=/ + syn match goField /\.\w\+\([.\ \n\r\:\)\[,]\)\@=/hs=s+1 endif -hi def link goField Type +hi def link goField Identifier -" Structs; -if g:go_highlight_structs != 0 - syn match goStruct /\(.\)\@<=\w\+\({\)\@=/ - syn match goStructDef /\(type\s\+\)\@<=\w\+\(\s\+struct\s\+{\)\@=/ +" Structs & Interfaces; +if g:go_highlight_types != 0 + syn match goTypeConstructor /\<\w\+{\@=/ + syn match goTypeDecl /\/ nextgroup=goTypeName skipwhite skipnl + syn match goTypeName /\w\+/ contained nextgroup=goDeclType skipwhite skipnl + syn match goDeclType /\<\(interface\|struct\)\>/ skipwhite skipnl + hi def link goReceiverType Type +else + syn keyword goDeclType struct interface + syn keyword goDeclaration type endif -hi def link goStruct Function -hi def link goStructDef Function +hi def link goTypeConstructor Type +hi def link goTypeName Type +hi def link goTypeDecl Keyword +hi def link goDeclType Keyword -" Interfaces; -if g:go_highlight_interfaces != 0 - syn match goInterface /\(.\)\@<=\w\+\({\)\@=/ - syn match goInterfaceDef /\(type\s\+\)\@<=\w\+\(\s\+interface\s\+{\)\@=/ +" Variable Assignments +if g:go_highlight_variable_assignments != 0 + syn match goVarAssign /\v[_.[:alnum:]]+(,\s*[_.[:alnum:]]+)*\ze(\s*([-^+|^\/%&]|\*|\<\<|\>\>|\&\^)?\=[^=])/ + hi def link goVarAssign Special +endif + +" Variable Declarations +if g:go_highlight_variable_declarations != 0 + syn match goVarDefs /\v\w+(,\s*\w+)*\ze(\s*:\=)/ + hi def link goVarDefs Special endif -hi def link goInterface Function -hi def link goInterfaceDef Function " Build Constraints if g:go_highlight_build_constraints != 0 - syn match goBuildKeyword display contained "+build" - " Highlight the known values of GOOS, GOARCH, and other +build options. - syn keyword goBuildDirectives contained - \ android darwin dragonfly freebsd linux nacl netbsd openbsd plan9 - \ solaris windows 386 amd64 amd64p32 arm armbe arm64 arm64be ppc64 - \ ppc64le mips mipsle mips64 mips64le mips64p32 mips64p32le ppc - \ s390 s390x sparc sparc64 cgo ignore race + syn match goBuildKeyword display contained "+build" + " Highlight the known values of GOOS, GOARCH, and other +build options. + syn keyword goBuildDirectives contained + \ android darwin dragonfly freebsd linux nacl netbsd openbsd plan9 + \ solaris windows 386 amd64 amd64p32 arm armbe arm64 arm64be ppc64 + \ ppc64le mips mipsle mips64 mips64le mips64p32 mips64p32le ppc + \ s390 s390x sparc sparc64 cgo ignore race - " Other words in the build directive are build tags not listed above, so - " avoid highlighting them as comments by using a matchgroup just for the - " start of the comment. - " The rs=s+2 option lets the \s*+build portion be part of the inner region - " instead of the matchgroup so it will be highlighted as a goBuildKeyword. - syn region goBuildComment matchgroup=goBuildCommentStart - \ start="//\s*+build\s"rs=s+2 end="$" - \ contains=goBuildKeyword,goBuildDirectives - hi def link goBuildCommentStart Comment - hi def link goBuildDirectives Type - hi def link goBuildKeyword PreProc - - " One or more line comments that are followed immediately by a "package" - " declaration are treated like package documentation, so these must be - " matched as comments to avoid looking like working build constraints. - " The he, me, and re options let the "package" itself be highlighted by - " the usual rules. - syn region goPackageComment start=/\v(\/\/.*\n)+\s*package/ - \ end=/\v\n\s*package/he=e-7,me=e-7,re=e-7 - \ contains=@goCommentGroup,@Spell - hi def link goPackageComment Comment + " Other words in the build directive are build tags not listed above, so + " avoid highlighting them as comments by using a matchgroup just for the + " start of the comment. + " The rs=s+2 option lets the \s*+build portion be part of the inner region + " instead of the matchgroup so it will be highlighted as a goBuildKeyword. + syn region goBuildComment matchgroup=goBuildCommentStart + \ start="//\s*+build\s"rs=s+2 end="$" + \ contains=goBuildKeyword,goBuildDirectives + hi def link goBuildCommentStart Comment + hi def link goBuildDirectives Type + hi def link goBuildKeyword PreProc endif +if g:go_highlight_build_constraints != 0 || s:fold_package_comment + " One or more line comments that are followed immediately by a "package" + " declaration are treated like package documentation, so these must be + " matched as comments to avoid looking like working build constraints. + " The he, me, and re options let the "package" itself be highlighted by + " the usual rules. + exe 'syn region goPackageComment start=/\v(\/\/.*\n)+\s*package/' + \ . ' end=/\v\n\s*package/he=e-7,me=e-7,re=e-7' + \ . ' contains=@goCommentGroup,@Spell' + \ . (s:fold_package_comment ? ' fold' : '') + exe 'syn region goPackageComment start=/\v\/\*.*\n(.*\n)*\s*\*\/\npackage/' + \ . ' end=/\v\n\s*package/he=e-7,me=e-7,re=e-7' + \ . ' contains=@goCommentGroup,@Spell' + \ . (s:fold_package_comment ? ' fold' : '') + hi def link goPackageComment Comment +endif + +" :GoCoverage commands +hi def link goCoverageNormalText Comment + +function! s:hi() + hi def link goSameId Search + + " :GoCoverage commands + hi def goCoverageCovered ctermfg=green guifg=#A6E22E + hi def goCoverageUncover ctermfg=red guifg=#F92672 +endfunction + +augroup vim-go-hi + autocmd! + autocmd ColorScheme * call s:hi() +augroup end +call s:hi() " Search backwards for a global declaration to start processing the syntax. "syn sync match goSync grouphere NONE /^\(const\|var\|type\|func\)\>/ @@ -376,3 +462,5 @@ endif syn sync minlines=500 let b:current_syntax = "go" + +" vim: sw=2 ts=2 et diff --git a/sources_non_forked/vim-go/syntax/godefstack.vim b/sources_non_forked/vim-go/syntax/godefstack.vim index 7574c21d..e4eefff4 100644 --- a/sources_non_forked/vim-go/syntax/godefstack.vim +++ b/sources_non_forked/vim-go/syntax/godefstack.vim @@ -1,5 +1,5 @@ if exists("b:current_syntax") - finish + finish endif syn match godefStackComment '^".*' @@ -16,3 +16,5 @@ hi def link godefStackComment Comment hi def link godefStackCurrentPosition Special hi def link godefStackFilename Directory hi def link godefStackEntryLocationNumber LineNr + +" vim: sw=2 ts=2 et diff --git a/sources_non_forked/vim-go/syntax/gohtmltmpl.vim b/sources_non_forked/vim-go/syntax/gohtmltmpl.vim index 5aa6c98d..fd2612a7 100644 --- a/sources_non_forked/vim-go/syntax/gohtmltmpl.vim +++ b/sources_non_forked/vim-go/syntax/gohtmltmpl.vim @@ -1,9 +1,9 @@ if exists("b:current_syntax") - finish + finish endif -if !exists("main_syntax") - let main_syntax = 'html' +if !exists("g:main_syntax") + let g:main_syntax = 'html' endif runtime! syntax/gotexttmpl.vim @@ -12,4 +12,4 @@ unlet b:current_syntax let b:current_syntax = "gohtmltmpl" -" vim:ts=4:sw=4:et +" vim: sw=2 ts=2 et diff --git a/sources_non_forked/vim-go/syntax/gotexttmpl.vim b/sources_non_forked/vim-go/syntax/gotexttmpl.vim index f8f4e682..ab8b1b6d 100644 --- a/sources_non_forked/vim-go/syntax/gotexttmpl.vim +++ b/sources_non_forked/vim-go/syntax/gotexttmpl.vim @@ -6,7 +6,7 @@ " Quit when a (custom) syntax file was already loaded if exists("b:current_syntax") - finish + finish endif syn case match @@ -74,12 +74,12 @@ hi def link goTplVariable Special syn region gotplAction start="{{" end="}}" contains=@gotplLiteral,gotplControl,gotplFunctions,gotplVariable,goTplIdentifier display syn region gotplAction start="\[\[" end="\]\]" contains=@gotplLiteral,gotplControl,gotplFunctions,gotplVariable display -syn region goTplComment start="{{/\*" end="\*/}}" display -syn region goTplComment start="\[\[/\*" end="\*/\]\]" display +syn region goTplComment start="{{\(- \)\?/\*" end="\*/\( -\)\?}}" display +syn region goTplComment start="\[\[\(- \)\?/\*" end="\*/\( -\)\?\]\]" display hi def link gotplAction PreProc hi def link goTplComment Comment let b:current_syntax = "gotexttmpl" -" vim:ts=4:sw=4:et +" vim: sw=2 ts=2 et diff --git a/sources_non_forked/vim-go/syntax/vimgo.vim b/sources_non_forked/vim-go/syntax/vimgo.vim index d62791d3..3a2204c4 100644 --- a/sources_non_forked/vim-go/syntax/vimgo.vim +++ b/sources_non_forked/vim-go/syntax/vimgo.vim @@ -1,5 +1,5 @@ if exists("b:current_syntax") - finish + finish endif let b:current_syntax = "vimgo" @@ -9,3 +9,5 @@ syn region goTitle start="\%1l" end=":" hi def link goInterface Type hi def link goTitle Label + +" vim: sw=2 ts=2 et diff --git a/sources_non_forked/vim-go/t/coverlay.vim b/sources_non_forked/vim-go/t/coverlay.vim deleted file mode 100644 index 9d60c21d..00000000 --- a/sources_non_forked/vim-go/t/coverlay.vim +++ /dev/null @@ -1,191 +0,0 @@ -" to execute, `rake test` on parent dir - -describe 'go#coverage#Buffer' - before - new - let g:curdir = expand(':p:h') . '/' - let g:srcpath = 't/fixtures/src/' - let g:sample = 'pkg1/sample.go' - let g:sampleabs = g:curdir . g:srcpath . 'pkg1/sample.go' - let g:samplecover = g:curdir . g:srcpath . 'pkg1/sample.out' - let g:go_gopath = g:curdir . 't/fixtures' - execute "badd " . g:srcpath . g:sample - execute "buffer " . bufnr("$") - end - after - execute "bprev" - execute "bdelete " . g:srcpath . g:sample - close! - end - - it 'puts match to the list' - call go#coverage#Buffer(0) - Expect len(go#coverlay#matches()) == 5 - call go#coverlay#Clearlay() - Expect len(go#coverlay#matches()) == 0 - - call go#coverage#Buffer(0) - Expect len(go#coverlay#matches()) == 5 - call go#coverlay#Clearlay() - Expect len(go#coverlay#matches()) == 0 - - call go#coverage#Buffer(0) - Expect len(go#coverlay#matches()) == 5 - call go#coverage#Buffer(0) - Expect len(go#coverlay#matches()) == 5 - call go#coverlay#Clearlay() - Expect len(go#coverlay#matches()) == 0 - end -end - -describe 'go#coverage#Buffer fail' - before - new - let g:curdir = expand(':p:h') . '/' - let g:srcpath = 't/fixtures/src/' - let g:sample = 'failtest/sample.go' - let g:sampletest = 'failtest/sample_test.go' - let g:sampleabs = g:curdir . g:srcpath . 'failtest/sample.go' - let g:go_gopath = g:curdir . 't/fixtures' - execute "badd " . g:srcpath . g:sample - execute "buffer " . bufnr("$") - end - after - execute "bprev" - execute "bdelete " . g:srcpath . g:sampletest - execute "bdelete " . g:srcpath . g:sample - end - - it 'does nothing if test fail' - call go#coverage#Buffer(0) - Expect len(go#coverlay#matches()) == 0 - Expect len(getqflist()) == 1 - end -end - -describe 'go#coverage#Buffer build fail' - before - new - let g:curdir = expand(':p:h') . '/' - let g:srcpath = 't/fixtures/src/' - let g:sample = 'buildfail/sample.go' - let g:sampleabs = g:curdir . g:srcpath . 'buildfail/sample.go' - let g:go_gopath = g:curdir . 't/fixtures' - execute "badd " . g:srcpath . g:sample - execute "buffer " . bufnr("$") - end - after - execute "bprev" - execute "bdelete " . g:srcpath . g:sample - end - - it 'does nothing if test fail' - call go#coverage#Buffer(0) - Expect len(go#coverlay#matches()) == 0 - end -end - -describe 'go#coverage#Buffer build test fail' - before - new - let g:curdir = expand(':p:h') . '/' - let g:srcpath = 't/fixtures/src/' - let g:sample = 'buildtestfail/sample.go' - let g:sampleabs = g:curdir . g:srcpath . 'buildtestfail/sample.go' - let g:go_gopath = g:curdir . 't/fixtures' - execute "badd " . g:srcpath . g:sample - execute "buffer " . bufnr("$") - end - after - execute "bprev" - execute "bdelete " . g:srcpath . g:sample - end - - it 'does nothing if test fail' - call go#coverage#Buffer(0) - Expect len(go#coverlay#matches()) == 0 - end -end - -describe 'go#coverlay#findbufnr' - before - new - let g:curdir = expand(':p:h') . '/' - let g:srcpath = 't/fixtures/src/' - let g:sample = 'pkg1/sample.go' - let g:sample2 = 'pkg2/sample.go' - let g:sampleabs = g:curdir . g:srcpath . 'pkg1/sample.go' - let g:sampleabs2 = g:curdir . g:srcpath . 'pkg2/sample.go' - let g:go_gopath = g:curdir . 't/fixtures' - execute "badd " . g:srcpath . g:sample - execute "badd " . g:srcpath . g:sample2 - end - after - execute "bdelete " . g:srcpath . g:sample2 - execute "bdelete " . g:srcpath . g:sample - close! - end - - it 'returns BUFNR if FILE is opened at BUFNR' - Expect go#coverlay#findbufnr('_' . g:sampleabs) == bufnr(g:sampleabs) - Expect go#coverlay#findbufnr(g:sample) == bufnr(g:sampleabs) - - Expect go#coverlay#findbufnr('_' . g:sampleabs2) == bufnr(g:sampleabs2) - Expect go#coverlay#findbufnr(g:sample2) == bufnr(g:sampleabs2) - end - - it 'returns -1 if FILE is not exists' - Expect go#coverlay#findbufnr('pkg1/NOTEXISTS.go') == -1 - Expect go#coverlay#findbufnr('_' . g:curdir . g:srcpath . 'pkg1/NOTEXISTS.go') == -1 - end -end - -describe 'go#coverlay#isopenedon' - before - new - let g:curdir = expand(':p:h') . '/' - let g:srcpath = 't/fixtures/src/' - let g:sample = 'pkg1/sample.go' - let g:sampleabs = g:curdir . g:srcpath . 'pkg1/sample.go' - let g:go_gopath = g:curdir . 't/fixtures' - execute "badd " . g:srcpath . g:sample - end - after - execute "bdelete " . g:srcpath . g:sample - close! - end - - it 'returns 1 if FILE is opened at BUFNR' - Expect go#coverlay#isopenedon('_' . g:sampleabs, bufnr(g:sampleabs)) == 1 - Expect go#coverlay#isopenedon(g:sample, bufnr(g:sampleabs)) == 1 - end - - it 'returns 0 if FILE is not opened at BUFNR' - Expect go#coverlay#isopenedon('_' . g:sampleabs, 42) == 0 - Expect go#coverlay#isopenedon(g:sample, 42) == 0 - end - - it 'returns 0 if FILE is not exists' - Expect go#coverlay#isopenedon('_' . g:curdir . g:srcpath . 'pkg1/NOTEXISTS', bufnr(g:sampleabs)) == 0 - Expect go#coverlay#isopenedon('pkg1/NOTEXISTS.go', bufnr(g:sampleabs)) == 0 - end -end - - - -describe 'go#coverlay#parsegocoverline' - it 'parses a go cover output line and returns as dict' - let d = {'file': 'f',"startline": "1", "startcol": "2", "endline": "3", "endcol": "4", "numstmt": "5", "cnt": "6"} - " file:startline.col,endline.col numstmt count - Expect go#coverlay#parsegocoverline("f:1.2,3.4 5 6") == d - end -end - -describe 'go#coverlay#genmatch' - it 'generate mark pattern from cover data' - let d = {'file': 'f',"startline": "1", "startcol": "2", "endline": "3", "endcol": "4", "numstmt": "5", "cnt": "6"} - Expect go#coverlay#genmatch(d) == {'group': 'covered', "pattern": '\%>1l\_^\s\+\%<3l\|\%1l\_^\s\+\|\%3l\_^\s\+\(\}$\)\@!', "priority": 6} - let d = {'file': 'f',"startline": "1", "startcol": "2", "endline": "3", "endcol": "4", "numstmt": "5", "cnt": "0"} - Expect go#coverlay#genmatch(d) == {'group': 'uncover', "pattern": '\%>1l\_^\s\+\%<3l\|\%1l\_^\s\+\|\%3l\_^\s\+\(\}$\)\@!', "priority": 5} - end -end diff --git a/sources_non_forked/vim-go/t/fixtures/src/buildfail/sample.go b/sources_non_forked/vim-go/t/fixtures/src/buildfail/sample.go deleted file mode 100644 index 45fc006a..00000000 --- a/sources_non_forked/vim-go/t/fixtures/src/buildfail/sample.go +++ /dev/null @@ -1,13 +0,0 @@ -// set gopath before -//go:generate go test --coverprofile=sample.out -// go1.5.3 example output: -// GOPATH=`pwd`/fixtures go test --coverprofile=log.out buildfail -// # buildfail -// /tmp/go-build264733986/buildfail/_test/_obj_test/sample.go:7: undefined: IT_SHOULD_BE_BUILD_FAILED -// /tmp/go-build264733986/buildfail/_test/_obj_test/sample.go:8: missing return at end of function -// FAIL buildfail [build failed] -package pkg - -func Sample() int { - IT_SHOULD_BE_BUILD_FAILED -} diff --git a/sources_non_forked/vim-go/t/fixtures/src/buildfail/sample_test.go b/sources_non_forked/vim-go/t/fixtures/src/buildfail/sample_test.go deleted file mode 100644 index 2356d3ed..00000000 --- a/sources_non_forked/vim-go/t/fixtures/src/buildfail/sample_test.go +++ /dev/null @@ -1,7 +0,0 @@ -package pkg - -import "testing" - -func TestSample(t *testing.T) { - Sample() -} diff --git a/sources_non_forked/vim-go/t/fixtures/src/buildtestfail/sample.go b/sources_non_forked/vim-go/t/fixtures/src/buildtestfail/sample.go deleted file mode 100644 index 792f1234..00000000 --- a/sources_non_forked/vim-go/t/fixtures/src/buildtestfail/sample.go +++ /dev/null @@ -1,7 +0,0 @@ -// set gopath before -//go:generate go test --coverprofile=sample.out -package pkg - -func Sample() int { - return 1 -} diff --git a/sources_non_forked/vim-go/t/fixtures/src/buildtestfail/sample_test.go b/sources_non_forked/vim-go/t/fixtures/src/buildtestfail/sample_test.go deleted file mode 100644 index 17c4d463..00000000 --- a/sources_non_forked/vim-go/t/fixtures/src/buildtestfail/sample_test.go +++ /dev/null @@ -1,15 +0,0 @@ -// go1.5.3 example output: -// GOPATH=`pwd`/fixtures go test --coverprofile=log.out buildtestfail -// # buildtestfail -// fixtures/src/buildtestfail/sample_test.go:14: undefined: IT_SHOULD_BE_BUILD_FAILED -// FAIL buildtestfail [build failed] -// echo $? -// 2 - -package pkg - -import "testing" - -func TestSample(t *testing.T) { - IT_SHOULD_BE_BUILD_FAILED -} diff --git a/sources_non_forked/vim-go/t/fixtures/src/failtest/sample.go b/sources_non_forked/vim-go/t/fixtures/src/failtest/sample.go deleted file mode 100644 index 5859e926..00000000 --- a/sources_non_forked/vim-go/t/fixtures/src/failtest/sample.go +++ /dev/null @@ -1,12 +0,0 @@ -// set gopath before -//go:generate go test --coverprofile=sample.out -package pkg - -func Sample() int { - if false { - return 0 - } else if false { - return 0 - } - return 1 -} diff --git a/sources_non_forked/vim-go/t/fixtures/src/failtest/sample_test.go b/sources_non_forked/vim-go/t/fixtures/src/failtest/sample_test.go deleted file mode 100644 index 7f1ade0d..00000000 --- a/sources_non_forked/vim-go/t/fixtures/src/failtest/sample_test.go +++ /dev/null @@ -1,8 +0,0 @@ -package pkg - -import "testing" - -func TestSample(t *testing.T) { - Sample() - t.Fatal("itwillfail") -} diff --git a/sources_non_forked/vim-go/t/fixtures/src/parsefail/sample.go b/sources_non_forked/vim-go/t/fixtures/src/parsefail/sample.go deleted file mode 100644 index e9f3faa9..00000000 --- a/sources_non_forked/vim-go/t/fixtures/src/parsefail/sample.go +++ /dev/null @@ -1,14 +0,0 @@ -// set gopath before -//go:generate go test --coverprofile=sample.out -// go1.5.3 example output: -// GOPATH=`pwd`/fixtures go test --coverprofile=log.out parsefail -// # cover parsefail -// 2016/01/17 23:59:08 cover: /home/sey/vimfiles/_vim/bundle/vim-go-coverlay/t/fixtures/src/parsefail/sample.go: /home/sey/vimfiles/_vim/bundle/vim-go-coverlay/t/fixtures/src/parsefail/sample.go:10:1: expected declaration, found 'IDENT' PARSEFAIL -// FAIL parsefail [build failed] -// echo $? -// 2 -package pkg - -PARSEFAIL Sample() int { - return 0 -} diff --git a/sources_non_forked/vim-go/t/fixtures/src/parsefail/sample_test.go b/sources_non_forked/vim-go/t/fixtures/src/parsefail/sample_test.go deleted file mode 100644 index 2356d3ed..00000000 --- a/sources_non_forked/vim-go/t/fixtures/src/parsefail/sample_test.go +++ /dev/null @@ -1,7 +0,0 @@ -package pkg - -import "testing" - -func TestSample(t *testing.T) { - Sample() -} diff --git a/sources_non_forked/vim-go/t/fixtures/src/pkg1/sample.go b/sources_non_forked/vim-go/t/fixtures/src/pkg1/sample.go deleted file mode 100644 index 6ce94b39..00000000 --- a/sources_non_forked/vim-go/t/fixtures/src/pkg1/sample.go +++ /dev/null @@ -1,12 +0,0 @@ -// set gopath before -//go:generate go test --coverprofile=sample.out -package pkg1 - -func Sample() int { - if false { - return 0 - } else if false { - return 0 - } - return 1 -} diff --git a/sources_non_forked/vim-go/t/fixtures/src/pkg1/sample.out b/sources_non_forked/vim-go/t/fixtures/src/pkg1/sample.out deleted file mode 100644 index 909a63f1..00000000 --- a/sources_non_forked/vim-go/t/fixtures/src/pkg1/sample.out +++ /dev/null @@ -1,6 +0,0 @@ -mode: set -pkg1/sample.go:5.19,6.11 1 1 -pkg1/sample.go:11.2,11.10 1 1 -pkg1/sample.go:6.11,8.3 1 0 -pkg1/sample.go:8.3,8.18 1 1 -pkg1/sample.go:8.18,10.3 1 0 diff --git a/sources_non_forked/vim-go/t/fixtures/src/pkg1/sample_test.go b/sources_non_forked/vim-go/t/fixtures/src/pkg1/sample_test.go deleted file mode 100644 index e39d7ba8..00000000 --- a/sources_non_forked/vim-go/t/fixtures/src/pkg1/sample_test.go +++ /dev/null @@ -1,7 +0,0 @@ -package pkg1 - -import "testing" - -func TestSample(t *testing.T) { - Sample() -} diff --git a/sources_non_forked/vim-go/templates/hello_world.go b/sources_non_forked/vim-go/templates/hello_world.go new file mode 100644 index 00000000..50e8d8d3 --- /dev/null +++ b/sources_non_forked/vim-go/templates/hello_world.go @@ -0,0 +1,7 @@ +package main + +import "fmt" + +func main() { + fmt.Println("vim-go") +} diff --git a/sources_non_forked/vim-go/templates/hello_world_test.go b/sources_non_forked/vim-go/templates/hello_world_test.go new file mode 100644 index 00000000..3ef4f524 --- /dev/null +++ b/sources_non_forked/vim-go/templates/hello_world_test.go @@ -0,0 +1,7 @@ +package main + +import "testing" + +func TestHelloWorld(t *testing.T) { + // t.Fatal("not implemented") +} diff --git a/sources_non_forked/vim-indent-object/doc/indent-object.txt b/sources_non_forked/vim-indent-object/doc/indent-object.txt index b22c9865..be99f313 100644 --- a/sources_non_forked/vim-indent-object/doc/indent-object.txt +++ b/sources_non_forked/vim-indent-object/doc/indent-object.txt @@ -4,14 +4,14 @@ Indent Text Objects -INTRODUCTION |idntobj-introduction| -TEXT OBJECTS |idntobj-objects| -BLANK LINES |idntobj-blanklines| -ABOUT |idntobj-about| +INTRODUCTION |indtobj-introduction| +TEXT OBJECTS |indtobj-objects| +BLANK LINES |indtobj-blanklines| +ABOUT |indtobj-about| ============================================================================== -INTRODUCTION *idntobj-introduction* +INTRODUCTION *indtobj-introduction* Vim text objects provide a convenient way to select and operate on various types of objects. These objects include regions surrounded by various types of @@ -24,7 +24,7 @@ structure can be quickly selected, for example. ============================================================================== -TEXT OBJECTS *ai* *ii* *aI* *iI* *idntobj-objects* +TEXT OBJECTS *ai* *ii* *aI* *iI* *indtobj-objects* This plugin defines two new text objects. These are very similar - they differ only in whether they include the line below the block or not. @@ -78,7 +78,7 @@ structure. ============================================================================== -BLANK LINES *idntobj-blanklines* +BLANK LINES *indtobj-blanklines* When scanning code blocks, the plugin usually ignores blank lines. There is an exception to this, however, when the block being selected is not indented. In @@ -94,7 +94,7 @@ This exceptional behaviour can be disabled by executing the following line ============================================================================== -ABOUT *idntobj-about* +ABOUT *indtobj-about* vim-indent-object was written by Michael Smith . The project repository is kept at: diff --git a/sources_non_forked/vim-markdown/README.markdown b/sources_non_forked/vim-markdown/README.markdown index cd79315f..8c7c6d07 100644 --- a/sources_non_forked/vim-markdown/README.markdown +++ b/sources_non_forked/vim-markdown/README.markdown @@ -20,6 +20,14 @@ To disable markdown syntax concealing add the following to your vimrc: let g:markdown_syntax_conceal = 0 +Syntax highlight is synchronized in 50 lines. It may cause collapsed +highlighting at large fenced code block. +In the case, please set larger value in your vimrc: + + let g:markdown_minlines = 100 + +Note that setting too large value may cause bad performance on highlighting. + ## License Copyright © Tim Pope. Distributed under the same terms as Vim itself. diff --git a/sources_non_forked/vim-markdown/ftplugin/markdown.vim b/sources_non_forked/vim-markdown/ftplugin/markdown.vim index f406db58..2fbdf66d 100644 --- a/sources_non_forked/vim-markdown/ftplugin/markdown.vim +++ b/sources_non_forked/vim-markdown/ftplugin/markdown.vim @@ -41,10 +41,35 @@ function! MarkdownFold() return "=" endfunction +function! MarkdownFoldText() + let hash_indent = s:HashIndent(v:foldstart) + let title = substitute(getline(v:foldstart), '^#\+\s*', '', '') + let foldsize = (v:foldend - v:foldstart + 1) + let linecount = '['.foldsize.' lines]' + return hash_indent.' '.title.' '.linecount +endfunction + +function! s:HashIndent(lnum) + let hash_header = matchstr(getline(a:lnum), '^#\{1,6}') + if len(hash_header) > 0 + " hashtag header + return hash_header + else + " == or -- header + let nextline = getline(a:lnum + 1) + if nextline =~ '^=\+\s*$' + return repeat('#', 1) + elseif nextline =~ '^-\+\s*$' + return repeat('#', 2) + endif + endif +endfunction + if has("folding") && exists("g:markdown_folding") setlocal foldexpr=MarkdownFold() setlocal foldmethod=expr - let b:undo_ftplugin .= " foldexpr< foldmethod<" + setlocal foldtext=MarkdownFoldText() + let b:undo_ftplugin .= " foldexpr< foldmethod< foldtext<" endif " vim:set sw=2: diff --git a/sources_non_forked/vim-markdown/syntax/markdown.vim b/sources_non_forked/vim-markdown/syntax/markdown.vim index 1b2a93a6..26ba4c9c 100644 --- a/sources_non_forked/vim-markdown/syntax/markdown.vim +++ b/sources_non_forked/vim-markdown/syntax/markdown.vim @@ -33,7 +33,10 @@ endfor unlet! s:type unlet! s:done_include -syn sync minlines=10 +if !exists('g:markdown_minlines') + let g:markdown_minlines = 50 +endif +execute 'syn sync minlines=' . g:markdown_minlines syn case ignore syn match markdownValid '[<>]\c[a-z/$!]\@!' @@ -49,12 +52,12 @@ syn match markdownH2 "^.\+\n-\+$" contained contains=@markdownInline,markdownHea syn match markdownHeadingRule "^[=-]\+$" contained -syn region markdownH1 matchgroup=markdownHeadingDelimiter start="##\@!" end="#*\s*$" keepend oneline contains=@markdownInline,markdownAutomaticLink contained -syn region markdownH2 matchgroup=markdownHeadingDelimiter start="###\@!" end="#*\s*$" keepend oneline contains=@markdownInline,markdownAutomaticLink contained -syn region markdownH3 matchgroup=markdownHeadingDelimiter start="####\@!" end="#*\s*$" keepend oneline contains=@markdownInline,markdownAutomaticLink contained -syn region markdownH4 matchgroup=markdownHeadingDelimiter start="#####\@!" end="#*\s*$" keepend oneline contains=@markdownInline,markdownAutomaticLink contained -syn region markdownH5 matchgroup=markdownHeadingDelimiter start="######\@!" end="#*\s*$" keepend oneline contains=@markdownInline,markdownAutomaticLink contained -syn region markdownH6 matchgroup=markdownHeadingDelimiter start="#######\@!" end="#*\s*$" keepend oneline contains=@markdownInline,markdownAutomaticLink contained +syn region markdownH1 matchgroup=markdownH1Delimiter start="##\@!" end="#*\s*$" keepend oneline contains=@markdownInline,markdownAutomaticLink contained +syn region markdownH2 matchgroup=markdownH2Delimiter start="###\@!" end="#*\s*$" keepend oneline contains=@markdownInline,markdownAutomaticLink contained +syn region markdownH3 matchgroup=markdownH3Delimiter start="####\@!" end="#*\s*$" keepend oneline contains=@markdownInline,markdownAutomaticLink contained +syn region markdownH4 matchgroup=markdownH4Delimiter start="#####\@!" end="#*\s*$" keepend oneline contains=@markdownInline,markdownAutomaticLink contained +syn region markdownH5 matchgroup=markdownH5Delimiter start="######\@!" end="#*\s*$" keepend oneline contains=@markdownInline,markdownAutomaticLink contained +syn region markdownH6 matchgroup=markdownH6Delimiter start="#######\@!" end="#*\s*$" keepend oneline contains=@markdownInline,markdownAutomaticLink contained syn match markdownBlockquote ">\%(\s\|$\)" contained nextgroup=@markdownBlock @@ -85,16 +88,16 @@ let s:concealends = '' if has('conceal') && get(g:, 'markdown_syntax_conceal', 1) == 1 let s:concealends = ' concealends' endif -exe 'syn region markdownItalic matchgroup=markdownItalicDelimiter start="\S\@<=\*\|\*\S\@=" end="\S\@<=\*\|\*\S\@=" keepend contains=markdownLineStart' . s:concealends -exe 'syn region markdownItalic matchgroup=markdownItalicDelimiter start="\S\@<=_\|_\S\@=" end="\S\@<=_\|_\S\@=" keepend contains=markdownLineStart' . s:concealends -exe 'syn region markdownBold matchgroup=markdownBoldDelimiter start="\S\@<=\*\*\|\*\*\S\@=" end="\S\@<=\*\*\|\*\*\S\@=" keepend contains=markdownLineStart,markdownItalic' . s:concealends -exe 'syn region markdownBold matchgroup=markdownBoldDelimiter start="\S\@<=__\|__\S\@=" end="\S\@<=__\|__\S\@=" keepend contains=markdownLineStart,markdownItalic' . s:concealends -exe 'syn region markdownBoldItalic matchgroup=markdownBoldItalicDelimiter start="\S\@<=\*\*\*\|\*\*\*\S\@=" end="\S\@<=\*\*\*\|\*\*\*\S\@=" keepend contains=markdownLineStart' . s:concealends -exe 'syn region markdownBoldItalic matchgroup=markdownBoldItalicDelimiter start="\S\@<=___\|___\S\@=" end="\S\@<=___\|___\S\@=" keepend contains=markdownLineStart' . s:concealends +exe 'syn region markdownItalic matchgroup=markdownItalicDelimiter start="\S\@<=\*\|\*\S\@=" end="\S\@<=\*\|\*\S\@=" keepend contains=markdownLineStart,@Spell' . s:concealends +exe 'syn region markdownItalic matchgroup=markdownItalicDelimiter start="\S\@<=_\|_\S\@=" end="\S\@<=_\|_\S\@=" keepend contains=markdownLineStart,@Spell' . s:concealends +exe 'syn region markdownBold matchgroup=markdownBoldDelimiter start="\S\@<=\*\*\|\*\*\S\@=" end="\S\@<=\*\*\|\*\*\S\@=" keepend contains=markdownLineStart,markdownItalic,@Spell' . s:concealends +exe 'syn region markdownBold matchgroup=markdownBoldDelimiter start="\S\@<=__\|__\S\@=" end="\S\@<=__\|__\S\@=" keepend contains=markdownLineStart,markdownItalic,@Spell' . s:concealends +exe 'syn region markdownBoldItalic matchgroup=markdownBoldItalicDelimiter start="\S\@<=\*\*\*\|\*\*\*\S\@=" end="\S\@<=\*\*\*\|\*\*\*\S\@=" keepend contains=markdownLineStart,@Spell' . s:concealends +exe 'syn region markdownBoldItalic matchgroup=markdownBoldItalicDelimiter start="\S\@<=___\|___\S\@=" end="\S\@<=___\|___\S\@=" keepend contains=markdownLineStart,@Spell' . s:concealends syn region markdownCode matchgroup=markdownCodeDelimiter start="`" end="`" keepend contains=markdownLineStart syn region markdownCode matchgroup=markdownCodeDelimiter start="`` \=" end=" \=``" keepend contains=markdownLineStart -syn region markdownCode matchgroup=markdownCodeDelimiter start="^\s*```*.*$" end="^\s*```*\ze\s*$" keepend +syn region markdownCode matchgroup=markdownCodeDelimiter start="^\s*````*.*$" end="^\s*````*\ze\s*$" keepend syn match markdownFootnote "\[^[^\]]\+\]" syn match markdownFootnoteDefinition "^\[^[^\]]\+\]:" @@ -105,7 +108,7 @@ if main_syntax ==# 'markdown' if has_key(s:done_include, matchstr(s:type,'[^.]*')) continue endif - exe 'syn region markdownHighlight'.substitute(matchstr(s:type,'[^=]*$'),'\..*','','').' matchgroup=markdownCodeDelimiter start="^\s*```*\s*'.matchstr(s:type,'[^=]*').'\>.*$" end="^\s*```*\ze\s*$" keepend contains=@markdownHighlight'.substitute(matchstr(s:type,'[^=]*$'),'\.','','g') + exe 'syn region markdownHighlight'.substitute(matchstr(s:type,'[^=]*$'),'\..*','','').' matchgroup=markdownCodeDelimiter start="^\s*````*\s*'.matchstr(s:type,'[^=]*').'\S\@!.*$" end="^\s*````*\ze\s*$" keepend contains=@markdownHighlight'.substitute(matchstr(s:type,'[^=]*$'),'\.','','g') let s:done_include[matchstr(s:type,'[^.]*')] = 1 endfor unlet! s:type @@ -122,6 +125,12 @@ hi def link markdownH4 htmlH4 hi def link markdownH5 htmlH5 hi def link markdownH6 htmlH6 hi def link markdownHeadingRule markdownRule +hi def link markdownH1Delimiter markdownHeadingDelimiter +hi def link markdownH2Delimiter markdownHeadingDelimiter +hi def link markdownH3Delimiter markdownHeadingDelimiter +hi def link markdownH4Delimiter markdownHeadingDelimiter +hi def link markdownH5Delimiter markdownHeadingDelimiter +hi def link markdownH6Delimiter markdownHeadingDelimiter hi def link markdownHeadingDelimiter Delimiter hi def link markdownOrderedListMarker markdownListMarker hi def link markdownListMarker htmlTagName diff --git a/sources_non_forked/vim-multiple-cursors/README.md b/sources_non_forked/vim-multiple-cursors/README.md index 26cb6d02..8ed8c113 100644 --- a/sources_non_forked/vim-multiple-cursors/README.md +++ b/sources_non_forked/vim-multiple-cursors/README.md @@ -18,7 +18,7 @@ - [Contributing](#contributing) - [Credit](#credit) -###Contributors +### Contributors - [eapache](https://github.com/eapache) - [aschrab](https://github.com/aschrab) - [kristijanhusak](https://github.com/kristijanhusak) @@ -188,6 +188,9 @@ endfunction With this locking and unlocking we prevent neocomplete to trigger it's function calls until we are finished with multiple cursors editing. +Plugins themselves can register `User` autocommands on `MultipleCursorsPre` and +`MultipleCursorsPost` for automatic integration. + ### Highlight The plugin uses the highlight group `multiple_cursors_cursor` and `multiple_cursors_visual` to highlight the virtual cursors and their visual selections respectively. You can customize them by putting something similar like the following in your vimrc: diff --git a/sources_non_forked/vim-multiple-cursors/autoload/multiple_cursors.vim b/sources_non_forked/vim-multiple-cursors/autoload/multiple_cursors.vim index 0df3e8ae..36d267ff 100644 --- a/sources_non_forked/vim-multiple-cursors/autoload/multiple_cursors.vim +++ b/sources_non_forked/vim-multiple-cursors/autoload/multiple_cursors.vim @@ -100,6 +100,17 @@ function! multiple_cursors#get_latency_debug_file() return s:latency_debug_file endfunction + +function! s:fire_pre_triggers() + if !s:before_function_called + doautocmd User MultipleCursorsPre + if exists('*Multiple_cursors_before') + exe "call Multiple_cursors_before()" + endif + let s:before_function_called = 1 + endif +endfunction + " Creates a new cursor. Different logic applies depending on the mode the user " is in and the current state of the buffer. " 1. In normal mode, a new cursor is created at the end of the word under Vim's @@ -111,10 +122,7 @@ endfunction " attempted to be created at the next occurrence of the visual selection function! multiple_cursors#new(mode, word_boundary) " Call before function if exists only once until it is canceled () - if exists('*Multiple_cursors_before') && !s:before_function_called - exe "call Multiple_cursors_before()" - let s:before_function_called = 1 - endif + call s:fire_pre_triggers() let s:use_word_boundary = a:word_boundary if a:mode ==# 'n' " Reset all existing cursors, don't restore view and setting @@ -269,10 +277,7 @@ function! multiple_cursors#find(start, end, pattern) " If we've created any cursors, we need to call the before function, end " function will be called via normal routes - if exists('*Multiple_cursors_before') && !s:before_function_called - exe "call Multiple_cursors_before()" - let s:before_function_called = 1 - endif + call s:fire_pre_triggers() call s:wait_for_user_input('v') endif @@ -436,8 +441,11 @@ function! s:CursorManager.reset(restore_view, restore_setting, ...) dict call self.restore_user_settings() endif " Call after function if exists and only if action is canceled () - if exists('*Multiple_cursors_after') && a:0 && s:before_function_called - exe "call Multiple_cursors_after()" + if a:0 && s:before_function_called + if exists('*Multiple_cursors_after') + exe "call Multiple_cursors_after()" + endif + doautocmd User MultipleCursorsPost let s:before_function_called = 0 endif endfunction @@ -1008,13 +1016,28 @@ function! s:get_visual_region(pos) return region endfunction +function! s:strpart(s, i, l) + if a:l == 0 + return '' + endif + let [s, l] = ['', 0] + for c in split(a:s[a:i :], '\zs') + let s .= c + let l += len(c) + if l >= a:l + break + endif + endfor + return s +endfunction + " Return the content of the buffer between the input region. This is used to " find the next match in the buffer " Mode change: Normal -> Normal " Cursor change: None function! s:get_text(region) let lines = getline(a:region[0][0], a:region[1][0]) - let lines[-1] = lines[-1][:a:region[1][1] - 1] + let lines[-1] = s:strpart(lines[-1], 0, a:region[1][1]) let lines[0] = lines[0][a:region[0][1] - 1:] return join(lines, "\n") endfunction diff --git a/sources_non_forked/vim-multiple-cursors/spec/multiple_cursors_spec.rb b/sources_non_forked/vim-multiple-cursors/spec/multiple_cursors_spec.rb index 9f83c219..2d92e5a2 100644 --- a/sources_non_forked/vim-multiple-cursors/spec/multiple_cursors_spec.rb +++ b/sources_non_forked/vim-multiple-cursors/spec/multiple_cursors_spec.rb @@ -1,3 +1,4 @@ +# -*- encoding: utf-8 -*- require 'spec_helper' def set_file_content(string) @@ -797,4 +798,20 @@ describe "Multiple Cursors" do EOF end + specify "#multi-byte strings" do + before <<-EOF + こんにちわビム + 世界の中心でビムを叫ぶ + ビム大好き + EOF + + type '/ビムcヴィム' + + after <<-EOF + こんにちわヴィム + 世界の中心でヴィムを叫ぶ + ヴィム大好き + EOF + end + end diff --git a/sources_non_forked/vim-pug/README.markdown b/sources_non_forked/vim-pug/README.markdown index c41f9ddd..7665388f 100644 --- a/sources_non_forked/vim-pug/README.markdown +++ b/sources_non_forked/vim-pug/README.markdown @@ -2,6 +2,8 @@ Vim syntax highlighting for Pug (formerly Jade) templates. +For best results consider using this with an (improved) HTML5 syntax plugin. + Installation ------------ diff --git a/sources_non_forked/vim-pug/syntax/pug.vim b/sources_non_forked/vim-pug/syntax/pug.vim index 86013a2e..7b0f1c37 100644 --- a/sources_non_forked/vim-pug/syntax/pug.vim +++ b/sources_non_forked/vim-pug/syntax/pug.vim @@ -30,13 +30,17 @@ syn region pugJavascript matchgroup=pugJavascriptOutputChar start="[!&]\==\|\~" syn region pugJavascript matchgroup=pugJavascriptChar start="-" skip=",\s*$" end="$" contained contains=@htmlJavascript keepend syn cluster pugTop contains=pugBegin,pugComment,pugHtmlComment,pugJavascript syn match pugBegin "^\s*\%([<>]\|&[^=~ ]\)\@!" nextgroup=pugTag,pugClassChar,pugIdChar,pugPlainChar,pugJavascript,pugScriptConditional,pugScriptStatement,pugPipedText -syn match pugTag "+\?\w\+\%(:\w\+\)\=" contained contains=htmlTagName,htmlSpecialTagName nextgroup=@pugComponent +syn match pugTag "+\?[[:alnum:]_-]\+\%(:\w\+\)\=" contained contains=htmlTagName,htmlSpecialTagName nextgroup=@pugComponent syn cluster pugComponent contains=pugAttributes,pugIdChar,pugBlockExpansionChar,pugClassChar,pugPlainChar,pugJavascript,pugTagBlockChar,pugTagInlineText -syn match pugComment '\s*\/\/.*$' -syn region pugCommentBlock start="\z(\s*\)\/\/.*$" end="^\%(\z1\s\|\s*$\)\@!" keepend -syn region pugHtmlConditionalComment start="" -syn region pugAttributes matchgroup=pugAttributesDelimiter start="(" end=")" contained contains=@htmlJavascript,pugHtmlArg,htmlArg,htmlEvent,htmlCssDefinition nextgroup=@pugComponent -syn match pugClassChar "\." contained nextgroup=pugClass +syntax keyword pugCommentTodo contained TODO FIXME XXX TBD +syn match pugComment '\(\s\+\|^\)\/\/.*$' contains=pugCommentTodo,@Spell +syn region pugCommentBlock start="\z(\s\+\|^\)\/\/.*$" end="^\%(\z1\s\|\s*$\)\@!" contains=pugCommentTodo,@Spell keepend +syn region pugHtmlConditionalComment start="" contains=pugCommentTodo,@Spell +syn region pugAngular2 start="(" end=")" contains=htmlEvent +syn region pugJavascriptString start=+"+ skip=+\\\("\|$\)+ end=+"\|$+ contained +syn region pugJavascriptString start=+'+ skip=+\\\('\|$\)+ end=+'\|$+ contained +syn region pugAttributes matchgroup=pugAttributesDelimiter start="(" end=")" contained contains=pugJavascriptString,pugHtmlArg,pugAngular2,htmlArg,htmlEvent,htmlCssDefinition nextgroup=@pugComponent +syn match pugClassChar "\." containedin=htmlTagName nextgroup=pugClass syn match pugBlockExpansionChar ":\s\+" contained nextgroup=pugTag,pugClassChar,pugIdChar syn match pugIdChar "#[[{]\@!" contained nextgroup=pugId syn match pugClass "\%(\w\|-\)\+" contained nextgroup=@pugComponent @@ -50,10 +54,10 @@ syn keyword pugHtmlArg contained href title syn match pugPlainChar "\\" contained syn region pugInterpolation matchgroup=pugInterpolationDelimiter start="[#!]{" end="}" contains=@htmlJavascript syn match pugInterpolationEscape "\\\@s etc... -hi SpecialKey guifg=#d8a080 guibg=#e8e8e8 gui=italic +" color of s etc... +"hi SpecialKey guifg=#d8a080 guibg=#e8e8e8 gui=italic +hi SpecialKey guifg=#d0b0b0 guibg=#f0f0f0 gui=none " Diff hi DiffChange guifg=NONE guibg=#e0e0e0 gui=italic,bold diff --git a/sources_non_forked/vim-repeat/autoload/repeat.vim b/sources_non_forked/vim-repeat/autoload/repeat.vim index f2caeb4a..fde6a38e 100644 --- a/sources_non_forked/vim-repeat/autoload/repeat.vim +++ b/sources_non_forked/vim-repeat/autoload/repeat.vim @@ -40,7 +40,7 @@ " in your mapping will look like this: " " nnoremap MyMap -" \ :execute 'silent! call repeat#setreg("\Plug>MyMap", v:register)' +" \ :silent! call repeat#setreg("\Plug>MyMap", v:register) " \ call MyFunction(v:register, ...) " \ silent! call repeat#set("\Plug>MyMap") diff --git a/sources_non_forked/vim-snipmate/README.md b/sources_non_forked/vim-snipmate/README.md index b47b56df..f025dce5 100644 --- a/sources_non_forked/vim-snipmate/README.md +++ b/sources_non_forked/vim-snipmate/README.md @@ -96,6 +96,20 @@ will load the `ruby-rails` scope whenever the `ruby` scope is active. The buffer. The [vim-rails](https://github.com/tpope/vim-rails) plugin automatically does `:SnipMateLoadScope rails` when editing a Rails project for example. +> What are the snippet parser versions and what's the difference between them? + +Originally SnipMate used regex to parse a snippet. Determining where stops were, +what the placeholders were, where mirrors were, etc. were all done with regex. +Needless to say this was a little fragile. When the time came for a rewritten +parser, some incompatibilities were a little necessary. Rather than break +everyone's snippets everywhere, we provided both the new (version 1) and the old +(version 0) and let the user choose between them. + +Version 0 is considered legacy and not a lot of effort is going to go into +improving or even maintaining it. Version 1 is the future, and one can expect +new features to only exist for version 1 users. A full list of differences can +be found in the docs at `:h SnipMate-parser-versions`. + ## Release Notes ## ### 0.89 - 2016-05-29 ### diff --git a/sources_non_forked/vim-snipmate/autoload/snipMate.vim b/sources_non_forked/vim-snipmate/autoload/snipMate.vim index 2157eeb1..9d1786ab 100644 --- a/sources_non_forked/vim-snipmate/autoload/snipMate.vim +++ b/sources_non_forked/vim-snipmate/autoload/snipMate.vim @@ -6,7 +6,7 @@ endif try call tlib#input#List('mi', '', []) catch /.*/ - echoe "you're missing tlib. See install instructions at ".expand(':h:h').'/README.md' + echoe "tlib is missing. See install instructions at ".expand(':h:h').'/README.md' endtry fun! Filename(...) abort @@ -28,13 +28,9 @@ function! snipMate#expandSnip(snip, version, col) abort let [snippet, b:snip_state.stops] = snipmate#parse#snippet(a:snip) " Build stop/mirror info let b:snip_state.stop_count = s:build_stops(snippet, b:snip_state.stops, lnum, col, indent) - let snipLines = map(copy(snippet), - \ 'snipMate#sniplist_str(v:val, b:snip_state.stops)') else let snippet = snipmate#legacy#process_snippet(a:snip) let [b:snip_state.stops, b:snip_state.stop_count] = snipmate#legacy#build_stops(snippet, lnum, col - indent, indent) - let snipLines = split(substitute(snippet, printf('%s\d\+\|%s{\d\+.\{-}}', - \ g:snipmate#legacy#sigil, g:snipmate#legacy#sigil), '', 'g'), "\n", 1) endif " Abort if the snippet is empty @@ -42,23 +38,7 @@ function! snipMate#expandSnip(snip, version, col) abort return '' endif - " Expand snippet onto current position - let afterCursor = strpart(line, col - 1) - " Keep text after the cursor - if afterCursor != "\t" && afterCursor != ' ' - let line = strpart(line, 0, col - 1) - let snipLines[-1] .= afterCursor - else - let afterCursor = '' - " For some reason the cursor needs to move one right after this - if line != '' && col == 1 && &ve != 'all' && &ve != 'onemore' - let col += 1 - endif - endif - - " Insert snippet with proper indentation - call setline(lnum, line . snipLines[0]) - call append(lnum, map(snipLines[1:], "empty(v:val) ? v:val : '" . strpart(line, 0, indent - 1) . "' . v:val")) + let col = s:insert_snippet_text(snippet, lnum, col, indent) " Open any folds snippet expands into if &foldenable @@ -77,6 +57,50 @@ function! snipMate#expandSnip(snip, version, col) abort return b:snip_state.set_stop(0) endfunction +function! s:insert_snippet_text(snippet, lnum, col, indent) + let line = getline(a:lnum) + let col = a:col + let snippet = type(a:snippet) == type([]) ? a:snippet : split(a:snippet, "\n", 1) + let lnum = a:lnum + + " Keep text after the cursor + let afterCursor = strpart(line, col - 1) + if afterCursor != "\t" && afterCursor != ' ' + let line = strpart(line, 0, col - 1) + else + let afterCursor = '' + " For some reason the cursor needs to move one right after this + if line != '' && col == 1 && &ve != 'all' && &ve != 'onemore' + let col += 1 + endif + endif + + call setline(lnum, '') + call append(lnum, repeat([''], len(snippet) - 1)) + + for item in snippet + let add = lnum == a:lnum ? line : strpart(line, 0, a:indent - 1) + + if !(empty(item) || (type(item) == type([]) && empty(item[0]))) + if type(item) == type([]) + call setline(lnum, add . + \ snipMate#sniplist_str(item, b:snip_state.stops)) + else + call setline(lnum, add . + \ substitute(item, printf('%s\d\+\|%s{\d\+.\{-}}', + \ g:snipmate#legacy#sigil, g:snipmate#legacy#sigil), + \ '', 'g')) + endif + endif + + let lnum += 1 + endfor + + call setline(lnum - 1, getline(lnum - 1) . afterCursor) + + return col +endfunction + function! snipMate#placeholder_str(num, stops) abort return snipMate#sniplist_str(a:stops[a:num].placeholder, a:stops) endfunction @@ -93,7 +117,14 @@ function! snipMate#sniplist_str(snippet, stops) abort if type(item) == type('') let str .= item elseif type(item) == type([]) - let str .= snipMate#placeholder_str(item[0], a:stops) + let placeholder = snipMate#placeholder_str(item[0], a:stops) + if len(item) > 1 && type(item[1]) == type({}) + let placeholder = substitute(placeholder, + \ get(item[1], 'pat', ''), + \ get(item[1], 'sub', ''), + \ get(item[1], 'flags', '')) + endif + let str .= placeholder endif let pos += 1 @@ -110,7 +141,7 @@ function! s:build_stops(snippet, stops, lnum, col, indent) abort for line in a:snippet let col = s:build_loc_info(line, stops, lnum, col, []) - if line isnot line[-1] + if line isnot a:snippet[-1] let lnum += 1 let col = a:indent endif @@ -353,7 +384,7 @@ function! snipMate#DefaultPool(scopes, trigger, result) abort let s:lookup_state.extends = [] for expr in s:snippet_filenames(scope, escape(a:trigger, "*[]?{}`'$|#%")) - for path in g:snipMate.snippet_dirs + for path in s:snippet_dirs() for file in s:Glob(path, expr) source `=file` endfor @@ -385,6 +416,10 @@ fun! snipMate#GetSnippets(scopes, trigger) abort return result endf +function! s:snippet_dirs() abort + return get(g:snipMate, 'snippet_dirs', split(&rtp, ',')) +endfunction + function! snipMate#OpenSnippetFiles() abort let files = [] let scopes_done = [] @@ -394,7 +429,7 @@ function! snipMate#OpenSnippetFiles() abort let files += s:snippet_filenames(scope, '') endfor call filter(files, "v:val !~# '\\*'") - for path in g:snipMate.snippet_dirs + for path in s:snippet_dirs() let fullpaths = map(copy(files), 'printf("%s/%s", path, v:val)') let exists += filter(copy(fullpaths), 'filereadable(v:val)') let notexists += map(filter(copy(fullpaths), @@ -488,8 +523,18 @@ fun! snipMate#WordBelowCursor() abort endf fun! snipMate#GetSnippetsForWordBelowCursorForComplete(word) abort - let snippets = map(snipMate#GetSnippetsForWordBelowCursor(a:word, 0), 'v:val[0]') - return filter(snippets, 'v:val =~# "\\V\\^' . escape(a:word, '"\') . '"') + let matches = snipMate#GetSnippetsForWordBelowCursor(a:word, 0) + let snippets = [] + for [trigger, dict] in matches + if get(g:snipMate, 'description_in_completion', 0) + call extend(snippets, map(keys(dict), + \ '{ "word" : trigger, "menu" : v:val, "dup" : 1 }')) + else + call add(snippets, { "word" : trigger }) + endif + endfor + return filter(snippets, + \ 'v:val.word =~# "\\V\\^' . escape(a:word, '"\') . '"') endf fun! snipMate#CanBeTriggered() abort diff --git a/sources_non_forked/vim-snipmate/autoload/snipmate/parse.vim b/sources_non_forked/vim-snipmate/autoload/snipmate/parse.vim index dd495e95..5f842609 100644 --- a/sources_non_forked/vim-snipmate/autoload/snipmate/parse.vim +++ b/sources_non_forked/vim-snipmate/autoload/snipmate/parse.vim @@ -171,6 +171,7 @@ endfunction function! s:parser_text(till) dict abort let ret = [] + let target = ret while self.pos < self.len let lines = [] @@ -180,8 +181,12 @@ function! s:parser_text(till) dict abort if !empty(var) if var[0] is# 'VISUAL' let lines = s:visual_placeholder(var, self.indent) + " Remove trailing newline. See #245 + if lines[-1] == '' && self.next == "\n" + call remove(lines, -1) + endif elseif var[0] >= 0 - call add(ret, var) + call add(target, var) call self.add_var(var) endif endif @@ -192,8 +197,12 @@ function! s:parser_text(till) dict abort endif if !empty(lines) - call add(ret, lines[0]) - call extend(self.stored_lines, lines[1:]) + call add(target, lines[0]) + call extend(self.stored_lines, lines[1:-2]) + " Don't change targets if there's only one line + if exists("lines[1]") + let target = [lines[-1]] + endif endif " Empty lines are ignored if this is tested at the start of an iteration @@ -203,6 +212,11 @@ function! s:parser_text(till) dict abort endwhile call s:join_consecutive_strings(ret) + if target isnot ret + call s:join_consecutive_strings(target) + call extend(self.stored_lines, target) + endif + return ret endfunction diff --git a/sources_non_forked/vim-snipmate/doc/snipMate.txt b/sources_non_forked/vim-snipmate/doc/snipMate.txt index 230fe686..d00e6b20 100644 --- a/sources_non_forked/vim-snipmate/doc/snipMate.txt +++ b/sources_non_forked/vim-snipmate/doc/snipMate.txt @@ -148,7 +148,8 @@ g:snipMate.snippet_version 1 Use the newer parser If unset, SnipMate defaults to version 0. The value of this option is also used for all - .snippet files. + .snippet files. See |SnipMate-parser-versions| + for more information. g:snipMate.override As detailed below, when two snippets with the @@ -160,6 +161,12 @@ g:snipMate.override maps and other settings work. Note: Load order is determined by 'runtimepath'. +g:snipMate.description_in_completion + If set to 1 (default is 0), snippet + descriptions will be included in the popup + menu used for snippet completion, like with + snipMateShow. + g:snipMate['no_match_completion_feedkeys_chars'] A string inserted when no match for a trigger is found. By default a tab is inserted @@ -259,14 +266,18 @@ Note: Hard tabs in the expansion text are required. When the snippet is expanded in the text and 'expandtab' is set, each tab will be replaced with spaces based on 'softtabstop' if nonzero or 'shiftwidth' otherwise. -Which version parser the snippets in a file should be used with can be -specified with a version line, e.g.: > + +SnipMate currently provides two versions for the snippet parser. The +differences between them can be found at |SnipMate-parser-versions|. Which +version parser the snippets in a file should be used with can be specified +with a version line, e.g.: > version 1 Specification of a version applies to the snippets following it. Multiple version specifications can appear in a single file to intermix version 0 and -version 1 snippets. +version 1 snippets. The default is determined by the +g:snipMate.snippet_version option. |SnipMate-options| Comments can be made in .snippets files by starting a line with a # character. However these can't be used inside of snippet definitions: > @@ -280,7 +291,7 @@ However these can't be used inside of snippet definitions: > This should hopefully be clear with the included syntax highlighting. - *snipMate-extends* + *SnipMate-extends* Borrowing from UltiSnips, .snippets files can also contain an extends directive, for example: > @@ -290,6 +301,11 @@ will tell SnipMate to also read html, javascript, and css snippets. SNIPPET SYNTAX *snippet-syntax* *SnipMate-syntax* +As mentioned above, there are two versions of the snippet parser. They are +selected by the g:snipMate.snippet_version option (|SnipMate-options|) or the +version directive in .snippets files. Differences will be mentioned throughout +with a summary at |SnipMate-parser-versions|. + Anywhere in a snippet, a backslash escapes the character following it, regardless of whether that character is special or not. That is, '\a' will always result in an 'a' in the output. A single backslash can be output by @@ -360,13 +376,15 @@ edited. These look like a tab stop without a placeholder; $1 for example. In the event that no placeholder is specified for a certain tab stop--say $1--the first instance becomes the tab stop and the rest become mirrors. -Additionally substitutions similar to |:substitute| can be performed. For -instance ${1/foo/bar/g} will replace all instances of "foo" in the $1 mirror -with "bar". This uses |substitute()| behind the scenes. +Additionally, in version 1 of the parser, substitutions similar to +|:substitute| can be performed. For instance ${1/foo/bar/g} will replace all +instances of "foo" in the $1 mirror with "bar". This uses |substitute()| +behind the scenes. Note: Just like with tab stops, braces can be used to avoid ambiguities: ${1}2 is a mirror of the first tab stop followed by a 2. Version 0 of the snippet -parser offers no way to resolve such ambiguities. +parser offers no way to resolve such ambiguities. Version 0 also requires that +a tabstop have a placeholder before its mirrors work. As an example, > @@ -430,6 +448,39 @@ Example: >
${0:${VISUAL:}}
+< + *SnipMate-parser-versions* +Parser Versions~ + +SnipMate provides two versions for its snippet parser. Version 0 is the legacy +regex based version and is updated sparingly. Version 1 is the revamped +version with new features. Any newly developed features will likely only be +available to version 1 users. + +Which version is used is determined by version directives in snippet files +(|SnipMate-snippet-files|) and by the g:snipMate.snippet_version option +(|SnipMate-options|). + +A complete list of current differences is as follows: +- Backslash escaping is guaranteed to work in version 1. In certain edge cases + this may not work in version 0. +- Certain syntactic errors, such as a missing closing brace for a tabstop, are + more gracefully handled in version 1. In most cases, the parser will either + discard the error or, as in the previous example, end an item at the end of + line. Version 0 may not be predictable in this regard. +- Braces are not mandatory in version 1. SnipMate will determine which + instance of a stop ID to use based on the presence of a placeholder, or + whichever instance occurs first. Braces can therefore be used to + disambiguate between stop 12, $12, and stop 1 followed by a 2, ${1}2. In + other words, version 0 makes a distinction between a mirror and a stop while + version 1 resolves the differences for you. +- Placeholders are not mandatory to enable mirror support in version 1. +- Version 0 uses the confusing syntax {VISUAL} to refer to visual content. + Version 1 treats it as just another stop ID, so both $VISUAL and ${VISUAL} + work. Plus version 1 allows a default value in case no visual selection has + been made. +- Transformations similar to |:substitute| can be preformed on any mirror, + including visual content. ============================================================================== SNIPPET SOURCES *SnipMate-snippet-sources* diff --git a/sources_non_forked/vim-snipmate/plugin/snipMate.vim b/sources_non_forked/vim-snipmate/plugin/snipMate.vim index 837f0dcc..75e74aab 100644 --- a/sources_non_forked/vim-snipmate/plugin/snipMate.vim +++ b/sources_non_forked/vim-snipmate/plugin/snipMate.vim @@ -93,8 +93,7 @@ endif let g:snipMate['get_snippets'] = get(g:snipMate, 'get_snippets', funcref#Function("snipMate#GetSnippets")) " List of paths where snippets/ dirs are located -let g:snipMate['snippet_dirs'] = get(g:snipMate, 'snippet_dirs', split(&rtp, ',')) -if type(g:snipMate['snippet_dirs']) != type([]) +if exists('g:snipMate.snippet_dirs') && type(g:snipMate['snippet_dirs']) != type([]) echohl WarningMsg echom "g:snipMate['snippet_dirs'] must be a List" echohl None diff --git a/sources_non_forked/vim-snipmate/t/parser.vim b/sources_non_forked/vim-snipmate/t/parser.vim index c5cf8739..3c2aa6e5 100644 --- a/sources_non_forked/vim-snipmate/t/parser.vim +++ b/sources_non_forked/vim-snipmate/t/parser.vim @@ -118,6 +118,16 @@ describe 'snippet parser' \ ["\t baz"], ["x"]] end + it 'removes newlines from the end of VISUALs if before an end of line' + let b:snipmate_visual = "1\n2\n" + Expect Parse("x\n$VISUAL\nx") == [['x'], ['1'], ['2'], ['x']] + end + + it 'splits the before and after a $VISUAL if it is multiline' + let b:snipmate_visual = "1\n2\n3" + Expect Parse("foo $VISUAL bar") == [['foo 1'], ['2'], ['3 bar']] + end + it 'determines which var with an id is the stop' let [snip, stops] = Parse("$1$1$1", 0, 1) Expect snip == [[[1, "", stops[1]], [1, {}], [1, {}]]] diff --git a/sources_non_forked/vim-snippets/.gitignore b/sources_non_forked/vim-snippets/.gitignore index 0d20b648..f3d74a9a 100644 --- a/sources_non_forked/vim-snippets/.gitignore +++ b/sources_non_forked/vim-snippets/.gitignore @@ -1 +1,2 @@ *.pyc +*~ diff --git a/sources_non_forked/vim-snippets/AUTHORS b/sources_non_forked/vim-snippets/AUTHORS new file mode 100644 index 00000000..907daef1 --- /dev/null +++ b/sources_non_forked/vim-snippets/AUTHORS @@ -0,0 +1,383 @@ +Authors +=============================================================================== + +Generated with "git log --oneline --pretty="%an" | sort | uniq > AUTHORS + +Aaron Broder +Adnan Zafar +afolmert +aisensiy +Alexander Ross +Alexandre de Oliveira +Alexey Shevchenko +Alex Tan +Allen.M +Alvin Chan +ALX-Liu-Xiao +Andrea Giardini +Andreas Krennmair +Andreas Steinel +Andrei Cristian Petcu +Andrej Radovic +Andre Walker +Andrey Paskal +Andy Waite +Angel Alonso +Ángel Alonso +Anne Douwe Bouma +Anthony Wilson +Arvind +ashfinal +Audrius Kažukauskas +Austin Wood +Aydar Khabibullin +babybeasimple +Benjamin Nørgaard +Bernhard Graf +Bill Casarin +binaryplease +Björn +Björn-Egil Dahlberg +BlackEagle +Boone Severson +bounceme +Bradlee Speice +Brandon Dulaney +Brandon Hilkert +Brian Hogan +Brian van Burken +Bruno Sutic +Camilo Payan +carme +Cézar Antáres +Chad Paradis +Chen Zhongzheng +Ches Martin +ChickenNuggers +Chipairon +Chris Dueck +Chris Nicola +Chris Sims +Christian +Christian Höltje +Christian Neumüller +Christopher Joslyn +chrisyue +Ciro Santilli +Ciro Santilli 六四事件 法轮功 +Claudio Maradonna +Connor Atherton +Cooper LeBrun +Corentin Peuvrel +Craig Paterson +Craig P Jolicoeur +crazymaster +daa84 +Daeyun Shin +Dale Roberts +Daniel Hahler +Dan Loewenherz +Danny Navarro +daoo +Darrell Hamilton +David Arvelo +David Barnett +David C. Bishop +David Deryl Downey - AKA Deryl R. Doucette +David Rodríguez de Dios +David Sanson +dengyaolong +Derek Morey +dhilipsiva +djdt +Dmitry Dementev +Donny Yang +DSIW +dzikie drożdże +Eduardo Gurgel +Eli Gundry +emzap79 +Enric Lluelles +Enrico Maria De Angelis +Erich Heine +Erik Westrup +Ernest +Eugene Kalinin +Eustaquio Rangel +Eustáquio Rangel +Fatih Arslan +Felix Jung +Filipe Giusti +Florent Lévigne +Florian Sattler +frans +Fuad Saud +Gabriel Chavez +Gaël Chamoulaud +Gea-Suan Lin +George Guimarães +George Lee +Georgios Samaras +Gert +gfixler +Gilad Peleg +gk +goonnow +Gueunet Charles +Gui Lin +guneysus +Gustavo Chain +Gustavo Ferreira +Hans-Guenter +Harald Wartig +Henrik Kjelsberg +HIRAKI Satoru +Holger Rapp +Honza +Honza Pokorny +hulufei +Igor Goldvekht +Ilker Cetinkaya +indi +Indra Susila +Ionică Bizău +Iuri Fernandes +Jack Stalnaker +Jacobo de Vera +Jacques Kvam +jake romer +Jakub Stasiak +James Turley +Jan Mollowitz +Jason S. Jones +Jean Jordaan +Jeffrey Tratner +Jens Hoepken +jiangyc0 +Jim Deville +Jinzhu +Joey Curtin +Johannes Wienke +jonasac +Jonas Bygdén +Jonathan Martin +Jorge García +Jorge López Pérez +Joseph Lin +Josh Bode +Josh Davis +Josh Matthews +Josh Vandergrift +Josh Wainwright +JuanPablo +Julian Bennecker +Julien Deniau +Julien Pivard +Julien Stechele +Julien STECHELE +Kalinin Eugene +kenshin54 +Kentaro Imai +Kevin Koltz +Kevin Lui +Kevin Mees +Kevin Murray +Kevin Schaul +Konstantin +Konstantin Gorodinskiy +Laas Toom +Laurent Georget +laxtiz +Leandro Moreira +Leonardo B +Leonidez Acosta +linduxed +Li Xin +Louis +Louis Pilfold +Lucas Hoffmann +Luis Carlos Cruz +Luis Carlos Cruz Carballo +Luiz Gonzaga dos Santos Filho +majjoha +mangege +Marc Camuzat +Marcelo D Montu +Marcelo Jacobus +Marcin Kulik +Marcus Kammer +Marc Weber +Mario de Frutos +Markus Benning +marocchino +Martin Atukunda +Martin Heuschober +Martxel Lasa +Matěj Cepl +Mathew Attlee +Mathieu Comandon +Matthew Barry +Matthias Viehweger +Mattia Tezzele +Matt Rasband +Matt Stevens +Mauro Porras P +Maximiliano Robaina +Mayeu (Cast) +Meng Zhuo +Michael Gehring +Michael Hinrichs +Michael Rutter +Michael Thessel +Michi Huber +Mickey +midchildan +Mike Foley +Mike Smullin +Miki Tebeka +Minjong Chung +M. Maxwell Watson +mMontu +mockturtl +m-pilia +Muhammad Hallaj Subery +mwcz +Namit +Nan Cloudio Jiang +Nan Zheng +Nate Mara +netei +Ngo The Trung +Nguyen Le +Nick Janetakis +Nicklasos +Nick Papanastasiou +Nicolas G. Querol +Nico Suhl +No Ducks +Norman Messtorff +obaoba +oddlydrawn +Oleg Voronkovich +Ole Hansen +Oliver Andrich +Ondrej Slinták +onemanstartup +opennota +Paco Esteban +Panagiotis Mavrogiorgos +Paolo Cretaro +Pascal +Paulo Romeira +Pawel Jankowski +phcerdan +Philippe Mongeau +Philipp Jovanovic +Piotr Jawniak +Piotr Yordanov +Pirogov Evgenij +Pompeu +Povilas Balzaravicius Pawka +Procras +protream +pydave +r4d2 +Radosław Szymczyszyn +Ralph-Wang +Raül Torralba +raydeal +rcolombo +Rekky +René +Rene Vergara +Renzo Poddighe +Reyes Yang +ricardogcolombo +Ricardo Jesus +Rich Layte +Roberto Miranda +robin +Robin Grindrod +Rok Garbas +Roland Sommer +Rory McNamara +rsw0x +rtorralba +Ruben Vereecken +Ryan Bright +Ryan Pineo +Ryan Wang +Sam Shepherd +Santiago Gallego +sasidhar-d +Sathors +Sebastian Röder +Sebastian Wiesner +Sergey Lebedev +Sergey Zasenko +Serhiy Oplakanets +SevereOverfl0w +Simeon F. Willbanks +Simeon Willbanks +Simon Désaulniers +sirex +skv +Sokovikov +Srijan Choudhary +Steeve +stefan +Stephen Tudor +Stephen Woods +Steve Brown +Steven Humphrey +Steven Oliver +Stuart Grimshaw +Sudar +¨switch87¨ +Tevin Zhang +theocrite +Thiago de Arruda +Thomas Duerr +Thomas Szymanski +tinyladi +Tobias Witt +Tobie Warburton +Tomasz Wisniewski +Tom Vincent +Tony +Tony Narlock +toogley +Torbjørn Vatn +tormaroe +ToruIwashita +Travis Holton +Trevor Sullivan +troydm +tUrG0n +twabiko +Tyler Ball +tyronepost +Tyrone Post +Vadim Khohlov +Vincent Hsu +Vladimir Rybas +Vladislav Khvostov +Vorzard +Vzaa +Waldecir Santos +Wildsky Fann +William Ma +William Travis Holton +X4fyr +xz.zhang +Yamamoto Yuji +Yannick Brehon +yerv000 +Yike Lu +yuhuanbo +Yu Huanbo +Yves Lange +yvhn +zauguin +Zaven Muradyan +ZPH diff --git a/sources_non_forked/vim-snippets/README.md b/sources_non_forked/vim-snippets/README.md index d4e83c33..5567c5d9 100644 --- a/sources_non_forked/vim-snippets/README.md +++ b/sources_non_forked/vim-snippets/README.md @@ -131,14 +131,14 @@ Don't add useless placeholder default texts like: ``` if (${1:condition}){ - ${2:some code here} + ${0:some code here} } ``` instead use: ``` if (${1}){ - ${2} + ${0:${VISUAL}} } ``` @@ -148,6 +148,8 @@ get vim-dev plugin which has function completion Thus for conditions (while, if ..) and block bodies just use ${N} - Thanks +When the snippet can be used to wrap existing code leverage `${VISUAL}` + Open questions: What about one line if ee then .. else .. vs if \n .. then \n ... \n else \n .. ? Which additional policies to add? diff --git a/sources_non_forked/vim-snippets/UltiSnips/ada.snippets b/sources_non_forked/vim-snippets/UltiSnips/ada.snippets index cc35c2c2..bea2a6cd 100644 --- a/sources_non_forked/vim-snippets/UltiSnips/ada.snippets +++ b/sources_non_forked/vim-snippets/UltiSnips/ada.snippets @@ -5,7 +5,9 @@ global !p def ada_case(word): out = word[0].upper() for i in range(1, len(word)): - if word[i - 1] == '_': + if word[i] == '-': + out = out + '.' + elif word[i - 1] == '_' or word[i - 1] == '-': out = out + word[i].upper() else: out = out + word[i] diff --git a/sources_non_forked/vim-snippets/UltiSnips/all.snippets b/sources_non_forked/vim-snippets/UltiSnips/all.snippets index 0e286e5a..6d77cc59 100644 --- a/sources_non_forked/vim-snippets/UltiSnips/all.snippets +++ b/sources_non_forked/vim-snippets/UltiSnips/all.snippets @@ -18,7 +18,7 @@ snippet box "A nice box with the current comment symbol" b box = make_box(len(t[1])) snip.rv = box[0] snip += box[1] -`${1:content}`!p +`${1:${VISUAL:content}}`!p box = make_box(len(t[1])) snip.rv = box[2] snip += box[3]` @@ -32,7 +32,7 @@ if not snip.c: box = make_box(len(t[1]), width) snip.rv = box[0] snip += box[1] -`${1:content}`!p +`${1:${VISUAL:content}}`!p box = make_box(len(t[1]), width) snip.rv = box[2] snip += box[3]` @@ -73,4 +73,31 @@ snippet modeline "Vim modeline" vim`!v ':set '. (&expandtab ? printf('et sw=%i ts=%i', &sw, &ts) : printf('noet sts=%i sw=%i ts=%i', &sts, &sw, &ts)) . (&tw ? ' tw='. &tw : '') . ':'` endsnippet +######### +# DATES # +######### +snippet date "YYYY-MM-DD" w +`!v strftime("%F")` +endsnippet + +snippet ddate "Month DD, YYYY" w +`!v strftime("%b %d, %Y")` +endsnippet + +snippet diso "ISO format datetime" w +`!v strftime("%F %H:%M:%S%z")` +endsnippet + +snippet time "hh:mm" w +`!v strftime("%H:%M")` +endsnippet + +snippet datetime "YYYY-MM-DD hh:mm" w +`!v strftime("%Y-%m-%d %H:%M")` +endsnippet + +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]` +endsnippet + # vim:ft=snippets: diff --git a/sources_non_forked/vim-snippets/UltiSnips/blade.snippets b/sources_non_forked/vim-snippets/UltiSnips/blade.snippets new file mode 100644 index 00000000..26fde179 --- /dev/null +++ b/sources_non_forked/vim-snippets/UltiSnips/blade.snippets @@ -0,0 +1,139 @@ +priority -50 + +extends html + +# We want to overwrite everything in parent ft. +priority -49 + +snippet break "@break" +@break +endsnippet + +snippet component "@component directive" +@component('$1') + ${2:${VISUAL}} +@endcomponent +endsnippet + +snippet each "@each directive" +@each('$1', $$2, '$3') +endsnippet + +snippet else "@else directive" +@else +endsnippet + +snippet eif "@else if directive" +@else if ($1) + ${2:${VISUAL}} +endsnippet + +snippet for "@for directive" +@for ($1) + ${2:${VISUAL}} +@endfor +endsnippet + +snippet foreach "@foreach directive" +@foreach ($$1 as $$2) + ${3:${VISUAL}} +@endforeach +endsnippet + +snippet extends "@extends directive" +@extends('$1') +endsnippet + +snippet if "@if directive" +@if ($1) + ${2:${VISUAL}} +@endif +endsnippet + +snippet ife "@if @else structure" +@if ($1) + ${2:${VISUAL}} +@else + ${3:${VISUAL}} +@endif +endsnippet + +snippet include "@include directive" +@include('$1') +endsnippet + +snippet includeIf "@includeIf directive" +@includeIf('$1') +endsnippet + +snippet isset "@isset directive" +@isset + ${1:${VISUAL}} +@endisset +endsnippet + +snippet inject "@inject directive" +@inject('$1', '$2') +endsnippet + +snippet lang "@lang directive" i +@lang('$1') +endsnippet + +snippet php "@php directive" +@php + ${1:${VISUAL}} +@endphp +endsnippet + +snippet push "@push directive" +@push('$1') + ${2:${VISUAL}} +@endpush +endsnippet + +snippet section "@section directive" +@section('$1') +endsnippet + +snippet show "@show directive" +@show +endsnippet + +snippet slot "@slot directive" +@slot('$1') + ${2:${VISUAL}} +@endslot +endsnippet + +snippet unless "@unless directive" +@unless + ${1:${VISUAL}} +@endunless +endsnippet + +snippet verbatim "@verbatim directive" +@verbatim + ${0:$VISUAL} +@endverbatim +endsnippet + +snippet wh "@while directive" +@while ($1) + ${2:${VISUAL}} +@endwhile +endsnippet + +snippet yield "@yield directive" +@yield('$1') +endsnippet + +snippet { "{{ }} statement." i +{{ $1 }} +endsnippet + +snippet {! "{!! !!} statement" i +{!! $1 !!} +endsnippet + +# vim:ft=snippets: diff --git a/sources_non_forked/vim-snippets/UltiSnips/c.snippets b/sources_non_forked/vim-snippets/UltiSnips/c.snippets index c9894649..6851a272 100644 --- a/sources_non_forked/vim-snippets/UltiSnips/c.snippets +++ b/sources_non_forked/vim-snippets/UltiSnips/c.snippets @@ -5,7 +5,7 @@ priority -50 snippet def "#define ..." -#define ${1} +#define $1 endsnippet snippet #ifndef "#ifndef ... #define ... #endif" @@ -16,7 +16,7 @@ endsnippet snippet #if "#if #endif" b #if ${1:0} -${VISUAL}${0} +${VISUAL}$0 #endif endsnippet @@ -32,20 +32,20 @@ endsnippet snippet main "main() (main)" int main(int argc, char *argv[]) { - ${VISUAL}${0} + ${VISUAL}$0 return 0; } endsnippet snippet for "for loop (for)" for (${2:i} = 0; $2 < ${1:count}; ${3:++$2}) { - ${VISUAL}${0} + ${VISUAL}$0 } endsnippet snippet fori "for int loop (fori)" for (${4:int} ${2:i} = 0; $2 < ${1:count}; ${3:++$2}) { - ${VISUAL}${0} + ${VISUAL}$0 } endsnippet @@ -60,7 +60,7 @@ else: snip.rv = snip.c`} #define $1 -${VISUAL}${0} +${VISUAL}$0 #endif /* end of include guard: $1 */ endsnippet @@ -71,7 +71,7 @@ endsnippet snippet eli "else if .. (eli)" else if (${1:/* condition */}) { - ${VISUAL}${0} + ${VISUAL}$0 } endsnippet @@ -86,14 +86,14 @@ struct ${1:`!p snip.rv = (snip.basename or "name") + "_t"`} { endsnippet snippet fun "function" b -${1:void} ${2:function_name}(${3}) +${1:void} ${2:function_name}($3) { - ${VISUAL}${0} + ${VISUAL}$0 } endsnippet snippet fund "function declaration" b -${1:void} ${2:function_name}(${3}); +${1:void} ${2:function_name}($3); endsnippet # vim:ft=snippets: diff --git a/sources_non_forked/vim-snippets/UltiSnips/coffee-react.snippets b/sources_non_forked/vim-snippets/UltiSnips/coffee-react.snippets index 4cdb40f8..3090c571 100644 --- a/sources_non_forked/vim-snippets/UltiSnips/coffee-react.snippets +++ b/sources_non_forked/vim-snippets/UltiSnips/coffee-react.snippets @@ -12,7 +12,7 @@ snippet createClass "React define Class" b ${1:classname}Class = React.createClass displayName: "$1" render: -> - ${2} + $2 $1 = React.createFactory($1) endsnippet @@ -23,58 +23,58 @@ endsnippet snippet propType "React propType (key/value)" b ${1:myVar}: React.PropTypes.${2:type}${3:.isRequired} -${4} +$4 endsnippet snippet setState "React setState" b @setState ${1:myvar}: ${2:myvalue} - ${3} + $3 endsnippet snippet getInitialState "React define getInitialState" b getInitialState: -> ${1:myvar}: ${2:myvalue} - ${3} + $3 endsnippet snippet getDefaultProps "React define getDefaultProps" b getDefaultProps: -> ${1:myvar}: ${2:myvalue} - ${3} + $3 endsnippet snippet componentWillMount "React define componentWillMount" b componentWillMount: -> - ${1} + $1 endsnippet snippet componentDidMount "React define componentDidMount" b componentDidMount: -> - ${1} + $1 endsnippet snippet componentWillReceiveProps "React define componentWillReceiveProps" b componentWillReceiveProps: (nextProps) -> - ${1} + $1 endsnippet snippet shouldComponentUpdate "React define shouldComponentUpdate" b shouldComponentUpdate: (nextProps, nextState) -> - ${1} + $1 endsnippet snippet componentWillUpdate "React define componentWillUpdate" b componentWillUpdate: (nextProps, nextState) -> - ${1} + $1 endsnippet snippet componentDidUpdate "React define componentDidUpdate" b componentDidUpdate: (prevProps, prevState) -> - ${1} + $1 endsnippet snippet componentWillUnmount "React define componentWillUnmount" b componentWillUnmount: -> - ${1} + $1 endsnippet diff --git a/sources_non_forked/vim-snippets/UltiSnips/cpp.snippets b/sources_non_forked/vim-snippets/UltiSnips/cpp.snippets index f7c2bd83..bb79a0e1 100644 --- a/sources_non_forked/vim-snippets/UltiSnips/cpp.snippets +++ b/sources_non_forked/vim-snippets/UltiSnips/cpp.snippets @@ -4,6 +4,28 @@ extends c # We want to overwrite everything in parent ft. priority -49 +########################################################################### +# Global functions # +########################################################################### + +global !p + +def write_docstring_args(arglist, snip): + args = str(arglist).split(',') + + if len(args) > 1: + c = 0 + for arg in args: + if c == 0: + snip.rv += arg + c = 1 + else: + snip += '* : %s' % arg.strip() + else: + snip.rv = args[0] + + +endglobal ########################################################################### # TextMate Snippets # @@ -27,7 +49,7 @@ endsnippet snippet ns "namespace .. (namespace)" namespace${1/.+/ /m}${1:`!p snip.rv = snip.basename or "name"`} { - ${VISUAL}${0} + ${VISUAL}$0 }${1/.+/ \/* /m}$1${1/.+/ *\/ /m} endsnippet @@ -61,7 +83,7 @@ snippet cla "An entire .h generator" b class ${1:`!v substitute(substitute(vim_snippets#Filename('$1','ClassName'),'^.','\u&',''), '_\(\w\)', '\u\1', 'g')`} { private: - ${3} + $3 public: $1(); @@ -70,4 +92,19 @@ public: #endif /* $2 */ endsnippet + + +snippet fnc "Basic c++ doxygen function template" b +/** +* @brief: ${4:brief} +* +* @param: `!p write_docstring_args(t[3],snip)` +* +* @return: `!p snip.rv = t[1]` +*/ +${1:ReturnType} ${2:FunctionName}(${3:param}) +{ + ${0:FunctionBody} +} +endsnippet # vim:ft=snippets: diff --git a/sources_non_forked/vim-snippets/UltiSnips/crystal.snippets b/sources_non_forked/vim-snippets/UltiSnips/crystal.snippets new file mode 100644 index 00000000..cab946f4 --- /dev/null +++ b/sources_non_forked/vim-snippets/UltiSnips/crystal.snippets @@ -0,0 +1,13 @@ +priority -50 + +snippet "\b(de)?f" "def ..." r +def ${1:method_name}${2:(${3:*args})} + $0 +end +endsnippet + +snippet "\b(pde)?f" "private def ..." r +private def ${1:method_name}${2:(${3:*args})} + $0 +end +endsnippet diff --git a/sources_non_forked/vim-snippets/UltiSnips/cs.snippets b/sources_non_forked/vim-snippets/UltiSnips/cs.snippets index aca245e5..13d3c971 100644 --- a/sources_non_forked/vim-snippets/UltiSnips/cs.snippets +++ b/sources_non_forked/vim-snippets/UltiSnips/cs.snippets @@ -16,7 +16,7 @@ namespace ${1:MyNamespace} endsnippet snippet class "class" w -class ${1:MyClass} +${1:public} class ${2:MyClass} { $0 } @@ -259,7 +259,7 @@ finally endsnippet snippet throw "throw" -throw new ${1}Exception("${2}"); +throw new $1Exception("$2"); endsnippet @@ -288,6 +288,10 @@ snippet cw "Console.WriteLine" b Console.WriteLine("$1"); endsnippet +snippet cr "Console.ReadLine" b +Console.ReadLine(); +endsnippet + # as you first type comma-separated parameters on the right, {n} values appear in the format string snippet cwp "Console.WriteLine with parameters" b Console.WriteLine("${2:`!p @@ -300,9 +304,9 @@ MessageBox.Show("${1:message}"); endsnippet -################## -# full methods # -################## +############# +# methods # +############# snippet equals "Equals method" b public override bool Equals(object obj) @@ -316,13 +320,53 @@ public override bool Equals(object obj) } endsnippet +snippet mth "Method" b +${1:public} ${2:void} ${3:MyMethod}(${4}) +{ + $0 +} +endsnippet + +snippet mths "Static method" b +${1:public} static ${2:void} ${3:MyMethod}(${4}) +{ + $0 +} +endsnippet + +############### +# constructor # +############### + +snippet ctor "Constructor" b +${1:public} ${2:`!p snip.rv = snip.basename or "untitled"`}(${3}) +{ + $0 +} +endsnippet ############## # comments # ############## -snippet /// "XML comment" b +snippet /// "XML summary comment" b /// -/// $1 +/// $0 /// endsnippet + +snippet

${2} +endsnippet + +snippet ${2} +endsnippet + +snippet $0 +endsnippet + +snippet $0 +endsnippet diff --git a/sources_non_forked/vim-snippets/UltiSnips/css.snippets b/sources_non_forked/vim-snippets/UltiSnips/css.snippets index ff265093..f5ccd2ff 100644 --- a/sources_non_forked/vim-snippets/UltiSnips/css.snippets +++ b/sources_non_forked/vim-snippets/UltiSnips/css.snippets @@ -1,11 +1,5 @@ priority -50 -snippet . "selector { }" -$1 { - $0 -} -endsnippet - snippet p "padding" padding: ${1:0};$0 endsnippet diff --git a/sources_non_forked/vim-snippets/UltiSnips/cuda.snippets b/sources_non_forked/vim-snippets/UltiSnips/cuda.snippets new file mode 100644 index 00000000..2a9a7e5e --- /dev/null +++ b/sources_non_forked/vim-snippets/UltiSnips/cuda.snippets @@ -0,0 +1,5 @@ +priority -50 + +extends cpp + +# vim:ft=snippets: diff --git a/sources_non_forked/vim-snippets/UltiSnips/d.snippets b/sources_non_forked/vim-snippets/UltiSnips/d.snippets index 9ce27513..a9d89b84 100644 --- a/sources_non_forked/vim-snippets/UltiSnips/d.snippets +++ b/sources_non_forked/vim-snippets/UltiSnips/d.snippets @@ -23,7 +23,7 @@ mixin ${1:/*mixed_in*/} ${2:/*name*/}; endsnippet snippet new "new (new)" -new ${1}(${2}); +new $1($2); endsnippet snippet scpn "@safe const pure nothrow (scpn)" @@ -98,7 +98,7 @@ endsnippet snippet enf "enforce (enf)" b enforce(${1:/*condition*/}, - new ${2}Exception(${3:/*args*/})); + new $2Exception(${3:/*args*/})); endsnippet # Branches @@ -106,14 +106,14 @@ endsnippet snippet if "if .. (if)" if(${1:/*condition*/}) { - ${VISUAL}${0} + ${VISUAL}$0 } endsnippet snippet ife "if .. else (ife)" b if(${1:/*condition*/}) { - ${2} + $2 } else { @@ -124,14 +124,14 @@ endsnippet snippet el "else (el)" b else { - ${VISUAL}${1} + ${VISUAL}$1 } endsnippet snippet elif "else if (elif)" b else if(${1:/*condition*/}) { - ${VISUAL}${0} + ${VISUAL}$0 } endsnippet @@ -139,10 +139,10 @@ snippet sw "switch (sw)" switch(${1:/*var*/}) { case ${2:/*value*/}: - ${3} + $3 break; case ${4:/*value*/}: - ${5} + $5 break; ${7:/*more cases*/} default: @@ -154,10 +154,10 @@ snippet fsw "final switch (fsw)" final switch(${1:/*var*/}) { case ${2:/*value*/}: - ${3} + $3 break; case ${4:/*value*/}: - ${5} + $5 break; ${7:/*more cases*/} } @@ -165,7 +165,7 @@ endsnippet snippet case "case (case)" b case ${1:/*value*/}: - ${2} + $2 break; endsnippet @@ -178,42 +178,42 @@ endsnippet snippet do "do while (do)" b do { - ${VISUAL}${2} + ${VISUAL}$2 } while(${1:/*condition*/}); endsnippet snippet wh "while (wh)" b while(${1:/*condition*/}) { - ${VISUAL}${2} + ${VISUAL}$2 } endsnippet snippet for "for (for)" b for (${4:size_t} ${2:i} = 0; $2 < ${1:count}; ${3:++$2}) { - ${VISUAL}${0} + ${VISUAL}$0 } endsnippet snippet forever "forever (forever)" b for(;;) { - ${VISUAL}${0} + ${VISUAL}$0 } endsnippet snippet fore "foreach (fore)" foreach(${1:/*elem*/}; ${2:/*range*/}) { - ${VISUAL}${3} + ${VISUAL}$3 } endsnippet snippet forif "foreach if (forif)" b foreach(${1:/*elem*/}; ${2:/*range*/}) if(${3:/*condition*/}) { - ${VISUAL}${4} + ${VISUAL}$4 } endsnippet @@ -222,7 +222,7 @@ snippet in "in contract (in)" b in { assert(${1:/*condition*/}, "${2:error message}"); - ${3} + $3 } body endsnippet @@ -231,7 +231,7 @@ snippet out "out contract (out)" b out${1:(result)} { assert(${2:/*condition*/}, "${3:error message}"); - ${4} + $4 } body endsnippet @@ -240,7 +240,7 @@ snippet inv "invariant (inv)" b invariant() { assert(${1:/*condition*/}, "${2:error message}"); - ${3} + $3 } endsnippet @@ -249,21 +249,21 @@ endsnippet snippet fun "function definition (fun)" ${1:void} ${2:/*function name*/}(${3:/*args*/}) ${4:@safe pure nothrow} { - ${VISUAL}${5} + ${VISUAL}$5 } endsnippet snippet void "void function definition (void)" void ${1:/*function name*/}(${2:/*args*/}) ${3:@safe pure nothrow} { - ${VISUAL}${4} + ${VISUAL}$4 } endsnippet snippet this "ctor (this)" w this(${1:/*args*/}) { - ${VISUAL}${2} + ${VISUAL}$2 } endsnippet @@ -295,16 +295,16 @@ endsnippet snippet scope "scope (scope)" b scope(${1:exit}) { - ${VISUAL}${2} + ${VISUAL}$2 } endsnippet # With snippet with "with (with)" -with(${1}) +with($1) { - ${VISUAL}${2} + ${VISUAL}$2 } endsnippet @@ -315,7 +315,7 @@ try { ${VISUAL}${1:/*code to try*/} } -catch(${2}Exception e) +catch($2Exception e) { ${3:/*handle exception*/} } @@ -326,7 +326,7 @@ try { ${VISUAL}${1:/*code to try*/} } -catch(${2}Exception e) +catch($2Exception e) { ${3:/*handle exception*/} } @@ -337,14 +337,14 @@ finally endsnippet snippet catch "catch (catch)" b -catch(${1}Exception e) +catch($1Exception e) { ${2:/*handle exception*/} } endsnippet snippet thr "throw (thr)" -throw new ${1}Exception("${2}"); +throw new $1Exception("$2"); endsnippet @@ -353,35 +353,35 @@ endsnippet snippet struct "struct (struct)" struct ${1:`!p snip.rv = (snip.basename or "name")`} { - ${2} + $2 } endsnippet snippet union "union (union)" union ${1:`!p snip.rv = (snip.basename or "name")`} { - ${2} + $2 } endsnippet snippet class "class (class)" class ${1:`!p snip.rv = (snip.basename or "name")`} { - ${2} + $2 } endsnippet snippet inter "interface (inter)" interface ${1:`!p snip.rv = (snip.basename or "name")`} { - ${2} + $2 } endsnippet snippet enum "enum (enum)" enum ${1:`!p snip.rv = (snip.basename or "name")`} { - ${2} + $2 } endsnippet @@ -390,7 +390,7 @@ endsnippet snippet exc "exception declaration (exc)" b /// ${3:/*documentation*/} -class ${1}Exception : ${2}Exception +class $1Exception : $2Exception { public this(string msg, string file = __FILE__, int line = __LINE__) { @@ -405,14 +405,14 @@ endsnippet snippet version "version (version)" b version(${1:/*version name*/}) { - ${VISUAL}${2} + ${VISUAL}$2 } endsnippet snippet debug "debug" b debug { - ${VISUAL}${1} + ${VISUAL}$1 } endsnippet @@ -422,7 +422,7 @@ endsnippet snippet temp "template (temp)" b template ${2:/*name*/}(${1:/*args*/}) { - ${3} + $3 } endsnippet @@ -440,7 +440,7 @@ endsnippet snippet unittest "unittest (unittest)" b unittest { - ${1} + $1 } endsnippet @@ -450,21 +450,21 @@ endsnippet snippet opDis "opDispatch (opDis)" b ${1:/*return type*/} opDispatch(string s)() { - ${2}; + $2; } endsnippet snippet op= "opAssign (op=)" b -void opAssign(${1} rhs) ${2:@safe pure nothrow} +void opAssign($1 rhs) ${2:@safe pure nothrow} { - ${2} + $2 } endsnippet snippet opCmp "opCmp (opCmp)" b -int opCmp(${1} rhs) @safe const pure nothrow +int opCmp($1 rhs) @safe const pure nothrow { - ${2} + $2 } endsnippet @@ -484,7 +484,7 @@ endsnippet snippet toString "toString (toString)" b string toString() @safe const pure nothrow { - ${1} + $1 } endsnippet @@ -493,7 +493,7 @@ endsnippet snippet todo "TODO (todo)" -// TODO: ${1} +// TODO: $1 endsnippet @@ -509,16 +509,16 @@ snippet fdoc "function ddoc block (fdoc)" b /// ${1:description} /// /// ${2:Params: ${3:param} = ${4:param description} -/// ${5}} +/// $5} /// /// ${6:Returns: ${7:return value}} /// -/// ${8:Throws: ${9}Exception ${10}} +/// ${8:Throws: $9Exception $10} endsnippet snippet Par "Params (Par)" Params: ${1:param} = ${2:param description} -/// ${3} +/// $3 endsnippet snippet Ret "Returns (Ret)" @@ -526,7 +526,7 @@ Returns: ${1:return value/s} endsnippet snippet Thr "Throws (Thr)" -Throws: ${1}Exception ${2} +Throws: $1Exception $2 endsnippet snippet Example "Examples (Example)" @@ -556,7 +556,7 @@ snippet gpl "GPL (gpl)" b // // Copyright (C) ${1:Author}, `!v strftime("%Y")` -${2} +$2 endsnippet snippet boost "Boost (boost)" b @@ -565,7 +565,7 @@ snippet boost "Boost (boost)" b // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -${2} +$2 endsnippet @@ -577,8 +577,8 @@ snippet module "New module (module)" b // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -module ${2}.`!v vim_snippets#Filename('$1', 'name')`; +module $2.`!v vim_snippets#Filename('$1', 'name')`; -${3} +$3 endsnippet diff --git a/sources_non_forked/vim-snippets/UltiSnips/django.snippets b/sources_non_forked/vim-snippets/UltiSnips/django.snippets index 0ba6c9d5..d6e2d434 100644 --- a/sources_non_forked/vim-snippets/UltiSnips/django.snippets +++ b/sources_non_forked/vim-snippets/UltiSnips/django.snippets @@ -124,7 +124,7 @@ endsnippet snippet model "Model" b class ${1:MODELNAME}(models.Model): - ${0} + $0 class Meta: verbose_name = "$1" verbose_name_plural = "$1s" @@ -275,67 +275,67 @@ endsnippet # VIEWS SNIPPETS snippet adminview "Model Admin View" b -class ${1}Admin(admin.ModelAdmin): +class $1Admin(admin.ModelAdmin): ''' - Admin View for ${1} + Admin View for $1 ''' - list_display = ('${2}',) - list_filter = ('${3}',) + list_display = ('$2',) + list_filter = ('$3',) inlines = [ - ${4}Inline, + $4Inline, ] - raw_id_fields = ('${5}',) - readonly_fields = ('${6}',) - search_fields = ['${7}'] -admin.site.register(${1}, ${1}Admin) + raw_id_fields = ('$5',) + readonly_fields = ('$6',) + search_fields = ['$7'] +admin.site.register($1, $1Admin) endsnippet snippet createview "Generic Create View" b class ${1:MODEL_NAME}CreateView(CreateView): - model = ${1:MODEL_NAME} + model = $1 template_name = "${2:TEMPLATE_NAME}" endsnippet snippet deleteview "Generic Delete View" b class ${1:MODEL_NAME}DeleteView(DeleteView): - model = ${1:MODEL_NAME} + model = $1 template_name = "${2:TEMPLATE_NAME}" endsnippet snippet detailview "Generic Detail View" b class ${1:MODEL_NAME}DetailView(DetailView): - model = ${1:MODEL_NAME} + model = $1 template_name = "${2:TEMPLATE_NAME}" endsnippet snippet listview "Generic List View" b class ${1:MODEL_NAME}ListView(ListView): - model = ${1:MODEL_NAME} + model = $1 template_name = "${2:TEMPLATE_NAME}" endsnippet snippet stackedinline "Stacked Inline" b -class ${1}Inline(admin.StackedInline): +class $1Inline(admin.StackedInline): ''' - Stacked Inline View for ${1} + Stacked Inline View for $1 ''' - model = ${2:${1}} + model = ${2:$1} min_num = ${3:3} max_num = ${4:20} extra = ${5:1} - raw_id_fields = (${6},) + raw_id_fields = ($6,) endsnippet snippet tabularinline "Tabular Inline" b -class ${1}Inline(admin.TabularInline): +class $1Inline(admin.TabularInline): ''' - Tabular Inline View for ${1} + Tabular Inline View for $1 ''' - model = ${2:${1}} + model = ${2:$1} min_num = ${3:3} max_num = ${4:20} extra = ${5:1} - raw_id_fields = (${6},) + raw_id_fields = ($6,) endsnippet snippet templateview "Generic Template View" b @@ -345,7 +345,7 @@ endsnippet snippet updateview "Generic Update View" b class ${1:MODEL_NAME}UpdateView(UpdateView): - model = ${1:MODEL_NAME} + model = $1 template_name = "${2:TEMPLATE_NAME}" endsnippet diff --git a/sources_non_forked/vim-snippets/UltiSnips/elm.snippets b/sources_non_forked/vim-snippets/UltiSnips/elm.snippets new file mode 100644 index 00000000..6e21bb5e --- /dev/null +++ b/sources_non_forked/vim-snippets/UltiSnips/elm.snippets @@ -0,0 +1,9 @@ +priority -50 + +snippet impa "Qualified import" +import ${1:Json.Encode} as ${0:`!p snip.rv = t[1].split(".")[-1]`} +endsnippet + +snippet impae "Qualified import with exposing" +import ${1:Json.Encode} as ${2:`!p snip.rv = t[1].split(".")[-1]`} exposing (${0:Value}) +endsnippet diff --git a/sources_non_forked/vim-snippets/UltiSnips/eruby.snippets b/sources_non_forked/vim-snippets/UltiSnips/eruby.snippets index fe38c2fc..ef93be44 100644 --- a/sources_non_forked/vim-snippets/UltiSnips/eruby.snippets +++ b/sources_non_forked/vim-snippets/UltiSnips/eruby.snippets @@ -27,12 +27,12 @@ def textmate_var(var, snip): endglobal -snippet % "<% ${0} %>" i -`!p textmate_var('TM_RAILS_TEMPLATE_START_RUBY_INLINE', snip)`${0}`!p textmate_var('TM_RAILS_TEMPLATE_END_RUBY_INLINE', snip)` +snippet % "<% $0 %>" i +`!p textmate_var('TM_RAILS_TEMPLATE_START_RUBY_INLINE', snip)`$0`!p textmate_var('TM_RAILS_TEMPLATE_END_RUBY_INLINE', snip)` endsnippet -snippet = "<%= ${0} %>" i -`!p textmate_var('TM_RAILS_TEMPLATE_START_RUBY_EXPR', snip)`${0}`!p textmate_var('TM_RAILS_TEMPLATE_END_RUBY_EXPR', snip)` +snippet = "<%= $0 %>" i +`!p textmate_var('TM_RAILS_TEMPLATE_START_RUBY_EXPR', snip)`$0`!p textmate_var('TM_RAILS_TEMPLATE_END_RUBY_EXPR', snip)` endsnippet ########################################################################### @@ -150,11 +150,11 @@ snippet licai "link_to (controller, action, id)" w endsnippet snippet linpp "link_to (nested path plural)" w -`!p textmate_var('TM_RAILS_TEMPLATE_START_RUBY_EXPR', snip)`link_to ${1:"${2:link text...}"}, ${3:${10:parent}_${11:child}_path(${12:@}${13:${10}})}`!p textmate_var('TM_RAILS_TEMPLATE_END_RUBY_EXPR', snip)` +`!p textmate_var('TM_RAILS_TEMPLATE_START_RUBY_EXPR', snip)`link_to ${1:"${2:link text...}"}, ${3:${10:parent}_${11:child}_path(${12:@}${13:$10})}`!p textmate_var('TM_RAILS_TEMPLATE_END_RUBY_EXPR', snip)` endsnippet snippet linp "link_to (nested path)" w -`!p textmate_var('TM_RAILS_TEMPLATE_START_RUBY_EXPR', snip)`link_to ${1:"${2:link text...}"}, ${3:${12:parent}_${13:child}_path(${14:@}${15:${12}}, ${16:@}${17:${13}})}`!p textmate_var('TM_RAILS_TEMPLATE_END_RUBY_EXPR', snip)` +`!p textmate_var('TM_RAILS_TEMPLATE_START_RUBY_EXPR', snip)`link_to ${1:"${2:link text...}"}, ${3:${12:parent}_${13:child}_path(${14:@}${15:$12}, ${16:@}${17:$13})}`!p textmate_var('TM_RAILS_TEMPLATE_END_RUBY_EXPR', snip)` endsnippet snippet lipp "link_to (path plural)" w @@ -162,7 +162,7 @@ snippet lipp "link_to (path plural)" w endsnippet snippet lip "link_to (path)" w -`!p textmate_var('TM_RAILS_TEMPLATE_START_RUBY_EXPR', snip)`link_to ${1:"${2:link text...}"}, ${3:${12:model}_path(${13:@}${14:${12}})}`!p textmate_var('TM_RAILS_TEMPLATE_END_RUBY_EXPR', snip)` +`!p textmate_var('TM_RAILS_TEMPLATE_START_RUBY_EXPR', snip)`link_to ${1:"${2:link text...}"}, ${3:${12:model}_path(${13:@}${14:$12})}`!p textmate_var('TM_RAILS_TEMPLATE_END_RUBY_EXPR', snip)` endsnippet snippet lim "link_to model" w diff --git a/sources_non_forked/vim-snippets/UltiSnips/go.snippets b/sources_non_forked/vim-snippets/UltiSnips/go.snippets index b6891ff0..35cf9091 100644 --- a/sources_non_forked/vim-snippets/UltiSnips/go.snippets +++ b/sources_non_forked/vim-snippets/UltiSnips/go.snippets @@ -53,7 +53,7 @@ endsnippet snippet switch "Switch statement" b switch ${1:expression}${1/(.+)/ /}{ -case${0} +case$0 } endsnippet diff --git a/sources_non_forked/vim-snippets/UltiSnips/haskell.snippets b/sources_non_forked/vim-snippets/UltiSnips/haskell.snippets new file mode 100644 index 00000000..11d82c81 --- /dev/null +++ b/sources_non_forked/vim-snippets/UltiSnips/haskell.snippets @@ -0,0 +1,5 @@ +priority -50 + +snippet impq "Qualified import" +import qualified ${1:Data.Text} as ${0:`!p snip.rv = t[1].split(".")[-1]`} +endsnippet diff --git a/sources_non_forked/vim-snippets/UltiSnips/html.snippets b/sources_non_forked/vim-snippets/UltiSnips/html.snippets index fd1aca51..924f02fd 100644 --- a/sources_non_forked/vim-snippets/UltiSnips/html.snippets +++ b/sources_non_forked/vim-snippets/UltiSnips/html.snippets @@ -12,33 +12,6 @@ def x(snip): snip.rv = "" endglobal -############ -# Doctypes # -############ -snippet doctype "DocType XHTML 1.0 Strict" b - - -endsnippet - -snippet doctype "DocType XHTML 1.0 Transitional" b - - -endsnippet - -snippet doctype "DocType XHTML 1.1" b - - -endsnippet - -snippet doctype "HTML - 4.0 Transitional (doctype)" b - - -endsnippet - snippet doctype "HTML - 5.0 (doctype)" b @@ -59,6 +32,18 @@ snippet escape "Escape (escape)" ⎋ endsnippet +snippet left "Left (left)" +← +endsnippet + +snippet return "Return (return)" +↩ +endsnippet + +snippet right "Right (right)" +→ +endsnippet + snippet shift "Shift (shift)" ⇧ endsnippet @@ -71,236 +56,475 @@ snippet up "Up (up)" ↑ endsnippet -snippet return "Return (return)" -↩ -endsnippet - -snippet right "Right (right)" -→ -endsnippet - -snippet left "Left (left)" -← -endsnippet - -snippet option "Option (option)" -⌥ -endsnippet - -####################### -# Conditional inserts # -####################### -snippet ! "IE Conditional Comment: Internet Explorer 5_0 only" -$0 -endsnippet - -snippet ! "IE Conditional Comment: Internet Explorer 5_5 only" -$0 -endsnippet - -snippet ! "IE Conditional Comment: Internet Explorer 5_x" -$0 -endsnippet - -snippet ! "IE Conditional Comment: Internet Explorer 6 and below" -$0 -endsnippet - -snippet ! "IE Conditional Comment: Internet Explorer 6 only" -$0 -endsnippet - -snippet ! "IE Conditional Comment: Internet Explorer 7+" -$0 -endsnippet - -snippet ! "IE Conditional Comment: Internet Explorer" -$0 -endsnippet - -snippet ! "IE Conditional Comment: NOT Internet Explorer" -${1: IE Conditional Comment: NOT Internet Explorer }$0 -endsnippet - ############# # HTML TAGS # ############# -snippet input "Input with Label" w - - +snippet a "Link" w +${4:Anchor Text} endsnippet -snippet input "XHTML " w - +snippet abbr "" w +$1 endsnippet - -snippet opt "Option" w -${3:$2} +snippet access "accesskey global attribute" +accesskey="$1" endsnippet -snippet select "Select Box" w - +snippet address "

" w +
$1
endsnippet - -snippet textarea "XHTML +snippet article "
" +
+ ${1:article content} +
endsnippet -snippet mailto "XHTML " w -${3:email me} +snippet aside "