Snippets y Templates Automáticos
Los snippets y templates son herramientas poderosas para acelerar la escritura de código repetitivo. En este capítulo aprenderás a crear y usar snippets eficientemente para maximizar tu productividad.
🚀 UltiSnips: El Motor de Snippets Más Potente
UltiSnips es el sistema de snippets más avanzado para Vim, con capacidades de Python scripting y lógica compleja.
Instalación y configuración básica
" Instalación con vim-plug
Plug 'SirVer/ultisnips'
Plug 'honza/vim-snippets' " Colección grande de snippets
" Configuración básica
let g:UltiSnipsExpandTrigger="<Tab>"
let g:UltiSnipsJumpForwardTrigger="<Tab>"
let g:UltiSnipsJumpBackwardTrigger="<S-Tab>"
let g:UltiSnipsEditSplit="vertical"
" Directorios de snippets
let g:UltiSnipsSnippetsDir="~/.vim/UltiSnips" " Personal
let g:UltiSnipsSnippetDirectories=["UltiSnips", "mysnippets"]
" Mapeos adicionales
nnoremap <Leader>ue :UltiSnipsEdit<CR>
nnoremap <Leader>ur :call UltiSnips#RefreshSnippets()<CR>
Sintaxis básica de snippets
snippet trigger "description" options
snippet content with ${1:placeholder} and ${2:another}
$0 # Posición final del cursor
endsnippet
📝 Creando Snippets Personalizados
Estructura de archivos de snippets
~/.vim/UltiSnips/
├── all.snippets # Snippets globales
├── python.snippets # Específicos para Python
├── javascript.snippets # Específicos para JavaScript
├── html.snippets # Específicos para HTML
└── vim.snippets # Específicos para Vim
Ejemplos de snippets básicos
Python snippets
# ~/.vim/UltiSnips/python.snippets
# Función básica
snippet def "Function definition" b
def ${1:function_name}(${2:args}):
"""${3:Docstring for $1.}"""
${4:pass}
$0
endsnippet
# Clase básica
snippet class "Class definition" b
class ${1:ClassName}(${2:object}):
"""${3:Docstring for $1.}"""
def __init__(self${4:, args}):
"""${5:Initialize $1.}"""
${6:pass}
$0
endsnippet
# Try-except
snippet try "Try except block" b
try:
${1:pass}
except ${2:Exception} as ${3:e}:
${4:raise}
$0
endsnippet
# If main
snippet ifmain "if __name__ == '__main__'" b
if __name__ == '__main__':
${1:main()}
$0
endsnippet
# Docstring con parámetros
snippet docs "Function docstring" b
"""${1:Brief description.}
Args:
${2:param1} (${3:type}): ${4:Description}
Returns:
${5:type}: ${6:Description}
Raises:
${7:ExceptionType}: ${8:Description}
"""
$0
endsnippet
JavaScript/TypeScript snippets
# ~/.vim/UltiSnips/javascript.snippets
# Función
snippet func "Function" b
function ${1:functionName}(${2:args}) {
${3:// TODO: implement}
$0
}
endsnippet
# Arrow function
snippet arrow "Arrow function" w
(${1:args}) => {
${2:// TODO: implement}
$0
}
endsnippet
# React component
snippet rfc "React functional component" b
import React from 'react';
const ${1:ComponentName} = (${2:props}) => {
return (
<div>
${3:// Component content}
$0
</div>
);
};
export default $1;
endsnippet
# Console log
snippet cl "console.log" w
console.log('${1:message}:', ${2:variable});$0
endsnippet
# Try-catch
snippet try "Try catch block" b
try {
${1:// code}
} catch (${2:error}) {
console.error('${3:Error message}:', $2);
$0
}
endsnippet
HTML snippets
# ~/.vim/UltiSnips/html.snippets
# HTML5 template
snippet html5 "HTML5 template" b
<!DOCTYPE html>
<html lang="${1:en}">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>${2:Document}</title>
${3:<link rel="stylesheet" href="style.css">}
</head>
<body>
${4:<!-- Content here -->}
$0
</body>
</html>
endsnippet
# Div con clase
snippet div "Div with class" w
<div class="${1:classname}">
$0
</div>
endsnippet
# Link
snippet a "Anchor tag" w
<a href="${1:url}"${2: target="_blank"}>${3:link text}</a>$0
endsnippet
🧠 Snippets Avanzados con Python
Snippets con lógica Python
# Snippet que genera getters/setters automáticamente
snippet prop "Property with getter/setter" b
@property
def ${1:property_name}(self):
"""${2:Property docstring.}"""
return self._$1
@$1.setter
def $1(self, value):
"""Set $1."""
self._$1 = value
$0
endsnippet
# Snippet con fecha automática
snippet date "Current date" w
`!p snip.rv = datetime.now().strftime("%Y-%m-%d")`$0
endsnippet
# Snippet con nombre de archivo
snippet filename "Current filename" w
`!p snip.rv = vim.eval("expand('%:t:r')")`$0
endsnippet
# Snippet condicional
snippet init "Class __init__ method" b
def __init__(self${1:, args}):
"""Initialize ${2:`!p snip.rv = snip.basename or "instance"`}.
`!p
if len(t[1]) > 2:
snip.rv = "\n Args:"
args = [arg.strip() for arg in t[1].split(',')[1:]]
for arg in args:
if arg:
snip.rv += f"\n {arg}: Description for {arg}."
`"""
${3:pass}
$0
endsnippet
Snippets con transformaciones de texto
# Convertir a mayúsculas
snippet const "Constant definition" b
${1/(.+)/\U$1\E/} = ${2:value}$0
endsnippet
# Convertir primera letra a mayúscula
snippet class "Class from filename" b
class ${1:`!p snip.rv = snip.basename.title()`}:
"""${2:Class docstring.}"""
def __init__(self):
"""Initialize $1."""
${3:pass}
$0
endsnippet
🎨 Templates de Archivos
Templates automáticos por tipo de archivo
" En .vimrc - Auto-cargar templates
augroup templates
autocmd!
autocmd BufNewFile *.py 0r ~/.vim/templates/python_template.py
autocmd BufNewFile *.js 0r ~/.vim/templates/javascript_template.js
autocmd BufNewFile *.html 0r ~/.vim/templates/html_template.html
autocmd BufNewFile *.sh 0r ~/.vim/templates/bash_template.sh
" Ejecutar snippets automáticamente después de cargar template
autocmd BufNewFile *.py normal! Gdd/TODO<CR>:nohlsearch<CR>a
augroup END
Ejemplos de templates
Python template
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
File: {filename}
Author: {author}
Date: {date}
Description: TODO: Add description
"""
import sys
import os
def main():
"""Main function."""
# TODO: Implement main logic
pass
if __name__ == '__main__':
main()
JavaScript template
/**
* @file {filename}
* @author {author}
* @date {date}
* @description TODO: Add description
*/
'use strict';
// TODO: Add imports
/**
* Main function
*/
function main() {
// TODO: Implement main logic
}
// TODO: Add exports
module.exports = {
main
};
Templates dinámicos con funciones Vim
" Función para crear template con variables
function! LoadTemplate(template_name)
let l:template_path = expand('~/.vim/templates/' . a:template_name)
if filereadable(l:template_path)
execute '0r ' . l:template_path
" Reemplazar variables
%s/{filename}/\=expand('%:t')/g
%s/{author}/\=g:author_name/g
%s/{email}/\=g:author_email/g
%s/{date}/\=strftime('%Y-%m-%d')/g
%s/{year}/\=strftime('%Y')/g
" Ir al primer TODO
call search('TODO')
endif
endfunction
" Variables globales para templates
let g:author_name = 'Tu Nombre'
let g:author_email = 'tu.email@ejemplo.com'
" Comando para cargar templates
command! -nargs=1 Template call LoadTemplate(<q-args>)
🔧 Sistemas Alternativos de Snippets
1. vim-snipmate (Ligero)
Plug 'MarcWeber/vim-addon-mw-utils'
Plug 'tomtom/tlib_vim'
Plug 'garbas/vim-snipmate'
" Configuración básica
imap <C-J> <Plug>snipMateNextOrTrigger
smap <C-J> <Plug>snipMateNextOrTrigger
2. neosnippet (Para compatibilidad)
Plug 'Shougo/neosnippet.vim'
Plug 'Shougo/neosnippet-snippets'
" Configuración
imap <C-k> <Plug>(neosnippet_expand_or_jump)
smap <C-k> <Plug>(neosnippet_expand_or_jump)
xmap <C-k> <Plug>(neosnippet_expand_target)
3. Snippets nativos con abbrev
" Abbreviations básicas
iabbrev teh the
iabbrev waht what
iabbrev @@ tu.email@ejemplo.com
" Snippets simples con abbrev
autocmd FileType python iabbrev <buffer> def<Tab> def ():<CR>""""""<CR><CR><Esc>3kwa
autocmd FileType javascript iabbrev <buffer> func function () {<CR><CR>}<Esc>2k$i
📚 Colecciones de Snippets
Instalación de colecciones populares
" Colección oficial de vim-snippets
Plug 'honza/vim-snippets'
" Snippets específicos para frameworks
Plug 'epilande/vim-es2015-snippets' " ES6+ JavaScript
Plug 'epilande/vim-react-snippets' " React
Plug 'dsznajder/vscode-es7-javascript-react-snippets' " VSCode style
" Configurar múltiples fuentes
let g:UltiSnipsSnippetDirectories=["UltiSnips", "vim-snippets", "mysnippets"]
Snippets por framework/librería
Django snippets
# ~/.vim/UltiSnips/python.snippets
snippet model "Django model" b
class ${1:ModelName}(models.Model):
"""${2:Model docstring.}"""
${3:name} = models.${4:CharField}(${5:max_length=100})
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
verbose_name = "${6:$1}"
verbose_name_plural = "${7:$1s}"
def __str__(self):
return self.$3
$0
endsnippet
snippet view "Django view" b
def ${1:view_name}(request):
"""${2:View docstring.}"""
${3:# TODO: Implement view logic}
context = {
${4:'key': 'value',}
}
return render(request, '${5:template.html}', context)
$0
endsnippet
React snippets
# ~/.vim/UltiSnips/javascript.snippets
snippet usestate "useState hook" w
const [${1:state}, set${1/(.)/\u$1/}] = useState(${2:initialValue});$0
endsnippet
snippet useeffect "useEffect hook" b
useEffect(() => {
${1:// Effect logic}
${2:return () => {
// Cleanup
};}
}, [${3:dependencies}]);$0
endsnippet
📝 Ejercicios Prácticos
Ejercicio 1: Setup básico
- Instala UltiSnips y vim-snippets
- Configura triggers personalizados
- Prueba snippets existentes para tu lenguaje favorito
- Crea tu primer snippet personalizado
Ejercicio 2: Snippets avanzados
- Crea snippets con múltiples placeholders
- Implementa snippets con lógica Python
- Crea snippets que usen transformaciones de texto
- Desarrolla snippets para tu framework/librería favorita
Ejercicio 3: Templates de archivos
- Crea templates para diferentes tipos de archivo
- Implementa variables dinámicas (fecha, autor, etc.)
- Configura auto-carga de templates
- Crea comando personalizado para cargar templates
Ejercicio 4: Workflow completo
- Desarrolla una librería completa de snippets para tu stack
- Organiza snippets por categorías
- Crea documentación para tus snippets
- Comparte tus snippets con el equipo
🏆 Tips Pro
1. Organización de snippets
" Estructura recomendada
~/.vim/UltiSnips/
├── all.snippets # Globales
├── web/
│ ├── html.snippets
│ ├── css.snippets
│ └── javascript.snippets
├── backend/
│ ├── python.snippets
│ └── go.snippets
└── frameworks/
├── react.snippets
├── django.snippets
└── express.snippets
2. Snippets contextuales
" Snippets que solo funcionan en contextos específicos
snippet if "if statement" b
if ${1:condition}:
${2:pass}
$0
endsnippet
# Solo en clases
snippet method "Class method" "re.search(r'class ', snip.buffer[max(0, snip.line-10):snip.line+1])" be
def ${1:method_name}(self${2:, args}):
"""${3:Method docstring.}"""
${4:pass}
$0
endsnippet
3. Snippets con validación
# Snippet que valida entrada
snippet email "Email input" w
`!p
import re
email = t[1] if t[1] else "example@email.com"
if not re.match(r'^[^@]+@[^@]+\.[^@]+$', email):
email = "example@email.com"
snip.rv = email
`$0
endsnippet
4. Debugging de snippets
" Ver snippets disponibles
:UltiSnipsEdit
" Recargar snippets después de cambios
:call UltiSnips#RefreshSnippets()
" Debug de snippets
let g:ultisnips_debug = 1
5. Integración con completado
" Mostrar snippets en completado
let g:UltiSnipsExpandTrigger = "<C-j>"
let g:UltiSnipsJumpForwardTrigger = "<C-j>"
let g:UltiSnipsJumpBackwardTrigger = "<C-k>"
" Usar Tab para completado normal y C-j para snippets
function! TabOrComplete()
if col('.') > 1 && strpart( getline('.'), col('.')-2, 3 ) =~ '^\w'
return "\<C-N>"
else
return "\<Tab>"
endif
endfunction
inoremap <Tab> <C-R>=TabOrComplete()<CR>
🔗 Integración con Otros Plugins
Con vim-surround
" Snippet que usa surround
snippet func "Function with surround" b
function ${1:name}(${2:args}) {
${3:// TODO: implement}
$0
}
endsnippet
Con auto-pairs
" Configurar para que funcione bien con snippets
let g:AutoPairsMapCR = 0
imap <silent><CR> <C-R>=AutoPairsReturn()<CR>
¡Los snippets bien organizados pueden acelerar dramáticamente tu velocidad de desarrollo!