January 9, 2019

PrettifyScp – Code Clean Up

Filed under: General,Scripting — Marcus Tettmar @ 2:10 pm

I often end up working on Macro Scheduler code that is hard to read because of a lack of indentation. Sometimes this is simply because the code has been chopped and changed so many times it’s become a bit messy and needs a bit of a clean up. And I’m not pointing fingers here either – some of this code is my own!

Indenting code inside code blocks makes it much easier to read. But cleaning up code and sorting out the indentation manually is tedious. So I wrote a little script to do it!

So here is my first PrettifyScp script. Just run it and browse to the .scp file you want to fix up. Wait a few seconds and it will pop up a message when it’s done.

//tokens to identify start and end of indented code
Let>incTokens=^IF.*|^SRT\>.*|^REPEAT\>.*|^WHILE\>.*|^ELSE|^ELSE>
Let>decTokens=^ENDIF|^END\>.*|^UNTIL\>.*|^ENDWHILE.*|^ELSE|^ELSE>

//tokens to identify blocks to ignore
Let>inIgnores=^DIALOG\>.*|^VBSTART|^/\*.*
Let>outIgnores=^ENDDIALOG\>.*|^VBEND|\*/.*

//set tab chars
Let>tabs={"  "}

Let>numTabs=0
Let>inIgnoreSection=0
Let>outText={""}

//ask user for input script file
Input>scp_file,Select script file

If>scp_file<>{""}

  //create backup file name
  ExtractFilePath>scp_file,path
  ExtractFileName>scp_file,scp_name
  ExtractFileName>scp_file,scp_name_no_ext,1
  Let>backupfile=%path%\%scp_name_no_ext%.BAK

  //read in script lines to loop through
  ReadFile>scp_file,scp_data
  //temporarily remove percent symbols to avoid unwanted variable resolution
  StringReplace>scp_data,%,~^PERCENT^~,scp_data
  //split to array of lines
  Separate>scp_data,CRLF,scp_lines

  //if there are lines, loop through them
  If>scp_lines_count>0

    Let>k=0
    Repeat>k

      Let>k=k+1
      Let>this_line=scp_lines_%k%

      //Message>To do: %this_line%

      //left trim the line
      LTrim>this_line,trimmed_line

      //are we going into a section to ignore?
      RegEx>inIgnores,trimmed_line,0,matches,pIgnore,0
      If>pIgnore>0
        Let>inIgnoreSection=1
      Endif

      If>inIgnoreSection=1
        //if we are in a section to ignore, are we coming out of it?
        RegEx>outIgnores,trimmed_line,0,matches,pIgnore,0
        If>pIgnore>0
          Let>inIgnoreSection=0
        Endif
      Else
        //otherwise we are not in an ignore section so see if we need to do anything

        //should we unindent?
        RegEx>decTokens,trimmed_line,0,matches,dec_nm,0
        If>dec_nm=1
          Let>numTabs=numTabs-1
          //capitalise first letter while we're here
          MidStr>trimmed_line,1,1,fChar
          Uppercase>fChar,fChar
          RegEx>(^.{1}),trimmed_line,0,matches,nm,1,fChar,trimmed_line
        Endif

        //create the indent chars
        Let>indent={""}
        If>numTabs>0
          Let>t=0
          Repeat>t
            Let>t=t+1
            Let>indent=%indent%%tabs%
          Until>t=numTabs
        Endif

        //insert indent chars to line to output
        Let>this_line=%indent%%trimmed_line%

        //should we indent further lines?
        RegEx>incTokens,trimmed_line,0,matches,inc_nm,0
        If>inc_nm=1
          Let>numTabs=numTabs+1
          //capitalise first letter
          MidStr>trimmed_line,1,1,fChar
          Uppercase>fChar,fChar
          RegEx>(^.{1}),trimmed_line,0,matches,nm,1,fChar,trimed_line
        Endif

      Endif

      //output the new line
      Let>outText=%outText%%this_line%
      If>k<scp_lines_count
        Let>outText=%outText%%CRLF%
      Endif

    Until>k=scp_lines_count

    //swap percent symbols back in ...
    StringReplace>outText,~^PERCENT^~,%,outText

    //backup the file
    DeleteFile>backupfile
    CopyFile>scp_file,backupfile

    //write output to original file name
    DeleteFile>scp_file
    Let>WLN_NOCRLF=1
    WriteLn>scp_file,res,outText

    MessageModal>Done! Backup saved to %backupfile%

Endif


The old script is renamed to a .BAK file so that your original script is backed up. So if there’s something I haven’t thought of in this first stab and something gets messed up, you can’t lose anything, but hopefully you are backing up your code already!

I’m ignoring code inside Dialogs and VBScript blocks as well as comment blocks. Dialogs shouldn’t be messed with and the indentation is handled by the dialog designer. VBScript could be cleaned up but would need a different parser and there are already VBScript code beautifiers out there so you could copy and paste those. So in this version I haven’t touched VBS blocks.

Hope this is useful. Any feedback or suggestions, or if you notice a bug, please post in the comments below.