Recursive Replacement in File

Help with writing and playing macros

Recursive Replacement in File

Postby JustMe » Tue Dec 04, 2007 12:20 pm

I'm using UE 13.20+4 - RegEx Unix Style

in my C-sources i have to format comments.

Example - Something like that

Code: Select all
  /**************************************************/
  /* Strukturverschiebung ? - Exception             */

      /**********************************************/
      /* Eingabedaten pruefen - technisch / fachlich*/
      /* Nr_Konto befuellt ?                        */


Should look like

Code: Select all
  /*********************************************************************
   * Strukturverschiebung ? - Exception   
   ********************************************************************/

      /*****************************************************************
       * Eingabedaten pruefen - technisch / fachlich   
       * Nr_Konto befuellt ? 
       ****************************************************************/


The length of comments never exceeds 72 for each line
The first /* should start at position where the old /* resits, the length of each line is 72 and the last */ is at row 72

To find the affecting lines this regex is used: (\s+/\*+\*/\r)(\s+/\*\s+[\w\s\d-?.>!\*>=/]+\*/)+

How can I replace those comments ?

Thanks in advance.

EDIT:
A macro for inserting a comment with correct format is:

Code: Select all
InsertMode
ColumnModeOff
HexOff
UnixReOff
"/"
Loop
"*"
IfColNum 72
ExitLoop
EndIf
EndLoop
"
 *
"
Loop
"*"
IfColNum 72
ExitLoop
EndIf
EndLoop
"/"
Key UP ARROW


Kind regards
Stefan
from Germany
User avatar
JustMe
Newbie
 
Posts: 3
Joined: Mon Dec 03, 2007 12:00 am

Re: Recursive Replacement in File

Postby Mofi » Wed Dec 05, 2007 9:15 am

Here is a macro which hopefully works for you. It works for your example. The right alignment to column 72 currently works only if there are no tabs before /*** or ***, only 0 or more spaces. This could be checked and corrected also with additional code if necessary. It does not modify already correct formatted comment blocks except the starting or ending line start with tab(s).

The macro is a little bit tricky because nesting of loops is not possible and there is also no search within a selection. Both would be possible in the script environment.

The macro property Continue if a Find with Replace not found or Continue if search string not found must be checked for this macro.

InsertMode
ColumnModeOff
HexOff
UnixReOff
Bottom
IfColNum 1
"
"
Else
"

"
EndIf
Top
TrimTrailingSpaces
Clipboard 9
Loop
IfSel
Find RegExp "%^([ ^t]++/^*[ ^t]^)"
Replace All SelectText "^1"
IfNotFound
SelectLine
EndSelect
Key UP ARROW
Paste
Key UP ARROW
Find "/"
Replace " "
Else
SelectLine
EndSelect
Key UP ARROW
Key DOWN ARROW
SelectLine
EndIf
Else
Find RegExp "%[ ^t]++/^*^*^*+/^n"
IfNotFound
ExitLoop
EndIf
Copy
EndSelect
Key UP ARROW
Key END
Key BACKSPACE
Key DOWN ARROW
SelectLine
EndIf
EndLoop
Bottom
Key BACKSPACE
Top
Find RegExp "%^([ ^t]++^)/^(^*[~^*]+^)^*/"
Replace All "^1 ^2"
TrimTrailingSpaces
Find "***"
Replace All "**************************************"
Find RegExp "%^(???????????????????????????????????????????????????????????????^*^*^*^*^*^*^*^*^)*/$"
Replace All "^1/"
Find RegExp "%^(????????????????????????????????????????????????????????????????^*^*^*^*^*^*^*^*^)*$"
Replace All "^1"
ClearClipboard
Clipboard 0

Add UnixReOn or PerlReOn (v12+ of UE) at the end of the macro if you do not use UltraEdit style regular expressions by default - see search configuration. Macro command UnixReOff sets the regular expression option to UltraEdit style.

Here is the code again with indentations for better understanding. See Macro examples and reference for beginners and experts how to highlight and edit such UEM (UltraEdit Macro code) files.

Code: Select all
    InsertMode
    ColumnModeOff
    HexOff
    UnixReOff
