Как закрыть окно из приложения, передав имя файла?

9

Я пытаюсь создать команду оболочки на основе Applescript, которая сообщает приложению Preview из Mac OS X закрыть определенное окно.

#!/bin/sh

osascript <<EOF
tell application "Preview"
   close "$1"
end tell
EOF

Но это не работает: я получаю сообщение об ошибке

25:52: execution error: Preview got an error: "musixdoc.pdf" doesn’t understand the close message. (-1708)

Смежный вопрос: Как закрыть приложение OS X из командной строки, используя псевдоним, определенный в моем .bash_profile?

Эван Деланой
источник
Это должно работать как ожидалось. Как вы называете свой сценарий, точно? Примечание. Ваш скрипт не закроет конкретное окно. Это закроет приложение, таким образом закрывая все окна документа, которые приложение могло открыть. Чтобы закрыть конкретный документ, приложение открылось, но не вышло из приложения само по себе, вам нужен другой скрипт. Хотя большинство приложений завершают работу, когда закрывается их последнее окно документа, это делают не все - это также зависит от используемой версии OS X.
Slhck
@slhck: «закрыть конкретный документ, который приложение открыло, но не выходить из приложения как такового» - это как раз то, что мне нужно. Вы случайно не знаете, где объясняется такой «другой сценарий»?
Эван Деланой

Ответы:

10

Получение Preview.app для принятия команд AppleScript

По умолчанию предварительный просмотр AppleScripting не работает, поскольку в предварительном просмотре отсутствует необходимый словарь. Чтобы это исправить, проверьте ответ Лаури здесь , который объясняет настройку NSAppleScriptEnabledPreview.app.

Выйдите из Preview.app, затем откройте терминал и введите:

sudo defaults write /Applications/Preview.app/Contents/Info NSAppleScriptEnabled -bool true
sudo chmod 644 /Applications/Preview.app/Contents/Info.plist
sudo codesign -f -s - /Applications/Preview.app


Закрытие окна из приложения

1) По индексу окна или названию окна

Команда для закрытия окна любого именованного приложения будет выглядеть примерно так:

tell application "Preview" to close window 1

... или если вы хотите закрыть именованное окно документа, например foo.jpg:

сказать приложению «Preview» о закрытии (каждое окно с именем « foo.jpg »)

Итак, в вашем сценарии оболочки это будет:

#!/bin/sh
osascript <<EOF
tell application "Preview"
  close (every window whose name is "$1")
end tell
EOF

Здесь первый аргумент, передаваемый скрипту, - это имя окна, которое вы хотите закрыть, например ./quit.sh foo.jpg. Обратите внимание, что если ваш файл содержит пробелы, вы должны указать имя файла, например ./quit.sh "foo bar.jpg".

Или, если вы хотите закрыть произвольные окна из любого приложения, используйте это:

#!/bin/sh
osascript <<EOF
tell application "$1"
  close (every window whose name is "$2")
end tell
EOF

Вот, вы бы использовали, ./quit.sh Preview foo.jpgнапример.

2) По имени файла

Если вы хотите закрыть окно, принадлежащее определенному документу, но указав имя файла, вам нужно что-то еще. Это связано с тем, что многостраничный PDF-файл может отображаться как foo.pdf (Page 1 of 42), но вы просто хотите перейти foo.pdfк AppleScript.

Здесь мы перебираем окна и сравниваем имена файлов с аргументом, переданным скрипту:

osascript <<EOF
tell application "Preview"
    set windowCount to number of windows
    repeat with x from 1 to windowCount
        set docName to (name of document of window x)
        if (docName is equal to "$1") then
            close window x
        end if
    end repeat
end tell
EOF

Теперь вы можете просто позвонить ./quit.sh foo.pdf. В общем случае для всех приложений с именованными окнами документов это будет:

osascript <<EOF
tell application "$1"
    set windowCount to number of windows
    repeat with x from 1 to windowCount
        set docName to (name of document of window x)
        if (docName is equal to "$2") then
            close window x
        end if
    end repeat
end tell
EOF


Предостережение: автоматическое закрытие Preview.app

Preview.app - одно из этих приложений, которое автоматически закрывается после закрытия последнего окна документа. Это делается для того, чтобы сохранить память и «очистить». Чтобы отключить это поведение, выполните следующее:

defaults write -g NSDisableAutomaticTermination -bool TRUE

Конечно, чтобы отменить это, измените TRUEна FALSE.


Использование функций вместо скриптов

Наконец, я бы предложил поместить ваши скрипты в функцию, которая всегда доступна в вашей оболочке. Для этого добавьте скрипты к себе ~/.bash_profile. Создайте этот файл, если он не существует.

cw() {
osascript <<EOF
tell application "$1"
    set windowCount to number of windows
    repeat with x from 1 to windowCount
        set docName to (name of document of window x)
        if (docName is equal to "$2") then
            close window x
        end if
    end repeat
end tell
EOF
}

После сохранения профиля bash и перезапуска оболочки вы можете звонить cw Preview foo.pdfоткуда угодно .

slhck
источник
Я попробовал это. На этот раз я не получаю сообщения об ошибке, но скрипт все равно не работает: окно остается видимым на экране.
Эван Деланой
Это сработало для меня. Если вы откроете документ в Preview.app, откроете AppleScript Editor и введете tell application "Preview" to windows, это даст вам какие-либо результаты? Какой точный сценарий вы используете?
slhck
Я не использую редактор AppleScript, я только использую «встроенный код appleScript» в скрипте bash, как описано в OP, хранящемся в файле .sh.
Эван Деланой
На самом деле, я обычно доволен сценариями оболочки, и это мой первый яблочный скрипт. Я просто сделал то, что вы посоветовали в своем последнем комментарии, и получил: "{идентификатор окна 113 приложения" Предварительный просмотр "}" в качестве ответа. Это то, что я должен получить?
Эван Деланой
Кроме того, когда я компилирую << сказать приложению «Предварительный просмотр», чтобы он закрывал «musixdoc.pdf» >> с помощью редактора applecript, он также не работает: окно musixdoc.pdf остается видимым на экране.
Эван Деланой
0

Ответ от slhck выглядит хорошо и тщательно. Осторожно, выполняя третью строку кода :

sudo codesign -f -s - /Applications/Preview.app

«Кажется» вызывало аварийное завершение Preview при каждом запуске:

Application Specific Information:
XPC domain creation failed: The code signature is not valid: The operation couldn’t be completed. (OSStatus error -67061.)

Согласно руководству по -fкодовому обозначению , это означает, что «кодовый знак заменяет существующую подпись», и это -sозначает «подписать код по указанному пути»… в этом случае-

По всей видимости, Preview теперь неправильно подписан и непригоден для использования. :(

Дэвид С
источник