Passer de AppleScript à Swift ;) quelques questions simple pour transposer.
Bonjour,
Dans le cadre de mon boulot de chargé de post prod sur Final Cut Pro x, j'écris parfois de petites applications pour lire et modifier des XML exportés depuis FCP X (Final Cut Pro X).
J'aimerais trouver un point d'entrée dans Swift comme j'avais pu le faire avec l'aide de quelques uns d'entre vous sur AppleScript.
Depuis ce petit coup de main, j'ai réussi à me familiariser avec l'Apple Script.
Pour transposer, j'essaie donc de réécrire certaines petites app écrite en AppleScript en Swift.
La lecture de l'anglais dans les Tuto me fatigue beaucoup et complexifie l'apprentissage et je crois que pour l'instant il me manque les logiques profonde de Swift. Il me faudra du temps...
Je pose mes questions et si vous trouvez qu'elles sont trop coûteuses en temps de réponse, c'est pas grave... je finirai bien par trouver ;)
Question 01:
Ma première question concerne les termes "contains" et "thru": J'aimerais trouver l'équivalent dans Swift...
Code:
1 2 3 4 5
|
set T_MediaId to "media id="
set T_Name to "name="
if La_Ligne contains "<media id=" then
set P_MediaId to (text ((offset of T_MediaId in La_Ligne) + 10) thru ((offset of T_Name in La_Ligne) - 3) of La_Ligne) |
Je pourrais boucler sur les character de la ligne mais je pense qu'il existe une commande plus rapide...
Et si vous avez le courage, quel serait l'équivalent de la dernière ligne
Code:
1 2
|
set P_MediaId to (text ((offset of T_MediaId in La_Ligne) + 10) thru ((offset of T_Name in La_Ligne) - 3) of La_Ligne) |
Question complémentaire:
Peut-on trouver l'offset d'un ensemble de mot (et non d'un caractère) : par exemple l'offset de "est" dans la phrase "le cheval est plan"
Question 02: (qui ne doit pas avoir une réponse simple)
Mon but est de traduire le tout début de mont programme en AppleScript:
Part 01a: ici une fois l'application lancée, une fenêtre s'ouvre et demande à l'utilisateur de choisir un fichier de type "fcpxml"
Code:
1 2 3 4 5 6
|
on run
set source to choose file of type {"fcpxml"} with prompt "Select the file .fcpxml to process :"
Prog_Principal(source)
end run |
Part 01b (début du programme principal): ici on crée un fichier vide de même type ("fcpxml") à côté de l'original.
Code:
1 2 3 4 5 6 7
|
on Prog_Principal(source)
tell application "Finder"
set Nom to name of source
set Nouv_Nom to (text 1 thru ((length of Nom) - 7) of Nom) & "_NEW.fcpxml"
set Destination to ((container of source) as text) & Nouv_Nom
end tell |
En vous remerciant par avance pour vos réponses éventuelles.
Martin Gosset
PS: si l'un d'entre vous se sentait la disponibilité de m'aider davantage dans ce début d'apprentissage, je suis formateur sur FCP X et peut donc en échange et avec grand grand plaisir, fournir toute explication sur ce logiciel ou encore offrir mes documents d'apprentissages (visible ici : martingosset.com)...
thru d'AppleScript ressemble furieusement à ..< du swift
Bonjour monsieur Osset, bonjour à toutes et à tous.
Citation:
Envoyé par
MartinOsset
Bonjour,
Question 01:
Ma première question concerne les termes "
contains" et "
thru": J'aimerais trouver l'équivalent dans Swift...
Code:
1 2 3 4 5
|
set T_MediaId to "media id="
set T_Name to "name="
if La_Ligne contains "<media id=" then
set P_MediaId to (text ((offset of T_MediaId in La_Ligne) + 10) thru ((offset of T_Name in La_Ligne) - 3) of La_Ligne) |
Ceci est correct seulement pour transcrire AppleScript.
Cordialement à
Je pourrais boucler sur les character de la ligne mais je pense qu'il existe une commande plus rapide...
Martin Gosset
Réponse à la question 01:
Dans les deux langages "contains" se transpose en "contains".
Mais pour "thru" c'est plus difficile, je pense que la bonne transposition est "..<".
La raison est ici dans le code :
// **************************************************************
// set P_MediaId to text A thru B of La_Ligne
P_MediaId = String(A..<B, of :La_Ligne)
// thru de l'AppleScript similaire à ..< du swift
// **************************************************************
La commande rapide est localizedStandardRange(of: texte) mais elle n'est pas adapter pour AppleScript.
Le code suivant va l'adapter et répondre ainsi à vos questions (si je ne me suis pas trompé).
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
| import Foundation
extension String.Index {
func move(_ quantité: Int, of texte: String) -> String.Index {
let min_index = texte.startIndex
let max_index = texte.endIndex
var index = self
if max_index > min_index {
var quantité = quantité
if quantité > 0 {
if self < max_index {
index = texte.index(after: self)
for _ in 1..<quantité {
if index < max_index {
index = texte.index(after: index)
} else {
break
}
}
}
}
if quantité < 0 {
quantité = -quantité
if self > min_index {
index = texte.index(before: self)
for _ in 1..<quantité {
if index > min_index {
index = texte.index(before: index)
} else {
break
}
}
}
}
}
return index
}
}
extension String {
init(_ range: Range<String.Index>?,of texte: String) {
self.init()
if let range = range {
self = texte.substring(with: range)
} else {
self = ""
}
}
func offset(of texte: String) -> String.Index? {
if let offSet = self.localizedStandardRange(of: texte) {
// offset pour être compatible avec AppleScript il faut prendre l'index d'après.
// sinon : return offSet.lowerBound
return self.index(after: offSet.lowerBound)
} else {
return nil
}
}
}
/* AppleScript
set T_MediaId to "media id="
set T_Name to "name="
set La_Ligne to "AppleScript, <media id=@essai@ name= la suite du texte..."
if La_Ligne contains T_Name then set P_MediaId to text ((offset of T_MediaId in La_Ligne) + 10) thru ((offset of T_Name in La_Ligne) - 3) of La_Ligne
log "P_MediaId : " & P_MediaId
set A to (offset of T_MediaId in La_Ligne) + 10
set B to (offset of T_Name in La_Ligne) - 3
if La_Ligne contains T_Name then set P_MediaId to text A thru B of La_Ligne
log "P_MediaId : " & P_MediaId
Note : Attention offset of donne l'offset suivant et non le premier offset du texte trouvé
*/
// Traduction en swift
// set La_Ligne to "AppleScript, <media id=@essai@ name= la suite..."
var La_Ligne = "AppleScript, <media id=@essai@ name= la suite du texte..."
// set T_MediaId to "media id="
var T_MediaId = "<media id="
// set T_Name to "name="
var T_Name = "name="
// if La_Ligne contains "<media id=" then
if La_Ligne.contains(T_MediaId) && La_Ligne.contains(T_Name) {
// set P_MediaId to text ((offset of T_MediaId in La_Ligne) + 10) thru ((offset of T_Name in La_Ligne) - 3) of La_Ligne
var P_MediaId = String(La_Ligne.offset(of: T_MediaId)!.move(10, of: La_Ligne)..<La_Ligne.offset(of: T_Name)!.move(-3, of: La_Ligne),of: La_Ligne)
// log P_MediaId
print ("P_MediaId ~> \(P_MediaId)")
/* La même chose en décomposant le code AppleScript en plus lisible dans le corps du if
set A to ((offset of T_MediaId in La_Ligne) + 10)
set B to ((offset of T_Name in La_Ligne) - 3)
set P_MediaId to text A thru B of La_Ligne
log "P_MediaId : " & P_MediaId
*/
// set A to ((offset of T_MediaId in La_Ligne) + 10)
let A = La_Ligne.offset(of: T_MediaId)!.move(10, of: La_Ligne)
// set B to ((offset of T_Name in La_Ligne) - 3)
let B = La_Ligne.offset(of: T_Name)!.move(-3, of: La_Ligne)
// **************************************************************
// set P_MediaId to text A thru B of La_Ligne
P_MediaId = String(A..<B, of :La_Ligne)
// thru de l'AppleScript similaire à ..< du swift
// **************************************************************
// log "P_MediaId : " & P_MediaId -- > (*P_MediaId : essai*)
print ("P_MediaId ~> \(P_MediaId)")
}
// Réponse complémentaire
typealias Offset = String.CharacterView.Index
print()
print("Trouver l'offset de \"est\" dans la phrase \"le cheval est plan\"")
var offset: Offset?
offset = "le cheval est plan".offset(of: "est")
print("offset ~> \(offset!)")
print()
print("Fin du programme et sortie avec code: 0")
// Console :
/*
P_MediaId ~> essai
P_MediaId ~> essai
Trouver l'offset de "est" dans la phrase "le cheval est plan"
offset ~> Index(_base: Swift.String.UnicodeScalarView.Index(_position: 11), _countUTF16: 1)
Fin du programme et sortie avec code: 0
Program ended with exit code: 0
*/
// Merci pour m'avoir lu. |
Citation:
Envoyé par
MartinOsset
Question 01 suite :
Et si vous avez le courage, quel serait l'équivalent de la dernière ligne
Code:
set P_MediaId to (text ((offset of T_MediaId in La_Ligne) + 10) thru ((offset of T_Name in La_Ligne) - 3) of La_Ligne)
Martin Gosset
Réponse
Code:
var P_MediaId = String(La_Ligne.offset(of: T_MediaId)!.move(10, of: La_Ligne)..<La_Ligne.offset(of: T_Name)!.move(-3, of: La_Ligne),of: La_Ligne)
Citation:
Envoyé par
MartinOsset
Question complémentaire:
Peut-on trouver l'offset d'un ensemble de mot (et non d'un caractère) : par exemple l'offset de "est" dans la phrase "le cheval est plan"
En vous remerciant par avance pour vos réponses éventuelles.
Martin Gosset
Code:
1 2 3 4 5
| // Trouver l'offset de "est" dans la phrase "le cheval est plan"
typealias Offset = String.CharacterView.Index
var offset: Offset?
offset = "le cheval est plan".offset(of: "est") // Attention c'est un optionnel. Si "est" n'est pas dans la phrase alors offset ~> nil.
print("offset ~> \(offset!)") |
Je pense que c'est correct pour transcrire les Offsets d'AppleScript.
Mais l'erreur est humaine.
Cordialement à Mr Ousset, toutes et à tous.
PS : Pour la question 02. J'ai une idée qui marchera peut être en attendant je sèche un peu.
J'espère pouvoir répondre à la question 02.
Bonjour,
Je vais regarder votre site martingosset.com afin de comprendre ce que fait FCP X.
J'ai un peu peur de courir trop de lièvres à la fois et de m'éparpiller, une introduction peut-être…
Grâce à vous, je me suis un peu amélioré dans Swift et ai eu plaisir à redécouvrir AppleScript, c'est déjà très bien.
Pour finir j'ai mal interprété votre question 02 car je ne suis pas spécialiste d'AppleScript. J'espère vous répondre prochainement.
Je ne suis pas seul et il est possible que quelqu'un d'autre vous répondre aussi, ce serait bien.
Cordialement
coderEnSwift
Aamélioration dans la transcription vers swift du code AppleScript
Bonjour monsieur Osset à toutes et à tous
La transcription vers swift est un peu mieux traduite.
Le principe du code reste inchangé.
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
| // ViewController.swift
// Créé par coderEnSwift le 14/08/2017
// Modifié le 15/08/2017
import Cocoa
// Transcription AppleScript -> Swift
func chooseFile(of_type type: String, with_prompt prompt: String) -> String {
var source = ""
let chargementPanel = NSOpenPanel()
chargementPanel.message = prompt
chargementPanel.prompt = "Choisir"
chargementPanel.allowedFileTypes = [type]
if (chargementPanel.runModal() == NSModalResponseOK) {
if let ancienChemin = chargementPanel.url?.path {
source = ancienChemin
}
}
return source
}
// on Prog_Principal(source)
func Prog_Principal(_ source: String) {
if source != "" {
// Rechercher le chemin dossier de source
var index = source.index(before: source.endIndex)
while index > source.startIndex {
if source.substring(with: source.index(before: index)..<index) != "/" {
index = source.index(before: index)
} else {break}
}
let dossierChemin = source.substring(with: source.startIndex..<index)
// Ce dossier est-il en mode lecture-écriture ?
let fileManager = FileManager()
if fileManager.isWritableFile(atPath: dossierChemin) {
// Construire le chemin complet du nouveau fichier source à partir de l'ancien fichier
var index = source.index(before: source.endIndex)
while index > source.startIndex {
if source.substring(with: source.index(before: index)..<index) != "." {
index = source.index(before: index)
} else {index = source.index(before: index);break}
}
let type = source.substring(with: index..<source.endIndex)
// set Nouv_Nom to (text 1 thru ((length of Nom) - 7) of Nom) & "_NEW.fcpxml"
// Ici la transcription n'est pas respecté mais l'affectation est identique
let Nouv_Nom = source.substring(with: source.startIndex..<index) + "_NEW" + type
// Création du nouveau fichier source
let _ = fileManager.createFile(atPath: Nouv_Nom, contents: Data(), attributes: nil)
}
}
}
// end Prog_Principal
class ViewController: NSViewController {
// on run
override func viewDidLoad() {
super.viewDidLoad()
// set source to choose file of type {"fcpxml"} with prompt "Select the file .fcpxml to process :"
let source = chooseFile(of_type: "fcpxml", with_prompt: "Select the file .fcpxml to process :")
// Prog_Principal(source)
Prog_Principal(source)
}
// end run
} |
Cordialement,
codeEnSwift