diff --git a/PBIDE-GitTool.pb b/PBIDE-GitTool.pb
index 255ea12..f5cbdca 100644
--- a/PBIDE-GitTool.pb
+++ b/PBIDE-GitTool.pb
@@ -1,31 +1,90 @@
; PBIDE-GitTool.pb — Outil externe Git pour l’IDE PureBasic
-; Gère init, status, add+commit, push/pull avec paramètres simples
-; PureBasic 6.x, multiplateforme
-; ------------------------------------------------------------
+; - Init, Status, Add+Commit (sélectif), Push/Pull
+; - UI : liste avec cases à cocher + actions Inclure/Exclure/Tout
+; - Fenêtre "Avancé…" : switch/restore de branche
+; - Assistant d’installation IDE si lancé sans paramètre
+; Contraintes respectées : pas d'underscore dans nos identifiants,
+; Protected uniquement dans les procédures, pas de IIf, déclarations = implémentations,
+; comparaisons uniquement dans If/While/Until/For, etc.
EnableExplicit
-
-; ====== Debug global ======
#EnableDebug = #True
; ====== Séparateur de chemin (portable) ======
CompilerIf #PB_Compiler_OS = #PB_OS_Windows
#PathSep$ = "\"
- ; Chemin Git forcé pour Windows (proposé) :
+ ; Chemin Git forcé pour Windows :
#GitExe$ = "C:\Program Files\Git\cmd\git.exe"
CompilerElse
#PathSep$ = "/"
- ; Sur macOS/Linux on garde 'git' dans le PATH
+ ; Sur macOS/Linux on garde 'git' dans le PATH :
#GitExe$ = "git"
CompilerEndIf
-; ====== Structure d'appel Git ======
+; ====== IDs UI (placer ce bloc AVANT toutes les procédures) ======
+
+; Fenêtre principale
+#GWindow = 1
+#GLabelRepo = 10
+#GStringRepo = 11
+#GButtonBrowse = 12
+#GListStatus = 13
+#GRefresh = 14
+#GLabelMsg = 15
+#GStringMsg = 16
+#GCheckPush = 17
+#GLabelRemote = 18
+#GStringRemote = 19
+#GLabelBranch = 20
+#GComboBranch = 21
+#GSavePrefs = 22
+#GInit = 23
+#GCommit = 24
+#GPull = 25
+#GPush = 26
+#GInclude = 27
+#GExclude = 28
+#GIncludeAll = 29
+#GExcludeAll = 30
+#GAdvanced = 31
+
+; Fenêtre avancée (branches)
+#WAdv = 200
+#GAdvLabel = 210
+#GAdvCombo = 211
+#GAdvSwitch = 212
+#GAdvRestore = 213
+#GAdvClose = 214
+
+; Assistant d’installation
+#WInstall = 100
+#GLabelIde = 110
+#GStringIde = 111
+#GButtonIde = 112
+#GLabelTools = 113
+#GStringTools = 114
+#GButtonTools = 115
+#GLabelTheme = 116
+#GStringTheme = 117
+#GButtonTheme = 118
+#GInstallGo = 119
+#GInstallCancel = 120
+#GInstallNote = 121
+
+
+; ====== Structures ======
Structure GitCall
- args.s ; ex: "status --porcelain"
- workdir.s ; répertoire de travail
- output.s ; stdout complet
- errors.s ; stderr complet
- exitcode.i ; code retour
+ args.s
+ workdir.s
+ output.s
+ errors.s
+ exitcode.i
+EndStructure
+
+Structure FileRow
+ stat.s ; 2 lettres porcelain (" M", "A ", "??", etc.)
+ file.s ; chemin relatif
+ include.i ; 1=coché (inclus), 0=exclu
EndStructure
; ====== Déclarations ======
@@ -43,12 +102,19 @@ Declare.i DoCommit(repoDir$, message$, doPush.i, remote$, branch$)
Declare.i DoPush(repoDir$, remote$, branch$)
Declare.i DoPull(repoDir$, remote$, branch$)
Declare.i ListBranches(repoDir$, List branchesList.s())
+Declare.i LoadStatusRows(repoDir$, List rows.FileRow())
+Declare.i FillStatusList(List rows.FileRow())
+Declare.i ToggleIncludeAt(index.i, List rows.FileRow())
+Declare.i CollectIncludedFiles(List rows.FileRow(), List files.s())
+Declare.i DoCommitSelected(repoDir$, message$, doPush.i, remote$, branch$, List files.s())
+Declare.i OpenAdvancedWindow(repoDir$)
+Declare.i SwitchToBranch(repoDir$, branch$)
+Declare.i RestoreFromBranch(repoDir$, branch$)
Declare.i InstallPBGitInIDE(ideExe$, toolsPrefs$, themeZip$)
Declare.i OpenInstallWizard()
; ====== Utils ======
Procedure.s TrimNewlines(text$)
- ; Supprime \r et \n en fin de chaîne
Protected s$ = text$
While Right(s$, 1) = #LF$ Or Right(s$, 1) = #CR$
s$ = Left(s$, Len(s$)-1)
@@ -56,20 +122,17 @@ Procedure.s TrimNewlines(text$)
ProcedureReturn s$
EndProcedure
-; Exécute git avec une structure d'appel passée par pointeur
-; Remplit *call\output, *call\errors, *call\exitcode
+; Exécute git avec capture stdout/stderr (structure passée par pointeur)
Procedure.i RunGit(*call.GitCall)
- Protected prg.i, line$
- Protected out$, err$
-
+ Protected prg.i, line$, out$, err$
If #EnableDebug
- Debug "[RunGit] exe=" + #GitExe$ + " args=" + *call\args + " wd=" + *call\workdir
+ Debug "[RunGit] " + #GitExe$ + " " + *call\args + " (wd=" + *call\workdir + ")"
EndIf
prg = RunProgram(#GitExe$, *call\args, *call\workdir, #PB_Program_Open | #PB_Program_Read | #PB_Program_Error | #PB_Program_Hide)
If prg = 0
- *call\output = ""
- *call\errors = "Impossible de lancer '" + #GitExe$ + "'."
+ *call\output = ""
+ *call\errors = "Impossible de lancer '" + #GitExe$ + "'."
*call\exitcode = -1
ProcedureReturn *call\exitcode
EndIf
@@ -77,34 +140,20 @@ Procedure.i RunGit(*call.GitCall)
While ProgramRunning(prg)
While AvailableProgramOutput(prg)
line$ = ReadProgramString(prg)
- If line$ <> ""
- out$ + line$ + #LF$
- EndIf
+ If line$ <> "" : out$ + line$ + #LF$ : EndIf
Wend
-
- ; ReadProgramError() renvoie "" s'il n'y a rien (non bloquant)
- line$ = ReadProgramError(prg)
- If line$ <> ""
- err$ + line$ + #LF$
- EndIf
-
+ line$ = ReadProgramError(prg) ; renvoie "" si rien à lire (non bloquant)
+ If line$ <> "" : err$ + line$ + #LF$ : EndIf
Delay(5)
Wend
- ; Vidange finale stdout
While AvailableProgramOutput(prg)
line$ = ReadProgramString(prg)
- If line$ <> ""
- out$ + line$ + #LF$
- EndIf
+ If line$ <> "" : out$ + line$ + #LF$ : EndIf
Wend
-
- ; Vidange finale stderr (jusqu'à chaîne vide)
Repeat
line$ = ReadProgramError(prg)
- If line$ = ""
- Break
- EndIf
+ If line$ = "" : Break : EndIf
err$ + line$ + #LF$
ForEver
@@ -123,9 +172,8 @@ Procedure.i RunGit(*call.GitCall)
EndProcedure
Procedure.s DetectRepoRoot(startDir$)
- ; Renvoie le toplevel git si présent, sinon startDir$
Protected gc.GitCall
- gc\args = "rev-parse --show-toplevel"
+ gc\args = "rev-parse --show-toplevel"
gc\workdir = startDir$
If RunGit(@gc) = 0
ProcedureReturn TrimNewlines(gc\output)
@@ -169,20 +217,16 @@ Procedure.i EnsureGitAvailable()
If RunGit(@gc) = 0 And FindString(LCase(gc\output), "git version", 1)
ProcedureReturn 1
EndIf
- MessageRequester("PBIDE-GitTool", "Git n'est pas détecté à l'emplacement prévu : " + #GitExe$, #PB_MessageRequester_Warning)
+ MessageRequester("PBIDE-GitTool", "Git n'est pas détecté à l’emplacement prévu : " + #GitExe$, #PB_MessageRequester_Warning)
ProcedureReturn 0
EndProcedure
+; Détermine un répertoire pertinent (project → env → --repo → exe)
Procedure.s DirFromArgOrFallback()
- ; 1) --project "
" si fourni (via %PROJECT)
- ; 2) PB_TOOL_Project -> GetPathPart()
- ; 3) --repo "" ou 1er argument libre
- ; 4) dossier de l'exécutable
Protected n.i = CountProgramParameters()
Protected gotNextProject.i = 0
Protected gotNextRepo.i = 0
- Protected dir$ = ""
- Protected i.i, p$
+ Protected dir$ = "", i.i, p$
For i = 0 To n - 1
p$ = ProgramParameter(i)
@@ -202,7 +246,7 @@ Procedure.s DirFromArgOrFallback()
Next
If dir$ <> ""
- If #EnableDebug : Debug "[DirFromArgOrFallback] from args: " + dir$ : EndIf
+ If #EnableDebug : Debug "[Dir] from args: " + dir$ : EndIf
ProcedureReturn dir$
EndIf
@@ -210,23 +254,23 @@ Procedure.s DirFromArgOrFallback()
If projFile$ <> ""
Protected projDir$ = GetPathPart(projFile$)
If projDir$ <> ""
- If #EnableDebug : Debug "[DirFromArgOrFallback] from PB_TOOL_Project: " + projDir$ : EndIf
+ If #EnableDebug : Debug "[Dir] from PB_TOOL_Project: " + projDir$ : EndIf
ProcedureReturn projDir$
EndIf
EndIf
dir$ = GetPathPart(ProgramFilename())
- If #EnableDebug : Debug "[DirFromArgOrFallback] fallback exe dir: " + dir$ : EndIf
+ If #EnableDebug : Debug "[Dir] fallback exe dir: " + dir$ : EndIf
ProcedureReturn dir$
EndProcedure
; ====== Opérations Git de base ======
Procedure.i DoInitRepo(repoDir$)
Protected gc.GitCall
- gc\args = "init"
+ gc\args = "init"
gc\workdir = repoDir$
If RunGit(@gc) = 0
- MessageRequester("Git init", "Répertoire initialisé comme dépôt Git." + #LF$ + TrimNewlines(gc\output), #PB_MessageRequester_Info)
+ MessageRequester("Git init", "Répertoire initialisé." + #LF$ + TrimNewlines(gc\output), #PB_MessageRequester_Info)
ProcedureReturn 1
EndIf
MessageRequester("Git init", "Échec: " + #LF$ + TrimNewlines(gc\errors), #PB_MessageRequester_Error)
@@ -235,7 +279,7 @@ EndProcedure
Procedure.i DoStatus(repoDir$, out$)
Protected gc.GitCall
- gc\args = "status --porcelain"
+ gc\args = "status --porcelain"
gc\workdir = repoDir$
If RunGit(@gc) <> 0
out$ = ""
@@ -247,23 +291,21 @@ Procedure.i DoStatus(repoDir$, out$)
EndProcedure
Procedure.i DoCommit(repoDir$, message$, doPush.i, remote$, branch$)
- Protected gc.GitCall
-
- ; add -A
- gc\args = "add -A"
+ Protected gc.GitCall, code.i
gc\workdir = repoDir$
- If RunGit(@gc) <> 0
+
+ gc\args = "add -A"
+ code = RunGit(@gc)
+ If code <> 0
MessageRequester("Git add", "Échec: " + #LF$ + TrimNewlines(gc\errors), #PB_MessageRequester_Error)
ProcedureReturn 0
EndIf
- ; commit
gc\args = "commit -m " + Chr(34) + message$ + Chr(34)
- If RunGit(@gc) <> 0
+ code = RunGit(@gc)
+ If code <> 0
MessageRequester("Git commit", "Échec ou rien à valider: " + #LF$ + TrimNewlines(gc\errors) + #LF$ + TrimNewlines(gc\output), #PB_MessageRequester_Warning)
- If doPush = 0
- ProcedureReturn 0
- EndIf
+ If doPush = 0 : ProcedureReturn 0 : EndIf
Else
MessageRequester("Git commit", "OK:" + #LF$ + TrimNewlines(gc\output), #PB_MessageRequester_Info)
EndIf
@@ -271,13 +313,12 @@ Procedure.i DoCommit(repoDir$, message$, doPush.i, remote$, branch$)
If doPush
ProcedureReturn DoPush(repoDir$, remote$, branch$)
EndIf
-
ProcedureReturn 1
EndProcedure
Procedure.i DoPush(repoDir$, remote$, branch$)
Protected gc.GitCall
- gc\args = "push " + remote$ + " " + branch$
+ gc\args = "push " + remote$ + " " + branch$
gc\workdir = repoDir$
If RunGit(@gc) = 0
MessageRequester("Git push", "OK:" + #LF$ + TrimNewlines(gc\output), #PB_MessageRequester_Info)
@@ -289,7 +330,7 @@ EndProcedure
Procedure.i DoPull(repoDir$, remote$, branch$)
Protected gc.GitCall
- gc\args = "pull " + remote$ + " " + branch$
+ gc\args = "pull " + remote$ + " " + branch$
gc\workdir = repoDir$
If RunGit(@gc) = 0
MessageRequester("Git pull", "OK:" + #LF$ + TrimNewlines(gc\output), #PB_MessageRequester_Info)
@@ -300,11 +341,9 @@ Procedure.i DoPull(repoDir$, remote$, branch$)
EndProcedure
Procedure.i ListBranches(repoDir$, List branchesList.s())
- ; Remplit la liste 'branchesList()' avec les noms de branches
ClearList(branchesList())
-
Protected gc.GitCall
- gc\args = "branch --list --format='%(refname:short)'"
+ gc\args = "branch --list --format='%(refname:short)'"
gc\workdir = repoDir$
If RunGit(@gc) <> 0
@@ -322,12 +361,198 @@ Procedure.i ListBranches(repoDir$, List branchesList.s())
branchesList() = b$
EndIf
Next i
-
ProcedureReturn 1
EndProcedure
-; ====== Interface simple ======
-; Gadgets IDs (sans underscores)
+; ====== Status → lignes et gestion des coches ======
+Procedure.i LoadStatusRows(repoDir$, List rows.FileRow())
+ Protected gc.GitCall, text$, line$, n.i, i.i
+ gc\args = "status --porcelain"
+ gc\workdir = repoDir$
+ If RunGit(@gc) <> 0
+ MessageRequester("Git status", "Échec: " + #LF$ + TrimNewlines(gc\errors), #PB_MessageRequester_Error)
+ ProcedureReturn 0
+ EndIf
+
+ text$ = gc\output
+ n = CountString(text$, #LF$) + 1
+ For i = 1 To n
+ line$ = Trim(StringField(text$, i, #LF$))
+ If line$ <> ""
+ AddElement(rows())
+ rows()\stat = Left(line$, 2)
+ rows()\file = Trim(Mid(line$, 4))
+ rows()\include = 0
+ EndIf
+ Next i
+ ProcedureReturn ListSize(rows())
+EndProcedure
+
+Procedure.i FillStatusList(List rows.FileRow())
+ ClearGadgetItems(#GListStatus)
+ Protected idx.i = 0
+ ForEach rows()
+ AddGadgetItem(#GListStatus, -1, rows()\stat + #LF$ + rows()\file)
+ If rows()\include
+ SetGadgetItemState(#GListStatus, idx, #PB_ListIcon_Checked)
+ Else
+ SetGadgetItemState(#GListStatus, idx, 0)
+ EndIf
+ idx + 1
+ Next
+ ProcedureReturn CountGadgetItems(#GListStatus)
+EndProcedure
+
+Procedure.i ToggleIncludeAt(index.i, List rows.FileRow())
+ If index < 0 : ProcedureReturn 0 : EndIf
+ Protected c.i = CountGadgetItems(#GListStatus)
+ If index >= c : ProcedureReturn 0 : EndIf
+
+ Protected state.i = GetGadgetItemState(#GListStatus, index)
+ Protected want.i
+ If state & #PB_ListIcon_Checked : want = 1 : Else : want = 0 : EndIf
+
+ Protected j.i = 0
+ ForEach rows()
+ If j = index
+ rows()\include = want
+ Break
+ EndIf
+ j + 1
+ Next
+ ProcedureReturn 1
+EndProcedure
+
+Procedure.i CollectIncludedFiles(List rows.FileRow(), List files.s())
+ ClearList(files())
+ ForEach rows()
+ If rows()\include
+ AddElement(files())
+ files() = rows()\file
+ EndIf
+ Next
+ ProcedureReturn ListSize(files())
+EndProcedure
+
+; Commit sélectif si des fichiers sont cochés
+Procedure.i DoCommitSelected(repoDir$, message$, doPush.i, remote$, branch$, List files.s())
+ If ListSize(files()) = 0
+ ProcedureReturn DoCommit(repoDir$, message$, doPush, remote$, branch$)
+ EndIf
+
+ Protected gc.GitCall, code.i, argsAdd$, q$
+ gc\workdir = repoDir$
+ q$ = Chr(34)
+
+ argsAdd$ = "add"
+ ForEach files()
+ argsAdd$ + " " + q$ + files() + q$
+ Next
+ gc\args = argsAdd$
+ code = RunGit(@gc)
+ If code <> 0
+ MessageRequester("Git add", "Échec: " + #LF$ + TrimNewlines(gc\errors), #PB_MessageRequester_Error)
+ ProcedureReturn 0
+ EndIf
+
+ gc\args = "commit -m " + Chr(34) + message$ + Chr(34)
+ code = RunGit(@gc)
+ If code <> 0
+ MessageRequester("Git commit", "Échec ou rien à valider: " + #LF$ + TrimNewlines(gc\errors) + #LF$ + TrimNewlines(gc\output), #PB_MessageRequester_Warning)
+ If doPush = 0 : ProcedureReturn 0 : EndIf
+ Else
+ MessageRequester("Git commit", "OK:" + #LF$ + TrimNewlines(gc\output), #PB_MessageRequester_Info)
+ EndIf
+
+ If doPush
+ ProcedureReturn DoPush(repoDir$, remote$, branch$)
+ EndIf
+ ProcedureReturn 1
+EndProcedure
+
+; ====== Fenêtre Avancé… (branches) ======
+#WAdv = 200
+#GAdvLabel = 210
+#GAdvCombo = 211
+#GAdvSwitch = 212
+#GAdvRestore = 213
+#GAdvClose = 214
+
+Procedure.i OpenAdvancedWindow(repoDir$)
+ Protected b$
+ NewList blist.s()
+ ListBranches(repoDir$, blist())
+
+ If OpenWindow(#WAdv, 0, 0, 440, 160, "Actions avancées — Branches", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
+ TextGadget(#GAdvLabel, 10, 14, 140, 24, "Branche :")
+ ComboBoxGadget(#GAdvCombo, 160, 12, 270, 24)
+ ForEach blist() : AddGadgetItem(#GAdvCombo, -1, blist()) : Next
+ GadgetToolTip(#GAdvCombo, "Sélectionnez la branche cible.")
+
+ ButtonGadget(#GAdvSwitch, 10, 60, 170, 30, "Basculer sur la branche")
+ GadgetToolTip(#GAdvSwitch, "git switch (ou git checkout).")
+
+ ButtonGadget(#GAdvRestore, 190, 60, 170, 30, "Restaurer depuis la branche")
+ GadgetToolTip(#GAdvRestore, "git restore --source -- . (remplace le contenu de travail).")
+
+ ButtonGadget(#GAdvClose, 370, 60, 60, 30, "Fermer")
+
+ Repeat
+ Protected ev.i = WaitWindowEvent()
+ If ev = #PB_Event_Gadget
+ Select EventGadget()
+ Case #GAdvSwitch
+ b$ = GetGadgetText(#GAdvCombo)
+ If b$ <> ""
+ If SwitchToBranch(repoDir$, b$)
+ MessageRequester("Branche", "Basculé sur '" + b$ + "'.", #PB_MessageRequester_Info)
+ EndIf
+ EndIf
+
+ Case #GAdvRestore
+ b$ = GetGadgetText(#GAdvCombo)
+ If b$ <> ""
+ If MessageRequester("Restauration", "Cette action va restaurer le contenu depuis '" + b$ + "'." + #LF$ + "Continuer ?", #PB_MessageRequester_YesNo) = #PB_MessageRequester_Yes
+ If RestoreFromBranch(repoDir$, b$)
+ MessageRequester("Restauration", "Contenu restauré depuis '" + b$ + "'.", #PB_MessageRequester_Info)
+ EndIf
+ EndIf
+ EndIf
+
+ Case #GAdvClose
+ CloseWindow(#WAdv)
+ ProcedureReturn 1
+ EndSelect
+ EndIf
+ Until ev = #PB_Event_CloseWindow
+
+ ProcedureReturn 1
+ EndIf
+ ProcedureReturn 0
+EndProcedure
+
+Procedure.i SwitchToBranch(repoDir$, branch$)
+ Protected gc.GitCall
+ gc\workdir = repoDir$
+ gc\args = "switch " + Chr(34) + branch$ + Chr(34)
+ If RunGit(@gc) = 0 : ProcedureReturn 1 : EndIf
+ gc\args = "checkout " + Chr(34) + branch$ + Chr(34) ; fallback versions anciennes
+ If RunGit(@gc) = 0 : ProcedureReturn 1 : EndIf
+ MessageRequester("Branche", "Échec: " + #LF$ + TrimNewlines(gc\errors), #PB_MessageRequester_Error)
+ ProcedureReturn 0
+EndProcedure
+
+Procedure.i RestoreFromBranch(repoDir$, branch$)
+ Protected gc.GitCall
+ gc\workdir = repoDir$
+ gc\args = "restore --source " + Chr(34) + branch$ + Chr(34) + " -- ."
+ If RunGit(@gc) = 0 : ProcedureReturn 1 : EndIf
+ MessageRequester("Restauration", "Échec: " + #LF$ + TrimNewlines(gc\errors), #PB_MessageRequester_Error)
+ ProcedureReturn 0
+EndProcedure
+
+; ====== UI principale ======
+; Gadgets IDs (inclut les NOUVEAUX boutons)
#GWindow = 1
#GLabelRepo = 10
#GStringRepo = 11
@@ -346,81 +571,87 @@ EndProcedure
#GCommit = 24
#GPull = 25
#GPush = 26
+#GInclude = 27
+#GExclude = 28
+#GIncludeAll = 29
+#GExcludeAll = 30
+#GAdvanced = 31
Procedure.i OpenGUI(initialDir$, prefsPath$)
Protected repoDir$ = DetectRepoRoot(initialDir$)
Protected remote$ = "", branch$ = ""
LoadPrefs(prefsPath$, remote$, branch$)
- If OpenWindow(#GWindow, 0, 0, 680, 520, "PBIDE-GitTool — Git simplifié pour PureBasic", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
+ If OpenWindow(#GWindow, 0, 0, 740, 560, "PBIDE-GitTool — Git simplifié pour PureBasic", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
TextGadget(#GLabelRepo, 10, 12, 60, 22, "Dépôt :")
- StringGadget(#GStringRepo, 80, 10, 480, 24, repoDir$)
- ButtonGadget(#GButtonBrowse, 570, 10, 100, 24, "Parcourir…")
+ StringGadget(#GStringRepo, 80, 10, 540, 24, repoDir$)
+ ButtonGadget(#GButtonBrowse, 630, 10, 100, 24, "Parcourir…")
- ListViewGadget(#GListStatus, 10, 46, 660, 250)
- ButtonGadget(#GRefresh, 10, 302, 90, 26, "Rafraîchir")
- ButtonGadget(#GInit, 110, 302, 90, 26, "Init repo")
+ ; Liste avec cases à cocher
+ ListIconGadget(#GListStatus, 10, 46, 720, 280, "Statut", 100, #PB_ListIcon_CheckBoxes | #PB_ListIcon_FullRowSelect)
+ AddGadgetColumn(#GListStatus, 1, "Fichier", 600)
- TextGadget(#GLabelMsg, 10, 342, 100, 22, "Message :")
- StringGadget(#GStringMsg, 110, 340, 560, 24, "")
- CheckBoxGadget(#GCheckPush, 10, 372, 120, 22, "Pousser après")
+ ButtonGadget(#GRefresh, 10, 332, 90, 26, "Rafraîchir")
+ ButtonGadget(#GInit, 110, 332, 90, 26, "Init repo")
+ ButtonGadget(#GInclude, 210, 332, 90, 26, "Inclure")
+ ButtonGadget(#GExclude, 310, 332, 90, 26, "Exclure")
+ ButtonGadget(#GIncludeAll, 410, 332, 110, 26, "Tout inclure")
+ ButtonGadget(#GExcludeAll, 530, 332, 110, 26, "Tout exclure")
+ ButtonGadget(#GAdvanced, 650, 332, 80, 26, "Avancé…")
+
+ TextGadget(#GLabelMsg, 10, 372, 100, 22, "Message :")
+ StringGadget(#GStringMsg, 110, 370, 620, 24, "")
+ CheckBoxGadget(#GCheckPush, 10, 402, 120, 22, "Pousser après")
SetGadgetState(#GCheckPush, #True)
- TextGadget(#GLabelRemote, 150, 372, 60, 22, "Remote :")
- StringGadget(#GStringRemote, 210, 370, 120, 24, remote$)
- TextGadget(#GLabelBranch, 340, 372, 60, 22, "Branche :")
- ComboBoxGadget(#GComboBranch, 400, 370, 150, 24)
- ButtonGadget(#GSavePrefs, 560, 370, 110, 24, "Sauver défauts")
+ TextGadget(#GLabelRemote, 150, 402, 60, 22, "Remote :")
+ StringGadget(#GStringRemote, 210, 400, 120, 24, remote$)
+ TextGadget(#GLabelBranch, 340, 402, 60, 22, "Branche :")
+ ComboBoxGadget(#GComboBranch, 400, 400, 170, 24)
+ ButtonGadget(#GSavePrefs, 580, 400, 150, 24, "Sauver défauts")
- ButtonGadget(#GCommit, 10, 410, 120, 30, "Add + Commit")
- ButtonGadget(#GPush, 140, 410, 120, 30, "Push")
- ButtonGadget(#GPull, 270, 410, 120, 30, "Pull")
+ ButtonGadget(#GCommit, 10, 440, 120, 30, "Add + Commit")
+ ButtonGadget(#GPush, 140, 440, 120, 30, "Push")
+ ButtonGadget(#GPull, 270, 440, 120, 30, "Pull")
- ; --------- Infobulles (tooltips) ---------
+ ; Infobulles
GadgetToolTip(#GStringRepo, "Dossier du dépôt Git. Utilisez 'Parcourir…' pour le sélectionner.")
GadgetToolTip(#GButtonBrowse, "Choisir le répertoire du dépôt.")
- GadgetToolTip(#GListStatus, "État des fichiers (git status --porcelain).")
- GadgetToolTip(#GRefresh, "Rafraîchir l’état du dépôt.")
+ GadgetToolTip(#GListStatus, "Cochez pour inclure un fichier dans le prochain commit. Colonnes : Statut / Fichier.")
+ GadgetToolTip(#GRefresh, "Rafraîchir l’état du dépôt (git status --porcelain).")
GadgetToolTip(#GInit, "Initialiser un dépôt Git ici (git init).")
+ GadgetToolTip(#GInclude, "Inclure l’élément sélectionné.")
+ GadgetToolTip(#GExclude, "Exclure l’élément sélectionné.")
+ GadgetToolTip(#GIncludeAll, "Inclure tous les éléments de la liste.")
+ GadgetToolTip(#GExcludeAll, "Exclure tous les éléments de la liste.")
+ GadgetToolTip(#GAdvanced, "Ouvrir les actions avancées (branches, restauration…).")
GadgetToolTip(#GStringMsg, "Message de commit.")
GadgetToolTip(#GCheckPush, "Activer pour pousser après le commit (git push).")
GadgetToolTip(#GStringRemote, "Nom du remote (ex: origin).")
- GadgetToolTip(#GLabelRemote, "Nom du remote par défaut.")
GadgetToolTip(#GComboBranch, "Branche cible (ex: main).")
GadgetToolTip(#GSavePrefs, "Sauver remote/branche comme valeurs par défaut.")
- GadgetToolTip(#GCommit, "git add -A puis git commit -m "+Chr(34)+"message"+Chr(34)+" (et push si coché).")
+ GadgetToolTip(#GCommit, ~"git add (fichiers cochés ou -A si aucun coché) puis git commit -m \"message\" (et push si coché).")
GadgetToolTip(#GPush, "Pousser la branche (git push).")
GadgetToolTip(#GPull, "Récupérer les changements distants (git pull).")
- ; Remplir branches via la LISTE
+ ; Branches et status
NewList branchItems.s()
ListBranches(repoDir$, branchItems())
ClearGadgetItems(#GComboBranch)
- ForEach branchItems()
- AddGadgetItem(#GComboBranch, -1, branchItems())
- Next
- If branch$ <> ""
- SetGadgetText(#GComboBranch, branch$)
- EndIf
+ ForEach branchItems() : AddGadgetItem(#GComboBranch, -1, branchItems()) : Next
+ If branch$ <> "" : SetGadgetText(#GComboBranch, branch$) : EndIf
- ; Status initial
- Protected stat$, line$, n.i, i.i
- If DoStatus(repoDir$, stat$)
- ClearGadgetItems(#GListStatus)
- n = CountString(stat$, #LF$) + 1
- For i = 1 To n
- line$ = StringField(stat$, i, #LF$)
- If Trim(line$) <> ""
- AddGadgetItem(#GListStatus, -1, line$)
- EndIf
- Next i
- EndIf
+ NewList rows.FileRow()
+ LoadStatusRows(repoDir$, rows())
+ FillStatusList(rows())
+ ; Boucle
Repeat
Protected ev.i = WaitWindowEvent()
Select ev
Case #PB_Event_Gadget
Select EventGadget()
+
Case #GButtonBrowse
Protected newDir$ = PathRequester("Choisir le répertoire du dépôt", repoDir$)
If newDir$ <> ""
@@ -429,27 +660,55 @@ Procedure.i OpenGUI(initialDir$, prefsPath$)
ClearList(branchItems())
ListBranches(repoDir$, branchItems())
ClearGadgetItems(#GComboBranch)
- ForEach branchItems()
- AddGadgetItem(#GComboBranch, -1, branchItems())
- Next
+ ForEach branchItems() : AddGadgetItem(#GComboBranch, -1, branchItems()) : Next
+ ClearList(rows())
+ LoadStatusRows(repoDir$, rows())
+ FillStatusList(rows())
EndIf
Case #GRefresh
repoDir$ = GetGadgetText(#GStringRepo)
- If DoStatus(repoDir$, stat$)
- ClearGadgetItems(#GListStatus)
- n = CountString(stat$, #LF$) + 1
- For i = 1 To n
- line$ = StringField(stat$, i, #LF$)
- If Trim(line$) <> ""
- AddGadgetItem(#GListStatus, -1, line$)
- EndIf
- Next i
- EndIf
+ ClearList(rows())
+ LoadStatusRows(repoDir$, rows())
+ FillStatusList(rows())
Case #GInit
repoDir$ = GetGadgetText(#GStringRepo)
DoInitRepo(repoDir$)
+ ClearList(rows())
+ LoadStatusRows(repoDir$, rows())
+ FillStatusList(rows())
+
+ Case #GInclude
+ Protected idx.i = GetGadgetState(#GListStatus)
+ If idx >= 0
+ SetGadgetItemState(#GListStatus, idx, #PB_ListIcon_Checked)
+ ToggleIncludeAt(idx, rows())
+ EndIf
+
+ Case #GExclude
+ idx = GetGadgetState(#GListStatus)
+ If idx >= 0
+ SetGadgetItemState(#GListStatus, idx, 0)
+ ToggleIncludeAt(idx, rows())
+ EndIf
+
+ Case #GIncludeAll
+ Protected c.i = CountGadgetItems(#GListStatus)
+ For idx = 0 To c - 1 : SetGadgetItemState(#GListStatus, idx, #PB_ListIcon_Checked) : Next
+ ForEach rows() : rows()\include = 1 : Next
+
+ Case #GExcludeAll
+ c = CountGadgetItems(#GListStatus)
+ For idx = 0 To c - 1 : SetGadgetItemState(#GListStatus, idx, 0) : Next
+ ForEach rows() : rows()\include = 0 : Next
+
+ Case #GAdvanced
+ repoDir$ = GetGadgetText(#GStringRepo)
+ OpenAdvancedWindow(repoDir$)
+ ClearList(rows())
+ LoadStatusRows(repoDir$, rows())
+ FillStatusList(rows())
Case #GSavePrefs
remote$ = GetGadgetText(#GStringRemote)
@@ -468,7 +727,16 @@ Procedure.i OpenGUI(initialDir$, prefsPath$)
If Trim(msg$) = ""
MessageRequester("Commit", "Merci de saisir un message.", #PB_MessageRequester_Warning)
Else
- DoCommit(repoDir$, msg$, GetGadgetState(#GCheckPush), remote$, branch$)
+ NewList files.s()
+ CollectIncludedFiles(rows(), files())
+ If ListSize(files()) > 0
+ DoCommitSelected(repoDir$, msg$, GetGadgetState(#GCheckPush), remote$, branch$, files())
+ Else
+ DoCommit(repoDir$, msg$, GetGadgetState(#GCheckPush), remote$, branch$)
+ EndIf
+ ClearList(rows())
+ LoadStatusRows(repoDir$, rows())
+ FillStatusList(rows())
EndIf
Case #GPush
@@ -483,78 +751,21 @@ Procedure.i OpenGUI(initialDir$, prefsPath$)
branch$ = GetGadgetText(#GComboBranch)
DoPull(repoDir$, remote$, branch$)
+ Case #GListStatus
+ idx = GetGadgetState(#GListStatus)
+ If idx >= 0 : ToggleIncludeAt(idx, rows()) : EndIf
+
EndSelect
EndSelect
-
Until ev = #PB_Event_CloseWindow
ProcedureReturn 1
EndIf
-
ProcedureReturn 0
EndProcedure
-; ------------------------------------------------------------------
-; Installe l’intégration dans l’IDE PureBasic :
-; - copie le thème d’icônes (zip) dans \Themes\
-; - lance l’IDE avec /A "" pour importer les outils
-; Retourne 1 si OK, 0 sinon.
-; ------------------------------------------------------------------
-Procedure.i InstallPBGitInIDE(ideExe$, toolsPrefs$, themeZip$)
- Protected ok.i = 1
- Protected ideHome$, themesDir$, destZip$, args$, prg.i, copyOk.i
-
- If FileSize(ideExe$) <= 0 Or FileSize(toolsPrefs$) <= 0 Or FileSize(themeZip$) <= 0
- MessageRequester("Installation", "Chemins invalides. Merci de sélectionner PureBasic.exe, le fichier d’outils et le thème.", #PB_MessageRequester_Error)
- ProcedureReturn 0
- EndIf
-
- ideHome$ = GetPathPart(ideExe$)
- themesDir$ = ideHome$ + "Themes" + #PathSep$
- destZip$ = themesDir$ + GetFilePart(themeZip$)
-
- ; Créer le dossier Themes si besoin
- If FileSize(themesDir$) <> -2
- If CreateDirectory(themesDir$) = 0
- MessageRequester("Installation", "Impossible de créer le dossier Themes : " + themesDir$, #PB_MessageRequester_Error)
- ProcedureReturn 0
- EndIf
- EndIf
-
- ; Copier le thème
- copyOk = CopyFile(themeZip$, destZip$)
- If copyOk = 0
- MessageRequester("Installation", "Échec de copie du thème vers : " + destZip$, #PB_MessageRequester_Error)
- ok = 0
- EndIf
-
- ; Importer les outils via /A ""
- If ok
- args$ = "/A " + Chr(34) + toolsPrefs$ + Chr(34)
- prg = RunProgram(ideExe$, args$, "", #PB_Program_Hide | #PB_Program_Wait)
- If prg = 0
- MessageRequester("Installation", "Échec de l’import des outils (/A).", #PB_MessageRequester_Error)
- ok = 0
- EndIf
- EndIf
-
- If ok
- MessageRequester("Installation", "Intégration importée !" + #LF$ +
- "- Thème copié dans: " + destZip$ + #LF$ +
- "- Outils importés via /A", #PB_MessageRequester_Info)
- EndIf
-
- ProcedureReturn ok
-EndProcedure
-
-; ------------------------------------------------------------------
-; Assistant d’installation graphique quand PBIDE-GitTool est lancé sans paramètre.
-; - Permet de choisir PureBasic.exe, git_tools.prefs et PBGitTheme.zip
-; - Appelle InstallPBGitInIDE()
-; Retourne 1 si installation OK, 0 sinon.
-; ------------------------------------------------------------------
-
-; Gadgets de la fenêtre d'installation (évite toute collision avec l’UI principale)
+; ====== Installation IDE ======
+; Fenêtre assistant
#WInstall = 100
#GLabelIde = 110
#GStringIde = 111
@@ -569,33 +780,74 @@ EndProcedure
#GInstallCancel = 120
#GInstallNote = 121
+Procedure.i InstallPBGitInIDE(ideExe$, toolsPrefs$, themeZip$)
+ Protected ok.i = 1, ideHome$, themesDir$, destZip$, args$, prg.i, copyok.i
+
+ If FileSize(ideExe$) <= 0 Or FileSize(toolsPrefs$) <= 0 Or FileSize(themeZip$) <= 0
+ MessageRequester("Installation", "Chemins invalides. Sélectionnez PureBasic.exe, le fichier d’outils et le thème.", #PB_MessageRequester_Error)
+ ProcedureReturn 0
+ EndIf
+
+ ideHome$ = GetPathPart(ideExe$)
+ themesDir$ = ideHome$ + "Themes" + #PathSep$
+ destZip$ = themesDir$ + GetFilePart(themeZip$)
+
+ If FileSize(themesDir$) <> -2
+ If CreateDirectory(themesDir$) = 0
+ MessageRequester("Installation", "Impossible de créer le dossier Themes : " + themesDir$, #PB_MessageRequester_Error)
+ ProcedureReturn 0
+ EndIf
+ EndIf
+
+ copyok = CopyFile(themeZip$, destZip$)
+ If copyok = 0
+ MessageRequester("Installation", "Échec de copie du thème vers : " + destZip$, #PB_MessageRequester_Error)
+ ok = 0
+ EndIf
+
+ If ok
+ args$ = "/A " + Chr(34) + toolsPrefs$ + Chr(34)
+ prg = RunProgram(ideExe$, args$, "", #PB_Program_Hide | #PB_Program_Wait)
+ If prg = 0
+ MessageRequester("Installation", "Échec de l’import des outils (/A).", #PB_MessageRequester_Error)
+ ok = 0
+ EndIf
+ EndIf
+
+ If ok
+ MessageRequester("Installation", "Intégration importée !" + #LF$ +
+ "- Thème copié : " + destZip$ + #LF$ +
+ "- Outils importés via /A", #PB_MessageRequester_Info)
+ EndIf
+ ProcedureReturn ok
+EndProcedure
+
Procedure.i OpenInstallWizard()
Protected exeDefault$ = ""
Protected dirExe$ = GetPathPart(ProgramFilename())
Protected prefsDefault$ = dirExe$ + "git_tools.prefs"
Protected themeDefault$ = dirExe$ + "PBGitTheme.zip"
-
+
If OpenWindow(#WInstall, 0, 0, 680, 240, "PBIDE-GitTool — Assistant d’installation IDE", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
TextGadget(#GLabelIde, 10, 16, 140, 22, "PureBasic.exe :")
StringGadget(#GStringIde,160, 14, 420, 24, exeDefault$)
ButtonGadget(#GButtonIde,590, 14, 80, 24, "Parcourir…")
-
+
TextGadget(#GLabelTools, 10, 56, 140, 22, "Fichier outils :")
StringGadget(#GStringTools,160, 54, 420, 24, prefsDefault$)
ButtonGadget(#GButtonTools,590, 54, 80, 24, "Parcourir…")
-
+
TextGadget(#GLabelTheme, 10, 96, 140, 22, "Thème icônes :")
StringGadget(#GStringTheme,160, 94, 420, 24, themeDefault$)
ButtonGadget(#GButtonTheme,590, 94, 80, 24, "Parcourir…")
-
+
ButtonGadget(#GInstallGo, 380, 150, 140, 30, "Installer")
ButtonGadget(#GInstallCancel, 530, 150, 140, 30, "Annuler")
-
- TextGadget(#GInstallNote, 10, 190, 660, 40,
- "Conseil : placez 'git_tools.prefs' et 'PBGitTheme.zip' à côté de PBIDE-GitTool.exe pour auto-renseignement." + #LF$ +
- "Après import, choisissez le thème dans Préférences → General → Themes, puis ajoutez des boutons 'Run tool' dans la Toolbar.")
-
- ; Infobulles de l’assistant
+
+ TextGadget(#GInstallNote, 10, 190, 660, 40,
+ "Astuce : placez 'git_tools.prefs' et 'PBGitTheme.zip' à côté de PBIDE-GitTool.exe pour auto-renseignement." + #LF$ +
+ "Ensuite choisissez le thème (Préférences → Themes) et ajoutez les boutons 'Run tool' dans la Toolbar.")
+
GadgetToolTip(#GStringIde, "Chemin de PureBasic.exe (IDE).")
GadgetToolTip(#GButtonIde, "Parcourir pour sélectionner l’exécutable de l’IDE PureBasic.")
GadgetToolTip(#GStringTools, "Fichier d’outils externes à importer (/A).")
@@ -604,7 +856,7 @@ Procedure.i OpenInstallWizard()
GadgetToolTip(#GButtonTheme, "Parcourir le fichier 'PBGitTheme.zip'.")
GadgetToolTip(#GInstallGo, "Lancer l’installation (copie du thème + import des outils).")
GadgetToolTip(#GInstallCancel, "Fermer l’assistant sans rien modifier.")
-
+
Repeat
Protected ev.i = WaitWindowEvent()
If ev = #PB_Event_Gadget
@@ -612,46 +864,40 @@ Procedure.i OpenInstallWizard()
Case #GButtonIde
Protected pickExe$ = OpenFileRequester("Choisir PureBasic.exe", GetPathPart(GetGadgetText(#GStringIde)), "Exécutable|*.exe;*|Tous|*.*", 0)
If pickExe$ <> "" : SetGadgetText(#GStringIde, pickExe$) : EndIf
-
+
Case #GButtonTools
Protected pickPrefs$ = OpenFileRequester("Choisir le fichier d'outils", GetGadgetText(#GStringTools), "Prefs|*.prefs;*.txt|Tous|*.*", 0)
If pickPrefs$ <> "" : SetGadgetText(#GStringTools, pickPrefs$) : EndIf
-
+
Case #GButtonTheme
Protected pickZip$ = OpenFileRequester("Choisir le thème (zip)", GetGadgetText(#GStringTheme), "Zip|*.zip|Tous|*.*", 0)
If pickZip$ <> "" : SetGadgetText(#GStringTheme, pickZip$) : EndIf
-
+
Case #GInstallGo
Protected ok.i = InstallPBGitInIDE(GetGadgetText(#GStringIde), GetGadgetText(#GStringTools), GetGadgetText(#GStringTheme))
- If ok
- CloseWindow(#WInstall)
- ProcedureReturn 1
- EndIf
-
+ If ok : CloseWindow(#WInstall) : ProcedureReturn 1 : EndIf
+
Case #GInstallCancel
CloseWindow(#WInstall)
ProcedureReturn 0
EndSelect
EndIf
Until ev = #PB_Event_CloseWindow
-
+
ProcedureReturn 0
EndIf
-
ProcedureReturn 0
EndProcedure
; ====== Entrée ======
+; On ne coupe pas si Git manque, pour permettre l’assistant d’installation
If EnsureGitAvailable() = 0
- ; On n’arrête pas forcément l’outil si Git manque, pour l’assistant d’installation
- ; Mais on avertit : Git sera requis pour les opérations.
+ ; Averti, mais continue.
EndIf
-; Emplacement prefs locale de l’outil
+; Préférences locales de l’outil
Define baseDoc$ = GetUserDirectory(#PB_Directory_Documents)
-If Right(baseDoc$, 1) <> #PathSep$
- baseDoc$ + #PathSep$
-EndIf
+If Right(baseDoc$, 1) <> #PathSep$ : baseDoc$ + #PathSep$ : EndIf
Define prefsDir$ = baseDoc$ + "PBIDE-GitTool" + #PathSep$
If FileSize(prefsDir$) <> -2 : CreateDirectory(prefsDir$) : EndIf
Define prefsPath$ = prefsDir$ + "settings.prefs"
@@ -663,7 +909,7 @@ Define repoArg$ = "", msgArg$ = "", remoteArg$ = "", branchArg$ = ""
Define wantStatus.i = 0, wantInit.i = 0, wantCommit.i = 0, wantPush.i = 0, wantPull.i = 0
Define w.i
-; --- Si aucun paramètre : proposer l’installation IDE ---
+; Si aucun paramètre : proposer l’installation IDE
If argCount = 0
If MessageRequester("PBIDE-GitTool", "Aucun paramètre détecté." + #LF$ + "Souhaitez-vous installer l’intégration IDE (outils + thème) maintenant ?", #PB_MessageRequester_YesNo) = #PB_MessageRequester_Yes
OpenInstallWizard()
@@ -671,10 +917,10 @@ If argCount = 0
EndIf
EndIf
-; Parsing arguments
For w = 0 To argCount - 1
Define a$ = ProgramParameter(w)
Select LCase(a$)
+ Case "--project" : If w + 1 < argCount : repoArg$ = ProgramParameter(w + 1) : EndIf
Case "--repo" : If w + 1 < argCount : repoArg$ = ProgramParameter(w + 1) : EndIf
Case "--status" : wantStatus = 1 : useGui = 0
Case "--init" : wantInit = 1 : useGui = 0
@@ -683,7 +929,6 @@ For w = 0 To argCount - 1
Case "--pull" : wantPull = 1 : useGui = 0
Case "--remote" : If w + 1 < argCount : remoteArg$ = ProgramParameter(w + 1) : EndIf
Case "--branch" : If w + 1 < argCount : branchArg$ = ProgramParameter(w + 1) : EndIf
- Case "--project" : If w + 1 < argCount : repoArg$ = ProgramParameter(w + 1) : EndIf
EndSelect
Next w
@@ -692,19 +937,19 @@ If useGui
If dir$ = "" : dir$ = DirFromArgOrFallback() : EndIf
OpenGUI(dir$, prefsPath$)
Else
- ; Exécution non interactive
+ ; Mode non interactif
Define remote$ = "", branch$ = ""
LoadPrefs(prefsPath$, remote$, branch$)
If remoteArg$ <> "" : remote$ = remoteArg$ : EndIf
If branchArg$ <> "" : branch$ = branchArg$ : EndIf
-
+
Define baseDir$ = repoArg$
If baseDir$ = "" : baseDir$ = DirFromArgOrFallback() : EndIf
baseDir$ = DetectRepoRoot(baseDir$)
-
+
If wantStatus
- Define st$, ok.i = DoStatus(baseDir$, st$)
- If ok : PrintN(st$) : EndIf
+ Define st$, okstat.i = DoStatus(baseDir$, st$)
+ If okstat : PrintN(st$) : EndIf
ElseIf wantInit
DoInitRepo(baseDir$)
ElseIf wantCommit
@@ -718,9 +963,9 @@ Else
EndIf
; IDE Options = PureBasic 6.21 (Windows - x64)
-; CursorPosition = 390
-; FirstLine = 386
-; Folding = ---
+; CursorPosition = 632
+; FirstLine = 628
+; Folding = -----
; EnableXP
; DPIAware
; Executable = ..\PBIDE-GitTool.exe
diff --git a/PureBasic_Compilation0.exe b/PureBasic_Compilation0.exe
index 9978629..4e6842c 100644
Binary files a/PureBasic_Compilation0.exe and b/PureBasic_Compilation0.exe differ