<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
    <title>Apunte Impensado</title>
    <description>Artículos largos sobre software y computadoras</description>
    <link>https://apunteimpensado.com/</link>
    <language>es</language>
    <lastBuildDate>Tue, 07 Apr 2026 17:53:29 </lastBuildDate>
    <atom:link href="https://apunteimpensado.com/feed.xml" rel="self" type="application/rss+xml" />
    <item>
        <title><![CDATA[Construyendo un Sitio Estático con IA, Por qué tus Primeros Prompts Fallan y Cómo Arreglarlo]]></title>
        <description><![CDATA[<!--
INDEX_START
This section will be parsed for the left sidebar index/chapter list.
Use standard Markdown link syntax - links should point to actual HTML files.
-->
</li>
</ul>
<p>¿Qué estrategias funcionan mejor al momento de realizar un proyecto
de programación asistido por Inteligencia Artificial?</p>
<p>Después de todo interactuamos con la IA de una forma bastante
particular. Le damos instrucciones escritas en un lenguaje natural, y
esperamos recibir la respuesta en un lenguaje formal. Usamos por ejemplo
inglés para describir un problema que requiere una acción en Python.</p>
<p>¿Podemos explicar correctamente las especificaciones de lo que
queremos? De la calidad de las instrucciones depende buena parte de
nuestro éxito.</p>
<p>Pero todas las interacciones encuentran limitaciones técnicas. La
efectividad de la IA no es la misma según la extensión del proyecto, y
necesitamos comprobar los resultados para evitar alucinaciones.</p>
<p>En lo que sigue voy a revisar un caso práctico: la creación de un
sitio estático. Por medio de ese ejemplo vamos a buscar en qué formas
podemos reducir la complejidad de nuestras instrucciones, con el
objetivo de usar la IA para tareas más grandes.</p>
<h2
id="qué-puede-enseñarnos-un-sitio-estático-de-la-utilización-de-la-ia">¿Qué
puede enseñarnos un sitio estático de la utilización de la IA?</h2>
<p>Pensemos en un sitio web estático que utiliza solamente dos
tecnologías:</p>
<ul>
<li>HTML para la estructura.</li>
<li>CSS para el estilo.</li>
</ul>
<p>No tenemos nada más en el proyecto. Una serie de archivos HTML y un
único gran archivo de CSS.</p>
<p>Puede parecer en un primer momento un proyecto sencillo de crear. Una
inteligencia artificial en el año 2025 parece ser capaz de generar todos
esos documentos sin inconvenientes.</p>
<p>Entonces surge la primera pregunta ¿Cuál es la mejor forma de encarar
el sitio?</p>
<p>La primera respuesta puede ser intentar completar el proyecto “One
Shot”. Pedirle a la IA que genere nuestro proyecto por medio de una
única instrucción.</p>
<p>Pero los primeros problemas se hacen aparentes.</p>
<p>Lo más seguro es que terminemos con un único archivo con cientos de
líneas de código, todo el contenido del sitio y el CSS juntos. Y por eso
mismo va a tratarse de una versión muy difícil de mantener y
expandir.</p>
<p>Intentamos simplificar el proyecto obteniendo todo de un solo
movimiento, pero nos encontramos con un archivo enorme en el que
fácilmente se nos pueden escapar errores.</p>
<p>¿Qué podemos hacer entonces?</p>
<p>Digamos que estamos programando con la versión pública de alguna de
las IA más populares. La mayoría de esas interfaces públicas, utilizadas
directamente desde sus propios sitios web, no nos van a permitir subir
múltiples archivos a la vez. E incluso si podemos trabajar con múltiples
archivos dentro de la ventana de contexto, todavía tenemos que tener en
cuenta que a mayor complejidad mayor posibilidad de error.</p>
<p>La solución parece ser movernos del “one shot” hacia un enfoque por
pasos de una forma pausada.</p>
<p>Imaginemos que estamos haciendo la página principal del sitio. Una
estrategia a seguir puede ser la siguiente:</p>
<ol type="1">
<li><p>Pedirle a la IA generar una primera versión de nuestra página
principal que incluya el HTML integrado al CSS.</p></li>
<li><p>Después de tener esa primera versión funcionando, le pedimos a la
IA que separe el código en dos archivos diferentes: .html y
.css</p></li>
</ol>
<p>Esos dos archivos van a estar correctamente vinculados, porque la IA
solamente los separó luego de tener una primera versión funcional.</p>
<p>Ahora solamente tenemos que vincular estos nuevos archivos de forma
local para ver que funcionen en conjunto.</p>
<p>Estamos sin embargo todavía lejos de un sitio funcional. Por eso
tenemos que pensar en…</p>
<h2 id="conocer-el-problema-para-intentar-resolverlo">Conocer el
problema para intentar resolverlo</h2>
<p>Entonces estamos intentando crear un sitio estático.</p>
<p>Y ya conocemos nuestro problema: si encaramos el proyecto de una
forma demasiado general el resultado se vuelve complejo. Y eso genera
nuevos errores.</p>
<p>Para evitar esos errores necesitamos reducir la complejidad. Lo que
buscamos es dividir el problema en partes que podemos manejar. Ahora en
lugar de pedir un sitio web completo, vamos a pensar en generar sus
componentes por separado.</p>
<p>Con eso en mente revisemos ¿Qué es un sitio web?</p>
<p>Un sitio web es una colección de páginas. Por ejemplo.</p>
<ul>
<li>Página de inicio (Landing page / Home page)</li>
<li>Página Acerca de (About page)</li>
<li>Página de contacto (Contact page)</li>
<li>Página de política de privacidad (Privacy policy page)</li>
</ul>
<p>Esas partes comparten elementos de diseño, como vamos a repasar a
continuación.</p>
<p>Nuestro primer intento para simplificar el problema fue pasar de un
único documento HTML+CSS a dos documentos diferentes, uno que contiene
el HTML y otro que contiene el CSS.</p>
<p>Ahora tenemos un segundo nivel de simplificación: podemos pedirle a
la IA que por ejemplo se concentre en únicamente el código de la página
de inicio.</p>
<p>Pero podemos seguir dividiendo el proyecto en módulos.</p>
<p>¿Qué es una página de inicio? Una página de inicio es una colección
de distintas secciones ordenadas:</p>
<p>Barra de navegación (Navigation bar / Header)<br />
Sección hero (Hero section)<br />
Formulario de suscripción (Subscription box )<br />
Pie de página (Footer)</p>
<p>Eso nos da toda otra dimensión para el trabajo con la IA. Empezamos
pidiendo que escriba un sitio web y ahora le pedimos que escriba “Un
Hero section para una página de inicio”.</p>
<p>Para hacer esto es necesario que tengamos conocimiento sobre la
tecnología de nuestro proyecto. Pero este enfoque más reducido nos ayuda
a ganar más control en nuestras instrucciones.</p>
<h2
id="evitar-repeticiones-innecesarias-por-medio-de-las-instrucciones">Evitar
repeticiones innecesarias por medio de las instrucciones</h2>
<p>Cuando empezamos con nuestro ejemplo le pedimos a la IA que genere
toda una parte de nuestro sitio estático en un solo movimiento.</p>
<p>Luego de eso, poco a poco, nos movimos a una forma de organización
más modular.</p>
<p>Nos queda por preguntar ¿Qué es lo que se mantiene dentro de la
memoria de corto plazo de la IA con la que estamos trabajando? ¿Podemos
reutilizar partes de nuestra conversación con la máquina para ahorrarnos
tiempo?</p>
<p>Toda la conversación de nuestro proyecto puede ser utilizada como
contexto previo. Gracias a eso la IA puede reutilizar un bloque que fue
generado con anterioridad dentro de la misma conversación.</p>
<p>Por supuesto el tamaño de una “ventana de contexto” va a variar entre
las diferentes implementaciones públicas de las diferentes IA. Si la
conversación se cierra, si empezamos a trabajar en una nueva
conversación, no podemos hacer referencia a esas otras memorias.</p>
<p>Vamos a volver nuestras instrucciones en algo todavía más
preciso.</p>
<p>Diferentes partes del sitio comparten las mismas estructuras y
clases. Siguiendo con nuestro ejemplo podemos suponer que el mismo “Pie
de Página” se repite mostrando la misma información tanto en la página
de inicio como en la de contacto y la de privacidad.</p>
<p>De esa forma no necesitamos que la IA escriba las mismas partes una y
otra vez. Conocer las reglas del HTML+CSS nos ayuda a resolver ese
problema.</p>
<p>Ahora por ejemplo cuando compartimos el prompt para la página
contacto, podemos decir por ejemplo “El sitio de contacto comparte la
misma barra de navegación y el mismo footer que la página principal”.
Incluso también podemos mencionar de manera explicita una clase o un
nombre ya existente para que pueda volver a ser utilizado.</p>
<p>La idea con eso es evitar que la herramienta escriba una y otra vez
lo mismo. Por ejemplo en nuestro caso, la IA puede escribir un nuevo
HTML haciendo un llamado a una clase que ya existe en una implementación
previa del CSS. Ahora solamente nos queda tener que actualizar la hoja
de estilo sin necesidad de crear un nuevo bloque de código.</p>
<p>Por supuesto también podemos pegar los ejemplos directos dentro de la
instrucción si el ejemplo que buscamos usar no se encuentra dentro de la
ventana de contexto actual.</p>
<h2 id="conclusión">Conclusión</h2>
<p>Con esto le doy un cierre a mi apunte revisando qué podemos aprender
de nuestro trato con la inteligencia artificial (LLM)) mientras creamos
un sitio estático.</p>
<p>Es simplemente un intento por analizar algunas de las cosas que
encontré al utilizar la IA, proponiendo al mismo tiempo una forma de
trabajo más organizada.</p>
<p>Por supuesto todo esta idea puede ser mejorada.</p>
<p>Como ejemplo pensamos de nuevo en el CSS ¿en que forma vamos a
estructurarlo? En este punto conocer las mejores prácticas del lenguaje
va a ayudarnos a entender mejor lo que le pedimos a la IA.</p>
<p>Me gustaría conocer tus opiniones sobre el texto, me gustaría leer tu
correo electrónico con lo que estás pensando del tema.</p>
<p>La seguimos en el próximo apunte.</p>
<p><strong>¿Comentarios o preguntas?</strong> Escríbeme tu opinión a: <a href="mailto:gustavol@apunteimpensado.com">gustavo@apunteimpensado.com</a></p>]]></description>
        <link>https://apunteimpensado.com/construyendo-sitio-estatico-ia-prompts/</link>
        <guid isPermaLink="true">https://apunteimpensado.com/construyendo-sitio-estatico-ia-prompts/</guid>
        <pubDate>Tue, 30 Sep 2025 00:00:00 </pubDate>
    </item>
    <item>
        <title><![CDATA[Ecuaciones Cuadráticas, buscando la explicación más simple]]></title>
        <description><![CDATA[<!--
INDEX_START
This section will be parsed for the left sidebar index/chapter list.
Use standard Markdown link syntax - links should point to actual HTML files.
-->

<script src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml-full.js" type="text/javascript"></script>
<p>En este apunte práctico voy a desarrollar una explicación sobre las
ecuaciones cuadráticas, intentando hacer el tema lo más sencillo que me
resulte posible.</p>
<p>Las ecuaciones cuadráticas siempre aparecen en muchos exámenes y en
planes de estudios, por lo que con esto voy a crear mi propio apunte
para entender de una vez por todas el tema.</p>
<p>Esta explicación va a necesitar atravesar varias capas…como las capas
de una cebolla. Por favor, no escapen del sitio todavía, prometo que
todo va a tener sentido al final.</p>
<p>El plan es el siguiente: Primero vamos a revisar una explicación
técnica. Luego voy a ir poco a poco tratando de explicar cada parte,
para que podamos visualizar el asunto.</p>
<h1 id="qué-es-una-ecuación-cuadrática">¿Qué es una ecuación
cuadrática?</h1>
<p>Una ecuación cuadrática es una ecuación polinómica de segundo grado
que tiene la forma general: \[ax^2 + bx + c = 0 \quad \text{con } a \neq
0.\]</p>
<h2 id="componentes-clave">Componentes clave</h2>
<p>- <strong>Coeficientes:</strong></p>
<p>- \(a\): Coeficiente del término cuadrático, con la condición de que
\(a \neq 0\).</p>
<p>- \(b\): Coeficiente del término lineal.</p>
<p>- \(c\): Término constante o independiente.</p>
<p>- <strong>Variable:</strong></p>
<p>- \(x\): Es la incógnita cuyo valor se busca determinar.</p>
<p>- <strong>Raíces:</strong></p>
<p>- Son los valores de \(x\) que satisfacen la ecuación \(ax^2 + bx + c
= 0\).</p>
<p>- Se pueden encontrar utilizando la fórmula cuadrática: \[x =
\frac{-b \pm \sqrt{b^2 - 4ac}}{2a}.\]</p>
<p>- <strong>Discriminante:</strong></p>
<p>El discriminante de la ecuación cuadrática se define como: \[D = b^2
- 4ac,\] y permite determinar la naturaleza de las raíces:</p>
<p>- Si \(D &gt; 0\), la ecuación tiene dos raíces reales y
distintas.</p>
<p>- Si \(D = 0\), la ecuación tiene una única raíz real, con
multiplicidad dos (raíz doble).</p>
<p>- Si \(D &lt; 0\), la ecuación tiene dos raíces complejas conjugadas,
y no tiene solución real.</p>
<h1 id="no-ahora-si-realmente-qué-es-una-ecuación-cuadrática">No, ahora
si realmente… ¿Qué es una ecuación cuadrática?</h1>
<p>Desde un punto de vista gráfico, la función cuadrática \[f(x) = ax^2
+ bx + c\] representa una <strong>parábola</strong> en el plano
cartesiano.</p>
<p>El término cuadrático \(ax^2\) es el responsable de la forma
característica curva de la parábola.</p>
<p>- <strong>Dirección de la parábola:</strong> El signo del coeficiente
\(a\) determina hacia dónde abre la parábola:</p>
<p>- Si \(a &gt; 0\), la parábola tiene un <strong>mínimo</strong> y
abre hacia arriba.</p>
<p>- Si \(a &lt; 0\), la parábola tiene un <strong>máximo</strong> y
abre hacia abajo.</p>
<p>- <strong>Vértice de la parábola:</strong> El vértice es el punto
extremo (máximo o mínimo) de la parábola, y su coordenada \(x\) está
dada por: \[x = -\frac{b}{2a}\] Este valor es especialmente importante
en problemas de optimización, ya que representa el valor donde la
función alcanza su máximo o mínimo. Se puede pensar el vértice como el
punto más bajo (mínimo) de la parábola cuando abre hacia arriba, y el
punto más alto (máximo) cuando abre hacia abajo.</p>
<p>- <strong>Eje de simetría:</strong> La recta vertical definida por
\(x = -\dfrac{b}{2a}\) corresponde al eje de simetría de la parábola.
Esto significa que la parábola es simétrica con respecto a esta
recta.</p>
<h1 id="ecuación-o-función-cuadrática">¿Ecuación o función
cuadrática?</h1>
<p>Es común confundir los términos <strong>ecuación cuadrática</strong>
y <strong>función cuadrática</strong>, ya que ambos conceptos están
estrechamente relacionados, pero tienen significados ligeramente
distintos:</p>
<p>- <strong>Función cuadrática:</strong> Es una regla que asigna a cada
valor de \(x\) un valor único mediante la expresión: \[f(x) = ax^2 + bx
+ c, \quad \text{con } a \neq 0.\] Su propósito es describir cómo cambia
el valor de \(f(x)\) a medida que varía \(x\). Gráficamente, representa
una parábola.</p>
<p>- <strong>Ecuación cuadrática:</strong> Surge cuando igualamos la
función cuadrática a un valor específico, normalmente a cero: \[ax^2 +
bx + c = 0.\] En este caso, el objetivo es encontrar los valores de
\(x\) que hacen cierta esta igualdad, es decir, las raíces o soluciones
de la ecuación.</p>
<p>- <strong>Relación entre ambos:</strong> La ecuación cuadrática está
basada en la función cuadrática. Resolver la ecuación \(ax^2 + bx + c =
0\) equivale a encontrar los valores de \(x\) para los cuales \(f(x) =
0\), es decir, las intersecciones con el eje \(x\).</p>
<p>En resumen: Una función cuadrática describe una relación, mientras
que una ecuación cuadrática busca soluciones específicas.</p>
<h1 id="qué-es-el-discriminante">¿Qué es el discriminante?</h1>
<p>De lo anterior, sabemos que los coeficientes \(a\), \(b\) y \(c\) son
los componentes de la ecuación cuadrática \(ax^2 + bx + c = 0\).</p>
<p>Pero… ¿qué es el discriminante?</p>
<p>El discriminante (\(D\) o \(\Delta\)) es un número que se calcula a
partir de los coeficientes de la ecuación cuadrática usando la fórmula:
\[D = b^2 - 4ac\] Este número no es la solución de la ecuación, pero
determina la naturaleza y cantidad de las raíces reales.</p>
<h2 id="qué-información-nos-da-el-discriminante">¿Qué información nos da
el discriminante?</h2>
<p>El discriminante clasifica las raíces de la ecuación cuadrática en
tres casos:</p>
<p>- <strong>Caso 1: \(D &gt; 0\)</strong> (Discriminante positivo) Dos
raíces reales distintas. Ejemplo: Si \(D = 25\), las raíces pueden ser
\(x = -1\) y \(x = -6\) (como en la ecuación \(x^2 + 7x + 6 = 0\)).
Gráficamente: La parábola cruza el eje \(X\) en dos puntos.</p>
<p>- <strong>Caso 2: \(D = 0\)</strong> (Discriminante nulo) Una raíz
real doble (repetida). Ejemplo: Si \(D = 0\), la raíz es \(x = 3\), pero
se escribe como \((x - 3)^2 = 0\). Entonces hay una solución real (\(x =
3\)), pero es una raíz doble (aparece dos veces en la factorización).
Gráficamente: La parábola toca el eje \(X\) en su vértice.</p>
<p>- <strong>Caso 3: \(D &lt; 0\)</strong> (Discriminante negativo) Dos
raíces complejas conjugadas (no reales). Ejemplo: Si \(D = -16\), las
raíces son \(x = -\frac{3}{2} \pm 2i\). Gráficamente: La parábola no
cruza el eje \(X\); “flota” por encima o por debajo.</p>
<p>El discriminante lo utilizamos dentro de la fórmula resolvente de la
cuadrática.</p>
<h1 id="qué-es-la-fórmula-resolvente-de-la-cuadrática">¿Qué es la
fórmula resolvente de la cuadrática?</h1>
<p>Esto se conoce también como la fórmula para resolver la función
cuadrática. Tiene la siguiente forma:</p>
<p>\[x = \frac{-b \pm \sqrt{D}}{2a}\]</p>
<p>Su resultado nos da los ceros o **raíces** de la ecuación.</p>
<p>Ya mencioné ampliamente la parte del discriminante, que lo usamos
dentro de esta fórmula. Pero hay otro detalle a tener en cuenta: En la
resolvente encontramos un signo \(+\) y \(-\) **junto al
discriminante**, esto es lo que genera dos soluciones. Recordemos que
son dos soluciones si el discriminante es distinto de cero; si el
discriminante es cero, ambas soluciones coinciden.</p>
<h1 id="qué-es-una-raíz-de-la-función">¿Qué es una raíz de la
función?</h1>
<p>Las raíces son las “\(x\)” que **satisfacen** la ecuación. Se trata
de los valores que al sustituirlos en la ecuación producen un resultado
igual a cero. Es decir, las raíces son las “\(x\)” que cumplen:</p>
<p>\[f(x) = ax^2 + bx + c = 0\]</p>
<p>Las raíces también pueden aparecer mencionadas como los **ceros** de
la función, los puntos donde el gráfico de la función intersecta el
**eje \(X\)** en el plano cartesiano (en el caso de raíces reales).</p>
<h1 id="tres-ejemplos-de-ecuación-cuadrática">Tres ejemplos de ecuación
cuadrática</h1>
<h2 id="cuadrática-con-dos-raíces-reales-distintas">Cuadrática con dos
raíces reales distintas</h2>
<p><strong>Ejemplo 1:</strong> Resolver la ecuación \[x^2 - 5x + 6 =
0.\]</p>
<p>- Coeficientes: \(a = 1\), \(b = -5\), \(c = 6\)</p>
<p>- Discriminante: \[D = (-5)^2 - 4(1)(6) = 25 - 24 = 1 &gt; 0,\] lo
que indica **dos raíces reales distintas**.</p>
<p>- Raíces: \[x = \frac{5 \pm \sqrt{1}}{2} = \frac{5 \pm 1}{2},\]
entonces, \[x_1 = \frac{5 + 1}{2} = 3, \quad x_2 = \frac{5 - 1}{2} =
2.\]</p>
<p>- Factorización: \((x - 3)(x - 2) = 0\).</p>
<h2 id="cuadrática-con-una-raíz-real-doble">Cuadrática con una raíz real
doble</h2>
<p><strong>Ejemplo 2:</strong> Resolver la ecuación \[x^2 - 4x + 4 =
0.\]</p>
<p>- Coeficientes: \(a = 1\), \(b = -4\), \(c = 4\)</p>
<p>- Discriminante: \[D = (-4)^2 - 4(1)(4) = 16 - 16 = 0,\] lo que
indica **una raíz real doble (repetida)**.</p>
<p>- Raíz: \[x = \frac{4}{2} = 2.\]</p>
<p>- Factorización: \((x - 2)^2 = 0\).</p>
<h2 id="cuadrática-con-dos-raíces-complejas-conjugadas">Cuadrática con
dos raíces complejas conjugadas</h2>
<p><strong>Ejemplo 3:</strong> Resolver la ecuación \[x^2 + 2x + 5 =
0.\]</p>
<p>- Coeficientes: \(a = 1\), \(b = 2\), \(c = 5\)</p>
<p>- Discriminante: \[D = 2^2 - 4(1)(5) = 4 - 20 = -16 &lt; 0,\] lo que
indica **dos raíces complejas conjugadas (no reales)**.</p>
<p>- Raíces: \[x = \frac{-2 \pm \sqrt{-16}}{2} = \frac{-2 \pm 4i}{2} =
-1 \pm 2i.\]</p>
<p>- Factorización: \((x + 1 - 2i)(x + 1 + 2i) = 0\).</p>
<h1 id="a-b-c-de-vuelta-a-las-partes-de-la-función-cuadrática">a, b, c
de vuelta a las partes de la función cuadrática</h1>
<p>Ya sabemos que la función cuadrática tiene esta forma:</p>
<p>\[ax^2 + bx + c = 0\]</p>
<p>Y al principio del apunte decíamos, por ejemplo, que \(b\) es el
término lineal. ¿Qué significa eso?</p>
<p>Revisamos cada parte una vez más, detallando su función:</p>
<h2 id="a-término-cuadrático">1. \(a\) (término cuadrático)</h2>
<p><strong>Qué es:</strong> Coeficiente de \(x^2\) (la variable elevada
al cuadrado).</p>
<p><em>Ejemplo:</em> En \(3x^2 - 5x + 2 = 0\), \(a = 3\).</p>
<p><strong>Importancia:</strong></p>
<p>- Define la curvatura de la parábola: - Si \(a &gt; 0\) → Parábola
abre hacia arriba (\(\cup\)). - Si \(a &lt; 0\) → Parábola abre hacia
abajo (\(\cap\)).</p>
<p>- Controla el “ancho” de la parábola: - \(|a|\) grande → Parábola
estrecha (ej: \(5x^2\)). - \(|a|\) pequeño → Parábola ancha (ej:
\(0.2x^2\)).</p>
<p>- Esencial para que la ecuación sea cuadrática: - Si \(a = 0\), ¡no
es cuadrática! (sería lineal).</p>
<p><strong>En la fórmula resolvente:</strong> Aparece en el denominador:
\(\frac{-b \pm \sqrt{D}}{2a}\).</p>
<h2 id="b-término-lineal">2. \(b\) (término lineal)</h2>
<p><strong>Qué es:</strong> Coeficiente de \(x\) (la variable sin
elevar).</p>
<p><em>Ejemplo:</em> En \(3x^2 - 5x + 2 = 0\), \(b = -5\).</p>
<p><strong>Importancia:</strong></p>
<p>- Influencia en la posición horizontal del vértice: - Coordenada
\(x\) del vértice: \(x_v = -\frac{b}{2a}\).</p>
<p>- Determina la simetría: - El eje de simetría es la recta vertical
\(x = -\frac{b}{2a}\). - Si \(b = 0\): La ecuación es simétrica respecto
al eje \(y\) (ej: \(2x^2 - 8 = 0\)).</p>
<p><strong>En el discriminante:</strong> Parte crucial de \(D = b^2 -
4ac\).</p>
<h2 id="c-término-independiente-o-constante">3. \(c\) (término
independiente o constante)</h2>
<p><strong>Qué es:</strong> Término sin variable (constante
numérica).</p>
<p><em>Ejemplo:</em> En \(3x^2 - 5x + 2 = 0\), \(c = 2\).</p>
<p><strong>Importancia:</strong></p>
<p>- Indica el corte con el eje \(y\): Cuando \(x = 0\), \(y = c\) →
Punto \((0, c)\).</p>
<p>- Influye en las raíces: Cambia el valor del discriminante \(D = b^2
- 4ac\).</p>
<h1 id="ecuación-cuadrática-algunas-otras-formas">Ecuación cuadrática:
algunas otras formas</h1>
<p>Los problemas sobre cuadráticas no siempre se nos presentan
directamente en la forma:</p>
<p>\[ax^2 + bx + c = 0\]</p>
<p>Algunas veces tenemos que hacer unos pasos extra antes de encontrar
los ceros/raíces. Lo que sigue son algunos ejemplos de eso.</p>
<h1 id="funciones-cuadráticas-en-forma-vértice">1. Funciones cuadráticas
en forma vértice</h1>
<p>Ecuación: \[f(x) = 2(x - 3)^2 - 8 = 0\]</p>
<p><strong>Paso a paso:</strong></p>
<ol type="1">
<li>Aislar el término cuadrático: \[2(x - 3)^2 - 8 = 0 \implies 2(x -
3)^2 = 8\]</li>
<li>Despejar el binomio al cuadrado: \[(x - 3)^2 = \frac{8}{2} \implies
(x - 3)^2 = 4\]</li>
<li>Aplicar raíz cuadrada (considerando ambas soluciones): \[\sqrt{(x -
3)^2} = \sqrt{4} \implies |x - 3| = 2\] Esto genera dos ecuaciones: \[x
- 3 = 2 \quad \text{o} \quad x - 3 = -2\]</li>
<li>Resolver cada ecuación: \[x = 3 + 2 = 5; \quad x = 3 - 2 = 1\]</li>
<li>Verificar las raíces: \[\text{Para } x = 5: \quad 2(5 - 3)^2 - 8 = 2
\cdot 4 - 8 = 0\] \[\text{Para } x = 1: \quad 2(1 - 3)^2 - 8 = 2 \cdot 4
- 8 = 0\]</li>
</ol>
<p><strong>Conclusión:</strong> Las raíces son \(x = 1\) y \(x = 5\). La
ecuación original está en forma vértice: \(a(x - h)^2 + k = 0\)</p>
<h1 id="ecuaciones-racionales-con-términos-cuadráticos">2. Ecuaciones
racionales con términos cuadráticos</h1>
<p>Ecuación: \[\frac{x^2 - 4}{x - 1} = 3\]</p>
<p><strong>Paso a paso:</strong></p>
<ol type="1">
<li>Restricción de dominio: \[x - 1 \neq 0 \implies x \neq 1\]</li>
<li>Eliminar el denominador (multiplicar ambos lados por \(x - 1\)):
\[x^2 - 4 = 3(x - 1)\]</li>
<li>Llevar a la forma estándar: \[x^2 - 4 = 3x - 3 \implies x^2 - 3x - 1
= 0\]</li>
<li>Aplicar resolvente cuadrática (\(a = 1\), \(b = -3\), \(c = -1\)):
\[D = (-3)^2 - 4(1)(-1) = 9 + 4 = 13\] \[x = \frac{3 \pm
\sqrt{13}}{2}\]</li>
<li>Verificar restricciones: \[x_1 = \frac{3 + \sqrt{13}}{2} \approx
3.303; \quad x_2 = \frac{3 - \sqrt{13}}{2} \approx -0.303\] Ambos
valores son \(\neq 1\) → Válidos.</li>
</ol>
<p><strong>Conclusión:</strong> Las raíces son \(x = \frac{3 \pm
\sqrt{13}}{2}\). Siempre hay que recordar excluir valores que anulen el
denominador.</p>
<h1 id="sistemas-de-ecuaciones-con-componentes-cuadráticas">3. Sistemas
de ecuaciones con componentes cuadráticas</h1>
<p>Sistema: \[\begin{cases} y = x^2 - 5x + 6 \\ y = 2x - 4
\end{cases}\]</p>
<p><strong>Resolvemos:</strong></p>
<ol type="1">
<li><p>Igualar ambas ecuaciones (puntos de intersección): \[x^2 - 5x + 6
= 2x - 4\]</p></li>
<li><p>Llevar a la forma estándar: \[x^2 - 7x + 10 = 0\]</p></li>
<li><p>Identificamos los coeficientes: \[\begin{aligned} a &amp;= 1 \\ b
&amp;= -7 \\ c &amp;= 10 \end{aligned}\]</p>
<p>Sustituimos en la fórmula: \[x = \frac{-(-7) \pm \sqrt{(-7)^2 -
4(1)(10)}}{2(1)}\]</p>
<p>\[x = \frac{7 \pm \sqrt{49 - 40}}{2}\]</p>
<p>\[x = \frac{7 \pm \sqrt{9}}{2}\]</p>
<p>\[x = \frac{7 \pm 3}{2}\]</p>
<p>Entonces las soluciones son: \[x_1 = \frac{7 + 3}{2} = 5 \quad
\text{y} \quad x_2 = \frac{7 - 3}{2} = 2\]</p></li>
<li><p>Hallar \(y\) para cada \(x\) (usar la ecuación lineal):
\[\text{Si } x = 2: \quad y = 2(2) - 4 = 0 \quad \rightarrow \quad (2,
0)\] \[\text{Si } x = 5: \quad y = 2(5) - 4 = 6 \quad \rightarrow \quad
(5, 6)\]</p></li>
<li><p>Verificar en la cuadrática: \[\text{Para } (2, 0): \quad 2^2 -
5(2) + 6 = 4 - 10 + 6 = 0\] \[\text{Para } (5, 6): \quad 5^2 - 5(5) + 6
= 25 - 25 + 6 = 6\]</p></li>
</ol>
<p><strong>Conclusión:</strong> Las soluciones del sistema son los
puntos \((2, 0)\) y \((5, 6)\). Si lo pensamos de forma gráfica podemos
encontrar en esos puntos las intersecciones entre la parábola y la
recta. Al igualar funciones, se reduce a una ecuación cuadrática:
\(f_{\text{cuad}}(x) = f_{\text{lin}}(x)\)</p>
<h1 id="conclusión">Conclusión</h1>
<p>Con esto le doy un cierre al apunte donde intento simplificar al
máximo posible la explicación de las ecuaciones cuadráticas.</p>
<p>Como todo apunte, el mismo puede ser mejorado. ¿Encontraste algún
error? ¿Hay algo que pudo haberse explicado de una forma más sencilla?
Envíame un correo electrónico contándome tu opinión:
<code>gustavo @apunte impensado.com</code></p>
<p>La seguimos en el próximo apunte.</p>
<p><strong>¿Comentarios o preguntas?</strong> Escríbeme tu opinión a: <a href="mailto:gustavol@apunteimpensado.com">gustavo@apunteimpensado.com</a></p>]]></description>
        <link>https://apunteimpensado.com/ecuaciones-cuadraticas-busqueda-explicacion-simple/</link>
        <guid isPermaLink="true">https://apunteimpensado.com/ecuaciones-cuadraticas-busqueda-explicacion-simple/</guid>
        <pubDate>Thu, 26 Jun 2025 00:00:00 </pubDate>
    </item>
    <item>
        <title><![CDATA[Programar con LibreOffice, Macros, ideas de automatización y consejos prácticos]]></title>
        <description><![CDATA[<!--
INDEX_START
This section will be parsed for the left sidebar index/chapter list.
Use standard Markdown link syntax - links should point to actual HTML files.
-->

<h2
id="cómo-establecer-objetivos-de-palabras-usando-macros-y-libreoffice-basic">Cómo
establecer objetivos de palabras usando Macros y LibreOffice Basic</h2>
<p>Seguramente en algún momento tuviste que escribir una determinada
cantidad de palabras. Tal vez por un trabajo, por cuestiones de estudio
o porque te encontrás escribiendo un proyecto personal.</p>
<p>Por completar este ejemplo, digamos que necesitamos escribir 20.000
palabras.</p>
<p>Una cosa que podemos hacer es revisar de tanto en tanto el contador
debajo de Libreoffice Writter para ver si estamos cerca del objetivo. O
también podemos crear un macro que nos permita averiguar esa información
simplemente apretando un atajo en el teclado.</p>
<p>La idea es tener un código que nos informe del porcentaje total de
palabras que completamos al momento de invocar el macro.</p>
<h3 id="el-código">El código</h3>
<p>El siguiente código es muy sencillo, y hace exactamente lo que estoy
buscando:</p>
<pre><code>REM  *****  BASIC  *****
REM Macro para dar el porcentaje completado en palabras de un OBJETIVO_TOTAL.

Sub contador_objetivo()
    Const OBJETIVO_TOTAL As Long = 20000
    Dim doc As Object
    Dim wordCount As Long
    Dim porcentaje As Long

    doc = ThisComponent
    wordCount = doc.WordCount
    porcentaje = (wordCount / OBJETIVO_TOTAL) * 100

    MsgBox (&quot;Ya hiciste el &quot; &amp; porcentaje &amp; &quot;% (&quot; &amp; wordCount &amp; &quot; palabras) de un total de &quot; &amp; OBJETIVO_TOTAL &amp; &quot; palabras.&quot;)

End Sub</code></pre>
<h3 id="la-explicación">La explicación:</h3>
<p>La mayor parte del código se encarga de establecer las variables.</p>
<p>De todo, creo que lo más importante es esto:</p>
<pre><code>Const OBJETIVO_TOTAL As Long = 20000</code></pre>
<p>Donde se puede reemplazar “20.000” por la cantidad de palabras que se
necesitan completar.</p>
<p>Y también esto otro:</p>
<pre><code>MsgBox (&quot;Ya hiciste el &quot; &amp; porcentaje &amp; &quot;% (&quot; &amp; wordCount &amp; &quot; palabras) de un total de &quot; &amp; OBJETIVO_TOTAL &amp; &quot; palabras.&quot;)</code></pre>
<p>Ya que es lo que muestra el mensaje con el porciento terminado cuando
invocamos el programa.</p>
<h3 id="cómo-utilizar-el-macro">¿Cómo utilizar el macro?</h3>
<p>Para ponerlo en funcionamiento es necesario:</p>
<ol type="1">
<li><p>Añadir el macro. Esto puede conseguirse en “Herramientas &gt;
Macros &gt; Organizar Macros &gt; Basic”</p></li>
<li><p>Asignarle un nuevo atajo al macro. Para esto voy a “Herramientas
&gt; Personalizar” y luego agregar la combinación de teclas en la
pestaña “teclado”.</p></li>
</ol>
<h2
id="macro-para-contar-palabras-bajo-cada-cabecera-en-libreoffice-writer">Macro
para contar palabras bajo cada cabecera en LibreOffice Writer</h2>
<p>Digamos que tenemos que escribir un proyecto con un total de 20.000
palabras. Escribir todas esas palabras es difícil, en especial cuando lo
comparamos con escribir solamente 1.000 palabras.</p>
<p>Entonces decidimos dividir el texto en 20 secciones, para que se
vuelva más fácil de completar. Creamos diferentes títulos, cabeceras o
“headings” (H1, H2…) y podemos navegar entre esos headings. Pero en un
principio no podemos saber cuantas palabras agregamos luego en cada
uno.</p>
<p>Este macro que comparto a continuación, escrito en LibreOffice Basic,
nos va a ayudar exactamente a eso.</p>
<p>La idea es tener un código que revise todo el texto y encuentre las
cabeceras. Luego tiene que informarnos del nombre de la cabecera y su
cantidad de palabras. Al final tiene que decirnos la cantidad total de
palabras, aunque eso ya lo conocemos del contador dentro del
documento.</p>
<h3 id="el-código-1"><strong>El código:</strong></h3>
<pre><code>Sub ContarPalabrasHeadings()
    Dim doc As Object
    Dim cursor As Object
    Dim para As Object
    Dim wordCount As Long
    Dim totalWordCount As Long
    Dim headingFound As Boolean
    Dim result As String

    doc = ThisComponent
    text = doc.getText()
    cursor = text.createEnumeration()

    headingFound = False
    result = &quot;&quot;
    wordCount = 0
    totalWordCount = 0

    While cursor.hasMoreElements()
        para = cursor.nextElement()

        If Left(para.ParaStyleName, 7) = &quot;Heading&quot; Then
            If headingFound Then
                &#39; Crea un string para reflejar el número de palabras entre cabeceras
                result = result &amp; headingText &amp; &quot;: &quot; &amp; wordCount &amp; &quot; palabras&quot; &amp; Chr(10)
            End If

            headingText = para.getString()
            headingFound = True
            wordCount = 0
        Else
            If headingFound Then
                &#39; Contar el número de palabras entre cabeceras
                trimmedText = Trim(para.getString())
                wordsArray = Split(trimmedText, &quot; &quot;)
                wordCount = wordCount + UBound(wordsArray) + 1
                totalWordCount = totalWordCount + UBound(wordsArray)
            End If
        End If
    Wend

    &#39; Actualiza la variable result con el número de palabras
    If headingFound Then
        result = result &amp; headingText &amp; &quot;: &quot; &amp; wordCount &amp; &quot; palabras&quot; &amp; Chr(10)
    End If

    If result = &quot;&quot; Then
        MsgBox &quot;No se encontraron cabeceras en el documento&quot;
    Else
        MsgBox result &amp; Chr(10) &amp; &quot;Total de palabras: &quot; &amp; totalWordCount
    End If

End Sub</code></pre>
<h3 id="posibles-mejoras">Posibles mejoras:</h3>
<p>Se me ocurren en este momento dos mejoras que se le pueden agregar al
programa:</p>
<p>1- Una forma de contar las palabras debajo de cada heading de forma
más precisa. En la forma que se encuentra implementado, encontré que a
veces el conteo por secciones puede tener algunas palabras de más o de
menos con el conteo total. Nada exagerado de todas maneras, el programa
sirve para conseguir una buena idea general de cuanto llevamos
avanzado.</p>
<p>2- Se puede modificar el programa para que también nos informe que
tipo de cabecera es cada una, H1, H2…</p>
<p>Pero el programa cumple con lo que promete sin necesidad de esas
mejoras.</p>
<h2 id="consejos-prácticos-para-usar-en-libreoffice">Consejos prácticos
para usar en LibreOffice</h2>
<h3 id="cómo-puedo-instalar-nuevas-tipografías-en-libreoffice">¿Cómo
puedo instalar nuevas tipografías en LibreOffice?</h3>
<p>No es necesario instalar tipografías para LibreOffice, lo que hacemos
es instalar tipografías a nivel del sistema.</p>
<p>Al instalarla en el sistema operativo, otros programas también pueden
aprovecharlas. Una tipografía instalada en el sistema puede usarla
LibreOffice, GIMP y otros programas.</p>
<p>En cada sistema operativo la instalación de nuevas fuentes puede
variar ligeramente. Lo que es seguro es que por un lado vos descargás,
creas o recibí la tipografía para agregar.</p>
<p>Luego buscá en el directorio de raíz la carpeta
<strong>/usr/share/fonts</strong> y dejá el archivo ahi, para que no se
pierda.</p>
<p>Acto seguido, dale doble click al archivo de la tipografía (puede ser
de extensión .otf o .ttf por ejemplo) y luego dale click a instalar.</p>
<p>Con eso tendrías que tener la tipografía instalada y ubicada en el
directorio correcto.</p>
<h3
id="cómo-puedo-usar-la-tipografía-times-new-roman-en-libreoffice-en-linux">¿C<strong>ó</strong>mo
puedo usar la tipografía Times New Roman en Libre<strong>O</strong>ffice
en Linux?</h3>
<p>Si tuviera que apostar, diría que esta es una de las preguntas más
comunes cuando instalamos LibreOffice por primera vez.</p>
<p><strong>Respuesta corta:</strong> No vas a encontrar la tipografía
Times New Roman en LibreOffice, porque esa tipografía tiene un tipo de
licencia que no permite su uso libre.</p>
<p>Lo mejor va a ser que uses una tipografía equivalente, por ejemplo
Liberation Serif que si viene lista para usar. Puede servirte como un
buen reemplazo y vas a evitarte vueltas.</p>
<p><strong>Respuesta larga:</strong> Es posible usar la tipografía Times
New Roman en GNU/Linux. Así podes hacerlo en algunas distribuciones, por
ejemplo Ubuntu y Linux Mint. Los pasos son los siguientes:</p>
<p>Por medio de la linea de comandos: Descargá el siguiente conjunto de
paquetes,</p>
<pre><code>sudo apt-get install ttf-mscorefonts-installer</code></pre>
<p>Y ahora dale aceptar a la licencia de acuerdo. Bueno, lee primero la
licencia y dale aceptar.</p>
<p>¿Cómo darle aceptar? Si, yo tampoco supe en un primer momento.
Presiona la tecla Tab y va a posicionarte sobre Aceptar.</p>
<p>Lo mejor ahora es reiniciar el equipo, aunque idealmente las
tipografías fueron instaladas y ya están disponibles.</p>
<p>Cuando abras un nuevo programa y vayas a escribir, ya van a estar
instaladas.</p>
<p>Por supuesto podes revertir la instalación con el comando:</p>
<pre><code>sudo apt-get purge ttf-mscorefonts-installer</code></pre>
<p><strong>Instalar por medio de un instalador gráfico:</strong> La otra
manera de instalar Times New Roman en GNU/Linux es utilizando el
Software Manager. O Ubuntu Software, el nombre puede variar.</p>
<p>El objetivo es: buscar el paquete
<strong>ttf-mscorefonts-intaller</strong> e instalarlo.</p>
<p>Listo, eso también tiene que conseguirte Times New Roman y otras
tipografías que estas buscando. Por ejemplo Arial Black, Arial, Courier
New y otras.</p>
<p>Pero en resumen… darle una oportunidad a las tipografías que ya trae
el sistema GNU/Linux (u otras de licencias similares) no es mala idea. A
menos que sea por algún tipo de obligación laboral/universitaria, en ese
caso, ya sabes como conseguirlas.</p>
<h3 id="cómo-quitar-las-cabeceras-en-libreoffice">¿<strong>Có</strong>mo
quitar las cabeceras en LibreOffice?</h3>
<p>El modo de remover las cabeceras personalizadas es muy sencillo, solo
hay que encontrar el menu correcto. Dirigite hacia:</p>
<pre><code>Formato &gt; Estilo de página &gt; Cabecera</code></pre>
<p>Y desmarcá la opción <strong>“Activar Cabece**</strong>ra”**.</p>
<p>Como es de esperar, en el mismo menú también vas a poder modificar
sus parámetros.</p>
<h3 id="cómo-puedo-activar-los-backups-automáticos-en-libreoffice">¿Cómo
puedo activar los backups automáticos en LibreOffice?</h3>
<p>Para activar la opción de realizar respaldos automáticos del
documento en que te encontrás trabajando, podes dirigirte al menú:</p>
<pre><code>Herramientas &gt; Opciones… &gt; Cargar/guardar &gt; General</code></pre>
<p>Allí podes activar y modificar opciones como la de <strong>guardar
datos de recuperación</strong> automática en intervalos de tiempo, y
también la opción de <strong>Crear Copia de seguridad</strong>.</p>
<h3 id="cómo-eliminar-una-página-en-blanco-en-writer">¿Cómo eliminar una
página en blanco en Writer?</h3>
<p>Digamos que terminaste el texto, pero sobra una página en blanco al
final.</p>
<p>Poné el cursor al principio de esa hoja en blanco, y empezá a borrar.
Si, borrar, con la tecla <strong>backspace</strong> del mismo modo que
lo harías con el texto.</p>
<p>Eso tendría que eliminar la última página vacía en el documento.</p>
<p>Dicho de otra forma, lo que estamos haciendo es “eliminar” todo el
espacio libre bajo el texto que termina el documento.</p>
<h3
id="cómo-puedo-recuperar-un-archivo-que-se-borró-accidentalmente">¿Cómo
puedo recuperar un archivo que se borró accidentalmente?</h3>
<p>Entre las preguntas de LibreOffice, esta realmente no tiene solución
sencilla.</p>
<p>En un caso difícil, donde no hay ningún tipo de respaldo del archivo,
la única solución posible sea tal vez usar algún tipo de programa al
estilo Testdisk.</p>
<p>Ahora, en el caso de que tengas activadas copias de seguridad o
guardados automáticos, busca en los directorios donde puedan haberse
guardado.</p>
<p>Podes conocer esos directorios si revisás dentro de LibreOffice en el
menú:</p>
<pre><code>Herramientas &gt; Opciones… &gt; LibreOffice &gt; Rutas &gt; Copias de seguridad</code></pre>
<p>O también en:</p>
<pre><code>Herramientas &gt; Opciones… &gt; LibreOffice &gt; Rutas &gt; Archivos temporales</code></pre>
<p>En esos dos lugares vas a averiguar sobre posibles espacios donde
pudo guardarse una copia extra de tu documento perdido.</p>
<p>Si hay archivos de respaldo guardados, seguramente tengan la
extensión <strong>.bak,</strong> por backup. Abrilo y guardalo con otro
nombre.</p>
<p>Vale aclarar que tus chances de recuperar el documento aumentan
cuanto más cerca a la fecha en que fue borrado comiences a buscarlo.</p>
<h3
id="cómo-puedo-insertar-una-página-en-el-medio-de-un-documento-de-writer">¿Cómo
puedo insertar una página en el medio de un documento de Writer?</h3>
<p>Para agregar una nueva página en el documento, posicioná el cursor al
final o al principio de la página actual según donde sea que necesitas
la nueva pagina.</p>
<p>Luego presiona el atajo <strong>Ctrl+Enter</strong> y con eso vas a
agregar la nueva hoja.</p>
<p>También podes hacerlo desde el menú:</p>
<pre><code>Insertar &gt; Salto de página</code></pre>
<p>O también desde:</p>
<pre><code>Insertar &gt; Más saltos &gt; Salto manual</code></pre>
<p><strong>¿Comentarios o preguntas?</strong> Escríbeme tu opinión a: <a href="mailto:gustavol@apunteimpensado.com">gustavo@apunteimpensado.com</a></p>]]></description>
        <link>https://apunteimpensado.com/programar-libreoffice-macros-automatizacion-consejos/</link>
        <guid isPermaLink="true">https://apunteimpensado.com/programar-libreoffice-macros-automatizacion-consejos/</guid>
        <pubDate>Mon, 23 Jun 2025 00:00:00 </pubDate>
    </item>
    <item>
        <title><![CDATA[Cómo extraer el texto de una imagen utilizando Python, Tesseract y OpenCV]]></title>
        <description><![CDATA[<!--
INDEX_START
This section will be parsed for the left sidebar index/chapter list.
Use standard Markdown link syntax - links should point to actual HTML files.
-->

<p>En este apunte práctico voy a revisar cómo extraer el texto contenido
en una imagen “.jpg” para utilizarlo como texto dentro de otros
documentos.</p>
<p>Para esto vamos a utilizar las siguientes herramientas: Python,
OpenCV y Tesseract.</p>
<p>Estamos recorriendo una época de grandes avances en LLM e
inteligencia artificial, y las tareas de visión por computadora son cada
vez más sorprendentes. Incluso la tarea que vamos a realizar a
continuación me resulta sorprendente, aunque al momento de escribir esto
pueda resultar algo común para otras personas.</p>
<p>Pero sin más introducción, vamos a empezar.</p>
<h2 id="qué-nos-interesa-hacer">¿Qué nos interesa hacer?</h2>
<p>Empecé a escribir esta entrada porque necesitaba extraer los datos de
una tabla que se encontraba guardada en formato .jpg y no quería hacer
el esfuerzo de copiarla por mi propia cuenta.</p>
<p>El resultado fue bueno, aunque tuve que hacer algunos ajustes
manualmente para obtener toda la información. Recuerden que no soy
experto en el tema, solamente un simple principiante y tienen que
existir muchas formas de mejorar mi aproximación al problema.</p>
<p>Para los efectos de esta entrada digamos que queremos extraer el
texto de la siguiente imagen:</p>
<p><img
src="https://apunteimpensado.com/wp/wp-content/uploads//2025/04/texto-1024x642.png" /></p>
<p>Si queremos hacer esto vamos a necesitar tener algunas cosas en
nuestra computadora.</p>
<h2 id="lista-de-cosas-que-necesitamos">Lista de cosas que
necesitamos</h2>
<p>Tengan en cuenta que estoy utilizando un sistema operativo Linux. Los
detalles para las siguientes instalaciones pueden variar según el
sistema que elijas.</p>
<h3 id="instalar-tesseract-a-nivel-global">Instalar Tesseract a nivel
global</h3>
<p><a href="https://github.com/tesseract-ocr/tesseract">Tesseract</a> es
un motor de Reconocimiento Óptico de Caracteres (ROC). En resume vamos a
necesitarlo para extraer el texto de la imagen.</p>
<p>Primero necesito instalar Tesseract al nivel de sistema:</p>
<pre><code>sudo apt install tesseract-ocr</code></pre>
<p>Ahora si escribo el comando:</p>
<pre><code>tesseract --list-langs</code></pre>
<p>Voy a conseguir que librerías de lenguaje tengo agregadas. Al
principio intenté extraer el texto sin la librería para Español, y tuve
buenos resultados. Pero por ejemplo aparecían problemas, la letra “ó”
con tilde se mostraba en el documento como “é”.</p>
<p>Para resolverlo necesito agregar la librería en Español, y lo hago
con este otro comando:</p>
<pre><code>sudo apt install tesseract-ocr-spa</code></pre>
<h3 id="crear-un-entorno-de-python-e-instalar-pytesseract">Crear un
entorno de Python e instalar pytesseract</h3>
<p>Voy a <a
href="https://apunteimpensado.com/como-crear-un-entorno-virtual-con-python-en-linux/">crear
un entorno virtual en Python</a>. Lo hago en el directorio en el que voy
a ejecutar el código:</p>
<p>Ahora instalo Pytesseract dentro del entorno virtual:</p>
<pre><code>pip install pytesseract</code></pre>
<p><a href="https://github.com/madmaze/pytesseract">Pytesseract</a> es
un librería que le permite interactuar con Python al motor de
reconocimiento que instalamos antes.</p>
<h3 id="instalar-opencv">Instalar Opencv</h3>
<p>Necesito ahora, otra vez dentro del entorno virtual agregar otra
librería llamada <a href="https://opencv.org/">Opencv</a>:</p>
<pre><code>pip install opencv-python</code></pre>
<p>Con eso consigo agregar OpenCV (Biblioteca de Visión Computacional de
Código Abierto) a mi entorno. Entre las cosas que nos va a permitir
hacer esta librería se encuentra la posibilidad de procesar la imagen
para mejorar las posibilidades de un reconocimiento de texto
exitoso.</p>
<h2 id="el-código">El código</h2>
<p>Comparto el código completo para poder extraer el texto de una imagen
“.jpg” para que puedas utilizarlo y modificarlo:</p>
<pre class="language-python"><code># Programa para extraer el texto de una imagen y pasar a un archivo.
# OpenCV para pre-procesar la imangen y Tesseract OCR para extraer el texto

import cv2
import pytesseract
import os
import sys

def preprocess_image(camino_imagen):

    image = cv2.imread(camino_imagen)
    if image is None:
        raise ValueError(&quot;Revisar el camino al directorio, no se pudo encontrar la imagen.&quot;)

    gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # Convierte la imagen a escala de grises
    blurred = cv2.GaussianBlur(gray_image, (3, 3), 0) # Aplica un desenfoque Gaussiano para reducir el ruido
    threshold_image = cv2.adaptiveThreshold(
        blurred,
        255,
        cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
        cv2.THRESH_BINARY,
        11,
        2
    )

    return threshold_image # adaptive thresholding aplicado en el paso anterior para mejorar la lectura de la imagen

def extraer_texto(image, config=None):
    return pytesseract.image_to_string(image, lang=&#39;spa&#39;, config=config)

def main():
    DEFAULT_OUTPUT_CONFIG = &quot;--psm 6 -c page_separator=&#39;&#39;&quot;  #  --psm 6 asume un texto uniforme

    if len(sys.argv) &lt; 2:
        print(&quot;Modo de uso: python texto_imagen.py [camino_imagen]&quot;) #si se usan menos de dos argumentos, explica cómo llamar el script
        sys.exit(1)

    camino_entrada = sys.argv[1]
    if not os.path.isfile(camino_entrada):
        print(&quot;revisr el nombre de archivo o el camino al directorio&quot;) # mensaje de error si falta el nombre de la imagen
        sys.exit(1)

     # Check if the file has a .jpg extension (case-insensitive)
    filename = os.path.basename(camino_entrada)
    if os.path.splitext(filename)[1].lower() not in (&#39;.jpg&#39;, &#39;.png&#39;):
        print(&quot;Error, solamente se pueden utilziar archivos .jpg o .png&quot;)
        sys.exit(1)

    try:
        preprocessed = preprocess_image(camino_entrada)
        text = extraer_texto(preprocessed, DEFAULT_OUTPUT_CONFIG)

        script_dir = os.path.dirname(os.path.abspath(__file__))
        archivo_salida = os.path.join(script_dir, &quot;texto_procesado.txt&quot;)

        with open(archivo_salida, &#39;w&#39;, encoding=&#39;utf-16&#39;) as f:
            f.write(text)

        print(f&quot;El texto fue extraido y guardado como {archivo_salida}&quot;)

    except ValueError as ve: # Manejo de errores, por ejemplo si la imagen provista no es del tipo de archivo adecuado.
        print(f&quot;Value error: {ve}&quot;)
        sys.exit(1)
    except pytesseract.TesseractError as te:
        print(f&quot;Tesseract error: {te}&quot;)
        sys.exit(1)
    except Exception as e:
        print(f&quot;Error inesperado: {e}&quot;)
        sys.exit(1)

if __name__ == &quot;__main__&quot;:
    main()</code></pre>
<p>Algo importante a tener en cuenta es que el código tiene una clausula
que se asegura que el archivo tenga la extensión “.jpg” o “.png” antes
de procesarlo. Esto no es completamente necesario, porque las librerías
que agregamos pueden usar otro tipo de archivos. Pero lo puse para
asegurarme de no confundirme al utilizarlo en mi caso.</p>
<p>Si te sirve podés extraer el texto de la misma imagen que compartí
más arriba para poder probar el código más rápido.</p>
<h3 id="cómo-utilizar-el-código">¿Cómo utilizar el código?</h3>
<p>El código se invoca con este formato:</p>
<pre><code>python texto_imagen.py [camino_imagen]</code></pre>
<p>Tengan en cuenta que “texto_imagen.py” es el nombre con el que guardé
el código en mi caso, podés modificarlo por el nombre que más quieras
usar.</p>
<h2 id="conclusión">Conclusión</h2>
<p>Con esto llega al final de mi apunte sobre cómo extraer el texto de
una imagen utilizando Python, Tesseract y OpenCV.</p>
<p>En mi propio caso es como una primera aproximación al tema, puedo
decir que aprendí mucho haciendo este material.</p>
<p>¿Te interesa el tema? ¿Encontraste algún error en mi explicación? Me
interesa leer tu opinión, por favor envíame un correo electrónico con tu
mensaje.</p>
<p>La seguimos en el próximo apunte</p>
<p><strong>¿Comentarios o preguntas?</strong> Escríbeme tu opinión a: <a href="mailto:gustavol@apunteimpensado.com">gustavo@apunteimpensado.com</a></p>]]></description>
        <link>https://apunteimpensado.com/como-extraer-texto-imagen-utilizando-python-tesseract-opencv/</link>
        <guid isPermaLink="true">https://apunteimpensado.com/como-extraer-texto-imagen-utilizando-python-tesseract-opencv/</guid>
        <pubDate>Tue, 01 Apr 2025 00:00:00 </pubDate>
    </item>
    <item>
        <title><![CDATA[Cómo alternar fácilmente entre el editor y la consola de comandos en VSCode]]></title>
        <description><![CDATA[<!--
INDEX_START
This section will be parsed for the left sidebar index/chapter list.
Use standard Markdown link syntax - links should point to actual HTML files.
-->

<p>En este apunte rápido voy a revisar cómo alternar de forma sencilla
entre la parte del editor y la consola de comandos en VSCode.</p>
<p>Por supuesto estos mismos atajos funcionan también para VSCodium.</p>
<p>¿Por qué escribo esto? Al programar en Bash, noté que necesitaba
moverme con el mouse repetidamente hacia la consola de comandos para
ejecutar el código. Esta acción era casi imperceptible, pero con el
tiempo se volvió molesta: me hacia utilizar el ratón una y otra vez con
este único objetivo.</p>
<p>Siendo demasiado tranquilo como para remediarlo nunca busqué cuál era
el atajo de teclado correcto. Pero ahora que si busqué la solución, la
escribo aquí para no olvidarla.</p>
<h2 id="cómo-mostrar-y-ocultar-la-consola-de-comandos">Cómo mostrar y
ocultar la consola de comandos</h2>
<p><a href="https://code.visualstudio.com/docs/terminal/basics">Esta es
la documentación de VSCode sobre los atajos de teclado.</a></p>
<p>Esa documentación dice que el atajo de teclado para esto es:</p>
<pre><code>Ctrl+`</code></pre>
<p>Pero personalmente no tuve suerte con ese comando. Creo que eso es
porque estoy utilizando el teclado configurado en español, y por algún
motivo el “backtick” no aparece sin dar varias vueltas.</p>
<p>Aunque por otra parte realmente no encontré configurada la opción
desde el vamos. Puede ser que dependa de qué versión estamos usando, en
versiones antiguos el atajo puede no venir pre configurado.</p>
<p>¿Cómo solucionarlo?</p>
<p>Primero necesitamos abrir el panel de atajos de teclado. Lo podemos
encontrar dentro de las opciones de configuración, o presionando
alternativamente:</p>
<pre><code>CTRL + k   Ctrl + s</code></pre>
<p>Luego tenemos que buscar la siguiente opción:</p>
<pre><code>view: Toggle Terminal</code></pre>
<p>Utilizo VSCode en inglés, pero seguro en castellano se puede
encontrar como “alternar terminal”. Esto nos va a permitir movernos sin
necesidad de crear una terminal nueva.</p>
<p>Y le asignamos a esa opción un nuevo atajo de teclado, en mi caso
utilicé:</p>
<pre><code>Shift + p</code></pre>
<p>Y listo, ahora presionando ese atajo puedo ocultar y mostrar la
terminal, lo que me permite mover el cursor entre ambos paneles sin
necesidad de utilizar el mouse.</p>
<p>Otra ventaja de crear este atajo es la siguiente. Digamos que me
encuentro en la consola para debug (debug Console). Si presiono por
primera vez la combinación en el teclado, me mueve hasta la consola de
terminal. Y si lo presiono de vuelta oculto la consola. Algo de mucha
utilidad.</p>
<h2 id="cómo-pasar-el-foco-de-la-terminal-de-comandos-al-editor">Cómo
pasar el foco de la terminal de comandos al editor</h2>
<p>Solo para agregar algo más a esta que admito es una entrada algo
corta, si me encuentro con el cursor en la terminal puedo presionar:</p>
<pre><code>Ctrl + 1</code></pre>
<p>Haciendo esto voy a poder pasar el curso al editor activo sin ocultar
la terminal. si tengo más de un editor activo, hago “Ctrl + 2” para ir a
ese editor y así por cada editor activo.</p>
<h2 id="cómo-mostrar-y-ocultar-cualquier-panel-en-vscode">Cómo mostrar y
ocultar cualquier panel en VSCode</h2>
<p>Y solo para volver todos los consejos anteriores más redundantes
todavía, aprendí que hay un atajo llamado: “Toggle Panel Visibility”</p>
<p>Esta opción permite que cualquier panel, incluso la consola de
comandos se muestre o se oculte inmediatamente. El atajo es:</p>
<pre><code>Ctrl + j</code></pre>
<p>Todo lo anterior no es completamente inútil porque este atajo es más
general, puedo usarlo para cerrar la consola de debug por ejemplo.</p>
<h1 id="conclusión">Conclusión:</h1>
<p>Con esto le doy cierre a este apunte sobre cómo alternar rápido entre
la consola de comandos y el editor en VSCode.</p>
<p>¿Encontraste algún error en el material? ¿Te interesa el tema?
Escribí un correo electrónico a mi cuenta, me interesa conocer tu
opinion.</p>
<p><strong>¿Comentarios o preguntas?</strong> Escríbeme tu opinión a: <a href="mailto:gustavol@apunteimpensado.com">gustavo@apunteimpensado.com</a></p>]]></description>
        <link>https://apunteimpensado.com/como-alternar-entre-editor-consola-comandos-vscode/</link>
        <guid isPermaLink="true">https://apunteimpensado.com/como-alternar-entre-editor-consola-comandos-vscode/</guid>
        <pubDate>Tue, 04 Mar 2025 00:00:00 </pubDate>
    </item>
    <item>
        <title><![CDATA[Cómo usar la terminal de Linux y Git desde Neovim sin plugins extra]]></title>
        <description><![CDATA[<!--
INDEX_START
This section will be parsed for the left sidebar index/chapter list.
Use standard Markdown link syntax - links should point to actual HTML files.
-->

<p>En este apunte rápido voy a revisar algunas opciones que tenemos para
utilizar Git en Neovim sin necesidad de complementos extra. Y para eso
vamos a necesitar acceder a la terminal.</p>
<p>Es importante mencionar que nos soy un experto en el asunto. Si lo
que te interesan son las funcionalidades más complejas de Git, es
posible que necesites la ayuda de un plugin extra.</p>
<p>Por otra parte, para seguir en esta serie de avisos, nada de esto va
en contra de la utilización de complementos. Así que sin más…</p>
<h2 id="opción-1-entrar-a-modo-terminal-y-ejecutar-git-desde-ahí">Opción
1: Entrar a modo terminal y ejecutar Git desde ahí</h2>
<p>Neovim cuenta con un <a
href="https://neovim.io/doc/user/terminal.html">“Modo Terminal” o
Terminal Mode.</a></p>
<p>Este emulador de terminal me va a permitir utilizar los comandos
directamente desde Neovim. Se puede entrar en este modo escribiendo en
modo comando:</p>
<pre><code>:terminal</code></pre>
<p>En este modo tengo que presionar “i” para poder agregar texto.</p>
<p>Para salir de modo terminal y volver al modo normal utilizo la
combinación de teclado:</p>
<pre><code>Ctrl + \  Ctrl + n</code></pre>
<p>La barra invertida \ la encuentro en el teclado, en la parte
izquierda al lado de la tecla “1”.</p>
<p>Digamos que entré en modo terminal desde un documento en el que
estaba trabajando. Para volver al buffer de ese documento presiono:</p>
<pre><code>Ctrl + o</code></pre>
<p>Desde el modo terminal puedo utilizar cualquier comando, entre ellos
los comandos de Git.</p>
<h2 id="opción-2-suspender-neovim-y-volver-a-la-terminal">Opción 2:
suspender Neovim y volver a la terminal</h2>
<p>Digamos que abrí Neovim desde la terminal de Linux. Si ahora
presiono:</p>
<pre><code>Ctrl + z</code></pre>
<p>Neovim va a suspenderse para devolverme a la terminal. Pero Neovim
sigue funcionando en segundo plano, por lo que puedo volver a retomarlo
luego de ejecutar algunos comandos.</p>
<p>Este es el punto en el que puedo utilizar Git.</p>
<p>Luego para volver a Neovim, escribo en la terminal:</p>
<pre><code>fg</code></pre>
<p>Este comando “fg” quiere decir “foreground” lo que significa “volver
al frente” en este contexto.</p>
<p>Esta forma de volver a la terminal puede causar problemas en algunas
configuraciones de Neovim, pero yo no tengo inconvenientes al
hacerlo.</p>
<h2
id="opción-3-ejecutar-comandos-de-linux-directamente-desde-modo-normal-en-neovim">Opción
3: ejecutar comandos de Linux directamente desde modo normal en
Neovim</h2>
<p>En Neovim puede ejecutar comandos de la shell directamente en modo
“normal”linea de comando” si agrego el prefijo “:!”</p>
<p>Por ejemplo si escribo:</p>
<pre><code>:git status</code></pre>
<p>No va a ocurrir nada porque ese es un comando de la shell, pero si
escribo:</p>
<pre><code>:!git status</code></pre>
<p>Obtengo el resultado del comando “git status”. Puedo volver al modo
normal presionando Enter.</p>
<p>De esta forma tengo otra opción para utilizar Git directamente desde
Neovim, y es una forma que se puede integrar sin muchas pausas
extra.</p>
<h2 id="opción-4-crear-nuevos-atajos">Opción 4: crear nuevos atajos</h2>
<p>Una de las grande ventajas de Neovim es la posibilidad de modificarlo
a mi gusto.</p>
<p>Puedo vincular alguna de las opciones anteriores a un nuevo atajo de
teclado, para no tener que escribir el comando completo cada vez.</p>
<p>Por ejemplo, en mi archivo de configuración “.lua” agrego la
siguiente linea de código:</p>
<pre><code>vim.keymap.set(&#39;n&#39;, &#39;&lt;F3&gt;&#39;, &#39;:!git status&lt;CR&gt;&#39;, { noremap = true, silent = true })</code></pre>
<p>Esto quiere decir que si en “modo normal” presiono la tecla “F3”, se
va a escribir el comando “:!git status” y se va a presionar “Enter” para
ejecutarlo.</p>
<p>De esta forma puedo agregar cualquier otro comando de la shell que
quiero utilizar de forma rápida, y puedo asociar esos comandos a las
combinaciones de teclado que más me ayuden.</p>
<h2 id="conclusión">Conclusión</h2>
<p>Bueno, con esto termino este apunte sobre cómo usar la Shell
directamente desde Neovim. Por añadidura eso nos va a permitir utilizar
Git en Neovim desde Linux.</p>
<p>¿Es todo esto una buena idea? Lo más seguro es que existen formas más
prácticas que se habilitan por medio de complementos. Pero de todas
formas es un buen ejercicio para aprender más de todo esto.</p>
<p>¿Encontraste algún error en el material? Por favor, avísame con un
correo electrónico para que pueda corregirlo.</p>
<p>Lo mismo si te interesa comentar algo sobre el texto, mi correo
electrónico se encuentra abierto para conocer tus opiniones.</p>
<p>La seguimos en el próximo apunte.</p>
<p><strong>¿Comentarios o preguntas?</strong> Escríbeme tu opinión a: <a href="mailto:gustavol@apunteimpensado.com">gustavo@apunteimpensado.com</a></p>]]></description>
        <link>https://apunteimpensado.com/como-usar-terminal-linux-git-neovim/</link>
        <guid isPermaLink="true">https://apunteimpensado.com/como-usar-terminal-linux-git-neovim/</guid>
        <pubDate>Tue, 21 Jan 2025 00:00:00 </pubDate>
    </item>
    <item>
        <title><![CDATA[Mi experiencia con Tmux, algunas cosas que aprendí como principiante]]></title>
        <description><![CDATA[<!--
INDEX_START
This section will be parsed for the left sidebar index/chapter list.
Use standard Markdown link syntax - links should point to actual HTML files.
-->

<p>Con estas palabras empiezo este apunte llamado “Guía mínima para
empezar a utilizar Tmux”.</p>
<p>O bueno, ese era el nombre que iba a ponerle a este texto en un
principio. Con la esperanza de volverlo un poco más personal y menos
técnico, decidí cambiarle el enfoque.</p>
<p>Por eso estas son algunas de las cosas que aprendí al empezar a usar
<a href="https://github.com/tmux/tmux">Tmux</a>, y creo que son cosas
que pueden ayudar a cualquiera que empieza a usar el programa.</p>
<h2 id="por-qué-elegí-empezar-a-usar-tmux">¿Por qué elegí empezar a usar
Tmux?</h2>
<p>Me gusta escribir y utilizar programas por medio de la terminal en
Linux, y Tmux es una herramienta que vuelve más sencillo utilizar la
terminal.</p>
<p>Aunque las ventajas de tmux son varias, principalmente <a
href="https://github.com/tmux/tmux/wiki/%20Getting-Started">esta frase
de la Wiki oficial es la que me convenció:</a></p>
<blockquote>
<p>Work with multiple programs and shells together in one terminal, a
bit like a window manager</p>
</blockquote>
<p>Tmux es un programa que va a permitirnos utilizar varias programas y
shells dentro de una misma terminal.</p>
<p>Por ejemplo podemos usar dentro de un mismo “marco” un fragmento de
la pantalla con Bash, otro con <a
href="https://apunteimpensado.com/apuntes-%20neovim-guia-practica-personal/">Neovim</a>
y otro con Nano.</p>
<p>Y de alguna forma este otro apunte también se encuentra relacionado,
por el asunto de encajar más programas en una misma pantalla:</p>
<ul>
<li><a
href="https://apunteimpensado.com/espacios-trabajo-terminales-virtuales-linux/">Espacios
de trabajo y terminales virtuales en Linux</a></li>
</ul>
<h2 id="instalar-tmux-y-abrirlo">Instalar Tmux y abrirlo</h2>
<p>En este momento estoy utilizando Linux Mint, por lo que para hacer la
instalación utilicé el comando:</p>
<pre><code>sudo apt install tmux</code></pre>
<p><a href="https://github.com/tmux/tmux/wiki/Installing">Pero este
enlace lleva a la documentación para hacer la instalación en otros
sistemas operativos</a></p>
<p>Ahora para empezar a usar Tmux escribo el comando:</p>
<pre><code>tmux new</code></pre>
<h2 id="tmux-tiene-una-estructura-jerárquica">Tmux tiene una estructura
jerárquica</h2>
<p>Estoy revisando esto de una forma superficial, pero según entiendo
Tmux tiene una estructura jerárquica en niveles. Estos niveles pueden
describirse de esta forma:</p>
<ol type="1">
<li>Servidor/cliente (server/client):</li>
</ol>
<p>Tmux mantiene todo lo que hace dentro de un único proceso, actuando
como un servidor que actúa detrás de escena mientras funciona. Luego
cada vez que creamos una nueva sesión o usamos un comando, nos
conectamos a Tmux como un cliente.</p>
<p>Esta relación server/client es lo que permite algunas de las ventajas
del programa, como por ejemplo la posibilidad de usarlo de forma remota
y retomarlo en distintos momentos.</p>
<p>Un servidor puede contener multiples sesiones en su interior.</p>
<ol start="2" type="1">
<li>Sesión (session):</li>
</ol>
<p>Una sesión representa un espacio de trabajo. Es un proyecto por
ejemplo. Cuándo uso el comando:</p>
<pre><code>tmux new</code></pre>
<p>Lo que estoy haciendo es empezar una nueva sesión. Por ejemplo si
quiero crear una sesión llamada “libro” utilizo el comando:</p>
<pre><code>tmux new -s libro</code></pre>
<p>Una misma sesión puede contener múltiples ventanas.</p>
<ol start="3" type="1">
<li>Ventana (window):</li>
</ol>
<p>Una sesión puede tener múltiples ventanas. Las ventanas pueden tener
sus propios nombres, y pueden ser modificadas de forma
independiente.</p>
<p>Por ejemplo, puedo tener una ventana llamada “ideas” y otra llamada
“tareas_pendientes” dentro de la sesión “libro” del ejemplo
anterior.</p>
<ol start="4" type="1">
<li>Panel (pane):</li>
</ol>
<p>Una ventana puede contener múltiples paneles en su interior. Cada
panel tiene una terminal o programa diferente.</p>
<p>Terminemos de imaginar nuestro ejemplo.</p>
<p>En nuestra sesión llamada “libro” tenemos una ventana llamada
“ideas”. Dentro de esa ventana tenemos tres paneles abiertos, uno con
Neovim, otro con Bash y otro con Nano. Y en cada panel estoy realizando
una tarea distinta.</p>
<h2
id="tmux-se-utiliza-por-medio-de-comandos-y-combinaciones-del-teclado">Tmux
se utiliza por medio de comandos y combinaciones del teclado</h2>
<p>Hay muchas combinaciones del teclado para este programa, en esto
también la experiencia de uso me recuerda mucho a Neovim.</p>
<p>Toda esa información es mucha como para detallarlos en esta entrada,
<a href="https://tmuxcheatsheet.com/">pero podemos encontrar toda la
información que necesitamos sobre las combinaciones en este
sitio</a></p>
<h2 id="tmux-tiene-una-barra-de-estatus">Tmux tiene una barra de
estatus</h2>
<p>Tmux tiene una barra de estatus (status bar) en la parte inferior de
la pantalla.</p>
<p>Esa barra nos aporta varios datos, por ejemplo el nombre de la sesión
y la fecha. El color de la barra puede cambiar.</p>
<p>Otro detalle a tener en cuenta es que podemos modificar los datos que
la barra nos muestra.</p>
<h2 id="tmux-tiene-diferentes-modos-de-trabajo">Tmux tiene diferentes
modos de trabajo</h2>
<p>Tmux tiene una forma de uso que alterna entre lo que puedo describir
como varios modos de trabajo. Y cada uno de esos modos se comporta de
una forma diferente. Podemos ir alternando entre estas formas con
algunas combinaciones de teclas.</p>
<h3 id="modo-predeterminado-default-mode">Modo Predeterminado (Default
mode)</h3>
<p>Me permite interactuar directamente con el texto. El equivalente a
“utilizar la terminal” por decirlo de alguna forma.</p>
<h3 id="modo-de-selección-choose-mode">Modo de selección (choose
mode)</h3>
<p>Entramos a este modo presionando “Ctrl + b” y luego “w”, o dicho de
otra forma:</p>
<pre><code>Ctrl + b w</code></pre>
<p>En este modo podemos seleccionar entre por ejemplo las diferentes
ventanas abiertas en la sesión.</p>
<h3 id="modo-de-comandos-command-mode">Modo de comandos (command
mode)</h3>
<p>Entramos a este modo presionando:</p>
<pre><code>Ctrl + b  :</code></pre>
<p>El espacio para escribir comandos aparece en el lugar que ocupaba la
barra de estatus.</p>
<p>Un comando que puedo escribir por ejemplo es el siguiente, que crea
un nuevo panel horizontal:</p>
<pre><code>split-window -h</code></pre>
<h2 id="conclusión">Conclusión</h2>
<p>Con esto le doy un cierre a este apunte, donde cuento mi experiencia
al utilizar Tmux.</p>
<p>Espero haber transmitido en el texto de forma sencilla algunas ideas
que, de haberlas conocido desde un primer momento, me hubieran
facilitado mucho el empezar a usar el programa.</p>
<p>Es algo así como una lista rápida de temas, una vez que conocemos los
detalles básicos podemos ampliar nuestro conocimiento con la práctica y
con la increíble calidad de todo la documentación que se consigue sobre
el tema.</p>
<p>¿Encontraste algún error en el texto? Por favor avisame para que
pueda corregirlo.</p>
<p>La seguimos en el próximo apunte.</p>
<p><strong>¿Comentarios o preguntas?</strong> Escríbeme tu opinión a: <a href="mailto:gustavol@apunteimpensado.com">gustavo@apunteimpensado.com</a></p>]]></description>
        <link>https://apunteimpensado.com/experiencia-tmux-algunas-cosas-aprendi-principiante/</link>
        <guid isPermaLink="true">https://apunteimpensado.com/experiencia-tmux-algunas-cosas-aprendi-principiante/</guid>
        <pubDate>Sat, 14 Dec 2024 00:00:00 </pubDate>
    </item>
    <item>
        <title><![CDATA[Cómo empezar con el generador de sitios estáticos Hugo en Linux]]></title>
        <description><![CDATA[<!--
INDEX_START
This section will be parsed for the left sidebar index/chapter list.
Use standard Markdown link syntax - links should point to actual HTML files.
-->

<p>En este nuevo apunte práctico vamos a revisar el generador de sitios
estáticos Hugo. Y vamos a hacerlo dentro de nuestra computadora con un
sistema operativo Linux.</p>
<p>Pelican, Hugo y Jekyll. Tres herramientas distintas, un sueño de
sitios estáticos.</p>
<p>Ya con anterioridad escribí sobre dos de esas herramientas:</p>
<ul>
<li><p><a
href="https://apunteimpensado.com/como-crear-sitio-estatico-jekyll/">Cómo
crear un sitio estático con Jekyll</a></p></li>
<li><p><a
href="https://apunteimpensado.com/como-crear-sitio-estatico-pelican/">Cómo
crear un sitio estático con Pelican</a></p></li>
</ul>
<p>Como no quiero dejar de esta serie de apuntes sin terminar, hoy voy a
ocuparme de hacer una pequeña introducción sobre Hugo.</p>
<p>Otra cosa interesante que me motiva a completar esta rápida entrada:
Pelican se encuentra escrito en Python, Jekyll fue creado con el
lenguaje Ruby y Hugo se encuentra escrito con el lenguaje de
programación Golang.</p>
<h2 id="requisitos-previos">Requisitos previos</h2>
<p>Todo lo que sigue lo hice guiándome <a
href="https://gohugo.io/documentation/">con la documentación oficial de
Hugo.</a></p>
<p>Antes de empezar vamos a necesitar algunos programas extras en la
computadora para que todo funcione bien. Estoy utilizando Linux mint al
escribir esto, algunos comandos se pueden ajustar para otras
distribuciones.</p>
<h3 id="instalar-git">Instalar Git</h3>
<p>Git nos va a permitir hacer varias cosas, por ejemplo conseguir el
código fuente de Hugo.</p>
<p>Si tengo el administrador de paquetes apt en el sistema puedo
conseguir Git con el comando:</p>
<pre><code>sudo apt install git-all</code></pre>
<h3 id="instalar-go">Instalar Go</h3>
<p>Necesitamos también el compilador y las librerías de Golang para
poder usar el código de Hugo.</p>
<p>Todo lo que sigue supone que no tenemos Go en la computadora. En caso
de tenerlo, vamos a necesitar remover el directorio:</p>
<pre><code>/usr/local/go</code></pre>
<p>Tener varias instalaciones de Go en la misma máquina es un tema
aparte. Pero en este caso estamos empezando desde cero, por lo que eso
no es inconveniente.</p>
<p>Me dirijo a <a href="https://go.dev/dl/">este sitio de descarga
oficial de Go y descargo la última versión del lenguaje.</a></p>
<p>En este caso por ejemplo la última versión es:</p>
<pre><code>go1.23.4.linux-amd64</code></pre>
<p>Entonces descargo ese nuevo archivo “tar.gz” y lo llevo hasta el
directorio “/usr/local/”. Voy a necesitar permiso de administración/sudo
para hacerlo.</p>
<p>Muevo la terminal hasta el directorio “/usr/local/” donde ahora se
encuentra el archivo y luego ejecuto el siguiente comando:</p>
<pre><code>sudo tar -C /usr/local -xzf go1.23.4.linux-amd64.tar.gz</code></pre>
<p>Eso crea el nuevo directorio “Go” con todo lo que necesita el
lenguaje para funcionar.</p>
<p>Acto seguido agrego ese nuevo directorio al camino de los archivos
ejecutables del sistema con:</p>
<pre><code>export PATH=$PATH:/usr/local/go/bin</code></pre>
<p>Puedo hacer una prueba para comprobar que todo funcionó correctamente
con el comando:</p>
<pre><code>go version</code></pre>
<h3 id="instalar-snap">Instalar Snap</h3>
<p>Para simplificar este y el siguiente paso vamos a necesitar el
administrador de paquetes Snap en el equipo.</p>
<p>Si es que no lo tenemos en el sistema, <a
href="https://snapcraft.io/docs/installing-snapd">agregamos Snap de esta
forma.</a></p>
<p>En Linux Mint primero tenemos que usar el comando:</p>
<pre><code>sudo mv /etc/apt/preferenc/es.d/nosnap.pref ~/Documents/nosnap.backup</code></pre>
<p>Para mover el archivo “nosnap.pref” que viene dentro del sistema.
Esto va a habilitar que podamos usar el programa.</p>
<p>Luego actualizamos con:</p>
<pre><code>sudo apt update</code></pre>
<p>Y terminamos con:</p>
<pre><code>sudo apt install snapd</code></pre>
<p>Y con eso ya tenemos Snap en el equipo.</p>
<p>Si intentamos instalar Snap directamente por medio de “apt” saltando
el paso de mover el archivo “nosnap.pref”, vamos a recibir el error:</p>
<pre><code>Package snapd is not available, but is referred to by another package. This may mean that the package is missing, has been obsoleted, or is only available from another source E: Package ‘snapd’ has no installation candidate</code></pre>
<h3 id="instalar-dart-sass">Instalar Dart Sass</h3>
<p>Entiendo que este lenguaje le permite a Hugo realizar varias tareas
dedicadas al estilo CSS mediante el lenguaje Dart.</p>
<p>La instalación de Dart Sass varía un poco dependiendo si lo estamos
usando para desarrollar Hugo de forma local, o si lo vamos a usar
directamente para producción.</p>
<p>Siendo que ahora estamos haciendo una instalación orientada al
desarrollo dentro de nuestra máquina, podemos conseguir Dart Sass con
este comando:</p>
<pre><code>sudo snap install dart-sass</code></pre>
<h2 id="cómo-instalar-hugo-en-un-sistema-linux">Cómo instalar Hugo en un
sistema Linux</h2>
<p>Con todos los requisitos anteriores cumplidos finalmente podemos
agregar Hugo a nuestro equipo.</p>
<p>Ahora bien, existen tres versiones de Hugo: Standard, Extendida y
“Extendida para producción”.</p>
<p>Sin detenernos demasiado en los detalles de cada una, vamos a
conseguir la versión extendida. Parece una buena opción para nuestro
objetivo de hacer desarrollo de forma local.</p>
<p>Hacemos una vez más uso de Snap y utilizamos el comando:</p>
<pre><code>sudo snap install hugo</code></pre>
<p>Y con eso finalmente ya puedo empezar a desarrollar con Hugo.</p>
<p>Puedo conocer la versión con:</p>
<pre><code>hugo version</code></pre>
<h2
id="cómo-crear-un-primer-sitio-en-hugo-dentro-de-nuestra-máquina">Cómo
crear un primer sitio en Hugo dentro de nuestra máquina</h2>
<p>De una forma similar a como ocurre con Pelican y Jekyll, con Hugo
podemos tomar un archivo escrito en Markdown para convertirlo
rápidamente en un sitio estático.</p>
<p>Por supuesto lo anterior es una simplificación, y cubrir todo el tema
desde esta entrada rápida sería muy difícil.</p>
<p>Pero para no terminar este apunte sin tener algo terminado, esto es
lo que podemos hacer para crear un primer sitio dentro de nuestra
computadora con una de las muchas planillas que este programa
ofrece.</p>
<p>Voy a hacer un directorio dedicado dentro de Home para guardar mis
proyectos. En ese nueva carpeta hago:</p>
<pre><code>hugo new site nuevo-blog</code></pre>
<p>Mi sitio en este caso se llama “nuevo-blog”, y Hugo va a crear un
nuevo árbol de directorios dentro de esa carpeta con todo lo necesario
para más tarde exportar el sitio terminado.</p>
<p>Ahora entro en la carpeta del proyecto con:</p>
<pre><code>cd nuevo-blog</code></pre>
<p>E inicio un repositorio de Git:</p>
<pre><code>init git</code></pre>
<p>Aunque podemos <a href="https://themes.gohugo.io/">elegir un tema
para nuestro sitio de entre las múltiples opciones ya disponibles</a>,
pero la documentación recomienda empezar con el tema “Ananke”.</p>
<p>Para eso utilizamos este comando:</p>
<pre><code>git submodule add https://github.com/theNewDynamic/gohugo-theme-ananke.git themes/ananke</code></pre>
<p>Acto seguido modificados el documento “hugo.toml”, que encontramos en
el directorio de nuestro proyecto. Dentro de ese documento agregamos
esta linea para establecer el tema Ananke como el predeterminado.</p>
<p>Lo hacemos con este comando:</p>
<pre><code>echo &quot;theme = &#39;ananke&#39;&quot; &gt;&gt; hugo.toml</code></pre>
<p>Solamente nos falta comenzar el server de desarrollo para poder
visitar el sitio desde nuestro equipo. Para eso utilizamos el
comando:</p>
<pre><code>hugo server --buildDrafts</code></pre>
<p>Y podemos entrar al sitio poniendo en el navegador esta
dirección:</p>
<pre><code>http://localhost:1313/</code></pre>
<p>Para terminar presionamos “Ctrl+C” en la terminal, y de esa forma
dejamos de servir el sitio.</p>
<p>Siguiendo estos pasos podemos cambiar el tema e iniciar nuevos
proyectos, solamente nos falta agregar nuevas páginas y entradas.</p>
<h2 id="conclusión">Conclusión</h2>
<p>Con esto termina este apunte revisando cómo empezar con el generador
de sitios estáticos Hugo en Linux</p>
<p>En mi breve experiencia probando Jekyll, Pelican y Hugo, creo que de
las tres opciones prefiero Pelican. Pero creo que es solamente porque se
encuentra escrito en Python, y estoy un poco más acostumbrado a ese
lenguaje.</p>
<p>¿Encontraste algún error en la publicación? ¿Encontraste algo que
puedo mejorar? Me gustaría conocer tu opinion, escribime un mensaje o un
correo electrónico sobre el tema.</p>
<p>La seguimos en el próximo apunte.</p>
<p><strong>¿Comentarios o preguntas?</strong> Escríbeme tu opinión a: <a href="mailto:gustavol@apunteimpensado.com">gustavo@apunteimpensado.com</a></p>]]></description>
        <link>https://apunteimpensado.com/como-empezar-generador-sitios-estaticos-hugo-linux/</link>
        <guid isPermaLink="true">https://apunteimpensado.com/como-empezar-generador-sitios-estaticos-hugo-linux/</guid>
        <pubDate>Sat, 07 Dec 2024 00:00:00 </pubDate>
    </item>
    <item>
        <title><![CDATA[Qué son los espacios de trabajo y las terminales virtuales en Linux]]></title>
        <description><![CDATA[<!--
INDEX_START
This section will be parsed for the left sidebar index/chapter list.
Use standard Markdown link syntax - links should point to actual HTML files.
-->

<p>En este breve apunte rápido voy a estar revisando dos conceptos que
van a mejorar y profundizar el uso que le damos a nuestro sistema
operativo Linux: qué son los espacios de trabajo y las terminales
virtuales en Linux.</p>
<p>Se trata de temas que solamente cobran sentido cuándo los utilizamos
directamente, por lo que es importante practicarlos mientras los
revisamos.</p>
<h2 id="qué-son-los-espacios-de-trabajo-workspaces-en-linux">¿Qué son
los espacios de trabajo (workspaces) en Linux?</h2>
<p>Digamos que tenemos que escribir un ensayo para la universidad.
Tenemos abierto en el escritorio de nuestra computadora un programa para
escribir, varios documentos de los que estamos estudiando y un navegador
de internet con múltiples pestañas para ayudarnos a investigar.</p>
<p>Pero en paralelo estamos realizando otro trabajo, estamos editando un
video. Tenemos abierto un programa de edición y un programa para editar
imágenes, además de varias carpetas desde dónde vamos buscando el
material de montaje.</p>
<p>Hasta ahora describí dos tareas posibles que podemos realizar en la
computadora. Esas dos tareas ocupan lugar del mismo escritorio, conviven
en la misma barra de tareas, y simplemente alternamos entre los
programas según los necesitamos.</p>
<p>Se puede notar que tenemos que hacer un esfuerzo extra para poder
organizarnos entre tanta mezcla de información dentro de un número
limitado de pantallas… ¿Podemos dividir esas tareas para que cada una
ocupe su propio “ambiente” en el escritorio?</p>
<p>En esto es donde entra la idea de espacios de trabajo o
“workstations”, una forma gráfica de poder hacer multitareas en
Linux.</p>
<p>Alternar entre espacios de trabajo es similar a utilizar varios
monitores dentro de un mismo monitor. Es una forma de hacer que cada
espacio se aparezca más ordenado. Es como usar varios escritorios
virtuales al mismo tiempo.</p>
<p>Siguiendo el ejemplo anterior, podemos utilizar uno de los espacios
de trabajo que ofrece el sistema para agrupar todo lo que tiene que ver
con la actividad de escribir nuestro ensayo universitario. Y luego otro
escritorio virtual va a ocupar todo lo que tiene que ver con la tarea de
edición de video.</p>
<p>Este aislamiento entre espacios de trabajo no es total, no se crean
compartimientos separados. Los recursos que se utilizan son iguales. Es
diferente a crear máquinas virtuales, donde la maquina anfitriona puede
correr un sistema huésped en su interior. Tampoco estamos creando
contenedores.</p>
<p>Los escritorios virtuales nos sirven para poder organizar múltiples
tareas en una misma computadora, sin necesidad de llenar todo dentro de
un mismo escritorio. Al parecido a lo que haríamos si pudiéramos
asignarle un monitor a cada conjunto de programas que estamos
usando.</p>
<h3 id="cómo-cambiar-entre-espacios-de-trabajo">¿Cómo cambiar entre
espacios de trabajo?</h3>
<p>Bueno, la forma práctica de usar los escritorios virtuales es un poco
diferente entre cada versión del sistema operativo Linux.</p>
<p>Pero para completar estos ejemplos voy a referirme a Linux Mint.</p>
<p>Este sistema operativo nos permite desde un principio alternar entre
cuatro workstations.</p>
<p>Un atajo para moverme entre estos espacios de trabajo es el de
presionar en el teclado:</p>
<pre><code>Alt + F1</code></pre>
<p>Se me va a mostrar en pantalla partida una representación gráfica de
cada escritorio y lo que está ocurriendo en cada uno.</p>
<p>La otra opción que tengo en Mint es la de mantener presionados “Ctrl
+ Alt” y luego moverme entre los distintos espacios con las flechas
direccionales izquierda/derecha/arriba/abajo.</p>
<p>Pero en resumen, cada sistema operativo puede ofrecer su propia forma
de alternar entre estos espacios de trabajo virtuales. Lo más importante
es saber que existen y que podemos utilizar los espacios para
organizarnos efectivamente.</p>
<h2
id="qué-son-las-terminales-virtuales-virtual-terminals-en-linux">¿Qué
son las terminales virtuales (virtual terminals) en Linux?</h2>
<p>Lo primero que quiero mencionar es si presionamos “Ctrl + Alt” en el
teclado, y luego alternamos entre F1 y F6 vamos a poder saltar entre las
diferentes terminales virtuales.</p>
<p>Menciono esto porque si sos como yo, probablemente tu primer
acercamiento a este tema ocurrió cuándo apretaste este atajo sin saber y
luego no pudiste salir de la pantalla de la nueva terminal virtual.</p>
<p>Para resumir hasta el momento, sabemos que si presiono las
teclas:</p>
<pre><code>Ctrl + Alt + F1</code></pre>
<p>Se aparece una terminal llamada “tty1” que ocupa toda la pantalla y
me pide una contraseña.</p>
<p>Por otra parte si ahora presiono:</p>
<pre><code>Ctrl + Alt + F7</code></pre>
<p>Vuelvo de nuevo al escritorio. ¿Qué es lo que está ocurriendo?</p>
<p>Según entiendo si yo abro una terminal dentro del “escritorio”, estoy
abriendo esa nueva terminal dentro de la interfaz gráfica del sistema
operativo. La terminal es emulada dentro de la parte gráfica, y la parte
gráfica al mismo tiempo esta siendo ejecutada por el sistema.</p>
<p>Por otra parte al presionar “Ctrl + Alt + F1” se me está presentando
una terminal que funciona por fuera de la parte gráfica. Y esta terminal
no es un programa, es un entorno de trabajo completo. Se trata de una
sesión independiente de la consola que trabaja con el sistema.</p>
<p>Lo importante de todo esto es que puedo usar estas diferentes
terminales para realizar diferentes tareas en paralelo. Puedo usar una
de esas terminales virtuales para corregir una pieza de código, otra
para modificar la configuración de un programa y otra terminal para
escribir un texto.</p>
<p>De alguna forma similar al caso de los diferentes espacios de
trabajo, puedo usar las distintas terminales virtuales para acomodar en
una misma pantalla las diferentes tareas que estoy realizando.</p>
<h3
id="qué-credenciales-necesito-para-acceder-a-una-terminal-virtual">¿Qué
credenciales necesito para acceder a una terminal virtual?</h3>
<p>Bien, antes dije que utilicé este atajo:</p>
<pre><code>Ctrl + Alt + F1</code></pre>
<p>Y se me apareció una terminal con el mensaje:</p>
<pre><code>Linux Mint 21.3 Virginia Computer tty1computer login:</code></pre>
<p>Bueno, lo que tenemos que usar es el nombre de mi propia cuenta y la
contraseña. En mi caso algo como:</p>
<pre><code>computer login: gus password:</code></pre>
<p>Pero hay dos cosas que tenemos que tener en cuenta:</p>
<ul>
<li><p>1: Si nuestra contraseña tiene números en su interior, no tenemos
que usar el teclado numérico para escribir esos números. Tenemos que
usar los números de la parte “izquierda” del teclado para no tener
errores.</p></li>
<li><p>2: puede parecer que la contraseña no se está escribiendo, pero
es una función de seguridad del sistema para ocultar el número de
caracteres del password. Al presionar enter va a funcionar de todas
formas, aunque nada se muestre escrito luego de ingresar el
password.</p></li>
</ul>
<h2 id="conclusión">Conclusión</h2>
<p>Con esto le doy un cierre al apunte referido a qué son los espacios
de trabajo y las terminales virtuales en Linux.</p>
<p>De esta forma pudimos cubrir dos temas muy útiles en una sola
entrada.</p>
<p>Es importante volver a mencionar que estoy haciendo todo lo posible
para explicar el tema con mis propias palabras y según lo entiendo.
Puedo equivocarme, te pido por favor que me avises si encontraste algún
error en el texto para poder repararlo. Y si no pude explicarme de la
mejor forma, avísame con un mensaje para que pueda mejorar el
material.</p>
<p><a
href="https://apunteimpensado.com/guia-minima-empezar-terminal-linux/">Te
recomiendo además esta otra publicación, dónde reviso más en profundidad
algunos detalles de la terminal en Linux.</a></p>
<p>La seguimos en el próximo apunte.</p>
<p><strong>¿Comentarios o preguntas?</strong> Escríbeme tu opinión a: <a href="mailto:gustavol@apunteimpensado.com">gustavo@apunteimpensado.com</a></p>]]></description>
        <link>https://apunteimpensado.com/espacios-trabajo-terminales-virtuales-linux/</link>
        <guid isPermaLink="true">https://apunteimpensado.com/espacios-trabajo-terminales-virtuales-linux/</guid>
        <pubDate>Thu, 21 Nov 2024 00:00:00 </pubDate>
    </item>
    <item>
        <title><![CDATA[Cómo estudiar programación orientada a objetos mientras creamos motion graphics en Processing]]></title>
        <description><![CDATA[<!--
INDEX_START
This section will be parsed for the left sidebar index/chapter list.
Use standard Markdown link syntax - links should point to actual HTML files.
-->

<p>En este apunte de título más complicado de lo necesario vamos a
revisar cómo estudiar programación orientada a objetos mientras creamos
motion graphics en Processing.</p>
<p>Para ejemplificar la explicación vamos a utilizar <a
href="https://processing.org/">Proc</a><a
href="https://processing.org/">e</a><a
href="https://processing.org/">ssing</a>, un entorno de desarrollo que
funciona muy bien para crear imágenes.</p>
<p>Ya escribí en otra oportunidad sobre <a
href="https://%20apunteimpensado.com/processing-guia-practica-basica/">Processing,
por lo que si te interesa aprender más este es el enlace a ese otro
apunte.</a></p>
<p>Vale mencionar que Processing utiliza el lenguaje “Java”, que es un
lenguaje de programación orientado a objetos. Python es otro lenguaje
orientado a objetos que es muy famoso.</p>
<p>¿Cuál es el objetivo de la entrada? Vamos a crear un sencillo video
de “gráficos en movimiento” utilizando código en Processing, y esos
gráficos van a tomar el lugar de clases y objetos en la ya tan
mencionada “programación orientada a objetos”.</p>
<h2 id="una-explicación-sin-explicación">Una explicación sin
explicación</h2>
<p>Este tema que nos entretiene puede ser comprendido por una serie de
inteligentes explicaciones graciosamente desarrolladas. Lamentablemente
esas explicaciones de ser escritas por alguien con poca experiencia
pueden resultar en algo muy confuso y aburrido. Soy una persona con poca
experiencia. ¿Es este el final de este apunte?</p>
<p>No, este no es el final de este texto. El apunte sigue adelante.</p>
<p>Tengo que decir que estamos de suerte, porque no tengo muchas ganas
de escribir y no estoy seguro de saber lo suficiente como para poder
escribir una explicación coherente.</p>
<p>Lo que voy a hacer en lugar de todo eso es crear una explicación que
se construye con una serie de ejemplos de código que sumados en conjunto
van a funcionar como una especie de explicación completa.</p>
<p>Para ser honesto, la mayoría de las cosas se explican menor cuándo
las ponemos en práctica. Y este es uno de esos temas que se explican
mejor en la forma de una epifanía. En un momento no sabemos lo que es la
programación orientada a objetos porque no necesitamos de ella, y al
otro encontramos una oportunidad para usar sus ventajas y tenemos una
relevación que explica qué es y para qué sirve.</p>
<p>Entonces advierto que esta no va a ser la explicación que mejor se
ajuste a los conceptos teóricos contemporáneos. Pero al terminar de
leerla vas a encontrar que pudiste utilizar la idea para crear algo
valioso, algo que luego vas a poder seguir utilizando en otro tipo de
proyectos.</p>
<p>Entonces sin más excusas…</p>
<h2
id="cómo-crear-un-sencillo-separador-de-video-usando-motion-graphics-en-processing">Cómo
crear un sencillo separador de video usando motion graphics en
Processing</h2>
<p>Processing nos sirve para crear imágenes y videos. En esta
oportunidad me interesa que hagamos un sencillo video, un video que
puede servir como una presentación para un proyecto (digamos para un
proyecto en las redes) o como un separador por ejemplo para un video más
grande.</p>
<p>El video va a estar compuesto por una serie de placas de colores que
suben y bajan en forma de cortina, descubriendo el título del
proyecto.</p>
<h3 id="paso-1-un-proyecto-muchos-capas-de-color">Paso 1: un proyecto,
muchos capas de color</h3>
<p>Lo primero que vamos a hacer es crear un sketch con las dimensiones
de la pantalla.</p>
<p>Siendo que queremos hacer un video, vamos a crear la pantalla<br />
en tamaño HD (1280 x 720) y vamos a dejarla de color negro. Por supuesto
es posible ajustar estos parámetros según lo que necesites en el
momento.</p>
<p>Acto seguido vamos a crear una nueva “capa” por llamarla de algún
modo, un color solido naranja que cubra toda la pantalla.</p>
<p>El primer código nos queda de esta forma:</p>
<pre class="language-java"><code>void setup() {
  size(1280, 720);
  background(0);
}

void draw() {
  fill(255, 128, 0); // Color naranja
  rect(0, 0, width, height); // Rectangulo que cubre la pantalla
}</code></pre>
<p>Por ahora nuestro primer rectángulo creado con la función “rect()”
tiene algunas características definidas. Por ejemplo tiene un color con
la notación (255, 128, 0).</p>
<p>Y el rectángulo tiene una posición en la pantalla determinada por
(0,0). Esto quiere decir que la parte superior izquierda del rectángulo
coincide con la coordenada del ángulo superior izquierdo de la pantalla.
Esto es en la forma (x, y), de una forma similar a la de un plano
cartesiano.</p>
<p>Los parámetros “width, height” definen el ancho y el alto del
rectángulo. Escritos de esta forma indican que nuestra capa tiene que
copiar el tamaño de la pantalla.</p>
<p>Este rectángulo naranja es el primero de los que vamos a usar para
crear nuestra cortina animada de motion graphics.</p>
<p>¿Por qué no agregar algunos nuevos colores?</p>
<p>Revisemos este nuevo ejemplo de código:</p>
<pre class="language-java"><code>void setup() {
  size(1280, 720);
  background(0);
}

void draw() {
  fill(255, 128, 0); // Color naranja
  rect(0, 0, width, height); //  Posición del color naranja

  fill(0, 0, 255); // Color Azul
  rect(0, 0, width, height); // Posición del azul

  fill(255, 0, 0); // Color rojo
  rect(0, 0, width, height); // Datos de posición rojo

  fill(0, 255, 0); // Color Verde
  rect(0, 0, width, height); // Posición del color verde
}</code></pre>
<p>Ahora tenemos cuatro rectángulos en total. Pero tenemos que notar
algunas cosas:</p>
<p>1- Cada capa se encuentra por debajo de la anterior. La última de la
lista es que primero aparece, por eso si ejecutamos el código vamos a
ver la pantalla de color verde. Y si borramos la capa verde, va a
aparecer la siguiente de color rojo y así sucesivamente.</p>
<p>2- Las capas son difíciles de identificar. Las capas no tienen
nombres que las separen, y lo único que nos dice fácilmente lo que hace
cada na es el comentario con el que estamos acompañándolas.</p>
<p>3- Las capas todavía no se mueven lo que hace a un video bastante
aburrido.</p>
<p>¿Cómo podemos solucionar todo esto? ¿Cómo podemos organizar mejor el
proyecto? Aquí es donde entra el momento de la programación orientada a
objetos.</p>
<h3 id="paso-2-una-nueva-clase-de-rectángulo">Paso 2: una nueva clase de
rectángulo</h3>
<p>Revisemos este nuevo código, expandiendo nuestro anterior
ejemplo:</p>
<pre class="language-java"><code>class Rectangulo {
  int x;
  int y;
  int width;
  int height;
  color fillColor;

  Rectangulo(int _x, int _y, int _width, int _height, color _fillColor) {
    x = _x;
    y = _y;
    width = _width;
    height = _height;
    fillColor = _fillColor;
  }

  void draw() {
    fill(fillColor);
    rect(x, y, width, height);
  }

}

Rectangulo naranjaCapa;
Rectangulo azulCapa;
Rectangulo rojoCapa;
Rectangulo verdeCapa;

void setup() {
  size(1280, 720);

  // Crear objetos de la clase Rectangulo
  naranjaCapa = new Rectangulo(0, 0, width, height, color(255, 165, 0));
  azulCapa = new Rectangulo(0, 0, width, height, color(0, 0, 255));
  rojoCapa = new Rectangulo(0, 0, width, height, color(255, 0, 0));
  verdeCapa = new Rectangulo(0, 0, width, height, color(0, 255, 0));

}

void draw() {
  background(0);

  naranjaCapa.draw();
  azulCapa.draw();
  rojoCapa.draw();
  verdeCapa.draw();

}</code></pre>
<p>Bueno, en un primer momento todo este código parece mucho más
complejo que el primero que estuvimos revisando. Pero si lo ejecutamos
vamos a notar que tenemos el mismo resultado. Una capa verde cubre la
pantalla.</p>
<p>Sin embargo es en este punto dónde empezamos a descubrir la idea de
la programación orientada a objetos.</p>
<p>Antes necesitábamos crear cada rectángulo por separado, de esta
forma:</p>
<pre><code>fill(0, 0, 255); // Color Azulrect(0, 0, width, height); // Posición del azul</code></pre>
<p>Pero ahora estamos creando una clase o <a
href="https://processing.org/reference/class.html">“class”</a>.</p>
<p>Al definir una clase podemos declarar las características, los datos
y las funciones que a nuestro parecer tiene que tener un rectángulo. Se
trata del “plano” del que luego vamos a construir los objetos.</p>
<p>Pero podríamos definir clases para cualquier tipo de objeto que
utilicemos en el futuro, coincide en este caso que nuestra primera clase
podemos entenderla de forma gráfica como una figura geométrica.</p>
<p>Realmente una clase puede representar cualquier cosa, como por
ejemplo un concepto dentro de una base de datos. Pero volvamos a nuestra
clase rectángulo.</p>
<pre class="language-java"><code>class Rectangulo {
  int x;
  int y;
  int width;
  int height;
  color fillColor;

  Rectangulo(int _x, int _y, int _width, int _height, color _fillColor) {
    x = _x;
    y = _y;
    width = _width;
    height = _height;
    fillColor = _fillColor;
  }

  void draw() {
    fill(fillColor);
    rect(x, y, width, height);
  }

}</code></pre>
<p>El manual de referencias de Processing dice que el nombre de una
clase es escrito en Mayúscula, para diferenciarla de otras variables. En
nuestro<br />
caso lo definimos como “class Rectangulo”.</p>
<p>Luego definimos las propiedades del rectángulo, por ejemplo que su
alto y ancho son números enteros:</p>
<pre><code>int x;int y;int width;int height;color fillColor;</code></pre>
<p>Acto seguido construimos la forma que va a tener el nuevo objeto
cuando llamemos al objeto:</p>
<pre><code>Rectangulo(int _x, int _y, int _width, int _height, color _fillColor) {    x = _x;    y = _y;    width = _width;    height = _height;    fillColor = _fillColor;  }</code></pre>
<p>Y luego creamos un método, una función que es parte de esta
clase:</p>
<pre><code>void draw() {    fill(fillColor);    rect(x, y, width, height);  }</code></pre>
<p>Esa función define la forma en que el rectángulo va a dibujarse en la
pantalla.</p>
<p>Con eso terminamos de crear la clase, que podemos considerar como el
plano o la serie de instrucciones que definen nuestro objeto. Recordemos
que en este caso estamos definiendo las características que queremos
agregarle a la clase rectángulo.</p>
<p>¿Dónde empezamos a utilizar a los objetos en todo esto?</p>
<p>Ahora dentro del código principal le asignamos un nombre diferente a
cada capa como variable, y creamos nuevos objetos a partir de la serie
de características que agregamos en la clase:</p>
<pre class="language-java"><code>Rectangulo naranjaCapa;
Rectangulo azulCapa;
Rectangulo rojoCapa;
Rectangulo verdeCapa;

void setup() {
  size(1280, 720);

  // Crear objetos de la clase Rectangulo
  naranjaCapa = new Rectangulo(0, 0, width, height, color(255, 165, 0));
  azulCapa = new Rectangulo(0, 0, width, height, color(0, 0, 255));
  rojoCapa = new Rectangulo(0, 0, width, height, color(255, 0, 0));
  verdeCapa = new Rectangulo(0, 0, width, height, color(0, 255, 0));

}</code></pre>
<p>Esto nos permite que cada capa de rectángulo pueda manipularse por
separado.</p>
<h3 id="los-objetos-en-movimiento">Los objetos en movimiento</h3>
<p>Ahora queremos pasar a la parte de “movimiento” de “gráficos en
movimiento”.</p>
<p>Esta es la nueva versión de nuestro código:</p>
<pre class="language-java"><code>class Rectangulo {
  int x;
  int y;
  int width;
  int height;
  color fillColor;
  float velocidad;

  Rectangulo(int _x, int _y, int _width, int _height, color _fillColor, float _velocidad) {
    x = _x;
    y = _y;
    width = _width;
    height = _height;
    fillColor = _fillColor;
    velocidad = _velocidad;
  }

  void draw() {
    fill(fillColor);
    rect(x, y, width, height);
  }

  void update() {
    y += velocidad;
  }
}

Rectangulo naranjaCapa;
Rectangulo azulCapa;
Rectangulo rojoCapa;
Rectangulo verdeCapa;

void setup() {
  size(1280, 720);

  // Crear objetos de la clase Rectangulo
  naranjaCapa = new Rectangulo(0, 0, width, height, color(255, 165, 0), 4.0);
  azulCapa = new Rectangulo(0, 0, width, height, color(0, 0, 255), -6.0);
  rojoCapa = new Rectangulo(0, 0, width, height, color(255, 0, 0), 9.0);
  verdeCapa = new Rectangulo(0, 0, width, height, color(0, 255, 0), 12.0);

}

void draw() {
  background(0);

  naranjaCapa.update();
  azulCapa.update();
  rojoCapa.update();
  verdeCapa.update();

  naranjaCapa.draw();
  azulCapa.draw();
  rojoCapa.draw();
  verdeCapa.draw();

}</code></pre>
<p>Lo que hicimos fue agregar una nueva variable llamada velocidad.
Luego la variable de posición “Y” se modifica cada vez que un nuevo
cuadro es dibujado:</p>
<p>Esto quiere decir que si la variable velocidad es “2.0”, cada vez que
un nuevo plano es dibujado el rectángulo se mueve dos puntos hacia abajo
en el eje “Y”. Por otra parte si la velocidad fuera “-2.0” el rectángulo
se va a mover dos posiciones hacia arriba cada vez que es dibujado.</p>
<p>Con esto conseguimos crear un efecto de cortina que “sube y baja” que
puede servirnos para presentar un proyecto.</p>
<h4 id="más-objetos-en-movimiento">Más objetos en movimiento</h4>
<p>Por supuesto también podemos crear una nueva serie de objetos en base
a la clase que creamos antes. Esta nueva serie de rectángulos va a ser
llamada luego, para cerrar la introducción.</p>
<p>El código nos queda de esta forma:</p>
<pre class="language-java"><code>// Este código de Processing sube y baja rectángulos de colores en forma de cortina

class Rectangulo {
  int x;
  int y;
  int width;
  int height;
  color fillColor;
  float velocidad;

  Rectangulo(int _x, int _y, int _width, int _height, color _fillColor, float _velocidad) {
    x = _x;
    y = _y;
    width = _width;
    height = _height;
    fillColor = _fillColor;
    velocidad = _velocidad;
  }

  void draw() {
    fill(fillColor);
    rect(x, y, width, height);
  }

  void update() {
    y += velocidad;
  }
}

Rectangulo naranjaCapa;
Rectangulo azulCapa;
Rectangulo rojoCapa;
Rectangulo verdeCapa;

Rectangulo amarilloCapa;
Rectangulo cyanCapa;
Rectangulo extra_naranjaCapa;

int startTime; // Variable para el tiempo de comienzo

void setup() {
  size(1280, 720);

  naranjaCapa = new Rectangulo(0, 0, width, height, color(255, 165, 0), 4.0);
  azulCapa = new Rectangulo(0, 0, width, height, color(0, 0, 255), -6.0);
  rojoCapa = new Rectangulo(0, 0, width, height, color(255, 0, 0), 9.0);
  verdeCapa = new Rectangulo(0, 0, width, height, color(0, 255, 0), 12.0);

  amarilloCapa = new Rectangulo(0, 720, width, height, color(255, 255, 50), -11.0);
  cyanCapa = new Rectangulo(0, 720, width, height, color(0, 255, 255), -8.0);
  extra_naranjaCapa = new Rectangulo(0, 720, width, height, color(245, 145, 0), -6.0);


  // Comenzar a guardar la variable de tiempo
  startTime = millis();
}

void draw() {
  background(0);

  naranjaCapa.update();
  azulCapa.update();
  rojoCapa.update();
  verdeCapa.update();

  if (millis() - startTime &gt;= 7000) {

    amarilloCapa.update();
    amarilloCapa.draw();
    cyanCapa.update();
    cyanCapa.draw();
    extra_naranjaCapa.update();
    extra_naranjaCapa.draw();

  }

  naranjaCapa.draw();
  azulCapa.draw();
  rojoCapa.draw();
  verdeCapa.draw();
}</code></pre>
<p>Haciendo esto le sacamos un poco más de jugo a nuestra clase de
Rectángulos, agregando nuevos objetos.</p>
<p>Solamente nos falta agregarle algo de texto al sketch para cumplir
nuestro objetivo de un sencillo separador en video de motion
graphics.</p>
<h3 id="un-objeto-de-texto">Un objeto de texto</h3>
<p>Esta es casi la última revisión del código:</p>
<pre class="language-java"><code>// Este código de Processing sube y baja rectángulos de colores en forma de cortina

class Titulo {
  float x, y;
  String contenido;
  float fade = 255;

  Titulo(float x, float y, String contenido) {
    this.x = x;
    this.y = y;
    this.contenido = contenido;
  }

  void display() {
    fill(255, fade);
    textSize(70);
    textAlign(CENTER, CENTER);
    text(contenido, x, y);
    fade -= 0.5;
    if (fade &lt;= 0) {
      fade = 0;
    }
  }
}

class Rectangulo {
  int x;
  int y;
  int width;
  int height;
  color fillColor;
  float velocidad;

  Rectangulo(int _x, int _y, int _width, int _height, color _fillColor, float _velocidad) {
    x = _x;
    y = _y;
    width = _width;
    height = _height;
    fillColor = _fillColor;
    velocidad = _velocidad;
  }

  void draw() {
    fill(fillColor);
    rect(x, y, width, height);
  }

  void update() {
    y += velocidad;
  }
}

Titulo miFrase;

Rectangulo naranjaCapa;
Rectangulo azulCapa;
Rectangulo rojoCapa;
Rectangulo verdeCapa;

Rectangulo amarilloCapa;
Rectangulo cyanCapa;
Rectangulo extra_naranjaCapa;

int startTime; // Variable para el tiempo de comienzo

void setup() {
  size(1280, 720);

  miFrase = new Titulo(width/2, height/2, &quot;TÍTULO DEL PROYECTO&quot;);

  naranjaCapa = new Rectangulo(0, 0, width, height, color(255, 165, 0), 4.0);
  azulCapa = new Rectangulo(0, 0, width, height, color(0, 0, 255), -6.0);
  rojoCapa = new Rectangulo(0, 0, width, height, color(255, 0, 0), 9.0);
  verdeCapa = new Rectangulo(0, 0, width, height, color(0, 255, 0), 12.0);

  amarilloCapa = new Rectangulo(0, 720, width, height, color(255, 255, 50), -11.0);
  cyanCapa = new Rectangulo(0, 720, width, height, color(0, 255, 255), -8.0);
  extra_naranjaCapa = new Rectangulo(0, 720, width, height, color(245, 145, 0), -6.0);

  // Comenzar a guardar la variable de tiempo
  startTime = millis();
}

void draw() {
  background(0);


  miFrase.display();

  naranjaCapa.update();
  azulCapa.update();
  rojoCapa.update();
  verdeCapa.update();

  if (millis() - startTime &gt;= 7000) {

    amarilloCapa.update();
    amarilloCapa.draw();
    cyanCapa.update();
    cyanCapa.draw();
    extra_naranjaCapa.update();
    extra_naranjaCapa.draw();

  }

  naranjaCapa.draw();
  azulCapa.draw();
  rojoCapa.draw();
  verdeCapa.draw();
}</code></pre>
<p>De la misma forma que habíamos hecho antes, ahora creamos una nueva
clase llamada “Titulo”.</p>
<pre class="language-java"><code>class Titulo {
  float x, y;
  String contenido;
  float fade = 255;

  Titulo(float x, float y, String contenido) {
    this.x = x;
    this.y = y;
    this.contenido = contenido;
  }

  void display() {
    fill(255, fade);
    textSize(70);
    textAlign(CENTER, CENTER);
    text(contenido, x, y);
    fade -= 0.5;
    if (fade &lt;= 0) {
      fade = 0;
    }
  }
}</code></pre>
<p>Entre las características que le dimos a esa clase está la habilidad
de desvanecer el texto poco a poco, registrando el cambio de forma
similar a la forma en que fuimos cambiando la posición de los
rectángulos en el espacio.</p>
<p>Con el título agregado el separador de video toma una forma. Pero lo
importante es poder seguir utilizando esta herramienta de clases y
objetos para nuevos proyectos de programación.</p>
<h3 id="una-clase-de-una-clase-herencias-en-los-objetos">Una clase de
una clase: herencias en los objetos</h3>
<p>Otra de las características importantes de la programación orientada
a objetos es la posibilidad de reutilizar las clases por medio de hacer
una inheritance o una “herencia”.</p>
<p>En nuestro código tenemos la siguiente clase llamada
“Rectángulo:”</p>
<pre class="language-java"><code>class Rectangulo {
  int x;
  int y;
  int width;
  int height;
  color fillColor;
  float velocidad;

  Rectangulo(int _x, int _y, int _width, int _height, color _fillColor, float _velocidad) {
    x = _x;
    y = _y;
    width = _width;
    height = _height;
    fillColor = _fillColor;
    velocidad = _velocidad;
  }

  void draw() {
    fill(fillColor);
    rect(x, y, width, height);
  }

  void update() {
    y += velocidad;
  }
}</code></pre>
<p>Si lo necesitamos podemos crear lo que puede definirse como una clase
diferente a partir de una clase ya existente. El resultado va a ser una
nueva clase, que referencia datos de la clase a la que hereda.</p>
<p>Las dos clases van a convivir al mismo tiempo, y eso nos permite
ahorrarnos repetir información. Los detalles particulares sobre cómo se
maneja este asunto de inheritance, y todo el asunto de clases y objetos
en general, depende de cada programa. Pero sigamos con la parte
práctica, dedicada a Processing y Java.</p>
<p>A partir de la clase “Rectangulo” voy a crear una nueva clase llamada
“Cierre”:</p>
<pre class="language-java"><code>class Cierre extends Rectangulo {
  float velocidadY;
  boolean stopYMovement; // Variable que decide si el rectangulo se mueve o no

  Cierre(int _x, int _y, int _width, int _height, color _fillColor, float _velocidadY) {
    super(_x, _y, _width, _height, _fillColor, 2.0);
    velocidadY = _velocidadY;
  }

  void update() {
    if (!stopYMovement) {
        y += velocidadY; // Modifica la velocidad revisando el eje y

        // Revisa si el eje y llega a 0
        if (y &lt;= 0) {
            y = 0;                // Detiene el movimiento en posición cero
                   }
    }

    super.update(); // Actualiza desde la calse heredada.
}

}</code></pre>
<p>Podemos leer que dice que “la clase”Cierre” extiende la clase
“Rectangulo”“.</p>
<p>Nuestra nueva clase cierre retiene las mismas características que
antes formaban nuestras capas rectangulares de colores. La diferencia es
que en<br />
esta nueva versión heredada la forma de revisar la posición en el eje de
“Y” es diferente. Siendo que vamos a usar esta imagen de cierre para
nuestro video, queremos que la capa deje de moverse al llegar a la
posición cero.</p>
<p>De esta forma vamos a tener una capa solida que nos va a permitir
generar un video Gif animado que hace un bucle sin que podamos notar
dónde empieza o termina.</p>
<p>El código completo es el siguiente:</p>
<pre class="language-java"><code>// Este código de Processing sube y baja rectángulos de colores en forma de cortina

class Titulo {
  float x, y;
  String contenido;
  float fade = 255;

  Titulo(float x, float y, String contenido) {
    this.x = x;
    this.y = y;
    this.contenido = contenido;
  }

  void display() {
    fill(255, fade);
    textSize(70);
    textAlign(CENTER, CENTER);
    text(contenido, x, y);
    fade -= 0.5;
    if (fade &lt;= 0) {
      fade = 0;
    }
  }
}

class Rectangulo {
  int x;
  int y;
  int width;
  int height;
  color fillColor;
  float velocidad;

  Rectangulo(int _x, int _y, int _width, int _height, color _fillColor, float _velocidad) {
    x = _x;
    y = _y;
    width = _width;
    height = _height;
    fillColor = _fillColor;
    velocidad = _velocidad;
  }

  void draw() {
    fill(fillColor);
    rect(x, y, width, height);
  }

  void update() {
    y += velocidad;
  }
}

class Cierre extends Rectangulo {
  float velocidadY;
  boolean stopYMovement; // Variable que decide si el rectangulo se mueve o no

  Cierre(int _x, int _y, int _width, int _height, color _fillColor, float _velocidadY) {
    super(_x, _y, _width, _height, _fillColor, 2.0);
    velocidadY = _velocidadY;
  }

  void update() {
    if (!stopYMovement) {
        y += velocidadY; // Modifica la velocidad revisando el eje y

        // Revisa si el eje y llega a 0
        if (y &lt;= 0) {
            y = 0;                // Detiene el movimiento en posición cero
                   }
    }

    super.update(); // Actualiza desde la calse heredada.
}

}

Titulo miFrase;

Rectangulo naranjaCapa;
Rectangulo azulCapa;
Rectangulo rojoCapa;
Rectangulo verdeCapa;

Rectangulo amarilloCapa;
Rectangulo cyanCapa;
Rectangulo extra_naranjaCapa;

Cierre nuevoVerdeCapa;

void setup() {
  size(1280, 720);

  miFrase = new Titulo(width/2, height/2, &quot;TÍTULO DEL PROYECTO&quot;);

  naranjaCapa = new Rectangulo(0, 0, width, height, color(255, 165, 0), 4.0);
  azulCapa = new Rectangulo(0, 0, width, height, color(0, 0, 255), -6.0);
  rojoCapa = new Rectangulo(0, 0, width, height, color(255, 0, 0), 9.0);
  verdeCapa = new Rectangulo(0, 0, width, height, color(0, 255, 0), 12.0);

  amarilloCapa = new Rectangulo(0, 720, width, height, color(255, 255, 50), -12.0);
  cyanCapa = new Rectangulo(0, 720, width, height, color(0, 255, 255), -11.0);
  extra_naranjaCapa = new Rectangulo(0, 720, width, height, color(245, 145, 0), -10.0);

  nuevoVerdeCapa = new Cierre(0, 720, width, height, color(0, 255, 0), -9.0);

}

int targetFrames = 300;

void draw() {
  background(0);

  miFrase.display();

  naranjaCapa.update();
  azulCapa.update();
  rojoCapa.update();
  verdeCapa.update();

  naranjaCapa.draw();
  azulCapa.draw();
  rojoCapa.draw();
  verdeCapa.draw();

  if (frameCount &gt;= targetFrames) {

    amarilloCapa.update();
    amarilloCapa.draw();
    cyanCapa.update();
    cyanCapa.draw();
    extra_naranjaCapa.update();
    extra_naranjaCapa.draw();
    nuevoVerdeCapa.update();
    nuevoVerdeCapa.draw();

  }

// saveFrame(&quot;frames/frame-####.png&quot;);

}</code></pre>
<h2 id="conclusión">Conclusión</h2>
<p>Con esto le doy un cierre a este apunte dónde intenté explicar cómo
estudiar programación orientada a objetos mientras creamos motion
graphics en Processing.</p>
<p>Hice todo lo posible por hacer el texto lo más breve posible, sin
omitir detalles de lo que entiendo del tema.</p>
<p>¿Hay algo que pueda mejorar de mi explicación? ¿Encontraste algún
error en los ejemplos? Me gustaría conocer tu opinion en los
comentarios, o por medio de un correo electrónico en mi dirección que se
encuentra en el menú de “contacto”.</p>
<p>La seguimos en el próximo apunte.</p>
<p><strong>¿Comentarios o preguntas?</strong> Escríbeme tu opinión a: <a href="mailto:gustavol@apunteimpensado.com">gustavo@apunteimpensado.com</a></p>]]></description>
        <link>https://apunteimpensado.com/como-estudiar-programacion-orientada-a-objetos-mientras-creamos-motion-graphics-en-processing/</link>
        <guid isPermaLink="true">https://apunteimpensado.com/como-estudiar-programacion-orientada-a-objetos-mientras-creamos-motion-graphics-en-processing/</guid>
        <pubDate>Wed, 02 Oct 2024 00:00:00 </pubDate>
    </item>
    <item>
        <title><![CDATA[Cómo cambiar el orden de arranque con GRUB en Linux]]></title>
        <description><![CDATA[<!--
INDEX_START
This section will be parsed for the left sidebar index/chapter list.
Use standard Markdown link syntax - links should point to actual HTML files.
-->

<p>En este apunte rápido voy a revisar cómo cambiar el orden de arranque
con GRUB en Linux. Esto va a permitirnos elegir con qué sistema
operativo inicia la computadora cuándo levanta.</p>
<p>GRUB en inglés quiere decir <a
href="https://www.gnu.org/software/grub/">Grand Unified Bootloader</a>,
lo que puede traducirse por “Cargador de Arranque Unificado”, y es un
programa que funciona entre otras cosas como cargador de arranque para
Linux.</p>
<p>Ese párrafo anterior no dice mucho. A los efectos prácticos, digamos
que en nuestra máquina conviven varios sistemas operativos. Al momento
de iniciar la computadora, GRUB nos da una ventana de tiempo para elegir
cuál de esos sistemas operativos va a utilizar.</p>
<p>De esa lista de sistemas para elegir, siempre hay una opción que
aparece como la principal. En el texto que sigue vamos a modificar esa
primera opción, para que siempre arranque primero el sistema que
queremos.</p>
<p>Lo más importante es que podemos hacer todo esto haciendo algunas
pocas modificaciones en unos archivos de texto.</p>
<h2 id="cómo-cambiar-el-orden-de-inicio-en-grub">Cómo cambiar el orden
de inicio en GRUB</h2>
<p>Los siguientes pasos cubre lo que necesitamos hacer.</p>
<h3 id="cómo-conocer-las-distintas-opciones-de-arranque">Cómo conocer
las distintas opciones de arranque</h3>
<p>Para conocer las opciones de disco de arranque y su orden utilizo el
comando:</p>
<pre><code>awk -F\&#39; &#39;/^menuentry/ {print &quot;Index=&quot; count++ &quot;, Menu Entry: &quot; $2} /^submenu/ {print &quot;Index=&quot; count++ &quot;, Submenu: &quot; $2}&#39; count=0 /boot/grub/grub.cfg</code></pre>
<p>Voy a recibir una respuesta similar a esta:</p>
<pre><code>Index=0, Menu Entry: Linux Mint 21.3 CinnamonIndex=1, Submenu: Advanced options for Linux Mint 21.3 CinnamonIndex=2, Menu Entry: Ubuntu 22.04 LTS Jammy Jellyfish (on /dev/sda3)Index=3, Submenu: Advanced options for Ubuntu 22.04 LTS Jammy Jellyfish (on /dev/sda3)Index=4, Menu Entry: UEFI Firmware Settings</code></pre>
<p>La opción de “índice=0” es la primera opción, la que empieza marcada
por default. A mi me interesa cambiar por la opción de “índice=2”.</p>
<h3 id="cómo-cambiar-la-opción-de-arranque">Cómo cambiar la opción de
arranque</h3>
<p>Luego uso este comando para entrar al archivo que necesito
modificar:</p>
<pre><code>sudo nano /etc/default/grub</code></pre>
<p>Y modifico la linea:</p>
<pre><code>GRUB_DEFAULT=0</code></pre>
<p>Por el número de arranque que quiero que sea el primero, en mi caso
es el representado por el número 2 y queda:</p>
<pre><code>GRUB_DEFAULT=2</code></pre>
<p>Luego de guardar el cambio, lo actualizo con:</p>
<pre><code>sudo update-grub</code></pre>
<p>Ahora puedo reiniciar la computadora, y el disco marcado va a ser el
que se selecciona primero.</p>
<h2 id="cómo-dar-más-tiempo-al-menú-de-grub-al-iniciar-la-máquina">¿Cómo
dar más tiempo al menú de Grub al iniciar la máquina?</h2>
<p>Puedo cambiar el número de segundos que la ventana de Grub me da para
cambiar de opción alterando esta entrada:</p>
<pre><code>GRUB_TIMEOUT=10</code></pre>
<p>En ese caso “10” quiere decir que las opciones van a esperarme 10
segundos. Puedo agregar más o menos tiempo. Si lo marco en “0”, GRUB
selecciona la opción inmediatamente.</p>
<h2 id="conclusión">Conclusión:</h2>
<p>Con esto le doy un cierre a este apunte rápido y bastante practico
para modificar el sistema operativo de arranque con GRUB en Linux.</p>
<p>Seguramente existen otras opciones para conseguir el mismo resultado.
Pero escribí esta entrada mientras intentaba modificar esto, y esta
alternativa consiguió el objetivo.</p>
<p>¿Encontraste algún error en el material? ¿Te resultó de utilidad? Me
gustaría leer tus opiniones, por medio de comentarios o algún correo
electrónico.</p>
<p>La seguimos en el próximo apunte.</p>
<p><strong>¿Comentarios o preguntas?</strong> Escríbeme tu opinión a: <a href="mailto:gustavol@apunteimpensado.com">gustavo@apunteimpensado.com</a></p>]]></description>
        <link>https://apunteimpensado.com/como-cambiar-orden-arranque-grub-linux/</link>
        <guid isPermaLink="true">https://apunteimpensado.com/como-cambiar-orden-arranque-grub-linux/</guid>
        <pubDate>Sun, 22 Sep 2024 00:00:00 </pubDate>
    </item>
    <item>
        <title><![CDATA[Apuntes para HTML Guía básica casi completa]]></title>
        <description><![CDATA[<!--
INDEX_START
This section will be parsed for the left sidebar index/chapter list.
Use standard Markdown link syntax - links should point to actual HTML files.
-->

<p>En este nuevo apunte voy a estudiar los fundamentos de HTML.</p>
<p>¿Por qué aprender sobre HTML ahora? Bueno, realmente no hay ninguna
mala oportunidad para empezar a aprender algo. Todo es nuevo cuándo no
conocemos cómo funciona.</p>
<p>Pero principalmente, encuentro dos ventajas para estudiar un poco de
HTML:</p>
<p>1- No tiene muchos requerimientos para empezar. Necesito solamente
tener un editor de texto sin formato para crear el documento y un
navegador de internet para mostrarme los resultados. Solo con eso ya
puedo empezar a crear cosas nuevas.</p>
<p>2- Incluso si parece difícil al principio, muchas partes de sus
sintaxis se repiten una y otra vez. Luego de un poco de práctica es
sencillo entender lo que estamos haciendo incluso antes de revisarlo en
el navegador.</p>
<p>Y otro detalle importante: puedo avanzar en la creación de un nuevo
sitio web trabajando completamente dentro de mi computadora. De este
modo puedo estudiar y entender cómo funciona desde un directorio. Luego
si quiero puedo publicar la página en un servidor para acceder a la
misma desde internet.</p>
<p>Por eso sin más excusas, lo siguiente es…</p>
<h2 id="qué-es-html">¿Qué es HTML?</h2>
<p>Las siglas HTML quieren decir:</p>
<p>HTML = Hypertext markup language</p>
<p>De esto necesito saber que “Hypertext” viene por la idea de un “texto
con links”. Un texto que se conecta con otros textos.</p>
<p>Y la parte de “markup language” me habla de un lenguaje por
anotaciones. Se trata de una forma de decirle al navegador, por medio de
etiquetas o “tags”, qué es lo que contiene cada parte de la página.</p>
<p>Por ejemplo estas etiquetas crean una estructura donde un a parte de
la página web es el título (heading) y otra parte es un párrafo
(paragraphs).</p>
<p>Este lenguaje lleva varias revisiones desde su creación. La versión
HTML 5.4 es la más actual al momento de escribir todo esto.</p>
<p>El HTML se encarga de la estructura estática de la página web. Cuáles
son los títulos, los bloques de texto, y ese tipo de cosas.</p>
<p>Y para cerrar este apartado, el desarrollo web en HTML por lo general
tiene otros dos lenguajes que lo complementan:</p>
<p>– El lenguaje CSS maneja el estilo del sitio. Por ejemplo tipografía,
colores, columnas y ese tipo de cosas.</p>
<p>– Javascript se encarga de la parte interactiva del sitio, la parte
dinámica y su funcionalidad.</p>
<h2 id="cómo-es-la-estructura-de-html">Cómo es la estructura de
HTML</h2>
<p>Para entender mejor todo esto, nada mejor que empezar trabajando con
un ejemplo.</p>
<p>Primero necesito crear un nuevo documento. Puedo usar cualquier
editor de texto. Pero si quiero tener todos los lujos, como el de
“autocompletar” código, lo mejor va a ser usar alguna alternativa como
Codium o algún editor al estilo de Neovim que pueda expandirse con
plugins.</p>
<p>Lo que sigue es crear el documento, al que tengo que darle una
extensión “.html” para guardarlo.</p>
<p>Y para mi suerte, todo archivo HTML tiene la misma forma:</p>
<pre class="language-html"><code>&lt;!DOCTYPE html&gt;

&lt;html&gt;
  &lt;head&gt; &lt;/head&gt;

  &lt;body&gt;&lt;/body&gt;
&lt;/html&gt;</code></pre>
<h3 id="qué-significa-doctype-en-html">Qué significa DOCTYPE en
HTML</h3>
<p>La primera linea de todo documento html se conoce como “doctype”.</p>
<pre class="language-html"><code>&lt;!DOCTYPE html&gt;</code></pre>
<p>Este marcación “doctype” identifica el tipo de archivo.</p>
<h3 id="qué-es-la-etiqueta-html">Qué es la etiqueta HTML</h3>
<p>La etiqueta es la raíz del documento.</p>
<pre class="language-html"><code>&lt;html&gt;
  ...código...
&lt;/html&gt;</code></pre>
<p>Todo lo que se encuentra entre esos dos tags es el código del
documento. Este tag siempre esta presente, abre y cierra el archivo.</p>
<p>A veces puede aparecer como:</p>
<pre class="language-html"><code>&lt;html lang=&quot;es&quot;&gt;
  ...código...
&lt;/html&gt;</code></pre>
<p>En este caso, el atributo “lang” identifica el idioma en el que se
encuentra escrita la página, por ejemplo “es” por “español”.</p>
<p>En su interior, la etiqueta “html” contienen otros dos tags: Head y
Body.</p>
<h4 id="qué-es-la-etiqueta-head-en-html">Qué es la etiqueta Head en
HTML</h4>
<p>En el interior de las etiquetas Head:</p>
<pre class="language-html"><code>&lt;head&gt;
  ...código...
&lt;/head&gt;</code></pre>
<p>Se puede encontrar información que no se muestra directamente en el
navegador, pero si es información que le dice al navegador cómo tiene
que interpretar la página.</p>
<p>Esta información incluye metadatos o links a hojas de estilo en
CSS.</p>
<p>Entre esos tags que puedo encontrar dentro de “Head”, existe por
ejemplo “Title” que es una etiqueta obligatoria del sitio.</p>
<pre class="language-html"><code>&lt;title&gt;Nombre del sitio&lt;/title&gt;</code></pre>
<p>El nombre incluido dentro de las etiquetas “Title” aparece por
ejemplo arriba en la barra del navegador, cuando visitamos la página
web.</p>
<p>Otra etiqueta que aparece dentro de head es una etiqueta llamada
“meta”, se trata de un tag que no tiene cierre. Se refiere a la
codificación del archivo:</p>
<pre class="language-html"><code>&lt;meta charset=&quot;UTF-8&quot; /&gt;</code></pre>
<p>Lo que hace es indicar cómo se van a codificar los caracteres,
unificando estándares entre los distintos navegadores.</p>
<h4 id="la-etiqueta-body-en-html">La etiqueta Body en HTML</h4>
<p>Dentro de las etiquetas:</p>
<pre class="language-html"><code>&lt;body&gt;&lt;/body&gt;</code></pre>
<p>Se incluye todos los elementos que van a mostrarse en mi sitio.</p>
<p>Esta etiqueta comienza directamente luego del cierre de “head”. Y le
sigue luego el cierre de la etiqueta html.</p>
<h2 id="sintaxis-de-html-ultra-resumen">Sintaxis de HTML: ultra
resumen</h2>
<p>Según lo que pude entender explicando el ejemplo anterior, en un
documento HTML voy a encontrar diferentes contenidos que se encuentran
acompañados de etiquetas.</p>
<p>La sintaxis de este lenguaje se maneja agregando la información
acompañada de “tags” o etiquetas.</p>
<p>Básicamente en este primer momento tengo que recordar que existen dos
tipos de etiquetas. Un tipo de etiquetas se cierra y otro tipo no. Las
etiquetas que no se cierran se consideran etiquetas vacías.</p>
<h3 id="etiquetas-que-abren-y-cierran">Etiquetas que abren y
cierran:</h3>
<p>Un ejemplo de este tipo de tag puede ser la etiqueta de párrafo:</p>
<pre><code>&lt;p&gt; este es un párrafo &lt;/p&gt;</code></pre>
Se puede notar que la etiqueta “
<p>
” abre el contenido y “
</p>
<p>” lo cierra. Ya había encontrado este tipo de tag antes, por ejemplo
al hablar de “body”. Cuando una etiqueta se abre, siempre tiene que
cerrarse en algún punto.</p>
<p>Las etiquetas ya vienen establecidas, no es posible crearlas. No es
necesario recordar todas y cada una de las etiquetas, algunas se
utilizan muchas veces y otras solo dependiendo de un caso en
particular.</p>
<p>Otros detalle importante es que las etiquetas se escriben siempre en
minúsculas.</p>
<p>Y también es bueno recordar que las etiquetas pueden “anidarse”,
pueden existir una dentro de otra. Esto también pude notarlo antes, por
ejemplo:</p>
<pre><code>&lt;head&gt;&lt;title&gt; Nombre del sitio&lt;/title&gt;&lt;/head&gt;</code></pre>
<h3 id="etiquetas-vacías">Etiquetas <strong>vacías</strong>:</h3>
<p>Este tipo de tag no tiene cierre. Se conocen también como “Empty
Tags” o “self-closing” (auto cierre).</p>
<p>No hay contenido en el interior de estas etiquetas, por lo que no es
necesario cerrarlas. Pero si pueden tener atributos.</p>
<p>Un ejemplo de esto puede ser:</p>
<pre><code>&lt;link rel=&quot;stylesheet&quot; href=&quot;styles.css&quot;&gt;</code></pre>
<p>En este caso la etiqueta “link” contiene una referencia a un archivo
externo, una hoja con estilos CSS. La etiqueta no tiene contenido, por
lo que no tiene otro tag de cierre.</p>
<p>Lo que si tiene el ejemplo son dos atributos: el atributo “rel”
especifica que se trata de una hoja de estilos y el atributo “href”
especifica la dirección al nombre del archivo.</p>
<p>Otro ejemplo de etiqueta vacía puede ser:</p>
<pre><code>&lt;meta charset=&quot;UTF-8&quot;&gt;</code></pre>
<p>Un etiqueta que ya revisé con anterioridad. Hay varias etiquetas de
esta forma, tampoco es necesario conocerlas a todas, solamente alcanza
con saber como es su forma.</p>
<h3 id="atributos-en-html">Atributos en HTML:</h3>
<p>Los atributos ( o “Attributes” en inglés) son una forma de agregarle
datos extra a un tag.</p>
<p>Modifican la forma en que un navegador interpreta el contenido. El
nombre de los atributos se escriben entre comillas. Y tampoco puedo
inventar nada en esto, cada tipo de etiqueta tiene sus propios tipos de
atributos preestablecidos.</p>
<p>Para revisar un ejemplo que ya escribí antes:</p>
<pre><code>&lt;meta charset=&quot;UTF-8&quot;&gt;</code></pre>
<p>En este caso tengo la etiqueta meta, que es un tag vacío. Aquí tengo
el atributo charset, que indica “UTF-8” como el tipo de codificación
unicode que utiliza la página.</p>
<p>Hay también más ejemplos de atributos, que voy a ir encontrando con
el desarrollo de mi sitio web.</p>
<h3 id="comentarios-en-html">Comentarios en HTML:</h3>
<p>Igual que en otros lenguajes de programación, HTML me permite dejar
un mensaje por fuera del código.</p>
<pre><code>&lt;!-- contenido --&gt;</code></pre>
<p>Estos mensajes no son para que los interprete el navegador, son para
que puedan leerlos las personas que revisan el código. Por ejemplo:</p>
<pre><code>&lt;!-- Dentro de las etiquetas &quot;Head&quot; van los metadatos --&gt;</code></pre>
<h2 id="revisando-mi-primer-sitio-web-en-html">Revisando mi primer sitio
web en HTML:</h2>
<p>Si todo va bien, ya tengo creado un documento, digamos que se llama
“inicio.html” por ponerle algún nombre.</p>
<p>Y si sumo todo lo anterior, el interior del documento se parece a
esto:</p>
<pre class="language-html"><code>&lt;!DOCTYPE html&gt;
&lt;html&gt;
  &lt;head&gt;
    &lt;!-- Dentro de la etiqueta &quot;Head&quot; van los metadatos --&gt;
    &lt;meta charset=&quot;UTF-8&quot; /&gt;
    &lt;title&gt;Mi sitio de ejemplo&lt;/title&gt;
  &lt;/head&gt;

  &lt;body&gt;
    &lt;!-- Dentro de la etiqueta &quot;body&quot; se muestra el contenido que aparece en la página --&gt;
    &lt;h1&gt;Este es un nuevo blog&lt;/h1&gt;
    &lt;p&gt;Algo de información para una página web que recien comienza.&lt;/p&gt;
  &lt;/body&gt;
&lt;/html&gt;</code></pre>
<p>Lo que puedo hacer ahora es abrir este archivo con un navegador, por
ejemplo con la opción “abrir con” o lanzando el archivo directamente
sobre la barra de herramientas del navegador.</p>
<p>Haciendo esto voy a poder ver el sitio web en su estado actual.</p>
<h2 id="recursos-para-saber-más-sobre-html">Recursos para saber más
sobre HTML</h2>
<p>No voy a sorprender a nadie si digo que realmente existen millones de
cosas sobre este tema para leer y estudiar. Después de todo lo de HTML
no es un asunto precisamente nuevo.</p>
<p>¿Dónde puedo encontrar un texto verdaderamente completo para seguir
aprendiendo?</p>
<p>Existe una documentación oficial de HTML. Esa documentación la
mantiene actualziada una organización internacional llamada World Wide
Web Consortium (W3C).</p>
<p><a href="https://html.spec.whatwg.org/multipage/">Se puede acceder a
ese material siguiendo este enlace.</a></p>
<p>Así que como siempre, si en algún momento mis apuntes se vuelven
confusos o insuficientes, lo mejor es referirse a la documentación
oficial.</p>
<h2 id="describiendo-la-forma-del-html">Describiendo la forma del
HTML</h2>
<p>Según entiendo la idea es darle un sentido a todo lo que se encuentra
en una la página web por medio de etiquetas.</p>
<p>Utilizando HTML le asigno etiquetas a las distintas partes de un
sitio. Estas etiquetas le permiten a los navegadores y buscadores
entender la página, pero también la vuelven legible para cualquier
humano que revise este código.</p>
<p>Es por eso que también se dice que HTML es un “lenguaje
estructurado”. Las etiquetas marcan la estructura que cumple cada
elemento.</p>
<p>Luego de señalar cada parte con uno de estos tags, puedes agregarle
estilo de diseño con CSS (“Hojas de estilo en cadena).</p>
<h2 id="agrupando-los-elementos-comunes-del-sitio">Agrupando los
elementos comunes del sitio</h2>
<p>Todo este tópico aparece muchas veces mencionado por el nombre en
inglés de “Common semantic grouping elements”. Esto es en castellano
“Agrupación semántica de elementos comunes”.</p>
<p>En lo que a mi respecta, ni siquiera se que quiere decir “semántico”.
En un rápido viaje al diccionario, al parecer quiere decir algo como
“estudiar el significado de las palabras”.</p>
<p>Una vez más, lo más importante para recordar parece ser esto: Las
etiquetas no “acomodan” las partes del sitio en su lugar ni les dan
estilo, pero si les dan estructura. Enseña que es cada cosa.</p>
<p>Ya en el anterior texto revisé algunas características de las
etiquetas. Algunas tienen que ser abiertas y cerradas, mientras que
otras permanecen siempre abiertas.</p>
<h2 id="algunas-de-las-etiquetas-más-comunes">Algunas de las etiquetas
más comunes</h2>
<p>Existen varias etiquetas, pero estas son unas de las más usadas:</p>
<h3 id="la-etiqueta-header">La etiqueta “Header”</h3>
<p>Según la documentación de (W3C):</p>
<blockquote>
<p>The header element represents a group of introductory or navigational
aids.manual html w3c</p>
</blockquote>
<p>Esto es que “el elemento header representa un grupo de ayudas
introductorias o de navegación”.</p>
<p>La misma se encuentra de esta forma:</p>
<pre><code>&lt;header&gt; &lt;/header&gt;</code></pre>
<p>En teoría puedo pensar que, al poder ser traducida la palabra
“header” como una “cabecera”, esta etiqueta tiene que aparecer al
principio de las distintas páginas de un sitio web.</p>
<p>Y la mayoría de las veces ocurre de esa forma, repitiéndose más o
menos igual en cada página. Contiene cosas como el logo y los títulos,
se supone que el header se ocupa de nuclear ese tipo de información
introductoria para la navegación.</p>
<p>Sin embargo tengo que recordar que las etiquetas no se refieren a la
posición de algo en el diseño. Puede existir más de un header en una
determinada página, puede aparecer incluso usado dentro de otras
etiquetas siempre que cumpla esa función de albergar datos
introductorios.</p>
Otra cosa que necesito tener en mente: aunque el nombre es similar,
<head>
y
<header>
<p>no son lo mismo en el contexto del sito.</p>
Dentro de la etiqueta
<head>
va información que no es contenido del documento, como por ejemplo
metadatos. Pero lo que va dentro de
<header>
<p>si es parte de lo que se enseña en la página.</p>
<h3 id="la-etiqueta-nav">La etiqueta nav</h3>
<p>La etiqueta “nav” aparece de esta forma</p>
<pre><code>&lt;nav&gt; &lt;/nav&gt;</code></pre>
<p>En inglés se conoce por “”navigation bar” y es el menú de navegación
de nuestra página.</p>
<p>Por lo general va dentro de la etiqueta “header”, y del mismo modo la
mayoría de las veces se repite constante en toda la página web.</p>
<p>Siendo el menú de de navegación, contiene los links para ir saltando
entre partes del sitio. Por ejemplo, la página de “información”,
“contacto” y similares. Aunque esto depende de lo que necesitemos en
cada caso, puede ser links a nuestro gusto.</p>
<h3 id="footer">Footer</h3>
<pre><code>&lt;footer&gt;&lt;/footer&gt;</code></pre>
<p>Se trata del pie de página, siendo de esta forma por lo general va al
final del sitio. Y de forma similar a “Header”, aparece casi igual en
todas las partes del sitio.</p>
<p>Contiene cosas como links importantes, mapa del sitio, datos de
contacto, metadata y ese tipo de cosas.</p>
<h3 id="main">Main</h3>
<p>La documentación dice:</p>
<blockquote>
<p>The main element represents the dominant contents of the
document.</p>
<p>manual w3c</p>
</blockquote>
<p>Este elemento representa a los contenidos dominantes del
documento.</p>
<p>Aparece de la siguiente forma:</p>
<pre><code>&lt;main&gt; &lt;/main&gt;</code></pre>
<p>Y en “main” aparece el contenido principal del sitio, que es
diferente en cada caso. Es único por cada página.</p>
Para simplificarlo, dicho de otro modo es todo lo que no forma parte ni
esta incluido en otras etiquetas como
<header>
,
<nav>
o
<footer>
<p>.</p>
<h3 id="la-etiqueta-article">La etiqueta “Article”</h3>
<p>Aparece de esta forma:</p>
<pre><code>&lt;article&gt;&lt;/article&gt;</code></pre>
<p>Es una etiqueta que encierra contenido que tiene sentido por su
propia cuenta, como por ejemplo todo el texto dentro de una publicación
específica de un blog.</p>
<p>Y el manual dice:</p>
<blockquote>
<p>The article element represents a complete, or self-contained,
composition in a document, page, application, or site and that is, in
principle, independently distributable or reusable, e.g. in syndication.
This could be a forum post, a magazine or newspaper article, a blog
entry, a user-submitted comment, an interactive widget or gadget, or any
other independent item of content.</p>
<p>manual w3c</p>
</blockquote>
<p>Es una etiqueta que encierra contenido que tiene sentido por su
propia cuenta, como por ejemplo todo el texto dentro de una publicación
específica de un blog. Pero puede representar también algo como un
widget en el sitio.</p>
<h3 id="la-etiqueta-section">La etiqueta “Section”</h3>
<pre><code>&lt;section&gt; &lt;/section&gt;</code></pre>
<p>La etiqueta “section” (sección) agrupa contenido relacionado. ¿Dónde
usarla? Por ejemplo en una parte secundaria de un página individual o
para crear un “bloque de sentido”.</p>
<p>El manual dice:</p>
<blockquote>
<p>Examples of sections would be chapters, the various tabbed pages in a
tabbed dialog box, or the numbered sections of a thesis. A web site’s
home page could be split into sections for an introduction, news items,
and contact information.manual w3c</p>
</blockquote>
<p>Esto es que un ejemplo de sección pueden ser los capítulos de un
libro. O también pueden ser secciones las partes de la página de inicio
de un sitio web.</p>
<h3 id="la-etiqueta-paragraph">La etiqueta
<strong>Paragraph</strong></h3>
<p>Es la etiqueta “parrafo” y aparece de la siguiente forma:</p>
<pre><code>&lt;p&gt; Esto es un párrafo.&lt;/p&gt;</code></pre>
<p>Puede tener texto o imágenes. Y es una etiqueta que se repite todas
las veces que sea necesario, por cada párrafo en el sitio.</p>
<h3 id="etiqueta-headings-en-html">Etiqueta Headings en HTML</h3>
<p>La etiqueta para los títulos. Puede aparecer por ejemplo de algunas
de estas formas:</p>
<pre><code>&lt;h1&gt; Primer titulo&lt;/h1&gt;</code></pre>
<pre><code>&lt;h2&gt;Segundo subtitulo&lt;/h2&gt;</code></pre>
<p>Se trata de distintos niveles de subtítulos, ordenados en importancia
decreciente desde el h1 hasta el h6.</p>
<p>No es lo mismo que el “font size” o el tamaño de la letra. No se
utilizan para darle estilo a un texto, pero si para marcar la
importancia de algo dentro de la estructura.</p>
<p>Se puede notar eso dentro de este mismo apunte por ejemplo, cada vez
que me refiero a una nueva etiqueta uso un título de nivel “h3”.</p>
<p>Por ejemplo, este que sigue es un “heading nivel 3”:</p>
<h3 id="atributos-de-imagen-en-html">Atributos de imagen en HTML</h3>
<p>Las imágenes (Images) tienen una etiqueta y dos atributos.</p>
<p>Su etiqueta no tiene elemento de cierre, y es:</p>
<pre><code>&lt;img&gt;</code></pre>
<p>Los atributo son:</p>
<ul>
<li><p>-src: el camino (source) relativo o absoluto al directorio donde
se encuentra la imagen.</p></li>
<li><p>– alt: El texto alternativo que acompaña. Sirve por si la misma
no llega a cargarse o para que pueda mencionarla un lector de
pantalla.</p></li>
</ul>
<p>Ejemplo:</p>
<pre><code>&lt;img src=&quot;lapiz.jpg&quot; alt=&quot;un lapiz de dibujo&quot;&gt;</code></pre>
<h3 id="cómo-crear-listas-en-html">Cómo crear Listas en HTML:</h3>
<p>Se trata de una forma de ordenar la información. Pueden ser listas
ordenadas o desordenadas.</p>
Para una lista ordenada tengo las etiquetas
<ol>
y
<li>
<p>de la siguiente manera:</p>
<pre><code>        &lt;ol&gt; &lt;li&gt;item 1&lt;/li&gt;
            &lt;li&gt;item 2&lt;/li&gt;
            &lt;li&gt;item 3&lt;/li&gt;
            &lt;li&gt;item 4&lt;/li&gt;
        &lt;/ol&gt;</code></pre>
Para armar una lista sin orden tengo las etiquetas
<ul>
y
<li>
<p>de esta forma:</p>
<pre><code> &lt;ul&gt; &lt;li&gt;item 1&lt;/li&gt;
            &lt;li&gt;item 2&lt;/li&gt;
            &lt;li&gt;item 3&lt;/li&gt;
            &lt;li&gt;item 4&lt;/li&gt;
        &lt;/ul&gt;</code></pre>
<h3 id="texto-preformateado">Texto preformateado</h3>
<pre><code>&lt;pre&gt; &lt;/pre&gt;</code></pre>
<p>También puede aparecer llamada como “preformated text”, sirve para
preservar los espacios en blanco o evitar cualquier otro tipo de
interpretación de texto enriquecido.</p>
<p>Yo por lo general uso esta etiqueta para marcar los ejemplos en el
blog, de esta forma:</p>
<pre><code>Esto es el ejemplo.</code></pre>
<h3 id="etiquetas-de-énfasis">Etiquetas de énfasis</h3>
<p>Estas etiquetas se utilizan para destacar palabras dentro de
párrafos. Sirve para decirle al navegador si un texto es en itálica o en
negrita.</p>
<p>Para itálica se utiliza la etiqueta <em>:</p>
<pre><code>&lt;em&gt; &lt;/em&gt;</code></pre>
<p>La etiqueta <strong> es para texto en negrita:</p>
<pre><code>&lt;strong&gt; &lt;/strong&gt;</code></pre>
<h2 id="cómo-agregar-links-en-html">Cómo agregar links en HTML</h2>
<p>La etiqueta para marcar los links en un sitio web es:</p>
<pre><code>&lt;a&gt; &lt;/a&gt;.</code></pre>
<p>Pero su utilización tiene algunas particularidades. Necesita del
atributo “href” para poder funcionar.</p>
<pre><code>&lt;a href=&quot;http://www.sitioweb.com/&quot;&gt;Hacer click en este texto&lt;/a&gt;</code></pre>
<p>El atributo href enseña el destino del link: puede tratarse de una
URL absoluta, URL relativa o un anchor.</p>
<h3 id="el-atributo-target">El atributo Target</h3>
<p>Este atributo se desprende directamente de lo anterior. Señala si un
link tiene que abrirse en una ventana nueva o en la ventana actual.</p>
<p>Si lo le agrego este atributo, el link se abre en la ventana actual.
Para una nueva ventana utilizo “_blank” de esta forma:</p>
<pre><code>&lt;a href=&quot;http://www.sitioweb.com/&quot; target=&quot;_blank&quot;&gt;Hacer click en este texto&lt;/a&gt;</code></pre>
<h2 id="conclusión">Conclusión:</h2>
<p>Con esto le doy un cierre al apunte sobre fundamentos de HTML.</p>
<p>Es cierto que es solamente un muestrario de algunas etiquetas que se
utilizan con mucha frecuencia en un sitio web. Las etiquetas se pueden
probar por separado, pero ganan mayor valor cuando las vemos
interactuando al mismo tiempo en un sitio.</p>
<p>Cualquier error que encuentres en este texto, por favor avisame para
que pueda corregirlo.</p>
<p>La seguimos en el siguiente apunte.</p>
<p><strong>¿Comentarios o preguntas?</strong> Escríbeme tu opinión a: <a href="mailto:gustavol@apunteimpensado.com">gustavo@apunteimpensado.com</a></p>]]></description>
        <link>https://apunteimpensado.com/apuntes-para-html-guia-basica-completa/</link>
        <guid isPermaLink="true">https://apunteimpensado.com/apuntes-para-html-guia-basica-completa/</guid>
        <pubDate>Sat, 21 Sep 2024 00:00:00 </pubDate>
    </item>
    <item>
        <title><![CDATA[Guía casi definitiva para utilizar Neovim y LaTeX en la universidad]]></title>
        <description><![CDATA[<!--
INDEX_START
This section will be parsed for the left sidebar index/chapter list.
Use standard Markdown link syntax - links should point to actual HTML files.
-->

<p>Este apunte le da forma a lo que voy a dar en llamar mi “Guía casi
definitiva para utilizar Neovim y Latex en la universidad”.</p>
<p>Ya sea que necesites escribir un ensayo argumentativo, una tesis, una
tesina o un sencillo informe, este apunte va a ayudarte en cualquier
contexto o proyecto académico.</p>
<p>En realidad todo este texto puede ayudar a cualquier persona, dentro
o fuera del contexto de la universidad. Pero el ángulo de la universidad
vuelve al tema un poco más amable para el marketing de las redes y todo
eso.</p>
<p>Antes de continuar recuerden que estoy escribiendo este material
utilizando un sistema operativo Linux. Los detalles pueden ser
diferentes en otros sistemas.</p>
<p>Dentro de todo lo posible voy a buscar las soluciones más sencillas a
los problemas que encontramos. Dónde puede evitar agregar un plugin
extra, voy a evitarlo. La idea es resolver nuestros problemas de la
forma más directa posible.</p>
<p>Y otro detalle importante: mucho de lo que vamos a hacer ahora nos va
a ayudar también a poder utilizar otros lenguajes además de LaTeX.
Varias de las herramientas que vamos a instalar son compartidas por
otros lenguajes de programación.</p>
<p>Ahora sin más introducción…</p>
<h2 id="lista-de-cosas-por-hacer-antes-de-empezar">Lista de cosas por
hacer antes de empezar</h2>
<p>Antes de empezar a modificar cosas en Neovim que tengan que ver con
LaTeX, necesitamos cubrir algunos puntos básicos para dejar todo
listo.</p>
<p>Entre eso tenemos:</p>
<h3 id="instalar-neovim">Instalar Neovim:</h3>
<p>Sin tener esto en el equipo no podemos hacer nada. <a
href="https://apunteimpensado.com/como-instalar-neovim-desde-el-codigo-fuente-en-linux/">Tengo
un apunte sobre cómo instalar Neovím desde el código fuente.</a></p>
<p>Instalar el programa de esa forma es una buena opción para tener
siempre la versión más actualizada.</p>
<h3 id="intalar-texlive">Intalar TexLive</h3>
<p>Antes de empezar necesitamos <a
href="https://apunteimpensado.com/como-instalar-latex-texlive-reciente-linux/">instalar
TexLive a nivel global en el sistema.</a></p>
<p>En ese apunte anterior van a encontrar cómo instalar la última
versión directamente desde la fuente oficial.</p>
<h2
id="organizar-el-servidor-de-lenguaje-con-nvim-lspconfig-y-texlab">Organizar
el servidor de lenguaje con nvim-lspconfig y Texlab</h2>
<p>Este momento de nuestro proyecto esta dividido en dos partes,
cubierto en un único apunte.</p>
<p>Ahora vamos a necesitar instalar plugins, y para ayudarnos con eso <a
href="https://apunteimpensado.com/como-instalar-plugins-de-forma-manual-en-neovim/">tengo
este apunte sobre cómo instalar plugins en Neovim de forma
manual.</a></p>
<p>En un resumen muy rápido, Neovim va a actuar como un cliente para un
servidor de lenguaje. En terminos prácticos esto va a darnos
funcionalidades extra como revisión de errores en la sintaxis.</p>
<p><a
href="https://apunteimpensado.com/como-utilizar-servidores-lenguaje-lsp-neovim-lspconfig/">En
este apunte tengo toda la información necesaria para instalar
nvim-lspconfig y Texlab.</a></p>
<p>Otra vez en el espiritu de resumir esto lo más posible:</p>
<ol type="1">
<li><p>Vamos a instalar <a
href="https://github.com/neovim/nvim-lspconfig">el plugin
nvim-lspconfig</a> dentro del directorio indicado del programa
nvim.</p></li>
<li><p>Necesitamos instalar de forma global desde la terminal de Linux
<a href="https://github.com/latex-lsp/texlab">el servidor de lenguaje
Texlab.</a></p></li>
</ol>
<h2 id="primer-punto-de-control">Primer punto de control</h2>
<p>Si todo funcionó correctamente hasta el momento, voy a tener que
poder:</p>
<ol type="1">
<li><p>Abrir Neovim en mi equipo.</p></li>
<li><p>Crear un archivo llamado “ensayo.tex” para empezar a
escribir.</p></li>
<li><p>Utilizar dentro de Neovim el comando:</p></li>
</ol>
<pre><code>:checkhealth lsp</code></pre>
<p>Con eso voy a saber si Neovim puede comunicarse correctamente con
Texlab.</p>
<p>Si tengo todo organizado como hasta este punto de control, voy a
encontrar que puedo:</p>
<ul>
<li><p>Revisar que el texto se encuentra coloreado según la
sintaxis.</p></li>
<li><p>Tengo la opción de auto completar texto en relación al código.
Por ejemplo digamos que escribo:</p></li>
</ul>
<p>Y luego presiono (estando en “insert mode”) “Ctrl + x Ctrl + o”.</p>
<p>Voy a ver que se despliega un nuevo menú oferciendome opciones para
autocompletar.</p>
<ul>
<li>Diagnóstico de errores: por ejemplo si escribo un ejemplo y me falta
un corchete, Texlab va a avisarme del error con un mensaje en la
pantalla.</li>
</ul>
<p>¿Tenemos suficiente con esto para empezar a escribir nuestros
trabajos universitarios? Posiblemente si.</p>
<p>Pero creo que todavía podemos mejorar algunas cosas.</p>
<h2 id="formas-de-compilar-nuestro-documento-latex-desde-neovim">Formas
de compilar nuestro documento LaTex desde Neovim</h2>
<h3 id="compilado-desde-texlab">Compilado desde Texlab</h3>
<p>¿Recordás el documento “texlab.lua” que antes nvim-lspconfig puso en
nuestro sistema?</p>
<p>Dentro de ese codigo vamos a encontrar una parte de commandos que
podemos utilizar directamente en Neovim.</p>
<p>Por ejemplo tenemos:</p>
<pre><code>TexlabBuild = { function() buf_build() end, description = ‘Build the current buffer’, },</code></pre>
<p>Esto quiere decir que si utilizo el comando:</p>
<pre><code>:TexlabBuild</code></pre>
<p>Vamos a poder compilar el documento para empezar a revisarlo en
PDF.</p>
<h3 id="vista-previa-con-pdf-para-latex-en-neovim">Vista previa con PDF
para LaTeX en Neovim</h3>
<p>No vamos a poder hacer mucho si no tenemos una opción para empezar a
visualizar el estado actual de nuesro proyecto en PDF cada vez que lo
necesitamos.</p>
<p>Para esto vamos a necesitar compilar el documento al momento de
guardarlo.</p>
<p><a href="https://github.com/latex-lsp/texlab/wiki/Previewing">La wiki
de Texlab tiene un apartado que trata sobre previsualizar.</a></p>
<p>Muchas guías que estuve leyendo sobre el asunto recomiendan utilizar
<a href="https://pwmt.org/projects/zathura/">el visualizador de
documentos llamado Zathura.</a></p>
<p>Otras de las opciones que tenemos es utilizar el programa <a
href="https://okular.kde.org/">el programa “Okular”, que cumple una
función similar y es más completo.</a></p>
<p>Voy a revisar un poco más cada alternativa.</p>
<h4 id="opción-1-instalar-okular">Opción 1: instalar “Okular”</h4>
<p>Aunque no utilicé mucho este programa, quiero mencionarlo porque
tiene dos grandes facilidades que facilitan bastante lo que estamos
haciendo. Y estas ventajas son:</p>
<p>1- Es sencillo de instalar en un solo movimiento. Puede que no sea la
version más actual, pero si estamos usando un sistema operativo en base
a Debian, como Ubuntu o Mint, podemos hacer:</p>
<pre><code>sudo apt install okular</code></pre>
<p>Y ya vamos a tenerlo funcionando.</p>
<p>2- Utilizando el programa solo para abrir archivos PDF, se puede
utilizar para remarcar texto sobre los documentos.</p>
<p>De las dos opciones que presento esta es la más “tradicional” por
decirlo de alguna forma, rápido de instalar y con una interfaz amable
para su utilización.</p>
<p>La forma de integrar Okular con Texlab se encuentra también en ese
enlace que puse más arriba, y es muy similar a la forma de integrar
Zathura que voy a describir a continuación.</p>
<h4 id="instalar-zathura">Instalar Zathura</h4>
<p>La forma más directa de instalar este programa, usando el sistema
“apt”, es de esta forma:</p>
<pre><code>sudo apt install zathura</code></pre>
<p>Y con eso voy a tener una versión funcional pero algo anticuada del
programa, en la mayoría de los casos.</p>
<p>Zathura se utiliza de una forma muy similar a Neovim. Es un programa
que nos va a demandar algo más de práctica, porque todo se Hace por
medios de comandos y atajos del teclado.</p>
<p>¿Y qué hacemos si queres la última versión?</p>
<p>En ese caso vas a tener que prepararte para pasar un par de horas
revisando tener los paquetes y dependencias correctos.</p>
<p>Si realmente queremos usar Zathura en su versión más actualizada, <a
href="https://pwmt.org/projects/zathura/download/">para eso descargo la
última versión de esta página.</a></p>
<p>Y luego <a
href="https://pwmt.org/projects/zathura/installation/">sigo estas
instrucciones.</a>.</p>
<p><a href="https://github.com/pwmt/zathura">Estas otras instruciones
detallan un poco mejor las librerias extra que vamos a
necesitar.</a></p>
<p><a href="https://pwmt.org/projects/zathura-pdf-poppler/">Por supuesto
luego vamos a necesitar instalar el plugin zathura-pdf-poppler para
poder abrir los archivos PDF</a></p>
<p>El asunto es que vamos a tener que consguir bastantes dependencias
extra antes, y eso puede tomar un buen rato. Yo lo instalé de las dos
formas para probarlo, pero al menos en un primer momento no encontré
diferencias en la forma que interactuan con TexLaB y Neovim. En los dos
casos se comunicaron de iday vuelta sin inconvenientes.</p>
<h3 id="configurar-texlab-y-zathura">Configurar Texlab y Zathura</h3>
<p>Entonces es seguro que antes tenía en esto en mi “init.lua”:</p>
<pre class="language-lua"><code>require’lspconfig’.texlab.setup{}</code></pre>
<p>Pero ahora voy a reemplazarla por:</p>
<pre class="language-lua"><code>require(&#39;lspconfig&#39;).texlab.setup({
    settings = {
      texlab = {
        build = {
          onSave = true,
          forwardSearchAfter = true,
        },
        forwardSearch = {
          executable = &quot;zathura&quot;,
          args = {&quot;--synctex-forward&quot;, &quot;%l:1:%f&quot;, &quot;%p&quot;},
        },
      },
    },
  })
</code></pre>
<p>Ahora cada vez que haga un guardado del documento, me va a aparecer
un archivo dentro de Zathura mostrandome los cambios.</p>
<p>¿Cómo funciona esto en la práctica? La actualización en la
visualización no se hace cada vez que se regenera el programa, en el
sentido que tengo que cerrar el programa Zathura para que vuelva a
abrirse con los cambios. Y lo mismo ocurre con Okular.</p>
<p>Puede ser que sea posible convertir esta visualización en algo “en
vivo” por medio de un plugin. O puede ser que me falte algún detalle en
mi propia configuración.</p>
<p>De esta forma cuando usamos el comando “:w” para guardar, Neovim
regenera nuestro proyecto de LaTeX. pero la instancia de Zathura no se
actualiza por si sola. Si cerramos Zathura, vuelve a abrirse ahora con
el texto actualizado. No es una molestia realmente.</p>
<p>Entonces descontando eso de que el PDF no refleja lo que escribimos
“en directo”, todo funciona muy bien y de momento es la mejor solución
que tengo sin herramientas extra.</p>
<h2 id="navegar-entre-neovim-y-el-documento-en-preview">Navegar entre
Neovim y el documento en preview</h2>
<ul>
<li>Búsqueda directa:</li>
</ul>
<p>Antes escribimos este código:</p>
<pre class="language-lua"><code>{executable = &quot;zathura&quot;,
args = {&quot;--synctex-forward&quot;, &quot;%l:1:%f&quot;, &quot;%p&quot;},</code></pre>
<p>Lo que eso nos permite es, según en que parte se encuentre el cursor
dentro de nuestro docuento en Neovin, esa parte se va a ver resaltada en
el documento abierto en Zathura.</p>
<p>Según el programa visualizador estos detalles cambián, por ejemplo
para Okular el cpodigo es ligeramente diferente y lo encontramos en la
wiki de Texlab en la parte de previewing.</p>
<ul>
<li>Búsqueda Indirecta:</li>
</ul>
<p>Ahora digamos que queremos hacer lo contrario, mover el cursor dentro
de Zathura y verlo reflejado dentro de Neovim.</p>
<p>Para eso buscamos (o creamos) el archivo “zathurarc” en este
directorio, que también tenemos que crear de ser necesario:</p>
<pre><code>~/.config/zathura/zathurarc</code></pre>
<p>Ese es uno de los directorios dónde el programa busca sus
configuraciones, por ejemplo podemos cambiar el tamaño de la pantalla y
otras cosas más.</p>
<p>Dentro de ese documento escribimos:</p>
<pre><code>set synctex trueset synctex-editor-command &quot;texlab inverse-search -i %{input} -l %{line}&quot;</code></pre>
<p>Y listo, ahora si hacemos “Ctrl+Click” en alguna parte del documento
de Zathura, el cursor dentro de Neovim se pone sobre la misma linea.</p>
<h2 id="conclusión">Conclusión</h2>
<p>Con esto le doy un cierre a mi “Guía casi definitiva para utilizar
Neovim y LaTeX en la universidad.”</p>
<p>Se trata de una guía “casi definitiva” porque todavía le estoy
agregando información. Lo importante a mi entender es que con el
material compartido en este texto podemos pasar de tener una
configuración nueva de Neovim a una que puede producir textos con Latex
en muy poco tiempo.</p>
<p>¿Encontraste algún error en el apunte? ¿Utilizás Neovim en conjunto
con LaTeX? Me gustaría conocer tus opiniones.</p>
<p>La seguimos en el próximo apunte.</p>
<p><strong>¿Comentarios o preguntas?</strong> Escríbeme tu opinión a: <a href="mailto:gustavol@apunteimpensado.com">gustavo@apunteimpensado.com</a></p>]]></description>
        <link>https://apunteimpensado.com/guia-utilizar-neovim-latex-universidad/</link>
        <guid isPermaLink="true">https://apunteimpensado.com/guia-utilizar-neovim-latex-universidad/</guid>
        <pubDate>Mon, 02 Sep 2024 00:00:00 </pubDate>
    </item>
    <item>
        <title><![CDATA[Cómo utilizar servidores de lenguaje (LSP) en Neovim con nvim-lspconfig]]></title>
        <description><![CDATA[<!--
INDEX_START
This section will be parsed for the left sidebar index/chapter list.
Use standard Markdown link syntax - links should point to actual HTML files.
-->
</li>
</ul>
<p>En este nuevo apunte rápido vamos a conseguir darle soporte a
múltiples lenguaje LaTeX dentro de Neovim por medio del plugin
“nvim-lspconfig”.</p>
<p>Esto quiere decir que vamos a usar Neovim como un cliente para un
servidor de Lenguaje, y vamos a ayudarnos de este plugin extra para
organizarlo.</p>
<p><a
href="https://apunteimpensado.com/como-instalar-servidor-lenguaje-neovim-forma-manual/">Ya
antes escribí un apunte sobre cómo usar LSP en Neovim sin utilizar
plugins.</a></p>
<p>Pero la verdad es que establecer conexión con un servidor de lenguaje
sin ayuda extra de un complemento es muy difícil de organizar. Cada
lenguaje tiene sus propias particularidades, e intentar conocerlas desde
cero demanda mucho tiempo.</p>
<p>Se puede decir entonces que esta es la solución más razonable, si
solamente nos interesa que todo funcione.</p>
<p>Los pasos que siguen voy a realizarlo en una máquina con un sistema
Linux. Pero los conceptos pueden dar de si para ser usados en otros
sistemas.</p>
<p>Por eso sin entretenernos más….</p>
<h2 id="agregar-el-plugin-nvim-lspconfig">Agregar el plugin
nvim-lspconfig</h2>
<p><a
href="https://apunteimpensado.com/como-instalar-plugins-de-forma-manual-en-neovim/">Tengo
un apunte que va a ayudarnos en este caso, para agregar plugins
utilizando git directamente.</a></p>
<p><a href="https://github.com/neovim/nvim-lspconfig">Y este es el sitio
oficial de “nvim-lspconfig”.</a></p>
<p>En ese espacio podemos encontrar toda la información extra que
necesitamos.</p>
<p>Pero en un ultra resumen si quiero hacer las cosas según el manual
utilizo el comando:</p>
<pre><code>git clone https://github.com/neovim/nvim-lspconfig ~/.config/nvim/pack/nvim/start/nvim-lspconfig</code></pre>
<p>Y si quiero hacer las cosas al estilo “apunte impensado”, voy a ir
hasta el directorio:</p>
<pre><code>~/.local/share/nvim/site/pack/plugins/start/</code></pre>
<p>Ahora en esa carpeta utilizo el comando:</p>
<pre><code>git clone https://github.com/neovim/nvim-lspconfig</code></pre>
<p>Y con eso tenemos que tener el plugin instalado.</p>
<p>Según entiendo, es indistinto utilizar la carpeta “.local” o
“.config” para instalar un plugin. Prefiero utilizar “.local” para
mantenerlo más ordenado, pero puedo equivocarme.</p>
<p>Tengo que recordar que todas las configuraciones para los futuros LSP
que voy a utilizar se encuentran en ese nuevo directorio
“nvim-lspconfig” y no necesito modificarlas directamente.</p>
<p>El directorio en el que puedo encontrarlas es el equivalente a:</p>
<p><a
href="https://github.com/neovim/nvim-lspconfig/tree/master/lua/lspconfig/server_configurations">lua/lspconfig/server_configurations</a></p>
<p>En nuestro caso esta es <a
href="https://github.com/neovim/nvim-lspconfig/blob/master/lua/lspconfig/server_configurations/texlab.lua">la
configuración lua que fue creada especialmente para texlab.</a></p>
<p>Lo que necesitamos ahora es un LSP para probarlo, por eso y ya que
necesito algunas cosas con Latex en Neovim…</p>
<h2 id="agregar-un-lsp-para-latex">Agregar un LSP para LaTeX</h2>
<h3 id="requerimientos-previos">Requerimientos previos</h3>
<p>No estoy seguro de que esto sea completamente necesario, pero puede
ser una buena idea tener instalado TexLive en el equipo.</p>
<p>Escribí sobre eso en: <a
href="https://apunteimpensado.com/como-instalar-latex-texlive-reciente-linux/">cómo
instalar la versión más reciente de TexLive en Linux</a></p>
<h3 id="cómo-instalar-texlab-en-linux">Cómo instalar Texlab en
Linux</h3>
<p>El servidor de lenguaje que vamos a utilizar <a
href="https://github.com/latex-lsp/texlab">se llama Texlab y este es su
sitio oficial.</a></p>
<p>La cosa es que no todos los sistemas cuentan con este LSP entre sus
paquetes, por lo que la forma más rápida de conseguirlo puede variar
entre sistema y sistema.</p>
<p>Por suerte <a
href="https://github.com/latex-lsp/texlab/releases">podemos encontrar
los paquetes pre compilados en este sitio.</a></p>
<p>Primero tengo que conocer los detalles de mi sistema con el
comando:</p>
<pre><code>uname -m</code></pre>
<p>Esto en mi caso da por resultado:</p>
<pre><code>x86_64</code></pre>
<p>Por lo que descargo la versión:</p>
<pre><code>texlab-x86_64-linux.tar</code></pre>
<p>Y lo llevo a mi directorio “Home”,</p>
<p>Luego en base a esa descarga, utilizo este comando para
extraerlo:</p>
<pre><code>tar -xzf texlab-x86_64-linux.tar.gz</code></pre>
<p>Muevo el archivo extraido a PATH:</p>
<pre><code>sudo mv texlab /usr/local/bin/</code></pre>
<p>Y en este punto hago el archivo extraido ejecutable:</p>
<pre><code>chmod a+x texlab</code></pre>
<p>Para terminar verifico la instalación con el comando:</p>
<pre><code>$ texlab –version</code></pre>
<pre><code>texlab 5.19.0</code></pre>
<p>En mi caso como se puede notar ya tengo instalado de forma global la
versión “5.19.0” de Texlab.</p>
<p>Recuerden que hasta este punto estuvimos haciendo todo desde la
Terminal en Linux.</p>
<h2
id="vincular-la-configuracion-lua-del-servidor-de-lenguaje-en-init.lua">Vincular
la configuracion lua del servidor de lenguaje en init.lua</h2>
<p>Ya tengo instalado un LSP de forma general. Lo que tengo que hacer es
darle a Neovim las opciones para usarlo.</p>
<p>Entonces en nuestro archivo “init.lua” escribimos:</p>
<pre><code>require’lspconfig’.texlab.setup{}</code></pre>
<p>Con esto hago una referencia al documento “texlab.lua” que conseguí
antes, al momento de instalar el plugin “nvim-lspconfig”.</p>
<p>Y listo, con eso terminamos la parte de la configuración.</p>
<h2
id="y-qué-ocurre-si-quiero-agregar-más-servidores-de-lenguaje-en-neovim-usando-este-metodo">¿Y
qué ocurre si quiero agregar más servidores de lenguaje en Neovim usando
este metodo?</h2>
<p>Básicamente siempre son los mismos pasos:</p>
<p>1- <a
href="https://microsoft.github.io/language-server-protocol/implementors/servers/">Averiguo
el nombre del LSP que necesito en este sitio.</a></p>
<p>Puede ser ese sitio o alguno similar, el punto es encontrar el
servidor que necesitamos.</p>
<p>2- Instalamos el LSP que vamos a utilizar de forma global en nuestro
sistema.</p>
<p>3- Me aseguro de tener lsp-config instalado. Y si ya lo tengo
instalado, recuerdo que en ese directorio del plugin se encuentran las
configuraciones lua para cada servidor.</p>
<p>4- Conectamos la configuracion del servidor desde “init.lua”. Por
ejemplo si estuviera usando “bashls” de servidor de lenguaje, y la
configuración es “bashls.lua, uso:</p>
<pre><code>require’lspconfig’.bashls.setup{}</code></pre>
<p>5- Ya podemos usar herramientas como diagnóstico de errores y auto
completar en Neovim para el lenguaje que recientemente descargamos
soporte.</p>
<p>6- En caso de ser necesario podemos agregar algunas configuraciones
extra si todo no funciona desde el vamos.</p>
<h3 id="cómo-compruebo-que-todo-funciona-correctamente">¿Cómo compruebo
que todo funciona correctamente?</h3>
<p>Digamos que quiero saber si la instalación del servidor de lenguaje
fue correcta.</p>
<p>Al hacer las cosas de esta forma, se supone que Neovim reconoce que
tipo de archivo estamos usando y lo “conecta” con el servidor de
lenguaje correcto.</p>
<p>Digamos que abrimos un nuevo documento llamado “ensayo.tex”. Neovim
va a reconocer el “.tex” de la extensión y va a actuar sobre eso.</p>
<p>En Neovim ahora uso el comando:</p>
<pre><code>:checkhealth lsp</code></pre>
<p>Si todo fue correctamente voy a notar que dice:</p>
<pre><code>vim.lsp: Active Clientstexlab (id=1, root_dir=~/v:null, attached_to=[11])</code></pre>
<p>Y esto me quiere decir que todo salio correctamente, ya puedo empezar
a realizar mis proyectos de código con todas las ventajas del servidor
de lenguaje agregadas.</p>
<h3 id="y-si-le-falta-algún-tipo-de-funcionalidad-a-mi-lsp">¿Y si le
falta algún tipo de funcionalidad a mi LSP?</h3>
<p>En mi breve experiencia haciendo estas pruebas puedo decir que no
siempre todo funciona desde un primer momento.</p>
<p>Cada LSP tiene sus propios detalles, lo mejor es revisar la
documentación oficial en cada caso.</p>
<p>Seguramente si falta alguna funcionalidad vamos a necesitar un plugin
o configuración extra para poder activarla.</p>
<h2 id="conclusión">Conclusión:</h2>
<p>Con esto le doy un cierre a mi apunte sobre cómo utilizar servidores
de lenguaje (LSP) en Neovim con la ayuda del plugin nvim-lspconfig.</p>
<p>Si hay algo que no pude cubrir correctamente en mi explicación o si
descubrís algún error, por favor enviame un correo electrónico para que
pueda arreglarlo. La información se encuentra en el menú de
“contacto”.</p>
<p>La seguimos en el próximo apunte.</p>
<p><strong>¿Comentarios o preguntas?</strong> Escríbeme tu opinión a: <a href="mailto:gustavol@apunteimpensado.com">gustavo@apunteimpensado.com</a></p>]]></description>
        <link>https://apunteimpensado.com/como-utilizar-servidores-lenguaje-lsp-neovim-lspconfig/</link>
        <guid isPermaLink="true">https://apunteimpensado.com/como-utilizar-servidores-lenguaje-lsp-neovim-lspconfig/</guid>
        <pubDate>Thu, 29 Aug 2024 00:00:00 </pubDate>
    </item>
    <item>
        <title><![CDATA[Cómo instalar un servidor de lenguaje en Neovim de forma manual]]></title>
        <description><![CDATA[<!--
INDEX_START
This section will be parsed for the left sidebar index/chapter list.
Use standard Markdown link syntax - links should point to actual HTML files.
-->

<p>En este apunte voy a revisar cómo instalar un servidor de lenguaje en
Neovim sin utilizar ningún plugin externo para organizarlo.</p>
<p>El objetivo de todo esto es conseguir darle soporte a distintos
lenguajes de programación dentro de este editor de texto.</p>
<p>Estuve practicando bastante con Neovim, pero todo lo que hice hasta
este punto fue utilizarlo para escribir texto narrativo o ensayos. Por
ejemplo esta misma entrada esta siendo escrita utilizando Markdown
dentro de Neovim. Pero nunca lo utilicé para escribir código de
computadora.</p>
<p>Eso va a cambiar en cuanto podamos poner esto en marcha. Pero antes
tengo que mencionar tres cosas:</p>
<ul>
<li><p>Estoy utilizando: Neovim v0.10.0</p></li>
<li><p>Necesitamos disponer de diferentes configuraciones LSP para
distintos lenguajes. Si hacemos todo esto de forma manual, necesitamos
un poco más de tiempo y los resultados pueden variar.</p></li>
<li><p><a
href="https://apunteimpensado.com/como-utilizar-servidores-lenguaje-lsp-neovim-lspconfig/">Esta
esa otra entrada, en la que reviso cómo utilizar LSP en Neovim
utilizando el plugin “nvim-lspconfig”, algo que simplifica bastante las
cosas.</a></p></li>
</ul>
<p>Ahora sin más vueltas…</p>
<h2 id="qué-es-un-servidor-de-lenguaje-qué-significa-lsp">¿Qué es un
servidor de lenguaje? ¿Qué significa “lsp”?</h2>
<p>Estoy intentando ir lo más rápido posible, por lo que este es mi
super resumen:</p>
<ul>
<li><p>LSP quiere decir “Language Server Protocol” y es un conjunto de
especificaciones que dice cómo tiene que comunicarse un servidor de
lenguaje con un cliente.</p></li>
<li><p>Un “Language Server” es un servidor de lenguaje de acuerdo al
protocolo LSP. Contiene información y funcionalidades de un lenguaje
determinado (por ejemplo revisión de sintaxis o diagnóstico de errores)
que el cliente puede usar.</p></li>
<li><p>Neovim funciona como un cliente para el servidor de lenguaje, y
realiza la comunicación entre el servidor y nuestro archivo.</p></li>
</ul>
<p>A modo de simplificarlo, digamos que queremos escribir dentro de
Neovim con en el lenguaje Python. Queremos tener herramientas de auto
formato, revisión de errores de sintaxis, ese tipo de cosas.</p>
<p>Para conseguir ese tipo de herramientas necesitamos un servidor de
lenguaje externo al programa. Ese servidor va a descansar en nuestra
computadora y Neovim va a comunicarse con el por medio del protocolo
LSP. Eso va a decirle al programa cómo darle formato al código de Python
y todo lo demás.</p>
<p>Estas dos cosas son elementos separados. Ya tenemos Neovim que va a
actuar como cliente, necesitamos conseguir un Servidor de Lenguaje
específico a nuestras necesidades.</p>
<p>Este servidor de lenguaje no tienen nada que ver con la forma en que
ejecutamos el código. Utilizar LSP principalmente nos va a habilitar
nuevas opciones de escritura en el programa.</p>
<h2 id="instalar-un-lsp-de-forma-manual-en-neovim">Instalar un lsp de
forma manual en Neovim</h2>
<p>Voy a tratar de resumir esto de la forma más directa que puedo.</p>
<h3 id="paso-1-conseguir-el-servidor-de-cada-lenguaje">Paso 1: conseguir
el servidor de cada lenguaje</h3>
<p>Ahora necesitamos descargar cada servidor de lenguaje propiamente
dicho. Por suerte conseguir esto es sencillo.</p>
<p>Para este ejemplo voy a descargar el servidor de lenguaje para Bash a
modo de ejemplo.</p>
<p><a
href="https://microsoft.github.io/language-server-protocol/implementors/servers/">Podemos
conseguir una lista de estos posibles servidores disponibles siguiendo
este enlace.</a></p>
<p><a href="https://langserver.org/">Esta es otra lista de servidores de
lenguaje, y que nos dice que opciones agrega cada servidor.</a></p>
<p>Los detalles de cómo descargar cada servidor se encuentra en cada
sitio en particular.</p>
<p>Entonces para Bash voy a utilizar <a
href="https://github.com/bash-lsp/bash-language-server">bash-language-server.</a></p>
<h3 id="paso-1.5-instalar-dependencias-específicas-para-bash">Paso 1.5:
instalar dependencias específicas para Bash</h3>
<p>Distintos servidores de lenguaje necesitan distintas dependencias.
Una vez más, eso podemos encontrarlo en el sitio de cada server.</p>
<p>En el caso de Bash LSP necesitamos: “shellcheck” para revisar el
código y “shfmt” para poder darle auto formato.</p>
<p>Entonces agregamos en el sistema:</p>
<pre><code>sudo apt install shellcheck</code></pre>
<pre><code>sudo apt install shfmt</code></pre>
<h4 id="cómo-instalar-nodejs-en-el-sistema">Cómo instalar nodejs en el
sistema</h4>
<p>Tal vez esto no es completamente necesario, pero ya que estoy en el
tema de agregar dependencias extra no viene mal mencionarlo.</p>
<p>Antes de continuar tenemos que revisar si tenemos “nodejs” en el
sistema. Tengan en cuenta que escribo esto utilizando Linux Mint, pero
los pasos se pueden ajustar a otos sistemas operativos.</p>
<p>Primero tengo que revisar las versiones de “node” y “npm” hacer:</p>
<pre><code>node -v</code></pre>
<pre><code>npm -v</code></pre>
<p>Siendo que seguro están desactualizados, lo mejor va a ser empezar
desinstalando lo que tenemos para empezar desde cero:</p>
<pre><code>sudo apt remove nodejs npm</code></pre>
<p>Y luego instalamos NVM con el siguiente comando:</p>
<pre><code>wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.0/install.sh | bash</code></pre>
<p>Con esto voy a tener también la última versión de NPM. Cierro la
terminal y vuelvo a abrirla para que la instalación tome efecto.</p>
<p>Ahora instalo “node.js” con este comando:</p>
<pre><code>nvm install –lts</code></pre>
<p>Puedo revisar la nueva versión con:</p>
<pre><code>node -v</code></pre>
<h3 id="paso-2-instalar-el-servidor-del-lenguaje">Paso 2: Instalar el
servidor del lenguaje</h3>
<p>Otra vez, eso depende de cada caso en particular, y lo más seguro es
que voy a encontrar esa información en el sitio de cada server.</p>
<p>Pero en nuestro caso particular tenemos para instalar bash language
server de forma global:</p>
<pre><code>npm i -g bash-language-server</code></pre>
<p>Y para verificar que todo funciona:</p>
<pre><code>bash-language-server –help</code></pre>
<p>Si no aparece ningún error, el servidor de lenguaje de bash ya se
encuentra en mi equipo.</p>
<p>Todo esto lo hacemos de forma global en nuestro equipo, todavía no
tuvimos necesidad de abrir Neovim.</p>
<h3 id="paso-3-configurar-el-servidor">Paso 3: Configurar el
servidor</h3>
<p>Esta es una lista de todas las configuraciones disponibles en
nvim-lspconfig: <a
href="https://github.com/neovim/nvim-lspconfig/blob/master/doc/server_configurations.md">lista
de configuraciones.</a></p>
<p>Si instalamos ese plugin, vamos a encontrar todas esas
configuraciones desde el vamos. Pero en esta oportunidad intento hacerlo
de forma manual.</p>
<p>En nuestro caso encontramos una posible configuración en la página de
bash language server.</p>
<p>Lo siguiente que tenemos que hacer es crear un archivo llamado
“bashls.lua” en el directorio dónde guardamos las configuraciones de
Neovim.</p>
<p>Y agregamos esto:</p>
<pre class="language-lua"><code>vim.api.nvim_create_autocmd(&#39;FileType&#39;, {
  pattern = &#39;sh&#39;,
  callback = function()
    vim.lsp.start({
      name = &#39;bash-language-server&#39;,
      cmd = { &#39;bash-language-server&#39;, &#39;start&#39; },
    })
  end,
})</code></pre>
<p>Luego hacemos un llamado a ese archivo desde nuestro archivo
“init.lua”:</p>
<pre class="language-lua"><code>require(&#39;bashls&#39;)</code></pre>
<h2 id="cómo-saber-si-el-lsp-funciona-en-neovim">¿Cómo saber si el LSP
funciona en Neovim?</h2>
<p>Para revisar el diagnóstico del server de lenguaje tengo que usar
este comando dentro de Neovim:</p>
<pre><code>:checkhealth lsp</code></pre>
<p>Y por ejemplo si tengo abierto un documento con la extension “sh”
(por ejemplo voy a crear un archivo “test.sh” para probarlo )me dice que
encuentra el servidor de Bash:</p>
<pre><code>vim.lsp: Active Clientsbash language server</code></pre>
<p>También tengo esto otro comando de diagnóstico:</p>
<pre><code>:lua vim.cmd.edit(vim.lsp.get_log_path())</code></pre>
<p>Que me va a dar mucha más información, aunque muchos de esos datos
exceden mi objetivos de este texto.</p>
<p>Pero a final de cuentas lo importante es revisar si todo esto
funciona o no sobre una pieza de código, ese es mi objetivo después de
todo, y eso es lo que vamos a revisar a continuación</p>
<h3 id="necesito-agregar-root_folder-en-la-configuración">¿Necesito
agregar root_folder en la configuración?</h3>
<p>Voy a notar que en el diagnostico aparece:</p>
<pre><code>root_dir=~/v:null</code></pre>
<p>En la documentación de Neovim al utilizar LSP pide establecer un
“directorio raíz” para que varios archivos en el mismo directorio puedan
compartir el mismo servidor de lenguaje.</p>
<p>O al menos eso entiendo de este detalle específico.</p>
<p>La configuración de bash language server parece no pedir este
directorio, así que por esta vez no necesito modificarlo. Pero la
documentación explica por ejemplo cómo establecerlo para el lenguaje
Python, los detalles pueden variar en cada caso.</p>
<h3
id="posible-error-de-lsp-warning-log-level-debug-will-cause-degraded-performance-and-high-disk-usage">Posible
error de LSP: WARNING Log level DEBUG will cause degraded performance
and high disk usage</h3>
<p>Para resolver este problema, es posible que tenga en mi “init.lua
algo como esto:</p>
<pre><code>vim.lsp.set_log_level(‘debug’)</code></pre>
<p>Eso me permite tener logs con más detalles. Pero si remuevo esa
opción, remuevo este error y todavía recibo bastante información al
ejecutar:</p>
<pre><code>:lua vim.cmd.edit(vim.lsp.get_log_path())</code></pre>
<h2 id="poner-el-lsp-recién-instalado-en-acción">Poner el LSP recién
instalado en acción</h2>
<p>Ya parece algo muy repetitivo pero… Las cosas que vamos a poder hacer
con cada LSP dependen de ese LSP. Pero si hay algunas cosas que vienen
establecidas desde el principio.</p>
<p>Lo importante de la configuración anterior que pusimos en
“bashls.lua” a mi entender es que el servidor va a iniciarse cada vez
que abramos un archivo con extension “sh” en Neovim.</p>
<p>Para empezar vamos a crear un nuevo archivo de Bash con esa extension
“.sh”, y vamos a abrirlo en Neovim.</p>
<p>En ese archivo vamos a poner este código para probarlo:</p>
<pre class="language-bash"><code>#!/bin/bash
&lt;br&gt;message= &quot;Testeando Bash LSP en Neovim&quot;
&lt;br&gt;echo &quot;$message&quot;</code></pre>
<p>Ahora vamos a notara que si presionamos “Esc” para salir del modo de
edición, bash language server va a mostrarnos los errores en el código.
Por ejemplo en nuestro caso va a decir:</p>
<pre><code>W message= &quot;Testeando Bash LSP en Neovim&quot; Remove space after = if trying to assign a value (for empty string, use var=’’ … ).</code></pre>
<p>Donde nos da un aviso diciéndonos que tenemos que remover el espacio
extra para declarar correctamente una variable.</p>
<p>Si queremos ejecutar el código de Bash directamente desde Neovim,
luego de darle permisos de ejecución, utilizo el comando:</p>
<pre><code>:!bash %</code></pre>
<p>Y de esta forma ya estamos usando el servidor de lenguaje de Bash con
Neovim, sin ningún intermediario extra.</p>
<p>Por otra parte Neovim cuenta con resaltado básico de lenguaje para
Bash desde el vamos, de la misma forma que con Markdown. Esa es otra
ventaja.</p>
<h2 id="activar-otras-funcionalidades-utilizando-lsp-functions">Activar
otras funcionalidades utilizando LSP functions</h2>
<p>Algunos detalles de LSP vienen mapeados de antemano, incluso si no
agregamos ninguna configuración extra.</p>
<p>Para conocer todo lo que puedo hacer tengo el <a
href="https://neovim.io/doc/user/lsp.html">Manual original LSP de Neovim
(en inglés).</a></p>
<p>Y por otra parte tengo este comando para utilizar en Neovim:</p>
<pre><code>:lua =vim.lsp.get_clients()[1].server_capabilities</code></pre>
<p>Lo que siguen son algunas cosas que puedo hacer en este momento, sin
intervenir dentro de los archivos lua.</p>
<h3
id="cómo-hago-para-ver-la-documentación-del-lenguaje-utilizando-lsp">¿Cómo
hago para ver la documentación del lenguaje utilizando LSP?</h3>
<p>Puedo poner el cursor sobre la palabra de la que quiero conocer la
documentación y utilizo el comando:</p>
<pre><code>:lua vim.lsp.buf.hover()</code></pre>
<p>Entonces me aparece una nueva ventana mostrándome esa parte de la
documentación.</p>
<p>O de forma más sencilla, puedo presionar la letra “K”(en máyuscula)
en “normal mode”.</p>
<h3 id="cómo-activar-el-auto-completar-con-lsp">¿Cómo activar el auto
completar con LSP?</h3>
<p>Digamos que estoy en “insert mode” y me encuentro escribiendo una
palabra. Desde el vamos LSP me permite hacer un auto-completado que se
activa de forma manual.</p>
<p>Con el cursor sobre esa palabra que quiero completar presiono la
combinación “Ctrl-x Ctrl-o” (uno primero, luego el otro).</p>
<p>Y esto me despliega una ventana de auto completar
(omni-completion).</p>
<h2
id="es-una-buena-idea-utilizar-lsp-en-neovim-organizando-la-configuración-de-forma-manual">¿Es
una buena idea utilizar LSP en Neovim organizando la configuración de
forma manual?</h2>
<p>En mi experiencia escribiendo este texto, puedo decir que:</p>
<ul>
<li><p>Si utilizamos pocos lenguajes de programación, es posible
hacerlo. Aunque va a requerir un poco más de tiempo conseguir que todo
funcione correctamente. No me imagino todo el esfuerzo que puede suponer
hacer algo como esto para cinco, diez o más lenguajes.</p></li>
<li><p>No pude conseguir que funcione el auto formato. El servidor se
conecta, tengo control de errores y auto completar pero nada más.
Conseguir que todo funcione necesita algo más de experiencia.</p></li>
<li><p>Si bien es un tema interesante para aprender, existen ya tantas
opciones para facilitar todo este trabajo de organizar LSP que es
difícil no elegir una y ahorrar todo este esfuerzo.</p></li>
<li><p>A final de cuentas es mejor conseguir la configuración que nos
resulte más cómoda. Esta configuración puede ser manual o creada por
plugins. Lo importante es no detenernos tanto en los detalles y empezar
a utilizar Neovim como una IDE para realizar otros proyectos.</p></li>
</ul>
<h2 id="conclusión">Conclusión</h2>
<p>Con esto le doy un cierre al apunte donde reviso cómo instalar un
servidor de lenguaje (lsp) en Neovim de forma manual.</p>
<p>Por supuesto esto no reemplaza la lectura de la documentación
oficial, simplemente estoy creando mi propio resumen para ayudarnos en
caso de necesitar configurar Neovim en nuestra máquina desde cero.</p>
<p>Y además es bueno recordar que aunque pude poner a funcionar el
servidor de lenguaje para Bash, seguramente hay formas más prácticas de
hacerlo.</p>
<p>¿Encontraste algún error en la información? ¿Hay algo del texto que
no fue bien explicado? Por favor, avísame con un correo electrónico para
que pueda solucionar el problema.</p>
<p>La seguimos en el próximo apunte.</p>
<h2 id="recursos">Recursos</h2>
<ul>
<li><p><a
href="https://dx13.co.uk/articles/2023/04/24/neovim-lsp-without-plugins/">Una
guía más sobre instalación de lsp sin plugins en neovim</a></p></li>
<li><p><a
href="https://vonheikemen.github.io/devlog/tools/neovim-lsp-client-guide/">Guía
para usar LSP en Neovim (en inglés)</a></p></li>
<li><p><a
href="https://dx13.co.uk/articles/2023/04/24/neovim-lsp-without-plugins/">Otra
guía para instalar LSP en Neovim sin usar plugins (en
inglés)</a></p></li>
</ul>
<p><strong>¿Comentarios o preguntas?</strong> Escríbeme tu opinión a: <a href="mailto:gustavol@apunteimpensado.com">gustavo@apunteimpensado.com</a></p>]]></description>
        <link>https://apunteimpensado.com/como-instalar-servidor-lenguaje-neovim-forma-manual/</link>
        <guid isPermaLink="true">https://apunteimpensado.com/como-instalar-servidor-lenguaje-neovim-forma-manual/</guid>
        <pubDate>Sat, 24 Aug 2024 00:00:00 </pubDate>
    </item>
    <item>
        <title><![CDATA[Mis apuntes sobre Neovim guía práctica personal]]></title>
        <description><![CDATA[<!--
INDEX_START
This section will be parsed for the left sidebar index/chapter list.
Use standard Markdown link syntax - links should point to actual HTML files.
-->
</li>
</ul>
<p>Estás leyendo una guía personal sobre cómo usar el editor de textos
Neovim.</p>
<p>Es el lugar dónde voy guardando las cosas que aprendo sobre ese
programa.</p>
<p>Originalmente este era un texto sobre Vim. Pero luego dejé de usar
Vim y olvidé la mayoría de lo que había aprendido. No tenía razones para
dejar la página como estaba sin actualizarla.</p>
<p>Decidí modificar el texto para cubrir Neovim en su lugar, una
herramienta que ahora estoy utilizando con algo más de confianza.</p>
<p>Y es bueno agregar que escribí este apunte ofreciendo mi propia
experiencia, la de un principiante aprendiendo sobre el tema.</p>
<p>En las distitnas entradas/ capítulos del texto voy a cubrir
diferentes temas.</p>
<p>Por ejemplo <a
href="https://apunteimpensado.com/como-instalar-neovim-desde-el-codigo-fuente-en-linux/">Escribí
un apunte detallando cómo instalar Neovim desde la fuente en está otra
entrada.</a></p>
<h2 id="un-editor-de-texto-tres-o-más-modos-de-uso">Un editor de texto,
tres (o más) modos de uso</h2>
<p>No voy a mentir: al principio Neovim es confuso. Y sin embargo… ¿Qué
puede haber de confuso en un programa que solamente espera trabajar con
texto?</p>
<p>Cuando abrí Neovim por primera vez, ni siquiera pude utilizarlo.
Ninguna tecla parecía hacer lo que le pedía, no pude escribir ni una
sola palabra.</p>
<p>Cada nueva tecla que apretaba causaba efectos inesperados. La
confusión aumentaba.</p>
<p>Entonces esto es lo IMPORTANTE para eliminar esta confusión
inicial:<br />
Neovim tiene varios modos distintos para trabajar con la aplicación. La
forma de encarar lo que tenemos que hacer, la configuración del teclado
y las opciones que tenemos cambian según el modo que se encuentra
activado.</p>
<p>Creo que estos modos que describo a continuación son los más
importantes para empezar. El tema puede no entenderse completamente al
principio, pero todo va a tomar sentido al empezar a hacer cosas.</p>
<h3 id="modo-normal-normal-mode">Modo Normal (Normal Mode)</h3>
<p>Cuando iniciamos Neovim empezamos con este modo. En este modo podemos
utilizar atajos por ejemplo para movernos por la pantalla o realizar
otras tareas, pero no podemos escribir texto.</p>
<p>Presionando en el teclado “Esc” (Escape) puedo entrar en el modo
normal en cualquier momento.</p>
<p>Toda mi confusión anterior se explica porque no conocía sobre estos
modos de utilizar el programa. Por ejemplo si en este modo presiono la
letra “h” no se escribe la letra h, me muevo en realidad un espacio
hacia la izquierda.</p>
<p>Otra vez, puede que esto no se entienda bien ahora pero va a
comprenderse mejor al empezar a practicar.</p>
<h3 id="modo-de-inserción-insertion-mode">Modo de Inserción (Insertion
Mode)</h3>
<p>Para ingresar texto en un archivo simplemente hay que presionar la
tecla “i” en el teclado.</p>
<p>Esto activa el modo de edición o inserción (insertion mode), toda la
edición de texto propiamente dicha se hace en este modo.</p>
<h3 id="modo-comandos-command-mode">Modo comandos (Command mode)</h3>
<p>Entramos a este modo partiendo desde el “modo normal”.</p>
<p>Antes de escribir un comando tenemos que apretar la tecla “:” en el
teclado.</p>
<p>Al hacerlo vamos a notar que aparece un “:” en la parte inferior
izquierda de la pantalla. Ahora agregamos la sintaxis del comando, y le
damos Enter para que tenga efecto. Los dos puntos indican que vamos a
ingresar un comando.</p>
<p>Por ejemplo puedo abrir una página de ayuda con el comando:</p>
<pre><code>:help</code></pre>
<p>Y puedo cerrar esta nueva página con el comando:</p>
<pre><code>:q!</code></pre>
<p>Ahora que conozco estos tres modos puedo alternarlos presionando:</p>
<pre><code>Esc para modo normal.i para modo edición.: para entrar a modo comandos.</code></pre>
<p>Existen otros modos de trabajo en Neovim, pero creo que conocer estos
tres me ayuda a empezar a utilizar el programa de forma más rápida.</p>
<h2 id="empezar-a-utilizar-el-editor-neovim">Empezar a utilizar el
editor Neovim</h2>
<p>Y empiezo a trabajar entonces en un documento desde cero, para darle
luego nombre y extensión.</p>
<p>Puedo abrir Neovim desde la terminal de Linux de esta forma:</p>
<pre><code>nvim</code></pre>
<p>Ahora tengo que recordar que el programa se abre en “modo
normal”.</p>
<p>Si quiero agregar texto presiono “i” para entrar en modo de
edición.</p>
<p>Ahora escribimos algo, cualquier cosa, para poder probar este modo de
edición.</p>
<p>Ahora digamos que queremos guardarlo. Para eso primero salimos del
<strong>modo de edición</strong> y entramos en el <strong>modo de
comandos</strong> presionando “Esc”, como dijimos antes.</p>
<p>Luego presiono “:” y el programa se encuentra a la espera de un
comando, ya no puedo escribir en la pantalla.</p>
<p>Para guardar entonces utilizo el comando:</p>
<pre><code>:w</code></pre>
<p>Le damos <strong>Enter</strong> y listo, guardamos el texto. Si
querés guardar con un nombre diferente, lo pongo al final de ese
comando.</p>
<h5 id="dónde-se-guarda-el-texto">¿Dónde se guarda el texto?</h5>
<p>El archivo se guarda en el directorio donde estabas trabajando. Si
abriste Neovim cuando la terminal esta abierta en la carpeta imágenes,
el texto se guarda en la carpeta imágenes.</p>
<p>Ahora, si queremos guardar y salir del documento la sintaxis del
comando es</p>
<pre><code>:wq</code></pre>
<p>Para salir del documento y volver a la terminal sin guardar los
cambios hacemos</p>
<pre><code>:q</code></pre>
<p>Hay que tener en cuenta que si no habíamos grabado el documento con
anterioridad, Neovim nos va a decir que si salimos los cambios van a
perderse, preguntándonos si realmente queremos salir o continuar.</p>
<p>Si queremos salir directamente sin ninguna pregunta, el comando
es:</p>
<pre><code>:q!</code></pre>
<p>Si lo pensamos usando un poco del idioma ingles todos estos comandos
tienen sentido. De esta forma entendemos que <strong>q</strong> es por
<strong>quit</strong> (abandonar o salir).</p>
<p>De hecho podríamos salir del programa escribiendo directamente el
comando</p>
<pre><code>:quit</code></pre>
<p>Pero se utiliza <strong>:q</strong> para ahorrar letras.</p>
<p>Saber esto sirve para que al menos comprendamos de donde viene cada
uno de los comandos, al menos los más básicos. No siempre, pero en
algunos casos puede servir. Si lo pensamos de este modo el aprendizaje
no parece tan confuso, podemos intuir que hace cada comando si no los
entendemos como letras elegidas al azar.</p>
<div class="line-block">:e nombre archivo | Abre un archivo diferente.
Si presiono la tecla <strong>Tab</strong> voy a conocer otros archivos
en esa carpeta. |</div>
<h4 id="movernos-por-la-pantalla-en-neovim"><strong>Movernos por la
pantalla en Neovim</strong></h4>
<p>Movernos por el texto en Neovim no es igual que en la mayoría de los
editores de textos, y ciertamente no es igual que en los editores
visuales.</p>
<p>Las flechas del teclado no siempre van a llevarnos a donde queremos y
no vamos a necesitar utilizar el puntero del artón por la mayor
parte.</p>
<p>Las teclas que necesitamos para movernos en el “modo normal” son la
“k”, “j”, “h”, “l”:</p>
<pre><code>k mueve una linea hacia arriba.
j nos mueve a la linea de abajo.
h mueve un espacio hacia la izquierda.
l nos mueve un espacio hacia la derecha.</code></pre>
<p>Para movernos un número determinado de letras a la derecha o a la
izquierda, podemos detallarlo directamente con un comando en el modo
normal.</p>
<p>Digamos por ejemplo 3 letras a la izquierda:</p>
<pre><code>3h</code></pre>
<p>O tal vez 3 lineas hacia arriba:</p>
<pre><code>2k</code></pre>
<p>Como si se tratase de un gran tablero, podemos designar los espacios
que nos movemos hacia cada lado.</p>
<p>Para que tengas como resumen, esta es la lista de movimientos que
podes hacer en el <strong>modo normal:</strong></p>
<table>
<colgroup>
<col style="width: 16%" />
<col style="width: 83%" />
</colgroup>
<thead>
<tr>
<th><em><strong>Comando</strong></em></th>
<th><em><strong>Mueve el cursor…</strong></em></th>
</tr>
</thead>
<tbody>
<tr>
<td>e</td>
<td>nos mueve al final de la palabra.</td>
</tr>
<tr>
<td>w</td>
<td>al principio de la siguiente palabra</td>
</tr>
<tr>
<td>E</td>
<td>al espacio vació entre dos palabras.</td>
</tr>
<tr>
<td>b</td>
<td>al principio de la palabra.</td>
</tr>
<tr>
<td>B</td>
<td>al principio del espacio vació entre dos palabras.</td>
</tr>
<tr>
<td>0</td>
<td>al principio de una linea.</td>
</tr>
<tr>
<td>^</td>
<td>al primer espacio ocupado de una linea.</td>
</tr>
<tr>
<td>$</td>
<td>al final de la linea.</td>
</tr>
<tr>
<td>H</td>
<td>A la primera linea en la pantalla.</td>
</tr>
<tr>
<td>M</td>
<td>A la linea en la mitad de la pantalla.</td>
</tr>
<tr>
<td>L</td>
<td>A la última linea de la pantalla.</td>
</tr>
<tr>
<td>:<em>n</em></td>
<td>Salta a la linea número “n”. Por ejemplo, :15 va a la linea núm
15.</td>
</tr>
</tbody>
</table>
<p>Todo esto anterior parece algo intimidante en un primer momento, pero
es parte de lo que nos permite utilizar el teclado con mayor
velocidad.</p>
<h4 id="borrar-y-modificar-texto-en-neovim">Borrar y modificar texto en
Neovim</h4>
<p>Si queremos borrar una linea entera, ponemos el cursor detrás de la
linea que queremos borrar y usamos el comando:</p>
<pre><code>:dd</code></pre>
<p>Si queremos borrar múltiples oraciones, agregamos el numero de lineas
delante del comando. Digamos que queremos borrar 5 lineas, el comando
quedaría como:</p>
<pre><code>:5dd</code></pre>
<p>Como resultado del comando vamos a borrar los cinco renglones de
texto por detrás del cursor.</p>
<p>Como apunte, estos son otros movimientos para el modo normal (y algún
comando extra) para borrar texto en Neovim.</p>
<table>
<colgroup>
<col style="width: 14%" />
<col style="width: 85%" />
</colgroup>
<thead>
<tr>
<th><em><strong>Comando</strong></em></th>
<th><em><strong>Resultado</strong></em></th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>i</strong></td>
<td>Insertar texto delante del cursor.</td>
</tr>
<tr>
<td>I</td>
<td>Insertar texto al principio de la linea donde nos encontramos.</td>
</tr>
<tr>
<td>a</td>
<td>Agregar texto después del cursor.</td>
</tr>
<tr>
<td>A</td>
<td>Agregar texto al final de la linea en la que nos encontramos.</td>
</tr>
<tr>
<td>o</td>
<td>Abre una nueva linea al final del texto y nos permite escribir.</td>
</tr>
<tr>
<td>O</td>
<td>Abre una linea en la parte superior del texto y nos permite
escribir.</td>
</tr>
<tr>
<td>C</td>
<td>Borrar el resto de la linea donde nos encontramos</td>
</tr>
<tr>
<td>r</td>
<td>Sobre escribir un carácter. Luego vuelve al modo de comandos.</td>
</tr>
<tr>
<td>R</td>
<td>Entra en modo de edición, pero reemplaza caracteres en lugar de
agregar nuevos.</td>
</tr>
<tr>
<td>Esc</td>
<td>Salir del modo de edición para entrar en modo normal.</td>
</tr>
<tr>
<td>x</td>
<td>Borra caracteres por detrás del cursor.</td>
</tr>
<tr>
<td>X</td>
<td>Borra caracteres por delante del cursor.</td>
</tr>
<tr>
<td>dd :d</td>
<td>Borra la linea donde nos encontramos</td>
</tr>
</tbody>
</table>
<h4 id="buscar-en-neovim"><strong>Buscar en Neovim</strong></h4>
<p>Pensemos que necesitamos encontrar una palabra en el texto. La
palabra para buscar en nuestro texto de ejemplo es
<strong>prueba</strong>. El comando nos queda:</p>
<pre><code>/prueba/</code></pre>
<p>Podemos buscar una palabra al comenzarla y terminarla con la tecla
<strong>/</strong>. Es posible buscar la próxima coincidencia en el
archivo presionando <strong>n</strong> y con <strong>N</strong> podemos
movernos a la coincidencia anterior.</p>
<p>También podemos conocer por ejemplo el número de linea en el que se
encuentra el cursor. Para eso escribimos el comando:</p>
<pre><code>:set number</code></pre>
<p>y para dejar de ver el número de linea escribimos:</p>
<pre><code>:set nonumber</code></pre>
<h4 id="cómo-hacer-y-deshacer-cambios-en-neovim">¿Cómo hacer y deshacer
cambios en Neovim?</h4>
<p>En Neovim tenemos algunos de los siguintes atajos para hacer y
desahcer cambios, que podemos utilizar en el modo normal:</p>
<table>
<thead>
<tr>
<th>u</th>
<th>Deshacer la última acción.</th>
</tr>
</thead>
<tbody>
<tr>
<td>U</td>
<td>Deshacer todos los últimos cambios hechos en el texto.</td>
</tr>
<tr>
<td>Ctrl + r</td>
<td>Rehacer el ultimo cambio deshecho.</td>
</tr>
</tbody>
</table>
<h2 id="conclusión"><strong>Conclusión:</strong></h2>
<p>Neovim es confuso cuando empezamos a usarlo. Luego, cuando tenemos
más practica, notamos que sigue siendo confuso.</p>
<p>Por supusto con lo anterior estoy bromeando, Neovim es una excelente
herramienta, que vuelve la actividad de escribir mucho más
divertida.</p>
<p>Con un poco más de practica empezamos a conocer como navegar sus
comandos, y usarlo se vuelve relativamente más sencillo. Es difícil
desprenderse de años de usar un procesador de textos visual, que depende
en gran medidas del mouse.</p>
<p>De algún modo tomar la costumbre de usar <strong>Neovim</strong> es
casi como un pasatiempo o un deporte en si mismo. Es útil de conocer, y
no esta de más abrirlo de vez en cuando para entenderlo.</p>
<p>¿Utilizás Neovim? ¿O alguna otra alternativa ?¿Se te ocurre alguna
idea para mejorar este apunte? Cualquier idea que tengas, es posible
contactarme con el correo electrónico, buscalo en la pestaña de
contacto.</p>
<h4 id="recursos">Recursos:</h4>
<ul>
<li><p><a href="https://neovim.io/doc/user/index.html">Manual de Neovim
(en inglés).</a></p></li>
<li><p><a href="https://linux.die.net/man/1/vi">Página del manual para
vim (en inglés).</a></p></li>
<li><p><a
href="https://www.man7.org/linux/man-pages/man1/vi.1p.html">Sitio del
manual del editor vi (en inglés).</a></p></li>
</ul>
<p><strong>¿Comentarios o preguntas?</strong> Escríbeme tu opinión a: <a href="mailto:gustavol@apunteimpensado.com">gustavo@apunteimpensado.com</a></p>]]></description>
        <link>https://apunteimpensado.com/apuntes-neovim-guia-practica-personal/</link>
        <guid isPermaLink="true">https://apunteimpensado.com/apuntes-neovim-guia-practica-personal/</guid>
        <pubDate>Tue, 13 Aug 2024 00:00:00 </pubDate>
    </item>
    <item>
        <title><![CDATA[Cómo instalar la versión más reciente de LaTeX (TexLive) en Linux]]></title>
        <description><![CDATA[<!--
INDEX_START
This section will be parsed for the left sidebar index/chapter list.
Use standard Markdown link syntax - links should point to actual HTML files.
-->

<p>En este apunte rápido voy a revisar cómo instalar la versión más
reciente de LateX (TexLive) de forma manual en Linux.</p>
<p>Antes de la información práctica me gustaría agregar algunos datos
que nos van a ayudar a entender mejor el tema.</p>
<p>Hay muchas guías en internet explicando cómo hacer este tipo de
instalaciones en un sistema operativo Linux. Pero muchas de esas guías
tienen un problema fundamental…</p>
<h2 id="el-problema">El problema</h2>
<p>La mayoría de las publicaciones escribiendo sobre el tema recomiendan
utilizar el comando:</p>
<pre><code>sudo apt install texlive-full</code></pre>
<p>Bastante sencillo, utilizar el comando “apt” para descargar los
paquetes necesarios. ¿Cuál es el problema entonces?</p>
<p>El asunto es que al hacerlo de esta manera tenemos chances de
encontrar una serie de paquetes antiguos sin actualizar.</p>
<p>Por ejemplo al momento de escribir estas palabras, puedo revisar que
la última versión del repositorio es:</p>
<pre><code>apt-cache madison texlive texlive | 2021.20220204-1 | texlive | 2021.20220204-1 |</code></pre>
<p>Mientras que el <a href="https://www.latex-project.org/get/">sitio
oficial dice que la versión más reciente es:</a></p>
<pre><code>LaTeX 2024-06-01</code></pre>
<p>Aunque es cierto que vamos a poder utilizar una versión antigua sin
problemas, mi interés es dirigirme a la documentación oficial para
conseguir instalar la versión más nueva.</p>
<p>Otra cosa que muchas veces olvidan otros blogs es que es posible
hacer una instalación con diferentes cantidades de lenguajes y
librerías. No necesitamos instalar todas las librerías al mismo tiempo,
aunque instalar todo completo sea una buena forma de evitar problemas
futuros.</p>
<h2 id="varias-opciones-para-instalar-latex">Varias opciones para
instalar Latex</h2>
<p>En lo que sigue vamos a realizar la instalación desde la terminal de
comandos. Tenemos varias fuentes de información:</p>
<ul>
<li><a
href="https://www.tug.org/texlive/doc/texlive-en/texlive-en.html#installation">Una
guía oficial resumida “no interactiva y”default”</a></li>
</ul>
<p>Es una guía resumida. Quizás el único inconveniente de esto es que su
utilizamos la instalación no interactiva esto significa descargar todas
las librerías completas, al rededor de +7 GB.</p>
<p>Existen también algunas opciones para elegir distintos niveles de
instalación:</p>
<ul>
<li><a
href="https://latex.ti.bfh.ch/doc_installation/native/linux.html">Para
realizar una instalación mínima tenemos esta otra guía</a></li>
</ul>
<p>Esa última opción es que la que reviso a continuación. Nos va a
permitir hacer una instalación completa, una “mediana” o una mínima de
LaTeX en nuestro sistema, cada una con una distinta cantidad de idiomas,
manuales, tipografías y ese tipo de cosas.</p>
<h2 id="diferencia-entre-latex-y-tex-live">Diferencia entre Latex y Tex
Live</h2>
<p>Estas palabras las uso a veces de forma intercambiable, pero no
significan lo mismo.</p>
<p><a href="https://www.tug.org/levels.html">Se puede leer todo al
respecto en este enlace</a></p>
<p>Pero para abreviar:</p>
<ul>
<li><p>TeX Live: Eso es realmente lo que vamos a instalar ahora. Es una
distribución o colección de programas y librerías que nos van a permitir
escribir en LaTeX.</p></li>
<li><p>LaTeX: Es un tipo de formato, una forma de lenguaje en el que
escribimos el documento.</p></li>
</ul>
<h2 id="instalar-tex-live-de-forma-dinámica">Instalar Tex Live de forma
dinámica</h2>
<p>Vamos a abrir la terminal de comandos y después:</p>
<h3 id="paso-0-requisitos-preliminares">Paso 0: requisitos
preliminares</h3>
<p>Vamos a necesitar algunos programas como por ejemplo “unzip”, “wget”
y “Perl”. Solucionamos eso consiguiendo todo con este comando:</p>
<pre><code>apt install -y unzip wget perl</code></pre>
<h3 id="paso-1-crear-directorio">Paso 1: crear directorio</h3>
<p>Este es el lugar recomendado para crearlo:</p>
<pre><code>mkdir /tmp/texlive &amp;&amp; cd /tmp/texlive</code></pre>
<h3 id="paso-2-descargar-el-instalador">Paso 2: Descargar el
instalador</h3>
<p>Descargo el instalador con:</p>
<pre><code>wget http://mirror.ctan.org/systems/texlive/tlnet/install-tl.zip</code></pre>
<h3 id="paso-3-desempaquetar-el-instalador">Paso 3: Desempaquetar el
instalador</h3>
<pre><code>unzip ./install-tl.zip -d install-tl</code></pre>
<h3 id="paso-4-movernos-al-nuevo-directorio-desempaquetado">Paso 4:
Movernos al nuevo directorio desempaquetado</h3>
<pre><code>cd install-tl/install-tl-$(date +%Y%m%d)</code></pre>
<h3 id="paso-5-empezar-la-instalación">Paso 5: Empezar la
instalación:</h3>
<pre><code>perl ./install-tl</code></pre>
<p>Ahora se me aparecen una serie de opciones. Presionando distintas
letras elijo distintas opciones.</p>
<p>Lo único que nos importa realmente es elegir el tipo de
instalación.</p>
<h3 id="paso-6-elegir-el-tipo-de-instalación">Paso 6: Elegir el tipo de
instalación:</h3>
<p>Voy a presionar “S” para poder elegir tipo de instalación. Luego
presiono la letra que acompaña cada opción para hacer una elección.</p>
<p>Por ejemplo tengo:</p>
<pre><code>b [ ] medium scheme (small + more packages and languages)</code></pre>
<p>Y también:</p>
<pre><code>c [ ] small scheme (basic + xetex, metapost, a few languages)</code></pre>
<p>Yo voy a realizar una instalación “medium” (unos +2 GB), pero si no
te interesa tener que trabajar un poco más después lo mejor es dejar
marcada la opción completa:</p>
<pre><code>a [X] full scheme (everything)</code></pre>
<p>La instalación completa va a tardar un buen rato en descargar (+7
GB), pero tiene todo lo que vas a utilizar y más.</p>
<p>Luego presiono “R” para volver al menú principal y luego presiono “I”
para completar la instalación.</p>
<p>No te preocupes, en cualquier caso se pueden instalar las colecciones
de librerías que faltan más tarde si necesitamos usarlas.</p>
<h3 id="paso-7-crear-un-symlink-al-directorio-usrlocalbin">Paso 7: crear
un symlink al directorio /usr/local/bin</h3>
<p>Esto va a permitir que algunos comandos, como el administrador de
paquetes, puedan utilizarse sin necesidad de señalar el camino al
directorio dónde se encuentra.</p>
<p>La forma del comando según la documentación es:</p>
<pre><code>/usr/local/texlive//bin/x86_64-linux/tlmgr path add</code></pre>
<p>Pero en mi caso de uso, para la versión de texlive que estoy
instalando queda:</p>
<pre><code>sudo ln -s /usr/local/texlivei/2024/bin/x86_64-linux/* /usr/local/bin/</code></pre>
<p>Si, estoy reemplazando “tlmgr” por un asterisco como wildcard. Más
sobre eso luego.</p>
<h2 id="paso-8-revisar-que-todo-funciona-correctamente">Paso 8: revisar
que todo funciona correctamente</h2>
<p>Puedo ver la versión del programa instalado con:</p>
<pre><code>tex –version</code></pre>
<p>Y puedo empezar a usarlo si consigo <a
href="https://www.xm1math.net/texmaker/">por ejemplo el editor
TexMaker.</a></p>
<p>Por supuesto también puedo usar Neovim, VSCode o algún otro
procesador de texto similar.</p>
<h2
id="solucionar-el-problema-cant-locate-texlivetlconfig.pm-in-inc">Solucionar
el problema “Can’t locate TeXLive/TLConfig.pm in <span class="citation"
data-cites="INC">@INC</span>”</h2>
<p>Digamos que ahora intentamos usar el manager de paquetes “tlmgr”.</p>
<p>Es posible que, incluso habiendo creado el symlink del paso anterior,
el sistema tiene problemas para encontrar el software “tlmgr” y nos
presenta este error:</p>
<pre><code>Can’t locate TeXLive/TLConfig.pm in @INC you may need to install the TeXLive::TLConfig module</code></pre>
<pre><code>BEGIN failed–compilation aborted at /usr/local/bin/tlmgr line 91.</code></pre>
<p><a href="https://github.com/void-linux/void-packages/issues/24013">El
problema parece ser conocido.</a></p>
<p>En mi caso encontré el error al crear el symlink de esta forma:</p>
<pre><code>sudo ln -s /usr/local/texlivei/2024/bin/x86_64-linux/tlmgr /usr/local/bin/</code></pre>
<p>En lugar de esta otra forma:</p>
<pre><code>sudo ln -s /usr/local/texlive/2024/bin/x86_64-linux/* /usr/local/bin/</code></pre>
<p>No puedo explicar exactamente porque ocurre este error en otras
oportunidades, pero en mi caso el sistema parecía no haber creado el
symlink al directorio correcto.</p>
<h2 id="elegir-un-nuevo-nivel-de-instalación-para-texlive">Elegir un
nuevo nivel de instalación para Texlive</h2>
<p>Entre todas las cosas que instalé <a
href="https://www.tug.org/texlive/doc/tlmgr.html">ahora tengo “tlmgr”
una herramienta para manejar paquetes.</a></p>
<p>Gracias a eso puedo utilizar el comando:</p>
<pre><code>tlmgr info schemes</code></pre>
<p>Cada “scheme” instalado contiene a todos los anteriores. Por ejemplo,
al instalar “medium” contengo también “small”. Si uno de estos conjuntos
se encuentra instalado, tiene una “i” al lado.</p>
<p>Con eso anterior entonces consigo listar los distintos tipo de
conjuntos de paquetes que puedo elegir. En mi caso instalé “medium” y
puedo pasarme a “full”.</p>
<p>Para hacer eso puedo agregar alguno de los schemes no instalados a mi
sistema con:</p>
<pre><code>tlmgr install nombre-nuevo-scheme</code></pre>
<h2 id="instalar-colecciones-de-paquetes-faltantes-en-latex">Instalar
colecciones de paquetes faltantes en Latex</h2>
<p>Para conocer las distintas colecciones de librerías, desde idiomas a
tipografías, tengo el comando:</p>
<pre><code>tlmgr info collections</code></pre>
<p>Las colecciones instaladas aparecen con una “i” a su lado.</p>
<p>Del mismo modo que hice con los “schemes/conjuntos”, puedo instalar
una colección que me falta usando el comando “tlmgr install”</p>
<pre><code>tlmgr install nombre-installar</code></pre>
<p>Puedo conocer los distintos paquetes en un tipo de instalación o
colección tengo el comando:</p>
<pre><code>tlmgr info –list</code></pre>
<p>Por ejemplo:</p>
<pre><code>tlmgr info –list scheme-bookpub</code></pre>
<pre><code>tlmgr info –list collection-latexextra</code></pre>
<h2 id="conclusión">Conclusión:</h2>
<p>Con esto termino este apunte práctico revisando cómo instalar la
versión más reciente de LaTeX (Tex Live) en Linux, de forma manual.</p>
<p>Tal vez exageré un poco con lo largo del texto, pero es uno de esos
temas que más profundo se vuelve cuanto más lo vamos investigando.</p>
<p>¿Escribís usando LateX? ¿Encontraste algún error en el texto? ¿Te
interesa el tema? Podes escribirme un correo electrónico, me interesa
leer tu opinión al respecto.</p>
<p>La seguimos en el próximo apunte.</p>
<p><strong>¿Comentarios o preguntas?</strong> Escríbeme tu opinión a: <a href="mailto:gustavol@apunteimpensado.com">gustavo@apunteimpensado.com</a></p>]]></description>
        <link>https://apunteimpensado.com/como-instalar-latex-texlive-reciente-linux/</link>
        <guid isPermaLink="true">https://apunteimpensado.com/como-instalar-latex-texlive-reciente-linux/</guid>
        <pubDate>Wed, 31 Jul 2024 00:00:00 </pubDate>
    </item>
    <item>
        <title><![CDATA[Cómo hacer notas al pie y referencias utilizando Markdown y Pandoc]]></title>
        <description><![CDATA[<!--
INDEX_START
This section will be parsed for the left sidebar index/chapter list.
Use standard Markdown link syntax - links should point to actual HTML files.
-->

<p>En este apunte rápido voy a revisar cómo hacer notas al pie y
referencias dentro de un ensayo utilizando Markdown y Pandoc.</p>
<p>Para conseguir nuestro objetivo no necesitamos utilizar ningún plugin
o complemento extra. Vamos a realizar nuestras referencias de la forma
más rápida y directa que encontremos.</p>
<p>Ahora un poco de auto promoción desvergonzada: <a
href="https://apunteimpensado.com/como-escribir-novelas-ensayos-utilizando-neovim/">esta
entrada es parte de mi serie sobre cómo escribir textos largos y ensayos
académicos utilizando Neovim.</a></p>
<p>Aunque realmente no sea necesario utilizar Neovim para todo lo que
sigue, cualquier programa para editar Markdown va a servirnos.</p>
<p>Por otra parte <a
href="https://v4.chriskrycho.com/2015/academic-markdown-and-citations.html">puede
leerse más extensamente sobre el tema en este otro blog (en
inglés).</a></p>
<p>Ahora sin más interrupciones…</p>
<h2 id="notas-al-pie-en-markdown">Notas al pie en Markdown</h2>
<p>Esta forma de hacer notas al pie en Markdown es la más rápida, y su
sintaxis es la siguiente:</p>
<pre><code>Esta es la primera oración que necesita referencia.[^1].Segunda referencia[^2].[^1]: Primer pie de página.[^2]: Segundo pie de página.</code></pre>
<p>Y cada referencia lleva su propio número, así que podemos agregar
múltiples de ellas sin perdernos dentro del texto.</p>
<p>Hay algunos detalles más, pero esto es básicamente todo.</p>
<p>Este tipo de notas al pie sirve bastante bien para agregar más
información en uno de esos ensayos universitarios que ponen un límite
estricto de páginas para responder.</p>
<h2 id="referencias-en-markdown-utilizando-pandoc">Referencias en
Markdown utilizando Pandoc</h2>
<p>Esta forma de crear referencias es la más práctica, porque nos
permite utilizar bibliografías más grandes con múltiples fuentes.</p>
<p><a href="https://pandoc.org/MANUAL.html#citations">La realidad es que
el tema es bastante extenso</a>, voy a hacer todo lo posible para
reducirlo a sus pasos prácticos.</p>
<h3 id="paso-1-crear-un-archivo-.bib">Paso 1: crear un archivo
“.bib”</h3>
<p>Este tipo de archivo contiene la bibliografía, en mi caso digamos que
el archivo se llama:</p>
<pre><code>bibliografia.bib</code></pre>
<p>Y dentro del archivo agrego los datos de los textos a citar. Por un
ejemplo posible de esto:</p>
<pre><code>@libro{ensayo:1,AUTHOR=&quot;Gustavo Impensado&quot;,TITLE=&quot;Ejemplos para mi Blog&quot;,PUBLISHER=&quot;Editorial Apuntes&quot;,YEAR=&quot;2005&quot;,}</code></pre>
<h3 id="paso-2-crear-o-descargar-un-archivo-.csl">Paso 2: Crear (o
descargar) un archivo “.csl”</h3>
<p>La sigla “CSL” viene por “Cytation Style Language” o en mi propia
traducción al castellano “Estilo para el lenguaje de cita”.</p>
<p><a href="https://citationstyles.org/">Es una forma de automatizar y
darle formato al estilo de las citas.</a></p>
<p>Para este ejemplo vamos a usar el tipo “Chicago Manual of Style.” que
nos va a dar un resultado similar a este:</p>
<pre><code>Impensado, Gustavo. Ejemplos para mi Blog. Editorial Apuntes, 2005.</code></pre>
<p>Podemos encontrar los estilos <a
href="https://github.com/citation-style-language">siguiendo este
enlace.</a></p>
<p><a href="https://www.zotero.org/styles">O también podemos encontrar
más estilos en este repositorio del software Zotero.</a></p>
<p>Descargamos el archivo y lo guardamos en el directorio dónde vamos a
usarlo. En mi caso voy a ponerle por nombre al archivo:</p>
<pre><code>chicago_style.csl</code></pre>
<h3
id="paso-3-especificar-el-archivo-.csl-y-el-.bib-en-el-documento-de-markdown">Paso
3: Especificar el archivo “.csl” y el “.bib” en el documento de
markdown</h3>
<p>Dentro de nuestro documento en Markdown agregamos la siguiente
cabecera:</p>
<pre><code>---title: &quot;Título_del_ejemplo&quot;bibliography: bibliografia.bibcsl: chicago_style.csl---</code></pre>
<p>Si las referencias de la bibliografía y el archivo de estilo se
encuentran en la misma carpeta que nuestro documento, no es necesario
señalar completo el camino hacia los directorios.</p>
<h3 id="paso-4-hacer-la-referencia-a-la-bibliografia-en-el-texto">Paso
4: Hacer la referencia a la bibliografia en el texto</h3>
<p>Ahora estoy dentro de mi documento en markdown. De esta forma hago la
referencia dentro del texto, de la misma forma que antes:</p>
<pre><code>Esta oración necesita una referencia.[^1].</code></pre>
<p>Pero al final del ensayo ahora hago un llamado a la bibliografía
“.bib”, mencionando directamente la referencia en la forma en que la
puse en ese archivo. Por ejemplo:</p>
<pre><code>[^1]:  [@ensayo:1]</code></pre>
<p>Puedo de esta forma utilizar muchas referencias, por ejemplo en este
caso puedo tener: [<span class="citation"
data-cites="ensayo:1">@ensayo:1</span>], [<span class="citation"
data-cites="ensayo:2">@ensayo:2</span>]…</p>
<p>El contenido completo en mi caso para el archivo “ejemplo.md” es de
esta forma:</p>
<pre><code>---tittle: &quot;Título del ejemplo&quot;bibliography: bibliografia.bibcsl: chicago_style.csl---Esta oración necesita una referencia.[^1]## Bibliografía[^1]: [@ensayo:1]</code></pre>
<h3 id="paso-5-convertir-el-archivo-de-markdown-utilizando-pandoc">Paso
5: Convertir el archivo de Markdown utilizando Pandoc</h3>
<p>Para exportar el resultado final tenemos que tener <a
href="https://pandoc.org/installing.html">instalado Pandoc en nuestro
sistema</a>, una herramienta para convertir archivos desde la terminal
de comandos.</p>
<p>Vamos a necesitar instalar tambien la siguiente herramienta:</p>
<pre><code>sudo apt install pandoc-citeproc</code></pre>
<p>Luego para conseguir exportar el archivo por ejemplo a “.odt” puedo
utilizar el comando:</p>
<pre><code>pandoc ejemplo.md -f markdown -t odt --bibliography=bibliografia.bib --csl=chicago_style.csl -s -o ejemplo.odt</code></pre>
<p>Y con eso voy a exportar mi documento “.odt” (para LibreOffice
Writer) completo con la bibliografía al final.</p>
<p>El resultado va a ser que tengo la referencia bibliográfica al final
del texto (en su propio “subheading”) y también la referencia más corta
en la nota al pie.</p>
<h2 id="conclusión">Conclusión:</h2>
<p>Con esto termino el apunte sobre cómo hacer notas al pie y
referencias utilizando Markdown y Pandoc.</p>
<p>¿Te fue útil la información? ¿Encontraste algún error? Podemos
escribirme un correo con tu opinión, mi email se encuentra en la página
de contacto.</p>
<p>La seguimos en el próximo apunte.</p>
<p><strong>¿Comentarios o preguntas?</strong> Escríbeme tu opinión a: <a href="mailto:gustavol@apunteimpensado.com">gustavo@apunteimpensado.com</a></p>]]></description>
        <link>https://apunteimpensado.com/como-hacer-notas-al-pie-referencias-markdown-pandoc/</link>
        <guid isPermaLink="true">https://apunteimpensado.com/como-hacer-notas-al-pie-referencias-markdown-pandoc/</guid>
        <pubDate>Fri, 26 Jul 2024 00:00:00 </pubDate>
    </item>
    <item>
        <title><![CDATA[Cómo crear un entorno virtual con Python en Linux]]></title>
        <description><![CDATA[<!--
INDEX_START
This section will be parsed for the left sidebar index/chapter list.
Use standard Markdown link syntax - links should point to actual HTML files.
-->

<p>En este breve apunte voy a estar revisando cómo crear un entorno
virtual de desarrollo para programar en Python dentro del sistema
operativo Linux.</p>
<p>Lo que quiero hacer con esta serie de apuntes es seguir registrando
toda esa serie de cosas que siempre quise aprender, pero que nunca me
tomé el tiempo para registrar o documentar.</p>
<p>Para nuestra suerte este tema es muy fácil de poner en práctica… tán
fácil que antes voy a tener que crear un poco de relleno para aumentar
el conteo de palabras.</p>
<h2 id="para-qué-hacer-un-entorno-virtual-de-python">¿Para qué hacer un
entorno virtual de Python?</h2>
<p>La idea es que tenemos Python instalado globalmente en nuestra
máquina. Bien podemos usar esa instalación global para todos los
proyectos que usamos.</p>
<p>El problema es que cada proyecto que utilizamos generalmente requiere
sus propias librerías extras. Agregar librerías y paquetes sobre esta
instalación termina por generar una acumulación poco ordenada.</p>
<p>La idea de un contención virtual de Python implica que de esta forma
cada proyecto consigue tener solamente las librerías necesarias para su
correcto funcionamiento.</p>
<p>Además no tenemos que olvidad que Python es una parte importante del
funcionamiento de la máquina. No es algo que ocurra seguido, pero si nos
ponemos a jugar con esto e intentamos desinstalar el interprete de
Python vamos a conseguir romper el sistema operativo. Puedo confirmar
que es algo que ocurre, como esa vez que borré algunas carpetas y no
pude volver a utilizar el comando “apt”.</p>
<h2
id="necesito-hacer-una-instalación-de-python-desde-cero-para-crear-un-entorno-virtual">¿Necesito
hacer una instalación de Python “desde cero” para crear un entorno
virtual?</h2>
<p>Esto es algo que al principio me confundía.</p>
<p>Según entiendo cada vez que inicio un entorno virtual, el directorio
obtiene una copia de Python que funciona completamente separada de la
versión global.</p>
<p>Por lo que no importa si mi instalación actual ya tiene librerías
agregadas.</p>
<p>Esta copia de Python que se inicia en cada entorno virtual no
contiene nada más que el interprete con su librería original. Esto
quiere decir que no tiene nada extra de los paquetes que habíamos
agregado antes.</p>
<h2 id="cómo-crear-el-entorno-virtual-de-python">¿Cómo crear el entorno
virtual de Python?</h2>
<p><a href="https://docs.python.org/es/3.12/library/venv.html">La
documentación de Python indica los pasos a seguir:</a></p>
<p>En sistemas operativos tipo Debian/Ubuntu antes vamos a necesitar
instalar, si no lo hicimos antes, una librería de Python:</p>
<pre><code>apt install python3.10-venv</code></pre>
<p>Aunque la versión de Python puede variar según la que tengas
instalada.</p>
<p>Lo importante es que para crear el entorno virtual propiamente dicho
utilizo el comando:</p>
<pre><code>python3 -m venv ~/camino/al/directorio/específico</code></pre>
<p>Esto crea los archivos necesarios en el directorio para habilitar
esta nueva versión “descartable” de Python que vamos a usar en este
proyecto en particular.</p>
<h2 id="cómo-activar-el-entorno-virtual-de-python">¿Cómo activar el
entorno virtual de Python?</h2>
<p>Digamos que establecí el entorno virtual con este comando:</p>
<pre><code>python3 -m venv ~/Desktop/test</code></pre>
<p>Podemos notar que nuevos archivos fueron creado dentro del directorio
test.</p>
<p>Si ahora entro en esa carpeta, voy a notar que hay un nuevo
directorio llamado “bin”. Y dentro de ese directorio hay un archivo
llamado “activate”.</p>
<p>Para activar el directorio virtual en ese caso utilizo el
comando:</p>
<pre><code>source ~/Desktop/test/bin/activate</code></pre>
<p>Voy a notar que el comando tuvo efecto porque el nombre del
directorio dónde estoy trabajando con el entorno virtual aparece en la
terminal de esta forma:</p>
<pre><code>(test) gus@equipo:</code></pre>
<p>Y para terminar el entorno virtual utilizo el comando:</p>
<pre><code>deactivate</code></pre>
<p>Básicamente entonces hago “source” apuntando al directorio
“/bin/activate/” de cada proyecto específico. Y termino el entorno
virtual con “deactivate”.</p>
<p>Y para eliminar un entorno virtual utilizo el comando:</p>
<pre><code>rm -rf /camino/al/directorio</code></pre>
<p>Y con eso consigo borrar el directorio.</p>
<p>Recordemos que cada librería que instale dentro de un entorno virtual
va a aplicar solamente a ese directorio.</p>
<h2
id="cómo-se-qué-paquetes-existen-agregados-en-mi-instalación-de-python">¿Cómo
se qué paquetes existen agregados en mi instalación de Python?</h2>
<p>Este puede ser un interesante experimento, rápido de realizar.</p>
<p>Digamos que estuvimos instalando librerías en nuestra versión de
Python global.</p>
<p>Si utilizamos el comando:</p>
<pre><code>pip list</code></pre>
<p>Vamos a tener un listado de todas las librerías instaladas.</p>
<p>Si ahora creamos un nuevo entorno virtual desde cero, y corremos de
nuevo el mismo comando, vamos a notar que tenemos muchos menos paquetes
instalados.</p>
<p>Esto último ocurre porque la versión de Python del entorno virtual no
tiene ninguna de las librerías extra que la versión global tiene
agregadas sobre su paquete básico.</p>
<h2 id="conclusión">Conclusión</h2>
<p>Con esto termino este breve apunte revisando cómo crear un entorno
virtual de Python en Linux.</p>
<p>Existen otras opciones para realizar este tipo de entornos, pero pro
ahora creo que con conocer esta forma me alcanza. No es algo complejo de
hacer, y puede ayudarnos a crear proyectos eficientes y ordenados.</p>
<p>¿Te fue de utilidad esta información? ¿Encontraste algún error en el
material? Si me escribís un correo voy a poder conocer tu opinión.</p>
<p>La seguimos en el próximo apunte.</p>
<p><strong>¿Comentarios o preguntas?</strong> Escríbeme tu opinión a: <a href="mailto:gustavol@apunteimpensado.com">gustavo@apunteimpensado.com</a></p>]]></description>
        <link>https://apunteimpensado.com/como-crear-un-entorno-virtual-con-python-en-linux/</link>
        <guid isPermaLink="true">https://apunteimpensado.com/como-crear-un-entorno-virtual-con-python-en-linux/</guid>
        <pubDate>Tue, 09 Jul 2024 00:00:00 </pubDate>
    </item>
    <item>
        <title><![CDATA[Cómo instalar un entorno local de Wordpress usando LAMP en Linux]]></title>
        <description><![CDATA[<!--
INDEX_START
This section will be parsed for the left sidebar index/chapter list.
Use standard Markdown link syntax - links should point to actual HTML files.
-->

<p>En este breve apunte vamos a revisar cómo instalar un entorno de
desarrollo de Wordpress en Linux.</p>
<p>Ocurre lo siguiente: estoy intentando actualizar el tema de mi sitio
utilizando Wordpress. Si bien analicé otras opciones, como por ejemplo
pasarme a un sitio estático, creo que todavía me quedan algunas cosas
por aprender en Wordpress. Por ejemplo desarrollar mi propio tema.</p>
<p>El problema con todo esto es que para empezar necesito poder probar
lo que estoy haciendo directamente en mi máquina. Probar cada ligero
cambio directamente en el hosting real de la página parece una cantidad
innecesaria de esfuerzo.</p>
<p>Para continuar necesito alguna forma de poder utilizar Wordpress
localmente en mi máquina con el sistema operativo Linux.</p>
<p><a
href="https://developer.wordpress.org/advanced-administration/before-install/development/">Con
el objetivo de realizar esto hay varias opciones.</a></p>
<p>Algunas de estas opciones implican una solución que demanda instalar
programa especialmente dedicado. Otras opciones implican utilizar un
ecosistema de programas, como por ejemplo <a
href="https://www.apachefriends.org/index.html">Xampp: Apache + MariaDB
+ PHP + Perl</a>.</p>
<p>En esta oportunidad vamos a utilizar un ecosistema llamado LAMP, la
combinación de: Linux, Apache, MySQL y PHP.</p>
<h2 id="cómo-instalar-wordpress-usando-lamp-en-linux">Cómo instalar
Wordpress usando LAMP en Linux</h2>
<p>Estoy utilizando Linux Mint, que es un sistema operativo basado en
Debian. De todas formas estos pasos pueden seguirse más o menos sin
cambios en otros sistemas operativos.</p>
<p>Debian tiene una <a href="https://wiki.debian.org/LaMp">guía en su
Wiki para instalar LAMP</a> y también tiene <a
href="https://wiki.debian.org/WordPress">una guía para instalar
Wordpress de forma local</a>.</p>
<p>Por supuesto este material no reemplaza las guías oficiales, mi
intención es transmitir mi experiencia de instalación y agregar la mayor
cantidad de atajos para configurar todo lo más rápido posible.</p>
<h3 id="paso-1-instalar-apache">Paso 1: instalar Apache</h3>
<p>El servidor Apache va a servir de host para nuestro sitio Wordpress.
Voy a instalarlo con:</p>
<pre><code>apt install apache2 apache2-doc</code></pre>
<p>Es bueno saber que en caso de necesitarlo, el servidor Apache puede
inciarse con el comando:</p>
<pre><code>sudo systemctl start apache2</code></pre>
<p>Y puedo utilizar este otro comando para ver si el servidor funciona
correctamente:</p>
<pre><code>sudo systemctl status apache2</code></pre>
<p>Pero olvidemos esto último. Lo que puedo hacer es escribir el
siguiente comando, que va a hacer que Apache se active al iniciarse el
equipo y nos va a evitar usar el comando “start” cada vez que iniciamos
la máquina:</p>
<pre><code>sudo systemctl enable apache2</code></pre>
<p>Lo que puede ser desactivado utilizando:</p>
<pre><code>sudo systemctl disable apache2</code></pre>
<p>En cualquier caso, si ya instalé Apache puedo abrir esta dirección en
mi navegador (http:/127.0.0.1):</p>
<pre><code>http://localhost/</code></pre>
<p>Y si todo funciona bien, voy a encontrarme la página default de
Apache siendo servida.</p>
<p>Hay que tener en cuenta que Apache sirve el contenido desde este
directorio raíz:</p>
<pre><code>/var/www/html</code></pre>
<p>Por lo que en este momento estamos viendo el archivo “index.html” de
ese directorio.</p>
<h3 id="paso-2-instalar-y-confugyrar-mysql-mariadb">Paso 2: instalar y
confugyrar Mysql (MariaDB)</h3>
<p>MariaDB va a guardar todos los datos de la instalación de
Wordpress.</p>
<pre><code>sudo apt install mariadb-server mariadb-client</code></pre>
<h4 id="asegurar-la-instalación-de-mariadb">Asegurar la instalación de
MariaDB</h4>
<p>Lo siguiente que necesito hacer es asegurar la instalación de
MariaDB. Esto merece algunas consideraciones extras.</p>
<p>Primero tengo que utilizar el siguiente comando:</p>
<pre><code>sudo mysql_secure_installation</code></pre>
<p>Esto me va a presentar una serie de opciones.</p>
<pre><code>Enter current password for root (enter for none):</code></pre>
<p>Básicamente me pide la contraseña par la cuenta root. Siendo que no
hay ninguna de momento, presiono directamente enter.</p>
<p>Lo que entiendo que ocurre es que MariaDB confía directamente en la
cuenta root del sistema, por lo que no necesito crear una super cuenta
específica para este caso. Pero luego puedo crear cuentas y contraseñas
dedicadas para cada base de datos.</p>
<pre><code>Switch to unix_socket authentication [Y/n]</code></pre>
<p>Otra vez presiono “n”, al parecer desde la versión “10.5”” esto viene
autorizado por defecto. Supongo que entonces al presionar “n” quiero
decir en realidad “y”. Pero la frase parece escrita de forma extraña, no
voy a mentir.</p>
<p>Luego sigue:</p>
<pre><code>Change the root password? [Y/n]</code></pre>
<p>Presiono “n”, porque no quiero crear una cuenta root para
MariaDB.</p>
<p>Luego sigue:</p>
<pre><code>Remove anonymous users? [Y/n]</code></pre>
<p>Al parecer al instalar MariaDB por primera vez, el sistema tiene una
cuenta anónima paraque podamos hacer algunas pruebas. Siendo que en
nuestro caso estamos pensando en utilizar el programa directamente,
podemos presionar “y” para seguir adelante.</p>
<p>Lo que sigue es:</p>
<pre><code>Disallow root login remotely? [Y/n]</code></pre>
<p>Y otra vez vamos a presionar “Y”, porque no nos interesa que alguien
pueda conectarse a nuestra base de datos de forma remota utilizando la
cuenta root del sistema, si es que consiguen adivinarla.</p>
<pre><code>Remove test database and access to it? [Y/n]</code></pre>
<p>A esta pregunta la respondemos de nuevo “y”. MariaDB crea una tabla
de prueba para que usemos de test, pero no nos interesa conservarla.</p>
<pre><code>Reload privilege tables now? [Y/n]</code></pre>
<p>Y de nuevo presionamos “y” para que los cambios tomen efectos.</p>
<p>En resumen la totalidad del cuestionario queda de la siguiente
forma:</p>
<pre><code>Enter current password for root (enter for none): enter Switch to unix_socket authentication [Y/n] nChange the root password? [Y/n] n Remove anonymous users? [Y/n] yDisallow root login remotely? [Y/n] y Remove test database and access to it? [Y/n] yReload privilege tables now? [Y/n] y</code></pre>
<h4 id="comandos-para-usar-mariadb">Comandos para usar MariaDB</h4>
<p>De la misma forma que hice con Apache, puedo iniciar MariaDB
directamente al iniciar el equipo usando este comando por única vez.
Escribo:</p>
<pre><code>sudo systemctl enable mariadb</code></pre>
<p>De otra forma puedo iniciar el programa en cualquier momento con el
comando:</p>
<pre><code>sudo systemctl enable mariadb</code></pre>
<p>Y puedo revisar si esta funcionando correctamente con el comando:</p>
<pre><code>sudo systemctl status mariadb</code></pre>
<h2 id="instalar-php">Instalar PHP</h2>
<p>PHP es el lenguaje que va a procesar el contenido de la página web en
el navegador.</p>
<p>Para instalarlo utilizo el comando:</p>
<pre><code>sudo apt install php libapache2-mod-php php-mysql</code></pre>
<h2 id="revisar-que-todo-funciona-hasta-el-momento">Revisar que todo
funciona hasta el momento</h2>
<p>Para que los complementos instalados se recarguen en Apache, utilizo
este comando:</p>
<pre><code>sudo systemctl restart apache2</code></pre>
<p>Luego creamos un arcivo PHP, y lo abrimos con Nano (utilizo Nano para
hacer rápido, es posible usar Neovim o cualquier otra herramienta)</p>
<pre><code>sudo nano /var/www/html/info.php</code></pre>
<p>Y agrego esto en el nuevo archivo:</p>
<pre><code>&lt;?php phpinfo();?&gt;</code></pre>
<p>Ahora puedo revisar en el navegador la dirección:</p>
<pre><code>http://127.0.0.1/info.php</code></pre>
<p>Si todo funciona correctamente voy a encontrarme una tabla con
información de PHP.</p>
<p>En este momento si todo salió bien voy a borrar este archivo
“info.php” y el archivo “index.html” original.</p>
<h2 id="crear-una-base-de-datos-mariadb-para-wordpress">Crear una base
de datos MariaDB para Wordpress</h2>
<p>Entro a Maria DB desde la terminal con el comando:</p>
<pre><code>sudo mariadb -u root</code></pre>
<p>Creo la base de datos para Wordpress, según el nombre de mi
proyecto:</p>
<pre><code>CREATE DATABASE miproyecto;</code></pre>
<p>Y ahora genero una cuenta y contraseña para esa base de datos
(reemplazando “wpuser” con el nombre de la cuenta y “password” con mi
contraseña):</p>
<pre><code>CREATE USER &#39;wpuser&#39;@&#39;localhost&#39; IDENTIFIED BY &#39;password&#39;;</code></pre>
<pre><code>GRANT ALL PRIVILEGES ON miproyecto.* TO &#39;wpuser&#39;@&#39;localhost&#39;;</code></pre>
<pre><code>FLUSH PRIVILEGES;</code></pre>
<p>Y salgo con el comando:</p>
<pre><code>quit</code></pre>
<h2 id="conseguir-los-archivos-de-wordpress">Conseguir los archivos de
Wordpress</h2>
<p>Ya sabemos que Apache sirve los archivos desde el directorio:</p>
<pre><code>/var/www/html</code></pre>
<p>Por lo que vamos a crear una nueva carpeta ahí dentro (en este
ejemplo “proyecto.com”) para instalar Wordpress y usarlo en nuestro
entorno de producción:</p>
<pre><code>sudo mkdir -p /var/www/html/proyecto.com/src</code></pre>
<p>Y vamos a entrar a ese directorio:</p>
<pre><code>cd /var/www/html/proyecto.com/src</code></pre>
<p>El directorio es “src” porque ahí vamos a guardar los archivos de
“source” o “fuente” de la descarga original.</p>
<p>Consigo los archivos necesarios de Wordpress con este comando:</p>
<pre><code>sudo wget http://wordpress.org/latest.tar.gz</code></pre>
<p>Extraigo los archivos:</p>
<pre><code>sudo tar -xvf latest.tar.gz</code></pre>
<p>Ahora voy a crear el directorio “public_html”:</p>
<pre><code>sudo mkdir -p /var/www/html/proyecto.com/public_html</code></pre>
<p>Y vamos a mover ahí la carpeta que recientemente descargamos de
Wordpress (nos va a quedar una copia original en “src”)</p>
<pre><code>sudo mv wordpress/* /var/www/html/proyecto.com/public_html</code></pre>
<p>Si ahora entramos a “public_html” vamos a encontrar que tenemos todos
los archivos de nuestra instalación de Wordpress.</p>
<p>Puedo entrar a visitar el sitio siguiendo la dirección de localhost
en el navegador, para este caso de mi ejemplo:</p>
<pre><code>http://127.0.0.1/proyecto.com/public_html</code></pre>
<h2 id="configurar-wordpress">Configurar Wordpress</h2>
<p>Ahora me dirijo al directorio “public_html”.</p>
<p>Acto seguido cambio el nombre del archivo:</p>
<pre><code>wp-config-sample.php</code></pre>
<p>Por el nombre:</p>
<pre><code>wp-config.php</code></pre>
<p>Ahora voy a abrir este archivo utilizando Neovim (puede ser otro
programa como Nano, pero ahora estoy tratando de acostumbrarme a
Neovim)</p>
<pre><code>nvim wp-config.php</code></pre>
<p>Dónde tengo que cambiar estos datos:</p>
<pre><code>/** The name of the database for WordPress */ define( &#39;DB_NAME&#39;, &#39;database_name_here&#39; );/** Database username */ define( &#39;DB_USER&#39;, &#39;username_here&#39; );/** Database password */ define( &#39;DB_PASSWORD&#39;, &#39;password_here&#39; );</code></pre>
<p>Por la misma información de la base de datos que utilicé antes,
cuando establecí la base de datos para el proyecto en MariaDB (por
ejemplo, en “username_here” va el nombre de la cuenta que hice para esa
base de dato).</p>
<p>Para terminar reinicio Apache y Maria DB con estos comandos:</p>
<pre><code>sudo systemctl restart apache2.service sudo systemctl restart mysql.service</code></pre>
<h3 id="instalar-wordpress-en-cinco-minutos">Instalar Wordpress en cinco
minutos</h3>
<p>Ya tengo que estar en una pestaña de mi navegador, siguiendo:</p>
<pre><code>http://127.0.0.1/proyecto.com/public_html</code></pre>
<p>Al actualizar el navegador, Wordpress me va a pedir nuevos datos.
Nuevo nombre de cuenta y contraseña para este sitio en particular.
Cualquier correo de fantasía puede servir, no tiene porque ser real.
Tenemos la posibilidad de corregir esta información desde nuestra base
de datos.</p>
<p>Y listo, si le doy continuar la instalación va a seguir su curso.</p>
<p>Ahora puedo ingresar mis credenciales y ya tengo una versión de
desarrollo de Wordpress funcionando en mi propia máquina.</p>
<p>Siempre puedo visitar el sitio y revisar las modificaciones que le
hago a los temas visitando la misma dirección que dirige a mi
localhost.</p>
<h4
id="facilitar-la-instalación-de-plugins-y-temas-importante">Facilitar la
instalación de plugins y temas (importante)</h4>
<p>Desde un principio Wordpress utiliza las credenciales FTP (File
Transfer Protocol) para realizar la acción de por ejemplo instalar
plugins.</p>
<p>Para evitar que esta ventana nos aparezca pidiendo estos datos, puedo
entrar a wp-config.php y agregar:</p>
<pre><code>/** Bypass FTP */ define(&#39;FS_METHOD&#39;, &#39;direct&#39;);</code></pre>
<p>El documento “config.php” tiene una parte para ingresar “custom
values” (código extra) antes del llegar al final.</p>
<p>Luego de guardar el archivo utilizo el comando en la terminal:</p>
<pre><code>sudo chown -R www-data:www-data /var/www/html/proyecto.com</code></pre>
<p>Y listo, con esto voy a poder instalar plugins sin
inconvenientes.</p>
<h2 id="extra-instalar-módulos-php">Extra: instalar módulos PHP</h2>
<p>Como un extra no es mala idea instalar los siguientes módulos PHP
para ampliar algunas funcionalidades:</p>
<pre><code>sudo apt install php-curlsudo apt install php-xmlsudo apt install php-imagicksudo apt install php-mbstringsudo apt install php-zipsudo apt install php-intl</code></pre>
<p>Esta instalación la hago desde la terminal de Linux.</p>
<p>Luego reinicio el servidor:</p>
<pre><code>sudo service apache2 restart</code></pre>
<p>Y puedo conocer los módulos PHP instalados con el comando:</p>
<pre><code>php -m</code></pre>
<h2 id="conclusión">Conclusión</h2>
<p>Con esto termino este breve apunte sobre cómo instalar una versión de
desarrollo de Wordpress en mi equipo.</p>
<p>Para hacer esto tuvimos que conseguir el stack de programas LAMP. Al
haber hecho esto vamos a tener también a nuestra disposición un servidor
local para crear otro tipo de proyectos.</p>
<p>Podemos ademas cera nuevos directorios, para probar proyectos en
distintas instalaciones de Wordpress.</p>
<p>¿Te sirvió la información? Podes escribirme un correo para contarme
tu opinión o para darme tus críticas.</p>
<p>La seguimos en el próximo apunte.</p>
<p><strong>¿Comentarios o preguntas?</strong> Escríbeme tu opinión a: <a href="mailto:gustavol@apunteimpensado.com">gustavo@apunteimpensado.com</a></p>]]></description>
        <link>https://apunteimpensado.com/como-instalar-un-entorno-local-de-wordpress-usando-lamp-en-linux/</link>
        <guid isPermaLink="true">https://apunteimpensado.com/como-instalar-un-entorno-local-de-wordpress-usando-lamp-en-linux/</guid>
        <pubDate>Sun, 07 Jul 2024 00:00:00 </pubDate>
    </item>
</channel>
</rss>