Inserting characters before/after selected text

Help with writing and running scripts

Inserting characters before/after selected text

Postby lm77054 » Fri Jun 17, 2011 7:18 am

Can someone help me? How would I script to add characters at the beginning and of a highlighted string? For instance, say you have:

The quick brown fox jumps over the lazy dog's back.

Quick through fox is highlight, as simulated above by the red lettering. How would I add in (begin) before "quick", and (end), after "fox"?

Thanks.
lm77054
Basic User
Basic User
 
Posts: 16
Joined: Sat Feb 26, 2011 12:11 pm

Re: Inserting characters before/after selected text

Postby Mofi » Fri Jun 17, 2011 12:55 pm

With a script this is very easy because scripts support variables and selected text is a string object. Therefore the script can be coded to insert text around selected text with a simple write command as demonstrated below for inserting (begin) at beginning and (end) at end of a selection.

Code: Select all
// Execute this script only with any file opened and column mode not enabled.
if ((UltraEdit.document.length > 0) && (UltraEdit.columnMode == false))
{
  // The script can't be used for a selection in hex edit mode.
  if (UltraEdit.activeDocument.hexMode == false)
  {
      if (UltraEdit.activeDocument.isSel())
      {
         var bInsertMode = UltraEdit.insOvrMode;
         UltraEdit.insertMode();
         // The replace is for duplicating every ^ because on write every ^^ is written as ^.
         UltraEdit.activeDocument.write("(begin)" + UltraEdit.activeDocument.selection.replace(/\^/g,"^^") + "(end)");
         if (!bInsertMode) UltraEdit.overStrikeMode();
      }
      else  // Tell McFly that something isn't selected.
      {
         UltraEdit.messageBox("HELLO! McFly, select some text!", "Nothing Selected...");
      }
   }
}

Duplicating every ^ in selected string is only required if at Advanced - Configuration - Search - Miscellaneous the character ^ is set for setting Special character used in find/replace strings (normally ^) as it is by default to be able to use in non regular expression finds/replaces the special characters as listed in table of the Find/Replace command help pages. This character is also used as special character for UltraEdit regular expression finds and replaces, see first table on help page Regular Expressions (Legacy). The Unix and the Perl regular expression engines use a backslash character as special (escape) character. In my point of view the special character should not be active on simple write, just for finds and replaces. But in UE v17.10.0.1015 it is necessary to escape every ^ with an additional ^ to get right content written into the file.
User avatar
Mofi
Grand Master
Grand Master
 
Posts: 4058
Joined: Thu Jul 29, 2004 11:00 pm
Location: Vienna

Re: Inserting characters before/after selected text

Postby dlgreene » Mon Aug 01, 2011 5:22 am

I need a simple script that does exactly what this script does... Problem I'm working with a Scala file so therefore (I assume because RegEx can be used in write) the written text has been modified. Currently I need to create blocks on Scala code that has ^^ characters. The script as written converts ^^ to ^. It's scala code so it's a problem for most editors as scala is essentially a really massive ANTR parsing mechanism. So I don't know if it's going to foul other parts of scala code as well. Anyway... is there some simple way to get the character position start of selection and then move to the end of the current selection insert ending text then move to where the start of the selection was and insert the starting text. Obviously order of insertion doesn't matter but I assume the if I can get character positions I need to do the end first so that the starting position won't change before I insert starting text.

I want:
selected text
to yield
{selected text}


Current Problem selected text
Code: Select all
"""[^=].*""".r ^^ Textual
currently yields:
Code: Select all
{"""[^=].*""".r ^ Textual}
                 ^ missing second caret

I did find UltraEdit.activeDocument.currentPos but I can't find it's complement UltraEdit.activeDocument.goToPos. Further it's not clear how to "unselect" preferably "toEnd" or "toStart" and I assume currentPos will return start, and I should be able to get current selection length (So long as the RegEx won't foul that as well)
dlgreene
Newbie
 
Posts: 2
Joined: Mon Aug 01, 2011 4:52 am

Re: Inserting characters before/after selected text

Postby Mofi » Mon Aug 01, 2011 5:43 am