/*! Often the last line of a file is not terminated with a line ending.
    Check this for the current file too and insert the line ending if
    the last line is not terminated. Additionally it is possible that
    at the end of the file is a comment block which should be converted
    into the new format. The following method to detect the end of such
    a comment block requires always a line below a comment block with
    or without any characters. So add always an additional extra line. !*/ 
    Bottom
    IfColNum 1
        "
        "
    Else
        "
   
        "
    EndIf
    Top
/*! Back at top of the file delete all spaces and tabs at end of all lines.
    That makes it easier for the following regular expressions. And switch
    to clipboard 9 to not destroy content of standard Windows clipboard. !*/
    TrimTrailingSpaces
    Clipboard 9
/*! The following loop copies the header line of a comment block and inserts
    it at bottom of the comment block. Also the required modifications at
    end of the header line and start of the footer line are done in this
    loop. The loop is executed until no further header line in wrong format
    is found anymore in the file.
    Nesting of loops and searching inside a selection only is not possible
    in macros. To avoid a sub macro a trick is used to determine in a single
    loop if a search for the next header line in wrong format or for the end
    of the comment block should be done. If there is currently a selection
    search for the end of the comment block. If there is no selection search
    for the next header line. !*/
    Loop
        IfSel
/*! Does the currently selected line start with 0 or more occurrences
    of spaces or tabs, followed by /* and an additional space or tab?
    A search within a selection is not possible, but a replace all in
    selected text. So use this workaround. The replace itself does not
    change anything in any case. !*/
            Find RegExp "%^([ ^t]++/^*[ ^t]^)"
            Replace All SelectText "^1"
            IfNotFound
/*! This line does not contain "/* " at start of the line with or without
    preceding white-space(s). So it is probable not a comment line which
    means the end of the comment block is found. The before copied header
    line must be inserted at start of this line. The problem is that
    although the replace has not really changed something, the selection
    and also the cursor position could be modified by UltraEdit and the
    cursor is not anymore at column 1 of the line below. UltraEdit could
    have moved the cursor back 1 or more characters. Best method to restore
    the selection and at the same time the correct cursor position is to
    simply re-select the line. Then the cursor is surely at start of the
    next line. Now stop selection mode and move the cursor up to the just
    before selected line without "/* " at start of the line. Insert here
    the header line and replace the first / by a space to get correct
    format for the footer line of a block. !*/
                SelectLine
                EndSelect
                Key UP ARROW
                Paste
                Key UP ARROW
                Find "/"
                Replace " "
            Else
/*! This selected line starts with "/* " and so it is probable a comment
    line of the current comment block. Restore the cursor position with
    re-selecting the line (see above for the reason), stop selection mode,
    unselect the line by moving the cursor up and down and select the next
    line for the next test. !*/
                SelectLine
                EndSelect
                Key UP ARROW
                Key DOWN ARROW
                SelectLine
            EndIf
        Else
/*! Nothing selected means search for header line of a comment block in
    wrong format. Such a line can have preceding white-space(s). Important
    is that it starts with "/***", can have more *, but no other characters
    before the line ends with a / and the line-feed (UNIX line endings).
    If such a line is not found anymore, exit the loop. If such a line was
    found, copy it to user clipboard 9, delete the / from end of the line
    and select the line below because now the macro have to search for the
    end of the wrong formatted comment block. !*/
            Find RegExp "%[ ^t]++/^*^*^*+/^n"
            IfNotFound
                ExitLoop
            EndIf
            Copy
            EndSelect
            Key UP ARROW
            Key END
            Key BACKSPACE
            Key DOWN ARROW
            SelectLine
        EndIf
    EndLoop
/*! After the loop the cursor is more or less at the end of the file.
    Move to end of file and delete the extra line inserted at start
    of the macro because it is not needed anymore. !*/
    Bottom
    Key BACKSPACE
    Top
/*! Back at top of the file run a replace all to reformat all comment lines
    (between the header and footer lines) which still start with "/*" and
    end with */. The next character after "/*" can be everything except an
    asterisk *. This is just for security. This replace replaces the / by
    a spaces and removes the */. The rest of the line is not changed.
    Note: It replaces also /* ... */ to * ... outside a comment block! !*/
    Find RegExp "%^([ ^t]++^)/^(^*[~^*]+^)^*/"
    Replace All "^1 ^2"
/*! There will be surely many unnecessary trailing spaces now which should
    be deleted too. !*/
    TrimTrailingSpaces
