- PromptStore/Frontmatter : un prompt = un fichier Markdown, en-tête au sous-ensemble strict du document d'architecture (§7), écriture UTF-8 - VariableEngine : variables typées + automatiques (selection, clipboard, date, app, cursor), résolution et profils de destination - Injector/ClipboardGuard : focus capturé/rendu, presse-papiers sauvegardé puis restauré conditionnellement, aucun envoi automatique par défaut - Search : classement flou insensible aux accents, pondéré par l'usage - UsageStats (usage.json), HotkeyManager (conflits signalés, jamais muets) - Settings : config.ini + profils par IA (claude, chatgpt, qwen, terminal…) - PromptKey.ahk : tray, instance unique, capture du contexte, surveillance de la bibliothèque, installation du pack au premier lancement
136 lines
6.6 KiB
AutoHotkey
136 lines
6.6 KiB
AutoHotkey
; Settings.ahk — Paramètres de PromptKey (config.ini) et profils de destination.
|
|
; Architecture §12 (profils) et §17.1 (paramètres en INI).
|
|
|
|
class Settings {
|
|
Path := ""
|
|
LibraryPath := ""
|
|
PickerHotkey := "^!Space"
|
|
ManagerHotkey := "^!m"
|
|
NewHotkey := "^!n"
|
|
ReplayHotkey := "^!v"
|
|
Method := "clipboard" ; clipboard | sendtext
|
|
PasteDelayMs := 150
|
|
RestoreDelayMs := 1500
|
|
SendAfterDelayMs := 800
|
|
ExternalEditor := "" ; vide = éditeur par défaut de Windows pour .md
|
|
Profiles := Map() ; nom -> Map(preambule, postambule, methode, sendAfter, appMatch, titreMatch)
|
|
|
|
__New(configPath) {
|
|
this.Path := configPath
|
|
this.Load()
|
|
}
|
|
|
|
Load() {
|
|
ini := this.Path
|
|
if FileExist(ini) {
|
|
this.LibraryPath := IniRead(ini, "General", "LibraryPath", "")
|
|
this.PickerHotkey := IniRead(ini, "General", "PickerHotkey", this.PickerHotkey)
|
|
this.ManagerHotkey := IniRead(ini, "General", "ManagerHotkey", this.ManagerHotkey)
|
|
this.NewHotkey := IniRead(ini, "General", "NewHotkey", this.NewHotkey)
|
|
this.ReplayHotkey := IniRead(ini, "General", "ReplayHotkey", this.ReplayHotkey)
|
|
this.Method := IniRead(ini, "Injection", "Method", this.Method)
|
|
this.PasteDelayMs := Integer(IniRead(ini, "Injection", "PasteDelayMs", this.PasteDelayMs))
|
|
this.RestoreDelayMs := Integer(IniRead(ini, "Injection", "RestoreDelayMs", this.RestoreDelayMs))
|
|
this.SendAfterDelayMs := Integer(IniRead(ini, "Injection", "SendAfterDelayMs", this.SendAfterDelayMs))
|
|
this.ExternalEditor := IniRead(ini, "Editeur", "ExternalEditor", "")
|
|
}
|
|
if (this.LibraryPath = "" || !DirExist(this.LibraryPath)) {
|
|
; Mode portable : dossier Bibliothèque à côté du script. Sinon Documents\PromptKey.
|
|
portable := A_ScriptDir "\Bibliothèque"
|
|
this.LibraryPath := DirExist(portable) ? portable : A_MyDocuments "\PromptKey\Bibliothèque"
|
|
}
|
|
DirCreate(this.LibraryPath)
|
|
this.LoadProfiles()
|
|
}
|
|
|
|
Save() {
|
|
ini := this.Path
|
|
IniWrite(this.LibraryPath, ini, "General", "LibraryPath")
|
|
IniWrite(this.PickerHotkey, ini, "General", "PickerHotkey")
|
|
IniWrite(this.ManagerHotkey, ini, "General", "ManagerHotkey")
|
|
IniWrite(this.NewHotkey, ini, "General", "NewHotkey")
|
|
IniWrite(this.ReplayHotkey, ini, "General", "ReplayHotkey")
|
|
IniWrite(this.Method, ini, "Injection", "Method")
|
|
IniWrite(this.PasteDelayMs, ini, "Injection", "PasteDelayMs")
|
|
IniWrite(this.RestoreDelayMs, ini, "Injection", "RestoreDelayMs")
|
|
IniWrite(this.SendAfterDelayMs, ini, "Injection", "SendAfterDelayMs")
|
|
IniWrite(this.ExternalEditor, ini, "Editeur", "ExternalEditor")
|
|
}
|
|
|
|
; Profils intégrés, surchargeables par des sections [Profil.<nom>] dans config.ini.
|
|
LoadProfiles() {
|
|
this.Profiles := Map()
|
|
base := Map(
|
|
"défaut", Map("preambule", "", "postambule", "", "methode", "", "sendAfter", 0, "appMatch", "", "titreMatch", ""),
|
|
"claude", Map("preambule", "", "postambule", "", "methode", "", "sendAfter", 0, "appMatch", "", "titreMatch", "Claude"),
|
|
"chatgpt", Map("preambule", "", "postambule", "", "methode", "", "sendAfter", 0, "appMatch", "", "titreMatch", "ChatGPT"),
|
|
"gemini", Map("preambule", "", "postambule", "", "methode", "", "sendAfter", 0, "appMatch", "", "titreMatch", "Gemini"),
|
|
"qwen", Map("preambule", "", "postambule", "", "methode", "", "sendAfter", 0, "appMatch", "", "titreMatch", "Qwen"),
|
|
"deepseek", Map("preambule", "", "postambule", "", "methode", "", "sendAfter", 0, "appMatch", "", "titreMatch", "DeepSeek"),
|
|
"terminal", Map("preambule", "", "postambule", "", "methode", "sendtext", "sendAfter", 0, "appMatch", "wt.exe,powershell.exe,cmd.exe,Code.exe", "titreMatch", ""),
|
|
"courriel", Map("preambule", "", "postambule", "", "methode", "", "sendAfter", 0, "appMatch", "", "titreMatch", "")
|
|
)
|
|
for name, p in base
|
|
this.Profiles[name] := p
|
|
; Surcharge INI : lire le fichier et repérer les sections [Profil.xxx].
|
|
if FileExist(this.Path) {
|
|
text := FileRead(this.Path, "UTF-8")
|
|
current := ""
|
|
for line in StrSplit(text, "`n", "`r") {
|
|
line := Trim(line)
|
|
if RegExMatch(line, "^\[Profil\.(.+)\]$", &m) {
|
|
current := StrLower(m[1])
|
|
if !this.Profiles.Has(current)
|
|
this.Profiles[current] := Map("preambule", "", "postambule", "", "methode", "", "sendAfter", 0, "appMatch", "", "titreMatch", "")
|
|
} else if (current != "" && RegExMatch(line, "^\[")) {
|
|
current := ""
|
|
} else if (current != "" && InStr(line, "=")) {
|
|
pos := InStr(line, "=")
|
|
key := StrLower(Trim(SubStr(line, 1, pos - 1)))
|
|
val := Trim(SubStr(line, pos + 1))
|
|
val := StrReplace(val, "\n", "`n")
|
|
switch key {
|
|
case "preambule": this.Profiles[current]["preambule"] := val
|
|
case "postambule": this.Profiles[current]["postambule"] := val
|
|
case "methode": this.Profiles[current]["methode"] := val
|
|
case "sendafter": this.Profiles[current]["sendAfter"] := (val = "true" || val = "1") ? 1 : 0
|
|
case "appmatch": this.Profiles[current]["appMatch"] := val
|
|
case "titrematch": this.Profiles[current]["titreMatch"] := val
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
GetProfile(name) {
|
|
name := StrLower(Trim(name))
|
|
if (name != "" && this.Profiles.Has(name))
|
|
return this.Profiles[name]
|
|
return this.Profiles["défaut"]
|
|
}
|
|
|
|
ProfileNames() {
|
|
names := []
|
|
for name in this.Profiles
|
|
names.Push(name)
|
|
return names
|
|
}
|
|
|
|
; Auto-détection (§12.3, étape 3) : AppMatch (processus) puis TitreMatch (titre de fenêtre).
|
|
DetectProfile(processName, windowTitle) {
|
|
for name, p in this.Profiles {
|
|
if (name = "défaut")
|
|
continue
|
|
if (p["appMatch"] != "") {
|
|
for app in StrSplit(p["appMatch"], ",") {
|
|
if (StrLower(Trim(app)) = StrLower(processName))
|
|
return name
|
|
}
|
|
}
|
|
if (p["titreMatch"] != "" && InStr(windowTitle, p["titreMatch"]))
|
|
return name
|
|
}
|
|
return "défaut"
|
|
}
|
|
}
|