Copiar la ruta del fichero seleccionado en Finder usando Ruby

septiembre 11, 2011

Tras hablar sobre varios temas, en la última @nscoder_mad acabamos hablando del famoso lenguaje AppleScript. Personalmente es un lenguaje que he intentado varias veces aprender, pero nunca acaba de gustarme. Una de las conclusiones a las que llegamos es que es un lenguaje para no programadores. Quizás uno de los aspectos que no me gusta del lenguaje es que no veo a primera vista los diferentes elementos que conforman el código escrito con otros lenguajes como por ejemplo las palabras reservadas o incluso las propias sentencias en si mismo.

Un ejemplo de Applescript podría ser algo así:

tell application "Finder"
	set theFolder to make new folder at desktop
end tell

Sin duda algo que no se puede negar es su “verbosidad”, cualquiera que lo lea, mas o menos sabe lo que hace este mini-script. Pero, desde mi punto de vista, aunque muy literario, no me resulta cómodo leer código escrito de esta manera.

Pese a que a priori, puede parecer una opción muy asequible para gente que no ha programado en otros lenguajes, lo cierto es que incluso para ellos, crear algo nuevo en Applescript no es tan sencillo, en el fondo es un lenguaje de programación, y no entiende cualquier frase inglesa que podamos escribir.

Sin duda uno de los grandes beneficios de Applescript es su integración dentro de OSX, y como es capaz de interactuar con el sistema y el resto de aplicaciones de una forma muy sencilla.

De hecho, @j4n0 me comentaba que el tenía un script para copiar al portapapeles la ruta del fichero seleccionado en la ventana del Finder, cosa que es bastante útil.

Según lo expuesto hasta ahora, nuestra situación es que pese a que Applescript no parece un lenguaje muy atractivo pero es una “joya” a la hora de interactuar con el sistema operativo.

Por suerte hay una alternativa, gracias al ScriptingBridge, y como hablamos aquí y aquí, podemos usar otros lenguajes de programación como Ruby o Python para acceder a los mismos recursos que Applescript.

Actualmente mi situación es, me gustaría aprender Applescript por curiosidad, pero ¿para qué?. Lo mismo se puede hacer con Ruby, y es un lenguaje que ya conozco 🙂

Continuando con el caso anterior, el código en Ruby para copiar al portapapeles el fichero seleccionado en el Finder sería algo como:

require 'osx/cocoa'
include OSX
OSX.require_framework 'ScriptingBridge'

finder = SBApplication.applicationWithBundleIdentifier_ "com.apple.finder"
fileURL = NSURL.URLWithString_ finder.selection.get[0].URL
system "echo #{fileURL.path} | pbcopy"

Seguramente el código en Applescript ocupa menos lineas, pero al menos para mi, la versión en Ruby es mucho mas clara.

Como breve resumen al código, con la función applicationWithBundleIdentifier_ obtenemos la referencia al objeto “Finder” y usando el comando de consola pbcopy introducimos los datos al clipboard.

Pese a que funciona sin problemas desde la linea de comandos, este script es sobre todo útil cuando lo tenemos en la propia ventana del finder, para ello necesitamos encapsular el script en un bundle de Aplicación que OSX sepa como ejecutar.

Para ello, y aunque podamos hacerlo a mano, existe una utilidad llamada Platypus que nos automatizará el proceso. Una vez que tengamos el bundle solo nos queda arrastrarlo a la barra superior del finder y usarlo siempre que queramos.

Anuncios

Probando clases ObjetiveC usando MacRuby

febrero 12, 2011

Sin duda una de las cosas que siempre me ha gustado tener a mano es una manera de probar código sin tener que crear todo un proyecto para ello. Hace mucho tiempo, cuando usaba Java como mi principal lenguaje de programación, usaba Beanshell, que ademas de ser un lenguaje de scripting ofrece una consola que interpreta código en java en tiempo real.

