Capítulo 26: Condicionales y bucles en Vimscript
Después de aprender cuales son los tipos básicos de datos que existen en Vimscript, el siguiente paso es aprender cómo combinarlos para empezar a escribir un programa básico. Un programa básico consiste en condicionales y bucles.
En este capítulo, aprenderás cómo utilizar los tipos de datos de Vimscript para escribir esos condicionales y bucles.

Operadores relacionales

Los operadores relacionales de Vimscript son similares a los que que existen en la mayoría de lenguajes de programación:
1
a == b igual a
2
a != b no igual a
3
a > b mayor que
4
a >= b mayor o igual que
5
a < b menor que
6
a <= b menor o igual que
Copied!
Por ejemplo:
1
:echo 5 == 5
2
:echo 5 != 5
3
:echo 10 > 5
4
:echo 10 >= 5
5
:echo 10 < 5
6
:echo 5 <= 5
Copied!
Recuerda que las strings o cadenas son forzadas a números en una expresión aritmética. Aquí Vim fuerza las cadenas a números en una expresión de igualdad."5foo" es forzado a 5 (verdadero):
1
:echo 5 == "5foo"
2
" devuelve true
Copied!
También recuerda que si comienzas una cadena con un carácter no numérico como "foo5", la cadena es convertida al número 0 (falso).
1
echo 5 == "foo5"
2
" devuelve false
Copied!

Operadores lógicos para cadenas

Vim tiene más operadores relacionales para comparar cadenas:
1
a =~ b
2
a !~ b
Copied!
Por ejemplo:
1
let str = "abundante desayuno"
2
3
echo str =~ "abundante"
4
" devuelve true
5
6
echo str =~ "cena"
7
" devuelve false
8
9
echo str !~ "cena"
10
" devuelve true
Copied!
El operador =~ realiza una coincidencia de expresiones regulares contra la cadena dada. En el ejemplo anterior, str =~ "hearty" devuelve verdadero porque str contiene el patrón "abundante". Siempre puedes utilizar == o !=, pero al usarlos comparará la expresión contra la cadena entera. =~ o !~ son unas elecciones más flexibles.
1
echo str == "abundante"
2
" devuelve false
3
4
echo str == "abundante desayuno"
5
" devuelve true
Copied!
Vamos a probar esta otra. Ten en cuenta la letra mayúscula "A":
1
echo str =~ "Abundante"
2
" true
Copied!
Devuelve verdadero incluso aunque "Abundante" comience con mayúscula. Interesante... Resulta que mi ajuste de Vim está establecido para ignorar las mayúsculas (set ignorecase), así que cuando Vim comprueba la igualdad, utiliza mis ajustes de Vim e ignora esa letra en mayúscula. Si inhabilitara esa opción de ignorar mayúsculas (set noignorecase), la comparación ahora devolvería un falso.
1
set noignorecase
2
echo str =~ "Abundante"
3
" devuelve false porque tiene en cuenta las mayúsculas
4
5
set ignorecase
6
echo str =~ "Abundante"
7
" devuelve true porque no tiene en cuenta las mayúsculas
Copied!
Si estás escribiendo un complemento para otras personas, esto puede ser una situación engorrosa. ¿Utiliza esa persona ignorecase o noignorecase? Realmente no quieres forzar a nadie a cambiar sus opciones de ignorar o no las mayúsculas. ¿Qué puedes hacer?
Afortunadamente, Vim tiene un par de operadores que siempre puede ignorar o tener en cuenta las mayúsculas y minúsculas. Para siempre tener en cuenta las mayúsculas, añade un # al final.
1
set ignorecase
2
echo str =~# "abundante"
3
" devuelve true
4
5
echo str =~# "AbundaNTe"
6
" devuelve false
7
8
set noignorecase
9
echo str =~# "abundante"
10
" true
11
12
echo str =~# "AbundaNTe"
13
" false
14
15
echo str !~# "AbundaNTe"
16
" true
Copied!
Para siempre ignorar las mayúsculas y minúsculas al comparar, añade ?:
1
set ignorecase
2
echo str =~? "abundante"
3
" true
4
5
echo str =~? "AbundaNTe"
6
" true
7
8
set noignorecase
9
echo str =~? "abundante"
10
" true
11
12
echo str =~? "AbundaNTe"
13
" true
14
15
echo str !~? "AbundaNTe"
16
" false
Copied!
Yo prefiero utilizar # para siempre tener en cuenta las mayúsculas y minúsculas y siempre ir sobre seguro.

If

Ahora que ya has visto las expresiones de igualdad de Vim, vamos a tratar un operador condicional fundamental, la sentencia if.
Como mínimo, la sintaxis es:
1
if {cláusula}
2
{alguna expresión}
3
endif
Copied!
Puedes extender el análisis del caso con elseif y else.
1
if {predicado1}
2
{expresión1}
3
elseif {predicado2}
4
{expresión2}
5
elseif {predicado3}
6
{expresión3}
7
else
8
{expresión4}
9
endif
Copied!
Por ejemplo, el complemento vim-signify utiliza un método diferente de instalación dependiendo de tus ajustes de Vim. Debajo está la instrucción de instalación copiada desde su readme, utilizando la instrucción if:
1
if has('nvim') || has('patch-8.0.902')
2
Plug 'mhinz/vim-signify'
3
else
4
Plug 'mhinz/vim-signify', { 'branch': 'legacy' }
5
endif
Copied!

