Files
Loki/internal/loki/sys_console_windows.go
T
Loki de6551a153 Rebaptise AJEAN en Loki (fork, lignée conservée)
- module github.com/R0m1k3/Loki, cmd/loki, internal/loki (package loki)
- LOKI_HOME, LOKI_MODEL_DIRS, LOKI_SERVICE, LOKI_DL_CONNS ; /etc/loki ;
  units loki-engine / loki-ui ; binaire et aide CLI
- updateRepo pointe sur R0m1k3/Loki (l'auto-update ne tirera plus les
  binaires AJEAN amont)

Conservé à l'identique : le domaine ajean.link (service de tunnel amont),
les littéraux de migration 0.7.x (migrate_07.go), RELEASE_NOTES.md et
LICENSE (historique et licence de l'amont).

go build/vet/test : verts.
2026-08-14 21:33:15 +00:00

101 lines
3.8 KiB
Go

//go:build windows
package loki
// sys_console_windows.go — gestion de la console sous Windows.
//
// Le binaire est compilé en sous-système CONSOLE. C'est ce qui fait que `cmd`
// ATTEND la fin du programme : avec un binaire graphique, il rendait la main
// aussitôt et réaffichait son invite AVANT la sortie d'Loki, ce qui donnait
//
// C:\Users\Nathan>loki
//
// C:\Users\Nathan>loki 0.8.0 — manager llama.cpp + UI web
//
// La même cause cassait la redirection et les tubes, et rendait `loki chat`
// inutilisable depuis un terminal (le shell et Loki se disputaient l'entrée).
//
// EN CONTREPARTIE, Windows alloue une console à tout lancement sans terminal —
// un double-clic. On la referme alors immédiatement : voir setupConsole. Les
// raccourcis créés par l'installation demandent en plus un démarrage minimisé,
// si bien que cette console n'est jamais peinte à l'écran.
import (
"syscall"
"unsafe"
)
// win appelle une procédure Win32 et renvoie (résultat, trouvée).
//
// LazyProc.Call PANIQUE quand la procédure est introuvable. Or tout ce fichier
// s'exécute AVANT le reste du programme : une panique ici et il ne reste rien à
// l'écran pour la comprendre, l'application ne démarre tout simplement plus.
// C'est exactement ce qui est arrivé en cherchant ShowWindow dans kernel32
// alors qu'elle vit dans user32. Aucun réglage de confort ne mérite ça.
func win(dll *syscall.LazyDLL, name string, a ...uintptr) (uintptr, bool) {
p := dll.NewProc(name)
if err := p.Find(); err != nil {
return 0, false
}
r, _, _ := p.Call(a...)
return r, true
}
var kernel32 = syscall.NewLazyDLL("kernel32.dll")
// setupConsole décide dans quel monde on tourne et renvoie true en usage CLI.
//
// Le signal est le nombre de processus rattachés à notre console : si nous
// sommes le SEUL, c'est que Windows l'a créée pour nous, donc qu'aucun terminal
// ne nous a lancés. On la fait disparaître et on bascule en mode application.
// Un shell rattaché (cmd, PowerShell, Windows Terminal) en fait au moins deux.
func setupConsole() bool {
// Le compte vaut 0 quand il n'y a aucune console (parent détaché). On répond
// alors « CLI », le cas contraire étant couvert autrement : les relances
// internes passent « app » explicitement (voir launch, sys_firstrun_windows.go).
// Mieux vaut afficher une aide inutile que démarrer un serveur en silence.
var pids [8]uint32
n, ok := win(kernel32, "GetConsoleProcessList",
uintptr(unsafe.Pointer(&pids[0])), uintptr(len(pids)))
if ok && n == 1 {
// Masquer AVANT de libérer : sinon la fenêtre reste peinte le temps que
// Windows la détruise. ShowWindow est dans user32, pas kernel32.
if hwnd, ok := win(kernel32, "GetConsoleWindow"); ok && hwnd != 0 {
const swHide = 0
win(u32s, "ShowWindow", hwnd, swHide)
}
win(kernel32, "FreeConsole")
return false
}
// Lancé depuis un terminal : les flux standard sont déjà ceux du shell,
// redirections et tubes compris. Il n'y a rien à rebrancher, seulement à
// régler l'encodage et les couleurs.
configureConsole()
return true
}
// configureConsole passe la console en UTF-8 + traitement des séquences ANSI
// (couleurs/curseur).
func configureConsole() {
const (
cpUTF8 = 65001
enableVirtualTerminalProcessing = 0x0004
stdOutputHandle = ^uintptr(10) // -11
)
win(kernel32, "SetConsoleOutputCP", uintptr(cpUTF8))
win(kernel32, "SetConsoleCP", uintptr(cpUTF8))
h, ok := win(kernel32, "GetStdHandle", stdOutputHandle)
if !ok {
return
}
var mode uint32
if r, ok := win(kernel32, "GetConsoleMode", h, uintptr(unsafe.Pointer(&mode))); ok && r != 0 {
win(kernel32, "SetConsoleMode", h, uintptr(mode|enableVirtualTerminalProcessing))
}
}
// appWarning : rien à signaler sous Windows (pas d'App Translocation). Voir
// sys_console_darwin.go.
func appWarning() string { return "" }