Como fecho uma janela de um aplicativo, passando o nome do arquivo?

9

Estou tentando produzir um comando shell baseado em Applescript que informa ao aplicativo Preview do Mac OS X para fechar uma janela específica.

#!/bin/sh

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

Mas isso não funciona: recebo a mensagem de erro

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

Pergunta relacionada: Como fecho um aplicativo OS X na linha de comando usando um alias definido em meu .bash_profile?

Ewan Delanoy
fonte
Isso deve funcionar conforme o esperado. Como você está chamando seu script, exatamente? Nota: Seu script não fechará uma janela específica. Ele encerrará o aplicativo, fechando todas as janelas de documentos que o aplicativo possa ter aberto. Para fechar um documento específico, o aplicativo foi aberto, mas não o encerrou em si, você precisa de um script diferente. Enquanto a maioria dos aplicativos é encerrada quando a última janela do documento é fechada, nem todos são executados - isso também depende da versão do OS X que você está usando.
slhck
@ sllck: "fechar um documento específico que o aplicativo abriu, mas não sair do aplicativo em si", é exatamente o que eu preciso. Você conhece algum lugar onde um "script diferente" é explicado?
Ewan Delanoy

Respostas:

10

Obtendo o Preview.app para aceitar comandos AppleScript

Por padrão, o AppleScripting Preview não funciona porque o Preview não possui o dicionário necessário. Para corrigir isso, verifique a resposta de Lauri aqui , que explica a configuração NSAppleScriptEnableddo Preview.app.

Saia do Preview.app, abra um terminal e digite:

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


Fechando uma janela de um aplicativo

1) Por índice da janela ou nome da janela

O comando para fechar uma janela de qualquer aplicativo nomeado seria algo como isto:

tell application "Preview" to close window 1

… Ou se você deseja fechar uma janela de documento nomeada, por exemplo foo.jpg:

diga ao aplicativo "Preview" para fechar (todas as janelas cujo nome é " foo.jpg ")

Então, no seu script shell, seria:

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

Aqui, o primeiro argumento passado para o script é o nome da janela que você deseja fechar, por exemplo ./quit.sh foo.jpg. Observe que se o seu arquivo contiver espaços, você deverá citar o nome do arquivo, por exemplo ./quit.sh "foo bar.jpg".

Ou se você deseja fechar janelas arbitrárias de qualquer aplicativo, use o seguinte:

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

Aqui, você usaria ./quit.sh Preview foo.jpgpor exemplo.

2) Pelo nome do arquivo

Se você deseja fechar uma janela que pertence a um determinado documento, mas fornecendo o nome do arquivo, você precisa de outra coisa. Isso ocorre porque um PDF de várias páginas pode ser exibido como foo.pdf (Page 1 of 42), mas você deseja apenas passar foo.pdfpara o AppleScript.

Aqui, iteramos pelas janelas e comparamos os nomes de arquivos com o argumento passado para o script:

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

Agora você pode simplesmente ligar ./quit.sh foo.pdf. De maneira generalizada, para todos os aplicativos com janelas de documentos nomeadas, isso seria:

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


Advertência: Preview.app de fechamento automático

O Preview.app é um desses aplicativos que fecha automaticamente quando a última janela do documento é fechada. Faz isso para economizar memória e "limpar". Para desativar esse comportamento, execute o seguinte:

defaults write -g NSDisableAutomaticTermination -bool TRUE

Obviamente, para desfazer isso, mude TRUEpara FALSE.


Usando funções em vez de scripts

Por fim, sugiro colocar seus scripts em uma função que esteja sempre disponível em seu shell. Para fazer isso, adicione os scripts ao seu ~/.bash_profile. Crie este arquivo se ele não existir.

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
}

Depois de salvar seu perfil do bash e reiniciar o shell, você pode ligar cw Preview foo.pdfde qualquer lugar.

slhck
fonte
Eu tentei isso. Desta vez, não recebo mensagem de erro, mas o script ainda não funciona: a janela permanece visível na tela.
Ewan Delanoy
Funcionou para mim. Se você abrir um documento no Preview.app, abra o AppleScript Editor e digite tell application "Preview" to windows: isso dá algum resultado? Qual script exato você está executando?
slhck
Não uso o editor AppleScript, apenas "código de script de maçã incorporado" em um script bash, conforme explicado no OP, armazenado em um arquivo .sh.
Ewan Delanoy
Na verdade, eu geralmente estou muito feliz com scripts de shell e este é o meu primeiro AppleScript. Acabei de fazer o que você recomendou em seu último comentário e recebi: "{window id 113 do aplicativo" Preview "}" como resposta. É isso que eu deveria conseguir?
Ewan Delanoy 01/01
Além disso, quando eu compilar << diga ao aplicativo "Preview" para fechar "musixdoc.pdf" >> com o editor de maçãscript, ele também não funcionará: a janela musixdoc.pdf permanece visível na tela.
Ewan Delanoy
0

A resposta do slhck parece boa e completa. Cuidado, executando a terceira linha de código :

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

'parece' ter causado o travamento da visualização a cada lançamento, com o seguinte:

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

De acordo com o manual de codesign, isso -festá forçando 'sinal de código para substituir e assinatura existente' e -s'sinalizando o código no caminho especificado' ... neste caso-

Aparentemente, a visualização agora está incorretamente assinada e inutilizável. :(

David C
fonte