Quoth kch:
eso es bueno, pero ahora tengo curiosidad por saber cómo puente de secuencias de comandos se compara con applescript. Supongo que tendré algunas lecturas de que hacer.
SB omite algunas funcionalidades que se encuentran en AppleScript. Por ejemplo, el siguiente script mueve todos los archivos desde el escritorio a la carpeta Documentos:
tell application "Finder"
move every file of desktop to folder "Documents" of home
end tell
En SB, la clase SBElementArray restringe severamente su capacidad de aplicar un único comando a varios objetos, por lo que o bien tienen que recurrir a la API de bajo nivel o bien obtener una lista de referencias de archivos individuales y que se muevan uno a la vez:
require 'osx/cocoa'; include OSX
require_framework 'ScriptingBridge'
finder = SBApplication.applicationWithBundleIdentifier('com.apple.finder')
destination = finder.home.folders.objectWithName('Documents')
finder.desktop.files.get.each do |f|
f.moveTo_replacing_positionedAt_routingSuppressed(destination, nil, nil, nil)
end
en rb-appscript, tendrá que utilizar el mismo enfoque que AppleScript:
require 'appscript'; include Appscript
app("Finder").desktop.files.move(:to => app.home.folders["Documents"])
...
SB ofusca el mecanismo de evento de Apple mucho más que AppleScript.AppleScript puede ser difícil de entender, con la sintaxis extraña, la tendencia a conflictos de palabras clave y cosas por el estilo, pero más allá de eso, presenta en gran medida los eventos de Apple tal como están. La única pieza de magia realmente importante en AS es su comportamiento de "obtención implícita" cuando evalúa una referencia literal que no aparece como un parámetro de un comando. El mayor pecado de AppleScript es que su documentación no explica mejor cómo funciona en realidad, pero hay un very good paper by William Cook que arroja mucha luz sobre lo que realmente está sucediendo.
SB, por otro lado, hace todo lo posible para pretender que es un Cocoa API genuino con un comportamiento de estilo Cocoa, por lo que las capas en una gran cantidad de magia. El resultado es algo superficialmente atractivo para los desarrolladores de Cocoa, pero tan pronto como esas abstracciones comiencen a filtrarse, como invariablemente suceden las abstracciones, estás completamente en el mar en términos de entender lo que está sucediendo. Por ejemplo, SBElementArray pretende ser una matriz, incluso subclases NSMutableArray, pero cuando realmente intenta utilizar sus métodos de matriz, la mitad de ellos funcionan y la mitad no. De hecho, no es una matriz real en absoluto; es un contenedor alrededor de un especificador de objeto de evento Apple no evaluado, simulado para pretender que es un NSMutableArray. Entonces, cuando hace algo parecido a un array, estás en gran medida relleno para entender por qué. Y, como se menciona en el n. ° 1, algunas de estas abstracciones espesas dificultan el acceso a la funcionalidad de eventos estándar de Apple debajo.
SB firstmost intenta ser una buena API de Cocoa en lugar de una API de evento de Apple, y termina siendo muy bueno en ninguno.
Appscript, por cierto, sigue el ejemplo de AppleScript y toma el enfoque opuesto: hacer los eventos de Apple correctos, y luego preocuparse por acomodar el idioma del host. Es por eso que algunas personas prefieren RubyOSA sobre rb-appscript; mientras que Appscript es la solución más capaz, si proviene de un entorno orientado a objetos, se sentirá muy extraño. Esto se debe a que los eventos de Apple usan un paradigma basado en RPC-plus-query, y cualquier semejanza que pueda tener APPDA con OOP es puramente sintáctico. La analogía más cercana sería enviar XQueries a través de XML-RPC, y lleva algo de tiempo acostumbrarse.
...
SB tiende a sufrir significativamente más problemas de compatibilidad de aplicaciones que AppleScript.
Algunos de estos problemas se deben a SB imponer sus propias ideas de cómo evento de Apple IPC debería trabajar en la parte superior de la forma en que realmente obras. Por ejemplo, SB crea un conjunto de clases proxy [pseudo] que representan las clases definidas en el diccionario; luego impone varias restricciones sobre cómo puede interactuar con esos objetos basándose principalmente en las reglas de comportamiento orientadas a objetos clásicos.
Por ejemplo, el siguiente script obtiene los nombres de todas las subcarpetas de la carpeta Documentos:
tell application "Finder"
get name of every folder of entire contents of folder "Documents" of home
end tell
Si intenta el mismo enfoque en SB:
finder.home.folders.objectWithName('Documents').entireContents.folders.arrayByApplyingSelector(:name)
se pone en la medida de como el método #folders, arroja un error porque el tipo de la propiedad 'todo el contenido' en el diccionario del Finder se declara como 'referencia'. Como no hay una clase de "referencia" con elementos de "carpeta" definidos en el diccionario, SB no le permite construir esa consulta en particular (a menos que desee bajar a las API de bajo nivel y usar códigos AE sin formato). Es perfectamente legal de acuerdo con las reglas de eventos de Apple, pero no encaja dentro del conjunto de reglas más estrecho centrado en OO impuesto por SB.
Otros errores se deben a SB que hace suposiciones sobre cómo las aplicaciones de secuencias de comandos implementarán ciertos comandos y otras características.Por ejemplo:
tell application "iTunes"
make new playlist with properties {name:"test 1"}
end tell
SB no le permite tomar ventaja de todos los accesos directos proporcionados por iTunes, aunque (se puede omitir la referencia al objeto de origen desea que la lista de reproducción creada en, en cuyo caso el principal 'Biblioteca' se utiliza la fuente), por lo que vamos a escribir en su totalidad para una mejor comparación:
tell application "iTunes"
make new playlist at source "Library" with properties {name:"test"}
end tell
en SB que iba a escribir esto como:
itunes = SBApplication.applicationWithBundleIdentifier('com.apple.itunes')
playlists = itunes.sources.objectAtIndex(0).playlists()
newplaylist = itunes.classForScriptingClass(:playlist).alloc().initWithProperties({:name => 'test'})
playlists.addObject(newplaylist)
Cuando se ejecuta, sin embargo, que vomita en #addObject . En su intento de convertir un único comando 'hacer' en un ejercicio multilínea, SB asume que el parámetro 'at' siempre será una referencia del formulario 'end of < elements> of < object>', que es cómo Cocoa Scripting aplicaciones basadas en lo hacen. Sin embargo, las aplicaciones de carbono no tienen un marco estándar único para implementar el soporte de eventos de Apple, por lo que tienden a variar un poco más en sus requisitos. iTunes, por ejemplo, espera una referencia al objeto contenedor, en este caso 'fuente' Biblioteca "', y no le gusta cuando SB pasa' al final de las listas de reproducción de la fuente 'Biblioteca' '. Así es como muchas aplicaciones de AppleScriptable, pero SB ignora esa realidad en su determinación de estar "orientada a objetos".
Sin embargo, se producen más problemas cuando un diccionario de aplicación no es 100% preciso o exhaustivo en detalle. Ni los formatos aete ni sdef le permiten describir cómo funciona la interfaz de scripting de una aplicación en un 100% de detalle; algunas cosas solo tienen que ser adivinadas por los usuarios, o se describen en documentación adicional; la naturaleza de la propiedad de "contenidos enteros" de Finder es un ejemplo. Otra información, como qué clases de objetos pueden ser elementos de qué otras clases de objetos, y qué tipo de cada propiedad es, en realidad nunca es utilizada por AppleScript en sí misma, solo está allí como documentación del usuario. Dado que AppleScript no confía en esta información, se perderán los errores al probar el soporte de scripting de la aplicación en AppleScript, ya que los scripts funcionan bien a pesar de ello. SB no utiliza esa información, por lo que cualquier error tipográfico dará como resultado características faltantes o rotas que tienen que sortearse al volver a bajar a las API de bajo nivel.
Appscript, BTW, tampoco es 100% 'compatible con AppleScript', pero sí mucho más cerca. Las primeras versiones de appscript también intentaron imponer varias reglas de OO en los eventos de Apple, como aplicar el modelo de objeto definido por el diccionario, pero después de un año de encontrarse con incompatibilidades de aplicaciones gané todo ese código "inteligente" y pasé los siguientes años intentando Black-Box hace ingeniería inversa en las maquinaciones internas de AppleScript y hace que Appscript las emule lo más cerca posible. "Si no puedes vencerlos (que no puedes), únete a ellos", en otras palabras. Y donde Appscript resuelve un problema de compatibilidad, generalmente hay formas de eludirlo, como voltear la configuración de compatibilidad interna, exportar la terminología de la aplicación a un módulo, parchearla a mano y usarla en su lugar, o bajar a su código AE de bajo nivel APIs
...
Fwiw, también debe conectar un par de golosinas appscript relacionados.
Primero, las herramientas ASDictionary y ASTranslate en el sitio de appscript son tus amigos. ASDictionary exportará diccionarios de aplicaciones en formato HTML de estilo appscript y también habilitará el método #help incorporado en rb-appscript; ideal para el desarrollo interactivo en irb. ASTranslate tomará un comando de AppleScript y (los bugs están dispuestos) devolverán el comando equivalente en la sintaxis de appscript.
En segundo lugar, la distribución fuente de rb-appscript contiene documentación y scripts de muestra. Si instala la gema de appscript, recuerde tomar la distribución zip para esos recursos también.
En tercer lugar, Matt Neuburg has written a book about rb-appscript. Ve a leerlo si estás pensando en usar rb-appscript. Y lea el documento del Dr. Cook, independientemente de lo que decida.
...
De todos modos, espero que ayude. (Ah, y disculpas por la duración, pero acabo de escribir unas 25000 palabras esta semana, así que esto es solo un poco de relajación ligera)
p.s. Ned, tu dólar brillante está en la publicación. ;)
¿Por qué no Scripting Bridge? – Chuck
¿puedes ampliar eso? – kch