3

Recently I'm learning go lang.

And I found that for many cases, I'll need to type the following text:

package main

import "fmt"

func main () {
}

So I was thinking that maybe I can write some vim functions in my .vimrc which can write template text into current file when using vim. Which can save me lots of work.

I know after some hours of learning vim scripts language, I can figure it out. But I think it would be a common need for many unseasoned vim users and I didn't find similar questions on Stackoverflow. So I asked this question.

Zen
  • 4,381
  • 5
  • 29
  • 56

4 Answers4

6

You can create a template as follow:

First, create a file (for example base.go) which will be your template with inside the snippet you typed in your question (I store my templates in $HOME/.vim/templates/<language>/, so in your case, it would be $HOME/.vim/templates/go/base.go, but the location is up to you really),

Then, in your .vimrc, add the following mapping:

nnoremap <space>t :-1read $HOME/.vim/templates/go/base.go<CR>/{<CR>o

This mapping does the following when you press space-t in normal mode:

  • the content of the file $HOME/.vim/templates/go/base.go is inserted where your cursor is,
  • the cursor is moved to the opening {,
  • you are put in insert mode in the brackets.

So when you open a new go file, press space-t and it will insert your template and place you where you need to be to start coding.

EDIT: -1 indicate the position of where to insert the content of the file(:.read file inserts it just after the current (.) line. -1 inserts it just after the current line -1. So effectively, it is to insert it where your cursor is and move down the lines including the one you are on. For more about it, you can read :help range.

The jump is done with the part /{<CR>o which looks for a { (/{), goes to it (<CR>) and goes in insert mode just after (o).

padawin
  • 4,230
  • 15
  • 19
  • This is really nice answer, if you can explain what exactly does `:-1read` mean and how read content is combined with jump cursor action, that's better. I mean, I got some good effect, but I didn't really quite understand the mechanism of `:-1read $HOME/.vim/templates/go/base.go/{o` – Zen Apr 15 '19 at 05:44
2

The other answers and comments are great so this is presented just as an additional option. This is very similar to padawin's answer but embeds the skeleton into the vimrc file, which may or may not be good for you.

I have mine set up as an insert mode expansion (by the last line here), so I just type copy# and hit enter and this text appears. (You'll note that the text doesn't include the comment stars on the subsequent lines, this is because they are automatically added while Vim is "typing" this in for me. There's probably a way to turn of that behavior but it was fine for me.)

function! InsertCopyright()
    let l:year = strftime("%Y")
    return
        \  "/**\n"
        \. "Copyright My Great Company, " . l:year . ". All rights reserved.\n"
        \. "/"
endfunction

iabbrev <expr> copy# InsertCopyright()
dash-tom-bang
  • 17,383
  • 5
  • 46
  • 62
  • I recommend "\r" instead of "\n" : https://stackoverflow.com/questions/71417/why-is-r-a-newline-for-vim – Jose Jun 03 '19 at 09:27
1

:help templates shows how to read a skeleton template when opening a new file.

Several template expander plugins build upon that primitive mechanism and support things like automatic evaluations (e.g. of the current date, environment variables, inlined Vimscript expressions).

Some people prefer to load these templates on demand (and not automatically), and thus they are perfectly happy with snippet plugins. Some plugins do both (snippets on demand and templates on new files).


Closely related (with a good piece of overlap): snippets are like the built-in :abbreviate on steroids, usually with parameter insertions, mirroring, and multiple stops inside them. One of the first, very famous (and still widely used) Vim plugins is snipMate (inspired by the TextMate editor); unfortunately, it's not maintained any more; though there is a fork. A modern alternative (that requires Python though) is UltiSnips. There are more, see this list on the Vim Tips Wiki and this comparison by Mark Weber.

There are three things to evaluate: First, the features of the snippet engine itself, second, the quality and breadth of snippets provided by the author or others; third, how easy it is to add new snippets.

Ingo Karkat
  • 167,457
  • 16
  • 250
  • 324
0

I have created my own solution based on ultisnips plugin and on Noah Frederick work. A file called: "ultisnips_custom.vim" should be placed at: after/plugin/ultisnips_custom.vim

Then a snipt called _skel should be created for each filetype you want to trigger a header.

Another tip: in the code linked below the ultisnips trigger was changed to <c-j> so you can change it to fit your needs.

Here's my code:

"             File: ultisnips_custom.vim - Custom UltiSnips settings
"       Maintainer: Sergio Araújo
" Oririnal Creator: Noah Frederick
"      Last Change: abr 02 2019 17:40
"      Place it at: after/plugin/ultisnips_custom.vim

" We need python or python3 to run ultisnips
if !has("python") && !has("python3")
  finish
endif

" This function is called by the autocommand at the end of the file
function! TestAndLoadSkel() abort
  let filename = expand('%')
  " Abort on non-empty buffer or extant file
  if !(line('$') == 1 && getline('$') == '') || filereadable('%')
    return
  endif

  " Load UltiSnips in case it was deferred via vim-plug
  if !exists('g:did_plugin_ultisnips') && exists(':PlugStatus')
    call plug#load('ultisnips')
    doautocmd FileType
  endif

  " the function feedkys simulates the insert key sequence in order to call
  " the template (skel)
  execute 'call feedkeys("i_skel\<c-j>")'
endfunction

augroup ultisnips_custom
  autocmd!
  au Bufnewfile *.sh,*.zsh,*.html,*.css,*.py,*.tex,*.md :call TestAndLoadSkel()
  "autocmd BufEnter *.sh,*.zsh,*.html,*.py execute 'call feedkeys("i_skel\<c-j>")'
augroup END

" vim: fdm=marker:sw=2:sts=2:et
SergioAraujo
  • 11,069
  • 3
  • 50
  • 40