Smart/contextual unindent (for Python scripts)

Smart/contextual unindent (for Python scripts)

1
NewbieNewbie
1

    Sep 12, 2017#1

    I downloaded the latest version of UltraEdit and when I enter the following into a Python file that is indented by 4 spaces:

    Code: Select all

    if blah == 1:
        x = 1<Enter><Backspace>
    I would expect the cursor to return to column 1. Most code editors that are Python aware perform this way. In UltraEdit, it simply deletes one character and leaves the cursor on column 4, where no valid text can be entered (per Python's indentation rules).

    Is there any way to change that behavior?

    6,684586
    Grand MasterGrand Master
    6,684586

      Sep 13, 2017#2

      UltraEdit is not designed as Python aware code editor. So it has built-in no feature for smart removing spaces on pressing key BACKSPACE in a Python script file.

      But UltraEdit can be customized and extended by their users using UltraEdit macros or scripts.

      Here is a quickly coded scripting solution for replacing built-in BACKSPACE behavior by a script designed for smart unindent Python indents with 4 spaces.

      Code: Select all

      function SmartUnindent()
      {
         var nIndentSpaces = 4;
      
         // Execute deletion with key BACKSPACE under following conditions:
      
         // The active file is opened in hex edit mode.
         if (UltraEdit.activeDocument.hexMode)
         {
            return;  // Do nothing because UltraEdit also does nothing
         }           // on pressing key BACKSPACE in hex edit mode.
      
         // There is a selection in active file.
         if (UltraEdit.activeDocument.isSel())
         {
            UltraEdit.activeDocument.key("BACKSPACE"); return;
         }
      
         // The caret is at beginning of a line.
         if (UltraEdit.activeDocument.isColNum(1))
         {
            UltraEdit.activeDocument.key("BACKSPACE"); return;
         }
      
         // The file extension is whether PY nor PYW.
         if ((!UltraEdit.activeDocument.isExt("py")) && (!UltraEdit.activeDocument.isExt("pyw")))
         {
            UltraEdit.activeDocument.key("BACKSPACE"); return;
         }
      
         // The character left to caret position is not a space character.
         UltraEdit.activeDocument.key("LEFT ARROW");
         if (!UltraEdit.activeDocument.isChar(" "))
         {
            UltraEdit.activeDocument.deleteText(); return;
         }
      
         // Smart delete 1 to 4 spaces.
         var nStartColumn = UltraEdit.activeDocument.currentColumnNum + 1;
      
         var nFirstColumnNumber = 1;
         // The next block is needed only for UltraEdit for Windows < v16.00 and
         // UEStudio < v10.00 on which property currentColumnNum has value 0 for
         // the first column in a line, 1 for second column, and so on.
         if (typeof(UltraEdit.activeDocumentIdx) == "undefined")
         {
            nStartColumn++;
            nFirstColumnNumber = 0;
         }
      
         var nDeleteSpaces = nIndentSpaces - 1;  // One space is already counted.
      
         // The loop below is exited before defined number of spaces being counted
         // if caret is already at first column in current line or the character
         // at current position in file is not a space character. In second case
         // are deleted just the spaces up to first non space character. The loop
         // is also exited if the current position of caret in file is at a tab
         // stop value / indent spaces position independent on how many spaces
         // have been already processed for being deleted next.
         do
         {
            if (UltraEdit.activeDocument.isColNum(1)) break;
            if (((UltraEdit.activeDocument.currentColumnNum - nFirstColumnNumber) % nIndentSpaces) == 0) break;
            UltraEdit.activeDocument.key("LEFT ARROW");
            if (!UltraEdit.activeDocument.isChar(" "))
            {
               UltraEdit.activeDocument.key("RIGHT ARROW");
               break;
            }
         }
         while(--nDeleteSpaces);
      
         UltraEdit.activeDocument.gotoLineSelect(0,nStartColumn);
         UltraEdit.activeDocument.deleteText();
      }
      
      if (UltraEdit.document.length > 0)  // Is any file opened?
      {
         SmartUnindent();
      }
      Copy and paste the script code into a new ANSI encoded file with DOS line terminators and save it for example with file name Python Smart Unindent.js in directory %APPDATA%\IDMComp\UltraEdit\Scripts whereby directory Scripts must be first created on saving the file.

      Then add this script to Script List. You have not posted which version of UltraEdit your are using in which GUI mode. Therefore I can't post a step by step instruction how to add a script to Script List suitable for your version of UltraEdit in used GUI mode.

      Assign Shift + BACKSPACE as hotkey to the script. It is not possible to assign just BACKSPACE directly to the script as this key is used also in the dialog window to delete existing hotkey assignment.

      You can already test now on an opened *.py or *.pyw file the script behavior on pressing Shift + BACKSPACE.

      Exit UltraEdit and open %APPDATA%\IDMComp\UltraEdit\uedit*.ini in Windows Notepad. The exact file name depends on version of Windows which I don't know as not posted by you. Search in INI file of UltraEdit for Shift + BACKSPACE and replace the single occurrence by just BACKSPACE. Save the INI file and exit Windows Notepad. Now the script is executed by UltraEdit on pressing key BACKSPACE.

      For this script it is definitely useful to open in UltraEdit for Windows Advanced - Settings or Configuration - Scripting and uncheck Show status information in output window and Show cancel dialog. But please note that these two options are global settings for all UltraEdit scripts. When you ever develop an UltraEdit script in future by yourself, you should enable both settings again for the duration of development and testing your script.

      I wrote first a scripting solution as I was not sure if the task could be done also with an UltraEdit macro because variables are not supported in macros. But after finishing script coding task I think this smart unindent could be also coded as UltraEdit macro with a different approach. A macro solution would be faster on execution than the scripting solution. But I decided to first post the already completed scripting solution and wait on your reply before coding a macro solution.

      Edit on 2017-09-17: The script was enhanced to stop at an indent spaces position of 4 for unindent when the number of spaces in current line is not a multiple of 4.
      Best regards from an UC/UE/UES for Windows user from Austria