AppleScript: как проверить, состоит ли буфер обмена из файла (а не из текста)?

Если я правильно понимаю, есть два типа контента, которые можно скопировать в глобальный (общесистемный) буфер обмена Mac:

  • text

или

  • file

Несмотря на то, что это два разных дискретных типа данных, они используют один и тот же буфер обмена. Например, если у вас есть изображение fileв буфере обмена, а затем вы копируете textпредложение, предложение перезапишет файл изображения, и наоборот. Пожалуйста, поправьте меня, если я ошибаюсь.

Мой вопрос: как я могу определить, не содержит ли буфер обмена файлы text, используя AppleScript?

Контекст моего вопроса — это файл AppleScript .scpt, в котором выделенный текст озвучивается системным голосом с заданной громкостью. Выделенный текст копируется в буфер обмена, а затем текст проговаривается с помощью sayкоманды. Скрипт запускается нажатием клавиши через FastScripts.app.

Время от времени мне выдается диалоговое окно об ошибке, в котором говорится: «Номер ошибки: -1728». Эта ошибка возникает, когда вместо того, чтобы textбыть выделенным, я выделил или выбрал фактический файл file. Функция «Речь» Mac не может произносить file; Речь может только вербализовать text.

Итак, я хотел бы создать if...thenоператор в своем сценарии, чтобы поймать эту ошибку. В идеале я хотел бы преобразовать в file, textесли это возможно, так, как это делает TextEdit.

Ваше первое предположение неверно: текст или файл (вероятно, вы действительно имеете в виду xor ). Это намного сложнее. Вы можете проверить содержимое буфера обмена с помощью приложения Apple (Xcode) «Clipboard Viewer». Он доступен во вспомогательных инструментах для Xcode 7.
Можно также легко создать службу Automator (назначенную сочетанию клавиш через панель настроек системы «Клавиатура»), которая получает выделенный текст в любом приложении, а затем выполняет действия «Установить громкость компьютера» и « Произнести текст» без необходимости копировать выделенный текст в буфер обмена. (Конечно, у вас могут быть веские причины использовать AppleScript вместо этого!)
@BigMac 1. Мой код AppleScript позволяет мне останавливать речь тем же нажатием клавиши, которое я использую для запуска речи. 2. Мой код фактически не влияет на громкость системы; он определяет громкость процесса «Речь» в процентах от текущего уровня громкости системы. 3. Запуск общесистемной службы с помощью сочетания клавиш ненадежен. См.: Сочетание клавиш для службы работает только после запуска службы вручную . FastScripts.app, OTOH, надежен. Но FastScripts, конечно, может запускать только файлы .scpt, а не файлы Automator Service.
@rubik'ssphere Спасибо за объяснение; Я не знаю, как сделать №1 в Automator, так что этого достаточно, чтобы использовать AppleScript! # 3 также исключил бы службу Automator, но, к счастью, я не сталкивался с этой проблемой (пока). # 2, вероятно, можно было бы выполнить в действии «Выполнить AppleScript» в Automator (вместо использования действий, которые я упомянул). Я хотел бы увидеть ваш окончательный сценарий, если вы готовы им поделиться, так как я тоже часто использую преобразование текста в речь Apple.
@BigMac (1/2) В основе моего кода лежит гениальное решение, предоставленное jackjr300 здесь: AppleScript: можно ли проверить, работает ли в данный момент Speech? . Чтобы установить громкость речи в процентах от текущей громкости системы (я выбрал 35%), см.: Как изменить громкость «говорить» в AppleScript? . Я обнаружил ошибку командной строки, поэтому см. обходной путь:
(2/2) Как обойти ошибку команды «говорить» при настройке громкости? Наконец, ответ @user3439894 на этот самый пост заставляет скрипт произносить имя выбранного файла : AppleScript: Как проверить, состоит ли буфер обмена из файла (а не из текста)? Соберите все это вместе, и вы создадите мой текущий файл AppleScript.

Ответы (1)

Если буфер обмена содержит файловый объект , то он clipboard infoбудет содержать, например, «class furl»(URL-адрес файла) вместе со многими другими классами.

Следующий пример кода проверит наличие «class furl»в clipboard info:

if ((clipboard info) as string) contains "«class furl»" then
    say "the clipboard contains a file named " & (the clipboard as string)
else
    say "the clipboard does not contain a file"
end if

Обновлять:

Как я упоминал в одном из своих комментариев, есть и другие способы закодировать это, и этот подход вернет либо пустой список , либо список, содержащий один список , что должно быть быстрее вместо 14, которые возвращает первый пример, если он содержит файл . Если в буфере обмена нет файла , то возвращаемый список будет пустым и выдаст ошибку, установив cbFileзначение false, а если оно не пусто, установив его в значение true, которое затем проверяется в следующем примере.

try
    (item 1 of (clipboard info for «class furl»))
    set cbFile to true
on error
    set cbFile to false
end try
if cbFile then
    say "the clipboard contains a file named " & (the clipboard as string)
else
    say "the clipboard does not contain a file"
end if

Между прочим, я запустил purge команду в Терминале между тестированием этих двух примеров, и мне показалось, что второй пример немного быстрее, однако YMMV.

Вы также знаете, как получить только имя файла (а не полный путь) в виде текста файла, который находится в буфере обмена? Если условие if выполнено: if ((clipboard info) as string) contains "«class furl»"то я хотел бы, чтобы мой скрипт использовал sayимя файла буфера обмена.
Дайте мне знать, если вы считаете, что вопрос в моем комментарии выше заслуживает отдельного поста.
Сфера @rubik, я обновил ответ, чтобы учесть условие, указанное в вашем комментарии. Кстати, если вам нужен полный путь, вам нужно использовать Cocoa-AppleScript и NSPasteboard, которые я не использую как обычный AppleScript.
Лучше всего подойдет другой узкий вопрос, @rubik'ssphere. Связывание двух здесь в комментариях было бы неплохо. Я отредактирую вопрос, который вы разместили здесь, чтобы прояснить тему здесь.
Проголосовавшему против, пожалуйста, объясните законную причину этого, разве это не отвечает на заданный вопрос? У вас есть лучший ответ вместо необоснованного отрицательного голоса !?
@user3439894 user3439894 Ваше решение прекрасно работает. Но я заметил, что есть небольшая задержка перед тем, как сценарий говорит: «Буфер обмена содержит файл с именем файла». Могу ли я что-нибудь сделать, чтобы сократить или устранить эту задержку?
Сфера @rubik, Какова задержка?... Когда я запускаю этот пример кода в редакторе сценариев, как есть, я действительно не замечаю задержки. Вы заметили задержку с этим примером кода в редакторе сценариев, как есть, или вы взяли этот пример и переработали его, чтобы он соответствовал вашим потребностям в более крупном сценарии, и вы заметили задержку? Если первое, то существует более одного способа написать этот код, и я тестировал разные кодировки, но действительно не заметил задержки в своей системе. Если последнее, то, не видя кода для тестирования, я действительно ничего не могу сказать ( каламбур с кодом ).
@user3439894 user3439894 Когда я запускаю ваш код в Script Editor.app, дословно, есть 1-секундная задержка перед произнесением «Буфер обмена содержит файл с именем ...» , но сразу же произносится «Буфер обмена не содержит файл» . Это верно независимо от типа или расположения файла в буфере обмена. Вы не испытываете задержки в своей системе? Это явно не большая задержка, но ее достаточно, чтобы я каждый раз замечал задержку. Могу ли я протестировать другие методы кодирования?
Сфера @rubik, Теперь, когда я знаю, что вы сравниваете разницу между двумя состояниями, этого и следовало ожидать, поскольку при оценке истинности происходит дополнительная обработка. Если false, возврат clipboard infoможет содержать всего 4 класса, а если true, может содержать гораздо больше, например 14 классов. Все они должны быть пронумерованы, и перечисление некоторых из них может занять больше времени, чем других, что еще больше увеличивает ожидаемую задержку. Так что это само по себе запускает задержку diff. Кроме того, если это правда, буфер обмена запрашивается для имени файла в виде строки, таким образом, добавляя больше к задержке diff. Имеет ли это смысл?
Сфера @rubik, я обновил ответ, добавив еще один пример, чтобы вы могли проверить, работает ли он быстрее.
@ user3439894 Да, это имеет смысл. Спасибо за подробное объяснение. Я до сих пор удивлен, что такая мощная и продвинутая машина не может выполнить эту относительно простую задачу мгновенно. Я предполагаю, что виноват какой-то неэффективный код со стороны Apple. Насколько я могу судить, ваш альтернативный метод не быстрее исходного метода. Новый метод по-прежнему имеет задержку в 1 секунду. Я не могу точно измерить время выполнения до миллисекунды. Спасибо за вашу помощь.
Сфера @rubik, FWIW Сохранение обеих версий кода как .scpt с модификацией ложной ветки, так сказать, будет говорить то же самое, что и истинная ветка, сделано это для лучшего сравнения и работает с в качестве аргумента , osascriptбыла timeразница между двумя версиями. Я закрывал / открывал терминал и использовал purgeкоманду между каждым запуском, и когда все было сказано, готовая версия 1 имела разницу 0,719 с между ветвью T / F, а версия 2 имела разницу 0,363 с между ветвью T / F по сравнению с 0,356. s diff между каждой версией. Хотя версия 2 была технически быстрее, разница незначительна.
@ user3439894 Интересный анализ. В этом случае я выберу альтернативный метод.