I have not known until now that UltraEdit converts on write a ^^ character sequence to just ^. I have modified my script to workaround this problem and you can now use it for your Scala files.
User avatar
Mofi
Grand Master
Grand Master
 
Posts: 4058
Joined: Thu Jul 29, 2004 11:00 pm
Location: Vienna

Re: Inserting characters before/after selected text

Postby dlgreene » Mon Aug 01, 2011 6:02 am

Thanks for the quick response... I'm just learning scala so I don't know if ^^ is the only problem. I'm still trying to figure out something that completely by passes the problem, i.e. positioning of somekind. Maybe bookmarks or something.

Code: Select all
var lineNum = UltraEdit.activeDocument.selection.currentLineNum;
var colNum = UltraEdit.activeDocument.selection.currentColumnNum;

UltraEdit.activeDocument.key("RIGHT ARROW");
UltraEdit.activeDocument.key("LEFT ARROW");
UltraEdit.activeDocument.write("}" + Pos );

while( Pos > UltraEdit.activeDocument.currentPos )
    UltraEdit.activeDocument.key("LEFT ARROW");

//UltraEdit.activeDocument.write("{");

doesn't work but maybe if...
Make a temp bookmark of selected
move to end of selection
insert ending text
goto Bookmark
move to start of selection
insert starting text
remove temp bookmark

It's almost as if fighting the editor is the problem... ie updating the document while the script is running. I'm fully aware that that is a problem, which is why my attempts are working with the end first.
How about getting to the file somehow?
dlgreene
Newbie
 
Posts: 2
Joined: Mon Aug 01, 2011 4:52 am

Re: Inserting characters before/after selected text

Postby Mofi » Mon Aug 01, 2011 12:53 pm

Modifying content of a file with a script while file content can be changed outside by another application will produce surely often damaged files.

I have posted at Insert characters/strings before and after selected block several methods how to insert strings or tags around a selection. I prefer for myself for the most often needed "insert string" cases the solution with templates because they offer the fastest and best method, especially because it works also if nothing is selected and caret position after template execution can be controlled. For the rarely used cases I use tags and the tag list view.

Macros and scripts are those which are often used by users not knowing that the templates and tags features offer the same much easier.

I have analyzed in the meantime why for ^^ in selection a temporary replacement in memory with ^^^^ is necessary and explained the reason in my initial post at bottom of the script. You can be 100% sure that this does not happen on other characters. And I will report this issue additionally by email to IDM support because in my point of view the script command UltraEdit.activeDocument.write() should not simply write ^^ as is into the file as UltraEdit.outputWindow.write() does for printing the same string into the output window.


But to answer your question because you want to insert strings around current selection as much complicated as possible, here is a first approach for a script solution:

Code: Select all
// Execute this script only with any file opened and column mode not enabled.
if ((UltraEdit.document.length > 0) && (UltraEdit.columnMode == false))
{
  // The script can't be used for a selection in hex edit mode.
  if (UltraEdit.activeDocument.hexMode == false)
  {
      if (UltraEdit.activeDocument.isSel())
      {
         var bInsertMode = UltraEdit.insOvrMode;
         UltraEdit.insertMode();
         var nLine = UltraEdit.activeDocument.currentLineNum;
         var nColumn = UltraEdit.activeDocument.currentColumnNum;
         // Depending on version of UltraEdit the returned column number
         // starts counting the columns with 0 or with 1, but for setting
         // the caret always a column count starting with 1 is required.
         if (typeof(UltraEdit.activeDocumentIdx) == "undefined") nColumn++;
         var nSelectedChars = UltraEdit.activeDocument.selection.length;
         UltraEdit.activeDocument.endSelect();
         UltraEdit.activeDocument.gotoLine(nLine,nColumn-nSelectedChars);
         UltraEdit.activeDocument.write("{");
         UltraEdit.activeDocument.gotoLine(nLine,nColumn + 1);
         UltraEdit.activeDocument.write("}");
         if (!bInsertMode) UltraEdit.overStrikeMode();
      }
      else  // Tell McFly that something isn't selected.
      {
         UltraEdit.messageBox("HELLO! McFly, select some text!", "Nothing Selected...");
      }
   }
}

