7 votos

¿Cómo utilizar AppleScript para crear un nuevo archivo de formato de texto enriquecido a partir del texto del portapapeles?

Tengo un servicio de Automator que toma el texto actual en el portapapeles y lo escribe en un nuevo archivo .txt. Esto se ejecuta simplemente con la siguiente pieza de código AppleScript:

do shell script "pbpaste > /path/to/your/clipboard-file.txt"

Este código proviene de la siguiente respuesta de Stack Overflow:

AppleScript para pegar texto del portapapeles en un archivo

Sin embargo, este código convierte el contenido del portapapeles en texto plano, eliminando todo el formato del texto.

¿Es posible utilizar AppleScript para escribir el contenido del portapapeles en un archivo .rtf o .rtfd, conservando el formato original del contenido del portapapeles? Por formato original, me refiero a los datos estilísticos como el énfasis tipográfico (negrita, cursiva, subrayado), el tamaño de la fuente y el color del texto.

Por capricho, he probado el siguiente comando:

do shell script "pbpaste > /path/to/your/clipboard-file.rtf"

Pero este comando dio como resultado un archivo .rtf que mi ordenador no pudo leer ni abrir.

0 votos

He actualizado mi respuesta para que funcione tanto con contenido RTF como con HTML Clipboard.

0 votos

¿Le ha servido mi respuesta actualizada?

12voto

user3439894 Puntos 5883

Esta respuesta ha sido actualizada para reflejar esfera de rubik malentendido entre lo que es el texto enriquecido (lo que se preguntó originalmente) y lo que realmente se trabaja desde Google Chrome, siendo HTML. (Ver comentarios trasladados a chat .)

Dejo la respuesta original como está, y debajo este nuevo contenido, ya que técnicamente sí responde a la pregunta original tal y como se hizo. También contiene información relevante para el proceso general de tratar el contenido del Portapapeles en el contexto de la pregunta original y modificada.

El código a continuación se muestra un ejemplo código para ser probado y ejecutado dentro de (Apple) script Editor, ya que aparte de la primera frase en la pregunta, ningún uso explícito y específico dentro de Automator ha sido, todavía, dado. El código puede necesitar ser editado para trabajar dentro del uso desconocido en Automator. Dicho esto, tal y como está escrito, si todo el script a continuación fue colocado por sí mismo en una acción de Ejecutar AppleScript, por sí mismo, en Automator ... funciona como es. Si se utilizan sólo segmentos del código Algunos cambios en el actual código podría ser necesario hacer.

El código a continuación contiene suficientes comentarios para entender en general lo que el script está haciendo.


--        # 
--        # Change the 'New RichText Filename.rtf' name to the wanted filename for the target file.
--        # Make sure you leave the double-quotes even if the filename does not contain spaces!
--        # Note that '(path to desktop as text)' can also be modified as needed, e.g. changed to,
--        # '(path to documents folder as text)' or the entire segment after 'set theRichTextFileName to'
--        # can be a fully qualified POSIX pathname, e.g.: set theRichTextFileName to "/path/to/filename.rtf"
--        #  

set theRichTextFileName to POSIX path of (path to desktop as text) & "New RichText Filename.rtf"

--    #        THE REMAINING CODE SHOULD NOT NEED TO BE MODIFIED.
--    # 
--    #     Note: This code, as is, works as written and intended when run from within (Apple) Script Editor.
--    #     Some AppleScript code when wrapped in Automator may not work the same as in (Apple) Script Editor.
--    #     In cases where is does not work from a Run AppleScript action in Automator, editing will be required.
--    # 
--    #     This AppleScript code preforms the following actions, sans errors caught during File I/O operations.
--    # 
--    # 1. See it the target file exists and prompts to be overwritten if it does. If yes is selected, it continues.
--    # 
--    # 2. If the Clipboard contains RTF content, writes it to the target file using plain AppleScript.
--    # 
--    # 3. If the Clipboard contains HTML content, writes it to the target file as RTF using a 'do shell script' command.
--    # 
--    # 4. If the Clipboard does not contain any RTF/HTML content, notify the user. 
--
--        #    Notes: The 'do shell script' makes use of the following:
--        #
--        #    'osascript' to get the HTML content from the Clipboard.
--        #    The content is a Hex stream within a data wrapper and
--        #    'awk' will be used to remove/replace the data wrapper.
--        #
--        #    'awk' to remove the data wrapper from 'osascript' output
--        #    replacing it with proper HTML opening/closing Tags to
--        #    ensure it actually gets processed by 'textutil' after 'xxd'.
--        #    Without the HTML opening/closing Tags 'textutil' does not 
--        #    properly, within limits, convert the HTML Clipboard content to RTF.
--        #
--        #    'xxd' to convert the Hex data from 'osascript/awk' to ASCII text.
--        #
--        #    'textutil' to convert the ASCII text HTML from 'xxd' to RTF
--        #    formatted data and write it to the target file.

