How to Use a Template in Vim

How to use a template in vim

The command that you've suggested is not going to work: what this will do is run no Vim command whenever you open ~/.vim/skeleton.R

A crude way of achieving what you want would be to use:

:au BufNewFile *.R r ~/.vim/skeleton.R

This will read (:r) your file whenever a new *.R file is created. You want to avoid having BufRead in the autocmd, or it will read the skeleton file into your working file every time you open the file!

There are many plugins that add a lot more control to this process. Being the author and therefore completely biased, I'd recommend this one, but there are plenty of others listed here.


Shameless plug:

They all work in a relatively similar way, but to explain my script:

You install the plugin as described on the linked page and then create some templates in ~/.vim/templates. These templates should have the same extension as the 'target' file, so if it's a template for .R files, call it something like skeleton.R. In your .vimrc, add something like this:

let g:file_template_default = {}
let g:file_template_default['R'] = 'skeleton'

Then create your new .R file (with a filename, so save it if it's new) and enter:

:LoadFileTemplate

You can also skip the .vimrc editing and just do:

:LoadFileTemplate skeleton

See the website for more details.

How to write vim function to paste a template text into current file?

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).

How to auto insert a template code into a new file of particular extension, that is created in a particular directory?

First of all: There are template plugins, you should search the net for "vim template plugin". Perhaps you find something useful.

If you want to do it yourself:

Create your template file like this (I assume ~/tmpl/tmpl.cpp as name):

/* 
* Author : <<name>>
* Date : <<date>>
*/

and in your vimrc:

function AddTemplate(tmpl_file)
exe "0read " . a:tmpl_file
let substDict = {}
let substDict["name"] = $USER
let substDict["date"] = strftime("%Y %b %d %X")
exe '%s/<<\([^>]*\)>>/\=substDict[submatch(1)]/g'
set nomodified
normal G
endfunction

autocmd BufNewFile *.c,*.cc,*.cpp,*.h call AddTemplate("~/tmpl/tmpl.cpp")

The set nomodified tells Vim that the file was not modified. That way you can exit the file with :q as long as you don't add additional text. Usefull if you typed the wrong file name.

If you only want to act on files within a special directory ~/project, you can add the following at the start of the function AddTemplate:

let fully_qualified_file = expand('%:p')
if 0 != match(fully_qualified_file, $HOME . '/project/.*')
return
endif

how can I run some commands to select template for new created file in vim?

Let's start with a list of requirements:

  • each time we edit a new C file, we want to…
  • insert a template…
  • selected from a list…
  • constructed from the content of a specific directory.

Let's do it, from the bottom up.

Directory layout

~/.vim/templates/skeleton.<extension> allows us to have several "skeletons" for a given extension. I tend to prefer doing things based on filetype instead but the extension makes more sense in this case so we will keep your layout.

List the files in a given directory

Whenever we need a built-in function, our first stop should be either :help function-list, which groups every built-in function by topic, or directly :help <topic>-functions if we are familiar with that grouping. In this case, we find the following line under :help file-function:

readdir()               get a List of file names in a directory

Indeed, :help readdir() is just what we need but, unfortunately (and undocumentedly), it doesn't expand environment variables or tildes on its own so we we have to :help expand() our directory path.

We can do:

:let templates = readdir(expand('~/.vim/templates/'))
:echo templates

to get something like:

['foo.c', 'bar.c', 'baz.h']

or we can only return the files with a .c extension:

:let templates = readdir(expand('~/.vim/templates/'), {name -> name =~ '.c$'})
:echo templates
['foo.c', 'bar.c']

or we can use the extension of the file associated with the current buffer:

:let templates readdir(expand('~/.vim/templates/'), {name -> name =~ '.' . expand('%:e') . '$'})
:echo templates
['foo.c', 'bar.c']

Done.

Select from the list

Again we turn to Vim for a clue. Under :help interactive-functions we find the following promising function:

inputlist()     let the user pick an entry from a list

First, let's get acquainted with :help inputlist().

:echo inputlist(['Choose:', '1. foo', '2. bar', '3. baz'])

which looks like:

Choose:
1. foo
2. bar
3. baz
Type number and <Enter> or click with the mouse (q or empty cancels):

and prints the chosen number.

Let's make it more useful by using the file listing command from before:

:let templates = readdir(expand('~/.vim/templates/'), {name -> name =~ '.' . expand('%:e') . '$'})
:echo inputlist(['Choose a template:'] + templates)

which looks like:

Choose a template:
bar.c
foo.c
Type number and <Enter> or click with the mouse (q or empty cancels):

and still prints the chosen number but we don't have a number before each entry. This can be solved with :help mapnew():

:let templates = readdir(expand('~/.vim/templates/'), {name -> name =~ '.' . expand('%:e') . '$'})
:let templates_for_display = templates->mapnew({idx, val -> 1 + idx . '. ' . val})
:echo inputlist(['Choose a template:'] + templates_for_display)

which looks like:

Choose a template:
1. bar.c
2. foo.c
Type number and <Enter> or click with the mouse (q or empty cancels):

and still prints the chosen number. What is left at this stage is to print the actual item in templates. Since lists are zero-based and we had to offset by one to get an intuitive display, we only need to subtract 1 to the number returned by inputlist():

:let templates = readdir(expand('~/.vim/templates/'), {name -> name =~ '.' . expand('%:e') . '$'})
:let templates_for_display = templates->mapnew({idx, val -> 1 + idx . '. ' . val})
:let choice = inputlist(['Choose a template:'] + templates_for_display)
:echo templates[choice - 1]

which correctly prints bar.c or foo.c.

We are making huge progress!

Insert the template

:help :read is a crude way to insert text from an external source. Here, we will prefer a slightly cleaner way using :help setline() and :help readfile().

But first, let's build a full path from the selected template name:

:let templates = readdir(expand('~/.vim/templates/'), {name -> name =~ '.' . expand('%:e') . '$'})
:let templates_for_display = templates->mapnew({idx, val -> 1 + idx . '. ' . val})
:let choice = inputlist(['Choose a template:'] + templates_for_display)
:let chosen_template = expand('~/.vim/templates/' . templates[choice - 1])
:echo chosen_template

which should print something like:

~/.vim/templates/foo.c

We can now read the file:

:let templates = readdir(expand('~/.vim/templates/'), {name -> name =~ '.' . expand('%:e') . '$'})
:let templates_for_display = templates->mapnew({idx, val -> 1 + idx . '. ' . val})
:let choice = inputlist(['Choose a template:'] + templates_for_display)
:let chosen_template = expand('~/.vim/templates/' . templates[choice - 1])
:let template_content = readfile(chosen_template)
:echo template_content

and, finally, insert it in the buffer:

:let templates = readdir(expand('~/.vim/templates/'), {name -> name =~ '.' . expand('%:e') . '$'})
:let templates_for_display = templates->mapnew({idx, val -> 1 + idx . '. ' . val})
:let choice = inputlist(['Choose a template:'] + templates_for_display)
:let chosen_template = expand('~/.vim/templates/' . templates[choice - 1])
:let template_content = readfile(chosen_template)
:call setline(1, template_content)

Let's put it all together in a function in our vimrc:

function SelectTemplate()
let templates = readdir(expand('~/.vim/templates/'), {name -> name =~ '.' . expand('%:e') . '$'})
let templates_for_display = templates->mapnew({idx, val -> 1 + idx . '. ' . val})
let choice = inputlist(['Choose a template:'] + templates_for_display)
let chosen_template = expand('~/.vim/templates/' . templates[choice - 1])
let template_content = readfile(chosen_template)
call setline(1, template_content)
endfunction

and test it from a c file:

:call SelectTemplate()

Great! We are almost done!

Automatisation

For the last step, we can simply use your snippet with a couple of minor changes:

if has("autocmd")
augroup templates
autocmd!
autocmd BufNewFile *.c call SelectTemplate()
augroup END
endif

Phew! What a ride!

What, now?

  • The function could be refined a little by removing duplication and adding checks here and there.
  • Which should make it possible to use * in the autocommand so that it works on any file extension.

Writing a vim function to insert a block of static text

I do that by keeping under my vim folder a set of files which then I insert using the r command (which inserts the contents of a file, at the current location if no line number is passed) from some function:

function! Class()
" ~/vim/cpp/new-class.txt is the path to the template file
r~/vim/cpp/new-class.txt
endfunction

This is very practical - in my opinion - when you want to insert multi-line text. Then you can, for example, map a keyboard shortcut to call your function:

nmap ^N :call Class()<CR>

generate template in vim

yes, you can.

1) create a file, with that content, say, foo.html

2) create a mapping E.g nnoremap <F9> :r /path/to/foo.html<cr>

3) when you want to get that template, press <F9> in normal mode. The content of your foo.html will be inserted into your current buffer.

Vim templates, get filename and use it

I believe that this might help? http://vim.wikia.com/wiki/Insert_current_filename

With this you can get the current filename:

expand("%:t:r")

Specifically, you are probably looking for this:

%s/TODO/\=expand("%:t:r")/g

A full example:

function! NewFile()
silent! 0r $HOME/vimfiles/templates/%:e.vim_template
s/FILENAME/\=expand("%:t:r")
endfunction

autocmd BufNewFile * call NewFile()

You could also give something like tSkeleton a try, I've never tried myself but it seems to solve this problem for you.



Related Topics



Leave a reply



Submit