Por aquel tiempo, si quería probar, por ejemplo, como sacar una subcadena a partir de un carácter dado, podía ir probando con las diferentes combinaciones en la consola de Beanshell. La alternativa era construirse todo un proyecto solo para probar como deberías hacer el substring correcto, proyecto que había que compilar y ejecutar para ver los resultados. Sin duda el hecho de usar una consola que te daba los resultados inmediatos era una gran ventaja.

Mas adelante, y con algunas aventuras en python o ruby, la existencia de la consola para probar código venia de serie con la plataforma. Así si queremos probar un pequeño fragmento de código Ruby, podemos arrancar el irb y escribirlo tal cual.

Hoy en día, en mis aventuras por Objetive-C, echaba de menos esta funcionalidad. Esta claro que al ser Objective-C un lenguaje compilado, a priori es complicado tener un programa que haga esto, pero es aquí donde encaja esa maravilla llamada MacRuby 🙂

Dado a que, usando MacRuby, podemos acceder a todas las clases definidas en los frameworks de OSX sin importar en que lenguaje estén definidas, vamos a poder usar el irb para poder probar esas clases de Cocoa que usamos habitualmente.

Vamos a ver un ejemplo:

Supongamos que tenemos una cadena de la forma “clave=valor;clave2=valor2″” y queremos transformarla en un diccionario que almacene esta información.

Para ello, necesitamos manipular la clase NSString, sin duda una alternativa sería escribir el código (siempre después de los test, claro 😉 ), e ir probando. Pero siempre surgen algunas dudas, como por ejemplo, el IndexOf de NSString, ¿esta basado en 0?, si hago un substring con inicio en la posición 3, ¿incluye el tercer carácter?

Estas dudas, harán posiblemente que el código que escribamos la primera vez, falle.

La alternativa es arrancar macirb, y jugar directamente con la clase NSString. Por ejemplo si ejecutamos lo siguiente:

irb(main):010:0> "clave=valor;clave2=valor2".componentsSeparatedByString(";")
=> ["clave=valor", "clave2=valor2"]

Veremos que el mensaje “componentsSeparatedByString”, funciona como esperábamos. Pero no solo eso, vemos que también podíamos aplicar lo mismo a cada elemento para obtener cada clave y cada valor:

irb(main):012:0> "clave=valor;clave2=valor2".componentsSeparatedByString(";").each { |x| p x.componentsSeparatedByString("=") }
["clave", "valor"]
["clave2", "valor2"]
=> ["clave=valor", "clave2=valor2"]

Como vemos, la comodidad que ofrece el probar código solo con teclearlo directamente en la consola es tremendamente util para reducir muchos ciclos de compilar (o ejecutar test) y ver como vuelve a fallar.

La “magia” de MacRuby no acaba aquí, como hemos dicho antes, podemos llamar a cualquier clase de Cocoa, por lo que si probamos el siguiente código:

irb(main):006:0> framework 'Cocoa'
irb(main):007:0> sp = NSSpeechSynthesizer.alloc.initWithVoice nil
=> #<NSSpeechSynthesizer:0x2005293e0>
irb(main):008:0> sp.startSpeakingString "hello from macruby. This is so cool!"
=> true

Nuestro mac empezará a hablar. 😀

Como veis, la única regla a seguir es en vez de utilizar la sintaxis típica de objetive c para enviar mensajes, debemos utilizar la notación habitual con el “.”. Aunque si esto nos incomoda, siempre podemos seguir usando mensajes gracias al método “send” de Ruby, y de esta manera ejecutar el anterior código como:

irb(main):010:0> sp.send :startSpeakingString, "hello from macruby. This is so cool!"

La interoperabilidad Ruby Cocoa abre todo un mundo de posibilidades, ¿Alguien ha dicho algo sobre RSpec para probar clases hechas en ObjectiveC?. En cualquier caso, son unos interesantes temas para otras entradas del blog.


DSL en Ruby. Generador de LaTeX.