Expresiones ternarias

Vim tiene expresiones ternarias para analizar en una sola línea:
1
{predicado} ? expresión verdadera : expresión falsa
Copied!
Por ejemplo:
1
echo 1 ? "Soy verdadero" : "Soy falso"
Copied!
Como 1 es tomado como verdadero, Vim mostrará el mensaje "Soy verdadero". Supongamos que quieres establecer una condición para configurar background a oscuro si estás usando Vim después de cierta hora. Añade esto a tu vimrc:
1
let &background = strftime("%H") < 18 ? "light" : "dark"
Copied!
&background es la opción de 'background' en Vim. strftime("%H") devuelve la hora actual. Si todavía no son las 6 PM, utiliza un fondo claro. De lo contrario, utilizará un fondo oscuro.

Or (O)

El "or" lógico (||) funciona como en la mayoría de lenguajes de programación.
1
{Expresión falsa} || {Expresión falsa} false
2
{Expresión falsa} || {Expresión verdadera} true
3
{Expresión verdadera} || {Expresión falsa} true
4
{Expresión verdadera} || {Expresión verdadera} true
Copied!
Vim evalúa la expresión y devuelve un 1 (verdadero) o 0 (falso).
1
echo 5 || 0
2
" devuelve 1
3
4
echo 5 || 5
5
" devuelve 1
6
7
echo 0 || 0
8
" devuelve 0
9
10
echo "foo5" || "foo5"
11
" devuelve 0
12
13
echo "5foo" || "foo5"
14
" devuelve 1
Copied!
Dentro del or la primera expresión se evalúa y si es verdadera, la expresión siguiente no será evaluada.
1
let una_docena = 12
2
3
echo una_docena || dos_docenas
4
" devuelve 1
5
6
echo dos_docenas || una_docena
7
" devuelve error
Copied!
Ten en cuenta que dos_docena no se ha definido nunca. La expresión una_docena || dos_docenas no muestra ningún error porque una_docena es evaluada primero y encuentra que es verdadera, por lo que Vim ya no evalúa dos_docenas.

And (Y)

El "and" lógico (&&) es el complemento del "o" lógico.
1
{Expresión falsa} && {Expresión falsa} false
2
{Expresión falsa} && {Expresión verdadera} false
3
{Expresión verdadera} && {Expresión falsa} false
4
{Expresión verdadera} && {Expresión verdadera} true
Copied!
Por ejemplo:
1
echo 0 && 0
2
" devuelve 0
3
4
echo 0 && 10
5
" devuelve 0
Copied!
&& evalúa una expresión hasta que ve la primera expresión falsa. Por ejemplo, si tienes true && true, evaluará ambas y devolverá true. Si tienes true && false && true, evaluará el primer true y parará en el primer false. No evaluará el tercer true.
1
let una_docena = 12
2
echo una_docena && 10
3
" devuelve 1
4
5
echo una_docena && v:false
6
" devuelve 0
7
8
echo una_docena && dos_docenas
9
" devuelve error
10
11
echo exists("una_docena") && una_docena == 12
12
" devuelve 1
Copied!

For

El bucle for es comúnmente utilizado con el tipo de datos listas.
1
let desayunos = ["tortitas", "gofres", "huevos"]
2
3
for comida in desayunos
4
echo comida
5
endfor
Copied!
También funciona con listas anidadas:
1
let meals = [["desayuno", "tortitas"], ["almuerzo", "pescado"], ["cena", "pasta"]]
2
3
for [tipo_comida, comida] in meals
4
echo "Estoy tomando " . comida . " para " . tipo_comida
5
endfor
Copied!
Técnicamente puedes utilizar el bucle for con un diccionario utilizando el método keys().
1
let bebidas = #{desayuno: "leche", almuerzo: "zumo de naranja", cena: "agua"}
2
for tipo_de_bebida in keys(bebidas)
3
echo "Estoy bebiendo " . bebidas[tipo_de_bebida] . " para " . tipo_de_bebida
4
endfor
Copied!

While

