__-  ★  :.  .   * .  ..  ☆• ° ★  .   . . ¸• ° ★  . ° .  °☆  . .  █ PROGRAMACIÓN DE PLUGINS PARA ☆• ★  . .  * . .   ° ★   : .   °  . .  ★  ° ☆   .    ★  ★  :. • ° ★  .   . .  ¸      ° ★  . ° .   .  ¸.   . • ° ██ ¸ .  ★  ★ ° ☆    .  °☆  . * //      : . . ★  .  * . .   ██ ██ ██ ▓▓▓▓▓▓▓▓▓▓    °  ¸. ¸ . . °  . .  ★   /██ /██/██//▓▓//▓▓//▓▓  .  ★   ★ ☆ . . • //██ /██ /██ /▓▓ /▓▓ /▓▓ .       °☆  . //████ /██ /▓▓ /▓▓ /▓▓   ★ ° .   . • ★ °   .     . //██ /██ ▓▓▓ /▓▓ /▓▓  .     ★ ○ °      . .   // // /// // //    °  ¸. ¸ . . • ° ° ☆     :. .  ★ ☆ .   .   ★  . ° .   .  ¸. ★  . ° .   .  ¸. ★  .  __▄ ☆ ¸. ☆ ¸. ¸. .  ★   ° ☆ .      ° ☆ ¸. ¸. ╚▌  . . . https://www.meetup.com/cdmx-vim-meetup/   .○ ° ██ ¸ ▄ ☆ ☆ ¸. ¸. .  ★ .  ★  ▐█ °☆  ☾ ▄█████▄ . ° .  Julio 27, 2017, Vim-CDMX ▐█ ★ ☆ ╓██▀▀▀▀▀██, ¸• ° ★  . ° ★  . __ ╟░b ▐█ ⌡███████████, ° ★ http://javier.io ░░ ╟░b▓░ ▐█ ∞▄ Φ,⌡░∩█████████████,(▓░ _ ⌡ ░░ ░░░░░▐██ ▓▓∩▓▌▓▓⌡▌⌡░▓▌⌡░⌡███▓░░░ ░ ███,▐░██░, ⌡█▌__▄▄_ __ _ _ ▓▓▓▓▓▓▓▓░█████▓▓▓░█████████▓▓▓███▓▓░▓x░∞███▓▓░██▓▓█▓▓▓██▓█████▓▓▓▓░▓▓░███▓ ████████████████▓██████████████▓███▓█▓▓▓▓▓███▓▓███████████▓█████▓▓▓███████████ @autoexe{ vim: set tw=78 ts=8 ft=help: } @autoexe{} echohl WarningMsg let err_msg="Error: no se ha encontrado una sesión de Tmux activa" let err_msg.=", por favor cree una e invoque esta presentación desde ahi" if !exists('$TMUX') | echo err_msg | endif echohl None @end ============================================================================== *CONTENIDOS* 1. Intro ............................................................. |3| 2. Autores prominentes ............................................... |1| 3. Librerias ......................................................... |4| 4. Tipos de plugins .................................................. |2| 5. Documentacion ..................................................... |3| 6. Caso de uso, vlide.vim ............................................ |4| 6.1 RDD, desarrollo orientado a documentacion ..................... |4| 6.2 Estructura general ............................................ |4| 6.2 Variables ..................................................... |4| 6.3 Funciones de usuario .......................................... |4| 6.4 Comandos ...................................................... |4| 6.5 Mapeos ........................................................ |4| 6.6 Listas y diccionarios ......................................... |4| 6.7 Depuración .................................................... |4| 6.8 Pruebas unitarias, Vader ...................................... |4| 6.9 Integración continua, Travis-CI ............................... |4| 6.10 Publicación .................................................. |4| 6.11 Gestores de plugins .......................................... |4| 7. Fin ............................................................... |4| @autoexe{ vim: set tw=78 ts=8 ft=help: } ============================================================================== INTRO ----- Como programadores pasamos mucho tiempo en editores de texto (o en IDEs), no es de extrañar entonces que dichos entornos sean altamente configurables, incluyan características avanzadas y puedan ser extendidos. @autoexe{ vim: set tw=78 ts=8 ft=markdown: } ------------------------------------------------------------------------------ Un editor propiamente configurado puede afectar directamente la calidad y cantidad de nuestro trabajo. ------------------------------------------------------------------------------ Por ejemplo, partiendo del siguiente código en C desordenado, Vim puede: @autoexe{sh} cat << EOF > /tmp/vlide_monkey_typer.c #include #include char * as_i_get_older_my_variables_get_longer = "monkey typer"; int randint(int n) { if ((n - 1) == RAND_MAX) { return rand(); } else { // Chop off all of the values that would cause skew... long end = RAND_MAX / n; // truncate skew assert (end > 0L); end *= n; } } EOF tmux split-window -v -p 50 tmux send-keys -t1 'vim /tmp/vlide_monkey_typer.c' tmux send-keys -t1 C-M tmux select-pane -t0 @end ------------------------------------------------------------------------------ * identar ------------------------------------------------------------------------------ @autoexe{sh} tmux send-keys -t1 'gg' tmux send-keys -t1 '=' tmux send-keys -t1 'G' tmux select-pane -t0 @end ------------------------------------------------------------------------------ * autocompletar variables / funciones ------------------------------------------------------------------------------ @autoexe{sh} tmux send-keys -t1 'G' tmux send-keys -t1 'o' tmux send-keys -t1 C-M tmux send-keys -t1 'a'; sleep 0.5 tmux send-keys -t1 's'; sleep 0.5 tmux send-keys -t1 '_'; sleep 0.5 tmux send-keys -t1 'i'; tmux select-pane -t0 @end ------------------------------------------------------------------------------ * expandir snippets ------------------------------------------------------------------------------ @autoexe{sh} tmux send-keys -t1 C-M; sleep 0.5 tmux send-keys -t1 C-M; tmux send-keys -t1 C-M; tmux send-keys -t1 'm'; sleep 0.5 tmux send-keys -t1 'a'; sleep 0.5 tmux send-keys -t1 'i'; sleep 0.5 tmux send-keys -t1 'n'; sleep 2 tmux send-keys -t1 Tab tmux select-pane -t0 @end ------------------------------------------------------------------------------ * consultar referencias ------------------------------------------------------------------------------ @autoexe{sh} tmux send-keys -t1 Escape tmux send-keys -t1 dd tmux send-keys -t1 ':h crv-assert' tmux send-keys -t1 C-M tmux select-pane -t0 @end ------------------------------------------------------------------------------ * navegar entre funciones / variables / archivos ------------------------------------------------------------------------------ @autoexe{sh} tmux send-keys -t1 ':q' tmux send-keys -t1 C-M tmux send-keys -t1 Escape tmux send-keys -t1 ',d' #enter XDevelopmentMode tmux select-pane -t0 @end ------------------------------------------------------------------------------ * notificar errores, advertencias o mensajes externos ------------------------------------------------------------------------------ @autoexe{sh} tmux send-keys -t1 ',d' #exit XDevelopmentMode tmux send-keys -t1 ':w!' tmux send-keys -t1 C-M tmux select-pane -t0 @end ------------------------------------------------------------------------------ * compilar y ejecutar pruebas ------------------------------------------------------------------------------ @autoexe{sh} cat << 'EOF' > /tmp/vlide_monkey_typer.c #include #include #include #include #include char alphabet[] = "abcdefghijklmnopqrstuvwxyz "; int randint(int n) { if ((n - 1) == RAND_MAX) { return rand(); } else { long end = RAND_MAX / n; assert (end > 0L); end *= n; int r; while ((r = rand()) >= end); return r % n; } } char * monkey(long unsigned int len) { char * monkey_phrase = malloc(sizeof(char) * len); int i; for (i = 0; i < len; i++) { monkey_phrase[i] = alphabet[randint(27)]; } monkey_phrase[len] = '\0'; return monkey_phrase; } int evaluate(char * monkey_phrase, char * phrase) { int score = 0; int i = 0; for (i = 0; i < strlen(phrase); i++) { if (monkey_phrase[i] == phrase[i]) { score++; } } if (score > 0) score = (score * 100) / strlen(phrase); return score; } int main(int argc, char const* argv[]) { if(argc == 1){ printf("Usage: %s phrase\n", argv[0]); exit(EXIT_FAILURE); } char phrase[strlen(argv[1]) + 1]; strncpy(phrase, argv[1], sizeof(phrase)); char best_phrase[sizeof(phrase)]; char monkey_phrase[sizeof(phrase)]; int best_score = 0; int score = 0; long unsigned int i = 0; srand(time(NULL)); while (1) { strncpy(monkey_phrase, monkey(sizeof(phrase)-1), sizeof(phrase)); score = evaluate(monkey_phrase, phrase); if (score == 100) { printf("monkey wrote it and only took %lu tries!\n", i); exit(EXIT_SUCCESS); } else { if (best_score < score) { best_score = score; strncpy(best_phrase, monkey_phrase, sizeof(monkey_phrase)); } if (i % 100000 == 0) printf("%10lu - best score so far against '%s' is '%s' (%d%%), current '%s' (%d%%)\n", i, phrase, best_phrase, best_score, monkey_phrase, score); } i++; } } EOF [ "$(tmux list-panes | wc -l)" -gt 1 ] && tmux kill-pane -a -t0 tmux split-window -v -p 50 tmux send-keys -t1 'vim /tmp/vlide_monkey_typer.c' tmux send-keys -t1 C-M tmux split-window -t1 -v -p 90 sleep 0.5 tmux send-keys -t1 ':make' for i in 1 2 3; do tmux send-keys -t1 C-M; done sleep 0.5 tmux send-keys -t2 'cp /tmp/vlide_monkey_typer ~/.monkey_typer' tmux send-keys -t2 C-M sleep 0.5 tmux send-keys -t2 '~/.monkey_typer vimmer' tmux send-keys -t2 C-M tmux select-pane -t0 @end ------------------------------------------------------------------------------ * etc... No importa si su editor es Emacs/Visual Studio Code/Atom o Vim, pocas curvas de aprendizaje le serán tan útiles a lo largo de su carrera como dominar su editor de texto. @autoexe{sh} rm -rf ~/.monkey_typer [ "$(tmux list-panes | wc -l)" -gt 1 ] && tmux kill-pane -a -t0 @end ============================================================================== La forma de dominar Vim, es a través de VimL, su lenguaje embebido: "Use Vim settings, rather than Vi settings (much better!). "This must be first, because it changes other options as a side effect. set nocompatible "Make backspace behave in a sane manner. set backspace=indent,eol,start "Switch syntax highlighting on syntax on "Enable file type detection and do language-dependent indenting. filetype plugin indent on Si alguna vez ha modificado el archivo '~/.vimrc', conoce los fundamentos de Vim scripting. @autoexe{ vim: set tw=78 ts=8 ft=vim: } ============================================================================== Otras interfaces ---------------- Adicionalmente, Vim puede comunicarse con otros lenguajes, como Python / Ruby / Lua / Tcl y Perl, siempre y cuando haya sido compilado con dicho soporte y el interprete del lenguaje objetivo se encuentre disponible. @autoexe{ vim: set tw=78 ts=8 ft=markdown: } ------------------------------------------------------------------------------ La función 'has' puede ayudarnos a detectar las opciones disponibles: if has('python') echo "soporte de python2 incluido" else echo "sin soporte de python2 (╯°□°)╯︵ ┻━┻" endif @autoexe{} echohl WarningMsg if has('python') | echo "soporte de python2 incluido" | endif if !has('python') | echo "sin soporte de python2 (╯°□°)╯︵ ┻━┻" | endif echohl None @end @autoexe{ vim: set tw=78 ts=8 ft=vim: } ------------------------------------------------------------------------------ También se puede utilizar el comando 'vim --version': $ vim --version | ag "[+-](python|ruby|lua|tcl|perl)"' @autoexe{sh} tmux split-window -v -p 50 tmux send-keys -t1 'vim --version|head -1; vim --version|awk "/Features/{print; exit;}"; vim --version|ag "[+-](python|ruby|lua|tcl|perl)"' tmux send-keys -t1 C-M tmux select-pane -t0 @end ------------------------------------------------------------------------------ Esta presentación se centrará en la programación de plugins con VimL. @autoexe{sh} [ "$(tmux list-panes | wc -l)" -gt 1 ] && tmux kill-pane -a -t0 @end ============================================================================== VimL / Vim scripting -------------------- Lo bueno: * Embebido, por lo tanto siempre disponible * Simple @autoexe{ vim: set tw=78 ts=8 ft=markdown: } ------------------------------------------------------------------------------ Lo malo: * Lento * Sin soporte multihilo, aunque existen trucos * La libreria estándar es muy pequeña @autoexe{ vim: set tw=78 ts=8 ft=markdown: } ------------------------------------------------------------------------------ Lo feo: * La sintaxis * El depurador * La documentación (poca) @autoexe{ vim: set tw=78 ts=8 ft=markdown: } ============================================================================== Autores prominentes ------------------- Hace poco terminé de escribir mi 8vo plugin, desafortunadamente eso no basta para ser experto en Vim, los siguientes autores sí lo son: * Marty Grenfell, https://github.com/scrooloose * Junegunn Choi, https://github.com/junegunn * Tim Pope, https://github.com/tpope * Shougo Matsu, https://github.com/Shougo * Charles E. Campbell, http://www.drchip.org/astronaut/vim/index.html ------------------------------------------------------------------------------ Por lo tanto, tomen todo lo que diga con una pizca (o varias) de incredulidad. ٩(- ̮̮̃-̃)۶ ============================================================================== Librerias --------- Para complementar la (pequeña) librería estándar de Vim, las personas han escrito extensiones, estas son las más populares: * https://github.com/xolox/vim-misc * https://github.com/LucHermitte/lh-vim-lib * https://github.com/vim-jp/vital.vim * https://github.com/vim-scripts/ingo-library * https://github.com/eparreno/vim-l9 Tal vez en el futuro se fusionen en una sola o se integren en Vim/NeoVim ... ============================================================================== Tipos de plugins ---------------- Los tipos de plugins que se pueden programar para Vim, son: ------------------------------------------------------------------------------ * Generales: definen comandos y mapeos ------------------------------------------------------------------------------ * Por ejemplo: `junegunn/vim-easy-align`, un plugin para formatear código que define el comando `:EasyAlign` @autoexe{sh} cat << 'EOF' > /tmp/vlide_easy-align.mkd |id|titulo|artista| |--|------|-------| |1|Noreste caliente|Band of Bitches| |2|Cordillera|Alex Anwandter| |3|Mania Cardiaca|Enjambre| |4|Fractubela|Tino el Pinguino| |5|Coqueta|Ghetto Kids| EOF [ "$(tmux list-panes | wc -l)" -gt 1 ] && tmux kill-pane -a -t0 tmux split-window -v -p 50 tmux send-keys -t1 'vim /tmp/vlide_easy-align.mkd' tmux send-keys -t1 C-M tmux select-pane -t0 @end ------------------------------------------------------------------------------ @autoexe{sh} sleep 0.5 tmux send-keys -t1 ':%EasyAlign *| {"a":"c"}' tmux send-keys -t1 C-M; sleep 0.5 tmux send-keys -t1 ':' tmux send-keys -t1 Up tmux select-pane -t0 @end ============================================================================== Tipos de plugins ---------------- Los tipos de plugins que se pueden programar para Vim, son: * Generales: definen comandos y mapeos * De eventos: reaccionan a cambios de estado @autoexe{sh} [ "$(tmux list-panes | wc -l)" -gt 1 ] && tmux kill-pane -a -t0 @end ------------------------------------------------------------------------------ * Por ejemplo: `ap/vim-css-color`, que se ejecuta en `CursorMoved`, `CursorMovedI` para colorear códigos hexadecimales. @autoexe{sh} cat << 'EOF' > /tmp/vlide_index.js const Styles = StyleSheet.create({ container: { alignItems: 'stretch', flex: 1 }, body: { flex: 9, flexDirection: 'row', alignItems: 'center', justifyContent: 'center', backgroundColor: '', }, }); EOF [ "$(tmux list-panes | wc -l)" -gt 1 ] && tmux kill-pane -a -t0 tmux split-window -v -p 50 tmux send-keys -t1 'vim /tmp/vlide_index.js' tmux send-keys -t1 C-M tmux select-pane -t0 @end ------------------------------------------------------------------------------ @autoexe{sh} tmux send-keys -t1 "6G0f'a" tmux send-keys -t1 "#8d2"; sleep 3 tmux send-keys -t1 'd1d' tmux select-pane -t0 @end ============================================================================== Tipos de plugins ---------------- Los tipos de plugins que se pueden programar para Vim, son: * Generales: definen comandos y mapeos * De eventos: reaccionan a cambios de estado * De tipo de archivo: solo aplicables a los archivos definidos @autoexe{sh} [ "$(tmux list-panes | wc -l)" -gt 1 ] && tmux kill-pane -a -t0 @end ------------------------------------------------------------------------------ * Por ejemplo: `sheerun/vim-polyglot`, que mejora drásticamente el soporte de sintaxis e integración a diferentes lenguajes de programación, como Nim, https://nim-lang.org @autoexe{sh} cat << 'EOF' > /tmp/vlide_average.nim #Compute average line length var sum = 0 count = 0 for line in stdin.lines: sum += line.len count += 1 echo("Average line length: ", if count > 0: sum / count else: 0) EOF [ "$(tmux list-panes | wc -l)" -gt 1 ] && tmux kill-pane -a -t0 tmux split-window -v -p 50 tmux send-keys -t1 'vim /tmp/vlide_average.nim' tmux send-keys -t1 C-M tmux select-pane -t0 @end ============================================================================== Tipos de plugins ---------------- Los tipos de plugins que se pueden programar para Vim, son: * Generales: definen comandos y mapeos * De eventos: reaccionan a cambios de estado * De tipo de archivo: solo aplicables a los archivos definidos * De temas: definen esquemas de colores @autoexe{sh} [ "$(tmux list-panes | wc -l)" -gt 1 ] && tmux kill-pane -a -t0 @end ------------------------------------------------------------------------------ * Por ejemplo: 'flazz/vim-colorschemes' @autoexe{sh} cat << 'EOF' > /tmp/vlide_dhcp.py #!/usr/bin/env python import socket,binascii,time,os,sys,IN, optparse if not hasattr(IN,"SO_BINDTODEVICE"): IN.SO_BINDTODEVICE = 25 #http://stackoverflow.com/a/8437870/541038 def slicendice(msg,slices): for x in slices: if str(type(x)) == "": x=eval(x) yield msg[:x] msg = msg[x:] EOF [ "$(tmux list-panes | wc -l)" -gt 1 ] && tmux kill-pane -a -t0 tmux split-window -v -p 50 tmux send-keys -t1 'vim /tmp/vlide_dhcp.py' tmux send-keys -t1 C-M tmux select-pane -t0 @end ------------------------------------------------------------------------------ @autoexe{sh} tmux send-keys -t1 ':colorscheme default' tmux send-keys -t1 C-M tmux select-pane -t0 @end ------------------------------------------------------------------------------ @autoexe{sh} tmux send-keys -t1 ':colorscheme pencil' tmux send-keys -t1 C-M tmux select-pane -t0 @end ------------------------------------------------------------------------------ @autoexe{sh} tmux send-keys -t1 ':colorscheme murphy' tmux send-keys -t1 C-M tmux select-pane -t0 @end ============================================================================== Los tipos de plugins que se pueden programar para Vim, son: * Generales: definen comandos y mapeos * De eventos: reaccionan a cambios de estado * De tipo de archivo: solo aplicables a los archivos definidos * De temas: definen esquemas de colores Esta presentación se centrará en la programación de plugins generales o de comandos. @autoexe{sh} [ "$(tmux list-panes | wc -l)" -gt 1 ] && tmux kill-pane -a -t0 tmux send-keys -t0 '/Generales: definen comandos y mapeos' tmux send-keys -t0 C-M tmux send-keys -t0 'gg0' @end ============================================================================== Documentación ------------- La documentación oficial aunque es buena referencia no es la mejor guía para comenzar. ------------------------------------------------------------------------------ :help usr_41.txt @autoexe{} help usr_41.txt wincmd p "forces to return the focus to the window who call it @end ------------------------------------------------------------------------------ :help function-list @autoexe{} help function-list wincmd p "forces to return the focus to the window who call it @end ------------------------------------------------------------------------------ Es mejor: https://www.ibm.com/developerworks/library/l-vim-script-1/index.html O http://vim.wikia.com/wiki/Vim_Tips_Wiki que contiene una cantidad considerable de snippets. @autoexe{} "close all but the presentation buffer let buffer = bufnr("%") | let lbuffer = bufnr("$") | let i = buffer while i <= lbuffer | if i != buffer && bufexists(i) | silent exe "bwipe " . i | endif | let i = i+1 | endwhile @end ------------------------------------------------------------------------------ Una mención especial a: http://learnvimscriptthehardway.stevelosh.com/ que aunque aparece con frecuencia en los resultados de búsqueda su contenido es poco relevante (los ejemplos con frecuencia son muy simples). ============================================================================== Caso de uso ----------- ▄ ▄ ▄ ▄▄▄▄▄▄▄▄▄▄▄ ▄▄▄▄▄▄▄▄▄▄ ▄▄▄▄▄▄▄▄▄▄▄ ▐░▌ ▐░▌▐░▌ ▐░░░░░░░░░░░▌▐░░░░░░░░░░▌ ▐░░░░░░░░░░░▌ ▐░▌ ▐░▌ ▐░▌ ▀▀▀▀█░█▀▀▀▀ ▐░█▀▀▀▀▀▀▀█░▌▐░█▀▀▀▀▀▀▀▀▀ ▐░▌ ▐░▌ ▐░▌ ▐░▌ ▐░▌ ▐░▌▐░▌ ▐░▌ ▐░▌ ▐░▌ ▐░▌ ▐░▌ ▐░▌▐░█▄▄▄▄▄▄▄▄▄ ▐░▌ ▐░▌ ▐░▌ ▐░▌ ▐░▌ ▐░▌▐░░░░░░░░░░░▌ ▐░▌ ▐░▌ ▐░▌ ▐░▌ ▐░▌ ▐░▌▐░█▀▀▀▀▀▀▀▀▀ ▐░▌ ▐░▌ ▐░▌ ▐░▌ ▐░▌ ▐░▌▐░▌ ▐░▐░▌ ▐░█▄▄▄▄▄▄▄▄▄ ▄▄▄▄█░█▄▄▄▄ ▐░█▄▄▄▄▄▄▄█░▌▐░█▄▄▄▄▄▄▄▄▄ ▐░▌ ▐░░░░░░░░░░░▌▐░░░░░░░░░░░▌▐░░░░░░░░░░▌ ▐░░░░░░░░░░░▌ ▀ ▀▀▀▀▀▀▀▀▀▀▀ ▀▀▀▀▀▀▀▀▀▀▀ ▀▀▀▀▀▀▀▀▀▀ ▀▀▀▀▀▀▀▀▀▀▀ https://github.com/javier-lopez/vlide.vim, un plugin para crear presentaciones interactivas con Vim ============================================================================== RDD, Readme Driven Development ------------------------------ Pero antes, un parentesis para describir una metodología que me ha funcionado para desarrollar plugins y otros proyectos de software libre, RDD: * http://tom.preston-werner.com/2010/08/23/readme-driven-development.html ------------------------------------------------------------------------------ - La programación es iterativa, no se conoce el problema hasta que no se resuelve, es más fácil iterar sobre documentación que sobre código. ------------------------------------------------------------------------------ - Una implementación perfecta de la especificación erronea es peor que una mala implementación de la correcta. ------------------------------------------------------------------------------ - No se trata de especificar a detalle cada características, sino de comenzar una discusión sobre las principales propiedades del sistema. Esto es especialmente útil discutir el proyecto con otros desarrolladores. ------------------------------------------------------------------------------ - Es más fácil escribir documentación al inicio de un proyecto que al final ( ͡° ͜ʖ ͡°) ============================================================================== RDD, Readme Driven Development ------------------------------ Aplicando estos principios me he encontrado repitiendo los siguientes pasos para cada nuevo plugin. ------------------------------------------------------------------------------ - Escribir el manual, **doc/plugin.txt** - Aquí se describen los comandos y opciones de configuraciones del plugin `:help NuestroPlugin` ------------------------------------------------------------------------------ - Escribir las pruebas unitarias y de integración, **tests/plugin.vader** ------------------------------------------------------------------------------ - Implementar el plugin de acuerdo a las pruebas y documentación. **plugin** **autoload**, **ftplugin**, **after** ------------------------------------------------------------------------------ - Escribir el archivo **README.mkd** con un subconjunto de los comandos y configuraciones descritos en **doc/plugin.txt**. ------------------------------------------------------------------------------ - Este documento hace enfásis en la instalación y primeros pasos, ¡usar **imágenes/videos y/o gifs**! ------------------------------------------------------------------------------ - Agregar insignias que describan el estado de las pruebas continuas, dependencias, licencias, etc ๑( ͝° ͜ʖ͡°)و ============================================================================== Estructura general ------------------ ▾ vlide.vim/ ▸ autoload/ ▸ doc/ ▸ plugin/ ▸ tests/ README.md @autoexe{} "close all but the presentation buffer let buffer = bufnr("%") | let lbuffer = bufnr("$") | let i = buffer while i <= lbuffer | if i != buffer && bufexists(i) | silent exe "bwipe " . i | endif | let i = i+1 | endwhile @end ============================================================================== Estructura general ------------------ ▾ vlide.vim/ ▸ autoload/ ▸ doc/ ▸ plugin/ vlide.vim => punto de partida, definición de comandos y mapeos ▸ tests/ README.md @autoexe{} "close all but the presentation buffer let buffer = bufnr("%") | let lbuffer = bufnr("$") | let i = buffer while i <= lbuffer | if i != buffer && bufexists(i) | silent exe "bwipe " . i | endif | let i = i+1 | endwhile let l:file = split(globpath(&runtimepath, "plugin/vlide.vim")) if !empty(l:file) | execute "split " . l:file[0] | wincmd p | endif @end ============================================================================== Estructura general ------------------ ▾ vlide.vim/ ▸ autoload/ => implementación perezosa ▾ vlide/ ▸ autoexe/ autoexe.vim init.vim slide.vim subslide.vim util.vim vlide.vim ▸ doc/ ▸ plugin/ ▸ tests/ README.md @autoexe{} "close all but the presentation buffer let buffer = bufnr("%") | let lbuffer = bufnr("$") | let i = buffer while i <= lbuffer | if i != buffer && bufexists(i) | silent exe "bwipe " . i | endif | let i = i+1 | endwhile let l:file = split(globpath(&runtimepath, "autoload/vlide.vim")) if !empty(l:file) | execute "split " . l:file[0] | wincmd p | endif @end ============================================================================== Variables --------- let ▸ define variables unlet ▸ elimina variables @autoexe{} "close all but the presentation buffer let buffer = bufnr("%") | let lbuffer = bufnr("$") | let i = buffer while i <= lbuffer | if i != buffer && bufexists(i) | silent exe "bwipe " . i | endif | let i = i+1 | endwhile @end ------------------------------------------------------------------------------ |buffer-variable| b:variable Local al buffer actual |window-variable| w:variable Local a la ventana actual |tabpage-variable| t:variable Local a la pestaña actual |global-variable| g:variable Global. |local-variable| l:variable Local a la función |script-variable| s:variable Local al script |function-argument| a:variable Argumentos de funciones |vim-variable| v:variable Global, predefinidas por Vim. @autoexe{ vim: set tw=78 ts=8 ft=help: } @autoexe{} "close all but the presentation buffer let buffer = bufnr("%") | let lbuffer = bufnr("$") | let i = buffer while i <= lbuffer | if i != buffer && bufexists(i) | silent exe "bwipe " . i | endif | let i = i+1 | endwhile let l:file = split(globpath(&runtimepath, "autoload/vlide.vim")) if !empty(l:file) | execute "split " . l:file[0] | call cursor(7,0) | setlocal cursorline | wincmd p | endif @end @autoexe{sh} tmux send-keys -t0 ':wincmd p' tmux send-keys -t0 C-M tmux send-keys -t0 ':Grep [bwtglsav]:' tmux send-keys -t0 C-M tmux send-keys -t0 ':wincmd t' #mv cursor to the top window tmux send-keys -t0 C-M @end ------------------------------------------------------------------------------ @autoexe{} "close all but the presentation buffer let buffer = bufnr("%") | let lbuffer = bufnr("$") | let i = buffer while i <= lbuffer | if i != buffer && bufexists(i) | silent exe "bwipe " . i | endif | let i = i+1 | endwhile "reset search pattern let @/ = "" @end ============================================================================== Funciones de usuario -------------------- function! NombreFuncion({argumentos}) [range|abort|dict] @autoexe{ vim: set tw=78 ts=8 ft=vim: } @autoexe{} "close all but the presentation buffer let buffer = bufnr("%") | let lbuffer = bufnr("$") | let i = buffer while i <= lbuffer | if i != buffer && bufexists(i) | silent exe "bwipe " . i | endif | let i = i+1 | endwhile let l:file = split(globpath(&runtimepath, "plugin/vlide.vim")) if !empty(l:file) | execute "split " . l:file[0] | call cursor(40,0) | setlocal cursorline | wincmd p | endif @end ------------------------------------------------------------------------------ function! directorio#archivo#funcion({argumentos}) [range|abort|dict] @autoexe{ vim: set tw=78 ts=8 ft=vim: } @autoexe{} "close all but the presentation buffer let buffer = bufnr("%") | let lbuffer = bufnr("$") | let i = buffer while i <= lbuffer | if i != buffer && bufexists(i) | silent exe "bwipe " . i | endif | let i = i+1 | endwhile let l:file = split(globpath(&runtimepath, "autoload/vlide/slide.vim")) if !empty(l:file) | execute "split " . l:file[0] | call cursor(7,0) | setlocal cursorline | wincmd p | endif @end ------------------------------------------------------------------------------ Número de argumentos: function! Funcion() ▸ no acepta argumentos function! Funcion(bang) ▸ acepta 1 argumento referenciado como a:bang function! Funcion(bang, ...) ▸ acepta 1 o más argumentos function! Funcion(...) ▸ acepta 0 o más argumentos @autoexe{ vim: set tw=78 ts=8 ft=vim: } @autoexe{} "close all but the presentation buffer let buffer = bufnr("%") | let lbuffer = bufnr("$") | let i = buffer while i <= lbuffer | if i != buffer && bufexists(i) | silent exe "bwipe " . i | endif | let i = i+1 | endwhile @end ------------------------------------------------------------------------------ :help E884 @autoexe{ vim: set tw=78 ts=8 ft=vim: } @autoexe{} "close all but the presentation buffer let buffer = bufnr("%") | let lbuffer = bufnr("$") | let i = buffer while i <= lbuffer | if i != buffer && bufexists(i) | silent exe "bwipe " . i | endif | let i = i+1 | endwhile help E884 wincmd p "forces to return the focus to the window who call it @end ============================================================================== Comandos -------- Los comandos son alias de funciones, pueden recibir rangos, argumentos y atributos. command! -nargs=* -complete=file -bang Vlide call vlide#start(0,) | `▸ Número de argumentos: 0-n, ? (0 o 1), + (1 o más), * (0 o más) :help command-nargs @autoexe{ vim: set tw=78 ts=8 ft=vim: } @autoexe{} "close all but the presentation buffer let buffer = bufnr("%") | let lbuffer = bufnr("$") | let i = buffer while i <= lbuffer | if i != buffer && bufexists(i) | silent exe "bwipe " . i | endif | let i = i+1 | endwhile help command-nargs wincmd p "forces to return the focus to the window who call it @end ============================================================================== Comandos -------- Los comandos son alias de funciones, pueden recibir rangos, argumentos y atributos. command! -nargs=* -complete=file -bang Vlide call vlide#start(0,) | `▸ Tipo de autocompletado, file, help, custom, etc :help command-complete @autoexe{ vim: set tw=78 ts=8 ft=vim: } @autoexe{} "close all but the presentation buffer let buffer = bufnr("%") | let lbuffer = bufnr("$") | let i = buffer while i <= lbuffer | if i != buffer && bufexists(i) | silent exe "bwipe " . i | endif | let i = i+1 | endwhile help command-complete wincmd p "forces to return the focus to the window who call it @end ============================================================================== Comandos -------- Los comandos son alias de funciones, pueden recibir rangos, argumentos y atributos. command! -nargs=* -complete=file -bang Vlide call vlide#start(0,) | `▸ Con modificador !, para forzar / conmutar :help command-bang @autoexe{ vim: set tw=78 ts=8 ft=vim: } @autoexe{} "close all but the presentation buffer let buffer = bufnr("%") | let lbuffer = bufnr("$") | let i = buffer while i <= lbuffer | if i != buffer && bufexists(i) | silent exe "bwipe " . i | endif | let i = i+1 | endwhile help command-bang wincmd p "forces to return the focus to the window who call it @end ============================================================================== Comandos -------- Los comandos son alias de funciones, pueden recibir rangos, argumentos y atributos. command! -nargs=* -complete=file -bang Vlide call vlide#start(0,) | `▸ Comando / alias @autoexe{ vim: set tw=78 ts=8 ft=vim: } @autoexe{} "close all but the presentation buffer let buffer = bufnr("%") | let lbuffer = bufnr("$") | let i = buffer while i <= lbuffer | if i != buffer && bufexists(i) | silent exe "bwipe " . i | endif | let i = i+1 | endwhile @end ============================================================================== Comandos -------- Los comandos son alias de funciones, pueden recibir rangos, argumentos y atributos. command! -nargs=* -complete=file -bang Vlide call vlide#start(0,) | `▸ Acción @autoexe{ vim: set tw=78 ts=8 ft=vim: } @autoexe{} "close all but the presentation buffer let buffer = bufnr("%") | let lbuffer = bufnr("$") | let i = buffer while i <= lbuffer | if i != buffer && bufexists(i) | silent exe "bwipe " . i | endif | let i = i+1 | endwhile @end ============================================================================== Comandos -------- Los comandos son alias de funciones, pueden recibir rangos, argumentos y atributos. command! -nargs=* -complete=file -bang Vlide call vlide#start(0,) | `▸ Función @autoexe{ vim: set tw=78 ts=8 ft=vim: } @autoexe{} "close all but the presentation buffer let buffer = bufnr("%") | let lbuffer = bufnr("$") | let i = buffer while i <= lbuffer | if i != buffer && bufexists(i) | silent exe "bwipe " . i | endif | let i = i+1 | endwhile @end ============================================================================== Comandos -------- Los comandos son alias de funciones, pueden recibir rangos, argumentos y atributos. command! -nargs=* -complete=file -bang Vlide call vlide#start(0,) | atributo booleano 0 o !0 ◂´ @autoexe{ vim: set tw=78 ts=8 ft=vim: } @autoexe{} "close all but the presentation buffer let buffer = bufnr("%") | let lbuffer = bufnr("$") | let i = buffer while i <= lbuffer | if i != buffer && bufexists(i) | silent exe "bwipe " . i | endif | let i = i+1 | endwhile let l:file = split(globpath(&runtimepath, "autoload/vlide.vim")) if !empty(l:file) | execute "split " . l:file[0] | call cursor(8,0) | setlocal cursorline | wincmd p | endif @end ============================================================================== Comandos -------- Los comandos son alias de funciones, pueden recibir rangos, argumentos y atributos. command! -nargs=* -complete=file -bang Vlide call vlide#start(0,) | argumentos adicionales ◂´ @autoexe{ vim: set tw=78 ts=8 ft=vim: } @autoexe{} "close all but the presentation buffer let buffer = bufnr("%") | let lbuffer = bufnr("$") | let i = buffer while i <= lbuffer | if i != buffer && bufexists(i) | silent exe "bwipe " . i | endif | let i = i+1 | endwhile let l:file = split(globpath(&runtimepath, "autoload/vlide.vim")) if !empty(l:file) | execute "split " . l:file[0] | call cursor(11,0) | setlocal cursorline | wincmd p | endif @end ============================================================================== Mapeos ------ Defición de atajos de teclado. nnoremap