Variable not found
¡16 años de Variable Not Found!
mayo 17, 2022 06:05

Hace unos días, Variable Not Found cumplió dieciséis añitos de vida, una eternidad para este mundo en el que vivimos, donde todo ocurre tan rápido y las cosas cambian a una velocidad de vértigo 😊.
Dieciséis años viviendo algo único. Cada uno de los 1.350 artículos publicados ha sido para mí una increíble oportunidad de mejora y aprendizaje y, con suerte, espero (y confío) haber podido ayudar a alguno de los muchísimos visitantes que durante este periodo han pasado por aquí y me han animado a seguir en la brecha.
Dieciséis años creciendo juntos. Comencé esta aventura con más pelo, mejor vista y bastante menos canas, pero la ilusión de poder escribir sobre lo que me gusta, con el plus de que esto pudiera ser útil para alguien, sigue intacta.
Pero bah, dejémonos de historias sentimentales... como es tradición, veamos cómo ha funcionado el blog durante este año.
Variable Not Found en cifras: 2021-2022
Durante este año pasado, las visitas han bajado respecto al anterior, que, por alguna extraña razón, registró unas cifras excepcionales. Aún así, 107.000 usuarios únicos, visitando un total de 180.000 páginas, es una barbaridad para un blog de barrio como este, donde sigo sin invertir ningún tiempo ni recursos en mejorar el SEO ni usar técnicas siniestras como click bait para atraer visitantes. El que llega aquí es porque tenía que llegar 😉
En Twitter, sumamos 2.800 seguidores entre @jmaguilar y @variablnotfound, y 972 seguidores en Facebook, lo que son también unas cifras bastante importantes si tenemos en cuenta que no puedo dedicarles apenas tiempo y que funcionan principalmente con el piloto automático. También siguen creciendo los followers desde Feedly, que superan ya los 2.340.
Como en años anteriores, continúa el imparable crecimiento de visitantes de sexo femenino, que alcanza el 31%. Podéis entender mejor a qué me refiero con "imparable" si tenéis en cuenta que en 2016, hace solo seis años, las mujeres representaban únicamente el 17% de las visitas.
Por edades, la mayoría de visitantes se encuentran en la franja de 18-34 años, aunque sigue viéndose que cada vez tenemos más seniors en esta profesión, creciendo cada año en un porcentaje interesante. Está claro que nos vamos haciendo mayores, y eso se refleja en las estadísticas.
El 90% de los visitantes proceden de buscadores (básicamente Google), mientras que un 7% vienen de forma directa. Los países desde los que más visitantes acuden al blog son:

País | % |
---|---|
México | 22,6% |
España | 18,28% |
Colombia | 11,97% |
Argentina | 9,11% |
Perú | 7,68% |
Ecuador | 4,24% |
En cuanto a los navegadores utilizados, Chrome continúa siendo el líder en el 78% de los visitantes, y Edge (9,31%) ha superado a Firefox (7,23%) por primera vez. Curiosamente, aún el 1% de los visitantes usan alguna versión de Internet Explorer 😱
Otra cosa positiva de este año es que que algunas publicaciones fueron esponsorizadas por Syncfusion (¡muchas gracias!), lo que me ha permitido obtener algún dinerillo extra para, al menos, tener algún detallito para la familia, a la que mis extrañas aficiones roban tanto tiempo.
En definitiva, ahí seguimos desde este pequeño rincón de la red, intentando aportar nuestro granito de arena al inmenso desierto del conocimiento. Muchas gracias a todos los que seguís el blog por continuar haciéndolo posible después de tanto tiempo, y espero que estéis por aquí un año más, ayudándome a buscar la variable ;)
Publicado en Variable not found.
Variable not found
Enlaces interesantes 487
mayo 16, 2022 06:05

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Describiendo APIs ASP.NET Core con Swagger
José María Aguilar - 32 técnicas de producción de ideas
José María Aguilar
.NET Core / .NET
- Announcing .NET 7 Preview 4
Jeremy Likness - Regular Expression Improvements in .NET 7
Stephen Toub - Using the when Keyword in C# While Handling Exceptions
Code Maze - C# Tip: Convert ExpandoObjects to IDictionary
Davide Bellone - Configuring the Diagnostics Port for dotnet monitor
Mark Downie - Finding “routes” of all-pairs shortest paths with Floyd-Warshall algorithm in C#
Oleg Karasik - The Azure Cosmos DB Journey to .NET 6
Vinod Sridharan - Raw String Literals In C# 11
Wade Gausden - Serializing a Cookie container in C#
Infinite Loop - Override vs New Polymorphism In C# .NET
Wade Gausden - How to Find All Distinct Elements of a Given Integer Array
Jamil Hallal
ASP.NET Core / ASP.NET / Blazor
- APIs instantáneas en .NET
Miguel Teherán - ASP.NET Core updates in .NET 7 Preview 4
Daniel Roth - Announcing gRPC JSON transcoding for .NET
James Newton-King - General ASP.NET Performance Best Practices (Part-1)
Jamil Hallal - Blazor Vs. Angular
Ravindu Shehan Perera - Improving Azure Key Vault Performance in ASP.NET Core By Up To 10x
Scott Sauber - Testing ASP.NET Core gRPC services in JetBrains Rider
Andrew Lock - Deploying Blazor WebAssembly applications to Azure Static Web Apps
Damir Arh - Using ASP.NET Core MVC Value Providers With Minimal APIs
Khalid Abuhakmeh - Improving Performance With Distributed Caching
Assis Zang - Building Headless CMS on Azure Static Web Apps with Blazor WASM
Justin Yoo
Azure / Cloud
- Deploying on Azure Functions & Deploying a Static Site to Azure Using the az CLI
Anuraj Parameswaran - How to test for resilience with Azure Chaos Studio
Azure Tips & Tricks - Azure Functions: Background Jobs
Isaac Ojeda - Mapping a wildcard domain name to an Azure App Services
Anuraj Parameswaran - Setting up an Azure Virtual Machine as Azure DevOps build agent
Anuraj Parameswaran
Conceptos / Patrones / Buenas prácticas
- La notación húngara: la nomenclatura para programadores que Microsoft creó, que hoy rechaza… y que aun así se sigue usando (mal)
Marcos Merino - How Google Developers Don’t Write Their Comments
Minhaz - An Either monad
Mark Seemann - Use a gateway service for a software UI with micro services architecture?
Damien Bowden - A tale of a trailing dot
Daniel Stenberg - Domain Modeling - Anemic Models
Steve Smith - Microservices gets it WRONG defining Service Boundaries
Derek Comartin - Technical Debt: Types, Causes, Model, Practices, Measure
ThinkSys - How to hash passwords and when not to
Tamás Sallai
Data
- Announcing Entity Framework 7 Preview 4
Jeremy Likness
Machine learning / IA / Bots
- Introduction to Tensorflow.js with Real-World Example & Speech Recognition with TensorFlow.js
Nikola M. Zivkovic
Web / HTML / CSS / Javascript
- Announcing TypeScript 4.7 RC
Daniel Rosenwasser - Converting your vanilla Javascript app to TypeScript
Allan Almazan - A Guide on How to use Emit in Vue
Johnny Simpson - Performance Game Changer: Browser Back/Forward Cache
Barry Pollard - How to Make a CSS Slinky in 3D
Jhey Tompkins - Cross-browser native lazy loading in JavaScript
Kingsley Ubah - Let’s Create a Tiny Programming Language
Md Shuvo - Phone Number Validation in JavaScript
Jamil Hallal - COLRv1 and CSS font-palette
Ollie Williams - A Guide to Events in Vue
Johnny Simpson - Magical SVG Techniques
Cosima Mielke - 7 Things To Know Before Your Angular Interview
Nwose Lotanna Victor - Angular Async/Await: How To Use It
Svetloslav Novoselski - 10 Best Free Open Source JavaScript Lightbox Widgets and Plugins
Monty Shokeen - Complex State Management in React
Leonardo Maldonado - Implementing Route Protection in Angular using CanActivate
Lakindy Hewawasam - 4 Cool Hover Effects That Use CSS Text Shadow
Temani Afif
Visual Studio / Complementos / Herramientas
- Visual Studio 2022 17.2 is now available!
Tim Heuer - Update all Visual Studio installations with a single click!
Sayyeda Mussa - Just-in-time refactoring made even easier with IntelliCode auto suggested code for C#
Peter Groenewegen - Building a Stack Overflow browser as a VS extension
Thomas Ardal - Useful Tools for Creating AVIF Images
Sunkanmi Fafowora - Launching Tabs in Windows Terminal
Mark Heath
Xamarin / .NET MAUI / Crossplatform
- ActivityIndicator en .NET MAUI
Leomaris Reyes - .NET MAUI Release Candidate 3
David Ortinau - Introducing Flutter 3
Tim Sneath - View PDF Pages as Thumbnails Using Xamarin.Forms PDF Viewer
Ramkumar Ravy - Building a Task Sequence in Xamarin Forms/ MAUI (Part 2)
Rendy del Rosario - Tips for Moving Your Xamarin Library to .NET MAUI
Luis Matos - How to use biometric authentication in .NET MAUI
Andreas Nesheim - Getting Offline Country Data in Dotnet MAUI or Xamarin.Forms
Damien Tohin Doumer
Otros
- 6 YAML Features most programmers don’t know
Martin Thoma - The regex [,-.]
Paul Boyd - Ballerina: A Data-Oriented Programming Language
Yehonathan Sharvit
Publicado en Variable not found.
Variable not found
Constructores estáticos, inicializadores de módulos y startup hooks: tres formas de ejecutar código antes que Program.Main()
mayo 10, 2022 06:05

