Estructuras condicionales en AppleScript

En AppleScript, al igual que en otros lenguajes de programación, existen ciertas estructuras de código para controlar el flujo de ejecución de nuestro programa. Recordemos que un script es un programa con ciertas características especiales.

La estructura más simple es la sentencia que se puede resumir como una orden que indica al programador a su programa. Un ejemplo sería la línea de código con la sentencia say que hemos visto en el ejemplo de Hola mundo de esta serie de artículos.

Otro ejemplo sería la línea de asignación de un valor a una variable.

Estructuras condicionales

Hasta ahora sólo sabemos crear AppleScripts que ejecuten una sentencia detrás de otra, almacenando información y manipulándola. ¿Pero podemos controlar aún más el flujo de ejecución?

Imaginemos que un trozo de nuestro script se ejecute a partir de una hora determinada, por ejemplo, un aviso para el usuario. Lo primero que debemos hacer es obtener la hora actual. Este ejemplo nos explica cómo hacerlo:


(*
Ejemplo para obtener la hora actual
*)
on run
set fecha to current date
set hora to fecha's hours
end run

En la variable hora se almacena el valor numérico de la hora actual.

Estructura if then

Para poder ejecutar un trozo de código si se cumple una condición debemos utilizar una estructura condicional. La estructura condicional más básica, y común a muchos lenguajes de programación, es la estructura if-then. La traducción al castellano de if, then es si, entonces….

Veamos su sintaxis en AppleScript para entenderla mejor:

if condición a cumplir then
código a ejecutar
end if

En la condición a cumplir se debe indicar una comparación u operación que devuelva un valor verdadero o falso. Ejemplo de esto son operaciones comparativas del tipo A < B, A = B, Nombre = «Jonathan»

Ampliemos nuestro ejemplo anterior para dar un mensaje por voz si la hora es mayor o igual a siete. El ejemplo quedaría así:


(*
Ejemplo para dar un aviso según la hora
*)
on run
-- obtenemos la fecha
set fecha to current date
set hora to fecha's hours
-- según la hora damos el aviso
if hora >= 7 then
say "¡Despierta! Ya es tarde"
end if
end run

En este ejemplo vemos otra forma de incluir comentarios: escribiendo dos caracteres de guión consecutivos (-) indicamos que lo que hay a la derecha de esa línea es un comentario de código. Es una forma de incluir comentarios de forma rápida.

Estructura if then else

El ejemplo anterior sólo nos avisará si son las 7 o más tarde pero no hará nada si es antes de las siete. A veces nos interesa realizar operaciones distintas tanto si se cumple la condición como si se cumple lo contrario. Una forma de hacer esto sería declarar dos estructuras if then con condiciones contrarias. Un ejemplo de esto sería:


(*
Ejemplo 2 para dar un aviso según la hora
*)
on run
-- obtenemos la fecha
set fecha to current date
set hora to fecha's hours
-- según la hora damos el aviso
if hora >= 7 then
say "¡Despierta! Ya es tarde"
end if
if hora < 7 then say "Todavía es temprano. Aprovecha." end if end run

Aunque esta solución pueda considerarse válida resulta poco eficiente y complica el código. Es poco eficiente porque para hacer una acción u otra realiza dos comparaciones. El código resulta más confuso porque ambas estructuras resultan iguales salvo por un signo matemático pudiendo provocar la confusión del programador.

AppleScript, como otros lenguajes, proporciona una solución elegante para cuando queremos ejecutar un trozo de código tanto para cuando se cumple una condición como para cuando se cumple la contraria. Veamos el ejemplo con esta nueva estructura condicional mejorada:


(*
Ejemplo 3 para dar un aviso según la hora
*)
on run
-- obtenemos la fecha
set fecha to current date
set hora to fecha's hours
-- según la hora damos el aviso
if hora >= 7 then
say "¡Despierta! Ya es tarde"
else
say "Todavía es temprano. Aprovecha."
end if
end run

Como se ve en el código aparece la palabra reservada del lenguaje else. Esta partícula nos permite incluir una separación en la estructura condicional para indicar que el código a continuación se ejecutará sólo si no se cumple la condición. La sintaxis completa es:

