AppleScript: ¿Cómo verificar si el portapapeles consiste en un archivo (en lugar de texto)?

Si mi comprensión es correcta, hay dos tipos de contenido que se pueden copiar en el portapapeles global (de todo el sistema) de Mac:

  • text

o

  • file

Aunque son dos tipos de datos discretos diferentes, comparten el mismo portapapeles. Por ejemplo, si tiene una imagen fileen su portapapeles y luego copia una textoración, la oración sobrescribirá el archivo de imagen y viceversa. Por favor, corríjame si estoy equivocado.

Mi pregunta es, ¿cómo puedo determinar si el portapapeles no contiene text, usando AppleScript?

El contexto de mi pregunta es un archivo .scpt de AppleScript que pronuncia el texto seleccionado en System Voice en un volumen específico. El texto seleccionado se copia en el portapapeles y luego se pronuncia mediante el saycomando. El script se activa con una pulsación de tecla a través de FastScripts.app.

De vez en cuando, aparece un cuadro de diálogo de error que dice "Número de error: -1728". Este error ocurre cuando, en lugar de textestar resaltado, he resaltado o seleccionado un archivo file. La función de voz de Mac no puede pronunciar un file; El habla sólo puede verbalizar text.

Por lo tanto, me gustaría crear una if...thendeclaración en mi secuencia de comandos para detectar este error. Idealmente, me gustaría convertir el filea text, si es posible en la forma en que lo hace TextEdit.

Su primera suposición es incorrecta: texto o archivo (probablemente realmente quiere decir xor ). Es mucho más complicado. Puede comprobar el contenido del portapapeles con la aplicación "Clipboard Viewer" de Apple (Xcode). Está disponible en Herramientas auxiliares para Xcode 7.
También se podría crear fácilmente un servicio de Automator (asignado a un método abreviado de teclado a través del panel de preferencias del sistema de teclado) que recibe el texto seleccionado en cualquier aplicación y luego ejecuta las acciones Establecer volumen de la computadora y Leer texto , sin necesidad de copiar el texto seleccionado a el portapapeles (¡Por supuesto, puede tener buenas razones para usar su AppleScript en su lugar!)
@BigMac 1. Mi código AppleScript me permite detener el discurso con la misma pulsación de tecla que utilizo para iniciar el discurso. 2. Mi código en realidad no afecta el volumen del sistema; define el volumen del proceso de voz como un porcentaje del nivel de volumen actual del sistema. 3. La activación de un servicio en todo el sistema mediante un atajo de teclado no es confiable. Consulte: El método abreviado de teclado para el servicio solo funciona después de ejecutar manualmente el servicio . FastScripts.app, OTOH, es confiable. Pero FastScripts, por supuesto, solo puede activar archivos .scpt, no archivos de Automator Service.
@rubik'ssphere Gracias por explicar; No conozco ninguna forma de hacer el #1 en Automator, ¡así que esa es razón suficiente para usar AppleScript! #3 también descartaría un servicio de Automator, pero afortunadamente no he experimentado ese problema (todavía). El #2 probablemente podría hacerse en una acción Ejecutar AppleScript dentro de Automator (en lugar de usar las acciones que mencioné). Me encantaría ver su guión final, si está dispuesto a compartirlo, ya que yo también uso con frecuencia el texto a voz de Apple.
@BigMac (1/2) El corazón de mi código es la solución genial proporcionada por jackjr300 aquí: AppleScript: ¿Es posible verificar si Speech se está ejecutando actualmente? . Para configurar el volumen del discurso, como un porcentaje del volumen actual del sistema (elegí 35%), consulte: ¿Cómo cambiar el volumen de "decir" en AppleScript? . Descubrí un error en la línea de comandos, así que vea aquí una solución alternativa:
(2/2) ¿Cómo evitar el error de comando "decir" al configurar el volumen? Finalmente, la respuesta de @user3439894 a esta misma publicación hace que el script diga el nombre de archivo de un archivo seleccionado : AppleScript: ¿Cómo verificar si el portapapeles consiste en un archivo (en lugar de texto)? Reúna todo esto y habrá creado mi archivo AppleScript actual.

Respuestas (1)

Si el Portapapeles contiene un objeto de archivo , entonces clipboard infocontendrá, por ejemplo, «class furl»(una URL de archivo), junto con muchas otras clases.

El siguiente código de ejemplo verificará la presencia de «class furl»en el clipboard info:

if ((clipboard info) as string) contains "«class furl»" then
    say "the clipboard contains a file named " & (the clipboard as string)
else
    say "the clipboard does not contain a file"
end if

Actualizar:

Como mencioné en uno de mis comentarios, hay otras formas de codificar esto, y este enfoque devolverá una lista vacía o una lista que contiene una lista , que debería ser más rápido en lugar de los 14 que devuelve el primer ejemplo si contiene un archivo _ Si el Portapapeles no contiene un archivo , entonces la lista devuelta está vacía y genera un error, se establece cbFileen false, y si no está vacío, se establece en true, que luego se prueba en el siguiente ejemplo.