Solemos pensar que el punto de entrada de una aplicación .NET, ya sea el método estático Main()
del clásico Program.cs
o el nuevo Program.cs
de .NET 6 que utiliza top level statements, es lo primero que se ejecuta en nuestras aplicaciones, en realidad no es así. Hay vida antes de que nuestra aplicación empiece a correr ;)
Aunque obviamente su utilidad es limitada y no es algo que necesitaremos hacer a menudo (o probablemente nunca), es conveniente saber que existen varias formas de insertar código que se ejecute antes que lo que siempre hemos considerado el entry point de nuestra aplicación, y es lo que veremos en este post.
1. Constructores estáticos
La primera fórmula consiste en usar el constructor estático de la clase Program
, que es donde se encuentra en entry point. En aplicaciones de consola, escritorio, web, etc., esta clase es la que contiene el método estático Main()
que tradicionalmente ha actuado como punto de entrada del programa.
Dado que el constructor estático de una clase se ejecuta antes que cualquier otra cosa en ella, bastaría con insertar aquí nuestro código personalizado:
internal class Program
{
static Program() => Console.WriteLine("Hello from Program static constructor");
static void Main(string[] args) => Console.WriteLine("Hello from Main()");
}
El resultado de la ejecución de este código será:
Hello from Program static constructor
Hello from Main()
Si usamos .NET 6 o superior, la cosa cambiará un poco, pues la clase Program.cs
está algo escondida tras la magia de los top level statements de C#9. Pero de forma similar a la anterior, podríamos introducir el constructor estático de la siguiente manera:
// File: Program.cs
Console.WriteLine("Hello from Main()")
public partial class Program
{
static Program() => Console.WriteLine("Hello from Program static constructor");
}
El resultado obtenido por consola será el mismo que antes:
Hello from Program static constructor
Hello from Main()
2. Inicializadores de módulos
Otra posibilidad es el uso de inicializadores de módulos, una característica introducida también en C# 9 que permite ejecutar código justo cuando el ensamblado en el que se encuentre sea cargado en memoria. Este código debe encontrarse en métodos estáticos void
sin parámetros, decorados con el atributo [ModuleInitializer]
.
Los module initializers se ejecutan una única vez, cuando el ensamblado se carga para que cualquiera de los componentes definidos en el mismo sean utilizados. Por ejemplo, imaginad que tenemos una biblioteca .NET llamada MyClassLibrary
con las dos clases siguientes:
public class Initializer
{
[ModuleInitializer]
public static void Initialize()
{
Console.WriteLine("Hello from MyClassLibrary module initializer!");
}
}
public class MyClass
{
public MyClass() => Console.WriteLine("Hello from MyClass constructor");
}
Si referenciamos esta biblioteca desde nuestro proyecto principal y hacemos una referencia a MyClass
en su método principal, veremos que el inicializador de módulo de cla clase Initializer
se está ejecutando:
internal class Program
{
static Program() => Console.WriteLine("Hello from Program static constructor");
static void Main(string[] args)
{
Console.WriteLine("Hello from Main()");
var foo = new MyClass(); // Clase definida en MyClassLibrary
}
}
La salida será la siguiente. Fijaos que el inicializador de MyClassLibrary
se ha ejecutado al principio, para dejar el módulo inicializado antes de ser utilizado; tras ello, se ejecutó el constructor estático de Program
seguido del método Main()
y finalmente el constructor de MyClass
:
Hello from MyClassLibrary module initializer!
Hello from Program static constructor
Hello from Main()
Hello from MyClass constructor
Si además introdujésemos un constructor estático en la clase MyClass
, veríamos que éste se ejecuta en el orden esperado, justo antes del constructor de instancia:
Hello from MyClassLibrary module initializer!
Hello from Program static constructor
Hello from Main()
Hello from MyClass static constructor
Hello from MyClass constructor
El código de los inicializadores de módulos se ejecutará también si el ensamblado ha sido cargado de forma dinámica. Así, en el siguiente código, el método marcado con [ModuleInitializer]
será ejecutado al intentar usarlo:
// path contiene la ruta al archivo .dll del ensamblado
var assembly = AssemblyLoadContext.Default.LoadFromAssemblyPath(path);
var c = assembly.CreateInstance("MyClassLibrary.MyClass");
// Aquí ya se habrá ejecutado el module initializer
// y luego el constructor de MyClass
...
3. Startup hooks
Una opción más para ejecutar código antes del entry point es utilizar los startup hooks. A diferencia del caso anterior, donde los inicializadores estaban incluidos en ensamblados referenciados directamente desde el proyecto principal, en esta ocasión se trata de algo que podemos modificar dinámicamente en cada entorno de ejecución.
La idea consiste en establecer en la variable de entorno DOTNET_STARTUP_HOOKS
la ruta (o rutas, separadas por punto y coma) de una serie de ensamblados en cuyo interior se encuentra el código de inicialización a ejecutar, que debe encontrarse obligatoriamente definido en el método estático Initialize()
de una clase interna llamada StartupHook
.
Un ejemplo sería el siguiente código en una biblioteca de clases, llamada por ejemplo 'MyHook':
// Esta clase debe definirse en la "raíz" del proyecto,
// por lo que no la definimos dentro de un namespace concreto.
internal class StartupHook
{
public static void Initialize()
{
Console.WriteLine("Hello from the startup hook!");
}
}
Este código se ejecutará al arrancar cualquier aplicación .NET (Core), en su mismo proceso, antes que los constructores estáticos e incluso que los inicializadores de módulos, siempre que la ruta hacia su ensamblado se encuentre en la variable de entorno DOTNET_STARTUP_HOOKS
, como podemos ver a continuación con un proyecto simple que únicamente saluda al usuario por consola:
C:\HelloWorld\bin\debug\net6.0\>HelloWorld.exe
Hello world!
C:\HelloWorld\bin\debug\net6.0\>SET DOTNET_STARTUP_HOOKS=C:\Hooks\MyHook.dll
C:\HelloWorld\bin\debug\net6.0\>HelloWorld.exe
Hello from the startup hook!
Hello world!
Esta capacidad de ejecución previa de un ensamblado externo puede resultar interesante, sobre todo para hacer cosas raras. Por ejemplo, imaginad una aplicación de consola como la siguiente:
internal class Program
{
public static string Text { get; set; } = "Hello world!";
static void Main(string[] args)
{
Console.WriteLine(Text);
}
}
Aunque previsiblemente su ejecución finalizará mostrando por pantalla el texto "Hello world!", sería posible adjuntarle un startup hook que modifique este comportamiento utilizando reflection para alterar el valor justo antes de que se ejecute:
internal class StartupHook
{
public static void Initialize()
{
var program = Assembly.GetEntryAssembly()?.DefinedTypes
.FirstOrDefault(t => t.Name == "Program");
var textProperty = program?.DeclaredProperties
.FirstOrDefault(p => p.Name == "Text");
textProperty?.SetValue(null, "Text changed by the hook!");
}
}
De esta forma, una vez incluida la ruta hacia el ensamblado que contiene esta clase en la variable de entorno DOTNET_STARTUP_HOOKS
, lo que veríamos por consola sería lo siguiente:
C:\HelloWorld\bin\debug\net6.0\>HelloWorld.exe
Hello world!
C:\HelloWorld\bin\debug\net6.0\>SET DOTNET_STARTUP_HOOKS=C:\Hooks\MyHook.dll
C:\HelloWorld\bin\debug\net6.0\>HelloWorld.exe
Text changed by the hook!
Podéis ver otros usos divertidos de los startup hooks en este post de Kevin Gosse, donde pone del revés la salida por consola, o sobrescribe Array.Empty()
, entre otras diabluras ;)
Y si queréis leer algo más sobre los temas que hemos visto en el post, ahí van algunas referencias:
- Executing code before Main in .NET
Gérald Barré - Module Initializers In C# 9
Khalid Abuhakmeh - How to use .NET module initializers in a concrete real use case
Daniel Cazzulino - Module initializers - C# 9.0 specification proposals
Microsoft - Startup hooks
Microsoft
Publicado en Variable not found.
Variable not found
Enlaces interesantes 486
mayo 09, 2022 06:33

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- ¿Qué es Blazor, eso de lo que todo el mundo habla?
José María Aguilar - Cómo reconocer a los buenos desarrolladores
José María Aguilar
.NET Core / .NET
- Set C# Language Version for All the Projects in a Solution
Bartosz Jarmuż - Getting telemetry data from inside or outside a .NET application
Gérald Barré - How to install and test nuget packages locally
Gary Woodfine - Case Study: Double performance in under 30 minutes
Nik Karpinsky - Techniques and tools to update your C# project - Migrating to nullable reference types
Maarten Balliauw - Using HTTPListener to build a HTTP Server in C#
Nick Charlton - Upgrading a WCF service to .NET 6 with CoreWCF
Mike Rousos - Microsoft Graph's Journey to .NET 6
Joao Paiva - Challenge: Spot the optimization & Challenge: Spot the optimization–solution
Oren Eini - Quickly Map Your NuGet Packages to Sources
Erdembayar Yondon - Generating sortable Guids using NewId
Andrew Lock - One step beyond by using .NET Collections to its fullest
Ioannis Kyriakidis - On awaiting a task with a timeout in C#
Raymond Chen - Forcing HttpClient to use IPv4 or IPv6 addresses
Gérald Barré - Hacking C# - Adjustable arrays
Simon Painter
ASP.NET Core / ASP.NET / Blazor
- YARP 1.1 is here with new requested reverse proxy features
Sam Spencer - What's Coming for Blazor Hybrid in .NET 7
David Ramel - Implement an OpenIddict identity provider using ASP.NET Core Identity with Keycloak federation
Damien Bowden - Introduction to Google Charts With Angular and ASP.NET Core Web API
Code Maze - ASP.NET Core JavaScript Collocated TagHelper
Khalid Abuhakmeh - How to Return HTML From ASP.NET Core Web API
Code Maze - Using Background Services in ASP.NET Core
Shawn Wildermuth - Improving ASP.NET Core Before It Ships 🚢
Martin Costello
Azure / Cloud
- Improve Angular performance with Gzip compression on Azure Storage
Anuraj Parameswaran - How to test application performance with Azure Load Testing
Michael Crump
Conceptos / Patrones / Buenas prácticas
- At the boundaries, applications aren't functional
Mark Seemann - Commands, Events, Versions, and Owners
Steve Smith - You Probably Don't Need to Worry About MediatR
Jimmy Bogard - Real-World Event Driven Architecture! 4 Practical Examples
Derek Comartin
Data
- Migrating a production database without any downtime
Denis Stebunov - Current Limitations of Entity Framework Core
Ricardo Peres - Demystifying Database Performance for Developers
Christopher Winslett
Machine learning / IA / Bots
- Naive Bayes Classification Using C#
James McCaffrey
Web / HTML / CSS / Javascript
- A Guide to Understanding Vue Lifecycle Hooks
Johnny Simpson - Angular Basics: Angular Templates Overview
John Au-Yeung - Creating Realistic Reflections With CSS
Preethi - Semantic Versioning for TypeScript Types
Semver - CSS Generators
Marko Denic - Designing A Better Language Selector
Vitaly Friedman - Styling
select
elements for real
Patrick Brosset - Can the Composition API Replace Vue Mixins?
Isuri Devindi - Top 10 Angular Component Libraries for 2022
Nipuni Arunodi - How to Watch for Nested Changes in Vue
Johnny Simpson - Resilience, Flexibility And Immediacy: Working With Headless Systems
Stefan Baumgartner - You Don’t Need A UI Framework
Josh Comeau - Non-interactive Elements with the inert attribute
Tim Nguyen - The triple dot syntax (
...
) in JavaScript: rest vs. spread
Axel Rauschmayer - Master Higher-Order Functions in JavaScript
Chinedu Imoh - Just jQuery The Core UI
Ian Elliot
Visual Studio / Complementos / Herramientas
- Qué es un contenedor y su seguridad frente a máquinas virtuales
CampusMVP - Visual Studio Code April 2022
VS Code Team - Visual Studio on an ultra-wide monitor
Mads Kristensen
Xamarin / .NET MAUI
- Implementando un Calendario Horizontal en Xamarin.Forms
Vicente Guzmán - Easily Create and Bind Custom Event Objects in .NET MAUI Scheduler
Jeyasri Murugan - What’s New in .NET MAUI RC2
Vijay Anand - Design Tools for Xamarin Forms
Luis Matos - Handling Light and Dark Mode With .NET MAUI
Leomaris Reyes
Otros
Publicado en Variable not found.
Blog Bitix
Desempaquetado y análisis de teclado mecánico compacto e inalámbrico KEMOVE DK61
mayo 05, 2022 05:00
El KEMOVE DK61 es un teclado mecánico que mejora en varios aspectos y aúna varias de las mejores cosas que tienen los DIERYA DK61E y DK63 sin incrementar demasiado su precio con lo que si no se quiere ajustar el presupuesto al máximo compensa por las características mejoradas. El KEMOVE DK61 es muy compacto, de formato 60% con con la ventaja de tener un tamaño reducido y el inconveniente de no tener algunas teclas. Similar al DIERYA DK61E pero que incorpora la conexión inalámbrica del DK63 e incrementa su autonomía con una batería de mayor capacidad y conservando la iluminación RGB. En otras características como switches y keycaps está a la altura de un buen teclado de gama alta pero que en este caso el KEMOVE a un precio por debajo de los 100€.
Hay una buena cantidad de teclados mecánicos entre los que elegir en base a las necesidades propias y las características de los teclados entre las que está el formato o número de teclas que tienen y por supuesto su precio entre otras. Aunque hay muchos teclados mecánicos muchos no están destinados de forma específica a los usuarios que los utilizan con disposición de teclas en español, otros cuantos ni siquiera se venden en tiendas españolas y no es tan fácil encontrar keycaps con la disposición española que tenga por ejemplo la letra ñ y la tecla de tilde. Sin embargo, hay algunos disponibles y dada la versatilidad y personalización de los teclados mecánicos se pueden adaptar a las necesidades propias con algunos pasos adicionales.
La marca KEMOVE me envía un nuevo teclado mecánico el KEMOVE DK61 para realizar su desempaquetado y análisis en este artículo que compararé con los anteriores DIERYA me envió con anterioridad y publique en sus respectivos artículos. KEMOVE es una marca de mayor calidad que se nota en varios aspectos de los teclados pero sin tener un precio significativamente mayor.
Contenido del artículo
Características técnicas del teclado KEMOVE DK61
El KEMOVE DK61 es un teclado mecánico compacto que tiene una combinación de características de los DIERYA DK61E y el DIERYA DK63. La marca KEMOVE se diferencia de la marca DIERYA en la calidad de los teclados y materiales, también sus teclados tiene un precio ligeramente mayor pero sin ser excesivamente mucho más y que salvo que se quiera ajustar el presupuesto la diferencia de precio compensa en las las mejoras proporcionadas. Loas DIERYA aún siendo unos buenos teclados con un precio muy ajustado para lo que ofrecen tenían algunos puntos a mejorar, algunos de ellos han sido resueltos en el KEMOVE DK61.
- Desempaquetado y análisis de teclado mecánico compacto DIERYA DK61E
- Desempaquetado y análisis de teclado mecánico compacto e inalámbrico DIERYA DK63
En cuanto a formato el KEMOVE DK61 es igual que el DIERYA DK61E, un teclado en formato 60% compacto de 61 teclas que prescinde de las teclas del teclado numérico, las teclas de función, las teclas de flechas y las del bloque superior como insertar, suprimir, inicio, fin, retroceder página, avanzar página, las teclas de función y algunas más.
Tener menos teclas tiene algunas ventajas, principalmente que el teclado ocupa menos espacio en la mesa y el ratón no queda tan lejos que usando un teclado completo con teclado numérico, otra ventaja es que es más fácilmente transportable. La desventaja es que al tener menos teclas algunas han de usarse como una combinación de teclas que si su uso es muy habitual resulta incómodo hasta acostumbrarse.
El KEMOVE DK61 se ofrece en varios tipos de switches, en Amazon están las versiones con los switches Gateron en diferentes colores y tanto lineales, táctiles y sonoros o clicky pero en la página de KEMOVE también se encuentra switches de las marcas Cherry MX y Kailh. En cualquier caso dado que el teclado es hot swappable estos se pueden intercambiar por otros que sean compatibles, el requerimiento es que sean de tres pines, compatibles con RGB si no se desea perder esta funcionalidad y de tipo cherry mx para reutilizar los mismos keycaps.
El ejemplar que tengo tiene switches Gateron Brown del tipo táctil, la diferencia entre este tipo de táctil y los lineales es muy poca y apenas es perceptible en el uso normal. Los switches lineales suelen ser preferidos por los que usan el teclado como jugadores y los táctiles suelen ser preferidos por aquellos que le dan un uso más a escribir texto, aunque cualquiera de los dos tipos sirven para ambas tareas siendo un preferencia personal que tipo usar. Como los switches son intercambiables si en algún momento se prefieren otros tanto de otro tipo como de otra marca compatible se pueden cambiar. Otra ventaja de que los switches sean intercambiables es que si alguno es defectuoso o se estropea con el uso se puede reemplazar por otro lo que prolonga la vida del teclado y no hay que desecharlo simplemente porque una tecla deja de funcionar correctamente.
El teclado tiene iluminación RGB en diferentes colores, efectos e intensidad que más allá del aspecto estético de tener colores resulta útil en caso de bajas condiciones de luz para ver las teclas. Además la iluminación RGB se utiliza para proporcionar algunas indicaciones al pulsar teclas como por ejemplo conocer de forma aproximada la carga de la batería.
El teclado tiene la posibilidad de funcionar tanto con cable como de forma inalámbrica mediante Bluetooth pudiendo configurar hasta tres dispositivos de forma simultánea. La conexión Bluetooth es fácil de configurar poniendo el teclado en modo configuración momento en el que es detectado por el dispositivo en el que se quiere usar y se completa la configuración. Utiliza una batería de 3000 mAh que le da para varias semanas de uso hasta la siguiente carga incluso con un uso diario de varias horas. La conexión es fiable y al tener batería no hace falta usar pilas ni reemplazarlas cada cierto tiempo.
El cable permite al teclado funcionar mediante cable que al ser Bluetooth en algunos casos es necesario como por ejemplo al acceder a la BIOS, el cable también sirve para cargar la batería del teclado. Es USB de tipo C para la conexión al teclado y de tipo A para la conexión al ordenador, destacando que es un cable de calidad como era en los DIERYA siendo mallado y reversible en ambos extremos lo que facilita su conexión en cualquier orientación del cable.
Las características completas del teclado son:
- Cuerpo del teclado de plástico robusto y buena construcción, regulable en altura en una posición con patas extensibles.
- Teclado 60%, 61 teclas.
- Sin teclas de desplazamiento.
- Disposición ANSI con teclas en inglés.
- Switches Gateron, Cherry MX o Kailh, intercambiables o hot swapabble.
- Keycaps PBT de doble disparo para la leyenda principal, pad printing para la serigrafía de función que está serigrafiada en el lateral de las teclas.
- Switches y keycaps incluídos y premontados.
- Iluminación RGB con varios efectos de luz e intensidad.
- Cable mallado desmontable USB Tipo C y Tipo A ambos reversibles.
- Conexión dual, con cable y/o Bluetooth 5.1 hasta 3 dispositivos, con batería recargable de 3000 mAh.
- Indicativo del nivel de carga de batería con una combinación de teclas.
- Incluye cubre teclado de plástico para evitar polvo.
Para conocer más detalles sobre los teclados mecánicos y en qué se diferencia de los teclados de membrana con una guía de introducción escribí el siguiente artículo comentando sus principales características, así como varios desempaquetados y análisis de teclados mecánicos con la que comparar con otros modelos más en detalle. Escribí una introducción a los conceptos básicos de los teclados mecánicos puedes visitar la guía de ese artículo y si quieres compararlo con un tecla de otra marca y tipo para saber cual te conviene según tus necesidades o preferencias escribí un Desempaquetado de teclado mecánico Glorious GMMK TKL junto con otros buenos modelos de teclados a considerar.
Diferencias con los teclados DIERYA DK63 y DK61E
Los modelos DIERYA DK63, DK61E y el KEMOVE DK61 son modelos muy parecidos entre ellos, pero examinando los detalles del KEMOVE DK61 se nota que es un teclado con algunas características que aúnan lo mejor de todos. Empezando porque el KEMOVE DK61 es inalámbrico al igual que el DK63 al contrario que el DK61E que solo era cableado, pero tiene una gran batería de 3000 mAh mayor que la del DK63 que era de 1900 mAh.
Tiene patas para regular la altura que ninguno de los DIERYA ofrecía. El switch para activar la conexión inalámbrica está en el lateral del teclado más accesible que en la parte inferior del DK63 y con un switch con un acabado de mejor calidad. La serigrafía de las funciones en vez de en la parte superior de la tecla está en un lateral, esto tiene la ventaja de que al ser de tipo pad printing evita que se desgaste y por otro lado hace la tecla más legible al tener menos símbolos en la parte superior para funciones que se usan menos habitualmente. Aún estando en un lateral la serigrafía es perfectamente legible desde la posición de uso. El backplate es de color blanco que resalta la iluminación RGB y finalmente se incluye un muy útil cubre teclado de plástico para evitar polvo cuando no se usa.
Consideraciones a tener en cuenta
Al ser un teclado compacto hay que considerar que algunas teclas han de usarse como una combinación, hasta acostumbrarse puede resultar incómodo. También hay que tener en cuenta que es un teclado con disposición ANSI que es diferente de la habitual en España que es ISO, tiene algunas diferencias en los tamaños de algunas teclas como la tecla Return. En caso de querer keycaps con serigrafía de teclado en Español hay que comprarlas aparte, en AliExpress hay unos keycaps con disposición en Español que usa mucha gente.
La conexión inalámbrica es Bluetooth con lo que requiere de que el dispositivo donde se tenga Bluetooth y esté la conexión disponible, por esto al acceder a la BIOS del equipo es probable que requiera utilizar la conexión por cable que tampoco es demasiado inconveniente.
Dónde comprar
El teclado mecánico KEMOVE DK61 se puede comprar directamente en la página oficial al mejor precio con la ventaja de poder hacer el pago mediante PayPal así como otros accesorios como una funda de transporte para el teclado, keycaps y switches. Si el modelo elegido está disponible en la página de Amazon del propio país lo envían directamente de Amazon en vez de China a un precio de unos 90 € y algo más barato en los momentos en tiene aplicado un descuento en el precio.
Aparte de este modelo la marca tiene disponibles otros modelos de teclado compactos como el DIERYA DK61E, el DIERYA DK63 y el DIERYA DK61 Pro, ambos DK61 son iguales pero el Pro tiene con conexión inalámbrica también por Bluetooth.
Si después de leer el artículo decides comprar uno de estos teclados y en el momento que vas a hacerlo no tiene algún descuento envíame un correo electrónico que puedes encontrar en la página Acerca de y le pido a la marca un cupón descuento para que puedas aplicarlo en el momento de realizar la compra.
- Página del fabricante del teclado KEMOVE DK61
- Página del fabricante del teclado DIERYA DK63
- Página del fabricante del teclado DIERYA DK61E
- Página del fabricante del teclado DIERYA DK61 Pro
- Manual de usuario del teclado DIERYA DK63
Desempaquetado del teclado mecánico KEMOVE DK61
La caja
La caja del KEMOVE muestra el logotipo de la marca en la parte delantera y y se compone de una ventana que con el protector de plástico del teclado deja ver una parte del él, tiene una serigrafía con relieve únicamente por motivos estéticos pero que indica que hasta la caja está cuidada.
En la parte trasera se muestran dos ilustraciones y las características básicas del teclado. En uno de los laterales otra forma de logotipo de la marca y las características del ejemplar del teclado incluyendo el modelo, color y switches. La caja está precintada por un plástico que impide que entre suciedad o líquidos durante el transporte y esté en perfectas condiciones hasta el momento de abrirla.
El contenido de la caja
El contenido de la caja aparte del propio teclado se compone de su manual de usuario en el que se muestran los diferentes grupos de teclas que se usan en combinación con la tecla de función junto con la descripción de que hacen que es útil como referencia en caso de cambiar los keycaps, el cable para la conexión al ordenador y carga de la batería, una tarjeta de garantía, un extractor de keycaps y un extractor de switches y tres switches adicionales para probar otros tipos de switches o reemplazar alguno, también sirven como reemplazo en caso de que alguno se estropee.
Contenido de la caja:
- El teclado.
- Cable USB.
- Un pequeño manual con las combinaciones de teclas.
- Cubre teclado de plástico para evitar polvo.
- Un extractor de keycaps.
- Un extractor de switches.
- Una tarjeta con la garantía ofrecida.
- 3 switches adicionales de otros colores.
Un detalle que en mi caso echaba en falta en los DIERYA era que no incluían una tapa protectora para cuando el teclado no se está usando y evitar que se le acumule polvo. El KEMOVE incluye esa tapa de plástico que a mi me resulta muy útil, un detalle a la altura de de los mejores teclados y que no se suele encontrar en teclados en el rango de precios del KEMOVE. Además, este plástico que también forma parte del empaquetado permite en vez de desechar todo el embalaje después de abierto darle un uso durante toda la vida del teclado que será de más de un lustro e incluso una década.
El teclado
El cuerpo del teclado es completamente de plástico que da sensación de resistente con un pequeño biselado en la parte delantera. En gran medida tiene el mismo aspecto de los DIERYA y es que el teclado tampoco necesitaba ninguna mejora adicional. Las diferencias están en la parte trasera que incluye el nombre de la marca y las patas que permite regular la altura al menos en una posición cosa de las que carecían los DIERYA. Por otro lado en este KEMOVE tiene dos interruptores que están en el lateral para activar el modo inalámbrico y cambiar el modo de compatibilidad entre Windows y macOS.
El teclado se ofrece en dos colores el negro donominado shadow y blanco denominado snowfox tanto para el cuerpo del teclado como para los keycaps. La estabilidad en las teclas grandes como la barra espaciadora y las teclas de shift es buena. Que el teclado sea RGB siendo inalámbrico, que el cable sea desmontable y que los switches sean intercambiables es algo que no se suele encontrar en teclados en el rango de precios alrededor de 90 € en los que se ofrece el KEMOVE, estas características se suelen ofrecer en teclados en un rango de precios superior.
En el modo de funcionamiento inalámbrico permite configurar hasta tres dispositivos para cambiar de uno a otro según se desee con la combinación de teclas FN+Z, FN+X y FN+C. Es compatible tanto con Windows, macOS, como con GNU/Linux y Android reconociéndose todas las teclas incluidas las de función multimedia para controlar la reproducción y el volumen de sonido.
Conserva las mismas dimensiones que los DIERYA DK61E y DK 63, siendo para el KEMOVE DK61 de 29 cm de ancho, 10 cm de largo, por unos 3 cm en la parte baja y unos 4,5 en la parte alta de altura incluyendo los keycaps. Con las patas extraídas para regular la altura su altura llega a los 4,5 cm.
Los switches
El teclado se ofrece premontado con switches Gateron, Cherry MX y Kailh, los primeros están en Amazon y se envían desde el país de la página si están disponibles, los Kailh se ofrecen en la página de KEMOVE. Por supuesto, se ofrece una amplia gama de colores dentro de los Gateron, que incluyen los tres tipos básicos de lineales, táctiles y sonoros, dentro de estos tipos básicos algunos con mayor resistencia para aquellos que prefieran unas teclas que sean algo más duras.
En cualquier caso dado que el teclado es hot swappable permite cambiar los switches por cualesquiera otros de otra marca que sean compatibles. Los switches han de ser de tres pines y eléctricos, si se desea conservar la iluminación RGB ha de ser compatible también con el RGB.
En la página de Gateron hay una leyenda con la descripción de cada switch según su color tanto de qué tipo son, su fuerza de actuación y recorrido. En general unos rojos para los lineales y los marrones para los táctiles son los más comunes.
Los keycaps
Los keycaps son de plástico PBT considerado generalmente mejor por ofrecer mayor durabilidad que el plástico ABS más barato, el plástico PBT no es de lo más gruesos que hay pero es más que suficiente y no presenta ningún problema en su uso y durabilidad. La serigrafía para las leyendas principales de la tecla es de doble disparo o double shot que evita que con el uso se deteriore como ocurre en otras formas de impresión más baratas pero también de peor calidad. La leyenda de las teclas de función es de pad printing que no ofrece las mismas garantías de durabilidad pero al está en una lateral del keycap que no se suele tocar con los dedos su durabilidad no es afectada, por otro lado, al esta la leyenda de las teclas de función en un lateral hace que las teclas tengan un aspecto limpio y la leyenda principal se vea sin ninguna distracción.
Al ofrecerse un cubre teclado permite minimizar la cantidad de polvo que se acumula entre teclas cuando no se usa, en cualquier caso en caso de que pasado un tiempo las teclas acumulen algo de polvo entre la teclas o en el backplate los keycaps se pueden desmontar de los switches y realizar una limpieza a fondo de tal forma que quede tan limpio como el primer día de uso.
Análisis y primeras impresiones del teclado mecánico KEMOVE DK61
Al usarlo no he tenido ningún inconveniente para que el teclado sea reconocido por cualquiera de los sistemas operativos donde lo he probado tanto de forma cableada como de forma inalámbrica, las pulsaciones se registran de forma inmediata, en el modo inalámbrico la latencia es imperceptible y la conexión inalámbrica se muestra estable.
Realizar la conexión inalámbrica se hace en unos pocos segundos activando el teclado en modo configuración y emparejándolo en el dispositivo donde se desea usar. El teclado se pone en modo configuración manteniendo durante unos segundos la combinación de teclas FN+Z, FN+X y FN+C. La conexión inalámbrica es útil para usarla tanto en un ordenador, como en un smartphone, consola o televisión inteligente incluido poder usar la conexión inalámbrica en dispositivos en ubicaciones diferentes como en la oficina y en casa. Tanto en los smartphones, como en las consolas y televisiones inteligentes es muy útil que el teclado sea inalámbrico sin cables, en el caso de la televisión desde el sofá, en un ordenador si se tiene en la habitación desde la cama y en un smartphone sin tener que utilizar la pantalla táctil y con con la misma experiencia de uso que un ordenador por ejemplo al escribir un documento o redactar un correo electrónico.
Al ser de 60% sigue siendo un modelo muy compacto, ligero y fácilmente transportable. Pero los teclados 60% no son para todos los usuarios y algunos prefieren los TKL para no perder algunas teclas. Desconozco si la limitación de de hasta tres dispositivos es una limitación técnica o de costes pero quizá incluso para algunos usuarios poder configurarlos con más dispositivos sería útil dados los varios dispositivos como los mencionados anteriormente donde se puede usar un teclado inalámbrico, se tarda poco en realizar la configuración pero sería innecesario si pudiese utilizarse en hasta 5 o 7 dispositivos. Aún así la mayoría de teclados inalámbricos solo permiten hasta tres dispositivos por lo que no es un defecto respecto a modelos de otras marcas.
Que los switches para cambiar entre el modo inalámbrico y modo de compatibilidad entre Windows y macOS estén en un lateral es más cómodo y de acceso más fácil que si estuviese en la parte inferior como ocurre en el DK63. Que el backplate sea blanco hace destacar la iluminación RGB y que ofrezca una tapa de plástico para cubrir el teclado es un detalle que seguro los usuarios que lo usen lo agradecen para evitar el polvo.
Algunos de estos detalles es algo que echaba en falta en los DIERYA y que en los KEMOVE están resueltos, aunque si no estoy equivocado en la serigrafía de la tecla dónde está el F11 tiene el mismo error de serigrafía que el DK61E estando los caracteres en la posición contraria. Dónde está el - debería estar el _, no es algo muy grave pero al ser algo de diseño es algo que seguro se podría corregir si añadir costes de fabricación.
Compatibilidad con sistemas operativos
Lo he probado tanto en GNU/Linux, macOS y Android, en todos estos sistemas operativos el teclado es detectado correctamente en el momento que se pone en modo de configuración. Permite cambiar de uno a otro sistema con la combinación de teclas. Si es compatible con esos sistemas operativos es seguro que lo será también con Windows tal y como se indica en su caja de empaquetado. Para Windows se ofrece una aplicación de escritorio para configurar la iluminación y macros de teclado, los controladores y manual de usuario. Al tener un botón de compatibilidad para macOS las teclas se adaptarán es modo de funcionamiento específico de macOS.
Análisis en vídeo
Aquí muestro un vídeo con la parte frontal del teclado visto desde la posición de uso y cerca tanto sin iluminación RBG como con iluminación RGB y en YouTube hay una buena cantidad de vídeos que analizan y hacen el desempaquetado de este modelo de teclado KEMOVE DK61. En los vídeos se explican detalles desde otro punto de vista, información adicional o complementaria a la ofrecida en este artículo.
Conclusión
El teclado KEMOVE mejora en varios aspectos a los teclados DIERYA sin incrementar demasiado su precio. Un precio que sigue siendo muy ajustado y con características que otras marcas ofrecen en un rango de precios más elevado. Encontrar un teclado con teclas PBT de doble disparo, que sea hot swappable, inalámbrico por Bluetooth y cableado, con iluminación RGB en este rango de precios no es tán fácil de encontrar.
Para algunos el mayor inconveniente sea tener unos keycaps en disposición de español si se quieren cambiar que en AliExpress hay varios vendedores que los ofrecen teniendo en cuenta que esto incrementa algo el precio del teclado y teniendo en cuenta que la serigrafía de las teclas de función se pierde. Otro aspecto a tener en cuenta es que carece de teclas de flechas dedicadas y teclas de bloque superior motivo por el cual algunos optan por modelos TKL con las mismas teclas y solo prescindiendo del teclado numérico.
El KEMOVE DK61 en los aspectos más importantes no tiene nada que envidiar a teclados considerados de gama alta y es que el KEMOVE puede considerarse también de gama alta, pero a diferencia de muchos otros tiene un precio asequible que se mantiene ajustado para muchos usuarios. Si se desea un teclado 60% con disposición ANSI e inglés sabiendo que se pueden cambiar los keycaps es una muy buena opción de compra pudiendo hacerlo además en Amazon o en su propia página a través del medio de pago PayPal.
Complementos para el teclado
Al comprar un teclado mecánico puede interesar comprar a la vez otros complementos para el teclado, como un concentrador USB para tener los puertos de conexión cerca especialmente si se suele estar conectando y desconectando dispositivos o el ordenador tiene difícil acceso a los puertos USB estando en la parte trasera del ordenador de torre.
En páginas como AliExpreses hay multitud de vendedores que venden conjuntos de keycaps y la marca KEMOVE también varios conjuntos de keycaps y switches. Una de las ventajas de los teclados mecánicos es poder personalizarlos y los keycaps es una forma, pudiendo elegir diferentes layouts o colores para algunas teclas como forma de distinción y hacer del teclado una pieza única.
Otro producto interesante es una alfombrilla de gran tamaño que permite colocar tanto el teclado como el ratón, permite evitar el desgaste de la mesa o ensuciarla. Algunas alfombrillas incluso con iluminación RGB que aparte de su efecto estético puede resultar también útil en condiciones de baja iluminación.
Finalmente, en caso de querer transportar el teclado es aconsejable comprar una funda para protegerlo en el transporte que KEMOVE vende en su página web o en algún momento también está disponible en Amazon y evitar que sufra algún deterioro en el transporte principalmente para proteger los keycaps.
Variable not found
Enlaces interesantes 485
mayo 03, 2022 06:05

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- ¿Recomendarías a tu hijo que se dedicase al mundo del desarrollo de software?
José María Aguilar - Incluir recursos estáticos en una Biblioteca de Clases Razor (RCL)
José María Aguilar
.NET Core / .NET
- Dockerfile para .Net 6
Fernando Escolar - CoreWCF 1.0 has been Released, WCF for .NET Core and .NET 5+
Sam Spencer - C++ For C# Developers: Part 1 – Introduction
Jackson Dunstan - How to generate Fake data in C#?
Karthik Chintala - Annotating your C# code - Migrating to nullable reference types
Maarten Balliauw - Create .NET Objects without Calling The Constructor
Khalid Abuhakmeh - Sharing coding style and Roslyn analyzers across projects
Gérald Barré - Different Ways to Implement IHttpClientFactory in .NET Core Apps
Mahesh More - Using User Secrets Configuration In .NET
Wade Gausden - C#: Add event handlers dynamically using reflection
Mike Hadlow
ASP.NET Core / ASP.NET / Blazor
- Consejos para mejorar el rendimiento de Blazor en ASP.NET Core
CampusMVP - [Parte 11] ASP.NET Core: Application Insights y Serilog
Isaac Ojeda - What’s Coming for Blazor in .NET 7?
Jon Hilton - Implementing Rate Limiting in ASP.NET Core Web API
Anuraj Parameswaran - ASP.NET Core: Custom Controller Action Parameter Binding using TryParse in Minimal APIs
Jaliya Udagedara - Distributed Caching in ASP.NET Core
Muhammed Saleem - ASP.NET Core 7 has built-in dark mode for error pages
Thomas Ardal - Multiple Directories for Static Files in ASP.NET Core
Shawn Wildermuth - How to get the full public URL of ASP.NET Core
Niels Swimberghe - Introduction to Testing Blazor WebAssembly With bUnit
Code Maze - Why isn't my ASP.NET Core app in Docker working?
Andrew Lock - Long-Running Tasks in a Monolith ASP.NET Core Application
Code Maze - Use the Query String to pass an array of selected values between Blazor Pages
Jon Hilton - Learn Blazor WebAssembly and Web API on .NET 6 by Building a Shopping Cart App
Beau Carnes
Azure / Cloud
- Suscribirte a los eventos de una cuenta en Azure Storage desde otro tenant con Azure Event Grid
Gisela Torres - Two Approaches of Dynamically Generating Images with Azure Functions
John kilmister - Working with Queues and Topics in Azure Service Bus
Will Velida - AWS Introduces the .NET Annotations Lambda Framework in Preview
Steef-Jan Wiggers
Conceptos / Patrones / Buenas prácticas
- How to use the Strategy Pattern in C#
Gary Woodfine - The Maybe monad
Mark Seemann - Top 9 Reasons To Unit Test Your C# Code
Vyom Srivastava - How to Mangle your git History
Ben Lorantfy
Web / HTML / CSS / Javascript
- What is DocumentFragment and createDocumentFragment() in JavaScript
Code Topology - 5 Useful TypeScript Features In VS Code
Daniel Fyhr - A Step-By-Step Guide to Server-Side Rendering with VueJS
Minura Samaranayake - What If Our Sliders Actually Slid?
Jhey Tompkins - Nested Components in a Design System
Dan Christofi - Angular Basics: Track Incoming Data With TrackBy Method
Dany Paredes - Private class fields in Javascript (ES2022)
Smitter hane - HTML event handler attributes: down the rabbit hole
Phil Eaton - Non-interactive Elements with the inert attribute
Tim Nguyen - Cool Hover Effects That Use Background Properties
Temani Afif - How the TypeScript Parameters Type Works
Johnny Simpson - Legacy String Methods for Generating HTML
David Walsh - Four Eras of JavaScript Frameworks
Chris Garrett - Chrome 102: Window Controls Overlay, a Host of Finished Origin Trials, PWAs as File Handlers and More
Chromium Blog - Functional Dependency Injection in Typescript
Hugo Nteifeh - Creating the DigitalOcean Logo in 3D With CSS
Jhey Tompkins
Visual Studio / Complementos / Herramientas
- Visual Studio 2022 for Mac Release Candidate
Jordan Matthiesen & Dominic Nahous - 5 Useful TypeScript Features In VS Code
Daniel Fyhr - Bringing code navigation to communities
The GitHub Blog
Xamarin / .NET MAUI
- .NET MAUI Release Candidate 2
David Ortinau - Top 10 Features of .NET MAUI Scheduler
Jeyasri Murugan - Replicating Foodora UI in .NET MAUI - Part 4
Andreas Nesheim
Otros
Celebrating 40 years of ZX Spectrum ❤️ 💛 💚 💙
The GitHub Blog
Publicado en Variable not found.
Blog Bitix
Cómo usar el comando git bisect para descubrir el primer commit con un error
abril 28, 2022 05:00
El comando git bisect es muy útil cuando se desea encontrar en que commit se ha introducido un error en un rango de commits ya que permite automatizar la búsqueda sin tener que hacerlo manualmente el desarrollador que simplemente se limita a indicar a Git si el commit a analizar en cada prueba es correcto o incorrecto. Una vez descubierto en que commit se ha introducido el error es cuestión de revisar los cambios de ese commit, analizar sus cambios e identificadas las líneas de código erróneas aplicar la solución.
Una herramienta de control de versiones para el código fuente de las aplicaciones es esencial, para guardar todos los cambios realizados en el código y permitir compartir código entre los desarrolladores aparte de otras funcionalidades proporcionadas. Una de las herramientas de control de versiones más populares es Git, desarrollado por Linus Torvalds también autor original de núcleo Linux entre otros colaboradores.
Una situación habitual al realizar cambios en el código fuente de un programa es pasado un tiempo descubrir un error y no conocer en que cambio lo ha producido y en que commit. Si no se tiene una pista de cual es el cambio que ha introducido error una solución es probar cada commit y para ver si esa versión de la aplicación tiene el error o no. Una vez probados varios commit al final se descubre que commit es el que ha introducido el error. Conociendo el commit que introduce el error hay que revisar los cambios de ese commit para conocer y cambiar las líneas de código erróneas.
El comando git bisect
Una de las funcionalidades que proporciona la herramienta de control de versiones Git es el subcomando bisect. El comando git bisect automatiza encontrar que commit ha introducido un error dado un rango de commits en el que se sospecha está el commit con el error.
El comando git bisect aplica un algoritmo de búsqueda al rango de commits, en función de la indicación que se le proporcione de si el commit tiene o no el error al final del número de comprobaciones que sean necesarias proporciona el primer commit con el error en el rango analizado.
El comando git bisect no se utiliza tan habitualmente como git stash o git commit pero cuando cuando es necesario es muy útil conocer como se usa y usarlo.
El primer paso del comando git bisect es iniciar la bisección y proporcionar el rango de commits a analizar. Una vez proporcionado el rango de commits git cambia el commit del espacio de trabajo según su algoritmo de búsqueda. El siguiente paso suele consistir en arrancar la aplicación y comprobar si el commit tiene o no el error. Una vez conocido si el commit es correcto o tiene el error se le indica a Git con el comando git bisect good o git bisect bad respectivamente. Git a continuación selecciona otro commit teniendo que comprobar de nuevo si el nuevo commit seleccionado es correcto o incorrecto. Después de varias repeticiones de estos pasos se descubre el commit en el que se introdujo el error.
Una vez terminada la bisección o en cualquier momento se puede dar por terminada con el comando git bisect reset y volver a un espacio de trabajo fuera del bisect. El comando git bisect view permite ver el estado de la bisección y los commits analizados.
Estos con los comandos básicos y un ejemplo de uso.
|
|
|
|
|
|
Metodologías ágiles. De lo racional a la inspiración.
Open Space, para un roto o para un descosido
abril 28, 2022 07:03
Header Files
Extendiendo el autocompletado en Bash
abril 26, 2022 06:45
Introducción
Personalmente creo que hay cuatro acciones de teclado que consumen el 70% de mi tiempo en una terminal: Enter, Control-C, Arriba y Tab. Las dos primeras para iniciar y parar comandos, y las dos últimas para agilizar la escritura, bien sea buscando en el historial o bien completando el nombre del comando actual.
Respecto al autocompletado, algunas shell, como Bash, permiten además hacer un autocompletado contextual, es decir, que una vez introducido el nombre del comando que se quiere ejecutar el motor de autocompletado ofrecerá las opciones pertinentes en base a dicho comando y a las opciones previamente seleccionadas. Esto no sólo ahorra tiempo de escritura, sino que además sirve de complemento a la ayuda del propio comando.
En esta entrada expondremos cómo crear un script de autocompletado propia, de forma que podamos incluirlo en nuestros proyectos. Aunque me centraré en la shell Bash, esta funcionalidad también es posible para otras: en cmd (Windows) mediante clink (usando Lua), PowerShell mediante funciones TabExpansion, zsh mediante zsh-autocomplete (aunque en este caso habría que extender el proyecto base).
Pre-requisitos
Además de tener Bash como shell activa, necesitaremos el paquete bash-completion
y activarlo en nuestra sesión. Podemos seguir las instrucciones listadas acá.
Diseñando el script
Comenzaremos detallando el comando al que queremos dar soporte, para luego mostrar y explicar el script en cuestión.
Sintaxis del comando
Vamos a suponer que nuestro comando se llama headerfiles
y tiene la siguiente sintaxis:
headerfiles [-h --help -j -f <nombre_de_fichero> -e [-x|-p] -o [slow|fast]]
Particularidades:
-x
y-p
sólo están disponible si-e
ha sido definido previamente.-x
y-p
son mutuamente excluyentes.-f <nombre_de_fichero>
puede ser especificado varias veces.-j -e
no presentan problems si se indican varias veces, pero es equivalente a que sólo se indicasen una vez.-o
sólo puede ser especificado una vez.-h --help
tienen prioridad sobre cualquier otra opción.
El script
El primer paso será crear un fichero para guardar las funciones del script. Personalmente los suelo guardar en una ruta del tipo <proyecto>/scripts/autocomplete/headerfiles.bash
, pero queda a vuestra discreción.
Hay, como es imaginable, varias formas de programar este autocompletado personalizado, pero mostraré la que a mí particurmente me resulta más sencilla mentalmente, aunque no necesariamente sea la más eficiente: definir una función que fije la variable de entorno COMPREPLY
. y pasar dicha función como argumento de complete
, junto con el nombre de nuestro comando (Bash usará este nombre para determinar si debe llamar a nuestro autocompletado particular o a algún otro). La variable COMPREPLY
es usada por complete
como la lista de opciones que se mostrarán. Como ayuda, usaremos el comando compgen
para generar, de forma amigable, dicha lista de opciones.
Presento el script correspondiente a la sintaxis antes mencionada y luego procedo a su explicación:
#/usr/bin/env bash
# Prints 1 if the given option has already been specified, 0 otherwise
has_option() {
for i in "${COMP_WORDS[@]}"; do
if [[ "$i" == "$1" ]]; then
echo "1"
return
fi
done
echo "0"
}
# Function to be called when auto-completing
_headerfiles() {
COMPREPLY=()
# These options have the highest precedence, so ignore any other if they've been specified
if [[ "$(has_option -h)" == "1" || "$(has_option --help)" == "1" ]]; then
return 0
fi
local cur=${COMP_WORDS[COMP_CWORD]}
local prev=${COMP_WORDS[COMP_CWORD - 1]}
case $prev in
# Options with additional arguments
"-f") COMPREPLY=(`compgen -f -- $cur`) ;;
"-o") COMPREPLY=(`compgen -W "slow fast" -- $cur`) ;;
# Any other option
*)
# This variable will contain the list of available options
local AVAILABLE_OPTIONS=()
# List of supported options that can be used only once
local ALL_ONCE_OPTIONS=("-e -o -h --help")
# Add dependant options
if [[ "$(has_option -e)" == "1" ]]; then
# Mutually exclusive options
# Do not remove current word in shell to allow finishing its autocompletion
if [[ "$(has_option -x)" == "1" ]]; then
ALL_ONCE_OPTIONS=("${ALL_ONCE_OPTIONS[0]} -x")
elif [[ "$(has_option -p)" == "1" ]]; then
ALL_ONCE_OPTIONS=("${ALL_ONCE_OPTIONS[0]} -p")
else
ALL_ONCE_OPTIONS=("${ALL_ONCE_OPTIONS[0]} -x -p")
fi
fi
# Most options are allowed only once, so remove the ones already in use,
# but do not remove current word in shell to allow finishing its autocompletion
local PREV_COMP_WORDS=("${COMP_WORDS[@]}")
unset "PREV_COMP_WORDS[-1]"
for i in ${ALL_ONCE_OPTIONS}; do
for j in "${PREV_COMP_WORDS[@]}"; do
if [[ "$i" == "$j" ]]; then
continue 2
fi
done
AVAILABLE_OPTIONS+=("$i")
done
# The -f option can be used several times
AVAILABLE_OPTIONS=("${AVAILABLE_OPTIONS[*]} -f")
COMPREPLY=(`compgen -W "${AVAILABLE_OPTIONS[*]}" -- $cur`)
;;
esac
}
complete -F _headerfiles headerfiles
Como notas particulares:
- Las opciones de máxima prioridad, aquéllas que cuando se especifican dejan sin efecto a las demás, se procesan de primero y con un early return.
- Las opciones con argumentos adicionales se procesan de forma independiente, pudiendo generar un autocompletado específico para dicha opción:
compgen -f
: nombres de ficheros.compgen -d
: nombres de directorios.compgen -W "..."
: una lista de palabras (nótese que éste es el mismo método empleado en otras partes del script).- La opción anterior puede usarse en conjunto con una función que extraiga los términos disponibles (de un fichero, de otro comando, etc). Por ejemplo, Git lo hace cuando detecta una línea tipo
git checkout
, entonces el siguiente autocompletado son nombres de las ramas disponibles, que son extraídas de una consulta agit branch -a
.
- Cuando hay que listar las opciones disponibles, primero se enumeran las que se pueden elegir una única vez y se filtran para quitar las ya introducidas. Posteriormente se añaden las que pueden repetirse
Activando el script de autocompletado
Para activarlo bash con que carguemos el script: source /path/to/script.bash
. Además, podemos agregar esta línea en nuestro .bashrc
para que esté disponible en cualquier nueva sesión Bash que ejecutemos.
Si nuestro proyecto incluye un comando de instalación o un paquete, deberemos añadir el script en el mismo e instalarlo en /usr/share/bash-completion/completions/
.
Conclusión
Hemos estudiado cómo extender el autocompletado de Bash con algunas de las opciones más frecuentes. Otras combinaciones más complicadas pueden resolverse con una extensión de éstas (por ejemplo, el caso de que la lista de subvalores de una opción deba ser extraída de un fichero o comando). Para más información podemos consultar la documentación oficial.
Variable not found
Requerir parámetros de la query string en ASP.NET Core 6
abril 26, 2022 06:05
Imaginad que tenemos un controlador MVC como el siguiente:
public class TestController : Controller
{
public IActionResult Add(int a, int b)
{
return Content($"Result: {a + b}");
}
}
Claramente, la acción Add()
retornará la suma de los enteros a
y b
que le llegarán como parámetros de la query string:
GET https://localhost:7182/test/add?a=1&b=2 HTTP/1.1
HTTP/1.1 200 OK
Content-Type: text/plain; charset=utf-8
Result: 3
Pero, como sabemos, podríamos llamar a la acción sin indicar alguno de esos parámetros, o incluso ninguno de ellos:
Petición | Respuesta |
---|---|
GET /test/add?a=1&b=2 | Result: 3 |
GET /test/add?a=0&b=0 | Result: 0 |
GET /test/add?a=1 | Result: 1 |
GET /test/add | Result: 0 |
Esto es así porque el binder será capaz de poblar correctamente los parámetros a
y b
cuando estén presentes en la cadena de la petición y sean correctos, o les asignará su valor por defecto (0
) cuando no hayan sido suministrados.
Pero dado que el cero es un valor de entrada válido, a priori desde nuestro código no tendríamos forma de distinguir cuándo el parámetro ha sido omitido y cuándo se ha establecido expresamente.
¿Cómo podríamos hacerlo?
Exigir parámetros no nulos, o usar [Required]
En parámetros de tipo valor como los usados en el ejemplo anterior, bastaría con hacerlos anulables y comprobar si sus valores son nulos, lo cual indicaría que en la petición no se incluyó un valor válido para ellos:
public IActionResult Add(int? a, int? b)
{
if (a == null || b == null)
return BadRequest();
return Content($"Result: {a + b}");
}
Otra forma, muy sencilla, legible y totalmente alineada con las buenas prácticas MVC, consiste simplemente en utilizar el atributo de validación [Required]
en ambos parámetros. Así, el binder establecerá el ModelState
como inválido si no existen valores correctos para ellos, y podremos actuar en consecuencia, como en el siguiente código:
public IActionResult Add([Required]int a, [Required]int b)
{
if (!ModelState.IsValid)
return BadRequest();
return Content($"Result: {a + b}");
}
De esta forma, en ambos casos se retornará un resultado Bad request (HTTP 400) para peticiones que no incluyan valores apropiados para los parámetros a
y b
.
Obviamente, en este caso podríamos mejorarlo usando el filtro [ApiController], pues sus convenciones se encargarían de verificar la validez de los datos de entrada incluso antes de ejecutar la acción.
¿Y los parámetros de tipo referencia, como string
?
Lo visto anteriormente funcionará bien con parámetros enteros o cualquier otro tipo valor (long
, byte
, bool
, decimal
...), pero con los tipos referencia como string
la cosa cambia un poco en función de la configuración del proyecto.
Si tenemos habilitados los tipos referencia anulables en el proyecto ASP.NET Core 6 (por ejemplo, introduciendo la propiedad <Nullable>enable</Nullable>
en el .csproj
, que es la configuración por defecto), los parámetros string
no permitirán la entrada de nulos durante el binding. Por tanto, el siguiente código funcionará de forma directa sin necesidad de utilizar atributos como [Required]
explícitamente, porque el framework lo habrá inferido automáticamente:
public class TestController: Controller
{
public IActionResult Concat(string a, string b)
{
if (!ModelState.IsValid)
return BadRequest();
return Content($"Result: '{a + b}'");
}
}
Una petición como GET /test/concat
retornará un error 400 (Bad request), mientras que algo como GET /test/concat?a=12&b=34
retornará "Result: '1234'"
.
Esto tiene bastante sentido, pues, cuando los tipos referencia anulables están activados, la propia firma de la acción ya está indicando que esos parámetros nunca deberían recibir nulos. Por esta razón, el binder establecerá el ModelState
como inválido. Si quisiésemos permitir la entrada de nulos, deberíamos haber utilizado string?
en la definición de los parámetros.
En cambio, si hubiéramos desactivado esa característica (<Nullable>disable</Nullable>
), los parámetros string
sí podrían contener nulos, por lo que deberíamos comprobarlos manualmente o bien utilizando [Required]
, igual que con los tipos valor:
public IActionResult Concat([Required] string a, [Required] string b)
{
if (!ModelState.IsValid)
return BadRequest();
return Content($"Result: '{a + b}'");
}
Publicado en Variable not found.
Blog Bitix
Aplicación con interfaz gráfica para repositorios Git
abril 18, 2022 10:00
Una herramienta con interfaz gráfica hace más fácil algunas tareas que usar la línea de comandos directamente. Este también es el caso al trabajar con repositorios de código fuente con la herramienta de control de versiones Git. Usar la linea de comandos tiene sus propias ventajas como permitir automatizar tareas con scripts o realizar operaciones sin tener que usar la interfaz gráfica. La interfaz gráfica y la linea de comandos no son excluyentes, se pueden usar según convenga en cada ocasión. Al trabajar con múltiples repositorios de Git, para realizar operaciones comunes como commits, analizar el historial y ver las diferencias en un archivo entre dos versiones una herramienta gráfica también facilita la tarea.
El sistema de control de versiones Git posee una línea de comandos con la que se realizan todas las acciones para clonar repositorios, para hacer commits, para ver diferencias, para explorar el historial, para crear ramas y cualquier otra acción. La línea de comandos es muy potente y además es automatizable con un script pero como cualquier otra línea de comandos no es intuitiva y difícil de aprender y en algún caso lenta al teclear un comando, sus opciones y argumentos.
Es aconsejable conocer los comandos básicos de línea de comandos pero en el uso diario o para algunas acciones las aplicaciones con interfaz gráfica son más rápidas, más fáciles de aprender y sin necesidad de recordar las opciones de cada comando. En GNU/Linux y GNOME una aplicación cliente de Git es gitg.
La aplicación gitg
Gitg es una aplicación de escritorio con interfaz gráfica que permite visualizar un repositorio de Git, su historial y el contenido de los diferentes archivos en sus versiones. No tiene todas las opciones disponibles de la línea de comandos pero si muchos incluyendo los más comunes. Usar una herramienta con interfaz gráfica puede mejorar la productividad al trabajar con varios repositorios de control de versiones en Git y permite a los usuarios que estén empezando a usar Git una forma de usarlo más intuitiva.
Está adaptada a la guía de estilos de las aplicaciones de GNOME, es una aplicación de software libre, está disponible tanto para GNU/Linux, macOS como Windows y en GNU/Linux se puede instalar como paquete de la distribución o como una aplicación en formato Flatpak independiente de la distribución disponible en Flathub con su paquete de gitg.
Las operaciones que permite son:
- Ver el historial.
- Ver el contenido de archivos.
- Gestionar el área de staging para componer el commit.
- Añadir y clonar un repositorio.
- Actualizar la información del usuario.
- Cambiar varias opciones de preferencias.
En esta capturas se muestran los commits, historial y merges en una linea de tiempo gráfica, además de poder ver las ramas locales, las ramas remotas, los orígenes de las ramas así como los archivos modificados en cada commit y las diferencias y cambios realizados en cada archivo.
Otras aplicaciones cliente de Git que tiene características similares son Github Desktop y SmartGit esta última tiene una licencia propietaria y no es gratuita, ambas tienen su versión de Flatpak en el repositorio de Flathub.
Blog Bitix
Mecanismos eléctricos, interruptores, enchufes y desempaquetado Schneider New Unica
abril 15, 2022 08:00
Los mecanismos de la instalación eléctrica que tenía de mi vivienda ya tienen alguno más de 20 años, con el uso y paso del tiempo algunos interruptores estaban sucios y ni aún intentando limpiarlos quedaban completamente limpios, por otro lado un par de interruptores me estaban haciendo ruido y arco eléctrico con la consecuencia de que alguna bombilla se me estaban fundiendo no cada más de tres o más años que duran las bombillas LED sino en menos de un año. Por estos motivos y también por el motivo estético he reemplazado tanto los interruptores como los enchufes. Reemplazar los mecanismos eléctricos no es difícil con uno mínimos conocimientos pero por seguridad al manipular elementos eléctricos hay que conocerlos y no tener ninguna duda ni cometer ningún error para no tener un accidente.
Desde hace ya unos días uno de los conmutadores de luz en la habitación me hace ruido eléctrico como si la electricidad dentro del mecanismo estuviese haciendo un arco eléctrico, otro conmutador en función de las posiciones de los interruptores también me hace el mismo ruido de arco. Esto es un problema ya que como mínimo hace que las bombillas se fundan más rápido con lo que hay que sustituirlas y en un caso grave puede ser la causa de problemas mayores como algún incendio o quemar algún elemento por el calor que se genera. A veces el arco eléctrico se puede solucionar desmontando los cables del interruptor y volviéndolos a colocar pero no siempre es suficiente.
Por este motivo he decidido cambiar los elementos eléctricos y aunque solo sean dos los que no funcionan correctamente he sustituido todos o al menos todos los visibles porque otro motivo del cambio es el estético y que todos tenga el mismo estilo. Hay varias marcas de mecanismos eléctricos y cada marca tiene varias líneas de mecanismos con su propia estética y funcionalidad. Otro motivo por el que se puede desear hacer el cambio de mecanismos es el funcional para por ejemplo tener interruptores iluminados y mecanismos inteligentes para regular el nivel de luz o controlarlos mediante un teléfono inteligente.
La sustitución de los mecanismos eléctricos es una tarea doméstica no complicada que no requiere un profesional, siempre y cuando se tomen ciertas precauciones y se tengan unas nociones básicas de electricidad para hacer la tarea con seguridad, sin peligro y correctamente.
En este artículo contiene los conceptos básicos de electricidad para hacer la sustitución, los mecanismos que he elegido, cómo colocarlos y donde comprar entre otras cosas.
Advertencia
Este artículo está escrito por alguien que apenas sabe nada sobre electricidad y simplemente se ha informado buscando en internet y haciendo algunas preguntas para las dudas que no he encontrado. Manipular electricidad y elementos eléctricos aunque sea a nivel doméstico tiene riesgos sin los conocimientos básicos sobre electricidad con lo que usa fuentes fiables generada por profesionales en la materia para informate bien.
Contenido del artículo
Mecanismos eléctricos
Los mecanismos eléctricos básicos de los que trata este artículo son interruptores de luz y enchufes de electricidad para conectar aparatos y herramientas. En cuanto a interruptores hay varios tipos de interruptores dependiendo desde cuántos puntos se desean apagar y encender la luz. Los mecanismos eléctricos ha de cumplir una normativa y aunque cada marca tienen sus propias líneas de productos en cuanto a funcionalidad todos se ajustan a la normativa. Por ejemplo, un enchufe de electricidad de tipo schuko es igual en cualquier marca en cuanto a forma del producto y utiliza los mismos cables de electricidad para su conexión. También todas las marcas ofrecen en sus catálogos los mismos tipos de interruptores.
Luego están los acabados de los mecanismos eléctricos tanto en su forma estética como en color, cada fabricante ofrece varios elementos para satisfacer los gustos y preferencias. Este artículo no habla de los elementos eléctricos del cuadro de electricidad, estos ya requieren tal vez de un profesional para su manipulación.
Tipos de interruptores
Una de las cosas básicas de electricidad básica es conocer que tipos de interruptores existen y cuál es la diferencia entre cada uno de ellos. Aparte de los propios mecanismos eléctricos estos requieren de un bastidor para colocarlo sobre la pared y según el modelo de interruptor algunos requieren elementos adicionales como un marco o elementos intermedios.
En algunos casos es posible colocar dos interruptores en el mismo módulo del bastidor, las teclas que accionan el interruptor será ancha o estrecha.
Interruptor
Los interruptores o interruptores simples permiten controlar un elemento de luz desde un único punto. Es un mecanismo eléctrico que cierra el circuito eléctrico o lo abre con el resultado de encender o apagar el elemento luminoso. Son los interruptores más sencillos, fáciles de colocar y baratos. Únicamente requieren un par de cables, el cable de fase por donde entra la electricidad y el cable de retorno del circuito eléctrico. No estoy seguro de si en estos tipos de mecanismos la posición de los cables importa, en algún vídeo he visto que si importa pero también me han dicho que no importa con lo que aún no estoy seguro, quizá alguien que lea este artículo y sepa más que yo me pueda decir.
Interruptor conmutador
Los interruptores conmutadores o conmutadores permiten controlar un elemento de luz desde dos puntos. Este es el caso por ejemplo de un pasillo largo en el que se desea encender y apagar la luz desde dos puntos diferentes del pasillo. A diferencia de los interruptores simples utilizan tres cables para realizar la conexión, el cable de fase y dos cables para conectar los conmutadores entre sí que dependiendo de su estado de actuación cortan o cierran el circuito eléctrico de forma alternativa según se pulsa cada uno de ellos.
En estos creo sí que importa que el cable de la línea esté colocado en la entrada de la línea, y también importa la posición donde se colocan los otros dos cables de modo que la posición de apagado de los pulsadores sea la correcta y la misma para ambos.
Interruptor de cruzamiento
Los interruptores de cruzamiento o cruzamiento permiten controlar la luz desde tres o más puntos. Normalmente se utilizan en la habitación principal, en la que a la entrada de la habitación y a cada lado de la cama hay interruptores. Los de cruzamiento son los elementos más complicados de los tres tipos de interruptores y requieren cuatro cables para realizar la conexión eléctrica.
Los interruptores de cruzamiento se utilizan en combinación con interruptores conmutadores. En un caso de tres puntos se utilizan dos conmutadores a los extremos del circuito y en la parte central del circuito un interruptor de cruzamiento, en los casos de más puntos de luz se van añadiendo interruptores de cruzamiento en la parte central del circuito.
En estos creo que también importa la posición donde se colocan los cables tanto en los conmutadores como en los de cruzamiento intermedios para que la posición de apagado de los pulsadores sea la correcta y la misma para todos.
Enchufes electricidad
Generalmente en España los enchufes de electricidad para conectar aparatos eléctricos utilizan la forma estándar de schuko. Los enchufes utilizan tres cables, el de fase por donde se proporciona la electricidad, el neutro y el de tierra por seguridad en caso de fallos eléctricos.
Para diferenciar la función de los diferentes tipos de cables, estos por normativa tienen definido un color para cada uno de ellos. El cable de fase suele ser negro, marrón o gris, el cable de tierra es amarillo y verde y el cable neutro es azul. Es importante seguir esta normativa de colores para no tener que revisar el conexionado del circuito eléctrico y poder instalarlo con seguridad y correctamente.
Marcos y bastidores
Aparte del propio mecanismo eléctrico son necesarios otros elementos. El bastidor es el elemento que hace de unión entre la caja embutida de la pared, permite montar el elemento eléctrico sobre el bastidor y colocar el marco para tapar el bastidor. Los bastidores y cajas de electricidad siguen una normativa en cuanto a dimensiones que es común para todos, los bastidores suelen ser compatibles con este estándar para poder montarlos sobre las cajas. Sin embargo, cada bastidor permite colocar elementos eléctricos de esa marca e incluso únicamente de una línea específica de la marca. Por lo que al cambiar los elementos eléctricos suele ser necesario cambiar también los bastidores y los marcos.
Los marcos son los elementos que dan el acabado al mecanismo eléctrico, permiten ocultar el bastidor al rodear el mecanismo eléctrico. Los bastidores pueden ser de plástico o de metal, para los interruptores de luz pueden utilizarse bastidores de plástico que no han de soportar mucho esfuerzo mecánico pero para los enchufes es mejor utilizar bastidores de metal ya que requieren más esfuerzo mecánico y los bastidores de metal soportan un mayor nivel de esfuerzo. Los bastidores de plástico son más baratos que los de metal pero al menos para los enchufes de electricidad es aconsejable utilizar bastidores de metal.
Algunas marcas y series tiene bastidores también dobles y triples pero las que solo proporcionan bastidores simples permiten componer bastidores de más elementos juntando tantos simples como se necesiten. En el caso de Schneider en el serie New Unica los bastidores son simples pero permiten juntarse como piezas de un puzzle quedando consistes muy parecido a como si fuese de una sola pieza y conservando las distancias adecuadas para los marcos y las cajas de registro. La ventaja de los bastidores simples es que permiten desmontarse individualmente, su desventaja es que montarlos requiere algo más de trabajo.
Otros elementos eléctricos
Los fabricantes proporcionan elementos adicionales y diferentes tipos de mecanismos para otro tipo de funcionalidades como salida de cables, reguladores, antena televisión, tapas ciegas, dispositivos inteligentes conectados, … Y algunas series utilizan elementos adicionales o intermedios para proporcionar a los elementos otro tipo de acabado estético más personalizable.
Preguntas frecuentes sobre interruptores
Un interruptor conmutador e incluso un interruptor de cruzamiento pueden hacer la función de un interruptor simple, por ello algunas marcas para algunas líneas de interruptores solo fabrican interruptores conmutadores y no fabrican interruptores simples. Aún así aunque un interruptor conmutador y de cruzamiento puedan hacer la función de un interruptor simple generalmente si la línea de interruptores utilizada los ofrece se siguen utilizando interruptores simples ya que son más baratos. El precio entre un interruptor simple y un conmutador generalmente es de unos pocos céntimos pero la diferencia con un conmutador de cruzamiento es ya de varios euros, con lo que sí es posible es mejor utilizar interruptores simples o conmutadores, por costes no es recomendable utilizar un interruptor de cruzamiento como si fuese un interruptor simple.
Finalmente, un interruptor conmutador no puede hacer las funciones de un interruptor de cruzamiento e igualmente un interruptor de cruzamiento no puede hacer las funciones de un interruptor conmutador.
Desempaquetado Schneider New Unica
Para realizar la sustitución de los elementos eléctricos he elegido los del fabricante Schneider y de la serie New Unica, en la página del fabricante se ofrece información técnica de la serie Schneider New Unica y un documento con su catálogo completo asi como sus elementos de dispositivos inteligentes conectados. Hay varios fabricantes o marcas otras reconocidas son Simon, Niessen, Legrand, bticino o Jung. Cada marca tiene varias líneas de interruptores y enchufes, con su estilo y tipos de elementos.
No he revisado todas las marcas y series y he elegido la serie New Unica por tener un precio que suele ser lo normal entre las diferentes marcas, por su aspecto estético, ofrecer acabado en negro y la posibilidad de montarle en cada módulo de bastidor dos elementos eléctricos, dos elementos estrechos. Me gustaría haber podido comprar interruptores iluminados pero el distribuidor donde lo he comprado no tenía esas referencias de la serie entre su catálogo a la venta. Otra serie que he mirado ha sido la serie Simon 270 que también estaba en el catálogo del distribuidor donde iba a hacer la compra, pero tenía dudas si sus bastidores permitían colocar dos elementos estrechos e el mismo módulo del bastidor.
Un aspecto a destacar de la serie New Unica de Schneider es que el conexionado es de conexionado fácil sin tornillos, la entrada de los cables están en la misma ubicación que permite que los cables queden mejor ordenados y tengan la misma longitud. El tiempo dirá si resulta y es un buen producto, en apariencia es una marca reconocida y de buena calidad. Los bticino que he reemplazado ya tenían más de 20 años , un conmutador ya me hacía ruido y arco eléctrico al encenderlo, esto además de un riesgo cuanto menos hace que las luces se fundan con mayor velocidad. Y desmontando y volviendo a colocar los cables ya lo he intentado sin solución. Además por el cambio estético y elegir el color negro según mi gusto.
En las imágenes se muestran los diferentes mecanismos eléctricos. La galería fotográfica de los fabricantes suelen ser escasa, este artículo tiene mejores fotos para saber cómo son los elementos por ejemplo muestra como son por detrás.
En el color antracita los Schneider New Unica tienen un diseño minimalista sin apenas detalles, menos que los bticino anteriores que tenia. La superficie de los pulsadores no es totalmente lisa sino que tiene una superficie arenosa. En color negro no se que tal soportarán la suciedad y cuando se ensucien la facilidad de limpieza. Los bastidores son de metal dando la sensación de ser capaces de soportar bastante carga ya que tiene un grosor considerable, la serie también ofrece otros de plástico a casi la mitad de precio que seguro son suficientes para los interruptores, para los enchufes son más recomendables los de metal, aún asi como la diferencia y precio simplemente es de unas decenas de céntimos el conjunto completo solo aumenta el precio total unos 10 euros por lo que si no se quiere ajustar el precio al máximo se pueden elegir los bastidores de metal para todos los elementos.
Las imágenes de la sección anterior de mecanismos eléctricos son de la serie New Unica ya desempaquetados y abierto su embalaje, estas son las imágenes del paquete original y el embalaje de los elementos de la serie. Excepto los bastidores los demás elementos van embalados en una bolsa de plástico en la que se indica el número de la referencia al que corresponde el contenido. Las referencias qu se muestran en las imágenes están los marcos, los bastidores, enchufe schuko, interruptor ancho, interruptor estrecho y placa ciega en color antracita.
Lo primero a realizar al recibir el paquete es comprobar que no falta nada, que contiene todos los productos y de las referencias solicitadas y están en condición de nuevo.
Un vídeo sobre la serie Schneider New Unica.
Colocación de interruptores y enchufes
La colocación de los interruptores y enchufes no es una tarea complicada ya que no requiere más que desatornillar y atornillar y desmontar y montar cables, sin embargo, es muy importante tener unas nociones básicas sobre electricidad y hay que saber y no tener ninguna duda de lo que se está haciendo. Antes de nada dado que se está manipulando electricidad siempre se ha de cortar la electricidad completamente desde el cuadro general de la electricidad de la vivienda para evitar cualquier accidente y manipular los elementos con seguridad. Antes de hacer ningún cambio se pueden tomar unas fotos de la instalación existente para antes de hacer cambio conocer como estaba realizada la instalación.
En el cuadro eléctrico tengo puestas unas etiquetas para saber que hace cada interruptor individual, sin embargo, algunos elementos eléctricos comparten el mismo interruptor en diferentes estancias (por ejemplo, un enchufe en la habitación y el termo de agua caliente en la cocina) con lo que para que no haya ninguna duda mejor desactivar el cuadro completo o si se apaga únicamente un interruptor comprobar que la luz o el enchufe realmente está cortado en el punto de luz a manipular haciendo caso omiso de las etiquetas indicadas en el cuadro.
Muchos mecanismos nuevos ofrecen un conexionado de fácil instalación sin necesidad de apretar tornillos tanto para los interruptores como para los enchufes. En internet y YouTube hay varios vídeos explicativos sobre cómo realizar estas tareas colocación de mecanismos eléctricos, algunos con información básica y algunos específicos utilizando los mecanismos a utilizar. En caso de no tener los conocimientos básicos antes de nada es mejor ver estos vídeos o ver algunos otros para aclarar las dudas. Hay que comprobar que los cables y bastidores quedan bien fijados, cortar los cables correctamente o limpiar las cajas de cualquier polvo si lo tuviera de construcción. Y evitar empalmes entre los cables, para ello los fabricantes ofrecen dos agujeros. En la serie de mecanismos eléctricos Schneider New Unica los cables se han de pelar con una longitud de 12 milímetros tal y como está serigrafiado en cada uno de los mecanismos con una marca visual y física de la longitud adecuada.
En mi caso al revisar la instalación eléctrica en algunos elementos había empalmes de cables seguramente porque al utilizar una conexión mediante tornillo esto era más sencillo de colocar cada cable individualmente pero los cables no quedan todo lo mejor que podrían. Para evitar hacer empalmes, tanto los interruptores y enchufes tienen dos agujeros para cada color de cable de modo que si hay que hacer algún empalme mejor hacerlo a través de estos orificios, no solo porque es la forma más correcta y ofrece mejor seguridad sino por al hacer el empalme el grosor de la unión sea demasiada gruesa para el diámetro de un orificio. Por otro lado, en muchas cajas los obreros ni siquiera se molestaron en dejar limpia la caja y tenían gran cantidad de yeso y suciedad dentro de ellas. Así que con el cambio seguramente deje la instalación incluso algo mejor de lo que estaba.
Los enchufes schuko tiene bastante profundidad y como haya bastante cable sobrante el mecanismo y dependiendo de la caja eléctrica para montarlo en el bastidor no debería hacer falta hacer mucha fuerza ni que se note que entra a presión, sin embargo en mis cajas en alguno si que he tenido que hacer más fuerza de la que me hubiese gustado hacer aún intentando organizar los cables lo mejor que he podido.
Los mecanismos originales y su desinstalación.
Los mecanismos nuevos y su instalación.
Trenzar bien los cables es importante para facilitar su inserción en los mecanismos y para el correcto funcionamiento sin problemas de electricidad.
Mis apuntes
Estas son algunas pautas que he seguido para la colocación de los interruptores y enchufes para hacer la tarea correctamente, con más seguridad y sin contratiempos.
Comprobar la electricidad de los interruptores y enchufes que funcionan correctamente para una vez desconectada la electricidad volver a comprobar y estar seguro que no tienen electricidad. Desconecta la electricidad antes de manipular ningún mecanismo. Las instalaciones más recientes permiten quitar la electricidad por estancias sin tener que quitar la electricidad general, pero en caso alguna duda siempre es mejor desconectar la electricidad general, sobre todo si el cuadro no está debidamente etiquetado. Aún después de desconectar la electricidad comprueba de nuevo que los interruptores y enchufes no tienen electricidad, los puntos de luz comprobando que la bombilla no se enciende y los puntos de electricidad comprobando con algún aparato que el enchufe no entrega electricidad. Seguramente un profesional como experto quizá no necesite estar más seguro y no necesite realizar tantas comprobaciones pero un no profesional que hace estas tareas domésticas cualquier comprobación no está demás. La tensión de la electricidad incluso en un piso doméstico es peligrosa y hay que evitar cualquier riesgo o accidente, en el peor de los casos las consecuencias pueden ser muy graves.
Ten a mano todas las herramientas necesarias, unos destornilladores planos y unos destornilladores de estrella, del tamaño y tipo que sean necesarios, también un pelacables o en su ausencia unas tijeras que sean capaces de pelar un cable y cortar el cable de cobre. Las herramientas adecuadas que sean necesarias para hacer la tarea. Quizá unos guantes aislantes o que al trenzar las puntas de los cables de cobre eviten daño en los dedos, también para evitar que las manos se ensucien. Como algunos enchufes están bajos hay que arrodillarse, para no hacerse daño en las rodillas se puede utilizar algo como almohada como una sábana vieja doblada. Algún aparato eléctrico para comprobar que los enchufes funcionan correctamente. Un nivel para comprobar que los bastidores y marcos quedan horizontalmente que en los interruptores es más fácil verlo a simple vista pero en los enchufes que suelen estar más bajos es más difícil.
Por si luego surgen dudas de cómo estaba la instalación y como referencia en un futuro se pueden tomar algunas fotos con un móvil, una vez cambiados los mecanismos antes de volver a dar la corriente y terminar de instalar el elemento en su bastidor y poner el marco también.
Los cables tienen una normativa de colores y estos han de insertarse en sus orificios correspondientes tanto de los interruptores y enchufes. Los enchufes utilizan tres cables, el de linea por donde entra se entrega la corriente que tiene alguno de los colores gris, negro o marrón, el neutro o de retorno que debe azul, y el de tierra que debe ser amarillo y verde. En los enchufes hay que colocar cada uno de estos cables en sus orificios correspondientes. En los enchufes e interruptores Schneider la ubicación de cada cable está indicado por su palanca de fácil instalación sin atornillamiento. Al embornar los cables en los orificios de los mecanismos mejor hacerlo de tal forma que no queden entrelazados, que cada uno vaya a su orificio sin rodear ningún otro cable.
Los cables se han de insertar de forma completa, hay que pelar los cables dejando una longitud de cobre al descubierto según la indicada por el fabricante del mecanismo, si se pela el cable trenzar los cables para evitar que al insertarlos se doblen. Los cables al insertarlos han de insertarse hasta el aislante, una vez insertados no debe quedar ninguna parte de cobre al aire. Los cables deben quedar bien sujetos tirando un poco de ellos para comprobar que están firmes ya se coloquen mediante mecanismo de inserción fácil de presa o atornillados. No debe quedar ningún hilo de cobre fuera de su agujero, es fácil que algún hilo rebelde se doble y quede fuera, si ocurre hay que volver a sacar el cable, volver a trenzarlo y repetir la operación de inserción. Si el mecanismo es de instalación fácil sin tornillos al insertar el cable la palanca de presa se ha de apretar completamente y luego insertar el cable, está algo dura y hay que hacer algo de fuerza.
Una vez insertados los cables es aconsejable tomarse unos segundos para evitar algún despiste comprobando que los cables están insertados en los orificios que les corresponden según su color. El bastidor hay que ponerlo primero antes de conectar los cables al mecanismo dado que los cables han de pasar por el centro del bastidor. Si hay que limpiar las cajas de los registros poner un papel para evitar ensuciar la tarima. Las cajas de registro donde se montan los bastidores son de plástico con lo que al apretar los tornillos hay que evitar apretar en exceso para no pasarse de rosca, tampoco es necesario apretar mucho para que el bastidor quede firmemente sujeto.
Al limpiar los registros de las cajas si están sucias y tienen mucho polvo que los obreros dejaron en la obra, al hacer la limpieza de la caja no está demás usar una mascarilla para evitar respirar el fino polvo que sale. Al manipular los cables y las cajas si tienen suciedad sin guantes las manos se van a ensuciar, si te las lavas con agua asegúrate de secarlas bien al volver a continuar con la tarea. Si se quitan muchos tonillos que no se van a colocar inmediatamente es muy útil tener un pequeño bote con tapa para guardalos ahí y que no se pierda ninguno.
Para evitar que el polvo caiga a la tarima mejor poner un papel que lo evite en la medida de lo posible, solo es polvo pero al barrer es abrasivo con el barniz de la tarima si no se tiene cuidado. Se aprecia la cantidad de suciedad que dejaron en los registros de las cajas los obreros en la construcción.
Tutoriales en vídeo
Si buscas en YouTube algún vídeo mira primero los del fabricante que suelen subir en sus cuentas videotutoriales de como colocar sus mecanismos. También hay profesionales que suben vídeos con tutoriales explicando los conocimientos básicos sobre electricidad para personas que no tienen los conocimientos básicos. Busca los vídeos en los que estén bien explicados y sean de alguien que demuestre tener conocimientos y ser profesional (porque hay algunos vídeos de algunos profesionales que no lo parecen y están más en un festival de humor), en caso de duda ver algún vídeo más o buscar otro.
En los siguientes vídeos que forman parte de un curso de electricidad básica en formato vídeo se explican muy bien los conocimientos básicos sobre electricidad, de enchufes e interruptores, conmutadores y de cruzamiento mostrando en vídeo cómo colocar cada uno de ellos, consejos y precauciones.
Estos son los tutoriales para la instalación de interruptores y enchufes.
Dónde comprar los mecanismos eléctricos
Hay numerosos distribuidores que ofrecen mecanismos eléctricos tanto en tienda física como por internet y en algunos casos ambos. No todos tienen todas las marcas, las series y el catálogo completo de referencias de las series con lo que en caso de querer una específica requiere comprobar que entre su catálogo tengan lo deseado.
En caso de realizar una sustitución completa de los elementos eléctricos es recomendable realizar un inventario de qué elementos se necesitan y que al realizar la compra o el pedido no falte ninguno. Este inventario puede ser una tabla como la siguiente que permite ver rápidamente y comprobar los elementos por estancia y los totales a pedir. Incluso por tener algún repuesto en caso de que alguno falle en el futuro se puede incluir en el pedido alguno adicional más de algún tipo.
Elemento | Total | Estancia 1 | Estancia 2 | Estancia 3 | Estancia 4 | Estancia 5 | Estancia 6 |
---|---|---|---|---|---|---|---|
Bastidor 1 módulo | 12 | 4 | 2 | 3 | 3 | ||
Bastidor 2 modulos | 1 | 1 | |||||
Bastidor 3 modulos | 2 | 1 | 1 | ||||
Marco 1 módulo | 12 | 4 | 2 | 3 | 3 | ||
Marco 2 modulos | 1 | 1 | |||||
Marco 3 modulos | 2 | 1 | 1 | ||||
Enchufes | 8 | 4 | 3 | 1 | |||
Interruptor | 2 | 2 | |||||
Interruptor (estrecho) | 3 | 1 | 2 | ||||
Conmutador | 3 | 2 | 1 | ||||
Conmutador (estrecho) | 1 | 1 | |||||
Cruzamiento | 1 | 1 | |||||
Cruzamiento (estrecho) | 0 | ||||||
Tapa ciega | 4 | 2 | 2 |
Leroy Merlin y Bricomart son dos tiendas especializadas en diferentes áreas de elementos para el hogar y de construcción que tienen canales de venta tanto físico como en línea a través de internet. Hay otras tiendas especializadas que realizar compra por internet como Ilumitec que seguramente tangan cualquier material eléctrico que alguien necesite y a precios económicos, esta ha sido donde he hecho la compra. En caso de realizar la compra por internet permiten hacer el pago utilizando diferentes formas de pago por tarjeta e incluso mediante PayPal que siempre da más seguridad en tiendas que encontramos en los primeros resultados en el buscador de páginas. En mi caso Amazon para esto lo he descartado porque no ofrece el catálogo completo de referencias de la serie y las referencias que están tienen unos precios bastante mayor que en tiendas especializadas.
En caso de realizar la compra por internet hay que leer siempre siempre las condiciones de compra ya que en ella se detallan las condiciones en caso de devolución y quien se hará cargo de los gastos de envío. Antes de formalizar la compra hay que revisar varias veces el pedido, por ello es recomendable hacer un inventario de los elementos necesarios como la anterior. Hay series con un gran número de referencias, algunos distribuidores ofrecen gran número de referencias y en caso de sustituir todos los mecanismos eléctricos hay que hacer un pedido con un gran número de ellos. Una vez llega el paquete lo primero es comprobar que contiene todos los elementos, del tipo solicitado, comprobar su estado y que no falta ninguno para si fuera el caso ponerse en contacto con el vendedor y solucionar el problema.
La compra la he realizado en Ilumitec, el envío del paquete ha sido rápido mediante el transportista Seur, con todos los elementos del pedido, en buen estado y cumpliendo el plazo orientativo indicado al hacer la compra. No puedo hablar de la atención al cliente porque no ha sido necesario que me ponga en contacto con ellos pero para realizar la compra en su página web y el pago ha funcionado todo correctamente. Además, ofrece PayPal como medio de pago que proporciona garantías adicionales en caso de disputas, también con PayPal por no tener que proporcionar el número de la tarjeta de crédito.
Complementos para los interruptores y enchufes
Además de los elementos eléctricos puede que sea necesario comprar otros productos relacionados. Por ejemplo, en caso de que los marcos sean de diferente tamaño para pintar la pared en caso de que quede marca de suciedad por que la caja no está bien aislada y el polvo que entra deja marca en la pared con la corriente de aire que entra por los tubos y pared. Si se necesita poca pintura para hacer pequeños arreglos Bruger en Amazon hay disponibles unos probadores de color que se pueden utilizar y son suficientes para hacer los pequeños arreglos para corregir esas pequeñas marcas de suciedad.
Otro productos puede ser algo de escayola para arreglar algún desperfecto en la pared o la caja del registro eléctrico. Unas tapas de enchufes schuko para que no se les acumule polvo mientras no se usan, cable eléctrico en caso de tener que sustituir alguno que puentea mecanismos, pintura, pinceles o brochas junto con disolvente. De todo estos productos están disponibles en tiendas especializadas y en Amazon también se ofrecen.
Blog Bitix
Por qué y ejemplo de cómo desarrollar un plugin de Gradle
abril 07, 2022 06:00
Generalmente cuando se necesita una funcionalidad en Gradle esta suele estar proporcionada por los propios desarrolladores de Gradle, por los propios mantenedores de otras herramientas para integrarlas en Gradle o en último caso por alguien que antes ha tenido la misma necesidad ha publicado un plugin. Si aún así no hay un plugin que ofrezca la funcionalidad que se desea, Gradle ofrece la posibilidad de que cualquiera desarrolle sus propios plugins y los use para sus necesidades específicas o en caso de ser útil para otras personas compartirlo en un repositorio público como cualquier otro.
Gradle es una herramienta de construcción y gestión del ciclo de vida de un proyecto principalmente usando en proyectos Java. Realiza importantes tareas como la descarga y gestión de las dependencias y resolución de conflictos entre las diferentes versiones que necesite una aplicación, tareas importantes que ni el sistema de módulos de Java proporciona. Permite ejecutar de forma sencilla la aplicación o las pruebas unitarias de código entre otras muchas tareas que pueden ser automatizadas como pruebas estáticas de código y generación de artefactos además de ser suficientemente flexible para adaptarse a las necesidades que haya en un proyecto.
Por todas estas importantes tareas que realiza Gradle es una herramienta imprescindible en cualquier cualquier proyecto Java. Su alternativa más usada es Maven que tiene un modelo declarativo y basado en XML con unos archivos más verbosos. Ambas herramientas se consideran ya maduras generalmente equivalentes para la mayoría de funcionalidades más comunes. Dado que los archivos de configuración de Gradle son menos verbosos, más legibles y fáciles de editar que el XML es la herramienta elegida como herramienta de construcción para muchos proyectos.
Cuando la funcionalidad ofrecida por Gradle no es suficiente, no existe un plugin de un tercero o no está adaptado a las necesidades de un proyecto u organización al igual que otros han desarrollado sus propios plugins cualquiera puede desarrolalr plugins con la interfaz que ofrece Gradle para su desarrollo y extender su funcionalidad.
Contenido del artículo
Por qué desarrollar un plugin propio de Gradle
Es seguro que en una empresa a lo largo del tiempo esta desarrolle varios proyectos, siendo varios una cantidad de unas pocas decenas a cientos dependiendo del tamaño de la organización. Con múltiples proyectos por motivos de mantenimiento el copiar y pegar código entre proyectos no es una opción viable con lo que también seguro que surge la necesidad de reutilizar código propio de la organización entre los diferentes proyectos tal y como se reutiliza código de otras librerías como Spring, Hibernate y otra multitud de librerías desarrolladas por terceros. La forma de reutilizar código en Java es a través de librerías que se publican en un repositorio de Maven igual que cualquier otra librería de terceros.
También es seguro que con múltiples proyectos surge la necesidad de reutilizar código entre múltiples proyectos incluso en la herramienta de construcción. La forma que ofrece Grade de reutilizar código es a través de plugins. En el caso de la herramienta de construcción un plugin permite aplicar a todos los proyectos de forma sencilla, homogénea, mantenible y sin copiar y pegar elementos comunes considerados un estándar en la organización como comprobaciones estáticas de código con PMD, Checkstyle y SpotBugs entre otras muchas cosas propias de una organización. Muchos terceros publican plugins que cualquiera puede aplicar a un proyecto si este plugin ofrece la funcionalidad que necesita y si no existe ninguno también es posible desarrollar uno propio ajustado a las necesidades propias.
Gradle ofrece un sistema muy flexible y extensible para desarrollar, publicar y reutilizar plugins. En su documentación hay varias páginas que explican cómo desarrollar un plugin, y otros muchos artículos incluido el presente.
Por ejemplo, hace tiempo hice un ejemplo en el que generaba un archivo al hacer la construcción y generación del artefacto que incluía información del artefacto como la versión, fecha de construcción, hash del commit y número de build de modo que en tiempo de ejecución el código tenga información para mostrar esa versión en las trazas y conocer la versión exacta del código desplegado en un entorno. Otro caso puede ser que se desee una funcionalidad similar al plugin de Maven Release que permite automatizar la generación de versiones de los proyectos para la que en Gradle la opción equivalente con gradle-release su última versión es del 2017.
Conceptos de Gradle
Gradle define varios conceptos propios para la configuración y ejecución. La configuración permite cambiar el comportamiento o adaptarlo a las necesidades propias. La configuración se definen en lo que Gradle denomina extensiones que son simplemente objetos de datos en los que Gradle permite al usuario introducir datos y que en el archivo de construcción se manifiestan como bloques de configuración con propiedades, las tareas al ejecutarse obtienen las extensiones y los datos configurados en ellas, en función de los datos las tareas varían su comportamiento.
Los plugins a través de la API que ofrece Gradle pueden realizar cualquier acción que permita la API como por ejemplo aplicar nuevos plugins al proyecto, definir objetos de extensiones, definir nuevas tareas o cambiar el comportamiento de tareas existentes. Con estas funcionalidades a disposición de cualquiera es posible crear un plugin de Gradle en el que encapsular cualquier funcionalidad relativa al ciclo de vida del proyecto, aplicarla y utilizarla en cualesquiera proyectos.
Una vez creado el plugin este se publica y comparte en un repositorio de Maven del que los proyectos que lo quieran usar simplemente han de incluir la URL del repositorio y la referencia al plugin.
Ejemplo de plugin para Gradle
Lo que hace este ejemplo es mediante código aplicar cambios a través de la clase Project que representa al proyecto de Gradle. A través de esta clase se añaden nuevos plugins, se configuran las extensiones y las tareas para aplicar la funcionalidad deseada en el plugin.
El ejemplo añade los plugins y configura sus extensiones para realizar comprobaciones estáticas de código a través de las herramientas PMD, Checkstyle, SpotBugs y sus plugins para Gradle. Además, la funcionalidad del plugin es generar un archivo con información de la versión del artefacto incluyendo su versión, fecha de construcción, hash del commit y número de build para conocer esta información del artefacto.
Incluir información variable en el artefacto que es diferente en función de la fecha de ejecución hace que la generación no sea reproducible, esto es, no genere exactamente el mismo binario dado que su contenido es diferente con cada build aunque el código no haya cambiado y solo lo haya hecho un archivo de configuración y únicamente ligeramente su contenido. Que la generación de los artefactos sean reproducibles tiene el beneficio de que el artefacto generado sea auditable por motivos de seguridad y es posible que esté libre de modificaciones diferentes del código empleado para la construcción.
Crear un plugin de Gradle
Hay varias formas de desarrollar un plugin de Gradle, se puede desarrollar dentro de un proyecto existente o como un proyecto independiente, Gradle ofrece un comando para disponer de la estructura básica de un proyecto para el plugin rápidamente y de forma sencilla al igual que se realiza para disponer de una aplicación normal. En el archivo de construcción del plugin que genera Gradle incluye un plugin propio de Gradle necesario para desarrollar plugins de Gradle, java-gradle-plugin.
Los plugins de Gradle se crean proporcionando una implementación de la interfaz Plugin, esta clase ofrece el método apply que Gradle invoca para que el plugin modifique el proyecto a través de la instancia de Project que lo representa y se proporciona como argumento del método. La clase Project ofrece métodos para añadir nuevos plugins al proyecto, obtener los objetos que contienen los datos de las extensiones, permite añadir o modificar tareas existentes y crear dependencias entre las tareas. En el siguiente código se observan estas modificaciones en el proyecto en el plugin del ejemplo.
Dado que el plugin de ejemplo configura otros plugins existentes necesita de las clases de los plugins y de sus extensiones de modo que han de incluirse como una dependencia del plugin desarrollado en el archivo de construcción del plugin. El plugin también puede proporcionar sus propias clases de extensiones.
|
|
|
|
|
|
|
|
Los plugins de Gradle se publican en un repositorio de Maven como cualquier librería o aplicación, Gradle compila el plugin y lo publica. Para desarrollar es posible publicar el plugin en el repositorio de Maven local.
|
|
También es posible realizar teses unitarios y funcionales sobre el plugin, al utilizar la tarea de creación del proyecto del plugin Gradle crea unos ejemplos en los basarse para crear más.
Aplicar el plugin de Gradle a un proyecto
Una vez el plugin está en el repositorio de Maven usar el plugin y aplicarlo a un proyecto es exactamente igual que cualquier otro plugin de Gradle, basta incluirlo en la sección plugins con su identificador y su versión. Una vez aplicado el plugin como este añade otros plugins al ejecutar la tareas tasks que muestra las tareas existentes en el proyecto se observa que aunque los plugins de PMD, Checkstyle, SpotBugs han incluido sus tareas en el proyecto aunque no se hayan aplicado de forma explícita sino de forma transitiva a través del plugin propio.
|
|
|
|
Ejecutando la build la tarea se genera el archivo como un recurso que se procesa al que se le realizan varias sustituciones con los valores que permite en tiempo de ejecución conocer información de la versión de la librería o aplicación, este archivo se incluye en el jar de la librería o aplicación y es posible acceder a él como un recurso más.
|
|
|
|
|
|
|
|
Al ejecutar la tarea de build dado que se han incluido los plugins PMD, CheckStyle y Spotbugs sus tareas de validación se ejecutan y detectan los errores en los archivos del código fuente según las reglas de validación configuradas. En el código de ejemplo Checkstyle indica que hay el código no está formateado de forma apropiada siguiendo las convenciones establecidas para el proyecto.
|
|
|
|
El código fuente completo del ejemplo puedes descargarlo del repositorio de ejemplos de Blog Bitix alojado en GitHub y probarlo en tu equipo ejecutando siguiente comando:./gradlew build
Coding Potions
Mis primeras impresiones usando emacs
abril 05, 2022 12:00
En este artículo voy a contar mis primeras impresiones usando el editor de textos
Emacs
. Lo primero que tengo que decir es que vengo de Vim por lo que fijo que voy a comparar ambos editores. Como digo, esto es mi opinión personal, por lo que para otra persona la experiencia sea completamente distinta.
Por qué probar emacs
Lo primero que tengo que decir es que me molaba la idea de usar Emacs porque parece un editor muy bien integrado con todo. Como suelen decir los usuarios de emacs es un sistema operativo en sí mismo con un editor de textos incorporado.
Y es que Vim está más limitado en ese aspecto porque trata de ser muy simple, y además está pensado para utilizarse en consola (aunque tiene versión gráfica gvim, pero las limitaciones son las mismas).
Y es que me molaba la idea de tenerlo todo en emacs: consolas, debuggers, notas, clientes HTTP, correo, etc. Se supone que la gente que usa emacs para todo no abre otra aplicación en todo el día, incluso navegan por Internet desde el editor.
También quería comprobar que tal las cosas que en Vim están más limitadas o hay que hacer malabares para poder usarlas: LSP, Dap, etc.
Por último está el tema de Org, que es una manera que tiene Emacs de escribir ficheros de notas que son muy potentes. Por lo que he visto puedes crear secciones que se pueden expandir y colapsar, tablas automáticas, tareas integradas, etc.
Aquí tengo que decir que soy muy fan de Markdown por su simplicidad y porque me sirve para lo que quiero, pero quiero probar Org igualmente.
Bien, una vez visto por encima lo que me llama la antención de Emacs vamos al lío.
Cómo instale y configuré emacs
Una vez instalado, cuando lo abres de cero aparece una pantalla en blanco muy fea de bienvenida a Emacs. Esto no me sorprende ni me da miedo porque en Vim pasa un poco lo mismo, lo abres y no tienes nada más, al menos en Emacs tienes un menú.
Aquí lo primero que hice fue buscar ficheros de config que usa la gente para ver un poco mis posibilidades. También encontré dos configs muy populares ya creadas: ^spacemacs y doom-emacs. Ambas configs utilizan keybindings de Vim, por cierto.
Decidí tirar por config propia porque, aunque esas configs están muy bien hechas, cambian demasiado la experiencia de usar Emacs (aunque fijo que las pruebo).
Lo primero es saber que Emacs emplea una variante del lenguaje Lisp para generar estos ficheros de configs y crear plugins (en concreto se llama Emacs Lips o Elisp para abreviar).
Este lenguaje supongo que tendrá su utilidad para programar y tal, pero para algo simple creo que lia bastante. Aquí tengo que decir que Vim con su Vimscript tampoco es que sea mejor (aunque ahora con Neovim y Lua la cosa puede cambiar).
Miré la serie de vídeos muy recomendada de System Crafters, en la que produce una config de Emacs desde 0 explicada paso por paso.
Tengo que decir que la config que empleo es muy parecida a la de esa serie, salvo que he cambiado un par de keybindings para que sean parecidos a los que tenía en Vim, además de añadir evil-mode, un paquete que añade todos los keybindings de Vim a la hora de editar ficheros.
Mi Emacs luce tal que así:
Opiniones tras usar emacs
Tras usar emacs con la config mencionada durante unos días tengo que decir que hay cosas que me gustan y otras que no me gustan nada. Aviso: hay muchas cosas no me gustan porque todavía tengo que buscar más config y actualizar la que tengo.
Para empezar el plugin de projectile está guay porque permite abrir varios proyectos que estés desarrollando a la vez. En vim lo que hacía era abrir otra tab de la terminal y abrir otro Vim.
Projectile tiene un comando para buscar ficheros en los proyectos (nada que no se haya visto ya en vscode o vim), simplemente escribes y busca ficheros con ese nombre.
Cuando busco ficheros hay un tema que no me gusta y es que no hace fuzzy fidning, es decir, aunque puedo simplemente poner nombre de fichero o carpeta, si por ejemplo quiero buscar el fichero userList.js, si escribo “usli” no me sale ningún resultado. Esto con Vim y el plugin te Telescope está resuelto sin tener que escribir bien el nombre completo todo el rato.
Supongo que tendré que buscar otra config para Projectile (aunque no he encontrado mucho en Internet) o usar otro plugin solo para esto.
Respecto a los keybindings los de emacs se me hacen muy extraños (hablo de los comandos que no tienen que ver con editar texto porque como ya he dicho utilizo los de vim). Son comandos de pulsar el control + otra tecla + luego otra vez control + otra tecla y así, cuestión de acostumbrarse..
Como muchos keybindings son de pulsar el control pues han cambiado las teclas hasta para hacer el mítico Control C + Control V, cosa que tampoco me gusta mucho.
Otra cosa que no me mola es lo de la terminal. Osea mola mucho poder abrir terminales (como pasa en vscode) pero debe ser que las eshells no las tengo bien configuradas porque no me cargan los colores dentro de la terminal (puede que pase por el tema que estoy utilizando, el de night owl), ah y no funciona el Control R para buscar comandos, tendré que investigar.
También con las terminales odio que no puedas abrir varias eshells. Lo que he visto por Internet es que la gente renombra el buffer de la terminal para poder abrir más (pereza).
Tengo que investigar más sobre las terminales porque al parecer hay muchas (esell, vterm y unas pocas más).
También he instalado ivy para poder tener un menú algo más cómodo para ejecutar los comandos de M-x. El caso es que he isntalado también witch-key para saber qué teclas apretar si no recuerdo el comando, pero a la hora de buscarlos como tampoco tiene fuzzy tengo que escribir el nombre del comando bien a la primera para encontrarlo.
Respecto a tema importante, el LSP (Language server protocol). Por si no lo sabes, el LSP es una cosa maravillosa, permite que los lenguajes saquen información de forma estándar para poder tener autocompletado, vamos, que si me instalo el LSP de typescript por ejemplo, puedo tener el mismo autocompletado que en el vscode.
Para vim uso el paquete de vim-coc que ya te lo da todo, lo instales y ale. Te da hasta maneras de instalar los language servers desde dentro de Vim.
En emacs estoy usando lsp-mode que lo usa la mayoría de gente. Es cierto que te da una forma de instalar los language servers, pero además necesita instalar otros tantos paquetes para tener popup de autocompletado o de documentación.
En concreto utilizo: company, lsp-ui y company-box. La cosa es que hace cosas raras. A veces me abre los ficheros sin tener el LSP activado y tengo que activarlo a mano. A veces no me autocompleta nada y otras sí.
Otra cosa que me pasa es que no autocompleta cosas del fichero (a veces sí que lo hace, veo que pone file al lado, pero no autocompleta casi nada). Con vim-coc da igual en que fichero esté, o con qué LSP, que siempre autocompleta algo de los ficheros que tenga abiertos.
Con el de Emacs muchas veces me quedo sin autocompletado porque me dice que no hay opciones, debe ser que el LSP no devuelva nada, miraré si hay más config para que funcione con el de vim (o buscar otros paquetes).
También tengo problemas con Svelte, precisamente como el LSP no devuelve nada, en Svelte en la parte de Javascript casi no autocompleta nada, y eso hace que se vuelva muy tedioso andar escribiendo todo.
Una cosa que me molestó mucho al principio es que Emacs al parecer guarda archivos autosave en el propio proyecto en el que estás, incluso me guardaba mensajes de log. Tuve que cambiar las carpetas de todas esas cosas por la carpeta temp del sistema.
Conclusiones
Como digo en el momento de escribir este artículo llevo cosa de unos días de uso, todavía tengo que habituarme, cambiar cosas de la config, aprender comandos y funciones, etc.
Mirando vídeos de gente usando emacs le veo mucho potencial, es como la mezcla perfecta entre la simplicidad de Vim en cuanto a interfaz y la potencia de un editor gráfico como
Vscode
.
Ahora bien, si por estar en ese punto medio va a tener las desventajas de Vim sumadas a las desventajas del Vscode pues para eso me vuelvo a Vim.
El tiempo lo dirá.
(Por cierto, acepto toda clase de recomendaciones, feedback, tips y tal, me puedes escrbir a mi Twitter @CodingPotions)
Blog Bitix
Novedades de Java 18
marzo 31, 2022 07:00
Las novedades de Java 18 no añaden nada en el lenguaje pero sí incorpora algunas relevantes en la plataforma como el uso de UTF-8 por defecto, una utilidad de línea de comandos para disponer de un servidor web simple, poder añadir fragmentos de código en los comentarios de la documentación Javadoc así como el marcado para su eliminación en futuras versiones de la finalización de objetos. También publican otras novedades en incubación, nuevas versiones en vistas previa de otras características se publicarán de forma definitiva en siguientes versiones y otros numerosos cambios menores.
Las mejoras incrementales se siguen añadiendo en cada nueva versión lanzada cada seis meses. En marzo de 2022 ha sido publicada la versión de Java 18 como siguiente versión después de Java 17 que es una versión con soporte extendido o LTS. Seguramente no muchos van a poder utilizar esta nueva versión por restricciones en los proyectos que seguirán usando versiones ya consideradas bastante antiguas incluyendo Java 8 y más en los casos que utilizan versiones anteriores. Por otro lado, otra parte de usuarios quizá esperen a la siguiente versión LTS para actualizar las aplicaciones en el caso de que ya estén utilizando Java 17.
La lista de características de Java 18 no es muy amplia pero hay algunas destacadas.
Contenido del artículo
Introducción
Con el paso de los meses muchas librerías y entornos de desarrollo irán publicando nuevas versiones compatibles con Java 18 y añadiendo soporte. Cuatro de las características más destacada son la utilización de la codificación de caracteres UTF-8 por defecto, la inclusión de un pequeño servidor web, soporte para añadir fragmentos de código en la documentación Javadoc y finalmente marcar para ser eliminada en una siguiente versión la finalización de objetos. Otras mejoras son nuevas vistas previas de características que están disponibles para obtener comentarios pero que en una siguiente versión podrían cambiar.
- Características de Java 18
- Notas de publicación de Java 18
- Documentación de Java 18
- Documentación Javadoc de Java 18
- JavaMagazine: Java 18 is here: 9 JEPs with core library improvements and updates
Las mejoras incluidas en esta versión son:
- 400: UTF-8 by Default
- 408: Simple Web Server
- 413: Code Snippets in Java API Documentation
- 416: Reimplement Core Reflection with Method Handles
- 417: Vector API (Third Incubator)
- 418: Internet-Address Resolution SPI
- 419: Foreign Function & Memory API (Second Incubator)
- 420: Pattern Matching for switch (Second Preview)
- 421: Deprecate Finalization for Removal
En los siguientes vídeos hace una explicación de estas nuevas características.
Con el nuevo calendario de publicaciones se observa claramente que los desarrolladores pueden predecir de forma más mucho fiable cuando se publicará una nueva versión. Se observa que el tiempo entre versiones se ha reducido considerablemente respecto a lo que tardaron las versiones Java 6 y 7 y se observa la incorporación de novedades de forma constante.
Nuevas características
Codificación de caracteres UTF-8 por defecto
Las operaciones que hacían entrada y salida como en el caso del sistema de archivos se utilizaban por defecto si no se indicaba uno explícitamente la codificación del sistema operativo. Dado que cada sistema operativo es capaz de definir su codificación de caracteres esto creaba algunas inconsistencias cuando las aplicaciones se ejecutan en diferentes sistemas operativos. Ahora en caso de que no se indique una codificación de caracteres se utiliza UTF-8 ofreciendo una mejor consistencia entre las diferentes plataformas.
Servidor web simple
Se añade una utilidad de línea de comandos y una API para iniciar un sencillo servidor web para archivos estáticos. La finalidad es que no haya que recurrir a utilidades externas al JDK y sirva para hacer pruebas. No es su intención reemplazar servidores web más completos como Apache o Nginx ni ofrece funcionalidades dinámicas como un contenedor de servlets como Tomcat.
Dado que es un servidor web simple tiene algunas limitaciones, como que solo soporta el protocolo HTTP/1.1, no soporta el protocolo seguro HTTPS, solo soporta operaciones idempotentes de los verbos HEAD y GET devolviendo el resto de versos un código de error 501 Not Implemented o 405 Not Allowed Response. Algunos MIME types son configurados de forma automática como los archivos con extensión html que son servidos con la cabecera de contenido text/html.
|
|
|
|
Además de la línea de comandos se ofrece una API para iniciar el servidor web mediante código.
Fragmentos de código en comentarios Javadoc
Algunos de los comentarios de Javadoc incluyen ejemplos de código. Hasta ahora los fragmentos de código insertaban con el taglet @code que tenía varias deficiencias como no ofrecer resaltado de sintaxis, no poder incluir fragmentos de código de archivos existentes con lo que puede quedar obsoleto y no poder hacer pruebas unitarias sobre este código con lo que podría no funcionar.
Se añade el taglet @snippet que permite incluir fragmentos o snippets de código en los comentarios de Javadoc, con resaltado de sintaxis y soporte para acceder a los taglets para procesar el código de la anotación. La anotación permite incluir en los comentarios de Javadoc regiones de archivos externos y aplicar transformaciones en el contenido a incorporar en el Javadoc. Pudiendo añadir fragmentos de código de archivos externos y pudiendo realizar transformaciones no hace falta copiar código y pegar código en los comentarios Javadoc sino que los fragmentos de código se extraen directamente de los archivos de código fuente.
Además se ofrece una API para acceder a esos fragmentos de código pudiendo hacer pruebas unitarias del código incluido en el Javadoc, esto no es solo para los desarrolladores del JDK sino también para cualquier programador que añada fragmentos de su código Java en la documentación Javadoc.
Los fragmentos de código no están limitados a archivos de código Java sino que también es posible incluir otros formatos utilizados comúnmente en aplicaciones Java como archivos properties, html u otros. En esta guía se detalla como usar los fragmentos de código con ejemplos de código.
Reimplementación de la reflexión con manejadores de métodos
Se reimplementan varias funcionalidades relacionadas con la reflexión utilizando los manejadores de eventos con la intención de facilitar el mantenimiento del JDK. Los MethodHandlers ofrecen una alternativa a la reflexión con mejor rendimiento a la vez que es más legible. Es un cambio interno más para los desarrolladores del JDK que para los usuarios.
Proveedor para resolver direcciones IP
Hasta ahora el JDK utilizaba el mecanismo del sistema operativo para resolver direcciones IP. Este es compartido por todas las aplicaciones y la operación de resolución es bloqueante que es un problema para la incorporación de los threads ligeros del project Loom. Se ha añadido un mecanismo extensible para proporcionar otras formas de resolución y soportar nuevos protocolos como DNS sobre QUIC, TLS y HTTPS. Ahora las aplicaciones tiene más control sobre el mecanismo de resolución y es útil en el contexto de pruebas automatizadas.
Nuevas características en vista previa
Como ya es habitual en el JDK se van incluyendo algunas características en modo vista previa que pueden ser utilizadas pero que en una siguiente versión y el código que las usen deberá ser modificado. Se ofrecen para que los usuarios puedan experimentar con ellas y los desarrolladores obtengan comentarios y si es necesario hacer cambios en siguientes versiones.
Vector API
Se proporciona una nueva versión de la Vector API que permite aprovechar las instrucciones SIMD de los procesadores con una API de Java común para todas las arquitecturas de procesadores. Se aprovechan las características disponibles de los procesadores y en aquellos que no tengan alguna se ofrece un modo de funcionamiento degradado.
En esta nueva versión se soportan las instrucciones Scalar Vector Extension (SVE) de la plataforma ARM. También se mejora el rendimiento de las operaciones que aceptan enmascaramiento en las arquitecturas hardware que soportan enmascaramiento.
Foreign Function & Memory API
Esta API permite acceder a memoria de procesos externos y utilizar librerías programadas en otros lenguajes como una alternativa más fácil de usar, de mayor rendimiento, más general para diferentes arquitecturas y más simple que la anterior alternativa con JNI. En esta nueva versión se mejora la API para soportar y facilitar operaciones con diferentes tipos y accesos a memoria.
Pattern Matching para las sentencias switch
El parttern matching en las sentencias switch permite al compilador comprobar de la expresión del switch contra los casos de la expresión del switch. En esta nueva revisión de esta característica el compilador lanza un error en caso de que un patrón domine al siguiente, sea más general siempre se cumpla antes que uno menos general. Ahora también el compilador es más preciso al comprobar la completitud de todos casos del switch en las clases sealed.
Otros cambios
Finalización de objetos marcado para ser eliminado
Java es un lenguaje que ha ofrecido recolección de basura desde las primeras versiones. Los programadores nunca han tenido que liberar la memoria de los objetos de forma explícita sino que de esta tarea se encarga la máquina virtual de Java. Pero también Java desde las primeras versiones ha ofrecido un mecanismo para la finalización de objetos que el tiempo ha demostrado que tiene varios fallos de diseño que no lo hacen útil y se desaconseja su utilización.
Algunos fallos de su diseño son que tiene una latencia impredecible y arbitraria sin garantía de que la finalización del objeto se realice. Las acciones de finalización no tienen ninguna restricción pudiendo revivir una referencia de objeto. Siempre está activo para cada instancia de una clase se use o no, ni se puede cancelar. Tampoco hay un orden predefinido en un entorno multihilo de modo que la ejecución de la finalización se puede ejecutar en cualquier orden.
Por los defectos anteriores la eliminación de la finalización de objetos en Java ha sido algo pendiente de realizar, en esta versión de Java aunque no se elimina se marca para la eliminación en versiones futuras de Java de modo que los que lo usen tengan tiempo de actualizar sus librerías y aplicaciones.
Esto solo impactará a algunos usuarios que realicen tareas avanzadas en las que necesiten la finalización de objetos, no es algo que en circunstancias normales se use. La alternativa a la finalización de objetos es usar la sentencia try-with-resources y en los objetos que tengan un ámbito mayor de vida utilizar la clase Cleaner que permite asociar acciones de finalización a una referencia de objeto cuando esta se convierte en una referencia phantom.
Otros cambios
Los anteriores son los cambios más destacados de Java 18 pero otro buen número de cambios menores e internos en el JDK. En las notas de publicación se incluye una lista detallada de todos.
Estos son artículos que también hacen resúmenes de las novedades de Java 18.
Coding Potions
Cómo ignorar en git ficheros o carpetas tras añadirlos al .gitignore
marzo 28, 2022 12:00
Si en un proyecto Git quieres ignorar ficheros o carpetas que has añadido recientemente al gitignore, es posible que no funcione porque ya existen commits anteriores con esos ficheros.
Para arreglar esto hay que quitar de la caché de git esos ficheros para que se puedan ignorar, para ello
Primero haz commit de todos los cambios que tengas y luego ejecuta:
git rm -rf --cached .
git add .
Esto lo que hará será quitarlos de la caché y añadirlo al stage, ahora solo tienes que hacer commit de esto para que funcione:
git commit -m "Arreglando el gitignore"
Header Files
Flags fuertemente tipadas
marzo 24, 2022 06:45
Introducción
En muchos sistemas es frecuente tener que saber si determinada característica, opción, componente, etc. está habilitado o no. Para ello se suelen usar flags (banderas), definidas como constantes o enumeraciones, y vectores de booleanos o std::bitset
.
enum CompilationFlags {
CompilationFlags_CrossCompilation,
CompilationFlags_Debug,
CompilationFlags_Count
};
std::bitset<CompilationFlags_Count> compilation_flags;
compilation_flags.set(CompilationFlags_Debug, true);
El principal problema de estas soluciones es que se basan en convertir un identificador en un índice en el vector / bitset, lo que lleva a que no haya comprobación en tiempo de compilación de que la característica esté soportada. Por ejemplo, puede ocurrir un desbordamiento de buffer si el índice supera el tamaño máximo del contenedor, o un error de lógica si se consulta un flag no correspondiente a dicho conjunto (pero con el mismo valor numérico).
Propuesta
Una posible solución es definir las banderas como tipos booleanos fuertemente tipados y usarlos en una tupla. En este artículo extenderemos la sintaxis que propusimos en una entrega anterior (Argumentos expresivos 1):
class Flag
{
bool m_value;
public:
Flag() = default;
explicit Flag(bool value) noexcept : m_value{value} {}
operator bool() const { return m_value; }
};
#define FLAG(name) struct name : Flag { using Flag::Flag; }
FLAG(CrossCompilation);
FLAG(Debug);
using CompilationFlags = std::tuple<CrossCompilation, Debug>;
Así, podemos aprovechar el método std::get
basado en tipos para consultar el estado de la bandera:
CompilationFlags comp_flags;
std::get<CrossCompilation>(comp_flags) = CrossCompilation{true}; // to set a value
auto const cross_compilation = std::get<CrossCompilation>(comp_flags); // to get a value
Ahora bien, esta sintaxis puede ser mejorada en varios aspectos; veamos cuáles son.
Estado inicial de la bandera
Lo primero es que no todas las banderas estarán en un estado off al inicio, por lo que podemos modificar el tipo Flag
para considerar este escenario y dotarlas de un estado inicial explícito:
template<bool default_value>
class Flag
{
bool m_value{default_value};
public:
Flag() = default;
explicit Flag(bool value) noexcept : m_value{value} {}
operator bool() const { return m_value; }
};
#define FLAG(name, value) struct name : Flag<value> { using Flag::Flag; }
FLAG(CrossCompilation, false);
FLAG(Debug, true);
Encapsulamiento
Lo siguiente es dotar de una mejor interfaz a nuestra solución. Para ello definiremos una clase Flags
que se hará cargo de dichas funciones. Veremos esta solución en conjunto con la siguiente mejora.
Inicialización selectiva
Aunque las banderas tengan un estado inicial, éste puede que no sea apropiado en algunos casos. Una solución podría ser tener un constructor que reciba todas las banderas, pero claramente no es la opción más limpia, especialmente si el conjunto es grande. En su lugar aprovecharemos el tipado fuerte de las banderas para poder definir un constructor más flexible.
template<typename... Types>
class Flags
{
public:
Flags() = default;
template<typename Flag, typename... Args>
explicit Flags(Flag flag, Args&&... args) : Flags{args...}
{
std::get<Flag>(m_flags) = flag;
}
template<typename T>
bool is_enabled() const noexcept
{
return std::get<T>(m_flags);
}
template<typename T>
void set_enabled(T const& state) noexcept
{
std::get<T>(m_flags) = state;
}
private:
std::tuple<Types...> m_flags;
};
Ejemplo de uso
using CompilationFlags = Flags<CrossCompilation, Debug>;
CompilationFlags const compilation_flags{Debug{false}};
auto const is_debug = compilation_flags.is_enabled<Debug>();
El ejemplo completo puede conseguirse acá.
Conclusión
Como se ha podido ver, el uso de tipos fuertemente tipados aumenta la expresividad del código, permiten soluciones máx flexibles y robustaz, y da una mayor cercanía entre la sintaxis y la semántica.
Por otro lado, permiten sacar partido a una de mis características favoritas de C++: el compilador. Si algo se puede hacer en tiempo de compilación, ¿por qué hacerlo en tiempo de ejecución? Si un fallo se puede detectar cuando sólo nosotros (los desarrolladores) somos los afectados, ¿por qué dejar que el cliente sea el que lo descubra? De todo esto hablaremos en una entrega futura, mientras tanto, y como diría Sheldon Cooper: ¡diversión con banderas!
Una sinfonía en C#
Parámetros, entrypoints y comandos en Kubernetes, ¿cómo funcionan?
marzo 05, 2022 12:00
Si estamos desplegando en Kubernetes en probable que si algo sale mal y necesitamos hacer troubleshooting, entre las herramientas más útiles (quitando los logs) poder ejecutar un comando o “entrar” en un container puede ser muy útil. El problema es si nuestro ejecutable es el que hace que el Pod se reinicie y no podemos obtener acceso al bash del Pod, una forma de solucionar eso es sobre-escribir el comando por defecto, vamos a hablar de eso.
Docker exec, Kubectl exec
La forma de ejecutar un comando (y obtener acceso a la línea de comandos) contra un container esté o no en Kubernetes es utilizando exec (varia un poco la sintáxis entre ambos pero es igual) algo así:
docker exec -it mycontainer bash
o en Kubernetes
kubectl exec -it mypod -- bash
Y con esto obtener acceso a la línea de comandos ya que ejecutamos bash y solicitamos modo interactivo con -it
Nuestro Pod no para de reiniciarse
El problema es que muchas veces nuestra aplicación no terminar de iniciar y genera que el Pod se reinicie todo el tiempo, entonces no podemos acceder a la línea de comando, entonces lo que podemos hacer el sobre-escribir el comando que ejecuta nuestra app y así obtener acceso a la línea de comando y ejecutarla desde ahí y hacer las pruebas correspondientes
Entrypoint, CMD, args, Commands.
Acá comienza la confusión
Si creamos una imagen de algo que no tiene un comando
FROM alpine
docker build -t test .
Y creamos un contenedor
docker run -d test
el mismo se ejecuta y finaliza inmeditamente porque la idea es que sea un proceso continuo, por eso necesitamos un comando
FROM alpine
CMD ["tail", "-f", "/dev/null"]
o un Entrypoint
FROM alpine
ENTRYPOINT ["tail", "-f", "/dev/null"]
¿Pero cuál es la diferencia entre ambos?
En principio ninguna en este caso, pero si lo que queremos es dar la posiblidad de que nuestro comando reciba parámetros (es decir algo detrás del nombre del ejecutable o script, en este caso “f” “/dev/null”) ahí sí que hay diferencia:
Cómo funciona el pasaje de parámetros en Docker?
Al final todo se resume a cómo funciona en Docker ya que Kubernetes se basa en ese comportamiento. Para no ser largo con ejemplos:
Lo que se defina con CMD se sobre-escribe por completo con parámetros en la línea de comandos, entonces esto
FROM alpine
CMD ["echo", "hola"]
Si lo ejecuto imprimer “hola” y finaliza. Pero es completamente sobre-escrito si hago esto:
docker run test echo chau
Estos parámetros reemplaza a todo lo que esté definido con CMD en el Dockerfile
Si hago esto dará error
docker run test hola
porque sobre-escribe todo, y el comando que intenta ejecutar es “chau” que no es válido. Entonces CMD me permite sobre-escribir todo pero no me da la posibilidad de cambiar parte de lo que es el comando original.
¿Qué pasa si quiere pasar parámetros pero que se agregar a mi ejecutable o script?
Para esto existe Entrypoint, si pasamos parámetros en la línea de comandos se toman como argumentos del Entrypoint, es como si se agregasen, por ejemplo esto:
FROM alpine
ENTRYPOINT ["echo"]
docker run test hola
En el ejemplo anterior daría error porque no existe un comando “hola” pero este caso imprime “hola” porque se pasa como argumento a echo
Genial, pero qué pasa si queremos tener un argumento por defecto que se pueda sobre-escribir, bien, combinamos ambos.
FROM alpine
ENTRYPOINT ["echo"]
CMD ["hola"]
Viéndolo así es simple, pero también podemos sobre-escribir el entrypoint en caso que querramos hacerlo
docker run --entrypoint ls test
Y sobre-escribimos el entrypoint y el cmd, de este modo tenemos todas opciones para poder evitar que el comando por defecto del Dockerfile se ejecute para lograr tener un contenedor estable que nos permita trabajar.
Kubernetes
Y cómo se hace todo esto en Kubernetes, con dos opciones, pero lo confuso es el nombre
- args: es equivalente a CMD en Docker
- COMMAND: es equivalente a ENTRYPOINT en Docker
entonces, para el ejemplo anterior en un Pod quedaría así:
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: test
name: test
spec:
containers:
- image: test
command: ["echo"]
args: ["hola desde pod"]
name: test
resources: {}
dnsPolicy: ClusterFirst
restartPolicy: Always
status: {}
Y listo, un ejemplo de cómo tener un Pod que se quede esperando para poder ingresar en él sería:
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: test
name: test
spec:
containers:
- image: test
command: ["tail", "-f", "/dev/null"]
name: test
resources: {}
dnsPolicy: ClusterFirst
restartPolicy: Always
status: {}
y ya podemos ingresar a su línea de comandos
kubectl exec -it test -- sh
Nos leemos.
Coding Potions
Cómo crear tu primer código en Javascript. Hello world!
marzo 05, 2022 12:00
En este artículo voy a tratar de explicarte cómo hacer tu primer código con Javascript.
Te recomiendo que te pases por el artículo de Entorno de desarrollo para frontend para que tengas las herramientas listas para empezar.
Hello world usando editor online (codepen)
La manera más rápida y sencilla de hacer un hola mundo es usar una web en la que puedes programar sin instalar nada.
Una de las que recomiendo es Codepen, simplemente le das a Start coding y ya te abre una pantalla tal que así:
Como ves se te abre un editor muy simple, con el que puedes escribir
HTML
,
CSS
Y Javascript (JS) que es lo que nos interesa para este artículo. Si no sabes lo que son estos lenguajes pásate por el post de Frontend.
Por cierto, en codepen puedes crearte una cuenta para ir guardando los proyectillos que vayas creando.
Vale, pues para escribir el hola mundo tan solo tienes que escribir lo siguiente en la caja de JS:
console.log("Hello world!");
Si ahora le das al botón de abajo a la izquierda que pone “Console”, podrás ver que en la pantalla pone Hello world!.
En eso consiste hacer un hello world, en crear un programita o web que simplemente pinte hello world en la pantalla, así de fácil.
Hello world con ficheros
¿Pero es así de fácil crear un hello world? Pues la realidad es que estás páginas precisamente lo que hacen es facilitarnos la vida para no tener que montar un entorno para desarrollar páginas web.
Si quieres crear un hello world usando ficheros en tu ordenador lo primero que te recomiendo es que tengas un editor de textos de código, puedes usar el que quieras, aunque para empezar te recomiendo que uses el
Vscode
que además es gratis.
Una vez descargado tienes que crear una carpeta en tu ordenador y abrirla con el editor de código. Dentro de esta carpeta crea un fichero llamado index.html
En realidad lo puedes llamar como quieras, pero al fichero principal de una web se le suele llamar index por convención.
El contenido del fichero index.html es el siguiente:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hello world</title>
</head>
<body>
<script>
console.log("Hello world!")
</script>
</body>
</html>
No me voy a parar mucho en explicar HTML, simplemente tienes que saber que con la etiqueta
HTML
de
script
lo que se puede hacer es ejecutar código Javascript, en este caso pues el console.log que lo que hace es escribirlo en la consola del navegador.
Si ahora abres este fichero en el navegador (botón derecho y abrir con firefox o chrome o el que uses) verás que no aparece nada, es normal.
El código que hemos escrito se ejecuta y se imprime en la consola del navegador, y no en la propia página web.
Para abrir la consola del navegador dale a botón derecho en la página y selecciona la opción de inspeccionar elemento o inspect, también puedes usar la combinación de teclas de Control + Shift + I
(en MAC ni idea, supongo que Comando + Shift + I).
Se te ha debido de abrir una ventana, bienvenido a las
Developers tools del navegador
(o herramientas para desarrolladores). Si quieres ser desarrollador web te recomiendo que te habitúes a usar esta herramienta porque la vas a usar mucho.
Con esta herramienta puedes ver el código fuente de una página web, puedes ver lo que se está ejecutando, hacer análisis de la ejecución, ver las llamadas que se hacen a servidor, etc.
Para nuestro caso nos interesa la pestaña de la consola (console). En esta pestaña puedes ver algunos errores y también el código que se ejecuta en los console.log.
Si has seguido bien los pasos deberías poder ver el Hello world.
Código Javascript en fichero independiente
Esto está muy bien, pero la realidad es que escribir código Javascript dentro de los ficheros .html se considera mala práctica, lo mejor es no mezclar lenguajes y separar las cosas en distintos ficheros.
Para el Hello World lo que puedes hacer es crear en la carpeta un fichero llamado index.js (o como quieras llamarlo pero que tenga extensión .js).
Dentro del fichero index.html tienes que modificar la etiqueta de script para que llame al fichero en lugar de ejecutar el código Javascript directamente.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hello world</title>
</head>
<body>
<script src="index.js"></script>
</body>
</html>
Y dentro del fichero .js tan solo tienes que escribir:
console.log("Hello world!");
Y listo, si ahora guardas ambos ficheros y vuelves a abrir las developers tools en el navegador podrás ver que el resultado es el mismo.
Prueba ahora a cambiar el texto entre las comillas dobles y a guardar el fichero. Si vuelves al navegador verás que no ha ocurrido nada, eso es porque tienes que recargar la página para que el navegador refresque los cambios, simplement4e pulsa F5 en la página o dale al botón de recargar web.
Y poco más la verdad. Si eres un programador o programadora que está empezando te recomiendo que tengas paciencia, es normal al principio sentirse abrumado por la cantidad de información que hay y que tienes que aprender, con práctica al final todo sale, buena suerte!
Bitácora de Javier Gutiérrez Chamorro (Guti)
Sourceforge premia de nuevo a FileOptimizer
marzo 04, 2022 07:09

