3 votos

AppleScript: ¿Cómo abrir un archivo de texto y mover el cursor a una ubicación específica (señalada por un carácter específico)?

Tengo un archivo .txt guardado en mi computadora. Quiero que mi aplicación Automator abra el archivo .txt y luego mueva la ubicación del cursor a la primera línea en blanco del archivo.

Por ejemplo, tengo un archivo .txt titulado My Fruit Log.txt guardado en mi computadora. Así es como pueden verse los contenidos del archivo .txt:

Entonces, en el caso anterior, quiero que el archivo sea abierto y luego que el cursor se mueva a la segunda línea del archivo.

Nota: No necesariamente quiero que el cursor se mueva a la segunda línea desde la parte superior. Dependiendo de qué texto ya se haya escrito en el archivo, podría querer que el cursor esté en una línea más baja. Por ejemplo:

En el caso anterior, querría que el cursor se mueva a la sexta línea.

La ubicación donde quiero que esté el cursor siempre será al menos la segunda línea desde la parte superior, pero podría estar tan abajo como la séptima línea desde la parte superior.

Entonces, la forma más fiable de articular dónde quiero que se coloque el cursor es "en la primera instancia de una línea en blanco en el archivo".

Ya tengo el código para abrir el archivo en TextEdit (tomado de la respuesta principal de esta pregunta de Stack Overflow):

set Target_Filepath to POSIX file "/Users/Me/Desktop/My Fruit Log.txt"

tell application "Finder" to open Target_Filepath

Ahora necesito el código para mover el cursor. La ubicación predeterminada del cursor es la primera línea del archivo.

4voto

user3439894 Puntos 5883

No sé si hay una forma fácil o bonita de hacer lo que estás pidiendo. En otras palabras, no puedes simplemente decir algo como abrir archivo de destino y mover el cursor a la primera línea vacía, sin embargo el código a continuación lo hará.

set filePathName to POSIX path of (path to desktop as string) & "Mi Registro de Frutas.txt"
set firstEmptyLineNumber to (do shell script "awk '$1 == \"\" {print NR;exit;}' \"" & filePathName & "\"")
do shell script "open -e " & quoted form of filePathName
tell application "TextEdit" to activate
tell application "System Events" to tell process "TextEdit"
    repeat (firstEmptyLineNumber - 1) times
        key code 125 # Flecha abajo
    end repeat
end tell

El código anterior está codificado para abrir el archivo de texto en TextEdit, que es lo que open -e en el segundo do shell script comando está haciendo y está codificado de esta manera porque System Events necesita saber dónde enviar las pulsaciones de teclas de la flecha abajo. Si quieres un editor de texto diferente entonces elimina el -e y el open comando lo abrirá en la aplicación con la que el archivo .txt está registrado para abrir. Luego también necesitarás cambiar:

tell application "System Events" to tell process "TextEdit"

A:

tell application "System Events" to tell front process

Y reemplaza:

tell application "TextEdit" to activate

Con: delay 1

En el primer do shell script comando, awk está obteniendo el número de línea de la primera línea vacía y saliendo y esto es lo que se usa para calcular cuantas pulsaciones de teclas de flecha abajo repetir.


Modifiqué ligeramente mi respuesta original para eliminar el delay comando pero quería agregar mi opinión sobre la respuesta de adc mientras elimino toda la parte de menu_click.

set filePathName to POSIX path of (path to desktop as string) & "Mi Registro de Frutas.txt"
set firstEmptyLineNumber to (do shell script "awk '$1 == \"\" {print NR;exit;}' \"" & filePathName & "\"")
if firstEmptyLineNumber = "" then set firstEmptyLineNumber to 1 as string
do shell script "open -e " & quoted form of filePathName
tell application "TextEdit" to activate
tell application "System Events" to tell process "TextEdit"
    key code 37 using command down # ⌘L
    keystroke firstEmptyLineNumber
    keystroke return
    key code 123 # Flecha Izquierda - Para que la línea no esté resaltada.

Actualización:

El código a continuación ha sido modificado del código arriba en mi respuesta, no es mi versión de la respuesta de arc aunque también es aplicable allí, para abordar el problema que estás teniendo con TextEdit escribiendo dos retornos de carro en lugar de los dos avances de línea esperados y normales para una línea vacía después de una línea con contenido o dos líneas vacías seguidas.

