Friday, May 23, 2008

UltraEdit macro: replace all is from top of file

Edit: 24/05/2008 12:18:08 AM. Thanks to the UltraEdit support team who showed me that bookmarks can store cursor position within a line.

UltraEdit is by far my favourite text editor. Over time, I have built up a small collection of macros suited to my needs. Many of these macros perform a find/replace over the entire document. The macro would act over the entire document because I always have the "Replace all is from top of file" option checked in the find/replace dialog. I also expect the cursor to be in the same place after the macro is completed - this wasn't a problem because "find/replace all" actions wouldn't move the cursor.

As of version 13.20, UltraEdit has changed the macro behaviour: now a macro is always executed from the current cursor position, irrespective of the "Replace all is from top of file" option. This means that for my "replace all in document" macros I need two things: a) in order to execute over the entire document, a macro needs the Top command to move the cursor to the start of the document before the find/replace processing and b) I need a workaround to get the cursor back to the starting position at the macro's completion.

One workaround for the cursor position is to set a bookmark at the start of the macro and go back to the bookmark at the end of the macro. The below example shows this.

InsertMode
ColumnModeOff
HexOff
PerlReOn
ToggleBookmark 1
Top
Find "bad text"
Replace All "good text"
GotoBookMark 1
ToggleBookmark

A couple of notes are relevant to this macro.

  1. By default, a bookmark stores only references a particular line in a file, not the cursor position within that line, but this can be controlled with a Configuration setting. Go to Advanced > Configuration > Editor > Bookmarks and make sure "Bookmark column with line" is checked. From now on, a bookmark will remember the particular cursor position within a line, as well as the line.
  2. Note the index after these two book mark commands: ToggleBookmark 1 and GotoBookMark 1. Use the index to make sure you return to the same bookmark you created. If the macro logic needs to work with bookmarks, make sure they use other indexes.

If you don't want to rely on bookmarks, there is another way. Insert some unique text at the start of the macro and execute a find/replace for that text at the end of the macro. The below example shows this.

InsertMode
ColumnModeOff
HexOff
PerlReOn
"xxxcxxx"
Top
Find "bad text"
Replace All "good text"
Find "xxxcxxx"
Key DEL

There are two flaws with this technique.

  1. The text must be unique!
  2. This technique puts the unique text insertion and deletion actions into the 'undo' queue i.e. undo a few times after the completion of this macro and you will see the unique text get un-deleted. This isn't a big issue, but it is not neat: the purpose of my macro is to replace "bad text" with "good text" - I shouldn't see artifacts of a workaround appear in the action queue.

Personally I prefer the former technique, and I have refactored my macros to use this.

No comments: