Add a string at the end of each line between /* and */

Help with writing and playing macros

Add a string at the end of each line between /* and */

Postby chiu2 » Sun Nov 11, 2007 4:46 am

Hi, I need to add a string "TC" at the end of each line between /* and */ while the number of lines between each /* ... */ pair may vary. Please help. Thanks.

Here is an example: I want to convert from:

/* Comment1
Comment1 cont */
Var1
/* Comment2 */ /* Comment3 */
Var2
/* Comment4
Comment5
Comment6
Comment7 */
Var3
...

to

/* Comment1 TC
Comment1 cont */ TC
Var1
/* Comment2 */ /* Comment3 */ TC
Var2
/* Comment4 TC
Comment5 TC
Comment6 TC
Comment7 */ TC
Var3
...
User avatar
chiu2
Newbie
 
Posts: 6
Joined: Sat Nov 10, 2007 12:00 am

Re: Add a string at the end of each line between /* and */

Postby pietzcker » Sun Nov 11, 2007 2:04 pm

Please read the sticky first and give us the required information. Then, what you write is not what your example shows. In line 2, there is a "TC" added outside of an /* */ pair. Which one is correct?
User avatar
pietzcker
Master
Master
 
Posts: 241
Joined: Sun Aug 22, 2004 11:00 pm

Re: Add a string at the end of each line between /* and */

Postby chiu2 » Sun Nov 11, 2007 4:19 pm

First, thanks for the reply.
Perhaps I should restate that "I need to add a string "TC" at the end of each line between /* and */ INCLUSIVELY."

In my example, the 1st group of /* ... */ is

/* Comment1
Comment1 cont */

which has 2 lines. I would like to convert to

/* Comment1 TC
Comment1 cont */ TC

Then skip 'Var1' as it's not inside any of /* ... */. The second group of /* */ is

/* Comment2 */ /* Comment3 */

which has 1 line. I would like to convert to

/* Comment2 */ /* Comment3 */ TC

(Notice that the conflict may be in here as there are indeed 2 /* */ groups within a line. But it would be okay if the macro can convert to either the above or like

/* Comment2 */ TC /* Comment3 */ TC)

Then skip 'Var2'. The last group of /* ... */ is

/* Comment4
Comment5
Comment6
Comment7 */

which has 4 lines. I would like to convert to

/* Comment4 TC
Comment5 TC
Comment6 TC
Comment7 */ TC

Then skip 'Var3'. And the search goes on until eof.

Also, please allow me to add additional info about my version of Uedit here:

I am using a trial version of Ultraedit v13.20, in WinXP environment, line terminator is 'Default'.

And I prefer Ultraedit's regular expression.

Thanks.
User avatar
chiu2
Newbie
 
Posts: 6
Joined: Sat Nov 10, 2007 12:00 am

Re: Add a string at the end of each line between /* and */

Postby Mofi » Mon Nov 12, 2007 8:38 am

Use following macro with the macro property Continue if search string not found activated for this macro. It does not use a regular expression engine.

InsertMode
ColumnModeOff
HexOff
Top
TrimTrailingSpaces
Loop
Find "/*"
IfNotFound
ExitLoop
EndIf
EndSelect
Key LEFT ARROW
Key LEFT ARROW
StartSelect
Find Select "*/^p"
IfSel
Find "^p"
Replace All SelectText " TC^p"
EndSelect
Key END
Else
ExitLoop
EndIf
EndLoop
Top

To create the macro with the code above do following:

  1. Copy the macro code above from your browser window to Windows clipboard.
  2. Start UltraEdit and open your file with the data.
  3. Click on Macro - Record, enter a macro name, disable the "Cancel" option, but enable the "Continue if search string not found" option and press button OK.
  4. Click on Macro - Stop Recording. If you see now the post macro dialog press the button Cancel.
  5. Click on Macro - Edit Macro....
  6. Select in the left macro code edit field the first 3 macro commands. Do not select the last line which contains the macro command for your configured regular expression engine.
  7. Press Ctrl+V to replace the first 3 lines with the macro code copied from the browser window.
  8. Press the button Close and confirm updating the macro with Yes.
  9. Click on Macro - Play Again. Finished!
User avatar
Mofi
Grand Master
Grand Master
 
Posts: 4055
Joined: Thu Jul 29, 2004 11:00 pm
Location: Vienna

Re: Add a string at the end of each line between /* and */

Postby chiu2 » Tue Nov 13, 2007 4:22 am

Hi, it works!!!!!!
Thank you very much. Really appreciate.
User avatar
chiu2
Newbie
 
Posts: 6
Joined: Sat Nov 10, 2007 12:00 am

Re: Add a string at the end of each line between /* and */

Postby chiu2 » Tue Nov 13, 2007 4:00 pm

Hi Mofi --- I'm studying your codes and hope that I can write something by myself soon. I think I have a good understanding of what you wrote, however I'm not up to the level that I can handle all by myself.

Here is an extra question and I hope that you could help me one more time:

Suppose that, in addition to the above, within each /* ...*/ group, I want to
(1) add '/*' at the beginning of each line if the line does not start with /*, and
(2) add '*/ TC' at the end of each line if the line does not end with */.

Can you show me how to modify from your codes so that I can compare and learn? Many thanks.

Here is the example, I want to convert from:

/* Comment1
Comment1 cont */
Var1
/* Comment2 */ /* Comment3 */
Var2
/* Comment4
Comment5
Comment6
Comment7 */
Var3
...

to

/* Comment1 */ TC
/* Comment1 cont */ TC
Var1
/* Comment2 */ /* Comment3 */ TC
Var2
/* Comment4 */ TC
/* Comment5 */ TC
/* Comment6 */ TC
/* Comment7 */ TC
Var3
...
User avatar
chiu2
Newbie
 
Posts: 6
Joined: Sat Nov 10, 2007 12:00 am

Re: Add a string at the end of each line between /* and */

Postby Mofi » Tue Nov 13, 2007 4:45 pm

Well, now we need some regular expression replaces. The problem is that when replacing something in a selected block which modifies the number of selected bytes the end position of the selection is not correct restored after the replace. Therefore further replaces on the selection can run not on the same block and the result could be not what you would expect.

A fast but not secure macro is following:

InsertMode
ColumnModeOff
HexOff
UnixReOff
Top
TrimTrailingSpaces
Loop
Find "/*"
IfNotFound
ExitLoop
EndIf
EndSelect
Key LEFT ARROW
Key LEFT ARROW
StartSelect
Find Select "*/^p"
IfSel
Find RegExp "%^(/[~*]^)"
Replace All SelectText "/* ^1"
Key HOME
Find RegExp "%^([~/]^)"
Replace All SelectText "/* ^1"
Key HOME
Find RegExp "^([~*]/^)$"
Replace All SelectText "^1 */"
Key HOME
Find RegExp "^([~/]^)$"
Replace All SelectText "^1 */"
Key HOME

Find "^p"
Replace All SelectText " TC^p"
EndSelect
Key END
Else
ExitLoop
EndIf
EndLoop
Top

But if this macro works or not depends on the line below the selected block and how large the selected block is and how many bytes are inserted by every replace.

Key HOME is not a really good method to restore the correct end position for the selection, especially if the line below the block starts with spaces or tabs and you have configuration setting Home Key always Goto column 1 not enabled as I have.

Here is a better solution. If first opens a new file where all the replaces for a block are done. Whenever the 2 main finds select a block in the main file, it is copied via user clipboard 9 to the new file where the replaces are done.

A replace all does not change the cursor position and therefore 1 Top after Paste is enough. The modified block in the temporary file is then cut and pasted over the still existing selection in the main file.

After all blocks are reformatted the new file created just for the replaces is closed without saving it.

InsertMode
ColumnModeOff
HexOff
UnixReOff
Top
TrimTrailingSpaces
NewFile
NextWindow
Clipboard 9
Loop
Find "/*"
IfNotFound
ExitLoop
EndIf
EndSelect
Key LEFT ARROW
Key LEFT ARROW
StartSelect
Find Select "*/^p"
IfSel
Copy
PreviousWindow
Paste
Top
Find RegExp "%^(/[~*]^)"
Replace All "/* ^1"
Find RegExp "%^([~/]^)"
Replace All "/* ^1"
Find RegExp "^([~*]/^)$"
Replace All "^1 */"
Find RegExp "^([~/]^)$"
Replace All "^1 */"
Find "^p"
Replace All " TC^p"
SelectAll
Cut
NextWindow
Paste
EndSelect
Key END
Else
ExitLoop
EndIf
EndLoop
Top
PreviousWindow
CloseFile NoSave
ClearClipboard
Clipboard 0