try
    (item 1 of (clipboard info for «class furl»))
    set cbFile to true
on error
    set cbFile to false
end try
if cbFile then
    say "the clipboard contains a file named " & (the clipboard as string)
else
    say "the clipboard does not contain a file"
end if

Por cierto, ejecuté el purge comando en Terminal entre probar estos dos ejemplos y sentí que el segundo ejemplo es un poco más rápido, sin embargo, YMMV.

¿También sabe cómo obtener solo el nombre del archivo (no la ruta completa) como texto de un archivo que está en el portapapeles? Si se cumple la condición if: if ((clipboard info) as string) contains "«class furl»"entonces me gustaría que mi secuencia de comandos tenga sayel nombre de archivo del archivo del portapapeles.
Avíseme si cree que la pregunta en mi comentario anterior amerita una publicación dedicada.
Esfera de @rubik, actualicé la respuesta para manejar la condición establecida en su comentario. Por cierto, si desea el nombre de ruta completamente calificado, deberá usar Cocoa-AppleScript y NSPasteboard, que no estoy al tanto como AppleScript normal.
Otra pregunta limitada sería mejor, @rubik'ssphere. Vincular los dos aquí en los comentarios también sería bueno. Editaré la pregunta que publicaste aquí para aclarar el tema aquí.
Para el votante negativo, explique una razón legítima para ello, ¿no responde esto a la pregunta formulada? ¿Tiene una mejor respuesta en lugar de un voto negativo injustificado?
@ user3439894 Su solución funciona muy bien. Pero me doy cuenta de que hay un breve retraso antes de que el script hable: "El portapapeles contiene un archivo llamado nombre de archivo". ¿Hay algo que pueda hacer para acortar o eliminar este retraso?
Esfera de @rubik, ¿Cuánto tiempo de retraso?... Cuando ejecuto este código de ejemplo en el Editor de secuencias de comandos, tal como está, realmente no noto un retraso. ¿Está notando un retraso con este código de ejemplo en el Editor de secuencias de comandos, tal como está, o ha tomado este ejemplo y lo ha modificado para que se ajuste a sus necesidades en el script más grande y ahí es donde nota un retraso? Si es lo primero, hay más de una forma de escribir este código y he probado diferentes codificaciones pero realmente no noto un retraso en mi sistema. Si es lo último, entonces sin ver el código para probar, realmente no hay nada que pueda decir ( juego de palabras con el código ).
@ user3439894 Cuando ejecuto su código en Script Editor.app, palabra por palabra, hay un retraso de 1 segundo antes de que se diga "El portapapeles contiene un archivo llamado ..." , pero "El portapapeles no contiene un archivo" se dice inmediatamente. Esto es cierto sin importar el tipo o la ubicación del archivo que se encuentra en el portapapeles. ¿No experimenta el retraso en su sistema? Obviamente, esto no es un gran retraso, pero es lo suficientemente largo como para notar el retraso cada vez. ¿Sería posible para mí probar los otros métodos de codificación?
La esfera de @rubik, ahora que sé que está comparando una diferencia entre los dos estados, eso es de esperar ya que se está procesando más cuando se evalúa como verdadero. Si es falso, el retorno de clipboard infopuede contener tan solo 4 clases y, si es verdadero, puede contener muchas más, por ejemplo, 14 clases. Todos los cuales deben enumerarse y algunos de ellos pueden tardar más en enumerarse que otros, lo que aumenta aún más la demora esperada. Así que solo eso inicia la diferencia de retardo. Además, si es verdadero, se consulta el Portapapeles por el nombre del archivo como una cadena, lo que agrega más a la diferencia de retraso. ¿Tiene sentido?
Esfera de @rubik, actualicé la respuesta agregando otro ejemplo para que pruebes si es más rápido.
@ user3439894 Sí, eso tiene sentido. Gracias por la explicación detallada. Todavía me sorprende que una máquina tan poderosa y avanzada no pueda realizar esta tarea relativamente simple al instante. Supongo que algún código ineficiente por parte de Apple tiene la culpa. Descubrí que su método alternativo no es más rápido que el método original, por lo que sé. El nuevo método todavía tiene un retraso de 1 segundo. No puedo medir con precisión el tiempo de ejecución hasta el milisegundo. Gracias por toda tu ayuda.
Esfera de @rubik, FWIW Guardar ambas versiones de código como .scpt con modificación de la rama falsa, por lo que diría exactamente lo mismo que la rama verdadera, hecho para una mejor comparación, y ejecutándose osascriptcomo un argumento de time, hubo una diferencia entre las 2 versiones. Cerré/abrí la Terminal y usé el purgecomando entre cada ejecución y cuando todo estuvo dicho, ver1 tenía una diferencia de 0.719 s entre la rama T/F y ver2 tenía una diferencia de 0.363 s entre la rama T/F en comparación con 0.356 s diff entre cada versión. Si bien ver2 fue técnicamente más rápido, el diferencial es insignificante.
@ user3439894 Interesante análisis. En ese caso, optaré por el método alternativo.