
elle améliore la convivialité et la commodité du langage en sacrifiant la rétrocompatibilité
AutoHotkey v2 vise à améliorer la convivialité et la commodité du langage et de l'ensemble des commandes en sacrifiant la rétrocompatibilité. Ainsi, les scripts écrits pour la v1 ne fonctionneront généralement pas sans modifications sur la v2. La syntaxe est globalement plus cohérente, avec beaucoup moins de bizarreries et de pièges, et de nombreuses autres améliorations ont été apportées.
AutoHotkey est un langage de script gratuit et open source pour Windows qui permet aux utilisateurs de créer facilement des scripts, petits ou complexes, pour toutes sortes de tâches telles que : remplissage de formulaires, clics automatiques, macros. L'objectif initial est de fournir des raccourcis clavier faciles ou hotkeys, une macro-création rapide et une automatisation logicielle permettant aux utilisateurs de tous niveaux de compétences informatiques d'automatiser des tâches répétitives dans n'importe quelle application Windows. Les interfaces utilisateur peuvent facilement être étendues ou modifiées par AutoHotkey.
AutoHotkey ne fait rien par lui-même ; il a besoin d'un script pour lui dire quoi faire. Un script est simplement un fichier de texte brut avec l'extension .ahk contenant des instructions pour le programme, comme un fichier de configuration, mais beaucoup plus puissant. Un script peut se contenter d'exécuter une seule action et de quitter le programme, mais la plupart des scripts définissent un certain nombre de touches de raccourci, chacune d'entre elles étant suivie d'une ou plusieurs actions à exécuter lorsque la touche de raccourci est enfoncée.
#z::Run "https://www.autohotkey.com" ; Win+Z
Code : | Sélectionner tout |
1 2 3 4 5 6 7 | ^!n:: ; Ctrl+Alt+N { if WinExist("Untitled - Notepad") WinActivate else Run "Notepad" } |
Voici, ci-dessous, quelques améliorations qu’apporte la version 2 d’AutoHotkey
Suppression de la syntaxe héritée
Suppression des affectations littérales : var = valeurSuppression de toutes les instructions If héritées, ne laissant que l'expression if, qui ne nécessite jamais de parenthèses (mais les autorise, comme dans toute expression).
Suppression de la « syntaxe de commande ». Il n'y a pas de « commandes », seulement des instructions d'appel de fonction, qui sont juste des appels de fonction ou de méthode sans parenthèses. Cela signifie que :
- Toutes les anciennes commandes sont désormais des fonctions (à l'exception des instructions de flux de contrôle) ;
- Toutes les fonctions peuvent être appelées sans parenthèses si la valeur de retour n'est pas nécessaire (mais comme auparavant, les parenthèses ne peuvent pas être omises pour les appels dans une expression) ;
- Tous les paramètres sont des expressions, donc tout le texte est "cité" et les virgules ne doivent jamais être échappées. Actuellement, cela exclut quelques directives (qui ne sont ni des commandes ni des fonctions) ;
- Les paramètres sont les mêmes indépendamment des parenthèses ; c'est-à-dire qu'il n'y a pas de variable de sortie pour la valeur de retour, elle est donc rejetée si les parenthèses sont omises ;
- Les références normales à des variables ne sont jamais entourées de signes de pourcentage (sauf avec #Include et #DllLoad). Utilisez la concaténation ou le format pour inclure les variables dans le texte ;
- Il n'y a pas de virgule entre le nom de la fonction et les paramètres, donc MouseGetPos(, y) = MouseGetPos, y (x est omis). Un espace ou une tabulation est nécessaire pour plus de clarté. Par souci de cohérence, les directives suivent également la nouvelle convention (il ne doit pas y avoir de virgule entre le nom de la directive et le paramètre) ;
- Les déclarations d'appel de méthode (appels de méthode qui omettent les parenthèses) sont limitées à une simple variable suivie d'un ou plusieurs identifiants séparés par des points, comme par exemple MaVar.MaPropriété.MaMéthode "Chaîne à passer".
Étiquettes des touches de raccourci et des chaînes de raccourci
Les touches de raccourci et les chaînes de raccourci non automatiques ne sont plus des étiquettes ; elles définissent (automatiquement) une fonction. Pour les raccourcis de plusieurs lignes, utilisez des accolades pour entourer le corps du raccourci au lieu de le terminer par return (qui est impliqué par l'accolade de fin). Pour permettre à un raccourci d'être appelé explicitement, spécifiez funcName(ThisHotkey) entre les : : et { - cela peut également être fait dans la v1.1.20+, mais il y a maintenant un paramètre. Lorsque la définition de la fonction n'est pas explicite, le paramètre est nommé ThisHotkey.
Noms
Les noms de fonctions et de variables sont maintenant placés dans un espace de noms partagé. Chaque définition de fonction crée une constante (variable en lecture seule) dans la portée actuelle.
Pour appeler une fonction lorsque tout ce que vous avez est un nom de fonction (chaîne de caractères), utilisez d'abord un double-deref pour résoudre le nom en une variable et récupérer sa valeur (l'objet fonction). %myVar%() effectue maintenant un double déréférencement, puis appelle le résultat, ce qui équivaut à f := %myVar%, f().
Évitez autant que possible de manipuler les fonctions par leur nom (chaîne de caractères) ; utilisez plutôt des références. Les noms ne peuvent pas commencer par un chiffre et ne peuvent pas contenir les caractères suivants qui étaient auparavant autorisés : @ # $. Seuls les lettres, les chiffres, les traits de soulignement et les caractères non ASCII sont autorisés.
Utilisez MaFunc à la place de Func("MaFunc").
Utilisez MyFunc à la place de "MyFunc" lorsque vous passez la fonction à une fonction intégrée telle que SetTimer ou Hotkey. Le passage d'un nom (chaîne de caractères) n'est plus pris en charge.
Utilisez myVar() à la place de %myVar%() lorsque vous appelez une fonction par valeur.
Mots réservés : Les mots-clés de déclaration et les noms des instructions de flux de contrôle ne peuvent pas être utilisés comme noms de variables, de fonctions ou de classes. Cela inclut :
local, global, static, if, else, loop, for, while, until, break, continue, goto, return, switch, case, try, catch, finally et throw.
Mots réservés : as, and, contains, false, in, is, IsSet, not, or, super, true, unset
Ces mots sont réservés à une utilisation future ou à d'autres fins spécifiques, et ne sont pas autorisés comme noms de variables ou de fonctions, même s'ils ne sont pas ambigus. Il s'agit principalement d'un souci de cohérence : dans la v1, and := 1 était autorisé sur sa propre ligne, mais (and := 1) ne fonctionnait pas.
Les mots listés ci-dessus sont autorisés comme noms de propriétés. Les noms de propriétés sont généralement précédés de ., ce qui empêche le mot d'être interprété comme un opérateur. En revanche, les mots-clés ne sont jamais interprétés comme des noms de variables ou de fonctions dans une expression. Par exemple, not(x) est équivalent à not (x) ou (not x).
Un certain nombre de classes sont prédéfinies, réservant effectivement ces noms de variables globales de la même manière qu'une classe définie par l'utilisateur. (Toutefois, les modifications de la portée décrites ci-dessous atténuent la plupart des problèmes qui en découlent).
Portée
Les variables super-globales ont été supprimées (à l'exception des variables intégrées, qui ne sont pas tout à fait les mêmes puisqu'elles ne peuvent pas être redéclarées. Dans une fonction assumée-locale, si un nom donné n'est pas utilisé dans une déclaration ou comme cible d'une affectation non dynamique ou de l'opérateur de référence (&), il peut être résolu vers une variable globale existante.
En d'autres termes :
- Les fonctions peuvent désormais lire les variables globales sans les déclarer ;
- Les fonctions qui n'ont pas de déclaration globale ne peuvent pas modifier directement les variables globales (éliminant ainsi une source d'effets secondaires involontaires) ;
- L'ajout d'une nouvelle classe au script est beaucoup moins susceptible d'affecter le comportement d'une fonction existante, car les classes ne sont pas super-globales ;
- Le mot-clé global est actuellement redondant lorsqu'il est utilisé dans une portée globale, mais il peut être utilisé pour plus de clarté. Les variables déclarées de cette façon sont maintenant beaucoup moins susceptibles d'entrer en conflit avec les variables locales (comme lors de la combinaison de scripts manuellement ou avec #Include), car elles ne sont pas super-globales. D'un autre côté, une certaine commodité est perdue ;
- Les déclarations ne sont généralement pas aussi nécessaires.
Variables
Les variables statiques locales sont initialisées si et quand l'exécution les atteint, au lieu d'être exécutées dans un ordre linéaire avant le début de la section d'auto-exécution. Chaque initialisation n'a aucun effet la deuxième fois qu'elle est atteinte. Les déclarations multiples sont autorisées et peuvent s'exécuter pour la même variable à des moments différents. Les avantages sont multiples :
- Lorsqu'un initialisateur statique appelle d'autres fonctions avec des variables statiques, il y a moins de risque que les initialisateurs n'aient pas encore été exécutés en raison de l'ordre des définitions de fonction ;
- Comme la fonction a été appelée, les paramètres, A_ThisFunc et les fermetures sont disponibles (ils ne l'étaient pas auparavant) ;
- Une variable statique peut être initialisée de manière conditionnelle, ce qui ajoute de la flexibilité, tout en ne s'exécutant qu'une seule fois sans avoir besoin de if IsSet() ;
- Comme il peut y avoir plusieurs initialisateurs pour une seule variable statique, les affectations composées telles que static x += 1 sont autorisées. (Cette modification a permis de réduire marginalement la taille du code, car elle était déjà autorisée par local et global).
- Remarque : static init := somefunction() ne peut plus être utilisé pour exécuter automatiquement une fonction. Cependant, puisque les sous-routines basées sur les étiquettes et les retours peuvent maintenant être complètement évitées, la section d'auto-exécution peut couvrir tout le script.
- Déclarer une variable avec local ne fait plus que la fonction assume-global.
Les doubles-références sont maintenant plus cohérentes avec les variables résolues au moment du chargement, et ne sont plus capables de créer de nouvelles variables. Cela permet d'éviter certaines incohérences et des points de confusion courants.
Les doubles déréférencements qui échouent pour une raison quelconque provoquent maintenant une erreur. Auparavant, les cas avec un nom invalide produisaient silencieusement une chaîne vide, tandis que les autres cas créaient et retournaient une variable vide.
Expressions
Les chaînes littérales citées peuvent être écrites avec des guillemets "doubles" ou "simples", mais doivent commencer et se terminer par la même marque. Les guillemets littéraux sont écrits en faisant précéder la marque d'un caractère d'échappement - `" ou `' - ou en utilisant le type de guillemet opposé : '"42" est la réponse'. Doubler les guillemets n'a pas de signification particulière, et provoque une erreur puisque l'auto-concat requiert un espace.
Les opérateurs &&, ||, et et ou donnent la valeur qui a déterminé le résultat, de manière similaire à JavaScript et Lua. Par exemple, "" ou default donne default au lieu de 1. Les scripts qui nécessitent une valeur booléenne pure (0 ou 1) peuvent utiliser quelque chose comme ! !(x ou y) ou (x ou y) ? 1 : 0.
L'auto-concat requiert maintenant au moins un espace ou une tabulation dans tous les cas (la documentation de la v1 dit qu'il "devrait" y avoir un espace).
Le résultat d'une expression à plusieurs énoncés telle que x(), [C=AutoHotkey]y()[C=AutoHotkey] est la dernière sous-expression (la plus à droite) au lieu de la première sous-expression (la plus à gauche). Dans les versions v1 et v2, les sous-expressions sont évaluées dans l'ordre de gauche à droite.
Les égaux après une virgule ne sont plus des affectations : y=z dans x:=y, y=z est une comparaison inefficace au lieu d'une affectation.
:= += -= *= /= ++ -- ont un comportement cohérent, qu'ils soient utilisés seuls ou combinés avec d'autres opérateurs, comme avec x := y, y += 2. Auparavant, il y avait des différences de comportement lorsqu'une erreur se produisait dans l'expression ou qu'une valeur vide était utilisée dans une opération mathématique.
!= est maintenant toujours insensible à la casse, comme =, tandis que !== a été ajouté comme contrepartie de ==.
<> a été supprimé.
// lève maintenant une exception si on lui donne un nombre à virgule flottante. Auparavant, les résultats étaient incohérents entre les flottants négatifs et les entiers négatifs.
|, ^, &, << et >> lèvent maintenant une exception si on leur donne un nombre à virgule flottante, au lieu de les tronquer en entier. La notation scientifique peut être utilisée sans point décimal (mais produit tout de même un nombre à virgule flottante). La notation scientifique est également supportée lorsque les chaînes numériques sont converties en nombres entiers (par exemple, "1e3" est interprété comme 1000 au lieu de 1).
Les appels de fonction permettent maintenant pratiquement n'importe quelle sous-expression pour spécifier la fonction à appeler, à condition qu'il n'y ait pas d'espace ou de tabulation avant la parenthèse ouverte de la liste des paramètres. Par exemple, MyFunc() appelle la valeur MyFunc, qu'il s'agisse du nom réel de la fonction ou d'une variable contenant un objet fonction, et (a?b:c)() appelle soit b, soit c, en fonction de a. Notez que x.y() est toujours un appel de méthode équivalent à (x.y)(x), mais que a[i]() est maintenant équivalent à (a[i])().
Les double-derefs autorisent maintenant presque toutes les expressions (pas seulement les variables) comme source du nom de la variable. La syntaxe double déréférence est désormais également utilisée pour déréférencer les VarRefs, comme ref := &var, value := %ref%.
Les expressions funcName[""]() et funcName.() n'appellent plus une fonction par son nom. L'omission du nom de la méthode comme dans .() provoque désormais un message d'erreur au moment du chargement. Les fonctions doivent être appelées ou manipulées par référence, et non par nom.
[C=AutoHotkey]var :=[C=AutoHotkey] sans valeur rest traité comme une erreur au moment du chargement. Dans la v1, il était équivalent à var := "", mais échouait silencieusement s'il était combiné à une autre expression - par exemple : x :=, y :=.
Lorsqu'une chaîne littérale est suivie d'un opérateur unaire/binaire ambigu, une erreur est signalée au moment du chargement. Par exemple, new counter: ++counter est probablement censé incrémenter et afficher le compteur, mais techniquement, il s'agit d'une addition invalide et d'un plus unaire.
word++ et word-- ne sont plus des expressions, puisque wordpeut être une fonction définie par l'utilisateur (et ++/- peut être suivi d'une expression qui produit une référence à une variable). Pour écrire une expression autonome de post-incrémentation ou de post-décrémentation, il faut soit omettre l'espace entre la variable et l'opérateur, soit mettre la variable ou l'expression entre parenthèses.
word ? x : y est toujours une expression ternaire, mais les cas plus complexes commençant par un mot, comme word1 word2 ? x : y, sont toujours interprétés comme des appels de fonction à word1 (même si une telle fonction n'existe pas). Pour écrire une expression ternaire autonome avec une condition complexe, mettez la condition entre parenthèses.
Le nouvel opérateur is, tel que dans x is y, peut être utilisé pour vérifier si la valeur x est une instance de la classe y, où y doit être un Objet avec une propriété prototype (c'est-à-dire une Classe). Cela inclut les valeurs primitives, comme dans x is Integer (qui est strictement une vérification de type, alors que IsInteger(x) vérifie une conversion potentielle).
Les mots-clés contains et in sont réserv...
La fin de cet article est réservée aux abonnés. Soutenez le Club Developpez.com en prenant un abonnement pour que nous puissions continuer à vous proposer des publications.