Подтвердить что ты не робот

Избегайте AppleScript через Ruby: rb-appscript или rubyosa?

Приветствуем маминовских рубистов и ненавистников AppleScript,

Для тех из вас, у кого есть опыт работы с rubyosa и rb-appscript, я хотел бы услышать плюсы и минусы каждого из них, с которым вы решили придерживаться, и какой из них вы бы рекомендовали бы полностью, -AppleScript опытный рубиновый старомодный. Кроме того, есть ли другие варианты, которые я пропустил?

Как и в любом случае, любые советы, касающиеся стороны AppleScript уравнения (например, словари для просмотра и т.д.), также приветствуются.

Видя некоторые примеры кода также помогает много.

4b9b3361

Ответ 1

Quoth kch:

Это хорошо, но теперь мне интересно как скриптовый мост сравнивается с AppleScript. Наверное, у меня есть считывание делать.

В SB отсутствует какая-то функциональность, найденная в AppleScript. Например, следующий script перемещает все файлы с рабочего стола в папку "Документы":

tell application "Finder"
   move every file of desktop to folder "Documents" of home
end tell

В SB класс SBElementArray строго ограничивает вашу способность применять одну команду к нескольким объектам, поэтому вам нужно либо прибегать к низкоуровневому API, либо получить список отдельных ссылок на файлы и перемещать их по одному

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

В rb-appscript вы будете использовать тот же подход, что и AppleScript:

require 'appscript'; include Appscript

app("Finder").desktop.files.move(:to => app.home.folders["Documents"])

...

SB обманывает механизм событий Apple намного сильнее, чем AppleScript. AppleScript может быть болью, чтобы окунуться в голову, что связано с странным синтаксисом, тенденцией к конфликтам с ключевым словом и т.п., Но помимо этого он в значительной степени представляет события Apple как есть. Единственная действительно значительная часть магии в AS - это ее "неявное поведение", когда она оценивает литеральную ссылку, которая не отображается как параметр для команды. Самый большой грех AppleScript заключается в том, что его документация не лучше объясняет, как это работает, но есть очень хорошая статья Уильяма Кука, которая проливает много света о том, что происходит на самом деле.

SB, с другой стороны, делает все возможное, чтобы притвориться, что это настоящий Cocoa API с Cocoa -стильным поведением, поэтому слои на большом количестве магии. Результатом является то, что поверхностно привлекает разработчиков Cocoa, но как только те абстракции начинают течь - как абстракции неизменно делают - вы полностью в море с точки зрения понимания того, что происходит. Например, SBElementArray утверждает, что он является массивом - он даже подклассы NSMutableArray, но когда вы на самом деле пытаетесь использовать методы массива, половина из них работает, а половина из них - нет. На самом деле это не настоящий массив; это обертка вокруг неоцененного спецификатора объекта событий Apple, подделанного, чтобы сделать вид NSMutableArray. Поэтому, когда он делает что-то не-массивное, вы в значительной степени набиты для понимания, почему. И, как упоминалось в №1, некоторые из этих толстых абстракций затрудняют доступ к стандартной функциональности событий Apple под ней.

Сначала SB пытается быть хорошим API Cocoa, а не хорошим API событий Apple, и в итоге получается не очень хорошо.

Приложения, кстати, следует примеру AppleScript и придерживаются противоположного подхода: правильно делайте события Apple, а затем беспокоитесь о размещении основного языка. Вот почему некоторые люди предпочитают RubyOSA над rb-appscript; в то время как appscript является более способным решением, если вы исходите из сильно объектно-ориентированного фона, это будет очень странно. Это потому, что события Apple используют парадигму, основанную на RPC-плюс-запросе, и любое приложение-напоминание может иметь ООП чисто синтаксическое. Ближайшая аналогия заключалась бы в отправке XQueries по XML-RPC, и к этому нужно привыкнуть.

...

SB имеет тенденцию страдать значительно больше проблем совместимости приложений, чем AppleScript.

Некоторые из этих проблем связаны с тем, что SB навязывает свои идеи о том, как Apple IPC должна работать над тем, как она работает. Например, SB создает набор [pseudo] прокси-классов, представляющих классы, определенные в словаре; он затем накладывает различные ограничения на то, как вы можете взаимодействовать с этими объектами, основанными в основном на классических объектно-ориентированных поведенческих правилах.

Например, следующий script получает имена всех подпапок в папке "Документы":

tell application "Finder"
   get name of every folder of entire contents of folder "Documents" of home
end tell

Если вы попытаетесь использовать тот же подход в SB:

finder.home.folders.objectWithName('Documents').entireContents.folders.arrayByApplyingSelector(:name)

он добирается до метода #folders, затем выдает ошибку, потому что тип свойства "всего содержимого" в словаре Finder объявлен как "ссылка". Поскольку в словаре нет класса 'reference' с элементами 'folder', SB не позволяет вам сконструировать этот конкретный запрос (если вы не захотите перейти к низкоуровневым API-интерфейсам и использовать исходные коды AE). Это совершенно законно в соответствии с правилами событий Apple, но не вписывается в более узкий набор правил, основанный на OO, наложенный SB.

Другие ошибки связаны с тем, что SB делает предположения о том, как скриптовые приложения будут реализовывать определенные команды и другие функции. Например:

tell application "iTunes"
   make new playlist with properties {name:"test 1"}
end tell

SB не позволяет вам использовать любые ярлыки, предоставленные iTunes, хотя (вы можете опустить ссылку на исходный объект, в который вы хотите создать список воспроизведения, и в этом случае используется основной источник "Библиотека" ), поэтому пусть напишите это полностью для лучшего сравнения:

tell application "iTunes"
   make new playlist at source "Library" with properties {name:"test"}