octubre 3, 2010

Lo cierto es que, Ruby es un lenguaje que cuanto más aprendes, más te sorprende. Lo último que he visto sobre el fantástico lenguaje creado por Matz, es la facilidad con que se pueden fabricar “interpretes” de lenguajes específicos, o lo que también se conoce como DSL por ser las anglosajonas siglas de Domain-specific Languages.

Como se puede esperar, estos lenguajes se centran en resolver problemas muy específicos, en lugar de, como C o Java, estar enfocados a un ámbito genérico. Ejemplos de estos DSL pueden ser lenguajes como SQL, HTML, VHDL o YACC. Cada uno de ellos existen para resolver un problema, y difícilmente se podrá utilizar para otra cosa. No me imagino hacer una web con YACC o una consulta a una base de datos con VHDL :-S

Crear estos lenguajes suele ser una tarea compleja, y en muchas ocasiones se suele usar otro lenguaje mas genérico. De hecho, hacer un “interprete” de un lenguaje usando C++ mediante macros y templates es un entretenimiento que no esta accesible a cualquiera 😉

Sin embargo, cuando Ruby se nos cruza en el camino, todo parece resolverse como por arte de magia.

Antes de meternos de lleno en el objetivo del post, que es una especie de sencillo interprete de LaTeX (si, el lenguaje que describe como es un documento 😀 ), vamos a ver que es lo que Ruby hace por que esto sea posible.

Sin duda, el principal elemento que añade la mayor parte de la magia es una sola sentencia, dicha sentencia es: “alias method_missing tag“.

Esa sentencia hará que cualquier invocación de un método no existente de una clase, se “reenviará” al método que le decimos a continuación, en nuestro caso, “tag”.

Si nos paramos a pensar la potencia de este mecanismo es tremenda, podemos hacer que nuestra clase “conteste” potencialmente a cualquier método. Sin duda le añade un factor dinámico al código que es difícil de encontrar en otros lenguajes, y sobre todo, con esa elegancia.

Otro elemento muy importante de la creación de DSL es el método instance_eval de cualquier clase de Ruby. Dicho método ejecutará lo que le pasemos como parámetro en el contexto del objeto sobre el que se invoca. La verdad es que es mas difícil explicarlo que verlo en acción, así que seguro que queda mas claro en este ejemplo:

class Prueba
  def metodo
    puts "Hola Mundo"
  end
end

p = Prueba.new
p.instance_eval "metodo"
=> "Hola Mundo"

Como veis, lo que hace instance_eval es ejecutar el parámetro, como si fuera código que se ejecuta sobre la variable p.

El último elemento clave son los bloques en Ruby. Sin duda uno de mis elementos favoritos del lenguaje, todo método en Ruby, puede llevar asociado un bloque, y dicho bloque se puede capturar como parámetro de un metodo. Si combinamos los bloques con el instance_eval, podemos tener lo siguiente.

class Prueba
  def metodo1
    puts "Método 1"
  end

  def metodo2
    puts "Método 2"
  end

  def self.generate(&block)
    Prueba.new.instance_eval(&block)
  end
end

Prueba.generate do
  metodo1
  metodo2
end
=> Método 1
=> Método 2

Mola, ¿no? 🙂

Pues bien, básicamente con estos elementos, podemos empezar nuestro mini-generador de LaTeX.

El objetivo será que usando una sintaxis mas próxima a Ruby, seamos capaces de crear un documento de LaTeX sin usar casi ninguna {} y sin preocuparnos de que ponemos un \end cuando debemos.

Para ello, debemos crear una clase que sea capaz de que ejecutar el siguiente código en un interprete de Ruby tenga como salida un documento con formato LaTeX

LaTeX.generate(STDOUT) do
  documentclass "article"
  usepackage "amsmath"
  title "\\LaTeX"
  date ""
  start "document" do
    title "hola"
    "Hola, hoy son las #{Time.now} y \\sqrt{2} = #{Math.sqrt(2)}"
  end