tell application "Finder"

    if exists theRichTextFileName as POSIX file then
        tell current application
            display dialog "The file \"" & theRichTextFileName & "\" already exists!" & "\n\n" & "Do you want to overwrite the file?" buttons {"No", "Yes"} default button 1 with title "File Already Exists..." with icon caution

            if the button returned of the result is "No" then
                return
            else
                tell application "Finder"
                    delete the file (theRichTextFileName as POSIX file)
                end tell
            end if
        end tell
    end if

    tell current application

        --    # Find out what class types are available for the Clipboard content
        --    # and use this information to determine which action will be taken.

        set cbInfo to get (clipboard info) as string

        if cbInfo contains "RTF" then

            try
                set richTextfromClipboard to get the clipboard as «class RTF »
            on error eStr number eNum
                display dialog eStr & " number " & eNum buttons {"OK"} default button 1 with icon caution
                return
            end try
            try
                set fileHandle to open for access theRichTextFileName with write permission
                write richTextfromClipboard to fileHandle
                close access fileHandle
            on error eStr number eNum
                display dialog eStr & " number " & eNum buttons {"OK"} default button 1 with title "File I/O Error..." with icon caution
                try
                    close access fileHandle
                end try
            end try

        else if cbInfo contains "HTML" then

            try
                do shell script "osascript -e 'try' -e 'get the clipboard as «class HTML»' -e 'end try' | awk '{sub(/«data HTML/, \"3C68746D6C3E\") sub(/»/, \"3C2F68746D6C3E\")} {print}' | xxd -r -p | textutil -convert rtf -stdin -stdout > " & quoted form of theRichTextFileName
            on error eStr number eNum
                display dialog eStr & " number " & eNum buttons {"OK"} default button 1 with icon caution
            end try

        else

            display dialog "The Clipboard does not contain\nany usable RTF/HTML content!" buttons {"OK"} default button 1 with title "No RTF/HTML Content on Clipboard..." with icon caution

        end if

    end tell

end tell

Respuesta original a la pregunta original formulada:

Para conseguir Texto enriquecido contenido de la Portapapeles en un archivo utilizando AppleScript Es un poco más complejo que un simple do shell script comando .

El ejemplo AppleScript código a continuación, si el objetivo archivo no existe ya y si Texto enriquecido contenido existe en el Portapapeles escribirlo en un archivo . Tendrá todos los atributos como el RichText contenido en el Portapapeles tiene, al igual que cuando se copió en el Portapapeles .

Abrir Script Editor y copiar y pegar el código abajo en un nuevo Sin título y luego ejecutarlo desde Script Editor , revisando el salida en Eventos/Respuestas . Ejecútalo un par de veces, con y sin Texto enriquecido contenido en el Portapapeles y con y sin la existencia del archivo en el disco duro, definido por set theRichTextFileName ... al inicio de la script .

Verás el código se asegura de que el archivo no existe, para no sobrescribir un archivo del nombre y la ubicación del objetivo y si el Portapapeles no contiene Texto enriquecido contenido También muestra un mensaje al respecto.

Ahora bien, si se utiliza esto en un Servicio de automatización Por ejemplo, donde El servicio recibe el texto enriquecido seleccionado entonces el código se puede modificar para que no atrape un error si Texto enriquecido contenido no está en el Portapapeles como el servicio no aparecerá en el Servicios menú si Texto enriquecido no está seleccionado en un documento. También si quiere sobrescribir el objetivo archivo en su ubicación designada el código alrededor que también se puede eliminar. Le daré a esos código ejemplos también.


Ejemplo código para pegar en Script Editor para su comprobación y revisión:

set theRichTextFileName to POSIX path of (path to documents folder as text) & "New RichText Filename.rtf"

