feat(core): moteur PromptKey — bibliothèque .md, variables, injection, raccourcis
- 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
This commit is contained in:
+100
@@ -0,0 +1,100 @@
|
||||
; Util.ahk — Fonctions utilitaires de PromptKey (dates, GUID, normalisation, journal).
|
||||
; Aucune dépendance. Voir le document d'architecture, section 19.
|
||||
|
||||
class Util {
|
||||
; Journal local : horodatage + message. JAMAIS de contenu de prompt (architecture §11.6 / §18).
|
||||
static LogFile := ""
|
||||
static Log(msg) {
|
||||
if (Util.LogFile = "")
|
||||
return
|
||||
try {
|
||||
line := FormatTime(, "yyyy-MM-dd HH:mm:ss") " " msg "`r`n"
|
||||
FileAppend(line, Util.LogFile, "UTF-8")
|
||||
; Rotation grossière : au-delà d'environ 1 Mo, on repart de zéro.
|
||||
if (FileGetSize(Util.LogFile) > 1048576)
|
||||
FileMove(Util.LogFile, Util.LogFile ".bak", true)
|
||||
}
|
||||
}
|
||||
|
||||
static NewGuid() {
|
||||
; GUID via l'API Windows (CoCreateGuid), formaté en minuscules avec tirets.
|
||||
buf := Buffer(16, 0)
|
||||
DllCall("ole32\CoCreateGuid", "Ptr", buf.Ptr)
|
||||
g := ""
|
||||
fmt := [4, 2, 2, 2, 6] ; tailles en octets des groupes 8-4-4-4-12 (hex)
|
||||
off := 0
|
||||
parts := []
|
||||
for i, sz in fmt {
|
||||
hex := ""
|
||||
; Le premier groupe est un entier little-endian : on lit les octets dans l'ordre inverse pour les groupes 1 à 3.
|
||||
if (i <= 3) {
|
||||
loop sz {
|
||||
hex := Format("{:02x}", NumGet(buf, off + A_Index - 1, "UChar")) hex
|
||||
}
|
||||
} else {
|
||||
loop sz {
|
||||
hex .= Format("{:02x}", NumGet(buf, off + A_Index - 1, "UChar"))
|
||||
}
|
||||
}
|
||||
parts.Push(hex)
|
||||
off += sz
|
||||
}
|
||||
return parts[1] "-" parts[2] "-" parts[3] "-" parts[4] "-" parts[5]
|
||||
}
|
||||
|
||||
static NowIso() {
|
||||
return FormatTime(, "yyyy-MM-ddTHH:mm:ss")
|
||||
}
|
||||
|
||||
static Today() {
|
||||
return FormatTime(, "yyyy-MM-dd")
|
||||
}
|
||||
|
||||
; Normalisation pour la recherche : minuscules + suppression des accents (architecture §14.1).
|
||||
static Normalize(s) {
|
||||
s := StrLower(s)
|
||||
static accents := Map(
|
||||
"à", "a", "á", "a", "â", "a", "ä", "a", "ã", "a",
|
||||
"è", "e", "é", "e", "ê", "e", "ë", "e",
|
||||
"ì", "i", "í", "i", "î", "i", "ï", "i",
|
||||
"ò", "o", "ó", "o", "ô", "o", "ö", "o", "õ", "o",
|
||||
"ù", "u", "ú", "u", "û", "u", "ü", "u",
|
||||
"ç", "c", "ñ", "n", "ÿ", "y")
|
||||
out := ""
|
||||
loop parse s {
|
||||
out .= accents.Has(A_LoopField) ? accents[A_LoopField] : A_LoopField
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
; Tronque proprement pour les aperçus.
|
||||
static Truncate(s, n) {
|
||||
if (StrLen(s) <= n)
|
||||
return s
|
||||
return SubStr(s, 1, n) "…"
|
||||
}
|
||||
|
||||
; Nom de fichier sûr à partir d'un titre (minuscules, tirets, sans accents).
|
||||
static Slugify(title) {
|
||||
s := Util.Normalize(Trim(title))
|
||||
s := RegExReplace(s, "[^a-z0-9]+", "-")
|
||||
s := Trim(s, "-")
|
||||
return (s = "") ? "sans-titre" : s
|
||||
}
|
||||
|
||||
; Échappe une valeur pour l'en-tête : guillemets si la valeur contient un caractère spécial du format.
|
||||
static QuoteIfNeeded(s) {
|
||||
if (s = "")
|
||||
return s
|
||||
if RegExMatch(s, "[,\[\]#:]") || (Trim(s) != s)
|
||||
return '"' StrReplace(s, '"', '\"') '"'
|
||||
return s
|
||||
}
|
||||
|
||||
static Unquote(s) {
|
||||
s := Trim(s)
|
||||
if (StrLen(s) >= 2 && SubStr(s, 1, 1) = '"' && SubStr(s, -1) = '"')
|
||||
s := StrReplace(SubStr(s, 2, StrLen(s) - 2), '\"', '"')
|
||||
return s
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user