Pages

24 juil. 2008

Levenshtein distance

Par Gary de la liste applescript-users@lists.apple.com

La distance de Levenshtein est égale au nombre minimal de caractères qu'il faut supprimer, insérer, ou remplacer pour passer d’une chaîne à l’autre.

on LEVENSHTEIN_DISTANCE(thisText, thatText)
set phpScr to "$lev=levenshtein('" & thisText & "', '" & thatText & "');echo $lev;"
set shCmdStub to "php -r "
set sh to shCmdStub & (quoted form of phpScr)
set res to do shell script sh
end LEVENSHTEIN_DISTANCE


LEVENSHTEIN_DISTANCE("the", "they") --> 1
LEVENSHTEIN_DISTANCE("hello world", "hell worm") --> 3

>>Ouvrir le script dans l'éditeur

En savoir plus ...

13 juil. 2008

Les objets 2/2

"La documentation officielle est claire et traite des variables globales, locales et des propriétés comme des variantes de variables. Du point de vue de la technique, rien à redire... Mais essayons un peu de nous extraire un moment de l'écriture informatique et de nous demander ce que pouvait bien avoir dans la tête l'équipe de developpement d'AppleScript (spéculons légèrement, à défaut de pouvoir le faire sauvagement).

Il est possible que la confrontation avec Hypercard que je vais faire soit historiquement erronée, mais l'hypothèse semble toutefois fonctionner (même à tort :-)). Le rêve de Bill Atkinson était que les Hypercardiens échangent leurs piles, à savoir des fragments de connaissance; d'un point de vue informatique, un échange de données. L'échange de fonctionnalités se trouvant au fond du panier, d'un point de vue technique, était secondaire, hors les fonctions externes (justement). Donc, chacun écrit ses routines en Hypertalk et les agglutine à la queu leu-leu dans les scripts. Comment ces routines entretiennent-elles des relations les unes avec les autres ? On n'en sait que couic, hors l'auteur (et encore, pendant quelques jours... après il s'exerce, lui aussi, à l'herméneutique). Les fonctions externes possèdent par contre cette qualité de pouvoir être échangées, comme fonctionnalités, et possèdent une description des points d'entrée et de sortie qui les rendent utilisables dans des contexte variés. Mais elles ne sont pas au coeur du système.

C'est la différence avec AppleScript. Il est possible qu'historiquement les premiers AppleScripteurs furent les HyperCardiens. Force de l'inertie, la coutume perdura, qui fit construire les scripts AS autour des routines (les handlers). Puisque cela fonctionne bien ainsi, pourquoi aller voir plus loin. Je ne crois pas que cela corresponde pourtant au rêve de l'équipe de developpement d'AppleScript (rêve spéculé, je le répète), puisque l'objet script (nourri de propriétés, qui se distinguent sous cet angle des autres variables) offre un supplément de puissance étonnant à AppleScript, permettant l'échange de fragments de fonctionnalités informatique de manière très propre.

L'échange n'est pas un élément de syntaxe, et la documentation n'a pas vocation de donner dans les humanités, mais le pourquoi des dispositifs fournis est peut-être quand même à rechercher chez des auteurs en chair et en os. Certes, l'objet script apporte une plus grande lisibilité des pages de scripts, le travail est mieux structuré, mais ce n'est pas là, à mes yeux, le plus important. Cela suppose surtout une modification de comportement, hors la technique immédiate. Nous n'avons plus seulement un scripteur qui écrit face à un utilisateur potentiel, mais un jeu à trois personnes mettant en scène le scripteur, l'utilisateur et un autre scripteur virtuel, dont le premier tient compte dans son écriture de script même (mais comme il est virtuel, on n'en tient évidemment pas compte actuellement, c'est le problème). Une modification d'approche, plus qu'un complément de savoir.

Je m'explique: mettons que quelqu'un écrive un gestionnaire de plug-in pour Photoshop. Il va créer une interface permettant
d'activer ou de désactiver des éléments d'une liste affichée représentant ces plug-in dont la classe de base sera "fichier", l'activation et la désactivation consistant à déplacer des fichiers du finder d'un dossier à un autre. L'interface prête au générique, puisque c'est un cas de figure fréquent, et la manipulation de fichiers tout autant, des scripts enfants pouvant varier selon la nature des fichiers manipulés (avec les incidences sur les menus)... Un vrai magasin de fonctions ou tout le monde peut se servir (pas par copier/coller... mais par "tell script bidule" ce qui rend dynamique tout le système...) pour peu que tout soit assez bien segmenté et rendu autonome. Cela signifie ensuite une diffusion publique et sélective de certaines déclarations de scripts, de certaines propriétés qu'ils contiennent (puisque l'on peut accéder à un état des propriétés de script sans exécution de commande particulière autre que "get") et de diverses commandes susceptibles d'être publiques. C'est-à-dire rendre publique tous les points d'entrées et de sorties autorisés sous une forme que l'on pourrait nommer... dictionnaire...on les aime chez les autres (les applications) mais les récusons chez nous, pratiquants du script,...c'est quand même bizarre.