if condición a cumplir then
código a ejecutar cuando se cumple la condición
else
código a ejecutar si no se cumple la condición
end if

Ahora podemos crear scripts más complejos que realicen operaciones según se cumplan o no ciertas condiciones.

Variables en AppleScript

AppleScript, al igual que en otros lenguajes de programación, nos permite utilizar variables para almacenar y manipular información.
Su uso es muy sencillo. Para declarar y asignar un valor a una variable debemos seguir la siguiente sintaxis:

set nombreDeVariable to valorParaLaVariable

Veamos un ejemplo simple:


on run
set mensaje to "Hola mundo!"
say mensaje
end run

Para reasignar el valor de una variable se sigue la misma sintaxis. En la asignación podemos realizar encadenamiento de cadenas de texto, operaciones matemáticas, etc.

Veamos un ejemplo en la que asignamos el valor 1 a la variable valor, pronunciamos su valor, reasignamos el valor de la variable al valor que tenía antes más una unidad y volvemos a pronunciarlo:


on run
set valor to 1
say valor
set valor to valor + 1
say valor
end run

Problemas de formatos y tipos

Las variables pertenecen a distintos formatos (texto, números enteros, números decimales, estructuras de datos, etc) y formatos (UTF-8, UTF-16, Unicode, etc). Si intentamos manipular variables entre si con tipos o formatos distintos podemos obtener un error. Por ejemplo, la función say, que pronuncia un texto, espera que le pasemos una variable de texto o de números enteros.

Veamos un ejemplo en el que intentamos hacer un script para que nos pronuncie la fecha de hoy:


on run
set fecha to current date
say fecha
end run

Si intentamos ejecutarlo obtendremos el siguiente mensaje de error: No es posible convertir date «sábado 18 de agosto de 2012 09:44:04″ en tipo «class utf8».

Para solucionar este problema deberemos convertir el valor de fecha, que está en el formato de fecha del sistema, a un valor de cadena de texto.

Para convertir el valor de una variable a otro formato debemos realizar una conversión. La conversión en appleScript sigue la siguiente sintaxis:

( variable as tipoAConvertir )

Necesitamos convertir el tipo fecha de la variable fecha a un tipo de cadena de texto. El ejemplo quedaría así:


on run
set fecha to current date
set fechaEnTexto to (fecha as text)
say fechaEnTexto
end run

Hola mundo en AppleScript al detalle

Un script de AppleScript es un conjunto de órdenes que siguen una gramática definida por el lenguaje y se ejecuta de forma ordenada empezando por arriba del script y terminando por abajo.

Este lenguaje de programación posee similitudes con otros lenguajes de programación para poder crear scripts más complejos. Podemos crear estructuras repetitivas, ejecutar ciertos comandos dependiendo de condiciones, almacenar y manipular información etc.

Analizando el código fuente

Vamos a analizar paso a paso el código fuente de un script de ejemplo Hola mundo, el cual, hemos visto en otro artículo de este blog. El código es el siguiente:


(*
Ejemplo 1:
Hola Mundo
*)
on run
say "Hola mundo!"
end run

Comentarios en AppleScript

Al principio del script encontramos esta estructura:


(*
Ejemplo 1:
Hola Mundo
*)

Esta es una estructura de comentario, en el código de las aplicaciones, sean scripts o aplicaciones compiladas, se introducen mecanismos para proporcionar comentarios y anotaciones para el programador, de esta forma puede detallar qué hacen ciertas partes del código del programa para refrescar la memoria por si vuelve a esa zona del código pasado un tiempo u otro programador accede al código de la aplicación.

En AppleScript se puede comentar un trozo de código utilizando los operadores (* (abre paréntesis seguido de asterísco) y *) (asterisco seguido de cierra paréntesis). Todo lo que esté entre estos dos operadores será ignorado por el intérprete de AppleScript a la hora de que el script sea ejecutado.

Zonas de ejecución

Siguiendo con el código del ejemplo nos encontramos una estructura que comienza por on run y termina con end run. El comando on nos permite definir un trozo de código que será ejecutado cuando suceda algo específico. En nuestro caso, la sentencia on espera al evento run que tiene lugar nada más comienza a interpretarse el script.