Note: The macro property Continue if search string not found must be checked for both macro versions.

If you want to understand the regular expressions, look into help of UltraEdit for page Regular Expressions on the table for the UltraEdit Syntax.

Note: The asterisk * inside [~] is interpreted always as normal character and not as regular expression character. It could be also escaped like [~^*]. But most regular expression characters are inside [...] interpreted as normal characters.
User avatar
Mofi
Grand Master
Grand Master
 
Posts: 4055
Joined: Thu Jul 29, 2004 11:00 pm
Location: Vienna

Re: Add a string at the end of each line between /* and */

Postby chiu2 » Tue Nov 13, 2007 5:40 pm

Man, this is fast, I really appreciate your help.

I tried both macro and they all ran fine in my simple example.

The 1st 'not secure' macro:
(1) You mentioned that the 'not secure' macro may run into problem that the end position may not be restored correctly after replace, could you give an example to show?
(2) there are several 'key HOME' there, do they bring the cursor back to the start position of the CURRENT line, or the start position of the SELECTED TEXT? I don't quite understand why you have to put 'key HOME' there?

The 2nd macro:
(1) If I understand correctly, the 'Top' is put to resolve the issue of 'key HOME' in the 1st macro, and you mentioned that since 'Replace All' does not change the cursor position, hence only 1 'Top' after 'Paste' is enough. But then, 'Replace All' is also used in the 1st macro too, why then 4 'Key HOME' are needed there?

This is very helpful, thanks a lot.
BTW, just checked with IT, my company has corporate lisense with Uedit, which is very good to me. Thanks again, looking forward to hearing from you soon.
User avatar
chiu2
Newbie
 
Posts: 6
Joined: Sat Nov 10, 2007 12:00 am

Re: Add a string at the end of each line between /* and */

Postby Mofi » Wed Nov 14, 2007 8:45 am

Insert in the first macro the command ExitMacro after second Replace All SelectText "/* ^1" before command Key HOME and run the macro on your example. The initial Find Select "*/^p" selects the block

/* Comment1
Comment1 cont */


and the cursor is on start of the next line (= after the line ending of the line with */). But as you now can see after the second replace (the first does nothing on your example) the selection is expanded and does not end anymore after */^p as before. Key HOME works here because the next line is not a blank line, does not start with a white-space character and is long enough to let the selection not expand over an additional line.

Now delete from your test file everything above /* Comment4, insert a blank line above Var3 and run the not secure macro with the ExitMacro command again. You will see that the cursor position (= end of selection) after the replace is completely wrong and Key HOME will not restore anymore the correct position.

Key HOME moves the cursor to start of the current line and because of selection mode is still active (activated with StartSelect, but EndSelect is below the replaces) the selection is also modified. It is like you have made a selection and press Shift+Home to change the cursor position and also the selection if the current selection ends on the current cursor position which is for example column 5.

The second macro avoids all the problems above because it copies the initial selection into a new file. After pasting a text the cursor is always at the end of the pasted text (= end of the temp file). The single command Top moves the cursor to top of the temp file (would be equal to start of selection in main source) and then run the same replaces as macro 1, but on whole file instead of a selected area because nothing is selected. The 5 replaces in macro 2 do not have parameter SelectText. This now always correct reformatted block is then copied back over the still selected original block in the main file.

If you want to understand that macro, I suggest to execute every command manually. Then you can see step by step what the macro does.

I have yesterday something forgotten:

You should insert the code block

Bottom
IfColNum 1
Else
"
"
EndIf


between the commands UnixReOff and Top. That makes sure that the last line of the file has also a line ending and is therefore really a line and not just a string at end of file. This is important if the last line of the file ends with */ but without a carriage return + line-feed (= no DOS line ending at end of the file).
User avatar
Mofi
Grand Master
Grand Master
 
Posts: 4055
Joined: Thu Jul 29, 2004 11:00 pm
Location: Vienna

Re: Add a string at the end of each line between /* and */

Postby chiu2 » Wed Nov 14, 2007 7:32 pm

THIS IS VERY CLEAR AND HELPFUL!!!!

Thanks a lot Mofi.
User avatar
chiu2
Newbie
 
Posts: 6
Joined: Sat Nov 10, 2007 12:00 am


Return to Macros