- C'est un programme d'indentation automatique qui permet de remettre les espaces en début de ligne pour bien aligner le code
- On peut l'installer dans l'éditeur de PureBasic ou dans JapPB pour l'avoir sous la main et le déclancher n'importe quand
- Si on fait une sélection de code avant de le lancer, l'indentation ne se fait que sur la sélection, sinon elle se fait sur la totalité du code
Petites notes pour ceux qui ont essayé la version précédente :
- Il fonctionne désormais sur un code trés long (jusqu'à un million de caractères)
- Le presse-papier est conservé (dans la précédente version, son contenu était perdu)
- Il gère désormais parfaitement TOUS les codes comportant plusieurs instructions par ligne comme :
Code : Tout sélectionner
For i=1 to 10 : blabla () : Next
Voilà :
Code : Tout sélectionner
;*********************************************************************************************
;* Il est Possible de passer en Paramètre le nombre de Blanc correspondant à l'indentation ! *
;* La valeur par défaut (#Tab) est de "2" mais ne demande qu'à être modifiée *
;* Si #IndentComment = 1, les commentaires sont indentés, sinon ils restent alignés à gauche *
;* Programme écrit par Brossden - Complété par Zapman avec les astuces de tout le monde *
;*********************************************************************************************
Global ProgText.s,mc.s
#Tab=2
#IndentComment=1
#RC1 = Chr(13)+Chr(10)
#RC2 = ":"
#MaxSize=1000000
Blanc=0
Dejacom = 0
While getkeystate_(#VK_LMENU)<0 ; si on appelé ce programme à l'aide d'une touche
Delay(10) ; de fonction, on attend que l'utilisateur relache
Wend ; la touche
;************************************************************
;* Le truc de Fred pour augmenter la taille du buffer texte *
;* et éviter les plantage quand on manipule des grandes *
;* chaines de caractères. *
;************************************************************
Procedure SetStringManipulationBufferSize(Bytes)
PBStringBase.l = 0
PBMemoryBase.l = 0
!MOV eax, dword [PB_StringBase]
!MOV [esp+4],eax
!MOV eax, dword [PB_MemoryBase]
!MOV [esp+8],eax
HeapReAlloc_(PBMemoryBase, #GMEM_ZEROINIT, PBStringBase, Bytes)
!MOV dword [_PB_StringBase],eax
EndProcedure
; Set the buffer size for all strings to 1 MB.
SetStringManipulationBufferSize(#MaxSize)
;************************************************************
;* La procédure qui permet de savoir si le caractère que *
;* l'on vient de trouver ne se trouve pas inclus dans une *
;* chaines entre guillemets *
;************************************************************
Procedure PasEntreGuillemets (Pos,Jusqu_a)
cr.s=Mid(ProgText,Pos,1) ; cr est le caractere recherché (situé à la position "Pos")
If pos<Jusqu_a And pos: cont=1 : Else : cont=0 : EndIf ; on regarde si on n'a pas ":" avant le retour chariot
While cont ; Il y a ":", mais il est peut-être entre guillemets !
DansGuillemets=0
test=pos - 1
While test >0
mc.s=Mid(ProgText,test,1)
If Mid(ProgText,test,1)=Chr(34) ; Chr(34) est le code ascii du guillemet
DansGuillemets=DansGuillemets+1
EndIf
If Mid(ProgText,test,1)=Chr(13) Or Mid(ProgText,test,1)=Chr(10)
test = 0
Else
test - 1
EndIf
Wend
If (Int(DansGuillemets/2)*2)<>DansGuillemets ; Si le nombre de guillements est impair...
pos=FindString(ProgText,cr,(pos + 1)) ; on ne tient pas compte du signe et on recherche le suivant
If pos<Jusqu_a And pos:cont=1:Else:cont=0:EndIf ; (En tout cas si c'est encore la peine)
Else
cont=0
EndIf
Wend
If pos>Jusqu_a
pos=0
EndIf
ProcedureReturn pos
EndProcedure
;*********************************************************
;* Recherche de la Fenêtre contenant le texte à Indenter *
;*********************************************************
Hwnd = FindWindow_( 0, 0 )
While Hwnd <> 0
Txt.s = Space(256)
GetWindowText_(Hwnd, Txt, 256)
Hwnd = GetWindow_(Hwnd, #GW_HWNDNEXT)
If FindString(UCase(Txt),"PUREBASIC - ",1) = 1 And FindString(UCase(Txt),"DEBUG",1) =0
Handle=Hwnd
Hwnd=0
EndIf
Wend
;*****************************************************
;* Activation de la Fenêtre de Programme à Indenter *
;* Copie du Texte du Programme dans le presse-papier *
;* puis du contenu du presse-papier dans ProgText *
;*****************************************************
SetFocus_(Handle)
ProgText.s=""
If OpenClipboard_(WindowID())
;*****************************************************
;* On sauvegarde le contenu du presse-papier *
;*****************************************************
*hmem = GetClipboardData_(#CF_TEXT)
*D=GlobalLock_(*hmem)
If *D
SauvPP.s = PeekS(*D,#MaxSize)
GlobalUnlock_(*hmem)
EndIf
;*****************************************************
;* On vide le presse-papier *
;*****************************************************
EmptyClipboard_()
CloseClipboard_()
;*****************************************************
;* On commence par un simple "Copier" pour voir si *
;* l'utilisateur a fait une sélection *
;*****************************************************
Res = Keybd_Event_(#VK_CONTROL,0,0,0)+ Keybd_Event_(#VK_C,0,0,0)+Keybd_Event_(#VK_CONTROL,0,#KEYEVENTF_KEYUP,0)
Delay(200) ; Il faut laisser assez de temps pour les textes longs
; ProgText=GetClipboardText() Plante quand le texte
; dépasse Maxsize. On va donc utiliser une méthode
; plus complexe mais qui permet de limiter la taille
; de ce qu'on manipule.
; (Sait-on jamais, le texte fera peut-être plus de 1000000 caractères vu les heures que je passe à programmer !)
OpenClipboard_(WindowID())
*hmem = GetClipboardData_(#CF_TEXT)
*D=GlobalLock_(*hmem)
If *D
ProgText = PeekS(*D,#MaxSize)
GlobalUnlock_(*hmem)
EndIf
CloseClipboard_()
If ProgText=""
;*****************************************************
;* Si on a rien récupéré, on fait "Tout sélectionner"*
;* puis à nouveau "Copier" *
;*****************************************************
Res = Keybd_Event_(#VK_CONTROL,0,0,0)+ Keybd_Event_(#VK_A,0,0,0)+ Keybd_Event_(#VK_C,0,0,0)+Keybd_Event_(#VK_CONTROL,0,#KEYEVENTF_KEYUP,0)
Delay(200) ; Il faut laisser assez de temps pour les textes longs
OpenClipboard_(WindowID())
*hmem = GetClipboardData_(#CF_TEXT)
*D=GlobalLock_(*hmem)
If *D
ProgText = PeekS(*D,#MaxSize)
GlobalUnlock_(*hmem)
EndIf
CloseClipboard_()
EndIf
If Len(ProgText)=#MaxSize
ProgText=""
hw=OpenWindow(30, 0, 0, 20, 20, #PB_Window_ScreenCentered | #PB_Window_TitleBar , "AutoIndent")
SetForegroundWIndow_(hw)
MessageRequester("Gasp !", "Désolé, ce texte est trop long. Procédez par morceau.", 0)
CloseWindow(30)
EndIf
If ProgText<>""
ProgText=ProgText+#RC1+#RC1
;**************************
;* Sauvegarde de sécurité *
;**************************
; If CreateFile(#1,"c:\sauvegarde.bak")
; WriteString(Progtext)
; CloseFile(#1)
; EndIf
;
;Maintenant que ça marche bien, inutile poluer le disque avec une sauvegarde
;
;
;*****************************************
;* Mise en Forme du texte et Indentation *
;*****************************************
Prog.s=""
Deb = 1
voir=0
mSep.s=""
Fin = FindString(ProgText,#RC1,Deb) ; on cherche le prochain retour chariot
Sep.s= #RC1
; On va ensuite chercher le prochain signe ":"
; S'il n'est pas entre guillemets, et s'il n'est pas situé
; aprés un ";" alors on va le prendre comme fin de ligne
; à la place du retour chariot
Fin2 = PasEntreGuillemets (FindString(ProgText,#RC2,Deb),Fin)
If Fin2
Fin3 = PasEntreGuillemets (FindString(ProgText,";",Deb),Fin)
If Fin3>Fin2 Or Fin3=0 ; Si le";" n'est pas avant le ":"
Fin=Fin2
Sep=#RC2
EndIf
EndIf
While fin + 2 < Len(ProgText)
LineAvecEspaces.s = Mid(ProgText,deb,fin-deb)
LineIndent.s = Trim(LineAvecEspaces)
If LineIndent > ""
Pos.l = FindString(LineIndent," ",1)
If Pos = 0
Cde.s = LineIndent
Else
Cde=Left(LineIndent,Pos-1)
EndIf
Pos.l = FindString(LineIndent,".",1)
If Pos
Cde=Left(Cde,Pos-1)
EndIf
Cde=UCase(Cde)
ChaineRech$="*ENDIF*END*ENDSELECT*ELSE*CASE*WEND*NEXT*UNTIL*DEFAULT*ELSEIF*ENDPROCEDURE*ENDSTRUCTURE*ENDDATASECTION*"
Cde2$="*"+Cde+"*"
If FindString(ChaineRech$,Cde2$,1)
Blanc - #Tab
EndIf
If Blanc < 0: blanc=0 : EndIf
If Left(Cde,1) =";" And DejaCom = 0: DejaCom = 1 : Prog + #RC1 : EndIf ; On met une ligne blanche avant les commentaires
If Left(Cde,1)<>";" And DejaCom: DejaCom = 0 : Prog + #RC1 : EndIf ; On met une ligne blanche aprés les commentaires
; Quand le séparateur trouvé n'est pas un retour chariot, on évite de faire Trim
; afin de garder les espaces avant et aprés le ":"
If mSep=#RC1
While Left(LineAvecEspaces,1)=" "
LineAvecEspaces=Right(LineAvecEspaces,(Len(LineAvecEspaces)-1))
Wend
EndIf
If Sep=#RC1
While Right(LineAvecEspaces,1)=" "
LineAvecEspaces=Left(LineAvecEspaces,(Len(LineAvecEspaces)-1))
Wend
EndIf
; Il nous reste à gérer la constante #IndentComment
If (#IndentComment = 0 And Left(Cde,1) =";") Or mSep<>#RC1
Prog + LineAvecEspaces + Sep
Else
Prog + Space(Blanc) + LineIndent + Sep
EndIf
ChaineRech$="*IF*FOREACH*REPEAT*WHILE*FOR*SELECT*ELSE*CASE*DEFAULT*ELSEIF*PROCEDURE*STRUCTURE*DATASECTION*"
If FindString(ChaineRech$,"*"+Cde+"*",1)>0
Blanc + #Tab
EndIf
EndIf
deb = fin+Len(Sep)
mSep=Sep
Fin = FindString(ProgText,#RC1,Deb) ; Voir commentaires en début de boucle
Sep = #RC1
Fin2 = PasEntreGuillemets (FindString(ProgText,#RC2,Deb),Fin)
If Fin2
Fin3 = PasEntreGuillemets (FindString(ProgText,";",Deb),Fin)
If Fin3>Fin2 Or Fin3=0 ; Si le";" n'est pas avant le ":"
Fin=Fin2
Sep=#RC2
EndIf
EndIf
Wend
Prog=Left(Prog,(Len(Prog)-2)) ; on enlève le dernier retour chariot inutile
;*********************************************************
;* Remplacement du programme Actuel par le texte indenté *
;*********************************************************
OpenClipboard_(WindowID()) ; Je suis happy avec les API
EmptyClipboard_()
SetClipboardData_(#CF_TEXT,@Prog)
CloseClipboard_()
SetFocus_(Handle)
Res = Keybd_Event_(#VK_CONTROL,0,0,0)+Keybd_Event_(#VK_V,0,0,0)
Delay(200)
Res = Keybd_Event_(#VK_CONTROL,0,#KEYEVENTF_KEYUP,0)
Delay(200)
;*********************************************************
;* Restauration du contenu du presse-papier *
;*********************************************************
OpenClipboard_(WindowID())
EmptyClipboard_()
SetClipboardData_(#CF_TEXT,@SauvPP)
CloseClipboard_()
EndIf
Else
hw=OpenWindow(30, 0, 0, 20, 20, #PB_Window_ScreenCentered | #PB_Window_TitleBar , "AutoIndent")
SetForegroundWIndow_(hw)
MessageRequester("Gasp !", "Impossible d'ouvrir le presse-papier !!", 0)
CloseWindow(30)
EndIf