Wie bekomme ich den ausgewählten Text in ein AppleScript, ohne den Text in die Zwischenablage zu kopieren?

Ich habe Methoden recherchiert, wie man die Auswahl als Textvariable in einem AppleScript erhält. Aber diese Methoden verlassen sich darauf, die Auswahl in die Zwischenablage zu kopieren (zum Beispiel durch Tastendruck auf den Kopierbefehl am Anfang des Skripts), um diesen Text in das AppleScript einzuführen (durch Verwendung von the clipboard).

Das ist natürlich alles andere als ideal, da der eigentliche Text aus der Zwischenablage überschrieben wird.

Gibt es eine andere Möglichkeit, den ausgewählten Text systemweit in AppleScript abzurufen, ohne die Zwischenablage zu stören?

Offensichtlich kann man den ausgewählten Text leicht abrufen, ohne die Zwischenablage in Automator zu berühren. In diesem Fall möchte ich jedoch Automator nicht verwenden. Ich brauche eine reine AppleScript-Lösung.

Könnten Sie verdeutlichen, was Sie zu tun versuchen, indem Sie einige praktische Beispiele geben. Ist der ausgewählte Text bearbeitbar, ja, nein, beides?
@user3439894 Der ausgewählte Text muss unbedingt bearbeitet werden. Ich möchte, dass der Code den ausgewählten Text übernimmt, einige Operationen daran ausführt und dann den ausgewählten Text ersetzt. Ein Beispiel wäre die Umwandlung der Groß- und Kleinschreibung des ausgewählten Textes in die Groß- und Kleinschreibung des Titels. (Ich habe bereits den Code, der die Groß-/Kleinschreibung umwandelt, also brauche ich keine Hilfe dabei. Und das Drücken des neuen Textes ist einfach genug. Ich weiß nur nicht, wie ich die Auswahl außerhalb der Zwischenablage in AppleScript bekomme.)
Sorry, aber das klärt die Sache nicht wirklich auf. Hoffentlich versteht es jemand anderes und kann etwas Hilfe anbieten.
@user3439894 Kannst du erklären, was unklar ist? Angenommen, der ausgewählte Text lautet: "Dies ist ein Satz, der aus Wörtern besteht." Ich möchte, dass mein AppleScript den ausgewählten Text durch eine neue Zeichenfolge ersetzt: „Dies ist ein Satz, der aus Wörtern besteht.“ Der ausgewählte Text kann immer bearbeitet werden. Das AppleScript wird von FastScripts ausgelöst, daher kann ich die Funktion „Dienst empfängt ausgewählten Text“ von Automator nicht verwenden.
Ich habe noch nie FastScripts verwendet, also muss ich es mir morgen ansehen.
Das Problem ist, dass FastScripts keinen inputParameter hat, wie ihn Automator bietet.
Auch für alle, die ein Skript schreiben, das vom Browser kopiert: Eine einfachere, aber schmale Lösung für Sie ist die Ausführung von JavascriptgetSelection().toString()
Ich habe Applescripts geschrieben, die Automator verwenden, um alle von Ihnen erwähnten Konvertierungen durchzuführen, GROSSBUCHSTABEN, Kleinbuchstaben, ROT13, Titelbuchstaben, Satzbuchstaben, sogar 1337 5p34k. Sie funktionieren großartig, neugierig, warum Sie Automator nicht verwenden würden?
@GlenYates Das Problem mit Automator Services besteht darin, dass sie nicht zuverlässig per Tastenkombination ausgeführt werden können. Es existiert ein schwerwiegender Fehler (und existiert bereits seit vielen Jahren), an dessen Behebung Apple anscheinend kein Interesse hat. Eine Beschreibung des Fehlers finden Sie hier: Die Tastenkombination für den Dienst funktioniert nur, nachdem ich den Dienst manuell ausgeführt habe . Also verwende ich FastScripts, um AppleScripts per Tastaturkürzel auszulösen, aber FastScripts enthält keine native Funktion, um den ausgewählten Text als String-Variable zu importieren. Also muss ich auf die folgende Methode zurückgreifen.

Antworten (1)

Hier ist ein kürzlich erschienener Blogbeitrag, der sich auf genau diese Mission konzentriert:

Michael Tsai - Blog - Verarbeitung des ausgewählten Textes per Skript

Eine Möglichkeit, den aktuell ausgewählten Text in ein AppleScript zu übertragen, ohne den Inhalt der Zwischenablage zu überschreiben, besteht darin, den the clipboardInhalt einfach in einer neuen Variablen zu speichern, bevor der ausgewählte Text kopiert wird. Platzieren Sie dann am Ende des Skripts den ursprünglichen Inhalt der Zwischenablage wieder in the clipboard.

So könnte das aussehen:

-- Back up clipboard contents:
set savedClipboard to the clipboard

-- Copy selected text to clipboard:
tell application "System Events" to keystroke "c" using {command down}
delay 1 -- Without this, the clipboard may have stale data.

set theSelectedText to the clipboard