end tell

В SB вы должны написать это как:

itunes = SBApplication.applicationWithBundleIdentifier('com.apple.itunes')

playlists = itunes.sources.objectAtIndex(0).playlists()
newplaylist = itunes.classForScriptingClass(:playlist).alloc().initWithProperties({:name => 'test'})
playlists.addObject(newplaylist)

Когда вы запустите его, он закроется на #addObject. В своей попытке превратить одну команду "make" в многострочное упражнение, SB предполагает, что параметр "at" всегда будет ссылкой на "конец < элементов" объекта <object> , который является тем, как Cocoa Приложения на основе сценариев делают это. У углеродных приложений нет единой стандартной структуры для поддержки поддержки событий Apple, поэтому они, как правило, немного отличаются от своих требований. Например, iTunes ожидает ссылку на объект-контейнер, в данном случае "исходную" библиотеку ", и не нравится, когда SB проходит" конец списков воспроизведения исходной "Библиотеки" ". Это то, как много приложений AppleScriptable, но SB игнорирует эту реальность в своей решимости быть" объектно-ориентированной".

Однако больше проблем возникает, когда словарь приложения не является точным или исчерпывающим на 100%. Ни форматы aete, ни sdef не позволяют описать, как интерфейс сценариев приложений работает со 100% -ными подробностями; некоторые вещи просто должны быть угаданы пользователями или описаны в дополнительной документации - характер свойства "всего содержимого" Finder является одним из примеров. Другая информация, например, какие классы объектов могут быть элементами, из которых принадлежат другие классы объектов, и каков тип каждого свойства, никогда не используется самим AppleScript - он существует только в качестве пользовательской документации. Поскольку AppleScript не полагается на эту информацию, любые ошибки будут упущены при тестировании поддержки сценариев приложений против AppleScript, поскольку скрипты работают нормально, несмотря на это. SB использует эту информацию, поэтому любые опечатки приведут к отсутствию или нарушению функций, которые необходимо обойти, снова опустившись до низкоуровневых API.

Appcript, BTW, не является 100% -ным AppleScript-совместимым, но это намного сложнее. Ранние версии appscript также пытались навязать различные правила OO для событий Apple, например, принудительное использование объектно-ориентированной модели, основанной на словарях, но через год, когда я столкнулся с несовместимостью приложений, я собрал весь этот "умный" код и провел следующие несколько лет, пытаясь black-box обратный инженер AppleScript внутренних махинаций и сделать appscript подражать им как можно ближе. "Если вы не можете победить их (что вы не можете), присоединитесь к ним, другими словами. И там, где appscript действительно сталкивается с проблемой совместимости, обычно есть способы обойти его, включая переключение внутренних параметров совместимости, экспорт терминологии приложения в модуль, исправление его вручную и использование этого вместо этого или переход к его низкоуровневому необработанному AE-коду API-интерфейсы.

...

FWIW, я должен также подключить несколько связанных приложений.

Во-первых, инструменты ASDictionary и ASTranslate на сайте appscript являются вашими друзьями. ASDictionary будет экспортировать словари приложений в формате HTML в стиле appscript, а также включить встроенный метод #help в rb-appscript; отлично подходит для интерактивного развития в irb. ASTranslate возьмет команду AppleScript и (с ошибками) вернет эквивалентную команду в синтаксисе appscript.

Во-вторых, исходное распределение rb-appscript содержит как документацию, так и образцы сценариев. Если вы установите дескриптор дескрипторов, не забудьте также захватить дистрибутив zip для этих ресурсов.

В-третьих, Мэтт Нойбург написал книгу о rb-appscript. Пойдите, прочитайте это, если Вы думаете об использовании rb-appscript. И идите читать книгу доктора Кука, независимо от того, что вы в конечном итоге решите.

...

В любом случае, надеюсь, что это поможет. (О, и извинения за длину, но на этой неделе я написал около 25000 слов, так что это всего лишь легкая релаксация.)

p.s. Нед, ваш блестящий доллар стоит на этом посту.;)

Ответ 2

Я не пробовал RubyOSA, но у меня был большой успех с rb-appscript. Он отлично работал у меня и намного приятнее, чем работать с AppleScript напрямую.

Вы видели этот поток, сравнивающий два? У этого есть хороший подробный ответ, отмечающий различия.

Ответ 3

Apple включает поддержку сценариев для Cocoa -совместимых языков через фреймворк под названием "Scripting Bridge". Я использую это через RubyCocoa/MacRuby для выполнения моих сценариев. Он включен прямо в коробку, поэтому он довольно удобен.

require 'osx/cocoa'
require_framework 'ScriptingBridge'
iTunes = SBApplication.applicationWithBundleIdentifier 'com.apple.iTunes'
puts iTunes.selection.name

Единственное серьезное раздражение, которое я обнаружил для Scripting Bridge, заключается в том, что вам нужно использовать идентификаторы пакетов, подобные этим, а не имена, но для меня это вообще не проблема. Он также включен только в 10.5, поэтому, если вам нужна поддержка Panther или Tiger, вам понадобится один из других.

Из двух других, rb-appscript все еще активно развивается, в то время как RubyOSA была фактически заморожена пару лет назад, поэтому я, вероятно, поеду с первым. Поскольку Ruby 2, MacRuby и другие новые реализации приводят к изменениям в языке, rb-appscript с большей вероятностью будет работать в будущем. В противном случае они очень похожи. Я по существу рассматриваю rb-appscript как новую версию RubyOSA, хотя это не технически верно.

Ответ 4

Короткий ответ: rb-appscript.

Потому что скриптовый мост, кажется, беспорядок, и RubyOSA было прекращено.