El comando end se utiliza para indicar el final de una estructura. Puede ser una estructura on, una estructura condicional, un bucle, etc. Veremos más ejemplos más adelante.

Haciendo hablar a nuestro script

Por último, sólo nos queda la sentencia say "Hola mundo!" Esta sentencia se compone del comando say y una cadena de texto, encerrada entre comillas («»).

El comando say verbalizará lo que haya a su derecha utilizando la voz del sistema. Puede modificarse su comportamiento pero esto lo veremos más adelante.

Complicando el ejemplo

El ejemplo anterior es muy simple ya que utiliza la configuración por defecto del sistema. El utilizar el comando say puede crear conflictos con otros métodos de verbalización de información. Por ejemplo, VoiceOver, el lector de pantallas de Mac OSX utilizados por los usuarios ciegos, puede sufrir problemas de tartamudeo o colapso en la voz si se usan demasiadas sentencias say consecutivas. Una forma de solucionar esto es hacer que la propia aplicación VoiceOver sea la que hable en lugar de que hable el sistema. Además, esto permitirá que se use la voz personalizada por el usuario de VoiceOver en lugar de la personalización del sistema. Para hacer esto debemos saber si el usuario está ejecutando VoiceOver y, si es así, usar las funciones de VoiceOver, si no es así deberemos seguir utilizando el comando say ya que no hay peligro de conflictos con los servicios de síntesis de voz.

El código de nuestro script sería el siguiente:


(*
Ejemplo 2:
Hola Mundo con VoiceOver
*)
on run
say "Hola mundo"
tell application "VoiceOver"
output " desde VoiceOver!"
end tell
end run

Al ejecutar el script escucharemos, con la voz del sistema, el texto Hola mundo y, los usuarios que tengan VoiceOver activado además escucharán el texto desde VoiceOver con la voz que tengan configurada en su lector de pantallas.

Si comparamos los dos scripts veremos que lo nuevo se concentra en el siguiente trozo de código:


tell application "VoiceOver"
output " desde VoiceOver!"
end tell

El comando tell hace que nuestro script se comunique con una aplicación para utilizar sus funciones. En nuestro caso se comunica con la aplicación VoiceOver. Una vez comunicados con VoiceOver podemos utilizar varios comandos AppleScript que VoiceOver nos proporciona, entre ellos, tenemos el comando output que nos permite utilizar los canales de salida de VoiceOver, los cuales pueden ser la voz sintética, la línea braille conectada al equipo y el sistema de subtítulos de VoiceOver.

A algunos usuarios de VoiceOver no les funcionará el anterior script debido a que tienen desactivado el soporte de script de VoiceOver por lo que al solicitar desde un script de AppleScript que VoiceOver nos ceda el control, se devolverá un mensaje de error. En un próximo artículo veremos cómo solucionar esto.

Iniciación a AppleScript

Apple incluye dentro de su sistema operativo para ordenadores de escritorio y portátiles un lenguaje de scripts conocido como AppleScript. Este lenguaje nos permite crear tareas y pequeños programas para automatizar rutinas o mejorar el funcionamiento de algunas aplicaciones.

En la documentación de AppleScript podemos encontrar el siguiente texto descriptivo:

AppleScript es un potente y versátil lenguaje para la creación de scripts que se incluye en Mac OS X. Puede utilizar AppleScript para crear funciones rápidas, automatizar tareas repetitivas o incluso crear aplicaciones personalizadas que le ahorren gran cantidad de tiempo. AppleScript le permite controlar las aplicaciones que admiten el uso de scripts.

Un script de AppleScript consiste en una serie de comandos en inglés que realizan acciones sobre objetos. Ejemplos de acciones: open, close, get the name of (es decir, abrir, cerrar, obtener el nombre de). Los objetos pueden ser, por ejemplo, una aplicación, una ventana o un ajuste de preferencias.

Un script puede controlar una o más aplicaciones. Para que una aplicación permita el uso de scripts, debe definir los términos que se pueden emplear en los scripts. Mac OS X incluye varias aplicaciones que aceptan scripts.