Otro bucle común es el bucle while.
1
let contador = 1
2
while contador < 5
3
echo "El valor del contador es: " . contador
4
let contador += 1
5
endwhile
Copied!
Otro ejemplo, para obtener el contenido desde la línea actual hasta la última línea:
1
let linea_actual = line(".")
2
let ultima_linea = line("quot;)
3
4
while linea_actual <= ultima_linea
5
echo getline(linea_actual)
6
let linea_actual += 1
7
endwhile
Copied!

Gestión del error

A menudo tu programa no funciona en la manera que esperas. Como resultado, el programa te lleva a un bucle (valga el juego de palabras). Lo que necesitas es una gestión del error adecuada.

Break

Cuando utilizas break dentro de un bucle while o for, esto detiene el bucle.
Veamos un ejemplo, modificando un poco el anterior. Para obtener los textos desde el inicio del archivo hasta la línea actual, pero parar el bucle cuando encuentre la palabra "donut":
1
let linea = 0
2
let ultima linea = line("quot;)
3
let total_palabras = ""
4
5
while linea <= ultima_linea
6
let linea += 1
7
let texto_linea = getline(linea)
8
if texto_linea =~# "donut"
9
break
10
endif
11
echo texto_linea
12
let total_palabras .= texto_linea . " "
13
endwhile
14
15
echo total_palabras
Copied!
Si tienes el siguiente texto:
1
uno
2
dos
3
tres
4
donut
5
cuatro
6
cinco
Copied!
Al ejecutar el bucle while anterior, este mostrará "uno dos tres" y no mostrará el resto de texto, ya que el bucle se detiene por el comando break cuando encuentra en esa lista la palabra "donut".

Continue

El método continue es similar a break, cuando es invocado en un bucle. La diferencia está en que en vez de detener el bucle, simplemente omite la evaluación actual.
Supongamos que tenemos el mismo texto que antes, pero en vez de break, utilizamos continue:
1
let linea = 0
2
let ultima_linea = line("quot;)
3
let total_palabras = ""
4
5
while linea <= ultima_linea
6
let linea += 1
7
let texto_linea = getline(linea)
8
if texto_linea =~# "donut"
9
continue
10
endif
11
echo texto_linea
12
let total_palabras .= linea_texto . " "
13
endwhile
14
15
echo total_palabras
Copied!
Esta vez mostrará uno dos tres cuatro cinco. Ahora salta la línea que contiene la palabra "donut", pero la ejecución del bucle continua.

Try, Finally y Catch

En Vim existe try, finally y catch para la gestión de errores. Para simular un error, puedes utilizar el comando throw.
1
try
2
echo "Try"
3
throw "Nope"
4
endtry
Copied!
Ejecuta esto. Vim mostrará un error "Exception not caught: Nope.
Ahora añade un bloque catch:
1
try
2
echo "Try"
3
throw "Nope"
4
catch
5
echo "Pillado"
6
endtry
Copied!
Ahora ya no habrá un error. Deberías ver "Try" y se mostrará "Pillado".
Vamos a eliminar catch y añadir finally:
1
try
2
echo "Try"
3
throw "Nope"
4
echo "No me verás"
5
finally
6
echo "Finalmente"
7
endtry
Copied!
Ejecuta esto. Ahora Vim muestra el error y el texto "Finalmente".
Vamos a poner todo junto:
1
try
2
echo "Try"
3
throw "Nope"
4
catch
5
echo "Pillado"
6
finally
7
echo "Finalmente"
8
endtry
Copied!
Esta vez Vim muestra tanto "Pillado" y "Finalmente". No se muestra el error por que Vim lo ha "pillado". No error is displayed because Vim caught it.
Los errores provienen de diferentes lugares. Otra fuente de error es una llamada a una función que no existe, como Nada() que veremos a continuación:
1
try
2
echo "Try"
3
call Nada()
4
catch
5
echo "Pillado"
6
finally
7
echo "Finalmente"
8
endtry
Copied!
La diferencia entre catch y finally es que finally siempre se ejecuta, haya error o no. Mientras que catch solo se ejecuta cuando tu código tiene algún error.
Puedes detectar un error específico con :catch. De acuerdo a :h :catch:
1
catch /^Vim:Interrupt$/. " detecta interrupciones (CTRL-C)
2
catch /^Vim\\%((\\a\\+)\\)\\=:E/. " detecta todos los errores de Vim
3
catch /^Vim\\%((\\a\\+)\\)\\=:/. " detecta errores e interrupciones
4
catch /^Vim(write):/. " detecta todos los errores en :write
5
catch /^Vim\\%((\\a\\+)\\)\\=:E123:/ " detecta el error E123
6
catch /my-exception/. " detecta excepciones de usuario
7
catch /.*/ " detecta todo
8
catch. " similar a /.*/
Copied!
Dentro de un bloque try, una interrupción es considerada un error que se puede detectar.
1
try
2
catch /^Vim:Interrupt$/
3
sleep 100
4
endtry
Copied!
En tu vimrc, si utilizas un esquema de color personalizado, como gruvbox, y de manera accidental eliminas el esquema de color del directorio, pero todavía tienes la línea colorscheme gruvbox en tu vimrc, Vim mostrará un error al ejecutar source para volver a tomar en cuenta las modificaciones del vimrc. Para solucionar esto, he añadido lo siguiente a mi vimrc:
1
try
2
colorscheme gruvbox
3
catch
4
colorscheme default
5
endtry
Copied!
Ahora al ejecutar source sin el directorio gruvbox, Vim utilizará colorscheme default el esquema de color predeterminado.

Aprende condicionales de la manera más inteligente

En los capítulos previos, aprendiste sobre los tipos de datos básicos de Vim. En este capítulo, has aprendido cómo combinarlos para escribir programas básicos utilizando condicionales y bucles. Estos están construidos con bloques de programación.
A continuación, vamos a aprender sobre el alcance de las variables.
Última actualización 1mo ago