tell application "Finder"
    if exists theRichTextFileName as POSIX file then
        tell current application
            display dialog "The file \"" & theRichTextFileName & "\" already exists!" buttons {"OK"} default button 1 with title "File Already Exists..." with icon caution
        end tell
    else
        tell current application
            try
                set richTextfromClipboard to get the clipboard as «class RTF »
            on error eStr number eNum
                display dialog eStr & " number " & eNum buttons {"OK"} default button 1 with title "No Rich Text Content on Clipboard..." with icon caution
                return
            end try
            try
                set fileHandle to open for access theRichTextFileName with write permission
                write richTextfromClipboard to fileHandle
                close access fileHandle
            on error eStr number eNum
                display dialog eStr & " number " & eNum buttons {"OK"} default button 1 with title "File I/O Error..." with icon caution
                try
                    close access fileHandle
                end try
                return
            end try
        end tell
    end if
end tell

Ejemplo código para usar en un Servicio de automatización Por ejemplo, donde El servicio recibe el texto enriquecido seleccionado :

set theRichTextFileName to POSIX path of (path to documents folder as text) & "New RichText Filename.rtf"

tell application "Finder"
    if exists theRichTextFileName as POSIX file then
        tell current application
            display dialog "The file \"" & theRichTextFileName & "\" already exists!" buttons {"OK"} default button 1 with title "File Already Exists..." with icon caution
        end tell
    else
        tell current application
            set richTextfromClipboard to get the clipboard as «class RTF »
            set fileHandle to open for access theRichTextFileName with write permission
            write richTextfromClipboard to fileHandle
            close access fileHandle
        end tell
    end if
end tell

Ejemplo código para usar en un Servicio de automatización Por ejemplo, donde El servicio recibe el texto enriquecido seleccionado y sobrescribe el objetivo existente archivo :

set theRichTextFileName to POSIX path of (path to documents folder as text) & "New RichText Filename.rtf"

tell current application
    set richTextfromClipboard to get the clipboard as «class RTF »
    set fileHandle to open for access theRichTextFileName with write permission
    write richTextfromClipboard to fileHandle
    close access fileHandle
end tell

La siguiente imagen es un ejemplo Servicio de automatización que crea el Nuevo archivo RichText.rtf archivo de una selección de Texto enriquecido de la Crear un archivo de texto enriquecido desde el portapapeles servicio en el Servicios Menú contextual (con el botón derecho del ratón) o Nombre_de_la_aplicación > Servicios > menú cuando Texto enriquecido se selecciona en un documento.

Automator Service - Create Rich Text file from Clipboard


Ahora bien, estos son sólo ejemplos y se puede codificar una lógica adicional para adaptarla a las necesidades de cada uno. A modo de ejemplo, código podría añadirse para incrementar automáticamente el nombre de un archivo existente para no sobrescribirlo, o pedir un nuevo nombre de archivo y completar la operación en lugar de abortar con un mensaje de que el archivo ya existe, etc.


Actualización para su uso con un do shell script comando :

Si realmente quieres hacerlo usando un do shell script comando Entonces, utilice lo siguiente código mientras se sustituye /path/to/new rich text file.rtf con una ruta de acceso nombre de archivo a una ubicación con permisos de escritura. Tenga en cuenta que no debe eliminar el \" antes y después /path/to/new rich text file.rtf en el actual comando ya que esto maneja el ruta de acceso nombre de archivo si contiene espacios. Si el ruta de acceso nombre de archivo no contiene espacios, entonces el \" antes y después /path/to/new rich text file.rtf no es necesario utilizarlo.

do shell script "osascript -e 'try' -e 'get the clipboard as «class RTF »' -e 'end try' | awk '{print substr($0, 12, length($0)-13)}' | xxd -r -p > \"/path/to/new rich text file.rtf\""

Aquí está el comando línea que se muestra como texto envuelto, para facilitar la visualización:

do shell script "osascript -e 'try' -e 'get the clipboard as «class RTF »' -e 'end try' | awk '{print substr($0, 12, length($0)-13)}' | xxd -r -p > \"/path/to/new rich text file.rtf\""

  • Aunque se puede copiar y pegar (recomendar) el código No obstante, a continuación se explica cómo escribir las comillas de doble ángulo, que también están disponibles bajo los paréntesis en los caracteres (especiales), por ejemplo optioncommandT en TextEdit.

    Nota: Tenga en cuenta el espacio en «class RTF » está destinado a ser compensado en este caso de uso.

    • Escribir comillas de doble ángulo

      • " Comillas de doble ángulo izquierdo, pulse: option\
      • " Comillas de doble ángulo derecho, pulse: shiftoption\

