{"id":2966,"date":"2019-01-09T14:10:28","date_gmt":"2019-01-09T14:10:28","guid":{"rendered":"https:\/\/www.mjtnet.com\/blog\/?p=2966"},"modified":"2019-01-12T15:36:49","modified_gmt":"2019-01-12T15:36:49","slug":"prettifyscp-code-clean-up","status":"publish","type":"post","link":"https:\/\/www.mjtnet.com\/blog\/2019\/01\/09\/prettifyscp-code-clean-up\/","title":{"rendered":"PrettifyScp &#8211; Code Clean Up"},"content":{"rendered":"<p>I often end up working on <a href=\"https:\/\/www.mjtnet.com\/macro-scheduler.htm\">Macro Scheduler<\/a> 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&#8217;s become a bit messy and needs a bit of a clean up. And I&#8217;m not pointing fingers here either &#8211; some of this code is my own! <\/p>\n<p><a href=\"https:\/\/en.wikipedia.org\/wiki\/Indentation_style\">Indenting code<\/a> 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!<\/p>\n<p>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&#8217;s done. <\/p>\n<pre class=\"brush:macroscript\">\r\n\/\/tokens to identify start and end of indented code\r\nLet>incTokens=^IF.*|^SRT\\>.*|^REPEAT\\>.*|^WHILE\\>.*|^ELSE|^ELSE>\r\nLet>decTokens=^ENDIF|^END\\>.*|^UNTIL\\>.*|^ENDWHILE.*|^ELSE|^ELSE>\r\n\r\n\/\/tokens to identify blocks to ignore\r\nLet>inIgnores=^DIALOG\\>.*|^VBSTART|^\/\\*.*\r\nLet>outIgnores=^ENDDIALOG\\>.*|^VBEND|\\*\/.*\r\n\r\n\/\/set tab chars\r\nLet>tabs={\"  \"}\r\n\r\nLet>numTabs=0\r\nLet>inIgnoreSection=0\r\nLet>outText={\"\"}\r\n\r\n\/\/ask user for input script file\r\nInput>scp_file,Select script file\r\n\r\nIf>scp_file<>{\"\"}\r\n\r\n  \/\/create backup file name\r\n  ExtractFilePath>scp_file,path\r\n  ExtractFileName>scp_file,scp_name\r\n  ExtractFileName>scp_file,scp_name_no_ext,1\r\n  Let>backupfile=%path%\\%scp_name_no_ext%.BAK\r\n\r\n  \/\/read in script lines to loop through\r\n  ReadFile>scp_file,scp_data\r\n  \/\/temporarily remove percent symbols to avoid unwanted variable resolution\r\n  StringReplace>scp_data,%,~^PERCENT^~,scp_data\r\n  \/\/split to array of lines\r\n  Separate>scp_data,CRLF,scp_lines\r\n\r\n  \/\/if there are lines, loop through them\r\n  If>scp_lines_count>0\r\n\r\n    Let>k=0\r\n    Repeat>k\r\n\r\n      Let>k=k+1\r\n      Let>this_line=scp_lines_%k%\r\n\r\n      \/\/Message>To do: %this_line%\r\n\r\n      \/\/left trim the line\r\n      LTrim>this_line,trimmed_line\r\n\r\n      \/\/are we going into a section to ignore?\r\n      RegEx>inIgnores,trimmed_line,0,matches,pIgnore,0\r\n      If>pIgnore>0\r\n        Let>inIgnoreSection=1\r\n      Endif\r\n\r\n      If>inIgnoreSection=1\r\n        \/\/if we are in a section to ignore, are we coming out of it?\r\n        RegEx>outIgnores,trimmed_line,0,matches,pIgnore,0\r\n        If>pIgnore>0\r\n          Let>inIgnoreSection=0\r\n        Endif\r\n      Else\r\n        \/\/otherwise we are not in an ignore section so see if we need to do anything\r\n\r\n        \/\/should we unindent?\r\n        RegEx>decTokens,trimmed_line,0,matches,dec_nm,0\r\n        If>dec_nm=1\r\n          Let>numTabs=numTabs-1\r\n          \/\/capitalise first letter while we're here\r\n          MidStr>trimmed_line,1,1,fChar\r\n          Uppercase>fChar,fChar\r\n          RegEx>(^.{1}),trimmed_line,0,matches,nm,1,fChar,trimmed_line\r\n        Endif\r\n\r\n        \/\/create the indent chars\r\n        Let>indent={\"\"}\r\n        If>numTabs>0\r\n          Let>t=0\r\n          Repeat>t\r\n            Let>t=t+1\r\n            Let>indent=%indent%%tabs%\r\n          Until>t=numTabs\r\n        Endif\r\n\r\n        \/\/insert indent chars to line to output\r\n        Let>this_line=%indent%%trimmed_line%\r\n\r\n        \/\/should we indent further lines?\r\n        RegEx>incTokens,trimmed_line,0,matches,inc_nm,0\r\n        If>inc_nm=1\r\n          Let>numTabs=numTabs+1\r\n          \/\/capitalise first letter\r\n          MidStr>trimmed_line,1,1,fChar\r\n          Uppercase>fChar,fChar\r\n          RegEx>(^.{1}),trimmed_line,0,matches,nm,1,fChar,trimed_line\r\n        Endif\r\n\r\n      Endif\r\n\r\n      \/\/output the new line\r\n      Let>outText=%outText%%this_line%\r\n      If>k&lt;scp_lines_count\r\n        Let>outText=%outText%%CRLF%\r\n      Endif\r\n\r\n    Until>k=scp_lines_count\r\n\r\n    \/\/swap percent symbols back in ...\r\n    StringReplace>outText,~^PERCENT^~,%,outText\r\n\r\n    \/\/backup the file\r\n    DeleteFile>backupfile\r\n    CopyFile>scp_file,backupfile\r\n\r\n    \/\/write output to original file name\r\n    DeleteFile>scp_file\r\n    Let>WLN_NOCRLF=1\r\n    WriteLn>scp_file,res,outText\r\n\r\n    MessageModal>Done! Backup saved to %backupfile%\r\n\r\nEndif\r\n<\/pre>\n<p><\/br><\/p>\n<p>The old script is renamed to a .BAK file so that your original script is backed up. So if there&#8217;s something I haven&#8217;t thought of in this first stab and something gets messed up, you can&#8217;t lose anything, but hopefully you are backing up your code already! <\/p>\n<p>I&#8217;m ignoring code inside Dialogs and VBScript blocks as well as comment blocks. Dialogs shouldn&#8217;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&#8217;t touched VBS blocks.<\/p>\n<p>Hope this is useful. Any feedback or suggestions, or if you notice a bug, please post in the comments below.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>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&#8217;s become a bit messy and needs a bit of a clean up. And I&#8217;m not pointing fingers here either [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[5,6],"tags":[],"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/www.mjtnet.com\/blog\/wp-json\/wp\/v2\/posts\/2966"}],"collection":[{"href":"https:\/\/www.mjtnet.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.mjtnet.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.mjtnet.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.mjtnet.com\/blog\/wp-json\/wp\/v2\/comments?post=2966"}],"version-history":[{"count":9,"href":"https:\/\/www.mjtnet.com\/blog\/wp-json\/wp\/v2\/posts\/2966\/revisions"}],"predecessor-version":[{"id":2979,"href":"https:\/\/www.mjtnet.com\/blog\/wp-json\/wp\/v2\/posts\/2966\/revisions\/2979"}],"wp:attachment":[{"href":"https:\/\/www.mjtnet.com\/blog\/wp-json\/wp\/v2\/media?parent=2966"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.mjtnet.com\/blog\/wp-json\/wp\/v2\/categories?post=2966"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.mjtnet.com\/blog\/wp-json\/wp\/v2\/tags?post=2966"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}