Increment/decrement numbers in selected columns by X?

Increment/decrement numbers in selected columns by X?

7
NewbieNewbie
7

    May 04, 2011#1

    I'm using UES 10.30.0.1003
    I'm hoping for some help with this one:

    I have several files which are in this format:

    some text here 01 more text
    some text here 04 more text
    some text here 09 more text
    ...
    the text itself is rather random (and can contain numbers), and the only thing you can be sure of is that all numbers starts at the same column as the first one, hence
    the need for columnmode or similar.

    what I'm looking for is a way to increment/decrement the value in all selected lines by a number such as 10.

    Using the text above the result would be:
    some text here 11 more text
    some text here 14 more text
    some text here 19 more text
    ...

    The api for scripting seems to miss some items related to selections, or there's something I'm missing in the documentation.
    It would be nice with things such as selStartLine, selStartColumn, selEndLine,selEndColumn and selectedLine[number] or similar
    to make such operations a bit easier.

    btw, can activeDocument.selection handle columnmode at all?
    So far I haven't managed to get it to do so.
    It seems to return some random text from the document (which may not necessarily be from within the selection) if
    columnmode is enabled.

    6,675585
    Grand MasterGrand Master
    6,675585

      May 05, 2011#2

      Here is a script which demonstrates searching in columns with increasing all numbers in columns 16 and 17 (with column count starting with 1).

      Code: Select all

      if (UltraEdit.document.length > 0) {
         UltraEdit.insertMode();
         UltraEdit.columnModeOff();
         UltraEdit.perlReOn();
         UltraEdit.activeDocument.top();
         UltraEdit.activeDocument.findReplace.mode=0;
         UltraEdit.activeDocument.findReplace.matchCase=false;
         UltraEdit.activeDocument.findReplace.matchWord=false;
         UltraEdit.activeDocument.findReplace.regExp=true;
         UltraEdit.activeDocument.findReplace.searchDown=true;
         UltraEdit.activeDocument.findReplace.searchInColumn=true;
         UltraEdit.activeDocument.findReplace.fromCol=15;
         UltraEdit.activeDocument.findReplace.toCol=17;
         while (UltraEdit.activeDocument.findReplace.find("\\d+")) {
            var nNumber = parseInt(UltraEdit.activeDocument.selection,10) + 10;
            var sNumber = nNumber.toString();
            while (sNumber.length < UltraEdit.activeDocument.selection.length) sNumber = '0' + sNumber;
            UltraEdit.activeDocument.write(sNumber);
         }
      }
      But you want a script which increments the numbers at column 16 just in selected text. That is no problem using core functions of Javascript.

      Code: Select all

      if (UltraEdit.document.length > 0) {
         if (UltraEdit.activeDocument.isSel()) {
            var sSelectedText = UltraEdit.activeDocument.selection;
            var asSelLines = sSelectedText.split("\r\n");
            asNewLines = new Array();
            for (nLineNum = 0; nLineNum < asSelLines.length; nLineNum++) {
               if (asSelLines[nLineNum][15] < '0' || asSelLines[nLineNum][15] > '9') {
                  asNewLines.push(asSelLines[nLineNum]);
               }
               else {
                  var sNumber = asSelLines[nLineNum].replace(/.{15}(\d+).*$/,"$1");
                  var nValue = parseInt(sNumber,10) + 10;
                  var sValue = nValue.toString();
                  while (sValue.length < sNumber.length) sValue = '0' + sValue;
                  asNewLines.push(asSelLines[nLineNum].replace(/(.{15})\d+/,"$1"+sValue));
               }
            }
            if (asNewLines.length == 1) {
               UltraEdit.activeDocument.write(asNewLines[0]);
            }
            else {
               UltraEdit.activeDocument.write(asNewLines.join("\r\n"));
            }
         }
      }

      7
      NewbieNewbie
      7

        May 05, 2011#3

        Thanks for the input.
        I modified your first one a bit as that one seemed easier to achieve most of what I wanted, and this is what I've ended up with so far. Instead of setting a specific ending column I try to check if it starts at the specified column so as to avoid breaking up a number.

        It leaves a bit to be desired, but I guess some of it is due to the limitations of UES script, such as missing default values for getValue (instead it uses '0' unselected), can't ask for a series of values at once, all single changes stored by undo etc. in addition to not being very fast mostly due to all operations being shown to the user.

        But it seems to do what it should, no matter how much the increment is by, and, apparently no matter the column number.

        It doesn't obey any selection though. Script removed, see better versions below.

        6,675585
        Grand MasterGrand Master
        6,675585

          May 06, 2011#4

          Fine. Just one additional note about can't ask for a series of values at once. You can use getString to ask the user for starting column and increment number and parse the returned string by script code to extract the starting column number and the increment number separated by any non digit character. You could even code that number parsing more smart so that script user can omit the second number for the increment value because script uses always 1 for increment when second number missing. Perhaps the script user could use also value 0 or nothing for starting column number and then the script uses simply the column number of caret position on script start.

          7
          NewbieNewbie
          7

            May 06, 2011#5

            Oh, thanks for the tip. I guess I'm a bit of spoilt with usually being able to set defaults etc. :)

            This is a somewhat brief attempt of the parse suggestion.
            Now it accepts blank (which uses the predefined settings), StartColumn, and StartColumn and Increment By.
            It worked better than expected. at least there's only one dialog.

            Code: Select all

            if (UltraEdit.document.length > 0) {
            	var startCol=8;
            	var incrementBy=1;
            	var maxWidth=0;
            	var origLine=UltraEdit.activeDocument.currentLineNum;
            	var origCol=UltraEdit.activeDocument.currentColumnNum;	
            	var valuesRE = /\s*(\d+)(?:\D+(\d+))?/i;
            	var values;
            	UltraEdit.insertMode();
            	UltraEdit.columnModeOff();
            	UltraEdit.perlReOn();
            	values=UltraEdit.getString('[StartColumn] [Increment By]',1)
            	// "parse" the input. Maybe a bit heavy handled to use a regex for it, but its less code I guess..
            	var valueMatches = valuesRE.exec(values);
            	if (valueMatches != null) {
            		startCol = parseInt(valueMatches[1],10);
            		if (valueMatches[2]){
            			incrementBy = parseInt(valueMatches[2],10);
            		} 
            	}
            	
            	UltraEdit.outputWindow.write('Start at column: '+startCol+'\r\nIncrement by: '+incrementBy);
            	if (startCol>0) startCol--;//decrement by 1 to make the column number in the status line be the correct to use.
            	UltraEdit.activeDocument.top();
            	UltraEdit.activeDocument.findReplace.mode=0;
            	UltraEdit.activeDocument.findReplace.matchCase=false;
            	UltraEdit.activeDocument.findReplace.matchWord=false;
            	UltraEdit.activeDocument.findReplace.regExp=true;
            	UltraEdit.activeDocument.findReplace.searchDown=true;
            	UltraEdit.activeDocument.findReplace.searchInColumn=true;
            	UltraEdit.activeDocument.findReplace.fromCol=startCol;
            	UltraEdit.activeDocument.findReplace.toCol=-1;
            	// Determine the max length of the number.
            	while (UltraEdit.activeDocument.findReplace.find("\\d+")) {
            		// Make sure we start at the proper column
            		if (UltraEdit.activeDocument.currentColumnNum==(startCol+UltraEdit.activeDocument.selection.length+1)){
            			maxWidth=Math.max(maxWidth,parseInt(UltraEdit.activeDocument.selection,10) + incrementBy);
            		}
            	}
            	maxWidth=maxWidth.toString().length;
            
            	// Start the actual incrementing, prefixing with '0' as necessary.
            	UltraEdit.activeDocument.top();
            	while (UltraEdit.activeDocument.findReplace.find("\\d+")) {
            		// Make sure we start at the proper column
            		if (UltraEdit.activeDocument.currentColumnNum==(startCol+UltraEdit.activeDocument.selection.length+1)){
            		  var nNumber = parseInt(UltraEdit.activeDocument.selection,10) + incrementBy;
            		  var sNumber = nNumber.toString();
            		  while (sNumber.length < maxWidth) sNumber = '0' + sNumber;
            		  UltraEdit.activeDocument.write(sNumber);
            	  }
            	}
            	// Return to original position in document.
            	UltraEdit.activeDocument.gotoLine(origLine,origCol);
            }

            6,675585
            Grand MasterGrand Master
            6,675585

              May 06, 2011#6

              Last hint:

              With adding below the code line

              if (startCol>0) startCol--;

              the code line

              else startCol = origCol-1;

              would result in using column of caret on script start as start column if script user enters 0 for the start column.


              A hint for users of UltraEdit with version lower 16.00 or UEStudio with a version 10.00:

              You have to take Document property currentColumnNum returns different value with UE v16.00+ into account when using myarmor's script.

              I have attached myarmor's script with above line a little bit different coded as suggested for correct information in output window, with counting and printing additionally the number of modified numbers, and with some small other changes to make the script more or less independent of version of UE/UES. Searching in columns requires at least UE v14.00 according to information in file changes.txt.
              IncrementNumbersInColumn.zip (1.03 KiB)   193
              myarmor's script a little bit modified as written above (with fixed initial condition)

              7
              NewbieNewbie
              7

                May 06, 2011#7

                Nice.. :)
                Your changes seems to make it a bit more useful to and a bit more compatible.
                static defaults isn't preferable so..

                I often end up having to do exactly this operation so a big thanks for the suggestions.

                I recommend using mofi's zipped version of this code as it implements all these changes,
                such as using the current column as default if nothing is written into the dialog etc..