end

Como veis, ademas de tener una sintaxis mucho mas “limpia” ganamos la incorporación del propio código Ruby, pudiendo usar cosas como “Time.now” o operaciones como la raíz cuadrada.

Aunque parezca mentira, usando los mecanismos que hemos puesto anteriormente, la clase necesaria seria algo como:

class LaTeX
  def initialize(out)
    @out = out
  end
  
  def tag(tagname, name=nil)
    if tagname == :start
      tagname = :begin
    end
    @out << "\\#{tagname}"
    if name
      @out << "\{#{name}\}"
    end
    @out << "\n"
    if block_given?
      content = yield
      if content
        @out << content.to_s << "\n"
      end
      @out << "\\end"
      if name 
        @out << "\{#{name}\}"
      end
      @out << "\n"
    end
    nil
  end
    
  alias method_missing tag
  
  def self.generate(out, &block)
    LaTeX.new(out).instance_eval(&block)
  end
end

Unicamente, con ese fragmento sencillo de código, seremos capaces de que construir un documento LaTeX sea mucho mas sencillo que lo habitual, pues la ejecución tendrá como resultado

\documentclass{article}
\usepackage{amsmath}
\title{\LaTeX}
\date{}
\begin{document}
\title{hola}
Hola, hoy son las Sat Oct 02 23:49:35 +0200 2010 y \sqrt{2} = 1.4142135623731
\end{document}

Dibujando un Fractal Mandelbrot con Ruby

septiembre 6, 2010

Hace mucho tiempo, cuando aún me pegaba con pascal en primero de carrera empecé a descubrir los fractales. Aún recuerdo lo bien que lo pasaba con el fractint, “navegando por las profundidades de mandelbrot”. Investigando un poco mas, descubrí que la formula que se utilizaba para generar dicho fractal era bastante sencilla, aún así, un software como el fractint parecía demasiado complejo.

Sin embargo, la curiosidad me picaba, ¿Qué pasaría si hiciera un programa que siguiera la formula que sirve para generar el fractal de mandelbrot?. Al fin y al cabo, la formula parecía sencilla de programar incluso para un imberbe programador 🙂

Sin más espera me puse manos a la obra y con el amado Pascal, hice un programa que supuestamente dibujaría el fractal de mandelbrot. ¿Y qué pasó?, pues ante mi asombro, al ejecutar el programa, allí estaba el famoso gráfico con forma de guitarra. ( Notese la licencia literaria, como buen programador, nada funciona a la primera 😀 )

Hace poco, trasteando con el nuevo “juguete”, ruby, me volvio a picar la curiosidad de dibujar de nuevo el fractal. En esta ocasión, gracias a las utilidades que nos da un lenguaje como Ruby y una gran libreria como SDL, en pocos minutos tenia el famoso gráfico en pantalla.

Centrandonos en el lado técnico del fractal, dibujar el conjunto de mandelbrot es más o menos sencillo.

Para cada numero imaginario se desarrolla la serie z(n+1) = z(n)^2 + c. Siendo la z(0) = 0,0 y c el punto sobre el que calculamos el desarrollo de la serie. Para algunos valores de c, la serie converge, y para otros rapidamente escapa a un valor umbral que habitualmente se establece en 2+2i. Si la serie converge, el punto no pertenece a la serie de mandelbrot, y por lo tanto se pinta de negro. Para los puntos que escapan al valor umbral, según los pasos que han necesitado para escapar se les pinta de un color. Pero eso si, a todos los que escapan con el mismo numero de pasos, se les da el mismo color.

Así por ejemplo, para el punto 1+i, si desarrollamos la serie tendremos:

z(1) = (0+0i)^2 + 1+i => 1+i
z(2) = (1+i)^2 + 1+i => 1+3i
z(3) = (1+3i)^2 + 1+i => -7+7i

