├── LICENSE ├── README.md ├── doc └── minisnip.txt └── plugin └── vim-minisnip.vim /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Keyboard Fire 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | _ _ _ 2 | _ __ ___ (_)_ __ (_)___ _ __ (_)_ __ 3 | | '_ ` _ \| | '_ \| / __| '_ \| | '_ \ 4 | | | | | | | | | | | \__ \ | | | | |_) | 5 | |_| |_| |_|_|_| |_|_|___/_| |_|_| .__/ 6 | |_| 7 | 8 | Minisnip is a tiny plugin that allows you to quickly insert "templates" into 9 | files. Among all the other snippet plugins out there, the primary goal of 10 | minisnip is to be as minimal and lightweight as possible. 11 | 12 | To get started with minisnip, create a directory called `~/.vim/minisnip`. 13 | Then placing a file called `foo` inside of it will create the `foo` snippet, 14 | which you can access by typing `foo` in insert mode. 15 | 16 | Filetype-aware snippets are also available. For example, a file called 17 | `_java_main` will create a `main` snippet only when `filetype=java`, allowing 18 | you to add ex. a `_c_main` snippet and so on. 19 | 20 | Here is a demo of the basic features of minisnip: 21 | 22 | ![demo GIF 1](https://raw.githubusercontent.com/KeyboardFire/keyboardfire.github.io/master/s/vim-minisnip/demo1-s.gif) 23 | 24 | Here is another example that shows how arbitrary code can be executed from 25 | within a snippet, allowing dynamic snippets based on the file name or other 26 | conditions: 27 | 28 | ![demo GIF 2](https://raw.githubusercontent.com/KeyboardFire/keyboardfire.github.io/master/s/vim-minisnip/demo2-s.gif) 29 | 30 | Minisnip is licensed under MIT. 31 | -------------------------------------------------------------------------------- /doc/minisnip.txt: -------------------------------------------------------------------------------- 1 | *minisnip* *minisnip.txt* super lightweight snippet manager 2 | 3 | Author: Keyboard Fire 4 | License: MIT 5 | 6 | _ _ _ ~ 7 | _ __ ___ (_)_ __ (_)___ _ __ (_)_ __ ~ 8 | | '_ ` _ \| | '_ \| / __| '_ \| | '_ \ ~ 9 | | | | | | | | | | | \__ \ | | | | |_) | ~ 10 | |_| |_| |_|_|_| |_|_|___/_| |_|_| .__/ ~ 11 | |_| ~ 12 | 13 | 1. Overview |minisnip-overview| 14 | 2. Mappings |minisnip-mappings| 15 | 3. Configuration |minisnip-configuration| 16 | 17 | =============================================================================== 18 | OVERVIEW *minisnip-overview* 19 | 20 | Minisnip is a tiny plugin that allows you to quickly insert "templates" into 21 | files. Among all the other snippet plugins out there, the primary goal of 22 | minisnip is to be as minimal and lightweight as possible. 23 | 24 | To get started with minisnip, create a directory called `~/.vim/minisnip`. 25 | Then placing a file called `foo` inside of it will create the `foo` snippet, 26 | which you can access by typing foo in insert mode. 27 | 28 | Filetype-aware snippets are also available. For example, a file called 29 | `_java_main` will create a `main` snippet only when |filetype|=java, allowing 30 | you to add ex. a `_c_main` snippet and so on. 31 | 32 | =============================================================================== 33 | MAPPINGS *minisnip-mappings* 34 | 35 | ------------------------------------------------------------------------------- 36 | *minisnip_* 37 | In insert mode, expand a mapping or jump to the next 38 | placeholder and enter select mode. 39 | In select mode, jump to the next placeholder. 40 | 41 | =============================================================================== 42 | CONFIGURATION *minisnip-configuration* 43 | 44 | ------------------------------------------------------------------------------- 45 | *'g:minisnip_dir'* 46 | Default: $HOME . '/.vim/minisnip' 47 | 48 | This allows you to specify where minisnip looks for snippet files. Add this 49 | line to your `.vimrc`: > 50 | let g:minisnip_dir = '/path/to/directory' 51 | < 52 | 53 | ------------------------------------------------------------------------------- 54 | *'g:minisnip_trigger'* 55 | Default: '' 56 | 57 | Specifies which key expands snippets and jumps to the next placeholder. This 58 | should be specified in the same format as you would use for a |:map|. For 59 | example: > 60 | let g:minisnip_trigger = '' 61 | < 62 | 63 | ------------------------------------------------------------------------------- 64 | *'g:minisnip_startdelim'* 65 | *'g:minisnip_enddelim'* 66 | Defaults: '{{+', '+}}' 67 | 68 | The start and end delimeters of the placeholder string to use. For example, 69 | with the default values, a sample snippet could look like this: > 70 | 71 | 72 | 73 | {{+default title+}} 74 | 75 | 76 | {{++}} 77 | 78 | 79 | < 80 | 81 | ------------------------------------------------------------------------------- 82 | *'g:minisnip_evalmarker'* 83 | Default: '~' 84 | 85 | Marks a template as meant to be executed as vimscript. With the default value, 86 | this looks something like: > 87 | It has been {{+~localtime()+}} seconds since the Unix epoch 88 | < 89 | 90 | ------------------------------------------------------------------------------- 91 | *'g:minisnip_backrefmarker'* 92 | Default: '\\~' 93 | 94 | When this is present, followed by a single digit `n`, in a placeholder that 95 | also starts with |'g:minisnip_evalmarker'|, it will be replaced with the `n`th 96 | to last previous placeholder value, surrounded by quotes. Here is an example 97 | of how it can be used: > 98 | #ifndef {{+INCLUDE_GUARD+}} 99 | #define {{+~\~1+}} 100 | 101 | {{++}} 102 | 103 | #endif 104 | < 105 | This will automatically fill the `#define` line with the value entered on the 106 | `#ifndef` line upon jumping to it. 107 | -------------------------------------------------------------------------------- /plugin/vim-minisnip.vim: -------------------------------------------------------------------------------- 1 | " set default global variable values if unspecified by user 2 | let g:minisnip_dir = fnamemodify(get(g:, 'minisnip_dir', '~/.vim/minisnip'), ':p') 3 | let g:minisnip_trigger = get(g:, 'minisnip_trigger', '') 4 | let g:minisnip_startdelim = get(g:, 'minisnip_startdelim', '{{+') 5 | let g:minisnip_enddelim = get(g:, 'minisnip_enddelim', '+}}') 6 | let g:minisnip_evalmarker = get(g:, 'minisnip_evalmarker', '~') 7 | let g:minisnip_backrefmarker = get(g:, 'minisnip_backrefmarker', '\\~') 8 | 9 | " this is the pattern used to find placeholders 10 | let s:delimpat = '\V' . g:minisnip_startdelim . '\.\{-}' . g:minisnip_enddelim 11 | 12 | function! ShouldTrigger() 13 | silent! unlet! s:snippetfile 14 | let l:cword = matchstr(getline('.'), '\v\w+%' . col('.') . 'c') 15 | 16 | " look for a snippet by that name 17 | let l:snippetfile = g:minisnip_dir . '/' . l:cword 18 | let l:ft_snippetfile = g:minisnip_dir . '/_' . &filetype . '_' . l:cword 19 | if filereadable(l:ft_snippetfile) 20 | " filetype snippets override general snippets 21 | let l:snippetfile = l:ft_snippetfile 22 | endif 23 | 24 | " make sure the snippet exists 25 | if filereadable(l:snippetfile) 26 | let s:snippetfile = l:snippetfile 27 | return 1 28 | endif 29 | 30 | return search(s:delimpat, 'e') 31 | endfunction 32 | 33 | " main function, called on press of Tab (or whatever key Minisnip is bound to) 34 | function! Minisnip() 35 | if exists("s:snippetfile") 36 | " reset placeholder text history (for backrefs) 37 | let s:placeholder_texts = [] 38 | let s:placeholder_text = '' 39 | " remove the snippet name 40 | normal! "_diw 41 | " insert the snippet 42 | execute 'keepalt read ' . escape(s:snippetfile, '#%') 43 | " remove the empty line before the snippet 44 | normal! kJ 45 | " select the first placeholder 46 | call s:SelectPlaceholder() 47 | else 48 | " save the current placeholder's text so we can backref it 49 | let l:old_s = @s 50 | normal! ms"syv`<`s 51 | let s:placeholder_text = @s 52 | let @s = l:old_s 53 | " jump to the next placeholder 54 | call s:SelectPlaceholder() 55 | endif 56 | endfunction 57 | 58 | " this is the function that finds and selects the next placeholder 59 | function! s:SelectPlaceholder() 60 | " don't clobber s register 61 | let l:old_s = @s 62 | 63 | " get the contents of the placeholder 64 | " we use /e here in case the cursor is already on it (which occurs ex. 65 | " when a snippet begins with a placeholder) 66 | " we also use keeppatterns to avoid clobbering the search history / 67 | " highlighting all the other placeholders 68 | keeppatterns execute 'normal! /' . s:delimpat . "/e\gn\"sy" 69 | 70 | " save the contents of the previous placeholder (for backrefs) 71 | call add(s:placeholder_texts, s:placeholder_text) 72 | 73 | " save length of entire placeholder for reference later 74 | let l:slen = len(@s) 75 | 76 | " remove the start and end delimiters 77 | let @s=substitute(@s, '\V' . g:minisnip_startdelim, '', '') 78 | let @s=substitute(@s, '\V' . g:minisnip_enddelim, '', '') 79 | 80 | " is this placeholder marked as 'evaluate'? 81 | if @s =~ '\V\^' . g:minisnip_evalmarker 82 | " remove the marker 83 | let @s=substitute(@s, '\V\^' . g:minisnip_evalmarker, '', '') 84 | " substitute in any backrefs 85 | let @s=substitute(@s, '\V' . g:minisnip_backrefmarker . '\(\d\)', 86 | \"\\=\"'\" . substitute(get( 87 | \ s:placeholder_texts, 88 | \ len(s:placeholder_texts) - str2nr(submatch(1)), '' 89 | \), \"'\", \"''\", 'g') . \"'\"", 'g') 90 | " evaluate what's left 91 | let @s=eval(@s) 92 | endif 93 | 94 | if empty(@s) 95 | " the placeholder was empty, so just enter insert mode directly 96 | normal! gvd 97 | call feedkeys(col("'>") - l:slen >= col('$') - 1 ? 'a' : 'i', 'n') 98 | else 99 | " paste the placeholder's default value in and enter select mode on it 100 | execute "normal! gv\"spgv\" 101 | endif 102 | 103 | " restore old value of s register 104 | let @s = l:old_s 105 | endfunction 106 | 107 | " plug mappings 108 | " the eval/escape charade is to convert ex. into a literal tab, first 109 | " making it \ and then eval'ing that surrounded by double quotes 110 | inoremap