-- Makes the selected text all uppercase:
-- From: http://apple.stackexchange.com/a/171196/184907
set theModifiedSelectedText to (do shell script ("echo " & theSelectedText & " | tr a-z A-Z;"))

-- Overwrite the old selection with the desired text:
set the clipboard to theModifiedSelectedText
tell application "System Events" to keystroke "v" using {command down}
delay 0.1 -- Without this delay, may restore clipboard before pasting.

-- Instead of the above three lines, you could instead use:
--      tell application "System Events" to keystroke theModifiedSelectedText
-- But this way is a little slower.

-- Restore clipboard:
set the clipboard to savedClipboard

Aber diese Methode ist unvollkommen, wie Michael bemerkt:

Das ist hässlich und hat einige Nachteile: Es gibt Verzögerungen, die durch das GUI-Skripting erforderlich sind, und bestimmte Arten von Zwischenablagedaten werden nicht beibehalten.


Shane Stanley hinterließ jedoch einen Kommentar zu dem Blogbeitrag mit einer Methode, um die ursprüngliche Formatierung des Inhalts der Zwischenablage beizubehalten.

Wenn Sie das vorherige Beispiel verwenden, ersetzen Sie die erste Zeile durch:

set savedClipboard to my fetchStorableClipboard()

Ersetzen Sie die letzte Zeile durch:

my putOnClipboard:savedClipboard

Und fügen Sie am Ende den folgenden Code hinzu:

use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "AppKit"


on fetchStorableClipboard()
    set aMutableArray to current application's NSMutableArray's array() -- used to store contents
    -- get the pasteboard and then its pasteboard items
    set thePasteboard to current application's NSPasteboard's generalPasteboard()
    -- loop through pasteboard items
    repeat with anItem in thePasteboard's pasteboardItems()
        -- make a new pasteboard item to store existing item's stuff
        set newPBItem to current application's NSPasteboardItem's alloc()'s init()
        -- get the types of data stored on the pasteboard item
        set theTypes to anItem's types()
        -- for each type, get the corresponding data and store it all in the new pasteboard item
        repeat with aType in theTypes
            set theData to (anItem's dataForType:aType)'s mutableCopy()
            if theData is not missing value then
                (newPBItem's setData:theData forType:aType)
            end if
        end repeat
        -- add new pasteboard item to array
        (aMutableArray's addObject:newPBItem)
    end repeat
    return aMutableArray
end fetchStorableClipboard


on putOnClipboard:theArray
    -- get pasteboard
    set thePasteboard to current application's NSPasteboard's generalPasteboard()
    -- clear it, then write new contents
    thePasteboard's clearContents()
    thePasteboard's writeObjects:theArray
end putOnClipboard:

Ich habe diese von Shane bereitgestellte Lösung getestet, und sie behält tatsächlich die gesamte ursprüngliche Formatierung des Inhalts der Zwischenablage bei, wenn Sie Rich-Text in der Zwischenablage haben.


Shane hinterließ später einen zweiten Kommentar , diesmal mit der Absicht, die Laufzeit des Skripts zu minimieren.

Ersetzen Sie diesen Code:

-- Copy selected text to clipboard:
tell application "System Events" to keystroke "c" using {command down}
delay 1 -- Without this, the clipboard may have stale data.

mit diesem Code:

set thePasteboard to current application's NSPasteboard's generalPasteboard()
set theCount to thePasteboard's changeCount()
-- Copy selected text to clipboard:
tell application "System Events" to keystroke "c" using {command down}
-- Check for changed clipboard:
repeat 20 times
    if thePasteboard's changeCount() is not theCount then exit repeat
    delay 0.1
end repeat

Ich habe diesen neuen Code getestet und festgestellt, dass das Skript tatsächlich merklich schneller war, nur um ein Haar.


Insgesamt ist dies kein schlechter Workaround. Der Inhalt der Zwischenablage bleibt erhalten und die Verzögerung ist viel weniger bemerkbar, wenn Sie den in Shanes zweitem Kommentar bereitgestellten Code verwenden.

Ich habe die Lösung mit einem in Automator.app erstellten Dienst getestet, der den ausgewählten Text als input. Die Ausführung des Dienstes und der reinen AppleScript-Lösung dauerte ungefähr gleich lange (dh ungefähr eine Sekunde).


Wenn Sie eine Methode suchen, um den ausgewählten Text abzurufen und zu ersetzen, ohne die Zwischenablage berühren zu müssen, schlägt Michael in seinem Blogbeitrag vor, dass Sie eine Software eines Drittanbieters mit dem Namen LaunchBar verwenden können . Dies ist jedoch "Schummeln", weil wir an diesem Punkt über den Rahmen meiner ursprünglichen Frage hinausgegangen sind, die sich ausschließlich mit AppleScript befasst.

Ich implementiere eine ähnliche Funktion wie Instant Send von LaunchBar. Ich frage mich, wie sie das erreichen. Soweit es mich betrifft, benötigt Instant Send die Zugriffsberechtigung, um zu funktionieren, und es imitiert auch den Kopierbefehl. Denn wenn ich die Verknüpfung für den Kopierbefehl einer Anwendung ändere, funktioniert sie nicht mehr.