z(3) escapa de los límites, por lo que el punto 1+i, pertenece al conjunto de mandelbrot y se pintará con el color elegido para los números que escapan en 3 pasos.

Si hacemos esto mismo con cada punto dentro del rango 2, -2 tanto para real como para imaginario, obtendremos el gráfico que encabeza el post.

Aunque han pasado unos cuantos años, no deja de sorprenderme que un programa tan sencillo tenga como salida un gráfico tan interesante y, por que no, bonito.

Realmente el fractal mandrelbrot es apasionante, una de sus propiedades es debido a que es un fractal, se autoreplica, por lo que podemos encontrar la misma forma si vamos haciendo zoom dentro del gráfico. No voy a entrar en mas detalles, pero os dejo con el enlace de la wikipedia que describe muchos detalles de este fascinante mundo.

Para finalizar el post, os dejo con el código ruby que dibuja la imagen. Lo único que necesitais para ejecutarlo es ruby y rubysdl.

require 'sdl'

WIDTH = 600
HEIGHT = 400
REALRANGE = 2
IMRANGE = 2
MAXSTEPS = 20

def mandelbrot_steps(x, y)
	steps = 0
	newx = newy = 0
	while steps < MAXSTEPS and ( ((newx*newx) + (newy*newy)) < ((REALRANGE*REALRANGE) + (IMRANGE*IMRANGE)) ) do
		xtemp = (newx * newx) - (newy * newy) + x
		newy = 2 * newx * newy + y
		newx = xtemp
		steps+=1
	end

	return steps
end

SDL.init SDL::INIT_VIDEO
screen = SDL.set_video_mode WIDTH, HEIGHT, 24, SDL::HWSURFACE

pallete = Array.new
pallete[0] = screen.format.mapRGB(0,0,0)
pallete[1] = screen.format.mapRGB(40,36,196)
pallete[2] = screen.format.mapRGB(30,144,255)
pallete[3] = screen.format.mapRGB(0,0,128)
pallete[4] = screen.format.mapRGB(0,255,0)
pallete[5] = screen.format.mapRGB(0,255,255)
pallete[6] = screen.format.mapRGB(0,0,255)
pallete[7] = screen.format.mapRGB(255,255,255)
pallete[8] = screen.format.mapRGB(255,100,255)
pallete[9] = screen.format.mapRGB(0,255,255)
pallete[10] = screen.format.mapRGB(100,255,100)

(-WIDTH/2).upto WIDTH/2 do |x|
	(-HEIGHT/2).upto HEIGHT/2 do |y|
		scaledX = (x * 2)/(WIDTH/2).to_f - 0.7
		scaledY = (y * 2)/(HEIGHT/2).to_f
		color = pallete[0]
		steps = mandelbrot_steps scaledX, scaledY
		color =  pallete[steps % 10] if steps < MAXSTEPS
		screen.put_pixel x+(WIDTH/2), y+(HEIGHT/2), color
	end
end

running = true
while running do
	while event = SDL::Event2.poll do
		case event
		when SDL::Event2::Quit
			running = false
		end
	end

	screen.flip
end

SDL.quit

RubyQuiz #60. Numeric Maze

agosto 1, 2010

En la época del año en la que estamos lo habitual es que o bien las vacaciones estén cerca o incluso ya estemos disfrutando de ellas. Sin duda es un buen momento para desconectar y hacer cosas que durante el año no podemos hacer.

A los que nos gustan los ordenadores, esto no tiene por que significar que dejemos de usarlos, simplemente podemos usarlos para otras cosas 😉

Personalmente me encantan los problemas numéricos y para ello el ordenador es una herramienta perfecta para desarrollar simples algoritmos que los solucionen.

Hace poco descubrí el rubyquiz . En esta web y en la lista de correo se mandan regularmente diversos problemas y se propone el desarrollar un pequeño programa hecho en Ruby que lo solucione.

El primer reto que he escogido es el número 60, llamado Numeric Maze.