Bref, ce travail fait avec des objets scripts autorise ensuite un petit malin qui aurait l'intention de faire un gestionnaire de
compléments de pilotage de s'épargner beaucoup de travail[...]Sans les propriétés, cette manière de voir les choses ne serait pas possible."

Gwénaël Le Dréan le 12/11/2001 sur la liste AppleScript francophone

12 juil. 2008

Les objets 1/2

"Le script principal, celui que l'on écrit de prime abord sur une feuille vierge, est un objet de type script, à l'égal de tout autre.
La seul différence qui le différencie d'un autre est que sa déclaration (script premier ... end script) est implicite, tout comme sa commande run d'exécution. Cette omission est justifiée (mais pourrait aussi justifier sa désignation sous un nom particulier, comme superscript) par le bon sens... mais les effets induits par cette omission ont finalement éroder le sens même. Ainsi, il n'est plus fait de différence, dans la pratique courante, entre un script et ce qu'il serait préférable de nommer feuille de script, feuillet de script, formulaire de script, ou autre nom pour désigner le support physique du script et le distinguer de ce qu'il contient.

Le symptome principal de cette dérive est que l'on a l'habitude de se donner les uns les autres des superscripts (le script principal, donc) et/ou/avec des routines (ou méthodes, bref les handlers). Si le secret bien gardé d'Apple est AppleScript, le secret bien gardé d'AppleScript est l'objet de type script.