Herramientas para desarrollar en AppleScript

Mac OSX incluye una aplicación para editar, compilar y depurar los scripts que desarrollemos. Esta aplicación se llama Editor AppleScript. En la documentación de la aplicación encontramos la siguiente definición:

Editor AppleScript es una aplicación para crear scripts muy fácil de utilizar que permite leer, escribir, grabar y guardar scripts de AppleScript.

Estas son algunas características de Editor AppleScript:

  • Ofrece una interfaz unificada y fácil de usar
  • Le permite buscar y reemplazar en el texto del script
  • Realiza un ajuste automático de las sentencias de gran longitud
  • Le permite deshacer varias acciones
  • Ofrece scripts de menú de función rápida para agilizar la redacción de scripts
  • Ofrece soporte para los servicios de las aplicaciones
  • Le permite acceder a scripts de aplicación mediante la paleta Biblioteca.
  • Ofrece un Asistente para Scripts que le ayuda a completar las sentencias
  • Ofrece el historial de resultados y el historial de registro de eventos para que pueda examinar qué ocurre en un script

Editor AppleScript está incluido en Mac OSX. Está situado en la carpeta Utilidades, de la carpeta Aplicaciones del disco duro.

Conceptos básicos de AppleScript

Cuando se ejecuta un script, AppleScript envía eventos Apple al sistema o a las aplicaciones que llevan a cabo los comandos. Estos eventos Apple son mensajes enviados a objetos del sistema o de aplicaciones instaladas en el sistema. Las aplicaciones o el sistema devolverán un resultado al script. Por ejemplo, si un script envía una petición a una aplicación para obtener el nombre de un objeto, la aplicación devuelve el nombre o un mensaje de error si no pudo realizar la petición.

No es necesario conocer los eventos Apple en profundidad ya que el editor AppleScript y sus funciones nos simplifican la tarea.

Applets

Un script que se guarda como aplicación se llama «aplicación AppleScript» o «applet». Los applets se ejecutan automáticamente al abrirse y realizan los comandos del script. Los applets pueden estar formados por solo un par de comandos, o ser aplicaciones más complejas.

Los applets pueden guardarse como editables o como solo ejecutables. Un applet editable sigue conteniendo el texto del script, por lo que puede editarse y volver a compilarse en cualquier momento.
Al guarda un script como solo ejecutable, la parte de texto editable se elimina y el archivo ya no puede modificarse ni volver a compilarse.

Ejemplo simple

Vamos a realizar la primera aplicación que todo desarrollador hace al aprender un lenguaje de programación, el conocido Hola mundo!. Abre el editor AppleScript y pega el siguiente código de ejemplo:


(*
Ejemplo 1:
Hola Mundo
*)
on run
say "Hola mundo!"
end run

Ahora ejecuta nuestro script bien pulsando la combinación Comando+R o usando la opción Ejecutar del menú Script del editor AppleScript. El sistema verbalizará el mensaje Hola mundo! utilizando la voz del sistema.

Automator, programación simple para usuarios de Mac OSX

Apple en su sistema operativo para ordenadores de escritorio y portátiles, más conocido como Mac OSX, incluye un lenguaje de script para poder realizar operaciones de forma controlada. Este sistema de scripts es conocido como Apple script. Con este sistema se pueden realizar varias operaciones así como ampliar funcionalidades del sistema operativo o algunas aplicaciones. El problema es que es necesario conocer el lenguaje de programación utilizado por Apple script y tener conocimientos de programación.

Apple es cosciente de las limitaciones de muchos usuarios que carecen de los conocimientos necesarios para utilizar Apple script pero conoce la necesidad de proporcionar alguna herramienta que permita a un usuario sin conocimientos en programación crear mecanismos para realizar, de forma automática, tareas monótonas y mecánicas. Por esta razón Apple ha desarrollado Automator.

Automator

Apple describe Automator de la siguiente forma:

