AHK Auto Formatter?

Get help with using AutoHotkey and its commands and hotkeys
User avatar
LazyMan
Posts: 26
Joined: 14 Jan 2014, 00:22
Location: peering out from behind my favorite rock

AHK Auto Formatter?

30 Jan 2014, 00:36

Auto-Syntax-Tidy v12 does not seem to be available now. :| Is there another auto formatter for AHK? Or perhaps you still use AHKTidy and could post it here? Thanks.
User avatar
LazyMan
Posts: 26
Joined: 14 Jan 2014, 00:22
Location: peering out from behind my favorite rock

Re: AHK Auto Formatter?

31 Jan 2014, 21:13

TLM found it and credited tidbit: Auto-Syntax-Tidy.ahk

Thanks again :D
Remonell
Posts: 5
Joined: 15 Jul 2016, 19:53

Re: AHK Auto Formatter?

23 Jan 2018, 18:35

Hi, if you still have it, could you please reupload it somewhere?
FanaticGuru
Posts: 1235
Joined: 30 Sep 2013, 22:25

Re: AHK Auto Formatter?

23 Jan 2018, 18:44

Remonell wrote:Hi, if you still have it, could you please reupload it somewhere?
Here it is but I don't believe it works with the current version of AutoHotkey.

Code: Select all

;Change indentation and case of commands according to syntax
;by toralf & hajos
;requires AHK 1.0.44.09
;www.autohotkey.com/forum/topic7810.html

Version = v12
ScriptName =  Auto-Syntax-Tidy %Version%