Tenga en cuenta que, tal como está escrito, este do shell script comando sobrescribe el archivo de salida si ya existe, sin preguntar. Será un archivo de longitud cero si el Portapapeles no contiene ningún contenido de Texto Enriquecido, de lo contrario el archivo tendrá la longitud necesaria para contener el contenido de Texto Enriquecido del Portapapeles. Obviamente, se podría codificar una lógica adicional en el archivo osascript comando Sin embargo, si necesitas más complejidad que esto, es mejor que utilices el método presentado en primer lugar en esta respuesta. O usando un script externo que sea llamado por do shell script comando que se encarga de todo lo necesario lógica y tratamiento de errores en función de la complejidad de las condiciones generales en las que se aplicará.

  • Por qué esa complejidad frente a la do shell script "pbpaste > /path/to/clipboard-file.rtf" ?

Esa es una buena pregunta y aunque pbpaste tiene la -Prefer {txt | rtf | ps} opción, sin embargo pbpaste -Prefer rtf puede no emitir texto enriquecido aunque exista en el portapapeles. O lo que hace, si no es texto ASCII, no será una forma de texto enriquecido que sea entendida, por ejemplo, por TextEdit, y o no contendrá todo el texto enriquecido atributos si lo hay, que contiene el contenido del Portapapeles.

Esto hace que sea necesario obtener el contenido de texto enriquecido en el portapapeles de una manera diferente y por qué get the clipboard as «class RTF » se utiliza en su lugar. Cuando se utiliza un do shell script comando con esto, requiere un procesamiento adicional para utilizar el datos devuelto, ya que está en un envoltura de datos cuando se devuelve y no se puede utilizar inmediatamente, por lo que requiere un tratamiento posterior.

Como ejemplo, Hello World! en texto enriquecido en el portapapeles puede tener este aspecto en texto ASCII:

{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf400
{\fonttbl\f0\fnil\fcharset0 ComicSansMS;}
{\colortbl;\red255\green255\blue255;}
\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\pardirnatural

\f0\b\fs36 \cf0 Hello World!}

El formato anterior, por desgracia, no es fácilmente utilizable, si es que lo es, en AppleScript y creo que es por eso por lo que se coge como codificado Hex datos es necesario.

  • Me baso en el hecho de que aunque el get clipboard info comando para el contenido del portapapeles en este ejemplo devuelve {«class RTF », 265} entre la información devuelta, no obstante, mientras que la forma de texto ASCII de este contenido de texto enriquecido tiene 265 bytes, se devuelve en formato hexadecimal a más del doble de bytes con el envoltura de datos . El hecho de que se devuelva en Hex por get the clipboard as «class RTF » tanto en el Editor de script o utilizando osascript apoyan esta suposición.

Aquí está el mismo Hello World! en texto enriquecido en el portapapeles en Hex:

7B5C727466315C616E73695C616E7369637067313235325C636F636F61727466313138375C636F636F617375627274663430300A7B5C666F6E7474626C5C66305C666E696C5C66636861727365743020436F6D696353616E734D533B7D0A7B5C636F6C6F7274626C3B5C7265643235355C677265656E3235355C626C75653235353B7D0A5C706172645C74783732305C7478313434305C7478323136305C7478323838305C7478333630305C7478343332305C7478353034305C7478353736305C7478363438305C7478373230305C7478373932305C7478383634305C7061726469726E61747572616C0A0A5C66305C625C66733336205C6366302048656C6C6F20576F726C64217D

Sin embargo, lo que se devuelve por get the clipboard as «class RTF » para el Hello World! ejemplo anterior es:

«data RTF 7B5C727466315C616E73695C616E7369637067313235325C636F636F61727466313138375C636F636F617375627274663430300A7B5C666F6E7474626C5C66305C666E696C5C66636861727365743020436F6D696353616E734D533B7D0A7B5C636F6C6F7274626C3B5C7265643235355C677265656E3235355C626C75653235353B7D0A5C706172645C74783732305C7478313434305C7478323136305C7478323838305C7478333630305C7478343332305C7478353034305C7478353736305C7478363438305C7478373230305C7478373932305C7478383634305C7061726469726E61747572616C0A0A5C66305C625C66733336205C6366302048656C6C6F20576F726C64217D»