Automator es un innovador asistente de procesos de automatización que facilita la automatización de las tareas repetitivas. Con Automator, podrá evitar las tediosas tareas de programar y crear scripts que suelen ser necesarias para crear procesos de automatización. Cada uno de los pasos de un proceso automatizado, denominados acciones, pueden ensamblarse en una tarea completa arrastrando las acciones hasta un flujo de trabajo de Automator. Puede ejecutar los flujos de trabajo finalizados tantas veces como desee e incluso compartirlos con otros usuarios.

De forma resumida podemos decir que Automator es una herramienta de desarrollo para crear macros sencillas utilizando las aplicaciones y servicios del sistema para que el ordenador realice por nosotros las tareas repetitivas y monótonas.

Automator trabaja con acciones y flujos de trabajo simplificando el proceso de crear macros y pequeños scripts.

Flujos de trabajo

Un flujo de trabajo consiste en un conjunto de tareas que deben realizarse en un orden determinado para alcanzar un objetivo. Cada una de estas tareas recibe un elemento, lo manipula, y lo pasa a la siguiente tarea del flujo de trabajo. Un ejemplo de la vida real, por ejemplo, sería el que podemos experimentar a la hora de convertir un documento de texto en un audio que escuchamos en nuestro reproductor MP3. El flujo sería algo similar a lo siguiente: descargamos el documento de texto, lo abrimos con nuestra aplicación de conversión texto a voz, cogemos los archivos MP3 generados y los pasamos a nuestro reproductor MP3 para, posteriormente, comenzar a escuchar el documento donde queramos. En este ejemplo el contenido del documento es el elemento que las distintas tareas manipulan hasta alcanzar el objetivo final.

Acciones

Las acciones son los distintos mecanismos de manipulación que Automator posee. En nuestro ejemplo serían las diversas tareas que realizamos con el contenido del documento. Automator posee una librería de acciones para crear nuestros flujos de trabajo. Esta librería se ve ampliada con cada nueva aplicación instalada en el sistema operativo que incluya compatibilidad con Apple script o Automator. Esto hace que Automator vaya siendo cada vez más potente.

Aprender con un ejemplo

En el ámbito de la programación el camino del aprendizaje suele basarse en la experimentación práctica así que aprendamos Automator con un pequeño ejemplo. Vamos a crear un servicio para el sistema que nos permita convertir ficheros de texto plano en archivos de audio en formato AIF, soportados por el reproductor de MP3 de Apple. De esta forma tendremos un rudimentario sistema para convertir ficheros de texto en audio para escucharlos donde queramos.

Para ayudar a los usuarios con discapacidad visual a seguir este pequeño tutorial se incluirán indicaciones para los usuarios de VoiceOver, el lector de pantallas de Mac OSX para usuarios con discapacidad visual. Aquellos usuarios que no utilicen este producto de apoyo pueden ignorar estas indicaciones.

Primer contacto con Automator

En primer lugar debemos abrir Automator, para ello debemos buscar la aplicación en la carpeta de aplicaciones del sistema.

Una vez abierto nos mostrará un asistente que nos preguntará que tipo de flujo de trabajo queremos crear. La ventana del asistente proporciona una descripción de cada tipo de flujo de trabajo disponible. Si leemos la descripción para el tipo Servicio podremos leer lo siguiente:

Los servicios son flujos de trabajo contextuales disponibles a través de Mac OS X. Aceptan texto o archivos de la aplicación activa o del Finder. Los servicios están disponibles en el menú Servicios

. Esta descripción es la más cercana a lo que necesitamos para nuestro ejemplo por lo que seleccionaremos esta opción y pulsaremos el botón Seleccionar.

El área de trabajo

A continuación nos aparecerá la ventana de trabajo de Automator con el flujo de trabajo Sin título. Ha de recorddarse que Automator es una herramienta de desarrollo por lo que el consumo de recursos para crear flujos de trabajo es grande así que no os asusteis si el equipo empieza a ir lento.

