Tech Tip: A 4D "Balancing" utility for finding paired closing character(s) in a text block
PRODUCT: 4D | VERSION: 14.1 | PLATFORM: Mac & Win
Published On: September 18, 2014
When working with text, most third party text, code, and method editors have a feature of function to aid a developer in highlighting the "Balancing" open and closing characters or tags. In 4D, it is a preference named "Highlight of the parentheses". In BBedit and Text Wrangler, its called "Balance". In Sublime Text, it has two names "Expand Selection to Brackets" and "Expand Selection to Scope."
The utility method, STR_FindBalancingChar, shown below the example images preforms such a function in 4D.
Example, with the block of JSON shown in Image 1, the need is to highlight for selection all the text contained between balanced "[{" and "}]".
Image 1
![](https://kb.4d.com:443/kbase/assets/images/77146-4.jpg)
From the Edit menu, Image 2, the seleciton is made for this type of Balance selection.
Image 2
![](https://kb.4d.com:443/kbase/assets/images/77146-5.jpg)
The resulting selection is show in Image 3 below.
Image 3
![](https://kb.4d.com:443/kbase/assets/images/77146-6.jpg)
Utility Method STR_FindBalancingChar
If (True) If (False) Begin SQL /* Name: STR_FindBalancingChar ( $Text_P; $Open_T; $Close_T {; $Pos_L} ) Path: STR_FindBalancingChar Purpose: Find the balancing end char(s) to the opening char() Example find balanced -- Parenthesis "(" to ")", -- Squar brackets "[" to "]", -- Curly brackets "{" to "}", -- Paired characters "[{" to "}]", -- or HTML/XML tags such as "<div>" to "</div>." $0 - C_LONGINT - Position of the closing $1 - C_POINTER - Pointer to the text to scan $2 - C_TEXT - Opening Char(s) $3 - C_TEXT - Closing Char(s) $4 - C_LONGINT - Offset into text starting point */ End SQL End if C_TEXT($MethodName_T) $MethodName_T:=Current method name //===================== Declare Variables ================================== //method_parameters_declarations C_LONGINT($0) C_POINTER($Text_P;$1) C_TEXT($Open_T;$2) C_TEXT($Close_T;$3) C_LONGINT($Pos_L;$4) //-------------------------------------------------------------------------------- //method_wide_constants_declarations //-------------------------------------------------------------------------------- //local_variable_declarations C_LONGINT($Ndx;$SOA;$RIS;$Params_L;$Pos_L;$Opns_L;$Cls_L;$OPos_L;$CPos_L;$OLen_L;$CLen_L) End if //====================== Initialize and Setup ================================ $Pos_L:=0 $CPos_L:=0 $Opns_L:=0 // Count of opening brackets $Cls_L:=0 // Count of closing brackets $Params_L:=Count parameters If ($Params_L>=3) $Text_P:=$1 $Open_T:=$2 $OLen_L:=Length($Open_T) $Close_T:=$3 $CLen_L:=Length($Close_T) If ($Params_L=4) $Pos_L:=Position($Open_T;$Text_P->;$4) Else $Pos_L:=Position($Open_T;$Text_P->) End if If (Length($Text_P->)>=($Pos_L+$OLen_L+$CLen_L)) $SOA:=$Pos_L //======================== Method Actions ================================== $Ndx:=0 $OPos_L:=Position($Open_T;$Text_P->;$Pos_L) $Opns_L:=$Opns_L+1 $CPos_L:=Position($Close_T;$Text_P->;$Pos_L+1) Repeat If ($OPos_L<$CPos_L) Repeat $Pos_L:=Position($Open_T;$Text_P->;$OPos_L+$OLen_L) If (($Pos_L>0) & ($Pos_L<$CPos_L)) $Opns_L:=$Opns_L+1 $OPos_L:=$Pos_L End if Until (($Pos_L>$CPos_L) | ($Pos_L<1)) End if $Cls_L:=$Cls_L+1 If ($Opns_L#$Cls_L) $CPos_L:=Position($Close_T;$Text_P->;$CPos_L+1) If ($Pos_L=0) $Cls_L:=$Cls_L+1 $Pos_L:=$CPos_L While ($Pos_L>0) $Pos_L:=Position($Close_T;$Text_P->;$CPos_L+1) If ($Pos_L>0) $Cls_L:=$Cls_L+1 $CPos_L:=$Pos_L End if End while End if End if Until (($Opns_L=$Cls_L) | ($Pos_L<1)) // Include the closing char(s) // $CPos_L:=$CPos_L+$CLen_L //======================== Clean up and Exit ================================= If (Not(Asserted($Opns_L=$Cls_L;$Open_T+" and "+$Close_T+" are unbalanced from starting point "+String($SOA)+"."))) $CPos_L:=0 End if End if End if $0:=$CPos_L |
The method was called using the code below...
C_TEXT($Open_T;$1) C_LONGINT($Ndx;$SOA;$RIS;$Params_L;$Start_L;$End_L) C_TEXT($End_T) //====================== Initialize and Setup ================================ $Params_L:=Count parameters $Open_T:=Get selected menu item parameter Case of : ($Open_T="[") $End_T:="]" : ($Open_T="{") $End_T:="}" : ($Open_T="[{") $End_T:="}]" Else ASSERT(False;"Unknown case test!") End case //======================== Method Actions ================================== GET HIGHLIGHT(*;"MyEdit_T";$Start_L;$End_L) $Ndx:=Position($Open_T;MyEdit_T) While (($Ndx>0) & ($Ndx<=$Start_L)) $SOA:=$Ndx $Ndx:=Position($Open_T;MyEdit_T;$SOA+1) End while $Start_L:=$SOA $End_L:=STR_FindBalancingChar (->MyEdit_T;$Open_T;$End_T;$Start_L) HIGHLIGHT TEXT(*;"MyEdit_T";$Start_L;$End_L) |