/*! All header and footer lines of a comment block should end at column 72.
    For fast granting this requirement replace all strings with 3 * by a
    string with many more *. 35 extra * per 3 * string should be enough. !*/
    Find "***"
    Replace All "**************************************"
/*! Now all header and footer lines of every comment block should have far
    too many *. With 2 simple regular expressions short them exactly to
    72 characters per line, first the footer, then the header lines. This
    quick method does not work for header and footer lines with preceding
    tabs if a tab is defined to be a place holder for more than 1 space. !*/
    Find RegExp "%^(???????????????????????????????????????????????????????????????^*^*^*^*^*^*^*^*^)*/$"
    Replace All "^1/"
    Find RegExp "%^(????????????????????????????????????????????????????????????????^*^*^*^*^*^*^*^*^)*$"
    Replace All "^1"
//  Clear the clipboard 9 to free RAM and switch back to Windows clipboard.
    ClearClipboard
    Clipboard 0
/*! Activate UnixReOn or PerlReOn (v12+ of UE) here at the end of the macro
    if you do not use UltraEdit style regular expressions by default - see
    search configuration. Macro command UnixReOff at start of the macro
    sets the regular expression option to UltraEdit style. !*/
//  UnixReOn
//  PerlReOn
User avatar
Mofi
Grand Master
Grand Master
 
Posts: 4064
Joined: Thu Jul 29, 2004 11:00 pm
Location: Vienna

Re: Recursive Replacement in File

Postby JustMe » Wed Dec 05, 2007 9:40 am

Hey, I'm really impressed.

There are a few things wrong:
The first line of the comment /******************** is closing with a */ - thats wrong - no problem i guess
the line after the comment : *******************/ is missing.

;-)

My examples look like:
Code: Select all
  /*************************************************************/
   * Strukturverschiebung ? - Exception             

      /*********************************************************/
       * Eingabedaten pruefen - technisch / fachlich
       * Nr_Konto befuellt ?

Meanwhile I did an update to 13.20+5 same results

Thanks for your work so far - it's great :!:
it's perfect when missing stuff is handled :-)

Kind regards
Stefan
from Germany
User avatar
JustMe
Newbie
 
Posts: 3
Joined: Mon Dec 03, 2007 12:00 am

Re: Recursive Replacement in File

Postby Mofi » Wed Dec 05, 2007 10:27 am

My macro produces exactly the output you want for your input. According to your description it looks like the loop does nothing and I think the reason is ^p in the regular expression string %[ ^t]++/^*^*^*+/^p which means DOS line ending (carriage return + line-feed).

I guess, your file is not a DOS file or at least converted temporarily to DOS. Do you see UNIX in the status bar at bottom of the UltraEdit window? Yes, then replace ^p by ^n in the regular expression string and it should work.

Next time don't forget the encoding and line ending format of the file when asking for a find/replace/regular expression or macro help.
User avatar
Mofi
Grand Master
Grand Master
 
Posts: 4064
Joined: Thu Jul 29, 2004 11:00 pm
Location: Vienna

Re: Recursive Replacement in File

Postby JustMe » Wed Dec 05, 2007 10:39 am

You're right. It's UNIX-Format, sorry.

Now it does the things wanted - perfect.

I have a nice effect with the macro.

If I have only a comment-line like /**********************************/
it's now replaced by
/*******************************************************
******************************************************/

No great problem ;-)

I'd like to understand how the macro works, so that I can use it for other purposes and change it as I need it.

Kind regards
Stefan
from Germany
User avatar
JustMe
Newbie
 
Posts: 3
Joined: Mon Dec 03, 2007 12:00 am

Re: Recursive Replacement in File

Postby Mofi » Thu Dec 06, 2007 8:25 am

I have edited my first post and replaced the UEM version with a new one which contains lots of comments which hopefully helps you to understand the macro.

For the problem with /**********************************/ either use a replace all at end of the macro to replace

/*******************************************************
******************************************************/


back to a single line comment or adapt the macro in the lower Else branch after finding the header line of the comment block to check immediately if the next line is also a comment line.
User avatar
Mofi
Grand Master
Grand Master
 
Posts: 4064
Joined: Thu Jul 29, 2004 11:00 pm
Location: Vienna


Return to Macros