; Known limitations:
;  - a space is required after the last ":" for hotkeys, hotstrings and subroutine
;  - comments might not have the right indentation in certain strongly
;      encapsulated block-structures, due to not knowing what the next line will bring.
;  - case correction only works for words longer than 4 characters,
;      (except: (in all cases) If, Loop, Else
;               (optional)     Goto, Gui, Run, Exit, Send, Sort, Menu
;                              Parse, Read, Mouse, SendAndMouse, Default, Permit, Screen, Relative
;                              Pixel, Toggle, UseErrorLevel, AlwaysOn, AlwaysOff
;      !!! caution !!! case correction is dangerous, since WinTitles in commands are case sensitive
;
;  - after doing indentation in an editor the cursor jumps
;      to the first position in the last line
;  - Indentation might fail, if a "{" is the last character of a Loop or If statement that
;      doesn't support OTB. E.g. "If x = {" or "Loop, Parse, Var, {"
;
; Functionality:
;  - Gui: For drag&drop of files, setting of options and feedback
;  - command line option "/in" for file and "/log" for log file
;  - command line option "/hidden" to start script with hidden GUI
;  - command line option "/watch hwnd" to start script with hidden GUI, closes itself when hwnd closes 
;  - command line option "/toggle" checks if another instance is running and closes both scripts
;  - command line option "/hidden" to start script without GUI
;  - Options:
;          - custom hotkey for indenation                                                    
;          - custom file extension             (overwrites old file if nothing is specified)
;          - custom indentation                (one tab or a number of spaces)
;          - different indentation styles      (Rajat, Toralf or BoBo)
;          - indentation of continuation lines (a number of tabs or spaces)
;          - indentation preservation of block continuation lines (round brackets) On/Off
;          - indentation preservation of block comments           (/* ... */)      On/Off
;          - case correction for syntax words with more than 4 characters  (thanks Rajat)
;          - statistics for script (lines of code, comments, total and empty an time needed)
;  - Dropped Files: Contents will be indented and copied to a new file with a user
;                   defined extension (overwrites old file if nothing is specified).
;  - Hotkey (F2): Highlighted syntax in an editor will be indented, if nothing is
;                 highlighted all text will be indented. (thanks ChrisM)
;  - Gui remembers last position and settings between sessions (thanks Rajat)
;  - The case of subroutine calls and function calls is adjusted to the case
;        of their respective definitions
;  - Ctrl-d toggles debug mode
;  - 12% faster then version 7 (due to shortened loop cycles) but 90 lines longer
;
; !!! Not heavily tested !!!!  ---- !!!!!! Backup your data !!!!!
;
; Suggestions are appreciated
;
; Wish:
;  - Option to strip code: Remove empty lines, all comments, and join split expressions (&&/AND/OR/||)

/*
changes since version 11:
- tray icon allows to toggle show/hide of GUI and to exit script
- added progressbar if identation is done inside an editor and blockinput is used to limit interference
- shortend code with functions, with new features the line numbers stay equal 
- log text is scrolled to the end
- on /hidden, gui is created but hidden, tray icon is visible in both cases.
- on "/watch hwnd" , gui is hidden and closes itself when hwnd closes
- on /toggle, script checks if another instance is running and closes both scripts
- improved possibilty to find path of AHK
- added warning message if syntax files do not exist
- OwnHotkey is stored in INI file and has a control in the GUI
*/

#SingleInstance off
SetBatchLines, -1

;set working dir, in case this script is called from some other script in a different dir 
SetWorkingDir, %A_ScriptDir%

;process command line parameters   ;by Ace_NoOne - www.autohotkey.com/forum/viewtopic.php?t=7556
If %0%{
    Loop, %0% { ; for each command line parameter
        next := A_Index + 1           ;get next parameters number
        ; check if known command line parameter exists
        If (%A_Index% = "/in")
            param_in := %next%   ;assign next command line parameter as value
        Else If (%A_Index% = "/log")
            param_log := %next%
        Else If (%A_Index% = "/hidden")
            param_hidden = Hide
        Else If (%A_Index% = "/watch"){
            param_hidden = Hide
            param_watch := %next%
        }Else If (%A_Index% = "/toggle")
            GoSub, CheckAndToggleRunState
      }
  }

;Turn DebugMode on (=1) to show MsgBox with Debug Info
DebugMode = 0

;location of icon file
If ( A_OSType = "WIN32_WINDOWS" )  ; Windows 9x
    IconFile = %A_WinDir%\system\shell32.dll
Else
    IconFile = %A_WinDir%\system32\shell32.dll

;tray menu
Menu, Tray, Icon, %IconFile%, 56   ;icon for taskbar and for Process in task manager
Menu, Tray, Tip, %ScriptName%
Menu, Tray, NoStandard
Menu, Tray, Add, Show/Hide, ShowHideGui
Menu, Tray, Add, Exit, ExitApp
Menu, Tray, Default, Show/Hide
Menu, Tray, Click, 1

SplitPath, A_ScriptName, , , , OutNameNoExt
IniFile = %OutNameNoExt%.ini
Gosub, ReadDataFromIni

;find path to AHK 
If !FileExist(AHKPath){
    SplitPath, A_AHKPath,, AHKPath
    If !FileExist(AHKPath){
        RegRead, AHKPath, HKLM, Software\AutoHotkey, InstallDir
        If !FileExist(AHKPath){
            RegRead, AHKPath, HKCR, Applications\AutoHotkey.exe\shell\Open\Command 
            StringTrimLeft, AHKPath, EdtAHKPath, 1
            StringTrimRight, AHKPath, EdtAHKPath, 24
            If !FileExist(AHKPath){
                AHKPath = %A_ProgramFiles%\AutoHotkey
                If !FileExist(AHKPath){
                    AHKPath = C:\Programme\AutoHotkey 
                    If !FileExist(AHKPath){
                        AHKPath = 
                      }
                  }
              }
          }
      }
  }
IfNotExist %AHKPath%
  { MsgBox,,, Could not find the AutoHotkey folder.`nPlease edit the script:`n%A_ScriptFullPath%`nin Linenumber: %A_LineNumber%
    ExitApp
  }

Gosub, ReadSyntaxFiles

If FileExist(param_in){
    Gosub, IndentFile
    ExitApp
  }

Gosub, BuildGui

If param_watch
    SetTimer, WatchWindow, On

;disable hotkey in its own gui
Hotkey, IfWinNotActive, %GuiUniqueID%
;set hotkey and remember it
Hotkey, %OwnHotkey%, IndentHighlightedText
OldHtk = %OwnHotkey%
Hotkey, IfWinNotActive,  
Return
;#############   End of autoexec section   ####################################

;#############   Toogle debug modus   #########################################
^d::
  DebugMode := not DebugMode
  ToolTip, DebugMode = %DebugMode%
  Sleep, 1000
  ToolTip
Return

;#############   Close script when watch window doesn't exist   ###############
WatchWindow:
  DetectHiddenWindows, On
  If !WinExist("ahk_id " param_watch)  ;check if watch window exists
      GoSub, GuiClose                  ;if not close this script
  DetectHiddenWindows, Off
Return

;#############   Toogle run status - close on second run   ####################
CheckAndToggleRunState:
  ;get own PID
  Process, Exist 
  OwnPID := ErrorLevel
  
  ;get own title
  If A_IsCompiled
      OwnTitle := A_ScriptFullPath
  Else
      OwnTitle := A_ScriptFullPath " - AutoHotkey v" A_AhkVersion
  
  ;get list of all windows
  DetectHiddenWindows, On 
  WinGet, WinIDs, List 
  
  ;go through list and get their titles 
  Loop, %WinIDs% {
      UniqueID := "ahk_id " WinIDs%A_Index% 
      WinGetTitle, winTitle, %UniqueID%
      
      ;check if there is a window with the same title as this script but not itself
      If (winTitle = OwnTitle ) {
          WinGet, winPID, PID, %UniqueID% 
          If (winPID <> OwnPID) {
              ;close it and itself
              Process, Close, %winPID%  
              ExitApp
            }
        }    
    } 
  DetectHiddenWindows, off
Return

;#############   Read directives and commands from syntax file   ##############
ReadSyntaxFiles:
  ;path to syntax files
  PathSyntaxFiles = %AHKPath%\Extras\Editors\Syntax

  ;clear lists
  ListOfDirectives =
  ListOfIFCommands =

  ;read each line of syntax file and search for directives and if-keywords
  CommandNamesFile = %PathSyntaxFiles%\CommandNames.txt
  IfNotExist %CommandNamesFile%
  { MsgBox,,, Could not find the "CommandNames.txt" file.`nPlease edit the script:`n%A_ScriptFullPath%`nin Linenumber: %A_LineNumber%
    ExitApp
  }
  Loop, Read , %CommandNamesFile%   ;Read syntax file
    { ;remove spaces from read line
      Line = %A_LoopReadLine%

      ;get first character and first 2 characters of line
      StringLeft,FirstChar, Line ,1
      StringLeft,FirstTwoChars, Line ,2

      ;if line is comment, continue with next line
      If (FirstChar = ";")
          Continue
      ;otherwise if keyword is directive or if-keyword add it to list
      Else If (FirstChar = "#")
          ListOfDirectives=%ListOfDirectives%,%Line%
      Else If (FirstTwoChars = "if") {
          ;get first word, since If-keywords in the syntax file have more words
          StringSplit, Array, Line, %A_Space%
          Line = %Array1%
          If (StrLen(Line) > 4)
              ListOfIFCommands=%ListOfIFCommands%,%Line%
        }
    }
  ;remove first comma and change to lower char
  StringTrimLeft,ListOfIFCommands,ListOfIFCommands,1
  StringTrimLeft,ListOfDirectives,ListOfDirectives,1

  ;remove multiple If
  Sort, ListOfIFCommands, U D,

  ;read in all variable names
  FileRead, Variables, *t %PathSyntaxFiles%\Variables.txt
  StringReplace , Variables , Variables , `n , | , All

  FilesSyntax = CommandNames|Keywords|Keys

  ;Loop over all syntax files
  Loop, Parse, FilesSyntax,|
    { String =
      SyntaxFile = %PathSyntaxFiles%\%A_LoopField%.txt
      IfNotExist %SyntaxFile%
        { MsgBox,,, Could not find the syntax file "%A_LoopField%.txt".`nPlease edit the script:`n%A_ScriptFullPath%`nin Linenumber: %A_LineNumber%
          ExitApp
        }
      ;read each line of syntax file
      Loop, Read , %SyntaxFile%
        {
          ;remove spaces from read line
          Line = %A_LoopReadLine%

          ;get first character, length of line and look for spaces
          StringLeft,FirstChar, Line ,1

          ;if line contains spaces, continue with next line
          If InStr(Line," ")
              Continue
          ;if line is empty, continue with next line
          Else If Line is Space
              Continue
          ;if line is comment, continue with next line
          Else If (FirstChar = ";")
              Continue
          ;otherwise if word is longer than 4 character, remember it
          Else If (StrLen(Line) > 4 )
              String = %String%,%Line%
        }
      ;remove first pipe
      StringTrimLeft,String,String,1
      ;store remembered string in var which has same name as syntaxfile
      %A_LoopField% := String
    }

  CommandNames = %CommandNames%,Goto,Gui,Run,Exit,Send,Sort,Menu
          ,Parse,Read,Mouse,SendAndMouse,Default,Permit,Screen,Relative
          ,Pixel,Toggle,UseErrorLevel,AlwaysOn,AlwaysOff

  ;read in all function names
  BuildInFunctions =
  ;read each line of syntax file
  FunctionsFile = %PathSyntaxFiles%\Functions.txt
  IfNotExist %SyntaxFile%
    { MsgBox,,, Could not find the "Functions.txt" file.`nPlease edit the script:`n%A_ScriptFullPath%`nin Linenumber: %A_LineNumber%
      ExitApp
    }
  Loop, Read , %FunctionsFile%
    { ;remove spaces from read line
      Line = %A_LoopReadLine%

      ;get first character, and name of function plus its braket, e.g. "ATan("
      StringLeft,FirstChar, Line ,1
      StringSplit, Line, Line, (

      ;if line is empty, continue with next line
      If Line is Space
          Continue
      ;if line is comment, continue with next line
      Else If (FirstChar = ";")
          Continue
      ;otherwise remember it with braket
      Else
          BuildInFunctions = %BuildInFunctions%,%Line1%(
    }
  ;don't remove first comma, it will be done just before correction

Return

;#############   Read Data from Ini file   ####################################
ReadDataFromIni:
  IniRead, Extension, %IniFile%, Settings, Extension, _autoindent_%Version%.ahk
  IniRead, Indentation, %IniFile%, Settings, Indentation, 2
  IniRead, NumberSpaces, %IniFile%, Settings, NumberSpaces, 2
  IniRead, NumberIndentCont, %IniFile%, Settings, NumberIndentCont, 8
  IniRead, IndentCont, %IniFile%, Settings, IndentCont, 2
  IniRead, Style, %IniFile%, Settings, Style, 2
  IniRead, CaseCorrectCommands, %IniFile%, Settings, CaseCorrectCommands, 1
  IniRead, CaseCorrectVariables, %IniFile%, Settings, CaseCorrectVariables, 1
  IniRead, CaseCorrectBuildInFunctions, %IniFile%, Settings, CaseCorrectBuildInFunctions, 1
  IniRead, CaseCorrectKeys, %IniFile%, Settings, CaseCorrectKeys, 1
  IniRead, CaseCorrectKeywords, %IniFile%, Settings, CaseCorrectKeywords, 1
  IniRead, CaseCorrectDirectives, %IniFile%, Settings, CaseCorrectDirectives, 1
  IniRead, Statistic, %IniFile%, Settings, Statistic, 1
  IniRead, ChkSpecialTabIndent, %IniFile%, Settings, ChkSpecialTabIndent, 1
  IniRead, KeepBlockCommentIndent, %IniFile%, Settings, KeepBlockCommentIndent, 0
  IniRead, AHKPath, %IniFile%, Settings, AHKPath, %A_Space%
  IniRead, OwnHotkey, %IniFile%, Settings, OwnHotkey, F2
Return

OwnHotKey:
  ;deacticate old hotkey
  Hotkey, IfWinNotActive, %GuiUniqueID%
  Hotkey, %OldHtk%, IndentHighlightedText, Off
  ;Don't allow no hotkey
  If OwnHotkey is space
    {
      Hotkey, %OldHtk%, IndentHighlightedText
      GuiControl, , OwnHotKey, %OldHtk%
  }Else{
      Hotkey, %OwnHotkey%, IndentHighlightedText
      OldHtk = %OwnHotkey%
    }
  Hotkey, IfWinNotActive,
Return

;#############   Build GUI for Auto-Syntax-Tidy   #############################
BuildGui:
  LogText = Drop your files for indentation on this Gui.`nOr highlight AHK syntax in script and press %OwnHotkey%.`n`n

  Gui, +ToolWindow +AlwaysOnTop
  Gui, Add, Text, xm Section ,Hotkey
  Gui, Add, Hotkey, ys-3 r1 w165 vOwnHotKey gOwnHotKey, %OwnHotKey%

  Gui, Add, Text, xm Section ,Extension for files
  Gui, Add, Edit, ys-3 r1 w117 vExtension, %Extension%

  Gui, Add, GroupBox, xm w210 r6.3,Indentation
  Gui, Add, Text, xp+8 yp+15 Section,Type:
  Gui, Add, Radio, ys vIndentation,1xTab or
  Gui, Add, Radio, ys Checked,Spaces
  Gui, Add, Edit, ys-3 r1 Limit1 Number w15 vNumberSpaces, %NumberSpaces%
  Gui, Add, Text, xs Section,Style:
  Gui, Add, Radio, x+8 ys vStyle,Rajat
  Gui, Add, Radio, x+8 ys Checked,Toralf
  Gui, Add, Radio, x+8 ys ,BoBo
  Gui, Add, Text, xs Section,Indentation of Method1 continuation Lines:
  Gui, Add, Edit, xs ys+15 Section r1 Limit2 Number w20 vNumberIndentCont, %NumberIndentCont%
  Gui, Add, Radio, ys+4 vIndentCont ,Tabs or
  Gui, Add, Radio, ys+4 Checked,Spaces
  Gui, Add, Checkbox, xs vKeepBlockCommentIndent Checked%KeepBlockCommentIndent%, Preserve indent. in Block comments
  Gui, Add, Checkbox, xs vChkSpecialTabIndent Checked%ChkSpecialTabIndent%, Special "Gui,Tab" indent

  Gui, Add, GroupBox, xm w210 r3,Case-Correction for
  Gui, Add, Checkbox, xp+8 yp+18 Section vCaseCorrectCommands Checked%CaseCorrectCommands%,Commands
  Gui, Add, Checkbox, vCaseCorrectVariables Checked%CaseCorrectVariables%,Variables
  Gui, Add, Checkbox, vCaseCorrectBuildInFunctions Checked%CaseCorrectBuildInFunctions%,Build in functions
  Gui, Add, Checkbox, ys vCaseCorrectKeys Checked%CaseCorrectKeys%,Keys
  Gui, Add, Checkbox, vCaseCorrectKeywords Checked%CaseCorrectKeywords%,Keywords
  Gui, Add, Checkbox, vCaseCorrectDirectives Checked%CaseCorrectDirectives%,Directives
  Gui, Add, Text, xm Section, Information
  Gui, Add, Checkbox, ys vStatistic Checked%Statistic%, Statistic
  Gui, Add, Edit, xm r10 w210 vlog ReadOnly, %LogText%

  If (Indentation = 1)
      GuiControl,,1xTab or,1
  If (Style = 1)
      GuiControl,,Rajat,1
  Else If (Style = 3)
      GuiControl,,BoBo,1
  If (IndentCont = 1)
      GuiControl,, IndentCont, 1

  ;get previous position and show Gui
  IniRead, Pos_Gui, %IniFile%, General, Pos_Gui,
  Gui, Show, %Pos_Gui% %param_Hidden% ,%ScriptName%
  Gui, +LastFound
  GuiUniqueID := "ahk_id " WinExist()

  ;get classNN of log control
  GuiControl, Focus, Log
  ControlGetFocus, ClassLog, %GuiUniqueID%
  GuiControl, Focus, Extension
Return

;#############   Toggle show / hide of Gui from tray icon   ###################
ShowHideGui:
  If param_Hidden {
      Gui, Show
      param_Hidden =
  }Else{
      param_Hidden = Hide
      Gui, Show, %param_Hidden%
    }
Return

;#############   Function iif: returns a or b depending on expression   #######
iif(exp,a,b=""){
    If exp
        Return a
    Return b
  }

;#############   Shortcut F? - indent highlighted text   ######################
IndentHighlightedText:
  ;store time for speed measurement
  StartTime = %A_TickCount%

  ;Save and clear clipboard
  ClipSaved := ClipboardAll
  Clipboard =

  ;Cut highlight to clipboard
  Send, ^c

  ;get window UID of current window
  WinUniqueID := WinExist("A")

  ;If nothing is highlighted, select all and copy
  If Clipboard is Space
    { ;Select all and copy to clipboard
      Send, ^a^c
    }

  ;get rid of all carriage returns (`r).
  StringReplace, ClipboardString, Clipboard, `r`n, `n, All

  ;restore the original clipboard and free memory
  Clipboard := ClipSaved
  ClipSaved =

  ;If something is selected, do the indentation and put it back in again
  If ClipboardString is Space
      MsgBox, 0 , %ScriptName%,
    (LTrim
      Couldn't get anything to indent.
      Please try again.
    ), 1
  Else {
      ;get Options
      Gui, Submit, NoHide

      ;create progress bar and block input
      StringReplace, x, ClipboardString, `n, `n, All UseErrorLevel
      NumberOfLines = %ErrorLevel%
      Progress, R0-%NumberOfLines% FM10 WM8000 FS8 WS400, `n, Please wait`, auto-syntax-tidy is Running, %ScriptName%
      BlockInput, On

      ;set words for case correction
      Gosub, SetCaseCorrectionSyntax

      ;create indentation
      Gosub, CreateIndentSize

      ;reset all values
      Gosub, SetStartValues

      ;Read each line form clipboard
      Loop, Parse, ClipboardString, `n
        { ;remember original line with its identation
          AutoTrim, Off
          Original_Line = %A_LoopField%
          AutoTrim, On

          ;do the indentation
          Gosub, DoSyntaxIndentation

          ;update progress bar every 10th line
          If (Mod(A_Index, 10)=0)
              Progress, %A_Index%, Line: %A_Index% of %NumberOfLines%
        }

      CaseCorrectSubsAndFuncNames()

      ;remove last `n
      StringTrimRight,String,String,1

      ;Save and clear clipboard
      ClipSaved := ClipboardAll
      Clipboard =

      ;put String into clipboard
      ;StringReplace, String, String, `n, `r`n, All
      Clipboard = %String%

      ;close progress bar and activate old window again
      Progress, Off
      WinActivate, ahk_id %WinUniqueID%

      ;paste clipboard
      Send, ^v{HOME}
      ;restore the original clipboard and free memory
      Clipboard := ClipSaved
      ClipSaved =

      ;turn off block input
      BlockInput, Off

      ;write information
      LogText = %LogText%Indentation done for text in editor.`n
      If Statistic
          Gosub, AddStatisticToLog
      Else
          LogText = %LogText%`n
      GuiControl, ,Log , %LogText%
      ControlSend, %ClassLog%, ^{End}, %GuiUniqueID%
    }
Return

;#############   Set words for case correction   ##############################
SetCaseCorrectionSyntax:
  CaseCorrectionSyntax =
  If CaseCorrectCommands
      CaseCorrectionSyntax = ,%CommandNames%
  If CaseCorrectVariables
      CaseCorrectionSyntax = %CaseCorrectionSyntax%,%Variables%
  If CaseCorrectKeys
      CaseCorrectionSyntax = %CaseCorrectionSyntax%,%Keys%
  If CaseCorrectKeywords
      CaseCorrectionSyntax = %CaseCorrectionSyntax%,%Keywords%
  If CaseCorrectDirectives
      CaseCorrectionSyntax = %CaseCorrectionSyntax%,%ListOfDirectives%
  ;remove first pipe
  StringTrimLeft, CaseCorrectionSyntax, CaseCorrectionSyntax, 1
Return

;#############   Create indentation size depending on options   ###############
CreateIndentSize:
  ;clear
  IndentSize =
  IndentContLine =

  ;turn of autotrim to be able to assign Spaces and tabs
  AutoTrim, Off

  ;Create indentation size depending on option
  If Indentation = 1
      IndentSize = %A_Tab%
  Else
      Loop, %NumberSpaces%
          IndentSize = %IndentSize%%A_Space%

      ;Create indentation for line continuation
  If IndentCont = 1
      Loop, %NumberIndentCont%
          IndentContLine = %IndentContLine%%A_Tab%
  Else
      Loop, %NumberIndentCont%
          IndentContLine = %IndentContLine%%A_Space%

      ;set autotrim to default
  AutoTrim, On
Return

;#############   Reset all start values   #####################################
SetStartValues:
  String =                 ;string that holds temporarely the file content (with auto-indentation)
  Indent =                 ;indentation string
  IndentIndex = 0          ;Index of array IndentIncrement and IndentCommand
  InBlockComment := False  ;Status if loop is in a Blockcomment
  InsideContinuation := False
  InsideTab = 0
  EmptyLineCount = 0       ;Counts the Number of empty Lines for statistics
  TotalLineCount = 0       ;Counts the Number of total Lines for statistics
  CommentLineCount = 0     ;Counts the Number of comments Lines for statistics
  If CaseCorrectBuildInFunctions
      CaseCorrectFuncList = %BuildInFunctions%  ;CSV list of function names in current script including build in functions
  Else
      CaseCorrectFuncList =                     ;CSV list of function names in current script
  CaseCorrectSubsList=     ;CSV list of subroutine names in current script
  Loop, 11{
      IndentIncrement%A_Index% =
      IndentCommand%A_Index% =
    }
Return

;#############   Indent all dropped files   ###################################
GuiDropFiles:
  ;store time for speed measurement
  OverAllStartTime = %A_TickCount%

  ;get options
  Gui, Submit,NoHide

  ;set words for case correction
  Gosub, SetCaseCorrectionSyntax

  ;create indentation
  Gosub, CreateIndentSize

  OverAllCodeLineCount = 0
  OverAllTotalLineCount = 0
  OverAllCommentLineCount = 0
  OverAllCommentLineCount = 0

  ;for each dropped file, read file line by line and indent each line
  Loop, Parse, A_GuiControlEvent, `n
    { ;store time for speed measurement
      StartTime = %A_TickCount%

      ;file
      FileToautoIndent = %A_LoopField%

      ;reset start values
      Gosub, SetStartValues

      ;Read each line in the file and do indentation
      Loop, Read, %FileToautoIndent%
        { ;remember original line with its identation
          AutoTrim, Off
          Original_Line = %A_LoopReadLine%
          AutoTrim, On

          ;do indentation
          Gosub, DoSyntaxIndentation
        }

      CaseCorrectSubsAndFuncNames()

      ;paste file with auto-indentation into new file
      ;  if Extension is empty, old file will be overwritten
      FileDelete, %FileToautoIndent%%Extension%
      FileAppend, %String%,%FileToautoIndent%%Extension%

      ;write information
      LogText = %LogText%Indentation done for: %FileToautoIndent%`n
      If Statistic
          Gosub, AddStatisticToLog
      Else
          LogText = %LogText%`n
      GuiControl, ,Log , %LogText%
      ControlSend, %ClassLog%, ^{End}, %GuiUniqueID%
    }
  If Statistic {
      LogText = %LogText%=====Statistics:=======`n
      LogText = %LogText%=====over all files====`n
      LogText = %LogText%Lines with code: %A_Tab%%A_Tab%%OverAllCodeLineCount%`n
      LogText = %LogText%Lines with comments: %A_Tab%%OverAllCommentLineCount%`n
      LogText = %LogText%Empty Lines: %A_Tab%%A_Tab%%OverAllEmptyLineCount%`n
      LogText = %LogText%Total Number of Lines: %A_Tab%%OverAllTotalLineCount%`n
      ;time for speed measurement
      OverAllTimeNeeded := (A_TickCount - OverAllStartTime) / 1000
      LogText = %LogText%Total Process time: %A_Tab%%OverAllTimeNeeded%[s]`n`n
      GuiControl, ,Log , %LogText%
      ControlSend, %ClassLog%, ^{End}, %GuiUniqueID%
    }
Return

;#############   Add statistics to log   ######################################
AddStatisticToLog:
  ;calculate lines of code
  CodeLineCount := TotalLineCount - CommentLineCount - EmptyLineCount

  OverAllCodeLineCount    += CodeLineCount
  OverAllTotalLineCount   += TotalLineCount
  OverAllCommentLineCount += CommentLineCount
  OverAllEmptyLineCount   += EmptyLineCount

  ;add information
  LogText = %LogText%=====Statistics:=====`n
  LogText = %LogText%Lines with code: %A_Tab%%A_Tab%%CodeLineCount%`n
  LogText = %LogText%Lines with comments: %A_Tab%%CommentLineCount%`n
  LogText = %LogText%Empty Lines: %A_Tab%%A_Tab%%EmptyLineCount%`n
  LogText = %LogText%Total Number of Lines: %A_Tab%%TotalLineCount%`n
  ;time for speed measurement
  TimeNeeded := (A_TickCount - StartTime) / 1000
  LogText = %LogText%Process time: %A_Tab%%TimeNeeded%[s]`n`n
Return

;#############   Indent file from command line   ##############################
IndentFile:
  ;set words for case correction
  Gosub, SetCaseCorrectionSyntax

  ;create indentation
  Gosub, CreateIndentSize

  ;file
  FileToautoIndent = %param_in%

  ;reset start values
  Gosub, SetStartValues

  ;Read each line in the file and do indentation
  Loop, Read, %FileToautoIndent%
    { ;remember original line with its identation
      AutoTrim, Off
      Original_Line = %A_LoopReadLine%
      AutoTrim, On

      ;do indentation
      Gosub, DoSyntaxIndentation
    }

  CaseCorrectSubsAndFuncNames()

  ;remove old file and paste with auto-indentation into same file
  FileDelete, %FileToautoIndent%
  FileAppend, %String%, %FileToautoIndent%

  ;write information to log file
  LogText = Indentation done for: %FileToautoIndent%`n
  If Statistic
      Gosub, AddStatisticToLog
  FileAppend , %LogText%, %param_log%
Return

;#############   Create indentation for next loop depending on IndentIndex   ##
SetIndentForNextLoop:
  ;clear
  Indent =
  If IndentIndex < 0            ;in case something went wrong
      IndentIndex = 0

  ;turn AutoTrim off, to be able to process tabs and spaces
  AutoTrim, Off

  ;Create indentation depending on IndentIndex
  Loop, %IndentIndex% {
      Increments := IndentIncrement%A_Index%
      Loop, %Increments%
          Indent = %Indent%%IndentSize%
    }

  ;turn AutoTrim on, to remove leading and trailing tabs and spaces
  AutoTrim, On
Return

;#############   Strip comments from Line   ###################################
StripCommentsFromLine(Line) {
    StartPos = 1
    Loop {   ;go from semicolon to semicolon, start at 2nd position, First doesn't make sence, since it would be a comment
        StartPos := InStr(Line,";","",StartPos + 1)
        If (StartPos > 1) {
            ;the following is not very robust but it will serve for most cases that a ";" is inside an := or () expression
            ; limitations:
            ; - comments that include a " on an := expression line
            ; - comments that include a ") on an ()expression line
            StringMid,CharBeforeSemiColon, Line, StartPos - 1 , 1
            If (CharBeforeSemiColon = "``")            ;semicolon is Escaped
                Continue
            Else If ( 0 < InStr(Line,":=") AND InStr(Line,":=") < StartPos
                      AND 0 < InStr(Line,"""") AND InStr(Line,"""") < StartPos
                      AND 0 < InStr(Line,"""","",StartPos) )   ;It on the right side of an := expression and surounded with "..."
                Continue
            Else If ( 0 < InStr(Line,"(") AND InStr(Line,"(") < StartPos
                      AND InStr(Line,")","",StartPos) > StartPos
                      AND 0 < InStr(Line,"""") AND InStr(Line,"""") < StartPos
                      AND 0 < InStr(Line,"""","",StartPos) )    ;It is inside and () expression and surounded with "..."
                Continue
            Else {                                     ;it is a semicolon
                StringLeft, Line, Line, StartPos - 1   ;get CommandLine up to semicolon
                Line = %Line%                          ;remove Spaces
                Return Line
              }
        } Else   ;no more semicolon found, hence no comments on this line
            Return Line
      }
  }

;#############   Function MemorizeIndent: Store list of indentations   ########
MemorizeIndent(Command,Increment,Index=0){
    global
    If (Index > 0)
        IndentIndex += %Index%
    Else If (Index < 0)
        IndentIndex := Abs(Index)
    IndentCommand%IndentIndex% = %Command%
    IndentIncrement%IndentIndex% = %Increment%
  }

;#############   Perform the syntax indentation for each given line   #########
DoSyntaxIndentation:
  ;count line
  TotalLineCount ++

  ;##################################
  ;########### judge on line   ######
  ;##################################
  ;remove space and tabs from beginning and end of original line
  Line = %Original_Line%

  If Line is Space                ;nothing in line
    { String = %String%`n

      ;count line
      EmptyLineCount ++
      Gosub, FinishThisLine
      Return  ;Continue with next line
    }

  ;##################################
  ;########### judge on first chars
  ;##################################
  ;get first and last characters of line
  StringLeft,  FirstChar    , Line, 1
  StringLeft,  FirstTwoChars, Line, 2

  FinishThisLine := False

  ;turn AutoTrim off, to be able to process tabs and spaces
  AutoTrim, Off

  If (FirstTwoChars = "*/") {          ;line is end of BlockComment
      String = %String%%Line%`n
      InBlockComment := False
      CommentLineCount ++
      FinishThisLine := True
    }

  Else If InBlockComment {              ;line is inside the BlockComment
      If KeepBlockCommentIndent
          String = %String%%Original_Line%`n
      Else
          String = %String%%Line%`n
      CommentLineCount ++
      FinishThisLine := True
    }

  Else If (FirstTwoChars = "/*") {          ;line is beginning of a BlockComment, end will be */
      String = %String%%Line%`n
      InBlockComment := True
      CommentLineCount ++
      FinishThisLine := True
    }

  Else If (FirstChar = ":") {                 ;line is hotstring
      String = %String%%Line%`n
      MemorizeIndent("Sub",1,-1)
      FinishThisLine := True
    }

  Else If (FirstChar = ";") {          ;line is comment
      String = %String%%Indent%%Line%`n
      CommentLineCount ++
      FinishThisLine := True
    }

  If FinishThisLine {
      Gosub, FinishThisLine
      Return  ;Continue with next line
    }

  ;turn AutoTrim back on
  AutoTrim, On

  ;##################################
  ;########### judge on commands/words
  ;##################################

  ;get pure command line
  StripedLine := StripCommentsFromLine(Line)

  ;get last character of CommandLine
  StringRight, LastChar     , StripedLine, 1

  ;get shortest first, second and third word of CommandLine
  Loop, 3
      CommandLine%A_Index% =
  StringReplace, CommandLine, StripedLine, %A_Tab%, %A_Space%,All
  StringReplace, CommandLine, CommandLine, `, , %A_Space%,All
  StringReplace, CommandLine, CommandLine, {, %A_Space%,All
  StringReplace, CommandLine, CommandLine, }, %A_Space%,All
  StringReplace, CommandLine, CommandLine, %A_Space%if(, %A_Space%if%A_Space%,All
  StringReplace, CommandLine, CommandLine, ), %A_Space%,All
  StringReplace, CommandLine, CommandLine, %A_Space%%A_Space%%A_Space%%A_Space%, %A_Space%,All
  StringReplace, CommandLine, CommandLine, %A_Space%%A_Space%%A_Space%, %A_Space%,All
  StringReplace, CommandLine, CommandLine, %A_Space%%A_Space%, %A_Space%,All
  CommandLine = %CommandLine%  ;remove Spaces from begining and end
  StringSplit, CommandLine, CommandLine, %A_Space%
  FirstWord  = %CommandLine1%
  SecondWord = %CommandLine2%
  ThirdWord  = %CommandLine3%

  ;get last character of First word
  StringRight, FirstWordLastChar,  FirstWord,  1

  ;check if previoulsly found function name is really a function definition
  ;if line is not start of bracket block but a funtion name exists
  If ( FirstChar <> "{" AND IndentIndex = 1 AND   FunctionName <> "") {
      FunctionName =         ; then that previous line is not a function definition.
      IndentIndex = 0         ; set back the indentation, which was previously set.
      Gosub, SetIndentForNextLoop
    }

  ;Assume line is not a function
  FirstWordIsFunction := False
  ;If no indentation and bracket not as first character it might be a function
  If ( IndentIndex = 0 And InStr(FirstWord,"(") > 0 )
      FirstWordIsFunction := ExtractFunctionName(FirstWord,InStr(FirstWord,"("),FunctionName)

  LineIsTabSpecialIndentStart := False
  LineIsTabSpecialIndent      := False
  LineIsTabSpecialIndentEnd   := False
  If (ChkSpecialTabIndent AND FirstWord = "Gui") {
      If (InStr(SecondWord,"add") And ThirdWord = "tab")
          LineIsTabSpecialIndentStart := True
      Else If (InStr(SecondWord,"tab")) {
          If ThirdWord is Space
              LineIsTabSpecialIndentEnd := True
          Else
              LineIsTabSpecialIndent := True
        }
    }

  ;turn AutoTrim off, to be able to process tabs and spaces
  AutoTrim, Off

  ;###### Start to adjust indentation ##########

  If FirstWord in %ListOfDirectives%         ;line is directive
    { Loop, Parse, CaseCorrectionSyntax, `,
          StringReplace, Line, Line, %A_LoopField%, %A_LoopField%, All
      String = %String%%Line%`n
    }
  Else If FirstChar in #,!,^,+,<,>,*,~,$     ;line is Hotkey (has be be after directives due to the #)
    { If InStr(FirstWord,"::"){
          String = %String%%Line%`n
          MemorizeIndent("Sub",1,-1)
        }
    }
  Else If (FirstChar = "," OR FirstTwoChars = "||" OR FirstTwoChars = "&&"
            OR FirstWord = "and" OR FirstWord = "or" )                     ;line is a implicit continuation
      String = %String%%Indent%%IndentContLine%%Line%`n
  Else If (FirstChar = ")" and InsideContinuation) {  ;line is end of a continuation block
      Gosub, SetIndentOfLastBracket
      String := String . Indent . iif(Style=1,"",IndentSize) . Line . "`n"
      ;IndentIndex doesn't need to be reduced, this is done inside SetIndentOfLastBracket
      InsideContinuation := False
    }
  Else If InsideContinuation {                ; line is inside a continuation block
      If AdjustContinuation
          String = %String%%Indent%%Line%`n
      Else
          String = %String%%Original_Line%`n
    }
  Else If (FirstChar = "(") {                 ;line is beginning of a continuation block
      String := String . Indent . iif(Style>1,IndentSize) . Line . "`n"
      MemorizeIndent("(",iif(Style=2,2,1),+1)
      AdjustContinuation := False
      If ( InStr(StripedLine, "LTrim") > 0 AND InStr(StripedLine, "RTrim0") = 0)
          AdjustContinuation := True
      InsideContinuation := True                  ;allow nested cont?
    }
  Else If LineIsTabSpecialIndentStart {                   ;line is a "Gui, Add, Tab" line
      String = %String%%Indent%%Line%`n
      MemorizeIndent("AddTab",1,+1)
    }
  Else If LineIsTabSpecialIndent {                        ;line is a "Gui, Tab, TabName" line
      Gosub, SetIndentOfLastAddTaborBracket
      String = %String%%Indent%%IndentSize%%Line%`n
      MemorizeIndent("Tab",1,+2)
    }
  Else If LineIsTabSpecialIndentEnd {                     ;line is a "Gui, Tab" line
      Gosub, SetIndentOfLastAddTaborBracket
      String = %String%%Indent%%Line%`n
    }
  Else If (FirstWordLastChar = ":") {   ;line is start of subroutine or Hotkey
      If (InStr(FirstWord,"::") = 0) {     ;line is start of a subroutine
          StringTrimRight, SubroutineName, Line, 1
          If SubroutineName not in %CaseCorrectSubsList%
              CaseCorrectSubsList = %CaseCorrectSubsList%,%SubroutineName%
        }
      String = %String%%Line%`n
      MemorizeIndent("Sub",1,-1)
    }
  Else If (FirstChar = "}") {             ;line is end bracket block
      If (FirstWord = "else"){            ;it uses OTB and must be a "}[ ]else [xxx] [{]"
          ;do the case correction
          StringReplace, Line, Line, else, Else
          Loop, Parse, CaseCorrectionSyntax, `,
              StringReplace, Line, Line, %A_LoopField%, %A_LoopField%, All

          Gosub, SetIndentOfLastCurledBracket
          IndentIndex --
          Gosub, SetIndentOfLastIfOrOneLineIf

          ;else line is also start of If-Statement
          If SecondWord in %ListOfIFCommands%          ;Line is an old  If-statement
            {
              StringReplace, Line, Line, if, If
              StringReplace, ParsedCommand, StripedLine, ```, ,,All
              ;Search if a third comma exists
              StringGetPos, ParsedCommand, ParsedCommand , `, ,L3
              If ErrorLevel                           ;Line is an old If-statement
                  MemorizeIndent("If",iif(Style=1,0,1),+1)
          }Else If (SecondWord = "if") {              ;Line is a Normal if-statement
              StringReplace, Line, Line, if, If
              MemorizeIndent("If",iif(Style=1,0,1),+1)
              If (LastChar = "{")                     ;it uses OTB
                  MemorizeIndent("{",iif(Style=3,0,1),+1)
          }Else If (SecondWord = "loop"){             ;Line is the begining of a loop
              StringReplace, Line, Line, loop, Loop
              MemorizeIndent("Loop",iif(Style=1,0,1),+1)
              If (LastChar = "{")                     ;it uses OTB
                  MemorizeIndent("{",iif(Style=3,0,1),+1)
          }Else If SecondWord is Space                 ;just a plain Else
            {
              MemorizeIndent("Else",iif(Style=1,0,1),+1)
              If (LastChar = "{")                     ;it uses OTB
                  MemorizeIndent("{",iif(Style=3,0,1),+1)
            }
          ;if all the previous if didn't satisfy,
          ; the Line is an else with any command following,
          ;  then nothing has to be done
          String = %String%%Indent%%Line%`n
      }Else {                               ;line is end bracket block without OTB
          Gosub, SetIndentOfLastCurledBracket
          String = %String%%Indent%%Line%`n
          IndentIndex --
        }
    }
  Else If (FirstChar = "{") {                   ;line is start of bracket block
      ;check if line is start of a function implementation
      If ( IndentIndex = 1 AND  FunctionName <> "" )
        ;then add function name to list if not in it already
          If FunctionName not in %CaseCorrectFuncList%
              CaseCorrectFuncList = %CaseCorrectFuncList%,%FunctionName%(
          ;clear function name
      FunctionName =

      IndentIndex ++
      IndentCommand%IndentIndex% = {
      IndentIncrement%IndentIndex% := iif(Style=3,0,1)

      ;check if command after { is if or loop
      If (FirstWord = "loop"){                   ;line is start of Loop block after the {
          ;do the case correction
          StringReplace, Line, Line, loop, Loop
          Loop, Parse, CaseCorrectionSyntax, `,
              StringReplace, Line, Line, %A_LoopField%, %A_LoopField%, All

          MemorizeIndent("Loop",iif(Style=1,0,1),+1)
          If (LastChar = "{")                     ;it uses OTB
              MemorizeIndent("{",iif(Style=3,0,1),+1)
          ;assuming that there are no old one-line if-statements following a {
      }Else If FirstWord in %ListOfIFCommands%  ;line is start of old If-Statement after the {
        {
          ;do the case correction
          StringReplace, Line, Line, if, If, 1
          Loop, Parse, CaseCorrectionSyntax, `,
              StringReplace, Line, Line, %A_LoopField%, %A_LoopField%, All

          MemorizeIndent("If",iif(Style=1,0,1),+1)
      }Else If (FirstWord = "if"){                ;line is start of If-Statement after the {
          ;do the case correction
          StringReplace, Line, Line, if, If, 1
          Loop, Parse, CaseCorrectionSyntax, `,
              StringReplace, Line, Line, %A_LoopField%, %A_LoopField%, All

          MemorizeIndent("If",iif(Style=1,0,1),+1)
          If (LastChar = "{")                     ;it uses OTB
              MemorizeIndent("{",iif(Style=3,0,1),+1)
        }
      String = %String%%Indent%%Line%`n
    }
  Else If FirstWordIsFunction {                ;line is function
      String = %String%%Line%`n
      MemorizeIndent("Func",1,-1)

      If (LastChar = "{") {                 ;it uses OTB
          If FunctionName not in %CaseCorrectFuncList%
              CaseCorrectFuncList = %CaseCorrectFuncList%,%FunctionName%(
          ;clear function name
          FunctionName =

          MemorizeIndent("{",iif(Style=3,0,1),+1)
        }
    }
  Else If (FirstWord = "loop") {         ;line is start of Loop block
      ;do the case correction
      StringReplace, Line, Line, loop, Loop
      Loop, Parse, CaseCorrectionSyntax, `,
          StringReplace, Line, Line, %A_LoopField%, %A_LoopField%, All

      PrevCommand := IndentCommand%IndentIndex%
      If (PrevCommand = "If"){               ;line is First line of a one-line If-block
          String := String . Indent . iif(Style<>3,IndentSize) . Line . "`n"
          MemorizeIndent("OneLineIf",iif(Style=2,2,1))
      }Else If (PrevCommand = "Else"){         ;Line is First line of a one-line Else-block
          String := String . Indent . iif(Style<>3,IndentSize) . Line . "`n"
          MemorizeIndent("OneLineElse",iif(Style=2,2,1))
      }Else If (PrevCommand = "Loop"){         ;Line is First line of a one-line loop-block
          String := String . Indent . iif(Style<>3,IndentSize) . Line . "`n"
          MemorizeIndent("OneLineLoop",iif(Style=2,2,1))
      }Else {                              ;it follows a Sub , { , OneLineCommand or nothing
          Gosub, SetIndentToLastSubBracketOrTab
          String = %String%%Indent%%Line%`n
        }
      MemorizeIndent("Loop",iif(Style=1,0,1),+1)
      If (LastChar = "{")                  ;it uses OTB
          MemorizeIndent("{",iif(Style=3,0,1),+1)
    }
  Else If FirstWord in %ListOfIFCommands% ;line is start of old If-Statement
    {
      ;do the case correction
      StringReplace, Line, Line, if, If
      Loop, Parse, CaseCorrectionSyntax, `,
          StringReplace, Line, Line, %A_LoopField%, %A_LoopField%, All

      PrevCommand := IndentCommand%IndentIndex%

      ;eliminate comments and escaped commas
      ParsedCommand := StripCommentsFromLine(Line)
      StringReplace, ParsedCommand, ParsedCommand, ```, ,,All
      ;Search if a third comma exists
      StringGetPos, ParsedCommand, ParsedCommand , `, ,L3
      If ( ErrorLevel = 0 ){                 ;Line is a old one-line If-statement
          If (PrevCommand = "If"){           ;Line is a one-line command of an If-block
              String := String . Indent . iif(Style<>3,IndentSize) . Line . "`n"
              MemorizeIndent("OneLineIf",0)
              MemorizeIndent("OneLineCommand",0,+1)
          }Else If (PrevCommand = "Else"){       ;Line is a one-line command of an Else-block
              String := String . Indent . iif(Style<>3,IndentSize) . Line . "`n"
              MemorizeIndent("OneLineElse",0)
              MemorizeIndent("OneLineCommand",0,+1)
          }Else If (PrevCommand = "Loop"){       ;Line is a one-line command of a loop-block
              String := String . Indent . iif(Style<>3,IndentSize) . Line . "`n"
              MemorizeIndent("OneLineLoop",0)
              MemorizeIndent("OneLineCommand",0,+1)
          }Else {                            ;line is Normal one-line if-statement
              Gosub, SetIndentToLastSubBracketOrTab
              String = %String%%Indent%%Line%`n
            }
      }Else {                              ;Line is not an one-line if-statement
          If (PrevCommand = "If"){              ;Line is First line of an one-line If-block
              String := String . Indent . iif(Style<>3,IndentSize) . Line . "`n"
              MemorizeIndent("OneLineIf",iif(Style=2,2,1))
          } Else If (PrevCommand = "Else"){       ;Line is First line of a one-line Else-block
              String := String . Indent . iif(Style<>3,IndentSize) . Line . "`n"
              MemorizeIndent("OneLineElse",iif(Style=2,2,1))
          } Else If (PrevCommand = "Loop"){       ;Line is First line of a one-line loop-block
              String := String . Indent . iif(Style<>3,IndentSize) . Line . "`n"
              MemorizeIndent("OneLineLoop",iif(Style=2,2,1))
          } Else {                             ;it follows a Sub , { , OneLineCommand or nothing
              Gosub, SetIndentToLastSubBracketOrTab
              String = %String%%Indent%%Line%`n
            }
          MemorizeIndent("If",iif(Style=1,0,1),+1)
        }
    }
  Else If (FirstWord = "if"){                  ;line is start of a Normal If-Statement
      ;do the case correction
      StringReplace, Line, Line, if, If
      Loop, Parse, CaseCorrectionSyntax, `,
          StringReplace, Line, Line, %A_LoopField%, %A_LoopField%, All

      PrevCommand := IndentCommand%IndentIndex%
      If (PrevCommand = "If"){              ;Line is First line of a one-line If-block
          String := String . Indent . iif(Style<>3,IndentSize) . Line . "`n"
          MemorizeIndent("OneLineIf",iif(Style=2,2,1))
      } Else If (PrevCommand = "Else"){       ;Line is First line of a one-line Else-block
          String := String . Indent . iif(Style<>3,IndentSize) . Line . "`n"
          MemorizeIndent("OneLineElse",iif(Style=2,2,1))
      } Else If (PrevCommand = "Loop"){       ;Line is First line of a one-line loop-block
          String := String . Indent . iif(Style<>3,IndentSize) . Line . "`n"
          MemorizeIndent("OneLineLoop",iif(Style=2,2,1))
      } Else {                             ;it follows a Sub , { , OneLineCommand or nothing
          Gosub, SetIndentToLastSubBracketOrTab
          String = %String%%Indent%%Line%`n
        }
      MemorizeIndent("If",iif(Style=1,0,1),+1)
      If (LastChar = "{")                  ;it uses OTB
          MemorizeIndent("{",iif(Style=3,0,1),+1)
    }
  Else If (FirstWord = "Else") {         ;line is a Else block
      ;do the case correction
      StringReplace, Line, Line, else, Else
      Loop, Parse, CaseCorrectionSyntax, `,
          StringReplace, Line, Line, %A_LoopField%, %A_LoopField%, All

      PrevCommand := IndentCommand%IndentIndex%
      If PrevCommand in OneLineCommand,Else
          Gosub, SetIndentOfLastIfOrOneLineIf

      ;else line is also start of If-Statement
      If SecondWord in %ListOfIFCommands%          ;Line is an old  If-statement
        {
          StringReplace, Line, Line, if, If
          StringReplace, ParsedCommand, StripedLine, ```, ,,All
          ;Search if a third comma exists
          StringGetPos, ParsedCommand, ParsedCommand , `, ,L3
          If ErrorLevel {                         ;Line is an old one-line If-statement
              MemorizeIndent("If",1,+1)
            }
      }Else If (SecondWord = "if"){               ;Line is a Normal if-statement
          StringReplace, Line, Line, if, If
          MemorizeIndent("If",iif(Style=1,0,1),+1)
          If (LastChar = "{")                  ;it uses OTB
              MemorizeIndent("{",iif(Style=3,0,1),+1)
      }Else If (Secondword = "loop"){             ;else is followed by a loop command
          ;do the case correction
          StringReplace, Line, Line, loop, Loop
          MemorizeIndent("Loop",iif(Style=1,0,1),+1)
          If (LastChar = "{")                  ;it uses OTB
              MemorizeIndent("{",iif(Style=3,0,1),+1)
      }Else If SecondWord is Space                 ;just a plain Else
        { MemorizeIndent("Else",iif(Style=1,0,1),+1)
          If (LastChar = "{")                  ;it uses OTB
              MemorizeIndent("{",iif(Style=3,0,1),+1)
        }
      ;if all the previous if didn't satisfy,
      ; the Line is an else with any command following,
      ;  then nothing has to be done
      String = %String%%Indent%%Line%`n
    }
  Else {                                        ;line is a Normal command or Return
      ;do the case correction
      Loop, Parse, CaseCorrectionSyntax, `,
          StringReplace, Line, Line, %A_LoopField%, %A_LoopField%, All

      PrevCommand := IndentCommand%IndentIndex%
      If (PrevCommand = "If"){             ;Line is a one-line command of an If-block
          String := String . Indent . iif(Style<>3,IndentSize) . Line . "`n"
          MemorizeIndent("OneLineIf",0)
          MemorizeIndent("OneLineCommand",0,+1)
      }Else If (PrevCommand = "Else"){      ;Line is a one-line command of an Else-block
          String := String . Indent . iif(Style<>3,IndentSize) . Line . "`n"
          MemorizeIndent("OneLineElse",0)
          MemorizeIndent("OneLineCommand",0,+1)
      }Else If (PrevCommand = "Loop"){      ;Line is a one-line command of a loop-block
          String := String . Indent . iif(Style<>3,IndentSize) . Line . "`n"
          MemorizeIndent("OneLineLoop",0)
          MemorizeIndent("OneLineCommand",0,+1)
      }Else If (PrevCommand = "Func"){      ;Line follows a function call   ??? is this ever True?
          String = %String%%Line%`n
          IndentIndex = 0
      }Else {                               ;line is Normal command or Return
          Gosub, SetIndentToLastSubBracketOrTab
          PrevCommand := IndentCommand%IndentIndex%

          ;if command is end of subroutine (return) no indentation, otherwise keep indentation
          If (FirstWord = "Return" AND PrevCommand = "Sub") {
              String = %String%%Line%`n
              IndentIndex = 0
          }Else
            ;String := String . Indent . iif(Style=2,IndentSize) . Line . "`n"
              String = %String%%Indent%%Line%`n
        }
    }
  Gosub, FinishThisLine
Return

FinishThisLine:
  ;###### End of change in indentation ##########

  ;turn AutoTrim on, to get back to default behaviour
  AutoTrim, On

  ;Show MsgBox for debug
  If DebugMode
      Gosub, ShowDebugStrings

  ;get Indentation for next loop
  Gosub, SetIndentForNextLoop
Return


;#############   Show MsgBox for debug   ######################################
ShowDebugStrings:
  msgtext = line#: %TotalLineCount%`n
  msgtext = %msgtext%Style: %Style%`n
  msgtext = %msgtext%line: %Line%`n
  msgtext = %msgtext%stripped line: %CommandLine%`n
  msgtext = %msgtext%Indent: |%Indent%|`n
  msgtext = %msgtext%1stChar: >%FirstChar%<`n
  msgtext = %msgtext%1st Word: >%FirstWord%<`n
  msgtext = %msgtext%2nd Word: >%SecondWord%<`n
  msgtext = %msgtext%3rd Word: >%ThirdWord%<`n
  msgtext = %msgtext%1st WordLastChar: >%FirstWordLastChar%<`n
  msgtext = %msgtext%FunctionName: >%FunctionName%<`n`n
  msgtext = %msgtext%IndentIndex: %IndentIndex%`n
  ;msgtext = %msgtext%LineIsTabSpecialIndentStart: %LineIsTabSpecialIndentStart%`n
  ;msgtext = %msgtext%LineIsTabSpecialIndent: %LineIsTabSpecialIndent%`n
  ;msgtext = %msgtext%LineIsTabSpecialIndentEnd: %LineIsTabSpecialIndentEnd%`n`n
  msgtext = %msgtext%Indent1: %IndentIncrement1% - %IndentCommand1%`n
  msgtext = %msgtext%Indent2: %IndentIncrement2% - %IndentCommand2%`n
  msgtext = %msgtext%Indent3: %IndentIncrement3% - %IndentCommand3%`n
  msgtext = %msgtext%Indent4: %IndentIncrement4% - %IndentCommand4%`n
  msgtext = %msgtext%Indent5: %IndentIncrement5% - %IndentCommand5%`n
  msgtext = %msgtext%Indent6: %IndentIncrement6% - %IndentCommand6%`n
  msgtext = %msgtext%Indent7: %IndentIncrement7% - %IndentCommand7%`n
  msgtext = %msgtext%Indent8: %IndentIncrement8% - %IndentCommand8%`n
  msgtext = %msgtext%Indent9: %IndentIncrement9% - %IndentCommand9%`n
  msgtext = %msgtext%Indent10: %IndentIncrement10% - %IndentCommand10%`n
  msgtext = %msgtext%Indent11: %IndentIncrement11% - %IndentCommand11%`n
  ;msgtext = %msgtext%`nDirectives: %ListOfDirectives%`n
  ;msgtext = %msgtext%`nIf-Commands: %ListOfIFCommands%`n
  ;msgtext = %msgtext%`nCommandNames: %CommandNames%`n
  ;msgtext = %msgtext%`nKeywords: %Keywords%`n
  ;msgtext = %msgtext%`nKeys: %Keys%`n
  ;msgtext = %msgtext%`nVariables: %Variables%`n
  ;msgtext = %msgtext%`nBuildInFunctions: %BuildInFunctions%`n
  ;msgtext = %msgtext%`nCaseCorrectFuncList: %CaseCorrectFuncList%`n

  MsgBox %msgtext%`n%String%
Return

;#############   Set the IndentIndex to to last if or onelineif   ##############
SetIndentOfLastIfOrOneLineIf:
  ;loop inverse through command array
  Loop, %IndentIndex% {
      InverseIndex := IndentIndex - A_Index + 2
      ;if command is if or onelineif, exit loop and remember the previous Index
      If IndentCommand%InverseIndex% in If,OneLineIf
        { IndentIndex := InverseIndex - 1
          Break
        }
    }
  ;set indentation for that index
  Gosub, SetIndentForNextLoop
Return

;#############   Set the IndentIndex to to last curled bracket   ##############
SetIndentOfLastCurledBracket:
  ;loop inverse through command array
  Loop, %IndentIndex% {
      InverseIndex := IndentIndex - A_Index + 1
      ;if command is bracket, exit loop and remember the previous Index
      If (IndentCommand%InverseIndex% = "{") {
          IndentIndex := InverseIndex - 1
          Break
        }
    }
  ;set indentation for that index
  Gosub, SetIndentForNextLoop
Return

;#############   Set the IndentIndex to to last bracket   #####################
SetIndentOfLastBracket:
  ;loop inverse through command array
  Loop, %IndentIndex% {
      InverseIndex := IndentIndex - A_Index + 1
      ;if command is bracket, exit loop and remember the previous Index
      If (IndentCommand%InverseIndex% = "(") {
          IndentIndex := InverseIndex - 1
          Break
        }
    }
  ;set indentation for that index
  Gosub, SetIndentForNextLoop
Return

;#############   Set the IndentIndex to the last addtab  ######################
SetIndentOfLastAddTaborBracket:
  ;loop inverse through command array
  Loop, %IndentIndex% {
      InverseIndex := IndentIndex - A_Index + 1
      ;if command is AddTab, exit loop and remember the previous Index
      If IndentCommand%InverseIndex% in {,AddTab
        { IndentIndex := InverseIndex - 1
          Break
        }
    }
  ;set indentation for that index
  Gosub, SetIndentForNextLoop
Return

;#############   Set the IndenIndex to to last Sub or bracket   ###############
SetIndentToLastSubBracketOrTab:
  FoundItem:=False
  ;loop inverse through command array
  Loop, %IndentIndex% {
      InverseIndex := IndentIndex - A_Index + 1

      ;if command is sub or bracket, exit loop and remember the Index
      If IndentCommand%InverseIndex% in {,Sub
        { IndentIndex := InverseIndex
          FoundItem:=True
          Break
      }Else If ChkSpecialTabIndent
          If IndentCommand%InverseIndex% in AddTab,Tab
            { IndentIndex := InverseIndex
              FoundItem:=True
              Break
            }
    }
  ;if not found set index to zero
  If ! FoundItem
      IndentIndex = 0

  ;set indentation for that index
  Gosub, SetIndentForNextLoop
Return

;#############   Extract Function Names   #####################################
ExtractFunctionName(FirstWord,BracketPosition, ByRef FunctionName)  {
    ;get function name without braket
    StringLeft, FunctionName, FirstWord, % BracketPosition - 1

    If (FunctionName = "If")   ;it is a If statement "If(", empty FunctionName and function will Return 0
        FunctionName =

    ;check each char in name if it is allowed
    Loop, Parse, FunctionName
        If ( A_LoopField <> "_" )
            If A_LoopField is not Alnum
              { FunctionName =
                Break
              }
    Return StrLen(FunctionName)
  }

;#############   Do CaseCorrection for Functions and Subroutines   ############
CaseCorrectSubsAndFuncNames() {
    global
    LenString := StrLen(String)

    ;remove first comma
    StringTrimLeft, CaseCorrectFuncList, CaseCorrectFuncList, 1
    StringTrimLeft, CaseCorrectSubsList, CaseCorrectSubsList, 1

    ;loop over all remembered function names
    Loop, Parse, CaseCorrectFuncList, CSV
      { FuncName := A_LoopField
        LenFuncName := StrLen(FuncName)

        ;Loop through string to find all occurances of function names
        StartPos = 0
        Loop {
            StartPos := InStr(String,FuncName,0,StartPos + 1)
            If (StartPos > 0) {
                StringMid,PrevChar, String, StartPos - 1 , 1
                If PrevChar is not Alnum
                    ReplaceName( String, FuncName, StartPos-1, LenString - StartPos + 1 - LenFuncName )
            } Else
                Break
          }
      }

    ;loop over all remembered subroutine names
    Loop, Parse, CaseCorrectSubsList, CSV
      { SubName := A_LoopField
        LenSubName := StrLen(SubName)

        ;Loop through string to find all occurances of function names
        StartPos = 0
        Loop {
            StartPos := InStr(String,SubName,"",StartPos + 1)
            If (StartPos > 0) {
                StringMid,PrevChar, String, StartPos - 1 , 1
                StringMid,NextChar, String, StartPos + LenSubName, 1

                ;if it is an exact match the char after the subroutine names has not to be a char
                If NextChar is not Alnum
                  { ;If previous character is a "g" and has TestStrings in same line replace the name.
                    If ( PrevChar = "g" ) {
                        TestAndReplaceSubName( String, SubName, "Gui,", LenString, LenSubName, StartPos)
                        TestAndReplaceSubName( String, SubName, "Gui ", LenString, LenSubName, StartPos)

                        ;If previous character is something else then Alnum and has TestStrings in same line replace the name.
                    }Else If PrevChar is not Alnum
                      { TestAndReplaceSubName( String, SubName, "Gosub" , LenString, LenSubName, StartPos )
                        TestAndReplaceSubName( String, SubName, "Menu"  , LenString, LenSubName, StartPos )
                        TestAndReplaceSubName( String, SubName, "`:`:"  , LenString, LenSubName, StartPos )
                        TestAndReplaceSubName( String, SubName, "Hotkey", LenString, LenSubName, StartPos )
                      }
                  }
            } Else
                Break
          }
      }
  }

TestAndReplaceSubName( ByRef string, Name, TestString, LenString, LenSubName, StartPos ) {
    ;find Positions of Teststring and LineFeed in String from the right side starting at routine position
    StringGetPos, PosTestString, String, %TestString%, R , LenString - StartPos + 1
    StringGetPos, PosLineFeed  , String,     `n      , R , LenString - StartPos + 1

    ;If %TestString% is in the same line do replace name
    If ( PosLineFeed < PosTestString )
        ReplaceName( String, Name, StartPos - 1, LenString - StartPos + 1 - LenSubName )
  }

ReplaceName( ByRef String, Name, PosLeft, PosRight ) {
    ;split String up into left and right
    StringLeft, StrLeft, String, PosLeft
    StringRight, StrRight, String, PosRight

    ;insert Name into it again
    String = %StrLeft%%Name%%StrRight%
  }

;#############   If Gui closes exit all   #####################################
GuiClose:
  ;store current position and settings and exit app
  Gui, Show
  WinGetPos, PosX, PosY, SizeW, SizeH, %ScriptName%
  Gui, Submit
  IniWrite, x%PosX% y%PosY%, %IniFile%, General, Pos_Gui
  IniWrite, %Extension%, %IniFile%, Settings, Extension
  IniWrite, %Indentation%, %IniFile%, Settings, Indentation
  IniWrite, %NumberSpaces%, %IniFile%, Settings, NumberSpaces
  IniWrite, %NumberIndentCont%, %IniFile%, Settings, NumberIndentCont
  IniWrite, %IndentCont%, %IniFile%, Settings, IndentCont
  IniWrite, %Style%, %IniFile%, Settings, Style
  IniWrite, %CaseCorrectCommands%, %IniFile%, Settings, CaseCorrectCommands
  IniWrite, %CaseCorrectVariables%, %IniFile%, Settings, CaseCorrectVariables
  IniWrite, %CaseCorrectBuildInFunctions%, %IniFile%, Settings, CaseCorrectBuildInFunctions
  IniWrite, %CaseCorrectKeys%, %IniFile%, Settings, CaseCorrectKeys
  IniWrite, %CaseCorrectKeywords%, %IniFile%, Settings, CaseCorrectKeywords
  IniWrite, %CaseCorrectDirectives%, %IniFile%, Settings, CaseCorrectDirectives
  IniWrite, %Statistic%, %IniFile%, Settings, Statistic

  IniWrite, %ChkSpecialTabIndent%, %IniFile%, Settings, ChkSpecialTabIndent
  IniWrite, %KeepBlockCommentIndent%, %IniFile%, Settings, KeepBlockCommentIndent
  IniWrite, %AHKPath%, %IniFile%, Settings, AHKPath
  IniWrite, %OwnHotkey%, %IniFile%, Settings, OwnHotkey
ExitApp:
  ExitApp
Return
;#############   End of File   #################################################
FG
Hotkey Help - Help Dialog for Currently Running AHK Scripts

AHK Startup - Consolidate Multiply AHK Scripts with one Tray Icon

[Function] Timer - Create and Manage Timers
toralf n-l-i

Re: AHK Auto Formatter?

24 Jan 2018, 01:03

Dear all,

The Problem ist that the script requires to read the Syntax file, see ReadSyntaxFiles.
They were present at that time of ahk Version. They are no more.
Don't know if I will find the time to modify the code to make it work again.
BoBo
Posts: 2515
Joined: 13 May 2014, 17:15

Re: AHK Auto Formatter?

24 Jan 2018, 01:22

toralf n-l-i wrote:Dear all,

The Problem ist that the script requires to read the Syntax file, see ReadSyntaxFiles.
They were present at that time of ahk Version. They are no more.
Don't know if I will find the time to modify the code to make it work again.
Hi toralf :thumbup: schön mal wieder einen 'alten' AHK veteranen zu sehn 8-)
toralf
Posts: 513
Joined: 27 Apr 2014, 21:08
Location: Germany

Re: AHK Auto Formatter?

24 Jan 2018, 01:46

Hi BoBo,
the last years I've moved around the globe but have always been here (at least reading/scanning the active topics). I also recognized that you "came back" after a period of silence. :) So I can say the same: Schön von Dir wieder zu lesen.
ciao
toralf
Remonell
Posts: 5
Joined: 15 Jul 2016, 19:53

Re: AHK Auto Formatter?

01 Mar 2018, 01:19

toralf n-l-i wrote:Dear all,

The Problem ist that the script requires to read the Syntax file, see ReadSyntaxFiles.
They were present at that time of ahk Version. They are no more.
Don't know if I will find the time to modify the code to make it work again.
Hi,
a lot of AHK coder would probably apprecciate it a lot (me included). I don't want to sound rude or anything, but would you do it if you get a certain amount of money for it? I was thinking about that all of the forums users raise some money (you have to tell us an amount). If the money gets raised, fine. If not, then thats what it is. Just an idea since money is definitely a motivation to me (bills gotta be paid).

P.S.: Ihr beiden seid zuckersüß :D
BoBo
Posts: 2515
Joined: 13 May 2014, 17:15

Re: AHK Auto Formatter?

01 Mar 2018, 05:40

Keyword :arrow: syntax. Well, slightly of topic ... can anyone explain to me why it seems so fundamental that the AHK interpreter is only allowing OTB with the generic Loop-command but not for its derivates (..., Files/Parse) ??

Code: Select all

Loop, 3 {                   ; fine
     }

Loop, Files, C:\*.txt {     ; illegal. But shouldn't be a problem here.
     }

Loop, Parse, Var, `n {      ; illegal. No, I doubt that someone is using a single { char as a delimiter/OmitChar that often. If necessary why not fore to escape it `{ like it has to be done for a comma?
     }
Thx for listening/reading. If that feature/adjustment could be made to AHK 1.1.2x I'd drink a few beers on the developers' behalf (OR if (s)he's around, and is begging for a hug ... :D )
Stenemo
Posts: 8
Joined: 25 Dec 2015, 04:48
Facebook: Stenemo
GitHub: MarkusStenemo

Re: AHK Auto Formatter?

15 Apr 2018, 04:08

Remonell wrote: Hi,
a lot of AHK coder would probably apprecciate it a lot (me included). I don't want to sound rude or anything, but would you do it if you get a certain amount of money for it? I was thinking about that all of the forums users raise some money (you have to tell us an amount). If the money gets raised, fine. If not, then thats what it is.
I completely agree! I found this thread after looking for a Visual Studio Code specific formater https://github.com/stef-levesque/vscode ... /issues/13. Since Visual Studio Code is getting more traction it would be great if that effort was put there if it is impossible to update the auto formater script to work.
User avatar
jeeswg
Posts: 5446
Joined: 19 Dec 2016, 01:58
Location: UK

Re: AHK Auto Formatter?

19 Apr 2018, 07:12

- I've attempted to update the syntax txt files here:
AutoHotkey syntax lists (text files) - AutoHotkey Community
https://autohotkey.com/boards/viewtopic ... 74&t=47603
- If someone wants to create a variants (a zip) of the txt files for use with this script, that's fine. I tried to keep the files very similar in nature to the originals. But if there are drop-down menus/autocorrect etc used by the script, I could imagine that tweaks to the lists might be desirable.
Remonell
Posts: 5
Joined: 15 Jul 2016, 19:53

Re: AHK Auto Formatter?

03 May 2018, 20:38

I found something. I don't know if you guys stumbled upon it already. https://autohotkey.com/boards/viewtopic.php?t=300

AHK-Studio. An AHK IDE with auto-format, syntax-highlighting and lots of other nice features. It is a huge improvement compared to all the other editors I have tried.

Return to “Ask For Help”

Who is online

Users browsing this forum: Google [Bot], JnLlnd, MannyKSoSo, newbieforever and 106 guests