But this solution has several problems:

  1. It works only for selections within a line. It does not work for multi-line selections. Multi-line selections would need analyzing the selected strings to find out how many lines are selected and how many characters are selected at end of first and at beginning of last selected line. This is not so easy, especially because of type of line terminator can be either DOS, or UNIX or MAC. Uuaargghh! I don't want to think further here.
  2. The returned line and column numbers are for current position of caret in the file. But from within a script it is not possible to determine if the caret is blinking at end of the selection because selection was made from left to right respectively top to bottom by the user, or is blinking at beginning of selection because the user selected from right to left respectively bottom to top.

Another solution:

Code: Select all
// Execute this script only with any file opened and column mode not enabled.
if ((UltraEdit.document.length > 0) && (UltraEdit.columnMode == false))
{
  // The script can't be used for a selection in hex edit mode.
  if (UltraEdit.activeDocument.hexMode == false)
  {
      if (UltraEdit.activeDocument.isSel())
      {
         var bInsertMode = UltraEdit.insOvrMode;
         UltraEdit.insertMode();
         var nPosition = UltraEdit.activeDocument.currentPos;
         var nSelectedChars = UltraEdit.activeDocument.selection.length;
         var_dump(nPosition);
         UltraEdit.activeDocument.gotoPos(nPosition);
         UltraEdit.activeDocument.write("{");
         nPosition += nSelectedChars + 1;
         UltraEdit.activeDocument.gotoPos(nPosition);
         UltraEdit.activeDocument.write("}");
         if (!bInsertMode) UltraEdit.overStrikeMode();
      }
      else  // Tell McFly that something isn't selected.
      {
         UltraEdit.messageBox("HELLO! McFly, select some text!", "Nothing Selected...");
      }
   }
}

Command UltraEdit.activeDocument.gotoPos(nPosition); requires UltraEdit v17.10 or later. It does not exist in previous versions of UltraEdit. UltraEdit.activeDocument.currentPos contains always the byte position (not character position which is different to byte position for Unicode files) at beginning of the selection independent of caret position, i.e. independent of direction of selection. So this script solves both problems of previous script.

But depending on string length inserted at beginning the number after nPosition += nSelectedChars + must be always correct set which makes writing such scripts more problematic than my initial script which does not depend on which strings are inserted at beginning and end of the currently selected text.

The script above works fine only for ASCII/ANSI files because for single byte encoded text files without BOM the byte position is equal the character position. But for Unicode files it does not work because the command UltraEdit.activeDocument.gotoPos(); requires the character position and not the byte position. So for Unicode files (with a BOM) the line

Code: Select all
         var nPosition = UltraEdit.activeDocument.currentPos;

must be replaced by

Code: Select all
         var nPosition = (UltraEdit.activeDocument.currentPos - 2) / 2;

to get the correct result. For UTF-16 files without BOM - 2 needs to be removed. In other words, this solution can work for one user, but might not work for another user because of using different type of files.

Also this solution procudes 2 undo steps, while my initial script solution as well as using a template, a tag, or the first macro solution (see referenced topic) produces only 1 unto step.

It's up to you if you want a simple solution as I suggested by using templates, tags, macros (could be coded also as scripts), or my initial script, or if you want a complicated solution with line/column or byte/character positioning with all their disadvantages.

PS: UltraEdit.activeDocument.currentPos was initially designed for hex editing mode which is the reason why it contains the number of bytes from top to current position in the file. The command UltraEdit.activeDocument.gotoLine() is in hex edit mode in real a "goto byte offset" command as you can see when you press Ctrl+G in text edit mode versus Ctrl+G in hex edit mode. But the users requested a "goto character position" unfortunately without taking into account that property currentPos does not contain always the number of characters from top to current position in the file because that is true only for ASCII/ANSI files.
User avatar
Mofi
Grand Master
Grand Master
 
Posts: 4058
Joined: Thu Jul 29, 2004 11:00 pm
Location: Vienna


Return to Scripts