jueves, 10 de septiembre de 2015

Nuevos atajos en ZinjaI (parte 1/2)

Las versiones de agosto de ZinjaI traen unas pocas novedades, pero creo que a pesar de ser pocas tendrán un gran impacto, ya que parecen muy útiles. Son algunos atajos para escribir más rápido. Por ahora están algo verdes, pero hay muchos escenarios en los que ya se pueden utilizar. Particularmente les vengo a comentar de tres cosas: las nuevas opciones en el submenú "Generación de código" del menú "Herramientas"; una mejora interesante en el mecanismo de autocódigos; y una nueva forma de editar varios lugares al mismo tiempo. La primera en este artículo, las otras dos quedarán para la segunda parte.

En lo personal, para mí son las tres cosas que no sabía que quería, pero que ahora que las probé las uso cada dos minutos y ya no puedo programar sin ellas. El objetivo de todo esto es como siempre escribir el código muy rápidamente. Y con acento en el "escribir". En un mundo ideal, el tiempo lo tenemos que invertir en "pensar" y no en "escribir". Entonces, mejor aprender a sacarle provecho a todo lo que el IDE nos ofrezca para el "escribir", para que consuma mucho tiempo menos que el "pensar". Sin más preámbulos, he aquí los nuevos trucos.

Si en algún momento, mientras están escribiendo código, presionan Ctrl+Shift+X, verán un nuevo menú contextual (también accesible como submenú desde el menú del click derecho), con algunas opciones para modificar o generar código, que dependerán de dónde estaban parados o qué habían seleccionado. Hay un par de acciones muy simples como "Rodear con if..." que toma el código de la selección y lo "envuelve" entre "if () {" y "}", agregando esas dos lineas antes y después de la selección, agregando un nivel al indentado a cada línea de la selección y dejando el cursor justo entre los paréntesis del "if ()" para que completen la condición. Hay similares para las demás estructuras de control, y hasta para el "#if" del preprocesador.


Pero la opción que me resultó especialmente útil, y que dio origen a este menú es "Generar definición de función a partir de llamada". Yo siempre diseño desde afuera hacia adentro. Simplificando, digamos que en un programa con funciones, primero hago el main y luego las funciones. Se supone que las funciones me tienen que simplificar el main, entonces, al escribir primero el main simplificado voy detectando qué funciones necesito. Luego, las implemento. Y ahí viene esta funcionalidad. Si ponemos el cursos sobre el nombre de alguna de estas funciones que falte implementar en alguna llamada de ese main, el menú nos ofrece definirla. Esto sería, tratar de adivinar cual debería ser el prototipo para la función, en base a cómo se usa en ese main, generar el código que la define, y colocarlo antes del main. En el ejemplo de la próxima imagen, ZinjaI deduce que la función recibe una lista y un entero, propone como nombre para la lista el mismo que uso en el main, pero no tiene como inventar un nombre para el entero, y deduce además que debería devolver un bool por estar en la condición de un "if". Genera el prototipo, lo pega antes del main, y nos deja el cursor entre las llaves para que escribamos el cuerpo de la función.


Finalmente, supongamos otro escenario donde ya escribí un main que resuelve todo, pero como quedó demasiado liado, quiero sacar un poco de código de ahí (algún subalgoritmo en particular) y delegarlo a una función. Aquí lo que hacemos es seleccionar ese código, y elegir la opción "Extraer código en nueva función". Veremos que al hacer esto, la selección se reemplaza por "foo();" y la definición de la función foo aparece justo antes del main, con ese código adentro. Además, foo está en verde en los dos lugares. Esto quiere decir, que si a continuación editamos foo en la llamada del main, el nombre también cambia en el prototipo. Más aún, si agregamos argumentos en la llamada, los argumentos también se agregan al prototipo. Al principio los veremos sin tipo, pero al terminar de escribir la llamada (presionando Esc) ZinjaI realizará las mismas deducciones que en el caso anterior y corregirá el prototipo. El cursor quedará al final del mismo por si faltan ajustes manuales. Por ejemplo, en el caso de la próxima imagen hay que pasar el "cout" por referencia. ZinjaI no deduce (a veces ni se podría) cuando usar referencia y cuando no, ni tampoco deduce nada todavía sobre los "const".


Las deducciones que ZinjaI hace pueden estar algo verdes y fallar en algunos casos, ya las iré mejorando dentro de lo posible y razonable. La mayoría de estas cosas hacen el mismo análisis del código que el mecanismo de autocompletado, así que verán fallas similares. Pero igual por ahora viene andando suficientemente bien en la mayoría de los casos. Las uso mucho cuando doy clases, al desarrollar ejemplos en vivo, donde lo que me interesa mostrar es el algoritmo, o algún concepto teórico, pero no quiero perder tiempo con el tipeo y la sintaxis. La idea de agregar esto la saqué de una charla de la CppCon 2014, donde quien la da (Peter Sommerlad) usa cosas similares en Eclipse; y además de algunos ejemplos que vi en otros IDEs modernos como CLion. Así que no es algo revolucionario, pero aporta valor a ZinjaI, que creo que ya tenía algunas ventajas sobre los demás ejemplos, como el hecho de que sea libre y gratuito, la mayor simplicidad de uso, o el menor consumo de recursos.

Por ahora puedo hacer cosas mayormente locales (todo dentro de un mismo fuente), y bastante limitadas en cuanto a qué puedo deducir y qué no. Pero supongo que como estas, habrá muchas otras operaciones más que puedan automatizarse con poco esfuerzo, o que resulten demasiado tediosas. Escucho ideas.

No hay comentarios:

Publicar un comentario