Add _SupTrim Helper

This commit is contained in:
2025-08-24 18:11:13 +02:00
parent 62b3ba4d52
commit c0148b8790

313
main.pb
View File

@@ -507,6 +507,40 @@ EndProcedure
; ---- Helpers ---------------------------------------------------------------
Procedure.s _SupTrim(text.s)
If text = "" : ProcedureReturn "" : EndIf
Protected i.i = 1
Protected j.i = Len(text)
Protected c.l
; Trim gauche : avancer tant que <= 32
While i <= j
c = Asc(Mid(text, i, 1))
If c <= 32
i + 1
Else
Break
EndIf
Wend
; Trim droite : reculer tant que <= 32
While j >= i
c = Asc(Mid(text, j, 1))
If c <= 32
j - 1
Else
Break
EndIf
Wend
If j < i
ProcedureReturn ""
Else
ProcedureReturn Mid(text, i, j - i + 1)
EndIf
EndProcedure
Procedure.s _JoinPath(base$, sub$)
Protected out$ = Trim(base$)
If out$ = "" : ProcedureReturn sub$ : EndIf
@@ -552,6 +586,60 @@ Procedure Max(nb1, nb2)
ProcedureReturn Result
EndProcedure
; ------------------------------------------------------------------
; Récupération récursive de TOUS les fichiers du workdir
; Remplit main\listFilesGit() avec un statut " " (clean/unmodified)
; ------------------------------------------------------------------
; --- Helper interne : scanne un dossier et alimente la liste
Procedure _ScanAndFillAllFiles(dir$, root$)
Protected did.i = ExamineDirectory(#PB_Any, dir$, "*")
If did = 0 : ProcedureReturn : EndIf
While NextDirectoryEntry(did)
Protected name$ = DirectoryEntryName(did)
If name$ = "." Or name$ = ".." : Continue : EndIf
Protected full$ = dir$ + name$
Debug full$
If DirectoryEntryType(did) = #PB_DirectoryEntry_Directory
; Ignorer le dépôt interne
If LCase(name$) <> ".git"
If Right(full$, 1) <> #PS$ : full$ + #PS$ : EndIf
_ScanAndFillAllFiles(full$, root$)
EndIf
Else
; Fichier : on ajoute une ligne dans main\listFilesGit()
Protected rel$ = Mid(full$, Len(root$) + 1)
rel$ = ReplaceString(rel$, "\", "/") ; chemins normalisés
AddElement(main\listFilesGit())
main\listFilesGit()\name = rel$
main\listFilesGit()\status = " " ; 2 espaces = clean
main\listFilesGit()\indexStatus = " "
main\listFilesGit()\workingTreeStatus = " "
main\listFilesGit()\statusDescription = "Unmodified"
EndIf
Wend
FinishDirectory(did)
EndProcedure
; --- API publique : appelle ceci pour remplir la liste
Procedure.i FillAllFilesRecursively()
root$ = GetCurrentDirectory()
; Normalise avec un séparateur de fin
If Right(root$, 1) <> "\" And Right(root$, 1) <> "/" : root$ + "/" : EndIf
; On n'efface pas ici pour laisser le choix à l'appelant
_ScanAndFillAllFiles(root$, root$)
ProcedureReturn ListSize(main\listFilesGit())
EndProcedure
Procedure.i EnsureGitAvailable()
Debug "EnsureGitAvailable()"
@@ -702,6 +790,8 @@ EndProcedure
Procedure.s GetStatusDescription(status.s)
Select status
Case " "
ProcedureReturn "Unmodified" ;Non modifié
Case "M "
ProcedureReturn "Modified in index";Modifié dans index seulement
Case " M"
@@ -750,8 +840,8 @@ Procedure.s GetStatusDescription(status.s)
EndProcedure
Procedure GetGitStatus()
; Vider la liste existante
ClearList(main\listFilesGit())
; Ne PAS vider la liste ici : on veut pouvoir mettre à jour des entrées existantes
; ClearList(main\listFilesGit()) ; <-- laissé intentionnellement commenté
; Configuration pour git status --porcelain --ignored
main\Gitcall\args = "status --porcelain --ignored"
@@ -806,27 +896,44 @@ Procedure GetGitStatus()
For i = 0 To ArraySize(lines())
line$ = lines(i)
If line$ <> ""
; Le format est : XY filename
; Le format est : XY␠<filename>
; X = index status, Y = working tree status
If Len(line$) >= 3
status$ = Left(line$, 2)
index$ = Left(line$, 1)
worktree$ = Mid(line$, 2, 1)
name$ = Mid(line$, 4) ; chemin tel que renvoyé par Git
name$ = ReplaceString(name$, "\", "/") ; normalisation (par sécurité)
; ----- MODIF: chercher si l'entrée existe déjà -----
found.b = #False
ForEach main\listFilesGit()
If main\listFilesGit()\name = name$
found = #True
; Mise à jour uniquement
main\listFilesGit()\status = status$
main\listFilesGit()\indexStatus = index$
main\listFilesGit()\workingTreeStatus = worktree$
main\listFilesGit()\statusDescription = GetStatusDescription(status$)
Break
EndIf
Next
; Si non trouvée, on l'ajoute
If Not found
AddElement(main\listFilesGit())
; Extraire le status (2 premiers caractères)
main\listFilesGit()\status = Left(line$, 2)
main\listFilesGit()\indexStatus = Left(line$, 1)
main\listFilesGit()\workingTreeStatus = Mid(line$, 2, 1)
; Extraire le nom du fichier (à partir du 4ème caractère)
main\listFilesGit()\name = Mid(line$, 4)
; Obtenir la description du status
main\listFilesGit()\statusDescription = GetStatusDescription(main\listFilesGit()\status)
main\listFilesGit()\name = name$
main\listFilesGit()\status = status$
main\listFilesGit()\indexStatus = index$
main\listFilesGit()\workingTreeStatus = worktree$
main\listFilesGit()\statusDescription = GetStatusDescription(status$)
EndIf
; ----- FIN MODIF -----
EndIf
EndIf
Next
Debug "Récupération des status Git réussie. " + Str(ListSize(main\listFilesGit())) + " fichiers trouvés."
Debug "Récupération des status Git réussie. " + Str(ListSize(main\listFilesGit())) + " fichiers (maj/ajout)."
ProcedureReturn #True
Else
@@ -835,6 +942,7 @@ Procedure GetGitStatus()
EndIf
EndProcedure
; Récupère le nombre immédiatement avant un mot-clé dans une ligne
Procedure.i ExtractNumberBefore(word.s, line.s)
Protected pos = FindString(line, word, 1)
@@ -1151,6 +1259,10 @@ EndProcedure
;-Suite
Procedure AddRemoteRepo(Url.s,name.s="origin")
Url=_SupTrim(Url)
name=_SupTrim(name)
Debug "Url="+Url
Debug "name="+name
;Check if this remote already exists
main\Gitcall\args = "remote get-url "+name
If RunExe(@main\Gitcall) = 0
@@ -1172,7 +1284,7 @@ EndProcedure
Procedure GetRemoteUrl(name.s="origin")
main\Gitcall\args = "remote get-url "+name
If RunExe(@main\Gitcall) = 0
SetGadgetText(#GdtFieldRemote,main\GitCall\output)
SetGadgetText(#GdtFieldRemote,_SupTrim(main\GitCall\output))
Else
SetGadgetText(#GdtFieldRemote,"")
EndIf
@@ -1208,6 +1320,111 @@ Procedure DoPull()
EndIf
EndProcedure
Procedure.s ExtractRepoNameFromUrl(url.s)
; helper for Doclone
; Extraire le nom du dépôt depuis l'URL
Protected repoName.s, parts.i, i.i
; Supprimer .git à la fin si présent
If Right(url, 4) = ".git"
url = Left(url, Len(url) - 4)
EndIf
; Remplacer les \ par des / pour uniformiser
url = ReplaceString(url, "\", "/")
; Compter le nombre de parties séparées par /
parts = CountString(url, "/")
; Extraire la dernière partie
If parts > 0
repoName = StringField(url, parts + 1, "/")
Else
repoName = url
EndIf
ProcedureReturn repoName
EndProcedure
Procedure.s GetParentPath(path.s)
Protected parentPath.s
; Supprimer le séparateur final si présent
If Right(Path, 1) = "\" Or Right(Path, 1) = "/"
Path = Left(Path, Len(Path) - 1)
EndIf
; Utiliser GetPathPart() qui retourne le chemin sans le fichier/dossier final
parentPath = GetPathPart(path)
ProcedureReturn parentPath
EndProcedure
Procedure DoClone()
Protected remoteUrl.s, repoName.s, targetFolder.s, currentDir.s, choice.i
remoteUrl = Trim(GetGadgetText(#GdtFieldRemote))
If remoteUrl = ""
MessageRequester("Git Clone", "Échec: " + #LF$ + "You Must have a remote URL", #PB_MessageRequester_Error)
ProcedureReturn #False
EndIf
; Extraire le nom du dépôt depuis l'URL
Debug "remoteUrl="+remoteUrl
repoName = ExtractRepoNameFromUrl(remoteUrl)
Debug "repoName="+repoName
; Obtenir le chemin complet du répertoire courant
currentDir = GetCurrentDirectory()
; Demander à l'utilisateur où cloner
choice = MessageRequester("Git Clone - Destination",
"Où voulez-vous cloner le dépôt ?" + #LF$ + #LF$ +
"OUI: Créer un répertoire '" + repoName + "' dans le répertoire courant" + #LF$ +
" → " + currentDir + repoName + "/" + #LF$ + #LF$ +
"NON: Cloner directement dans le répertoire courant" + #LF$ +
" → " + currentDir + #LF$ + #LF$ +
"ANNULER: Annuler l'opération",
#PB_MessageRequester_YesNoCancel)
Select choice
Case #PB_MessageRequester_Yes
; Créer un nouveau répertoire avec le nom du dépôt
targetFolder = repoName
main\Gitcall\args = "clone " + remoteUrl + " " + targetFolder
Case #PB_MessageRequester_No
; Cloner directement dans le répertoire courant (doit être vide)
SetCurrentDirectory(GetParentPath(GetGadgetText(#GgtFieldRepo)))
targetFolder = "."
main\Gitcall\args = "clone " + remoteUrl + " " + targetFolder
Case #PB_MessageRequester_Cancel
; Annuler l'opération
ProcedureReturn #False
EndSelect
; Exécuter la commande git clone
If RunExe(@main\Gitcall) = 0
If targetFolder = "."
MessageRequester("Git Clone", "Succès:" + #LF$ +
"Dépôt cloné dans le répertoire courant" + #LF$ + #LF$ +
main\Gitcall\output, #PB_MessageRequester_Info)
Else
MessageRequester("Git Clone", "Succès:" + #LF$ +
"Dépôt cloné dans le répertoire: " + targetFolder + "/" + #LF$ + #LF$ +
main\Gitcall\output, #PB_MessageRequester_Info)
EndIf
AddRemoteRepo(remoteUrl)
SetCurrentDirectory(GetGadgetText(#GgtFieldRepo))
CreateThread(@RefreshFileList(),0)
ProcedureReturn #True
Else
MessageRequester("Git Clone", "Échec: " + #LF$ + main\Gitcall\errors, #PB_MessageRequester_Error)
ProcedureReturn #False
EndIf
EndProcedure
Procedure DoStatus()
Protected *status.GitStatus=@main\GitStatus
@@ -1397,7 +1614,7 @@ EndProcedure
Procedure.s GetBranchesList()
ClearGadgetItems(#GdtSlctBranch)
main\Gitcall\args = "branch"
main\Gitcall\args = "branch -a"
If RunExe(@main\Gitcall) <> 0
ProcedureReturn ""
EndIf
@@ -1586,7 +1803,7 @@ Procedure RefreshFileList(null.i)
ClearGadgetItems(#GdtListStatus)
ClearList(main\listFilesGit())
;-Init File List
DoLsFilesByType("C")
FillAllFilesRecursively()
;DoLsFilesByType("D")
;DoLsFilesByType("O")
;DoLsFilesByType("I")
@@ -1604,6 +1821,8 @@ Procedure RefreshFileList(null.i)
Next
DisableGadget(#GdtListStatus,#False)
DisableGadget(#GdtBtnRefresh,#False)
GetBranchesList()
GetRemoteUrl()
EndProcedure
Procedure UpdateHelp(txt.s)
@@ -1706,6 +1925,13 @@ Procedure InitGadget()
EndProcedure
Macro RightGadget(GDT)
GadgetX(GDT)+GadgetWidth(GDT)
EndMacro
Macro DownGadget(GDT)
GadgetY(GDT)+GadgetHeight(GDT)
EndMacro
Procedure OpenGUI()
Protected argCount.l=CountProgramParameters(), w.l,a$
@@ -1731,11 +1957,9 @@ Procedure OpenGUI()
EndIf
; --- Dimensions générales ---
#WinW = 950
#WinH = 930 ; plus haut pour la zone daide
#PanelX = 15
#PanelY = 15
#WinH = 720 ; plus haut pour la zone daide
#PanelW = 920
#PanelH = 700
#PanelH = 500
#InPad = 15 ; marge interne au Panel
#FrmGap = 10 ; espace vertical entre frames
#RowH = 26
@@ -1743,15 +1967,16 @@ Procedure OpenGUI()
If OpenWindow(#WinMain, 0, 0, #WinW, #WinH, "Git helpmate", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
PanelGadget(#gdtPnl, #PanelX, #PanelY, #PanelW, #PanelH)
PanelGadget(#GdtPnl, #InPad,#InPad, #PanelW, #PanelH)
; ============================================================
; Onglet 1 : Dépôt
; ============================================================
AddGadgetItem(#gdtPnl, -1, T("#gdtPnl-Repo","Dépôt"))
Protected PanelH.l=WindowHeight(#WinMain)- 2*#InPad
Protected PanelW.l=900
; ---- Cadre "Dépôt local" ----
FrameGadget(#GdtFrmLocal, #InPad, #InPad, #PanelW - 2*#InPad, 100, T("GdtFrmLocal","Dépôt local"))
FrameGadget(#GdtFrmLocal, #InPad, #InPad, PanelW - 2*#InPad, 100, T("GdtFrmLocal","Dépôt local"))
TextGadget(#GdtLblRepo, #InPad + 10, #InPad + 30, 60, 22, T("GdtLblRepo","Dépôt :"))
StringGadget(#GgtFieldRepo, #InPad + 75, #InPad + 28, #PanelW - 2*#InPad - 75 - 105, #RowH, repoDir$)
ButtonGadget(#GdtBtnBrowseRepo, #PanelW - #InPad - 95, #InPad + 28, 95, #RowH, T("GdtBtnBrowseRepo","Parcourir…"))
@@ -1857,12 +2082,25 @@ Procedure OpenGUI()
CloseGadgetList()
; ============================================================
; Zone daide (plus haute grâce à #PanelH réduit)
; Aide à droite du Panel (sans splitter)
; ============================================================
Define helpY = #PanelY + #PanelH + 10
;FrameGadget(#GdtFrmHelp, #PanelX, helpY, #PanelW, #WinH - helpY - #PanelX, T("GdtFrmHelp","Aide"))
WebViewGadget(#GdtHelp, #PanelX + 10, helpY + 25, #PanelW - 20, #WinH - helpY - #PanelX - 35)
; On garde #PanelW / #PanelH tels quels
Define helpGap = 10 ; espace entre panel et aide
Define helpX = #InPad + #PanelW + helpGap ; à droite du panel
Define helpY = #InPad
Define helpW = WindowWidth(#WinMain)-GadgetWidth(#gdtPnl)- #InPad*4 ; reste de largeur jusqu'à la marge droite
Define helpH = #PanelH ; même hauteur que le panel
; (Optionnel) borne minimale si besoin
If helpW < 100 : helpW = 100 : EndIf
; Soit en direct :
WebViewGadget(#GdtHelp, helpX, helpY, helpW, helpH)
; — ou, si tu veux un cadre :
; FrameGadget(#GdtFrmHelp, helpX, helpY, helpW, helpH, T("GdtFrmHelp","Aide"))
; WebViewGadget(#GdtHelp, helpX + 10, helpY + 25, helpW - 20, helpH - 35)
SetGadgetText(#GgtFieldRepo,main\GitCall\workdir)
@@ -1901,19 +2139,26 @@ Procedure OpenGUI()
Case #GdtBtnRefresh
CreateThread(@RefreshFileList(),0)
Case #GgtFieldRepo
If EventType()=#PB_EventType_Change
If EventType()=#PB_EventType_LostFocus
main\GitCall\workdir=GetGadgetText(#GgtFieldRepo)
CreateThread(@RefreshFileList(),0)
EndIf
Case #GdtBtnBrowseRepo
Protected path.s=PathRequester("Select Folder",main\GitCall\workdir,WindowID(#WinMain))
If path<>"" And FileSize(path)=-2
main\GitCall\workdir=path
SetCurrentDirectory(main\GitCall\workdir)
SetGadgetText(#GgtFieldRepo,main\GitCall\workdir)
CreateThread(@RefreshFileList(),0)
EndIf
Case #GdtFieldRemote
;If EventType()=#PB_EventType_LostFocus
; AddRemoteRepo(GetGadgetText(#GdtFieldRemote),"origin")
; EndIf
Case #GdtBtnClone
DoClone()
Case #GdtBtnPush
DoPush()
Case #GdtBtnPull
@@ -1957,9 +2202,9 @@ OpenGUI()
; IDE Options = PureBasic 6.21 (Windows - x64)
; CursorPosition = 1947
; FirstLine = 1906
; Folding = --------
; CursorPosition = 541
; FirstLine = 509
; Folding = ----------
; Optimizer
; EnableThread
; EnableXP