La cadena codificada en hexadecimal está en un «data RTF » envoltura que debe eliminarse antes de convertir el contenido codificado en hexadecimal a texto ASCII para escribirlo en un archivo de disco mediante el uso de la redirección de E/S, por ejemplo > en el do shell script comando ejemplo anterior.

Así, la salida de osascript -e 'try' -e ' get the clipboard as «class RTF »' -e 'end try' se canaliza ( | ) a awk donde crea una subcadena, imprimiendo sólo el contenido codificado en hexadecimal, no el envoltura de datos ya que no sería procesado correctamente por xxd en el siguiente paso del proceso.

Luego hay que canalizarlo ( | ) a xxd para la conversión a ASCII Text que se escriba en un archivo de disco utilizando la Redirección de E/S, por ejemplo > al objetivo ruta de acceso nombre de archivo .

La imagen de abajo es de Visor de portapapeles cambiar entre las vistas de codificación ASCII y Hex, mostrando Hello World! copiado de un documento de texto enriquecido, el utilizado en este ejemplo.

Clipboard Viewer


Espero que esto proporcione una mejor comprensión de cómo AppleScript trabaja con contenido de texto enriquecido en el portapapeles, ya que de cualquier manera la conversión de una cadena codificada en hexadecimal a texto ASCII tiene que tener lugar y esto se está haciendo de forma transparente en el ejemplo original código mientras que requiere un procesamiento adicional fuera de AppleScript código que está siendo procesado por osascript cuando se utiliza el do shell script comando en este contexto.

0 votos

Los comentarios no son para ampliar la discusión; esta conversación ha sido trasladado al chat .

0 votos

La esfera de @rubik, Esto código tenía el mismo error como en su otra pregunta en que el archivo de destino se sobreescribía internamente y no se borraba. He corregido el error añadiendo delete the file (theRichTextFileName as POSIX file) dentro de un Finder tell bloque en el añadido si no rama de la if the button returned of the result is "No" then declaración .

0 votos

Esfera de @rubik, En cuanto a la modificación que has pedido, tendré que revisar el código y ver lo que se puede hacer, sin embargo, ya que esta respuesta, ahora como es, en realidad responde a la pregunta original formulada, creo que cualquier modificación debe ser intentado primero por usted y luego publicado como una pregunta separada si no puede lograr su objetivo. OMI No es precisamente justo volver meses más tarde pidiendo que se hagan modificaciones a una respuesta ya aceptada y votada que añade parámetros adicionales no preguntados previamente a la pregunta original.

1voto

Aneal Puntos 11

Los archivos RTF, a diferencia de los TXT, no son sólo texto plano, sino que tienen una estructura básica. Para crear un archivo RTF, utilice la siguiente estructura (en lugar del texto plano del teclado):

{\rtf1\ansi\deff0 {\fonttbl {\f0 Verdana;}}
\f0\fs16
Hello World!
}

Fuente: https://www.safaribooksonline.com/library/view/rtf-pocket-guide/9781449302047/ch01.html

0 votos

He editado mi pregunta para que sea más clara. ¿Tienes alguna idea de cómo puedo pegar el texto del portapapeles en el archivo RTF, y hacer que el archivo RTF coincida con la fuente, el tamaño, el color, etc. del texto del portapapeles?

0 votos

Lo que está diciendo es que si pones esos metadatos en un archivo de texto plano y le das la extensión .rtf, entonces tienes un archivo .rtf válido.

0 votos

@JonathanWarner Así es.

0voto

Matt B Puntos 41

Aquí hay funciones basadas en la respuesta del usuario3439894 para imprimir la versión de texto enriquecido del portapapeles convertida a HTML o la versión HTML del portapapeles. La versión HTML del portapapeles se incluye para el texto copiado desde una vista web.

ppr(){ osascript -e'the clipboard as"RTF "'|sed 's/«data RTF //;s/»//'|xxd -r -p|textutil -convert html -stdin -stdout; }

pph(){ osascript -e'the clipboard as"HTML"'|sed 's/«data HTML//;s/»//'|xxd -r -p; }

El sed Los comandos anteriores también pueden ser sustituidos por ruby -lpe'$_=$_[10..-2]' (aunque eso selecciona las posiciones de bytes incorrectas en la configuración regional de C).

En versiones anteriores de OS X pbpaste -Prefer rtf imprimió la versión RTF del portapapeles, pero ahora parece que sólo imprime texto plano.

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