11 votos

¿Cómo obtener el texto seleccionado en un AppleScript, sin copiar el texto en el portapapeles?

Yo he investigado métodos sobre cómo obtener la selección de una variable de texto en un AppleScript. Pero estos métodos se basan en copiar la selección al portapapeles (por ejemplo, por keystroking el comando copiar en la parte superior de la secuencia de comandos) con el fin de introducir este texto a la AppleScript (mediante el uso de the clipboard).

Esto es menos que ideal, por supuesto, debido a que el texto del portapapeles se sobrescribe.

Hay otra forma de obtener el texto seleccionado, de todo el sistema, en AppleScript, sin perturbar el portapapeles?

Obviamente, uno puede fácilmente obtener el texto seleccionado sin tocar el portapapeles en Automator. Sin embargo, en este caso, no quiero usar Automator, necesito un puro AppleScript solución.

9voto

rubik's sphere Puntos 31

Aquí está un reciente post en el blog que se centra en esta misión:

Michael Tsai - Blog - Procesamiento de Texto Seleccionado a través de la secuencia de Comandos

Una forma de obtener el texto seleccionado en un AppleScript, sin sobrescribir el contenido del portapapeles, es simplemente para ahorrar the clipboard contenido a una nueva variable antes de que el texto seleccionado se copia. Luego, al final de la secuencia de comandos, coloque el original en el contenido del portapapeles de nuevo en the clipboard.

He aquí lo que esto podría ser así:

-- 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

Pero, este método es imperfecta, como Michael notas:

Esta es feo y tiene algunas desventajas: hay demoras causadas por la GUI de secuencias de comandos, y ciertos tipos de datos del portapapeles no se conservan.


Sin embargo, Shane Stanley dejado un comentario en el blog con un método para conservar el formato original de los contenidos del portapapeles.

Si se utiliza el ejemplo anterior, reemplace la primera línea con:

set savedClipboard to my fetchStorableClipboard()

Reemplazar la última línea con:

my putOnClipboard:savedClipboard

Y agregue el código siguiente al final:

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:

He probado esta solución proporcionada por Shane, y lo hace de hecho retener todo el formato original de los contenidos del portapapeles si han enriquecido el texto en el portapapeles.


Shane luego a la izquierda un segundo comentario, esta vez con la intención de minimizar el tiempo de ejecución de la secuencia de comandos.

Reemplace este código:

-- 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.

con este código:

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() = theCount then exit repeat
    delay 0.1
end repeat

He probado este nuevo código y me encontré que el guión era de hecho mucho más rápido, sólo por un pelo.

Actualización: no sé lo que pasó, pero me fui a probar este código un día más tarde, y no pude hacer que funcione correctamente, en todos. He pasado varias horas tratando de determinar el problema de la lectura acerca de NSPasteboard. Pero yo no puedo ir a Shane en la segunda solución para que funcione de nuevo.


En general, esto no es una mala solución. El contenido del portapapeles se conservan , y el retraso es mucho menos apreciable utilizando el código proporcionado en Shane segundo comentario.

He probado la solución (excepto el código proporcionado en Shane segundo comentario) en contra de un Servicio creado en Automator.la aplicación que recibe el texto seleccionado como entrada. El Servicio tomó aproximadamente un segundo para completar. La pura AppleScript solución se requiere de dos segundos.


Si uno quiere un método para obtener y reemplazar el texto seleccionado sin tener que tocar el portapapeles, Michael sugiere en su blog que uno puede utilizar una pieza de software de terceros con derecho barra de inicio. Sin embargo, este es "trampa", porque, en ese momento, nos hemos movido más allá del alcance de mi pregunta original, que es estrictamente de que se trate acerca de AppleScript.

AppleAyuda.com

AppleAyuda es una comunidad de usuarios de los productos de Apple en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X