Jak zamknąć okno z aplikacji, przekazując nazwę pliku?

9

Próbuję utworzyć polecenie powłoki oparte na Applescript, które nakazuje aplikacji Preview z Mac OS X zamknięcie określonego okna.

#!/bin/sh

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

Ale to nie działa: pojawia się komunikat o błędzie

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

Powiązane pytanie: Jak zamknąć aplikację OS X z wiersza poleceń przy użyciu aliasu zdefiniowanego w moim pliku .bash_profile?

Ewan Delanoy
źródło
To powinno działać zgodnie z oczekiwaniami. Jak dokładnie nazywasz swój skrypt? Uwaga: Twój skrypt nie zamknie określonego okna. Opuści aplikację, zamykając w ten sposób wszystkie okna dokumentów, które aplikacja mogła otworzyć. Aby zamknąć konkretny dokument, który aplikacja otworzyła, ale nie jest w stanie sama zamknąć aplikacji, potrzebujesz innego skryptu. Chociaż większość aplikacji kończy pracę po zamknięciu ostatniego okna dokumentu, nie wszystkie - to zależy również od używanej wersji systemu OS X.
slhck
@slhck: „dokładnie zamknij konkretny dokument, który aplikacja otworzyła, ale nie zamknij samej aplikacji”. Czy zdarzyło Ci się wiedzieć, gdzie wyjaśniono taki „inny skrypt”?
Ewan Delanoy

Odpowiedzi:

10

Pobieranie Preview.app do akceptowania poleceń AppleScript

Domyślnie podgląd AppleScripting nie działa, ponieważ podglądowi brakuje niezbędnego słownika. Aby to naprawić, sprawdź odpowiedź Lauriego tutaj , która wyjaśnia ustawienie NSAppleScriptEnabledPreview.app.

Zamknij Preview.app, otwórz terminal i wprowadź:

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


Zamykanie okna z aplikacji

1) Według indeksu lub nazwy okna

Polecenie zamknięcia okna dowolnej nazwanej aplikacji wyglądałoby mniej więcej tak:

tell application "Preview" to close window 1

… Lub jeśli chcesz zamknąć okno nazwanego dokumentu, np . foo.jpg:

powiedz aplikacji „Preview”, aby zamknęła (każde okno o nazwie „ foo.jpg ”)

W skrypcie powłoki byłoby to:

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

Tutaj pierwszym argumentem przekazanym do skryptu jest nazwa okna, które chcesz zamknąć, np ./quit.sh foo.jpg. Pamiętaj, że jeśli plik zawiera spacje, musisz podać nazwę pliku, np ./quit.sh "foo bar.jpg".

Lub jeśli chcesz zamknąć dowolne okna z dowolnej aplikacji, użyj tego:

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

Tutaj użyłbyś ./quit.sh Preview foo.jpgna przykład.

2) Według nazwy pliku

Jeśli chcesz zamknąć okno należące do określonego dokumentu, ale podając nazwę pliku, potrzebujesz czegoś innego. Wynika to z faktu, że wielostronicowy plik PDF może być wyświetlany jako foo.pdf (Page 1 of 42), ale użytkownik chce po prostu przejść foo.pdfdo AppleScript.

Tutaj iterujemy przez okna i porównujemy nazwy plików z argumentem przekazanym do skryptu:

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

Teraz możesz po prostu zadzwonić ./quit.sh foo.pdf. W uogólniony sposób dla wszystkich aplikacji z nazwanymi oknami dokumentów będą to:

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


Zastrzeżenie: automatyczne zamykanie Preview.app

Preview.app to jedna z tych aplikacji, która automatycznie zamyka się po zamknięciu ostatniego okna dokumentu. Robi to w celu oszczędzania pamięci i „czyszczenia”. Aby wyłączyć to zachowanie, uruchom następujące polecenie:

defaults write -g NSDisableAutomaticTermination -bool TRUE

Oczywiście, aby to cofnąć, zmień TRUEna FALSE.


Używanie funkcji zamiast skryptów

Na koniec sugeruję włączenie skryptów w funkcję, która jest zawsze dostępna w twojej powłoce. Aby to zrobić, dodaj skrypty do swojego ~/.bash_profile. Utwórz ten plik, jeśli nie istnieje.

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
}

Po zapisaniu profilu bash i zrestartowaniu powłoki możesz dzwonić cw Preview foo.pdfz dowolnego miejsca.

slhck
źródło
Próbowałem tego. Tym razem nie otrzymuję komunikatu o błędzie, ale skrypt nadal nie działa: okno pozostaje widoczne na ekranie.
Ewan Delanoy
To zadziałało dla mnie. Jeśli otworzysz dokument w Preview.app, a następnie otworzysz AppleScript Editor i wejdziesz tell application "Preview" to windows, czy to daje jakieś wyniki? Jaki dokładnie skrypt uruchamiasz?
slhck
Nie używam edytora AppleScript, używam tylko „osadzonego kodu AppleScript” w skrypcie bash, jak wyjaśniono w OP, przechowywanym w pliku .sh.
Ewan Delanoy
W rzeczywistości zazwyczaj jestem całkiem zadowolony ze skryptów powłoki i jest to mój pierwszy skrypt Apple. Właśnie zrobiłem to, co poradziłeś w swoim ostatnim komentarzu, i otrzymałem: „{window id 113 aplikacji„ Preview ”}” jako odpowiedź. Czy to powinienem dostać?
Ewan Delanoy
Ponadto, gdy kompiluję << powiedz aplikacji „Preview”, aby zamknąć „musixdoc.pdf” >> z edytorem AppleScript, to również nie działa: okno musixdoc.pdf pozostaje widoczne na ekranie.
Ewan Delanoy
0

Odpowiedź slhck wygląda dobrze i dokładnie. Uwaga, wykonanie trzeciej linii kodu :

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

„wydaje się” powodować awarię Preview przy każdym uruchomieniu z następującymi przyczynami:

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

Zgodnie z instrukcją -fdo podpisywania znaków wymusza to „zastąpienie i zastąpienie istniejącego podpisu kodem” oraz -s„podpisanie kodu podaną ścieżką”… w tym przypadku-

Najwyraźniej Preview jest teraz nieprawidłowo podpisana i nie nadaje się do użytku. :(

David C.
źródło