AppleScript: Comment ouvrir un fichier texte et déplacer le curseur à un emplacement spécifique (signalé par un caractère spécifique)?

3

J'ai un fichier .txt enregistré sur mon ordinateur. Je souhaite que mon application Automator ouvre le fichier .txt, puis déplace l'emplacement du curseur sur la première ligne vierge du fichier.

Par exemple, j'ai un fichier .txt intitulé Mon Fruit Log.txt enregistré sur mon ordinateur. Voici à quoi peut ressembler le contenu du fichier .txt:

Donc, dans l'exemple ci-dessus, je veux que le fichier soit ouvert, puis le curseur déplacé vers la deuxième ligne du fichier.

Remarque: ce n'est pas nécessairement la deuxième ligne du haut à laquelle je souhaite que le curseur soit envoyé. Selon le texte qui a déjà été écrit dans le fichier, je souhaiterais peut-être placer le curseur sur une ligne inférieure. Par exemple:

Dans le cas ci-dessus, je voudrais que le curseur soit déplacé à la sixième ligne.

L'emplacement où je veux que le curseur soit toujours au moins la deuxième ligne en partant du haut, mais il pourrait être aussi bas que la septième ligne en partant du haut.

Ainsi, le moyen le plus fiable d’articuler où je veux que le curseur soit placé est "sur la première instance d’une ligne vide dans le fichier".

J'ai déjà le code pour ouvrir le fichier dans TextEdit (emprunté à la première réponse de cette question Stack Overflow ):

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

tell application "Finder" to open Target_Filepath

Maintenant, j'ai besoin du code pour déplacer le curseur. L'emplacement par défaut du curseur est la première ligne du fichier.

la sphère de rubik
la source
Je pense que cela ne peut pas être fait avec TextEdit car il manque une fonction de recherche dans la bibliothèque AppleScript. BBEdit et TextWrangler devraient fonctionner car ils en fournissent un.
klanomath

Réponses:

4

Je ne sais pas s'il existe un moyen simple ou agréable de faire ce que vous demandez. En d'autres termes, vous ne pouvez pas simplement dire quelque chose comme cela open target file and move cursor to first empty line, mais le code ci-dessous le fera.

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 & "\"")
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 # Down Arrow
    end repeat
end tell

Le code ci-dessus est codé pour ouvrir le fichier texte dans TextEdit, comme open -edans la deuxième
do shell script commande. Il est codé de cette façon, car System Events doit savoir où envoyer les séquences de touches fléchées vers le bas . Si vous souhaitez un autre éditeur de texte, supprimez-
le -eet la open commande l'ouvrira dans l'application que l' extension de fichier .txt est enregistrée pour pouvoir l'ouvrir. Ensuite, vous devrez également changer:

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

À:

tell application "System Events" to tell front process

Et remplace:

tell application "TextEdit" to activate

Avec: delay 1

Dans la première do shell script commande , awkobtient le numéro de ligne de la première ligne vide et la sortie, et c’est ce qui permet de calculer le nombre de frappes de la flèche vers le basrepeat .


J'ai légèrement modifié ma réponse initiale pour me débarrasser de la delay commande, mais je voulais ajouter ma réponse à la réponse de adc tout en éliminant tout le menu_clickcontenu.

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 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 # Left Arrow - So the line is not highlighted.
end tell

Mise à jour:

Le code ci-dessous a été modifié à partir du code ci-dessus en haut de ma réponse, et non de ma réponse à la réponse de arc, bien qu'elle puisse également s'appliquer ici, afin de résoudre le problème rencontré par TextEdit lors de l'écriture de deux retours à la place au lieu des deux retours attendus et normaux. la ligne est utilisée pour une ligne vide après une ligne contenant du contenu ou deux lignes vides dans une ligne.

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 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 # Down Arrow
    end repeat
end tell

Remarque: Bien que le code modifié fonctionne avec votre fichier testfile.txt à partir du lien de votre commentaire, je ne souscris pas personnellement à cette solution de contournement et rechercherais plutôt la cause première du problème et le corrigerait ainsi que vos fichiers!