La première caractéristique d'un objet script est d'être un objet. Partant de là, la notion de Propriété n'est pas essentiellement
(quoique je reconnaisse que la documentation officielle prête légèrement (par l'emploi du mot variable, qui n'est pourtant pas faux, d'un point de vue technique) à confusion) la différence de pérennité de son état par rapport aux variables globales et locales. Cette pérennité est liée en fait, nécessairement, à la définition du mot Objet. La Propriété n'est pas essentiellement une facilité, comme outillage de programmation de mémorisation de valeurs comme les variables locales et globales, mais bien une nécessité existentielle pour un objet. Un objet "pomme", dont la propriété couleur possèderait une valeur "rouge" et la propriété grosseur possèderait une valeur "petite" qui disparaitraient toutes deux après l'exécution d'un script, perdrait, pour autant que le nombre de propriétés le caractérisant soit relativement complet, sa caractéristique d'objet reconnaissable en tant que pomme, parmi tous autres objets. La propriété ne dépend donc pas de l'exécution d'un script.

La nature de la Propriété, n'est pas inclue, à mon sens, dans une interrogation du "qu'est-ce que cela fait", mais du "qu'est-ce que cela est". C'est-à-dire que je tente, en scriptant, de décrire un espace encombré d'objets (potentiels ou réels) et non d'actions (on comprend, du coup, pourquoi une propriété est accessible de l'"extérieur"; ce qui compte est que l'objet existe).

Les actions porteront, entre autre, sur cet espace et ces objets reconnus, en modifiant notamment les valeurs des propriétés
des objets. La date de dernière sauvegarde est l'une des propriétés de l'objet backup, ainsi même que l'on peut se définir en français les propriétés nécessaires pour caractériser ce mot backup (ce qui pose vraiment la question de la définition d'un objet, en général, puisque je prend volontairement comme exemple ce qui n'est associé, en principe, qu'à une suite d'actions :)).

Je semble peut-être couper les cheveux en quatre, mais je ne le crois pas,parceque l'échange d'objets seraient autrement plus bénéfiques que l'échange de routines. Or, si nous examinons généralement attentivement le dispositif des objets que l'on manipule par script dans les applications scriptables, il est moins fréquent d'être aussi bien disposé avec les objets que l'on pourrait manipuler dans le script même, pour peu qu'on définisse justement comme objets au préalable ce que l'on triture empiriquement.

L'une des grosses critiques faite à Hypercard, qui se présentait comme application objet, était qu'il était bridé, que l'on ne pouvait pas créer (inventer) d'objets. Cette contrainte est levée avec AppleScript, en grande partie grace aux Propriétés."

Gwénaël Le Dréan le 10/11/2001 sur la liste AppleScript francophone

Bricolage et conception

"Le bricolage, consiste à partir d'une collection finie d'outils et de matériaux, à chercher comment les agencer pour réaliser quelque chose. L'idée émerge donc peu à peu des essais et de la réalisation. Le bricolage consiste à faire avec ce qu'on a sous la main, et le bricoleur collectionne volontiers des trucs et des machins qui "pourront toujours servir".
La conception consiste, au contraire, à partir d'une idée, à en faire un modèle ou un plan sans tenir compte de la disponibilité immédiate des matériaux et des outils. Le concepteur définit ses besoins puis se met en quête de ce qu'il lui faut. Il peut naturellement être amené dans la logique de sa démarche, à créer ou faire créer des outils ou des matériaux qui n'existent pas."

Laurent Sebilleau d'après Claude Levi-Strauss

6 juil. 2008

DataBase (5/5)

on read_file(thePath)
try
set thePath to thePath as string
set idFile to open for access file thePath
set fileData to read idFile as list
close access idFile
on error errMsg number errNum
close access file thePath
return false
end try
return fileData
end read_file

on write_file(theText, thePath)
try
set thePath to thePath as string
set idFile to open for access file thePath with write permission
write theText to idFile starting at 0 as list
close access id_file
return true
on error
close access file thePath
return false
end try
end write_file

-- Check the entry in a dialog box who must not be empty
on checkEmptyDialog(theText, defaultAnswer)
repeat
set theAnswer to text returned of (display dialog theText default answer defaultAnswer with icon 1)
if (count theAnswer) > 0 then exit repeat
end repeat
return theAnswer
end checkEmptyDialog

-- Return the number of one item in a list
on ItemNumber(theItem, theList)
repeat with NumItem from 1 to count theList
if theItem = item NumItem of theList then return NumItem
end repeat
return 0
end ItemNumber

on ASTID(x) -- set  item delimiter to x
set AppleScript's text item delimiters to x
end ASTID

>>Ouvrir le script dans l'éditeur

DataBase (4/5)

on createCard(a, b, c, d, e)
script
property item1 : a -- Auteur
property item2 : b -- Titre
property item3 : c -- Sujet
property item4 : d -- Edition
property item5 : e -- critere tri
on getInfos()
if item5 is "Auteur" then
return item1 & " • " & item2 & " • " & item3 & " • " & item4
else if item5 is "Titre" then
return item2 & " • " & item1 & " • " & item3 & " • " & item4
else if item5 is "Sujet" then
return item3 & " • " & item1 & " • " & item2 & " • " & item4
else
return item4 & " • " & item1 & " • " & item2 & " • " & item3
end if
end getInfos
on getInfos2()
if item5 is "Auteur" then
return item1
else if item5 is "Titre" then
return item2
else if item5 is "Sujet" then
return item3
else
return item4
end if
end getInfos2
end script
end createCard

>>Ouvrir le script dans l'éditeur

DataBase (3/5)

on newCard()
set item1 to text returned of (display dialog "Auteur :" default answer "" with icon 1)
set item2 to text returned of (display dialog "Titre :" default answer "" with icon 1)
set item3 to text returned of (display dialog "Sujet :" default answer "" with icon 1)
set item4 to text returned of (display dialog "Edition :" default answer "" with icon 1)
set item5 to "Auteur" -- tri par defaut
set the end of allCards to createCard(item1, item2, item3, item4, item5)
end newCard

>>Ouvrir le script dans l'éditeur

DataBase (2/5)

on CardList()
if allCards = {} then
display dialog "DataBase empty." with icon 0
return {}
end if
set btn to button returned of (display dialog "DataBase" buttons {"Search...", "Show cards"} default button 2 with icon 1)
set SortBy to choose from list {"Auteur", "Titre", "Sujet", "Edition"} with prompt "Sort by :" cancel button name "Retour"
if SortBy is false then return
set SortBy to item 1 of SortBy
set listeInfos to {}
if btn is "Show cards" then
-- afficher les cartes
repeat with theCard in allCards
set (item5 of theCard) to SortBy
copy (getInfos() of theCard) to the end of listeInfos
end repeat
set cardToDelete to (choose from list listeInfos with prompt "DataBase" OK button name "Delete" cancel button name "Back")
-- effacer une carte
if cardToDelete is not false then
set cardToDelete to item 1 of cardToDelete
ASTID(" • ")
set newCardList to {}
repeat with theCard in allCards
if (text item 1 of cardToDelete item1 of theCard) ¬
or (text item 2 of cardToDelete item2 of theCard) ¬
or (text item 3 of cardToDelete item3 of theCard) ¬
or (text item 4 of cardToDelete item4 of theCard) ¬
then
copy theCard to the end of newCardList
end if
end repeat
ASTID("")
set allCards to newCardList
end if
else -- chercher une carte
set stringToSearch to checkEmptyDialog("Search " & SortBy & " :", "")
repeat with theCard in allCards
set (item5 of theCard) to SortBy
if stringToSearch is in (getInfos2() of theCard) then
copy (getInfos() of theCard) to the end of listeInfos
end if
end repeat
if listeInfos is {} then
display dialog myQuote & stringToSearch & myQuote & "is not found." buttons {"•"} default button 1 with icon 0
else
choose from list listeInfos with prompt "Result :"
end if
end if
end CardList


>>Ouvrir le script dans l'éditeur