Analyse AHK
Analyse détaillée du script clavier AutoHotkey
Cette page présente une analyse complète du script AutoHotkey d'Optimot.[1]
Vous pourrez retrouver la liste des pilotes disponibles au téléchargement directement sur la page Windows d'Optimot.
1. Informations générales et licence
Le script commence par une déclaration de licence MIT avec une clause d'exception:
- Licence open-source permettant la modification et distribution
- Exception concernant la disposition du clavier elle-même, qui doit être licenciée séparément
- Auteur: Jean-Philippe Molla (Gepeto)
2. Configuration initiale
#NoEnv ; Recommandé pour les performances et la compatibilité
#SingleInstance, force ; Force une seule instance du script
SendMode Input ; Mode d'envoi recommandé pour sa vitesse et fiabilité
SetWorkingDir %A_ScriptDir% ; Assure un répertoire de travail cohérent
Ces directives configurent l'environnement d'exécution:
#NoEnv
: Améliore la compatibilité en n'accédant pas aux variables d'environnement#SingleInstance, force
: Empêche l'exécution de plusieurs instances du scriptSendMode Input
: Utilise une méthode plus fiable pour envoyer les touchesSetWorkingDir
: Définit le répertoire de travail pour les chemins relatifs
3. Variables globales
enableNotifications := True ; Active les notifications
enableAltLeft := False ; Désactive la modification avec Alt gauche
lockLayer := False ; Désactive le verrouillage sur modificateur
Ces variables contrôlent le comportement de base du script:
enableNotifications
: Affiche des info-bulles lors des changements de coucheenableAltLeft
: Active des caractères spéciaux avec la touche Alt gauchelockLayer
: Maintient la couche active après avoir tapé un caractère
4. Système de localisation
Le script définit plusieurs variables pour les textes affichés dans l'interface:
MenuNotifications := "Notifications"
MenuLockModifier := "Verrouillage sur modificateur"
MenuAltLeftModifier := "Geek sur Alt Gauche"
MenuSuspend := "Mettre en pause"
MenuExit := "Quitter"
Cela facilite la traduction de l'interface sans modifier le code principal.
5. Gestion de la configuration
Le script utilise un fichier INI pour sauvegarder et charger les préférences:
baseName := RegExReplace(A_ScriptName, "\.\w{3}$", "")
iniFile := baseName ".ini"
if FileExist(iniFile) {
; Lecture des paramètres...
}
Paramètres sauvegardés:
ExcludeAppTitles
: Applications où le script est désactivéNotifications
: État des notificationsLockLayer
: État du verrouillage de coucheAltLeftEnabled
: État de la touche Alt gaucheControlLayer
: Disposition de base (AZERTY, QWERTY, par défaut)
6. Structure des couches du clavier
6.1. Table d'indexation
rcindex := {0x29: 1, 0x02: 2, 0x03: 3, ...}
Cette table associe les codes de scan des touches (en hexadécimal) à des indices utilisés dans les tableaux de caractères.
6.2. Couches de contrôle
qwerty_control := ["", "1", "2", "3", "4", ...]
azerty_control := ["", "1", "2", "3", "4", ...]
none_control := ["`", "1", "2", "3", "4", ...]
Ces tableaux définissent les caractères de base pour différentes dispositions lorsqu'on utilise la touche Ctrl.
6.3. Couches principales et modificateurs
none := {"default": [...], "shift": [...], "alt": [...], "altshift": [...]}
Structure des couches:
- Chaque couche est un objet avec quatre états:
default
,shift
,alt
,altshift
- Chaque état contient un tableau de caractères correspondant aux touches du clavier
- Les caractères sont représentés en Unicode (
\u....
)
6.4. Couches spéciales
Le script définit plus de 50 couches spéciales comme:
_0fd36
: Caractères avec accent circonflexe_c763e
: Caractères cyrilliques_c1125
: Flèches et symboles directionnels_a65b9
: Symboles monétaires_97810
: Symboles scientifiques_49b23
: Caractères grecs
À la fin, toutes ces couches sont regroupées dans un objet layers
:
layers := {"none": none, "cir+": _0fd36, "cir-": _d3951, ...}
7. Initialisation et menu système
initMenu()
Cette fonction crée un menu dans la barre d'état système avec:
- Option pour activer/désactiver les notifications
- Option pour le verrouillage de couche
- Option pour activer Alt gauche
- Sous-menu pour choisir la disposition (AZERTY, QWERTY, défaut)
- Options pour suspendre/quitter le script
8. Intercepteurs de touches
$*SC29::ScanCodeProcess()
$*SC02::ScanCodeProcess()
...
$*SC39::ScanCodeProcess()
Fonctionnement:
$
: Empêche le script de se déclencher lui-même*
: Fonctionne même si des modificateurs sont enfoncésSC##
: Code de scan de la touche- Toutes les touches redirigent vers la même fonction de traitement
9. Le modèle de machine à états du script
La fonction ScanCodeProcess()
est conçue selon le principe d'une machine à états finie, ce qui constitue une approche particulièrement élégante pour gérer la complexité des entrées clavier tout en évitant les problèmes de récursivité.
9.1. Principes de la machine à états
Une machine à états finie comporte:
- Des états (ici: couches du clavier, combinaisons de modificateurs)
- Des entrées (ici: touches pressées)
- Des transitions (ici: changements de couche)
- Des actions (ici: envoi de caractères)
ScanCodeProcess()
implémente ce modèle en:
- Capturant l'état actuel (touches enfoncées, modificateurs actifs, couche courante)
- Déterminant l'état suivant (changement de couche ou envoi de caractère)
- Effectuant la transition appropriée
- Revenant à l'état initial si nécessaire
9.2. Mécanismes anti-récursivité
$*SC02::ScanCodeProcess() ; Le préfixe $ empêche la récursivité
Le préfixe $
est fondamental: il indique à AutoHotkey de ne pas déclencher ce raccourci lorsque la touche est envoyée programmatiquement par Send
. Sans cela, le script entrerait dans une boucle infinie:
- L'utilisateur appuie sur "A"
- Le script intercepte cette touche et envoie "B"
- Sans le préfixe
$
, l'envoi de "B" déclencherait à nouveau le script - Le script enverrait un autre caractère
- Et ainsi de suite...
De plus, l'utilisation de SendLevel
dans certaines fonctions permet de contrôler davantage le niveau d'interception, offrant une couche supplémentaire de protection contre la récursivité.
9.3. Structure de contrôle non-linéaire
ScanCodeProcess() {
; Détermination de l'état
if altl && none_altl && enableAltLeft {
; Traitement Alt gauche
return
} else if altgr {
state := "alt"
} else if ctrl {
; Traitement Ctrl
return
}
; Sélection du caractère basée sur l'état actuel
map := layers[lockedLayer]
rcvalues := map[state]
render := rcvalues[index]
; Transition d'état ou action
isSubLayer := RegExMatch(render, "„([a-z]+)"", layer)
if isSubLayer {
SwitchLayer(layer1) ; Transition vers un nouvel état
} else {
SendValue(render) ; Action (envoi du caractère)
if !(lockLayer and capsLock) {
SwitchLayer() ; Retour à l'état initial
}
}
}
Ce code illustre les principes de la machine à états:
- Détermination de l'état: Analyse des modificateurs actifs
- Sélection basée sur l'état: Choix du caractère selon la couche et l'état
- Transitions conditionnelles: Changement de couche si nécessaire
- Actions: Envoi du caractère approprié
- Retour à l'état initial: Réinitialisation de la couche sauf si verrouillée
9.4. Avantages de cette architecture pour un pilote clavier
Évitement des boucles infinies: Le modèle de machine à états prévient naturellement la récursivité.
Gestion élégante de la complexité: Des combinaisons potentiellement infinies de touches et modificateurs sont réduites à un nombre fini d'états.
Modularité: Chaque couche peut être définie indépendamment, facilitant l'extension du script.
Performance: Les décisions sont prises à travers une structure conditionnelle claire plutôt que par des appels récursifs coûteux.
Prévisibilité: Le comportement du script est déterministe, ce qui facilite le débogage.
9.5. Applications de ce modèle à d'autres types de pilotes
Cette approche par machine à états peut être transposée à d'autres contextes:
- Systèmes de saisie complexes: Méthodes d'entrée asiatiques (IME) où plusieurs frappes produisent un caractère
- Interfaces gestuelles: Traduction de séquences de mouvements en actions
- Périphériques adaptés: Interfaces d'accessibilité pour personnes en situation de handicap
- Émulation matérielle: Conversion entre différents protocoles ou formats d'entrée
Dans tous ces cas, la machine à états offre un cadre conceptuel robuste pour gérer des interactions complexes tout en évitant les effets secondaires indésirables comme la récursivité ou les états incohérents.
10. Fonctions principales
10.1. GetValue et SendValue
GetValue(value) {
isUnicode := RegExMatch(value, "^\\u([a-zA-Z0-9]+)$", hex)
if isUnicode {
value := "U+" hex1
if hex1 = 0008 {
SendLevel, 1
Send, {Backspace}
value :=
}
}
Return, value
}
SendValue(value) {
foundUnicode := InStr(value, "\u")
if foundUnicode {
values := StrSplit(value, "\u")
for k, v in values {
if (v != "") {
if v = 0008 {
SendLevel, 1
Send, {Backspace}
} else {
v := "U+" v
Send, {%v%}
}
}
}
} else {
Send, {%value%}
}
}
Ces fonctions:
- Convertissent les codes Unicode (
\u....
) en format utilisable par AutoHotkey - Gèrent les cas spéciaux comme la touche Retour arrière
- Envoient les caractères au système
10.2. SwitchLayer
SwitchLayer(layer = "") {
global layers, lockedLayer
if !layer or !layers.HasKey(layer) {
lockedLayer := "none"
} else {
lockedLayer := layer
ShowTrayTip(layer)
}
}
Cette fonction:
- Change la couche active du clavier
- Réinitialise à la couche par défaut si aucune couche n'est spécifiée
- Affiche une notification du changement de couche
10.3. ScanCodeProcess
C'est la fonction principale qui traite les touches pressées:
ScanCodeProcess() {
; Détermine quelle touche a été pressée
; Vérifie les modificateurs actifs (Shift, Alt, Ctrl)
; Sélectionne la couche et l'état appropriés
; Envoie le caractère correspondant ou change de couche
}
Étapes de traitement:
- Identifie la touche pressée et les modificateurs actifs
- Gère les cas spéciaux (touche Windows, Ctrl)
- Détermine l'état (default, shift, alt, altshift)
- Consulte la couche active pour trouver le caractère correspondant
- Vérifie si le caractère est un changement de couche
- Envoie le caractère ou change de couche
- Réinitialise la couche si nécessaire
11. Gestion des touches spéciales
$Esc:: ; SC01
$End:: ; SC4f
$Home:: ; SC47
$Delete:: ; SC53
$Backspace:: ; SC0e
key := SubStr(A_ThisHotkey, 2) ; removing $
if (key != "Delete" and key != "Backspace") {
SwitchLayer()
}
SendLevel, 1
Send, {%key%}
return
Ces touches ont un comportement spécial:
- Échap, Fin, Début: Réinitialisent la couche active puis effectuent leur action normale
- Suppr, Retour arrière: Effectuent uniquement leur action normale sans réinitialiser la couche
12. Workflow complet
Initialisation:
- Chargement de la configuration depuis le fichier INI
- Définition des couches et des correspondances de touches
- Création du menu système
Surveillance des touches:
- Toutes les touches sont interceptées et redirigées vers
ScanCodeProcess()
- Toutes les touches sont interceptées et redirigées vers
Traitement d'une touche:
- Identification de la touche et des modificateurs
- Détermination de la couche et de l'état
- Récupération du caractère correspondant
- Envoi du caractère ou changement de couche
Gestion des options:
- Le menu système permet de modifier le comportement
- Les options sont sauvegardées dans le fichier INI
13. Points forts et cas d'utilisation
13.1. Fonctionnalités avancées
- Système multi-couches: Accès à des milliers de caractères spéciaux
- Couches contextuelles: Changement temporaire ou permanent de couche
- Support multiple: Compatible avec QWERTY, AZERTY et autres dispositions
- Notifications visuelles: Info-bulles lors des changements de couche
- Exclusion d'applications: Désactivation automatique dans certains programmes
13.2. Cas d'utilisation
Ce script est particulièrement utile pour:
- Scientifiques: Accès à de nombreux symboles mathématiques et scientifiques
- Linguistes: Saisie de caractères phonétiques et diacritiques
- Traducteurs: Utilisation de plusieurs alphabets (latin, grec, cyrillique)
- Développeurs: Saisie rapide de symboles spéciaux pour la programmation
- Typographes: Utilisation de symboles typographiques avancés
14. Extensibilité
Le script est conçu pour être facilement extensible:
- Ajout de nouvelles couches en définissant de nouveaux tableaux
- Modification des correspondances de touches
- Personnalisation des options et du comportement
Cette analyse couvre les aspects essentiels du script AutoHotkey pour l'émulation d'une disposition de clavier personnalisée, expliquant sa structure, son fonctionnement et ses cas d'utilisation.