utilisateur3439894
la source
Solution intelligente. Mais, pour une raison quelconque, votre code ne fonctionne pas pour moi. Il ouvre le fichier .txt dans TextEdit, mais le curseur ne bouge pas. J'ai essayé de changer delay 1d' delay 10être en sécurité; cependant, il n’a pas déplacé le curseur. Ensuite, j'ai inséré display dialog firstEmptyLineNumberaprès la deuxième ligne de votre code. Lorsque j'ai exécuté le code, une boîte de dialogue complètement vide est apparue. C’est le fichier .txt que j’utilise pour tester votre code. Lorsque vous utilisez ce fichier .txt, le code fonctionne-t-il correctement sur votre ordinateur?
La sphère de rubik
Le fichier "testfile.txt" a été créé sur mon Mac. Voici comment cela a été créé (et je ne connais pas d'autre moyen de créer un fichier .txt sur un Mac): j'ai créé un nouveau document dans TextEdit, tapé le texte, cliqué sur le menu Format, puis sur Texte brut, puis enregistré. le fichier en tant que "testfile.txt" avec l'option de codage par défaut de "Unicode (UTF-8)". Je vois ce que vous voyez dans l'éditeur d'hex; il y a un 0D0Dentre les quatrième et cinquième lignes du fichier. Est-il possible d'éditer votre code afin qu'il puisse reconnaître les deux lignes vierges 0D0Dainsi 0A0Dque de nouvelles?
La sphère de rubik
La sphère de @ rubik, supprimez tout sauf votre premier commentaire sous ma réponse jusqu'à présent, car ils ne sont plus vraiment nécessaires, maintenant que nous savons que le problème est TextEdit sur votre système et écrit à la 0Dplace de 0Ala norme sur un Mac. J'ai essayé de reproduire votre problème dans TextEdit sous OS X 10.11.6 et macOS 10.12, en procédant comme vous le dites et je ne peux pas le reproduire. Toutes mes fins de lignes sont 0Acomme elles devraient être et par conséquent la ligne vide s'affiche comme 0A0Adans l'éditeur hexadécimal, deux sauts de ligne consécutifs comme il est supposé par défaut sur un Mac, et non deux retours à la ligne.
user3439894
La sphère de @ rubik, j'ai mis à jour ma réponse pour traiter votre problème et l' ai testée sur votre fichier testfile.txt à partir du lien de votre commentaire et cela fonctionne. FWIW
user3439894
Wow, le nouveau code fonctionne vraiment. Merci beaucoup user3439894. Je tiendrai toujours compte de vos conseils sur le diagnostic du problème fondamental, mais cela me retiendra dans l’intervalle. Sur une note séparée, pourquoi avez-vous décidé de supprimer entièrement la delaycommande de votre code? Je pensais que vous aviez initialement inclus la delaycommande pour garantir que les pressions de la flèche vers le bas ne se produiraient pas prématurément. (Ce n'est pas que ça me pose problème; je suis simplement curieux.)
sphik's sphere
0

Voici un AppleScript pour TextWrangler permettant de passer à la fin du premier paragraphe d'un fichier texte:

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

En ajoutant une deuxième expression directement après (?=\\r^\\r|\\A)mais entre les guillemets, on devrait pouvoir passer à la ligne suivante. Puisque je ne sais pas ce que (?=\\r^\\r|\\A)cela signifie vraiment, je ne peux pas vous aider davantage.

Klanomath
la source
Le problème que je vois est que TextWrangle mémorise la position du curseur dans le document lors du dernier enregistrement dans TextWrangler et que le curseur peut ne pas être en haut du fichier, comme ce sera le cas avec TextEdit lors de son ouverture. Donc, tel qu’il est codé, il peut échouer à plus d’un titre, c’est le cas sur mon système. En d'autres termes, si j'ai enregistré le fichier à la fin du premier paragraphe, il ira à la fin du deuxième paragraphe lorsque j'exécuterai le code . Ou si j’enregistre à la fin du deuxième paragraphe, il ne fait aucune remarque lorsque j’exécute le code car, à ce stade, il n’ya que trois paragraphes dans le fichier.
user3439894
0

J'aborderais probablement ceci en utilisant quelque chose comme Ruby et TextMate: un script Ruby pourrait déterminer la ligne à choisir (probablement par une simple expression régulière) et même ajouter la date du jour suivant, le cas échéant. TextMate peut être appelé sur la ligne de commande pour déplacer le curseur sur une ligne spécifique, par mate -l 7exemple.

Cela dit, utiliser uniquement AppleScript dans TextEdit et à awkpartir des réponses de user3439894, un moyen un peu plus robuste de naviguer vers une ligne spécifique utilise l'élément de menu Evénements système et TextEdit "Sélectionner une ligne" (Commande + L).

J'ai également utilisé une fonction de MacOSXHints car les scripts de menu dans AppleScript sont très pénibles. L'élimination de la fonction menu_click est un exercice pour le lecteur.

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", "Find", "Select Line..."})


tell application "System Events"
    keystroke firstEmptyLineNumber
    keystroke return
end tell




-- `menu_click`, by Jacob Rus, September 2006
-- 
-- Accepts a list of form: `{"Finder", "View", "Arrange By", "Date"}`
-- Execute the specified menu item.  In this case, assuming the Finder 
-- is the active application, arranging the frontmost folder by date.

on menu_click(mList)
    local appName, topMenu, r

    -- Validate our input
    if mList's length < 3 then error "Menu list is not long enough"

    -- Set these variables for clarity and brevity later on
    set {appName, topMenu} to (items 1 through 2 of mList)
    set r to (items 3 through (mList's length) of mList)

    -- This overly-long line calls the menu_recurse function with
    -- two arguments: r, and a reference to the top-level menu
    tell application "System Events" to my menu_click_recurse(r, ((process appName)'s ¬
        (menu bar 1)'s (menu bar item topMenu)'s (menu topMenu)))
end menu_click

on menu_click_recurse(mList, parentObject)
    local f, r

    -- `f` = first item, `r` = rest of items
    set f to item 1 of mList
    if mList's length > 1 then set r to (items 2 through (mList's length) of mList)

    -- either actually click the menu item, or recurse again
    tell application "System Events"
        if mList's length is 1 then
            click parentObject's menu item f
        else
            my menu_click_recurse(r, (parentObject's (menu item f)'s (menu f)))
        end if
    end tell
end menu_click_recurse
adc
la source
Vous pouvez remplacer tout menu_clickça (ce qui est intéressant BTW) par deux lignes de code. Placez-le tell application "TextEdit" to activatejuste avant le tell application "System Events"bloc et ajoutez-y key code 37 using command down(qui est ⌘L la touche de raccourci pour "Sélectionner une ligne ...") ou plus keystroke "l" using command down haut keystroke firstEmptyLineNumberdans le tell application "System Events"bloc. J'ajouterais aussi key code 123(flèche droite) après keystroke returnpour que la ligne ne soit pas en surbrillance.
user3439894