ReIndent Selection problem with {} used for variables and blocks

ReIndent Selection problem with {} used for variables and blocks

3
NewbieNewbie
3

    Jul 09, 2009#1

    This is what I'm using for WORDFILE.UEW, if you need to see full syntax file let me know please.

    Code: Select all

    /L14"MacroQuest2" Line Comment = |: Block Comment On = |* Block Comment Off = *| Escape Char = \ String Chars = " File Extensions = MAC INC
    /Delimiters = ~!@%^&*()-+=|\/{}[]:;"'<>,.?
    /Function String = "%Sub[ ^t*]+^([a-zA-Z_0-9]+^)"
    /Indent Strings = "/for" "} else {" "{"
    /Unindent Strings = "/next" "} else /" "} else {" "}" "/return"
    /Open Brace Strings ="{" "(" "[" "${"
    /Close Brace Strings ="}" ")" "]" "}"
    /Ignore Strings SOL = "|*" "*|" "%^${^}"
    /Open Fold Strings = "sub" "/if"
    /Close Fold Strings = "/return" "}"
    My problem is my if statements are little different then C++ here is example below. I'm trying to get the ReIndent Selection to work for my coding.

    Code: Select all

    Sub Sub_Name2
    /if (!${Defined[Var]}) /varset Var value 0
    /if (!${Defined[Var2]}) /varset Var2 value 0
    /if (!${Defined[Var3]}) /varset Var3 value 0
    
    /if (${Var} && !${Var2} && !${Var3}) {
      /call Sub_Name
      /if (${Var} == 1) {
        /do something
        /if (${Var2} == 0) {
          /do something
          /if (${Var3} == 0) {
            /do something
            /do something
          } else {
            /echo something else
          }
        }
      } else {
        /do something
        /do something
      }
    } else /if (${Var} && ${Var2} && ${Var3} != 1) {
      /if (${Var}) /echo message
    }
    
    /for x 1 to ${Math.Calc[${Timer}+1]}
       /if (${x} == 101) /echo Timer Finished.
    /next x
    
    /if (${Var.Equal[${Me.Name}]} && ${Math.Calc[${pTarget[${pName}].Y}+10]} && !${Math.Calc[${pTarget[${pName}].X}+10]}) /echo Not within the X Location.
    /return
    Above is how I would like it to indent, format like, below is the results I'm getting.

    Code: Select all

    Sub Sub_Name2
    /if (!${Defined[Var]}) /varset Var value 0
    /if (!${Defined[Var2]}) /varset Var2 value 0
    /if (!${Defined[Var3]}) /varset Var3 value 0
    
    /if (${Var} && !${Var2} && !${Var3}) {
    /call Sub_Name
    /if (${Var} == 1) {
    /do something
    /if (${Var2} == 0) {
    /do something
    /if (${Var3} == 0) {
    /do something
    /do something
    } else {
    /echo something else
    	}
    	}
    } else {
    	/do something
    	/do something
    	}
    } else /if (${Var} && ${Var2} && ${Var3} != 1) {
    	/if (${Var}) /echo message
    	}
    
    	/for x 1 to ${Math.Calc[${Timer}+1]}
    	/if (${x} == 101) /echo Timer Finished.
    	/next x
    
    	/if (${Var.Equal[${Me.Name}]} && ${Math.Calc[${pTarget[${pName}].Y}+10]} && !${Math.Calc[${pTarget[${pName}].X}+10]}) /echo Not within the X Location.
    	/return
    More examples:

    Code: Select all

    /if (${Var1} || ${var2}) {
    	
    	/if (${Math.Calc[${Target.Distance}].Int} < ${Math.Calc[${Var5}-2].Int}) {
    		/if (${var4.Active} && !${Var3}) /stick moveback ${Math.Calc[${Var5}+4]}
    	}
    
    	/if (${Math.Calc[${Target.Distance}].Int} > ${Math.Calc[${Var5}-2].Int}) {
    		/if (${var4.Active} && !${Var3}) /stick uw ${Var5}
    	}
    
    }

    Code: Select all

    /if (${Var1}) {
    	/if (${Spawn[${Var1}].ID}) {
    		/call ChatOut 4 "${Message1}"
    	} else {
    		/call ChatOut 4 "${Message2}"
    		/return
    	}
    }

    Code: Select all

    /if (${CommandParam.Find[-ini]}) {
    	/if (${Select[${VarName},${Ini["${IniFile}","${Section}"].Replace["|",","].Left[-2]}]}) {
    		/ini "${IniFile}" "${Section}" "${VarName}" "${Value}"
    	}
    }

    Code: Select all

    /if (${Var1}) {
    	/if (${${sList}.Length}) {
    		/varset ${sList} ${${sList}}${sDiv}${sElement}
    	} else {
    		/varset ${sList} ${sElement}
    	}
    }

    Code: Select all

    /if (${Var1}) {
    	/if (${Var2} && ${Spawn[id ${QuickID}].Class.SubClass} && ${Spawn[id ${QuickID}].Class.ID}) {
    		/if (${Spawn[id ${QuickID}].Class.PctPCs}<${Var3}) {
    			/call SubRoute ${Spawn[${QuickID}].Class.ID} "${Var4}" "${Message}"
    		}
    	}
    }

    Code: Select all

    /if (!${Var1}) {
    	/if ((${Var2}<95 || ${Var3}) && !${Me.Slot["${Var4}"].ID} && ${Me.Ready["${Var4}"]}) {
    		/do something
    	}
    }

    Code: Select all

    /if (${Var1.NotEqual[${Var1-DefaultValue}]}) {
    
    	/if (${Var2} || ${Var3}) /return
    	/if (!${Var4}) {
    		/if (!${Var5}) /return
    
    		/for ArgNum 1 to ${Math.Calc[${Var1.Count[|]}+1]}
    			/varset CommandParam ${Var1.Arg[${ArgNum},|]}
    		/if (${Me.Slot[${CommandParam}].ID} == NULL) {
    			/call Check "${CommandParam}" "${Var6}"
    			/varset Var7 ${Spawn[${Var8}].ID}
    			/call Check "${CommandParam}" "${Var7}"
    
    			/if (${Sub.Return.Equal[Ready]}) /call MQ2 "${CommandParam}" "${Var9}" 7s "${Var6}" "${Var10}"
    		/next ArgNum
    		}
    		/next ArgNum
    	}
    	
    }

    Code: Select all

    /if (${Defined[Var1]}) {
    	/varset GenStr |${Var1.Lower}|
    	/if (${GenStr.Find[|${CurrCommand.Lower}|]}) {
    		/echo doing sCut ${CommandText}
    		/call sCut "${CommandText}"
    		/return
    	}
    }
    Is this problem something I can fix with the WORDFILE.UEW?

    If anyone need any more information let me know. I tried to give a good example with Sub and if statements in it and what it's doing for me.

    6,686585
    Grand MasterGrand Master
    6,686585

      Jul 10, 2009#2

      I played very, very long with various indent/unindent settings, but nothing worked perfect. Using auto-indent for your language is no problem. But the ReIndent Selection feature failed all the time. I had also no success with using Artistic Style Formatter to get your code formatted as you would like it. The reason is always the usage of { and } around variables. Neither the ReIndent Selection feature nor Artistic Style can handle this correct.

      But finally I found a solution for you. Use following in your wordfile with tab replaced by a horizontal tab character:

      /L14"MacroQuest2" Line Comment = |: Block Comment On = |* Block Comment Off = *| Escape Char = \ String Chars = " File Extensions = MAC INC
      /Delimiters = ~ !tab@%^&*()-+=|\/{}[]:;"'<>,.?
      /Function String = "%Sub[^t *]+^([0-9a-z_]+^)"
      /Indent Strings = "/for" "{"
      /Unindent Strings = "/next" "}" "/return"
      /Open Brace Strings = "{" "(" "[" "${"
      /Close Brace Strings = "}" ")" "]" "}"
      /Ignore Strings SOL = "|*" "*|"
      /Open Fold Strings = "Sub" "{"
      /Close Fold Strings = "/return" "}"

      Please note: No only the indent/unindent strings are modified. Please use really the block above.

      The ReIndent Selection command can't be used for re-indenting a selection. Instead use the macro below with the macro property Continue if search string not found checked. Here is the explanation of the macro.

      First the macro checks if there is currently a selection when starting the macro. If this is the case it cuts the selection to clipboard 9, inserts the character þ (byte code 254) as marker for start of the selection, pastes the selection back and inserts character ÿ (byte code 255) as marker for end of the selection. If there is no selection on macro start, the macro inserts these two characters at bottom and top of the file and selects the entire file content.

      Now a loop is executed which is defined as endless loop, but of course is not an endless loop. The main task of this loop is to replace all {} of the variables by «» in the current selection only. The regular expression string ^${^([~}^p]+^)} in UltraEdit syntax means:
      • ^$ ... find character $ which has a special regex meaning (end of line) and therefore must be escaped with ^ which is the escape character for UE syntax to be interpreted as literal character.
      • { ... after $ the character { must follow.
      • ^(...^) ... means tag the string found by the expression inside ^(...^) for being re-used in the replace string. We want to keep the variable names.
      • [~}^p]+ ... means find any character one or more times which are neither } nor carriage return + line-feed. So this expression selects everything after $ to next } or end of line (for security because a negative character range does not stop at end of line).
      • } ... after the string not containing } the character } must follow. So a ${ without a matching } on the same line is ignored.
      The replace string keeps the string between ${...}, and replaces { by « and } by ».

      This replace all in current selection is now done in a loop until the search can't find anymore the expression ${...}. This is necessary because of nesting the variables. The replace does not first replace {} around the inner variables and then those of the outer variables. It replaces on first run ${ of the outer variable and the } of the inner variable and on second run ${ of the inner variable with } of the outer variable. But that does not matter. At end all ${...} around variables are converted to $«...».

      Between every replace the selection must be restored. I don't know why UltraEdit sometimes keep the selection after the replace all inside the selection, which does not change the number of bytes selected, and sometimes it loses the selection. So for security the macro always reselects the selection. This is definitely not good for speed, but your files are probably not very large.

      However, after the loop the only remaining {} are those for the blocks. So after a final reselection the re-indent selection command can make its job without problems.

      The final steps are moving the cursor to top of the file, replace all « back to { and all » back to }, delete the inserted "start of selection marker character" þ and also the "end of selection marker character" ÿ. The cursor is at end of the initial selection or end of the file after the macro has finished. If you want the cursor at  top of the file or start of the initial selection, use following for the last 4 lines of the macro:

      Code: Select all

      Find "ÿ"
      Replace ""
      Find Up "þ"
      Replace ""
      
      Here is the macro which needs the macro property Continue if search string not found checked.

      Code: Select all

      InsertMode
      ColumnModeOff
      HexOff
      UltraEditReOn
      IfSel
      Clipboard 9
      Cut
      "þ"
      Paste
      ClearClipboard
      Clipboard 0
      "ÿ"
      Find Up Select "þ"
      Else
      Bottom
      "ÿ"
      Top
      "þ"
      SelectAll
      EndIf
      Loop 0
      Find RegExp SelectText "^${^([~}^p]+^)}"
      Replace All "$«^1»"
      IfNotFound
      ExitLoop
      EndIf
      EndSelect
      Top
      Find "þ"
      Find Select "ÿ"
      EndLoop
      EndSelect
      Top
      Find "þ"
      Find Select "ÿ"
      ReIndentSelection
      Top
      Find "«"
      Replace All "{"
      Find "»"
      Replace All "}"
      Find "þ"
      Replace ""
      Find "ÿ"
      Replace ""
      
      Best regards from an UC/UE/UES for Windows user from Austria

      3
      NewbieNewbie
      3

        Jul 15, 2009#3

        Thanks Mofi. I'm starting to understand it a little more now. The final script you gave me seems to work perfect. I applied it to a lot of my code and I cannot find a spot it didn't work in scanning though it quickly.

        Thanks a lot for explaining each section out to me that helped a ton also.

        5
        NewbieNewbie
        5

          Sep 08, 2009#4

          I am trying to modify this a little for my own reindention usage. But I seem to be getting stuck. I've isolated my problem down to the Find RegExp command. I've also reduced my macro to the small subset to try and figure out my problem.

          The macro is:

          Code: Select all

          InsertMode
          ColumnModeOff
          HexOff
          Find RegExp SelectText "{[~}{^p]+}"
          
          This macro will successfully highlight the string I am looking for, but every time I try to add in "(" and ")" to isolate the text inside my curly braces { }, I can not get the command to select my text. I've tried a few variations, but can not seem to make them select the code that the expression above selects.

          Code: Select all

          Find RegExp SelectText "{([~}{^p]+)}"
          Find RegExp SelectText "{^([~}{^p]+^)}"
          
          I'm trying to get far enough along to add to the macro code:

          Code: Select all

          Replace All "«^1»"
          Right now I'm assuming the parentheses are used to set a subset variable "^1" so the Replace All ends up effectively removing my curly braces with the « and » characters. (Only working for matching { and } within the same line.)

          My goal is to be able to properly reindent TCL code such as:

          Code: Select all

          if {$x == 100} {
              puts "Line 1"
          } else {
              if {$x == 200} {
                  puts "Line 2"
              }
          }
          Any help would be greatly appreciated. Thanks!

          6,686585
          Grand MasterGrand Master
          6,686585

            Sep 09, 2009#5

            Following worked perfect for your example code using UE v15.10.0.1031:

            Code: Select all

            InsertMode
            ColumnModeOff
            HexOff
            UltraEditReOn
            IfSel
            Clipboard 9
            Cut
            "þ"
            Paste
            ClearClipboard
            Clipboard 0
            "ÿ"
            Find Up Select "þ"
            Else
            Bottom
            "ÿ"
            Top
            "þ"
            SelectAll
            EndIf
            Find RegExp SelectText "{^([~}{^p]+^)}"
            Replace All "«^1»"
            Top
            Find "þ"
            Find Select "ÿ"
            ReIndentSelection
            Top
            Find "«"
            Replace All "{"
            Find "»"
            Replace All "}"
            Find "þ"
            Replace ""
            Find "ÿ"
            Replace ""
            
            Best regards from an UC/UE/UES for Windows user from Austria

            5
            NewbieNewbie
            5

              Sep 09, 2009#6

              Still not working for me.  I am on version 15.10.0.1031, and I copied your macro exactly.
              When I omit the ^( and ^) from the regular expression, i.e. use Find RegExp SelectText "{[~}{^p]+}",  it works correct, except everything inside the { }s is converted to "^1".  :-)

              Do I need to set my regexp somewhere to tell it to use Perl format?

              Thanks again for all the help and advice.

              6,686585
              Grand MasterGrand Master
              6,686585

                Sep 09, 2009#7

                I'm using the same version as you and the macro uses the UltraEdit regular expression engine enabled by the command UltraEditReOn.

                Is your file a UNIX file opened without temporary conversion to DOS?

                In this case you would need ^n instead of ^p in the regular expression search string. Or better you use ^r^n instead of ^p which should result in a working replace for all type of line terminations for this regular expression search string.

                Of course the UltraEdit regular expression engine works with this search/replace strings only if you have not specified a different character than ^ as special (escape) character at Advanced - Configuration - Search - Miscellaneous.

                You can also use the Perl engine as shown in the macro code below:

                Code: Select all

                InsertMode
                ColumnModeOff
                HexOff
                PerlReOn
                IfSel
                Clipboard 9
                Cut
                "þ"
                Paste
                ClearClipboard
                Clipboard 0
                "ÿ"
                Find Up Select "þ"
                Else
                Bottom
                "ÿ"
                Top
                "þ"
                SelectAll
                EndIf
                Find RegExp SelectText "\{([^}{\r\n]+)\}"
                Replace All "«\1»"
                Top
                Find "þ"
                Find Select "ÿ"
                ReIndentSelection
                Top
                Find "«"
                Replace All "{"
                Find "»"
                Replace All "}"
                Find "þ"
                Replace ""
                Find "ÿ"
                Replace ""
                
                Best regards from an UC/UE/UES for Windows user from Austria

                5
                NewbieNewbie
                5

                  Sep 09, 2009#8

                  I don't know how, why, or when, but I had removed the "^" from Advanced - Configuration - Search - Miscellaneous. Putting it back made all the difference! I'm glad I had the error though, because I do work with both Unix and DOS file types, so your suggestion to use "^r^n" instead of "^p", will be very helpful.

                  Thanks again Mofi, you're the man!

                  6,686585
                  Grand MasterGrand Master
                  6,686585

                    Mar 24, 2022#9

                    The ReIndent Selection feature is greatly enhanced in UltraEdit for Windows v2022.0.0.70 and UEStudio v2022.0.0.70.

                    The MacroQuest code examples can be re-indented now as requested without the usage of a macro by using in the syntax highlighting wordfile:

                    /L14"MacroQuest" Line Comment = |: Block Comment On = |* Block Comment Off = *| Escape Char = \ String Chars = " File Extensions = MAC INC
                    /Delimiters = ! "tab%&'()*+,-./:;<=>?@[\]^{|}~
                    /Function String = "%Sub[^t *]+^([0-9a-z_]+^)"
                    /Indent Strings = "/for" "{"
                    /Unindent Strings = "/next" "}"
                    /Open Brace Strings = "{" "(" "[" "${"
                    /Close Brace Strings = "}" ")" "]" "}"
                    /Open Fold Strings = "Sub " "/for" "{"
                    /Close Fold Strings = "/return" "/next" "}"
                    /Ignore Fold Strings = "tab/return" " /return"

                    The two tab are placeholders for a horizontal tab character.

                     The code folding works also fine with the definition above on the MacroQuest examples in first post.

                    The enhanced ReIndent Selection feature works also for the TCL code example.
                    Best regards from an UC/UE/UES for Windows user from Austria