Siguen llegando reconocimientos y galardones a mi FileOptimizer. El último fue el Building Good with C++ Builder Contest 2021, un galardón que además tenía una contrapartida económica. Ahora le toca a Sourceforge, quienes en el pasado lo premiaron en varias ocasiones como Project of the Week y que expliqué en el recopilatorio sobre Galardones FileOptimizer. …
Sourceforge premia de nuevo a FileOptimizer Leer más »
Artículo publicado originalmente en Bitácora de Javier Gutiérrez Chamorro (Guti)
Coding Potions
Comandos de Vim para movimientos entre líneas del fichero
marzo 02, 2022 12:00
En el artículo de Comandos de Vim para movimientos horizontales ya vimos algunos comandos del Modo normal de Vim para movernos dentro de las propias líneas y ahora toca justo lo contrario, movernos entre todas las líneas.
Lo primero, lo que ya vimos en Movimientos básicos en Vim, puedes usar h j k l para moverte, en concreto j k para moverte arriba o abajo una línea.
También puedes combinar j k con números para desplazarte más líenas, por ejemplo: 20
k
para moverte 20 líneas hacia arriba.
Aquí te recomiendo que te pongas :set relativenumber
dentro de tu fichero .vimrc, más info en Configuración básica de Vim.
Ir al principio y al final del fichero
Para ir al principio del documento existe el comando gg
(regla memotécnica good game jejeje).
Mientras que para ir al final del fichero existe la tecla G
, ojo porque es mayúscula, tienes que pulsar SHIFT.
Por ejemplo, si quieres borrar todo el documento puedes hacer: g
g
0
d
G
(ve al principio del fichero, ponte al principio de la líena y borra hasta el final del fichero).
Ir a una línea en concreto
Para ir a una línea en concreto del fichero tienes dos variantes que se comportan igual, elige la que más te guste (o mejor recuerdes):
-
20
G
: Ir a la líena 20 del fichero -
:24
+Enter
: Ir a la líena 24 del fichero
Moverte entre líneas vacías
Este par de comandos viene bien para moverte por el fichero sin tener que usar tantas veces jjjjjj y kkkkkk.
Con `{ te mueves hacia atrás y cada vez que lo pulses el cursor se pondrá en una líena vacía del fichero.
Con }
es lo mismo solo que te mueves hacia adelante en las líneas vacías.
Como muchas veces al programar separamos el fichero por funciones, pues normalmente vas a tener una línea vacía siempre al comienzo de cada función, por eso este par de comandos puede ser bastante útil.
Mover el cursor en la pantalla
Otra cosa que puedes hacer es mover el cursor al principio, al final o al medio de la pantalla, en concreto se hace con las teclas mayúsculas de H M L.
-
Shift
+H
: Mueve el cursor al principio de la pantalla -
Shift
+M
: Mueve el cursor a la mitad -
Shift
+L
: Mueve el cursor al final de la pantalla
Scroll por el fichero sin mover el cursor
Para esto Vim tiene unos cuantos comandos:
-
Control
+y
: Mueve la pantalla una línea hacia arriba -
Control
+e
Mueve la pantalla una línea hacia abajo -
Control
+u
: Mueve la pantalla hacia arriba ½ página -
Control
+d
: Mueve la pantalla hacia abajo ½ página -
Control
+b
: Mueve la pantalla hacia una página entera hacia arriba -
Control
+f
: Mueve la pantalla hacia una página entera hacia abajo
Por cierto, pulsando dos veces zeta zz
puedes centrar el cursor en mitad de la pantalla sin moverlo de la línea que estaba.
Con el plugin de vim-sneak
https://github.com/justinmk/vim-sneak
Este plugin lo uso mucho a lo largo del día y lo recomiendo mucho. La idea es muy simple, una vez instalado, le das a la tecla s
y escribes dos letras, a continuación en la pantalla te saldrán marcadas las coincidencias de esas dos letras en las palabras que hay en la pantalla.
Lo que mola es que para ir a una coincidencia solo tienes que pulsar la letra que te sale en la pantalla, por lo que puedes navegar a cualquier parte de la pantalla usando solo 3 letras.
Vamos, que es como el comando f
y t
que vimos en Comandos de Vim para movimientos horizontales pero más chetado porque puedes escribir dos caracteres. De hecho, este plugin también puede sustituir a f
y t
para que funcionen también con dos caracteres.
Echa un ojo a Plugins interesantes para Vim si quieres descubrir más plugins que recomiendo usar.
Una sinfonía en C#
Acceder a un repository de imágenes con autenticación desde Kubernetes
marzo 01, 2022 12:00
Los Pods en Kubernetes utilizan imágenes, y lo más probable es que estas imágenes estén en un registro fuera del cluster, y lo segundo más probable es que necesite autenticación. Entonces nos encontramos con la pregunta “Cómo hago para que un Pod o Deployment en Kubernetes se autentique para descargar una imagen desde un repositorio que no es público?”. Bien, es post es acerca de cómo resolver este caso en Azure Container Registry, pero podría ser cualquier otro repository.
Secrets al rescate
La respuesta es bastante sencilla, necesitamos crear un secret, pero de un tipo especial en este caso kubernetes.io/dockerconfigjson sin embargo como casi siempre con los secrets lo más adecuado es crearlos en el momento de utilizarlos y no dejar el YAML en en repository de código porque pierden un poco el sentido, el comando para crearlo sería así:
kubectl create secret docker-registry mysecreto --docker-username=username --docker-password=password --docker-server=urldemiregistro
Y el resultado es el siguiente (notemos que ya el password está encriptado)
apiVersion: v1
type: kubernetes.io/dockerconfigjson
data:
.dockerconfigjson: eyJhdXRocyI6eyJ1cmxkZW1pcmVnaXN0cm8iOnsidXNlcm5hbWUiOiJ1c2VybmFtZSIsInBhc3N3b3JkIjoicGFzc3dvcmQiLCJhdXRoIjoiZFhObGNtNWhiV1U2Y0dGemMzZHZjbVE9In19fQ==
kind: Secret
metadata:
creationTimestamp: null
name: mysecreto
¿Cómo usamos el secret para acceder en nuestro pod / deployment?
Bien, esto es relativamente sencillo, solo debemos agregar una opción a nivel de containers (que es imagepullsecrets, porque podrían ser varios)
apiVersion: v1
kind: Pod
metadata:
labels:
run: busybox
name: busybox
spec:
imagePullSecrets: # indicamos que si se necesita autenticación se utilice el user y password del secret
- name: mysecreto
containers:
- image: busybox
args: ["tail", "-f", "/dev/null"]
name: busybox
resources: {}
dnsPolicy: ClusterFirst
restartPolicy: Always
status: {}
Y listo, nos leemos en la próxima.
Coding Potions
Listado de plugins interesantes para Vim y Neovim
febrero 28, 2022 12:00
En este artículo voy a tratar de hacer una lista de algunos plugins de Vim que a mi me encantan y que recomiendo mucho su uso.
Antes de empezar hay que aclarar que algunos plugins funcionan para vim y neovim, pero algunos solo funcionan para neovim.
Te recomiendo que te pases por el artículo de
Cómo instalar plugins en vim
y por el de
Temas de color recomendados para Vim
para que termines de completar tu Vim.
Ya que en el artículo de Configuración básica de Vim no puse nada de config de plugins, voy a tratar de poner aquí la config que uso de cada uno.
Lualine
https://github.com/nvim-lualine/lualine.nvim
Lualine es un plugin que añade una barra de estado en Vim, para saber en qué modo estás, para ver el número de líneas del fichero, la rama de git, etc.
Hace años la gente usaba mucho lightline y el mítico airline, pero los he cambiado por este que es más ligero.
Mi config es la siguiente:
require("lualine").setup {
options = {
theme = "tokyonight",
},
sections = {
lualine_a = { "mode" },
lualine_b = { "filename" },
lualine_c = { "g:coc_status" },
lualine_x = { "branch" },
lualine_y = { "encoding" },
lualine_z = { "location" }
}
nvim-telescope
https://github.com/nvim-telescope/telescope.nvim
Mi plugin preferido para neovim. Se trata de un popup que se abre en medio de la pantalla y que contiene un buscador. Dependiendo del comando que ejecutes para abrir el popup puedes buscar una cosa o otra.
Yo por ejemplo tengo un comando para abrir buscador de ficheros y otro para hacer una búsqueda de un texto de forma global en todos los ficheros del proyecto.
Funciona incluso mejor que el Control + P de vscode porque tiene una pequeña previsualizaciñón del fichero antes de abrirlo.
Mi config de telescope es la siguiente:
telescope.setup {
defaults = {
vimgrep_arguments = {
"rg",
"--color=never",
"--no-heading",
"--with-filename",
"--line-number",
"--column",
"--smart-case",
},
prompt_prefix = " ",
selection_caret = " ",
entry_prefix = " ",
initial_mode = "insert",
selection_strategy = "reset",
sorting_strategy = "ascending",
layout_strategy = "horizontal",
layout_config = {
horizontal = {
prompt_position = "top",
preview_width = 0.55,
results_width = 0.8,
},
vertical = {
mirror = false,
},
width = 0.87,
height = 0.80,
preview_cutoff = 120,
},
file_sorter = require("telescope.sorters").get_fuzzy_file,
file_ignore_patterns = {},
generic_sorter = require("telescope.sorters").get_generic_fuzzy_sorter,
path_display = { "absolute" },
winblend = 0,
border = {},
borderchars = { "─", "│", "─", "│", "╭", "╮", "╯", "╰" },
color_devicons = true,
use_less = true,
set_env = { ["COLORTERM"] = "truecolor" }, -- default = nil,
file_previewer = require("telescope.previewers").vim_buffer_cat.new,
grep_previewer = require("telescope.previewers").vim_buffer_vimgrep.new,
qflist_previewer = require("telescope.previewers").vim_buffer_qflist.new,
-- Developer configurations: Not meant for general override
buffer_previewer_maker = require("telescope.previewers").buffer_previewer_maker,
},
extensions = {
fzf = {
fuzzy = true, -- false will only do exact matching
override_generic_sorter = false, -- override the generic sorter
override_file_sorter = true, -- override the file sorter
case_mode = "smart_case", -- or "ignore_case" or "respect_case"
-- the default case_mode is "smart_case"
},
media_files = {
filetypes = { "png", "webp", "jpg", "jpeg" },
find_cmd = "rg", -- find command (defaults to `fd`)
},
},
}
Y mis keybindings para abrir los popups son los siguientes:
nmap <C-P> :Telescope git_files hidden=true <CR>
nmap <C-T> :Telescope live_grep <CR>
Es decir, con Control
P
(como en el vscode) abro el popup y puedo escribir el nombre del fichero a buscar en el proyecto. Con Control
‘T
lo que se abre es un buscador para buscar cualquier texto en los ficheros del proyecto.
Bufftabline
https://github.com/ap/vim-buftabline
Esta extensión la llevo usando varios años, se trata de una barra que se añade arriba para tener una lista de los buffers abiertos como si fueran pestañas en un editor de textos moderno.
Hay muchas alternativas a este plugin pero al final siempre vuelvo a este por su sencillez y que funciona perfecto.
Config para este plugin creo que no tengo, debo de estar usando la que viene por defecto.
nvim-treeshitter
https://github.com/nvim-treesitter/nvim-treesitter
Plugin para neovim que lo que hace es parsear el código que estás desarrollando para mejorar el coloreado de la sintaxis y el identado. Este plugin muchas veces es necesario para otros.
En la captura puedes ver cómo el código de la derecha tiene más colores debido al parseo que hace treeshitter del código.
Mi config es esta:
ts_config.setup {
ensure_installed = {
"lua",
"javascript",
"typescript",
"html",
"css",
"vue",
"svelte"
},
highlight = {
enable = true,
use_languagetree = true,
},
}
vim-coc
https://github.com/neoclide/coc.nvim
Este plugin es el que uso para el autocompletado y la instalación de lenguage servers (un lenguage server es un sistema independiente del editor de textos que permite añadir autocompletado y funciones del lenguaje a cualquier editor).
Es cierto que en neovim ya se puede instalar de forma nativa los language servers (LSP), pero a mi me gusta más usar coc porque funciona también para vim y además es plug & play.
Tras instalar la extensión te tienes que acordar de instalar también los language servers, para ello tienes que ejecutar un comando dentro de vim tal que así:
:CocInstall coc-tsserver
La lista de language servers la puedes encontrar aquí
Mi config es esta:
set updatetime=100
set pumheight=20
inoremap <silent><expr> <TAB>
\ pumvisible() ? coc#_select_confirm() :
\ coc#expandableOrJumpable() ?
\ "\<C-r>=coc#rpc#request('doKeymap', ['snippets-expand-jump',''])\<CR>" :
\ <SID>check_back_space() ? "\<TAB>" :
\ coc#refresh()
function! s:check_back_space() abort
let col = col('.') - 1
return !col || getline('.')[col - 1] =~# '\s'
endfunction
let g:coc_snippet_next = '<tab>'
Esto lo que hace es hacer que el plugin se comporte más o menos como el autocompletado del vscode, es decir, según escribes te sale un popup con las opciones, y con la tecla Tab seleccionas la opción que quieres añadir
También tengo estos keybindings para poder navegar mejor por el código:
nmap <leader>gd <Plug>(coc-definition)
nmap <leader>gr <Plug>(coc-references)
nmap <leader>gi <Plug>(coc-implementation)
Es decir, con ,
g
d
voy a la definición de la función o de la clase, con ,
g
r
voy a todas los sitios en los que use usa la función sobre la que estoy y con ,
g
i
a su implementación (lo de la coma es porque tengo definida la tecla coma como tecla leader).
Aparte de esta config, vim-coc también tiene otra que se guarda en un fichero aparte llamado coc-settings.json, que en mi caso es este:
{
"coc.preferences.hoverTarget": "preview",
"signature.enable": false,
"suggest.echodocSupport": true,
"suggest.enablePreview": false,
"suggest.floatEnable": false,
"suggest.triggerCompletionWait": 200,
"suggest.maxCompleteItemCount": 16,
"typescript.preferences.quoteStyle": "double",
"javascript.preferences.quoteStyle": "double",
"typescript.suggest.completeFunctionCalls": false,
"javascript.suggest.completeFunctionCalls": false,
"coc.preferences.formatOnSaveFiletypes": ["css", "svelte", "vue", "javascript", "typescript"]
}
Tengo desactivado el cuadradito que sale con documentación de la función a autocompletar porque me he dado cuenta de que me ralentiza bastante.
nvim-comment
https://github.com/terrortylor/nvim-comment
Esta extensión básicamente lo que hace es comentar líneas que tengas seleccionadas, en muchos lenguajes de programación.
Mis keybindings son los siguientes:
nmap <Leader>t :CommentToggle<cr>
vmap <Leader>t :CommentToggle<cr>
Lo que hago simplemente es seleccionar el código que quiera comentar y le doy a ,
t
, y lo mismo para descomentar.
NERDTree
https://github.com/preservim/nerdtree
NerdTree también lleva mucho tiempo en mi config. Se trata de un árbol de carpetas y ficheros que se abre a un lado del editor, como en el vscode.
Lo que me mola es que es muy simple, abres el editor y con el enter entras en el fichero que te interesa.
Otra cosa que mola es que desde el propio árbol puedes crear ficheros, moverlos y borrarlos, todo a golpe de teclado.
Mi config es muy simple:
:let g:NERDTreeWinSize=40
Y el keybinding que tengo para abrirlo es el siguiente:
nmap <Leader>nt :NERDTreeToggle<cr>
Aunque tengo también otro para que se abra directamente en el fichero en el que estoy:
map <Leader>nf :NERDTreeFind<CR>
Por cierto, dentro del árbol, con la tecla m
activas la opción de crear borrar y modificar ficheros o directorios.
vim-sneak
https://github.com/justinmk/vim-sneak
Este plugin sirve para moverte más rápido por la pantalla. El funcionamiento es muy simple, le das a la tecla s
y escribes dos caracteres a los que te quieras mover, luego en la pantalla te salen letras y puedes escribir una de ellas para saltar rápidamente a esa posición.
Mi config es la siguiente:
let g:sneak#label = 1
map f <Plug>Sneak_f
map F <Plug>Sneak_F
vim-gitgutter
https://github.com/airblade/vim-gitgutter
Este plugin lo que hace es añadir los típicos iconos de otros editores de los cambios de git de los ficheros (los de + para las líneas añadidas y el - para las eliminadas).
Para este no tengo config porque hace tiempo que no lo uso.
Otros plugins que tengo pendiente probar
Nvim DAP
https://github.com/mfussenegger/nvim-dap
Este plugin para neovim al parecer permite hacer debugging de unos cuantos lenguajes de programación desde dentro del propio editor de vim.
Para estas cosas ya existían otros plugins en vim, pero este me ha resultado interesante porque tiene también otro plugin asociado llamado nvim-dap-ui que mejora bastante la interfaz.
Lens.vim
https://github.com/camspiers/lens.vim
Al parecer este plugin lo que hace es redimensionar automáticamente los splits dependiendo de cuál tengas el focus, para así poder ver todo el contenido sin que se corte.
Pone que lo hace de forma inteligente para que se adapte al contenido del split, de tal forma que si ocupa poco el split no sea demasiado grande y viceversa.
nvim-spectre
https://github.com/nvim-pack/nvim-spectre
Plugin que permite reemplazar de forma global en varios ficheros a la vez. Mola porque soporta regex y además puedes especificar glob de ficheros para que se modifiquen solo ciertos tipos de fichero de una ruta.
Sinceramente, hasta ahora usaba la funcionalidad de vscode de buscar y reemplazar porque no encontraba manera de poder hacer esto de forma simple en Vim. Tengo ganas de probarlo a ver si me convence.
sniprun
https://github.com/michaelb/sniprun
Sniprun es una herramienta que permite ejecutar una o varias líenas de código sin salir de Vim. Soporta varios lenguajes y lo que mola es que puedes configurar dónde quieres que te salgal el resultado, si en un popup, al lado de las líneas, etc.
Otros plugins recomendados por la gente
Ya que estoy, voy a publicar también algunos plugins que recomienda la gente y que yo no he probado.
Harpoon
https://github.com/ThePrimeagen/harpoon
Harpoon permite añadir marcas en cualquier parte del código de tal forma que puedes navegar posteriormente entre las marcas sin tener que andar con buffers o buscando los ficheros que has abierto.
Ale
Ale lo que permite es que puedas pasar el linter del código cuando modificas ficheros, lo bueno es que te pinta los errores que saque en el propio código para que puedas moficiarlo.
También permite configurar el fixer para que automáticamente corrija el código si puede hacerlo.
Vim goyo
https://github.com/junegunn/goyo.vim
Goyo es un plugin mítico que lo que hace es quitar elementos de pantalla para que puedas escribir en Vim sin distracciones.
project.nvim
https://github.com/ahmedkhalf/project.nvim
Plugin que premite administrar proyectos, es decir, permite poder cambiar entre proyectos y buscar entre ellos.
Conclusiones
Y esto es un poco la lista de plugins que tengo instalados y recomiendo. Si usas alguno y cosideras que es muy interesante mándame un mensaje en Twitter para chekearlo y añadirlo a esta lista.
Coding Potions
Cómo configurar Vim y su configuración recomendada
febrero 23, 2022 12:00
Dónde esta el fichero de config de vim
Lo primero que tienes que saber es que Vim no tiene algo como vscode para configurar el editor de forma cómoda. Vim usa su propio fichero de config que tienes que modificar a mano.
Para el caso de Vim este fichero se encuentra dentro de tu carpeta personal y se tiene que llamar .vimrc
.
Para el caso de Línux sería tal que así:
~/.vimrc
Mientras que el de Neovim estaría en:
~/.config/nvim/init.vim
Para el caso de Windows estaría en:
`C:/Users/<TU USUARIO>/_vimrc`
En Mac debería estar aquí, aunque no lo tengo claro porque no uso Mac:
/usr/share/vim/vimrc
Si no tienes este fichero creado lo tienes que crear de forma manual.
La configuración que uso en mi día a día
Para no andar explicando cada config que tiene Vim porque es mucha, voy a explicar directamente la config que tengo en mi Vim y luego ya modificas tú lo que necesites.
Tengo que aclarar que yo tengo dos configs, una para vim asecas y otra para neovim. Esto es así porque al principio usaba vim y luego me pasé a neovim.
La config para neovim es la misma que para vim asecas, solo que tienes que poner alguna línea menos.
Por cierto, si ves en la config dobles comillas “ significa que es un comentario, en este artículo voy a poner comentarios con el nombre del fichero de config que uso para diferenciar entre vim y neovim
IMPORTANTE: Voy a dejar de lado los plugins, ya que para eso existe el artículo de Plugins interesantes para Vim. Entre los plugins se encuentra uno para poder tener autocompletado en Vim como el del vscode, por si has entrado en este artículo buscando eso.
También te recomiendo que eches un ojo al artículo de
Configuración de Vim para frontend
y al de
Temas de color recomendados para Vim
.
Config general
Lo primero que tengo en mi .vimrc (vim asecas) es lo siguiente:
" .vimrc
set nocompatible
Esto lo que hace es anular la compatibilidad con Vi, el editor antiguo del que se basa Vim. En neovim no necesitas poner esta línea en la config.
También tengo justo debajo esta línea:
" .vimrc
set history=1000
Esta opción lo que hace es aumentar la cantidad de comandos y de cosas que guarda Vim para que luego puedas volver atrás, por defecto es de 20. En neovim esta línea no la tengo en la config porque no es necesaria.
Luego tengo esta línea que lo que hace es que la terminal dibuje mejor el color de fondo, ya que con ciertos temas de color el fondo de la terminal solo se dibuja en la línea con texto. Más info en este issue
" .vimrc
let &t_ut='' " To render properly background of the color scheme
Una vez más, esta líena no la tengo en el fichero de neovim, pero si en el de vim asecas.
Config de ficheros
Una cosa muy recomendable es desactivar los ficheros swap que crea Vim ya que son muy molestos. Los ficheros swap lo que permiten es que aunque cierres Vim puedas volver atrás a cambios anteriores y que no pierdas el fichero original.
Hoy en día esto no es muy recomendable porque por cada fichero se va a crear un fichero swap en el proyecto, recomiendo mejor usar un sistema de control de versiones como git.
Para desactivar los ficheros swap, en el vimrc tengo estas 3 líneas (esto tampoco te hace falta si usas neovim).
" .vimrc
set nobackup
set nowritebackup
set noswapfile
La siguiente líena que tengo en mi .vimrc sirve para poder usar el backspace del teclado en modo insert en cualquier sitio:
.vimrc
set backspace=indent,eol,start " backspace everywhere in insert mode
La línea anterior tampoco la tengo en mi config de neovim, supongo que porque tampoco hará falta.
Las siguientes líneas de la config tienen que ver con el identado:
".vimrc y init.vim
set autoindent " autoindent always ON.
set expandtab " expand tabs
set shiftwidth=2 " spaces for autoindenting
set softtabstop=2 " remove a full pseudo-TAB when i press <BS>
El autoident sirve a la hora de crear nuevas líenas en el fichero, que dependiendo de donde la crees te meta indentado de forma automática.
Con expandtab lo que hago es transformar los tabs del identado en espacios (cuestión de gustos), y con shiftwidth y softtabstop configuro los espacios para que sean por defecto de 2 espacios (no te preocupes porque luego puedes definir que para x lenguaje se aplique una config de 4 o de 8), por ejemplo:
autocmd BufRead,BufNewFile *.java setlocal shiftwidth=4 softtabstop=4
Para el caso de vim asecas también tengo esta config (en neovim no hace falta):
" .vimrc
set encoding=utf-8 " always use unicode
set hidden " to hide warning when opening files
set ignorecase " to ignore case in searchs
Como dicen los comentarios con la primera línea le digo a vim que abra los ficheros en UTF-8, con la segunda línea desactivo un warning molesto al abrir un fichero y tener el actual sin guardar y en la última línea le digo a vim que las búsquedas las haga sin tener en cuenta las mayúsculas y minúsculas. Toda esta config no es necesaria en neovim.
La siguiente config la añadí recientemente. Se trata de una opción que lo que hace es añadir un márgen de unas líneas cuando haces scroll bajando o subiendo el cursor por la pantalla (no me mola que el cursor esté en la última línea de la pantalla al bajar por ejemplo). Esta config también la tengo en neovim.
" .vimrc y init.vim
set scrolloff=8 " Keep at least 8 lines below cursor
Config de interfaz
Sobre la config de interfaz y de UI lo primero que tengo es una opción para habilitar los números relativos. Esto de los números relativos lo que hace es que a la izquierda, en lugar de salirte los números de la línea, te salen de forma relativa, es decir:
Esto sirve para que luego sea más sencillo hacer los saltos de línea, ya que puedes leer directamente el número sin tener que hacer sumas y restas para saber el número de líneas a saltar.
Para activar esto lo tengo así:
" .vimrc y init.vim
set number relativenumber " Relative numbers for jumping
set nu rnu "Hybrid. Relative numbers and the current line number
También tengo esta config para que a la hora de dividir la pantalla en varios ficheros a la vez, siempre se abran a la derecha y abajo. Echa un ojo también al artículo de
Splits en vim
.
" .vimrc y init.vim
set splitbelow splitright " Set the splits to open at the right side and below
También tengo esta opción para mejorar un pelín el rendimiento, lo que hace es desactivar el fold (el plegado y desplegado, las típicas flechitas de otros editores para contraer funciones), como no lo uso pues lo quito.
" .vimrc y init.vim
set foldmethod=manual "To avoid performance issues, I never fold anything
También relacionado con la performance tengo este par de opciones para hacer que la terminal se pinte cuando se necesite y para aprovechar las ventajas de las terminales rápidas.
" .vimrc y init.vim
set lazyredraw
set ttyfast
Para el caso particular de vim asecas también tengo esta config en esta sección:
" .vimrc
set showmatch " higlight matching parentheses and brackets
set wildmenu " enable visual wildmenu
set nohlsearch " clear highlight after a search
La primera opción lo que hace es que cuando te pongas con el cursor sobre un paréntesis o llave, automáticamente te señala el de cierre (o el de apertura si estás en el de cierre).
Con wildmenu lo que consigues es que tengas un pequeño autocompletado de los comandos que escribes con los dos puntos, por ejemplo cuando escribes :color y le das al Tab.
La última opción es para que al buscar cosas en un fichero, cuando navegues a los resultados se borre el higlight, ya que me pone muy nervioso que se mantenga cuando ya he buscado algo.
Config de macros y atajos
Por último vamos a ver la config que tengo de atajos de teclado que uso habitualmente.
Lo primero es saber que tengo la tecla leader usando la coma por comodidad. La tecla leader se suele usar para crear otros atajos, por lo que a partir de ahora cuando veas <leader en la config estoy hablando de esta tecla.
" .vimrc y init.vim
let mapleader = ","
Lo primero que tengo es un snippet para poner un console.log(), como lo tengo mapeado con leader pues para meter el console solo tengo que pulsar ,
,
c
Por cierto, cuando veas nmap significa que es un mapeo para el Modo normal de Vim, mientras que los de noremap lo que hacen es anular mapeos anteriores (hacerlos no recursivos).
" .vimrc y init.vim
nmap <leader><leader>c oconsole.log({});<Esc>0t{la
Este mapeo lo tengo desde hace poco y muy contento. Lo que hace es que al escribir de forma normal en modo insertar, si te da por usar las teclas de dirección del teclado, que no cree puntos de guardado, así cuando pulsas u
para volver atrás no tiene en cuenta la pulsación de las flechas.
" .vimrc y init.vim
inoremap <Left> <c-g>U<Left>
inoremap <Right> <c-g>U<Right>
También tengo estos comandos para poder mover el cursor entre los splits abiertos a la vez en pantalla.
" .vimrc y init.vim
map <C-h> <C-w>h
map <C-j> <C-w>j
map <C-k> <C-w>k
map <C-l> <C-w>l
Es decir, con los mapeos anteriores puedo pulsar por ejemplo Control
+ l
para moverme al split de la derecha o puedo pulsar Control
+ k
para moverme al de arriba.
Los siguientes comandos son para trabajar con los buffers. Cuando abres varios ficheros en Vim vas abriendo buffers, y para nevegar entre ellos tengo esto:
" .vimrc y init.vim
map <C-d> :bnext<CR>
map <C-a> :bprev<CR>
imap <C-D> <Esc>:bnext<CR>a
imap <C-A> <Esc>:bprev<CR>a
Con esto puedo hacer Control
+ d
para ir al buffer anterior y Control
+ a
para ir al buffer siguiente.
Siguientes comandos que tengo:
" .vimrc y init.vim
noremap <silent> <Up> gk
noremap <silent> <Down> gj
Lo que hace es que cuando tienes puesto el editor que haga wrap de las líneas (que si hay una líena muy larga hace un salto de línea “virtual” el editor para que quepa en pantalla), al moverte por las líneas que han saltado puedas hacerlo como si fueran líneas normales.
También tengo estos comandos para poder hacer resize de los splits de manera más comoda:
" .vimrc y init.vim
nnoremap <silent> <Leader>h+ :exe "resize " . (winheight(0) * 5/4)<CR>
nnoremap <silent> <Leader>h- :exe "resize " . (winheight(0) * 4/5)<CR>
nnoremap <silent> <Leader>w+ :exe "vertical resize " . (winwidth(0) * 5/4)<CR>
nnoremap <silent> <Leader>w- :exe "vertical resize " . (winwidth(0) * 4/5)<CR>
Es decir, pulsando ,
h
+
lo que hago es aumentar el tamaño del split de forma horizontal, mientras que con ,
h
-
lo disminuyo, y lo mismo para el verticual pero usando la w
en lugar de la h
.
Estos dos son truquitos que he aprendido recientemente.
" .vimrc y init.vim
nnoremap Y y$
nnoremap n nzzzv
nnoremap N Nzzzv
nnoremap * *zzzv
El primero lo que hace es hacer que la letra Y mayúsculas en modo normal se comporte como el resto de letras mayúsculas (como la D por ejemplo).
Las otras líneas sirven para que al hacer búsquedas y usar la tecla n para ir nevegando entre los resultados, siempre se te mantenga el cursor centrado en pantalla.
Por último tengo este comando que lo que hace es que al usar :bd para cerrar un buffer, en caso de que lo tengas abierto a la vez con otro fichero (en un split), al ejecutarlo no te reviente el split.
" .vimrc y init.vim
nnoremap <silent> <C-q> :lclose<bar>b#<bar>bd #<CR>
Fichero completo de config
Te comparto también ambos ficheros con mi config. No he incluído plugins y config de plugins para que no sea un lío.
.vimrc:
" TABLE OF CONTENTS:
" 1. Generic settings
" 2. File settings
" 3. UI
" 4. Maps and functions
"-----------------------------------------
" 1. GENERIC SETTINGS
"-----------------------------------------
set nocompatible " disable vi compatibility mode
set history=1000 " increase history size
"-----------------------------------------
" 2. FILE SETTINGS
"-----------------------------------------
" Stop creating backup files, please use Git for backups
set nobackup
set nowritebackup
set noswapfile
set backspace=indent,eol,start
" Modify indenting settings
set autoindent " autoindent always ON.
set expandtab " expand tabs
set shiftwidth=2 " spaces for autoindenting
set softtabstop=2 " remove a full pseudo-TAB when i press <BS>
" Modify some other settings about files
set encoding=utf-8 " always use unicode
set hidden
set ignorecase
set scrolloff=8 " Keep at least 8 lines below cursor
set foldmethod=manual " To avoid performance issues, I never fold anything so...
"-----------------------------------------
" 3. UI
"-----------------------------------------
set fillchars+=vert:\ " Remove unpleasant pipes from vertical splits
" Sauce on this: http://stackoverflow.com/a/9001540
set wildmenu " enable visual wildmenu
set number " show line numbers
set showmatch " higlight matching parentheses and brackets
set nohlsearch
set lazyredraw
set ttyfast
set hidden
"-----------------------------------------
" 4. MAPS AND FUNCTIONS
"-----------------------------------------
let mapleader=","
" Snippet for console.log
nmap <leader><leader>c oconsole.log({});<Esc>==f{a
" To avoid undo points when using arrow keys
inoremap <Left> <c-g>U<Left>
inoremap <Right> <c-g>U<Right>
" Whit leader p you can delete things without saving to register so you can
" paste what you have before
vnoremap <leader>p "_d
" Make window navigation less painful.
map <C-h> <C-w>h
map <C-j> <C-w>j
map <C-k> <C-w>k
map <C-l> <C-w>l
" Working with buffers is cool.
map <C-d> :bnext<CR>
map <C-a> :bprev<CR>
imap <C-D> <Esc>:bnext<CR>a
imap <C-A> <Esc>:bprev<CR>a
" Capital Y to copy to the end of the line like C or D
nnoremap Y y$
" To move in the search list but keeping the cursor in the middle of screen
nnoremap n nzzzv
nnoremap N Nzzzv
nnoremap * *zzzv
" To close buffers without closing splits
nnoremap <silent> <C-q> :lclose<bar>b#<bar>bd #<CR>
También te dejo la config para neovim, aunque es muy similar simplemente tiene menos cosas.
"------------------------
" General options
"----------------------------
set lazyredraw
set ttyfast
set number relativenumber " Relative numbers for jumping
set nu rnu " Hybrid numbers, you have relative numbers and the current line number
set autoindent " autoindent always ON.
set expandtab " expand tabs
set shiftwidth=2 " spaces for autoindenting
set softtabstop=2 " remove a full pseudo-TAB when i press <BS>
set scrolloff=8 " Keep at least 8 lines below cursor
set foldmethod=manual " To avoid performance issues, I never fold anything so...
set noshowmode " We don't need to know the insert/normal mode casue we have lualine
set ignorecase
set nohlsearch " Clear search highlights
set splitbelow splitright " Set the splits to open at the right side and below
"---------------------------
" Keybindings
"----------------------------
let mapleader = ","
" Snippet for console.log
nmap <leader><leader>c oconsole.log({});<Esc>==f{a
" To avoid undo points when using arrow keys
inoremap <Left> <c-g>U<Left>
inoremap <Right> <c-g>U<Right>
" Whit leader p you can delete things without saving to register so you can
" paste what you have before
vnoremap <leader>p "_d
" Make window navigation less painful.
map <C-h> <C-w>h
map <C-j> <C-w>j
map <C-k> <C-w>k
map <C-l> <C-w>l
" Working with buffers is cool.
set hidden
map <C-d> :bnext<CR>
map <C-a> :bprev<CR>
imap <C-D> <Esc>:bnext<CR>a
imap <C-A> <Esc>:bprev<CR>a
" Move up/down in wrapped lines by display lines
noremap <silent> <Up> gk
noremap <silent> <Down> gj
" To resize window height
nnoremap <silent> <Leader>h+ :exe "resize " . (winheight(0) * 5/4)<CR>
nnoremap <silent> <Leader>h- :exe "resize " . (winheight(0) * 4/5)<CR>
" To resize window width
nnoremap <silent> <Leader>w+ :exe "vertical resize " . (winwidth(0) * 5/4)<CR>
nnoremap <silent> <Leader>w- :exe "vertical resize " . (winwidth(0) * 4/5)<CR>
" Capital Y to copy to the end of the line like C or D
nnoremap Y y$
" To move in the search list but keeping the cursor in the middle of screen
nnoremap n nzzzv
nnoremap N Nzzzv
nnoremap * *zzzv
" To close buffer without closing splits
nnoremap <silent> <C-q> :lclose<bar>b#<bar>bd #<CR>
Meta-Info
¿Que es?
Planeta Código es un agregador de weblogs sobre programación y desarrollo en castellano. Si eres lector te permite seguirlos de modo cómodo en esta misma página o mediante el fichero de subscripción.
Puedes utilizar las siguientes imagenes para enlazar PlanetaCodigo:
Si tienes un weblog de programación y quieres ser añadido aquí, envíame un email solicitándolo.
Idea: Juanjo Navarro
Diseño: Albin
Fuentes
- Arragonán
- Bitácora de Javier Gutiérrez Chamorro (Guti)
- Blog Bitix
- Blog de Diego Gómez Deck
- Blog de Federico Varela
- Blog de Julio César Pérez Arques
- Bloggingg
- Buayacorp
- Coding Potions
- DGG
- Es intuitivo...
- Fixed Buffer
- Header Files
- Infectogroovalistic
- Ingenieria de Software / Software Engineering / Project Management / Business Process Management
- Juanjo Navarro
- Koalite
- La luna ilumina por igual a culpables e inocentes
- Made In Flex
- Mal Código
- Mascando Bits
- Metodologías ágiles. De lo racional a la inspiración.
- Navegapolis
- PHP Senior
- Pensamientos ágiles
- Picando Código
- Poesía Binaria
- Preparando SCJP
- Pwned's blog - Desarrollo de Tecnologia
- Rubí Sobre Rieles
- Spejman's Blog
- Thefull
- USANDO C# (C SHARP)
- Una sinfonía en C#
- Variable not found
- Yet Another Programming Weblog
- design-nation.blog/es
- info.xailer.com
- proyectos Ágiles
- psé
- vnsjava