El objetivo es hacer un programa que te calcule la ruta desde un número inicial A a un numero final B, con solo 3 operaciones: sumar 2, dividir por 2 y multiplicar por 2.

Así por ejemplo para llegar de 2 a 9, la ruta seguida será. [2, 1, 3, 5, 7, 9]

Como podemos ver, una de las formas de resolver el problema se trata de construir un con las diferentes posibilidades. A priori lo podemos plantear como un caso de backtracking, o de exploración del árbol en profundidad, sin embargo, esta forma de intentar solucionarlo tiene un problema. No sabemos cuando parar descendiendo por el árbol de soluciones.

La alternativa es explorar el árbol de forma horizontal, es decir, para cada paso, sacar las posibles posibilidades y ir generando el árbol paso a paso con todos los casos en cada nivel. De esta manera nos aseguramos que encontraremos la solución tan pronto aparezca. Aunque la desventaja general de este tipo de métodos es que se generan pasos que no van a ser utilizados para nada.

Además, se plantea una interesante posibilidad de “poda” del árbol, pues no es necesario volver a explorar un número que ya se ha explorado.

De esta manera, el árbol ejemplo para el caso de 2 a 9 seria:

[2]
[4 1]
[8 6 3]
[16 10 12 5]
[18 32 20 24 14 7]
[36 9 64 34 22 40 ...]

Para representar este árbol en Ruby, he escogido una lista que esta compuesta por cada numero del nivel determinado. Como tenemos que guardar la ruta de números que nos ha llevado hasta el resultado, acompañando a cada número se guarda dicho histórico.

Así en el ejemplo anterior, la estructura de datos que manejamos es

[2 []]
[ [4, [2]], [1, [2]] ]
[ [8, [4, 2]], [6, [4, 2]], [3, [1,2]] ]
...
[... [9 [2, 4, 8, 16, 18, 9]],...]

De esta manera cuando lleguemos a la solución ya tenemos el conjunto de números por los que hemos ido pasando.

Finalmente el código Ruby que resuelve el problema es el siguiente:

def solve startNumber, endNumber
  current = []
  curStep = 0
  current[curStep] = [ [startNumber, []] ]
  numbers = [startNumber]
	while (numbers.index endNumber) == nil
	  curStep+=1
	  current[curStep] = []
    current[curStep-1].each do |tuple|
	    if (numbers.index tuple[0] << 1) == nil
	      current[curStep] << [(tuple[0] << 1), tuple[1] + [tuple[0]]]
	      numbers << (tuple[0] << 1)
      end

	    if ((tuple[0] % 2) == 0) and ((numbers.index(tuple[0] >> 1) ) == nil)
	      current[curStep] << [(tuple[0] >> 1), tuple[1] + [tuple[0]]]
	      numbers << (tuple[0] << 1)
      end

	    if (numbers.index tuple[0]+2) == nil
	      current[curStep] << [tuple[0]+2, tuple[1] + [tuple[0]]]
	      numbers << tuple[0]+2
      end
    end
  end

  current[curStep].each do |res|
    return res[1] + [endNumber], curStep if res[0] == endNumber
  end

  return nil
end

p solve 2, 9

# [[2, 4, 8, 16, 18, 9], 5]
# Siendo 5 el numero de pasos usados para llegar a la solución

Como veis el código, aunque en esta Ruby, aun le queda para tener ese toque “perl-extraño” que suelen tener los scripts hechos en Ruby. Esto se debe a que aún mi nivel del lenguaje no es muy alto 😉


Otra manera de programar en Cocoa. Ruby y Python.

abril 28, 2010

Cuando pensamos en desarrollar aplicaciones para Mac, siempre nos viene a la mente Cocoa, y junto a este Framework aparece el lenguaje mas maquero, Objetive-C. Sin embargo, es posible hacer aplicaciones completas usando otros lenguajes, como puede ser Java, C o C++ y los que, desde mi punto de vista, son mas interesantes, estoy hablando de los lenguajes de Script de “moda” Ruby y Python.

Gracias a RubyCocoa y PyObjc, podemos invocar a métodos de clases desarrolladas en ObjetiveC, lo que quiere decir que vamos a ser capaces de utilizar las librerias de Cocoa, desde nuestro lenguaje de script favorito. Además, como ambos vienen instalados por defecto en nuestros OSX, no tendremos que instalar nada para empezar a desarrollar con ellos.

Aparte de la posibilidad de crear aplicaciones Cocoa únicamente usando estos lenguajes de script, se nos abre otra posibilidad bastante interesante. Gracias a la inclusión en OSX del Scripting Bridge y combinándolo con la posibilidad que comentabamos de usar Python o Ruby para usar librerías hechas en Objetive-C, podremos comunicarnos con las aplicaciones Cocoa usando estos lenguajes.

Antiguamente, si hablamos de lenguajes de script, esta posibilidad de comunicación entre aplicaciones estaba limitada al propio AppleScript.

Particularmente no tengo nada en contra de AppleScript, pero siempre me pareció un lenguaje un tanto complicado de aprender, sin embargo, Python o Ruby me parecen lenguajes bastante prácticos, por lo que el hecho de poder usarlos como medio de comunicación con otras aplicaciones Cocoa, me parece una idea tremenda 🙂

A partir de OSX 10.5 se introdujo en el sistema operativo lo que se conoce como Scripting Bridge. Este sistema permite comunicarse con los objetos en ejecución usando mensajes de Objetive-C. Anteriormente la única manera de comunicarse con las aplicaciones era usando comandos AppleScript, por eso, este era el único lenguaje con el que podíamos, por ejemplo, recuperar las canciones de nuestra lista de iTunes.

Como seguramente habreís podido deducir, gracias también al Scripting Bridge, podemos comunicarnos con dichas aplicaciones usando el omnipresente Objetive-C

La inclusión del Scripting bridge, de la misma manera, es cruicial para la parte “servidora”, es decir, el iTunes o el Safari, ya que ha simplificado en gran medida la forma de añadir soporte de Script a una aplicación, pese a que esta tarea sigue siendo no trivial.

Como siempre, la mejor forma de aprender algo es viendo algún ejemplo. Así que vamos a utilizar a Python para listar todas las canciones que tenemos en nuestra librería de iTunes.

El código para realizar esto es bastante sencillo como podemos ver:

import ScriptingBridge

iTunes = ScriptingBridge.SBApplication.applicationWithBundleIdentifier_("com.apple.iTunes")

for source in iTunes.sources():
	print source.name()
	for playlist in source.playlists():
		print "\\---", playlist.name()
		for track in playlist.tracks():
			print "\t\\---", track.name()

Si lo ejecutamos, veremos como se lanza “silenciosamente” iTunes, y momentos después se nos muestra la lista de canciones.

Es importante apreciar que con sólo 6 lineas, estamos salvando muchisimas dificultades que existían en el pasado, y sobre todo, estamos abriendo una posibilidad tremenda para crear nuevas aplicaciones.

Ahora bien, os podeis preguntar, ¿Cómo se que métodos tiene un objeto SBApplication determinado?, ya que por mucho que sea sencillo, si no tenemos documentación al respecto no podemos hacer nada.

Para averiguar que nos ofrece una aplicación existen varios métodos, el mas “visual” es usando la opción de “Abrir Diccionario” del “AppleScript Editor”. Como vemos en la captura.

El otro método “menos amigable” es usar los comandos sdef y sdp, que se encargan de “extraer” la definiciónes de script que posee una aplicación; como podemos ver en la captura de la terminal.

Estos comandos nos sacaran un fichero .h que podemos utilizar para importarlo en nuestro proyecto de Objetive-C, y que desde el punto de vista de nuestros lenguajes de script, nos van a permitir saber que métodos nos expone la aplicación.