set filePathName to POSIX path of (path to desktop as string) & "Mi Registro de Frutas.txt"
set firstEmptyLineNumber to (do shell script "awk '$1 == \"\" {print NR;exit;}' \"" & filePathName & "\"")
if firstEmptyLineNumber is equal to "" then  
    set firstEmptyLineNumber to (do shell script "awk '/\r\r/{print NR+1;exit;}' \"" & filePathName & "\"")
end if
do shell script "open -e " & quoted form of filePathName
tell application "TextEdit" to activate
tell application "System Events" to tell process "TextEdit"
    repeat (firstEmptyLineNumber - 1) times
        key code 125 # Flecha Abajo
    end repeat

Nota: Aunque el código modificado funciona con tu archivo testfile.txt del enlace en tu comentario, personalmente no recomiendo este arreglo y preferiría encontrar la causa root del problema y ¡arreglarlo y tus archivos!

0voto

klanomath Puntos 19587

Aquí tienes un AppleScript para TextWrangler para saltar al final del primer párrafo de un archivo de texto:

try
    tell application "TextWrangler"
        find "(?=\\r^\\r|\\A)" searching in text of front text window options {search mode:grep, wrap around:false, backwards:false, case sensitive:false} with selecting match
    end tell
end try

Al agregar una segunda expresión directamente después de (?=\\r^\\r|\\A) pero dentro de las comillas, se debería poder saltar a la siguiente línea. Dado que no sé lo que realmente significa (?=\\r^\\r|\\A), no puedo ayudarte más.

0voto

adc Puntos 1

Probablemente abordaría esto utilizando algo como Ruby y TextMate— un script de Ruby podría determinar qué línea elegir (probablemente a través de una expresión regular simple) e incluso agregar la fecha del día siguiente si es apropiado. TextMate puede ser invocado en la línea de comandos para mover el cursor a una línea específica por mate -l 7 por ejemplo.

Dicho esto, utilizando solo AppleScript en TextEdit y awk de la respuesta de user3439894, una forma algo más sólida de navegar a una línea específica utiliza System Events y el elemento de menú "Seleccionar línea" (Comando + L) de TextEdit.

También usé una función de MacOSXHints porque la escritura de menús en AppleScript es muy complicada. Eliminar la función menu_click es un ejercicio para el lector.

set filePathName to POSIX path of (path to desktop as string) & "My Fruit Log.txt"
set firstEmptyLineNumber to (do shell script "awk '$1 == \"\" {print NR;exit;}' \"" & filePathName & "\"")
if firstEmptyLineNumber = "" then set firstEmptyLineNumber to 1

do shell script "open -e " & quoted form of filePathName

menu_click({"TextEdit", "Edit", "Buscar", "Seleccionar línea..."})

tell application "System Events"
    keystroke firstEmptyLineNumber
    keystroke return

-- `menu_click`, por Jacob Rus, septiembre 2006 -- -- Acepta una lista de forma: `{"Finder", "Ver", "Organizar por", "Fecha"}` -- Ejecuta el elemento de menú especificado. En este caso, asumiendo que Finder -- es la aplicación activa, organizando la carpeta más frontal por fecha. on menu_click(mList) local appName, topMenu, r -- Validamos nuestra entrada if mList's length < 3 then error "La lista de menú no es lo suficientemente larga" -- Establecemos estas variables para mayor claridad y brevedad más adelante set {appName, topMenu} to (items 1 through 2 of mList) set r to (items 3 through (mList's length) of mList) -- Esta línea excesivamente larga llama a la función menu_recurse con -- dos argumentos: r, y una referencia al menú de nivel superior tell application "System Events" to my menu_click_recurse(r, ((process appName)'s ¬ (menú barra 1)'s (elemento de menú barra topMenu)'s (menú topMenu))) end menu_click on menu_click_recurse(mList, parentObject) local f, r -- `f` = primer elemento, `r` = resto de elementos set f to item 1 of mList if mList's length > 1 then set r to (items 2 through (longitud de mList) of mList) -- haga clic realmente en el elemento de menú, o recursión nuevamente tell application "System Events" if mList's length is 1 then clic en el elemento de menú del objeto padre f else mi menu_click_recurse(r, (el objeto padre del objeto (elemento de menú f)'s (elemento de menú f))) end if end tell end menu_click_recurse

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