En el centro de la ventana veremos una tabla con las tareas de nuestro flujo de trabajo. Esta tabla es reconocida por voiceOver con el texto Sin título flujo de trabajo. Al profundizar sobre esta tabla encontraremos nuestra primera acción del flujo. Es una tarea de recepción identificada por el texto El servicio recibe la selección de. VoiceOver identificará esta tarea con el texto texto en El servicio recibe la selección de cualquier aplicación Reemplaza el texto seleccionado grupo (1 de 1). Podemos modificar algunos parámetros de esta tarea para ajustarlos a nuestras necesidades. Los usuarios de VoiceOver deberán profundizar en la tarea para cambiar los diversos parámetros que posee.

Ajustando la acción a nuestros requisitos

Para nuestro servicio queremos recibir un documento de texto desde el Finder, que es nuestro explorador de archivos. En el primer parámetro seleccionaremos Documento y para el segundo parámetro seleccionaremos Finder. VoiceOver verbalizará, al leer la tarea, lo siguiente: documentos en El servicio recibe la selección de Finder Reemplaza el texto seleccionado grupo (1 de 1)

Para cambiar el valor de cada parámetro debemos hacer click sobre él y nos aparecerá una lista desplegable con todos los posibles valores.

Añadiendo más acciones

Ahora debemos añadir, a continuación de la acción para recibir el documento, una nueva acción para convertir el fichero de texto plano en un fichero de audio. Mac OSX proporciona un comando del terminal para verbalizar mensajes de voz, es el comando say. Este comando, entre sus parámetros, nos permite crear un fichero de audio en lugar de verbalizar el texto. Es la forma más rápida para convertir un texto a audio. Por esta razón utilizaremos para este ejemplo este comando del terminal.

Para poder añadir comandos del terminal en nuestro flujo de trabajo debemos utilizar una acción de tipo Ejecutar el script Shell. Para ello nos dirigiremos a la biblioteca de acciones, los usuarios de VoiceOver deben profundizar en el elemento vista dividida de descripción de acciones dividir grupo y, posteriormente, profundizar sobre vista dividida de biblioteca de acciones dividir grupo. Encontraremos una tabla de la biblioteca de acciones y una tabla de acciones. En la segunda tabla se mostrarán las acciones asociadas a la categoría que representa la primera tabla. Para nuestra acción debemos elegir la categoría Utilidades en la primera tabla, así podremos seleccionar el elemento Ejecutar el script Shell. Pulsa Enter para añadir esta nueva acción a nuestro flujo de trabajo.

Ahora debemos ajustar la nueva acción para que ejecute un pequeño script del terminal que convierta el documento de texto a un archivo de audio utilizando el comando say. La acción de ejecución del script, identificada por VoiceOver como Ejecutar el script Shell acción (2 de 2), debe recibir algunas modificaciones para que se adapte a nuestros requisitos. El parámetro Pasar datos de entrada:, con valor por defecto a string, debe tener el valor como argumentos. A continuación de dicho parámetro hay un campo de texto donde se ve un pequeño script de consola por defecto. El código por defecto del script es el siguiente:


for f in "$@"
do
echo "$f"
done

Podemos editar el código para modificar el comando echo o sustituir todo el script por el siguiente código:

Nuestro flujo de trabajo está terminado. Ahora debemos guardarlo utilizando la opciem>Guardar del menú Archivo de la barra de menú. Nos preguntará por un nombre para nuestro flujo de trabajo, podemos nombrarla como Convertir a voz

Una vez guardado pertenecerá a los servicios de Finder. Cerremos Automator y busquemos en Finder un archivo de texto plano. Al utilizar el menú contextual del archivo, los usuarios de voiceOver deben utilizar la combinación Control+ALT+Mayúsculas+M y el resto de usuarios hacer click con el botón derecho, nos aparece una opción con el nombre de nuestro flujo de trabajo. Al seleccionar esta opción comenzará a ejecutarse nuestro flujo de trabajo, visualmente se verá una rueda dentada trabajando, los usuarios de VoiceOver no tendrán ningún tipo de feedback. El proceso tardará dependiendo del tamaño del archivo que queramos convertir.

Hay muchas mejoras que se le pueden hacer a este flujo de trabajo: soportar documentos en formato RTF, poder seleccionar otra voz, añadir un feedback para los usuarios de VoiceOver, etc. Pero como iniciación a Automator creo que es suficiente.