• Login
Community
  • Login

TextFX doesn't work

Scheduled Pinned Locked Moved Help wanted · · · – – – · · ·
12 Posts 3 Posters 5.5k Views
Loading More Posts
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • L
    LAPIII
    last edited by May 3, 2018, 1:06 PM

    What I want to work is Line up multiple lines by (,). I made a list on three lines, selected everything, and then went to TextFX Edit to select the option, but nothing happened. I tried the same for the other two Line up options, neither had worked. I uninstalled the plug-in and then reinstalled, but it still doesn’t work for me. Am I doing something wrong?
    I’m using Notepad v7.6.5 32 bit on Windows 106 4 bit. I read that the add-on is 32-bit only, but should be okay in N++ 32-bit.
    I’m using

    S 1 Reply Last reply May 3, 2018, 1:29 PM Reply Quote 3
    • S
      Scott Sumner @LAPIII
      last edited by May 3, 2018, 1:29 PM

      @LAPIII

      I’m not at all a big fan of TextFX, but it seemed to work for what I guessed might resemble your situation (see below for my “before” and “after”). Maybe if you’d have shown some sample data where it doesn’t work for you…

      Imgur

      1 Reply Last reply Reply Quote 4
      • S
        Scott Sumner
        last edited by Jun 20, 2018, 3:13 PM

        This isn’t the best code I’ve ever written [ :-D ] but it seems to mimic the TextFX functionality, and should run on 64-bit where TextFX isn’t–and likely will never be–available.

        It requires the Pythonscript plugin; I call it LineUpMultipleLinesBySpecifiedCharacter.py:

        def LUMLBSC_main():
        
            ps_name = 'Line Up Multiple Lines By Specified Character'
        
            line_ending = ['\r\n', '\r', '\n'][notepad.getFormatType()]
        
            (first_line, last_line) = editor.getUserLineSelection()
            if first_line == 0 and last_line == editor.getLineCount() - 1:
                if notepad.messageBox('\r\n'.join([
                    'Do you want to line up ALL lines in the file by the alignment character',
                    '(which you will specify in a moment)',
                    '?',
                    '\r\n',
                    'If not, create a selection touching lines to affect, and re-run...',
                    ]),
                    ps_name, MESSAGEBOXFLAGS.YESNO) != MESSAGEBOXFLAGS.RESULTYES: return
        
            result = notepad.prompt('Enter delimiter:', ps_name, ',')
            if result == None or len(result) == 0: return
            delimiter = result
        
            line_interdelim_list_of_lists = []
            longest_length_list = []
        
            (selection_start, selection_end) = editor.getUserCharSelection()
            start_position_selected_lines = editor.positionFromLine(editor.lineFromPosition(selection_start))
            end_position_selected_lines = editor.getLineEndPosition(editor.lineFromPosition(selection_end))
        
            lines = editor.getTextRange(start_position_selected_lines, end_position_selected_lines).splitlines()
        
            # find the longest interdelimiter piece between each delimiter:
            for line in lines:
                interdelimiter_list = line.split(delimiter)
                line_interdelim_list_of_lists.append(interdelimiter_list)
                num_delimiters_this_line = len(interdelimiter_list) - 1
                if num_delimiters_this_line > 0:
                    if len(longest_length_list) < num_delimiters_this_line + 1:
                        longest_length_list += [0] * (num_delimiters_this_line + 1 - len(longest_length_list))
                    for (j, interdelimiter_string) in enumerate(interdelimiter_list):
                        if len(interdelimiter_string) > longest_length_list[j]: longest_length_list[j] = len(interdelimiter_string)
        
            # build up new lines:
            new_lines_list = []
            for old_interdelimiter_list in line_interdelim_list_of_lists:
                if len(old_interdelimiter_list) - 1 > 0:
                    new_interdelimiter_list = []
                    for (j, interdelimiter_string) in enumerate(old_interdelimiter_list):
                        if len(interdelimiter_string) < longest_length_list[j] and j != len(old_interdelimiter_list) - 1:
                            new_interdelimiter_list.append(interdelimiter_string + ' ' * (longest_length_list[j] - len(interdelimiter_string)))
                        else:
                            new_interdelimiter_list.append(interdelimiter_string)
                    line = delimiter.join(new_interdelimiter_list)
                else:
                    line = delimiter.join(old_interdelimiter_list)
                new_lines_list.append(line)
        
            # replace original lines with new lines:
            editor.setTarget(start_position_selected_lines, end_position_selected_lines)
            editor.replaceTarget(line_ending.join(new_lines_list))
        
        LUMLBSC_main()
        
        1 Reply Last reply Reply Quote 1
        • G
          guy038
          last edited by Jun 20, 2018, 10:41 PM

          Hello, @scott-sumner and All ,

          I’ve just tried your script and it’s working nice ! Now, if you copy/paste the following blocks of text in Notepad++, unset the Word wrap option, for best reading !

          Two remarks :


          A)

          • From your initial text, below :
          Hot, with food story told once chief seven, press smile often, modern begin did.
          Sugar town gold heart boat modern dead, did; meet crowd tube several figure.
          Four; loud brought our before size segment south; open second, bright answer board stood; over.
          Offer him sentence caught necessary feet just plan write noise rope question foot.
          Can early young stand, tie most expect play value black!
          Pick thick special, left hair thank grass boat; morning.
          Him corn, look cotton they match floor fair came also better side stretch quite.
          Sent now favor rock type tail huge; good flat where opposite try add.
          Wrong kill use point may broad region grand king minute.
          Term organ value, million ring charge view, control map, sight wall, tool interest.
          

          After running the script, we get the following text :

          Hot                                                          , with food story told once chief seven                                 , press smile often, modern begin did.
          Sugar town gold heart boat modern dead                       , did; meet crowd tube several figure.
          Four; loud brought our before size segment south; open second, bright answer board stood; over.
          Offer him sentence caught necessary feet just plan write noise rope question foot.
          Can early young stand                                        , tie most expect play value black!
          Pick thick special                                           , left hair thank grass boat; morning.
          Him corn                                                     , look cotton they match floor fair came also better side stretch quite.
          Sent now favor rock type tail huge; good flat where opposite try add.
          Wrong kill use point may broad region grand king minute.
          Term organ value                                             , million ring charge view                                              , control map      , sight wall       , tool interest.
          

          I noticed that the last comma sign ( the 4th ), of the last line, seems aligned with a virtual comma char, located after the end of the first line. So, to be logic, it would be better to consider that the first comma of every line, should begin AFTER the longest line of text, which has not a comma character, at all ! ( the 4th line, in your example )

          So, we would obtain :

          Hot                                                                               , with food story told once chief seven                                 , press smile often, modern begin did.
          Sugar town gold heart boat modern dead                                            , did; meet crowd tube several figure.
          Four; loud brought our before size segment south; open second                     , bright answer board stood; over.
          Offer him sentence caught necessary feet just plan write noise rope question foot.
          Can early young stand                                                             , tie most expect play value black!
          Pick thick special                                                                , left hair thank grass boat; morning.
          Him corn                                                                          , look cotton they match floor fair came also better side stretch quite.
          Sent now favor rock type tail huge; good flat where opposite try add.
          Wrong kill use point may broad region grand king minute.
          Term organ value                                                                  , million ring charge view                                              , control map      , sight wall       , tool interest.
          

          It look easier to read ;-))


          B)

          May be, a second version, of your script, could take delimiters in account ! I mean that the specified character would not be considered if found between a list of specific delimiters, or after some comment delimiters until the end of current line !

          Of course, it’s just some thoughts and, simply, do as you like !

          Best Regards,

          guy038

          S 1 Reply Last reply Jun 22, 2018, 1:30 PM Reply Quote 2
          • S
            Scott Sumner @guy038
            last edited by Jun 22, 2018, 1:30 PM

            Hello @guy038 ,

            Thank you for taking an interest in the script. My purpose was to exactly duplicate the TextFX functionality, but after reading your comments and some further testing, I see that it doesn’t quite do that, so I offer up a revised version, below.

            Regarding enhancements over and above the TextFX functionality, let’s not go there with this one. I am, however, working up something in response to this thread which will maybe meet a more flexible alignment need (and it probably will involve regular expressions!)…

            def LUMLBSC_main():
            
                ps_name = 'Line Up Multiple Lines By Specified Character'
            
                line_ending = ['\r\n', '\r', '\n'][notepad.getFormatType()]
            
                (first_line, last_line) = editor.getUserLineSelection()
                if first_line == 0 and last_line == editor.getLineCount() - 1:
                    if notepad.messageBox('\r\n'.join([
                        'Do you want to line up ALL lines in the file by the alignment character',
                        '(which you will specify in a moment)',
                        '?',
                        '\r\n',
                        'If not, create a selection touching lines to affect, and re-run...',
                        ]),
                        ps_name, MESSAGEBOXFLAGS.YESNO) != MESSAGEBOXFLAGS.RESULTYES: return
            
                result = notepad.prompt('Enter delimiter:', ps_name, ',')
                if result == None or len(result) == 0: return
                delimiter = result
            
                line_interdelim_list_of_lists = []
                longest_length_list = []
            
                (selection_start, selection_end) = editor.getUserCharSelection()
                start_position_selected_lines = editor.positionFromLine(editor.lineFromPosition(selection_start))
                end_position_selected_lines = editor.getLineEndPosition(editor.lineFromPosition(selection_end))
            
                lines = editor.getTextRange(start_position_selected_lines, end_position_selected_lines).splitlines()
            
                # find the longest interdelimiter piece between each delimiter:
                for line in lines:
                    interdelimiter_list = line.split(delimiter)
                    line_interdelim_list_of_lists.append(interdelimiter_list)
                    num_delimiters_this_line = len(interdelimiter_list) - 1
                    if num_delimiters_this_line > 0:
                        if len(longest_length_list) < num_delimiters_this_line: longest_length_list += [0] * (num_delimiters_this_line - len(longest_length_list))
                        for (j, interdelimiter_string) in enumerate(interdelimiter_list):
                            if j != len(interdelimiter_list) - 1:
                                if len(interdelimiter_string) > longest_length_list[j]: longest_length_list[j] = len(interdelimiter_string)
            
                # build up new lines:
                new_lines_list = []
                for old_interdelimiter_list in line_interdelim_list_of_lists:
                    if len(old_interdelimiter_list) - 1 > 0:
                        new_interdelimiter_list = []
                        for (j, interdelimiter_string) in enumerate(old_interdelimiter_list):
                            if (j != len(old_interdelimiter_list) - 1) and (len(interdelimiter_string) < longest_length_list[j]):
                                new_interdelimiter_list.append(interdelimiter_string + ' ' * (longest_length_list[j] - len(interdelimiter_string)))
                            else:
                                new_interdelimiter_list.append(interdelimiter_string)
                        line = delimiter.join(new_interdelimiter_list)
                    else:
                        line = delimiter.join(old_interdelimiter_list)
                    new_lines_list.append(line)
            
                # replace original lines with new lines:
                editor.setTarget(start_position_selected_lines, end_position_selected_lines)
                editor.replaceTarget(line_ending.join(new_lines_list))
            
            LUMLBSC_main()
            
            1 Reply Last reply Reply Quote 1
            • G
              guy038
              last edited by guy038 Jun 22, 2018, 5:51 PM Jun 22, 2018, 5:48 PM

              Hello, @scott-sumner and All ,

              OK, got it ! Changes concern the first and last line of your original test. More logical, of course !


              Now, Scott, I found an easy work-around to get my “preferred line-up” behavior ! ( Rather stubborn, the guy ! )

              • Firstly, I use the regex S/R : SEARCH (?-s)^(?!.*,).+ and REPLACE $0,, which adds a comma at the end of all the lines, which do not contain any comma, yet.

              • Secondly, I run your LineUpMultipleLinesBySpecifiedCharacter.py script.

              • Thirdly, I use a second regex S/R : SEARCH \x20*,$ and REPLACE Leave EMPTY, which deletes any comma at the end of line, and its possible leading space characters.

              Et voilà,

              Cheers,

              guy038

              P.S. :

              Of course, in case of a list, made up some comma separated columns, it’s, likely, does not have a row, without any comma !

              1 Reply Last reply Reply Quote 2
              • S
                Scott Sumner
                last edited by Scott Sumner Jun 22, 2018, 6:02 PM Jun 22, 2018, 6:01 PM

                One thing that I failed to mention earlier is that it doesn’t take much data for the TextFX version of this function to fail big-time:

                Imgur

                The Pythonscript version, however, easily handled a 1000-line file with average line length of 150 characters and a variable amount of commas per line. I cite these numbers–which aren’t really all that “large”–as that is something I tested it on; I wasn’t looking for any kind of “maximum capability” during my experimentation, just (hopefully) correct behavior.

                To get TextFX to handle the same file, I found I had to cut it down to around 40 lines so that it would not choke with the “Out of memory” error.

                1 Reply Last reply Reply Quote 1
                • G
                  guy038
                  last edited by guy038 Jun 30, 2018, 12:26 AM Jun 30, 2018, 12:10 AM

                  Hi, @Scott-sumner and All,

                  I found a small bug in your LineUpMultipleLinesBySpecifiedCharacter.py script, when text contains accentuated characters !

                  For instance, assuming the 3-lines text, below, containing some French words :

                  été,automobile,écart,table
                  entrepôt,avion,bien-être,couteau
                  parlementaire,tu,prestidigitateur,fourchette
                  

                  Running the present script, I obtained :

                  été        ,automobile,écart          ,table
                  entrepôt    ,avion     ,bien-être      ,couteau
                  parlementaire,tu        ,prestidigitateur,fourchette
                  

                  Of course, I would expect this nicer text, below :-))

                  été          ,automobile,écart           ,table
                  entrepôt     ,avion     ,bien-être       ,couteau
                  parlementaire,tu        ,prestidigitateur,fourchette
                  

                  Cheers

                  guy038

                  P.S. :

                  Scott, I’m just thinking about a nice improvement :

                  Could it be possible to define, in addition to the character to line up,( default comma character ), a string which would separate the different columns ?

                  For example :

                  • Any , would be changed into two space + , + two space chars

                  =>

                  été            ,  automobile  ,  écart             ,  table
                  entrepôt       ,  avion       ,  bien-être         ,  couteau
                  parlementaire  ,  tu          ,  prestidigitateur  ,  fourchette
                  
                  • Any , would be changed into two space + | + two space chars

                  =>

                  été            |  automobile  |  écart             |  table
                  entrepôt       |  avion       |  bien-être         |  couteau
                  parlementaire  |  tu          |  prestidigitateur  |  fourchette
                  
                  • Any , would be changed into the ; punctuation char + 6 space chars + the ; punctuation character, again

                  =>

                  été          ;      ;automobile;      ;écart           ;      ;table
                  entrepôt     ;      ;avion     ;      ;bien-être       ;      ;couteau
                  parlementaire;      ;tu        ;      ;prestidigitateur;      ;fourchette
                  
                  S 1 Reply Last reply Jun 30, 2018, 12:44 AM Reply Quote 1
                  • S
                    Scott Sumner @guy038
                    last edited by Jun 30, 2018, 12:44 AM

                    @guy038 said:

                    small bug…when text contains accentuated characters !

                    Hi Guy,

                    Don’t you know by now that I am an A-Z (and, correspondingly, a-z) sort of person? :-D

                    I don’t know…I wanted to confine this script to just mimic the TextFX functionality…on an (?i)[A-Z] basis, though, of course, heheheh…

                    I’m just thinking about a nice improvement…

                    You’ve seen enough Pythonscript by now…how about trying your hand at these modifications? :-)

                    1 Reply Last reply Reply Quote 1
                    • G
                      guy038
                      last edited by guy038 Jun 30, 2018, 2:33 AM Jun 30, 2018, 2:30 AM

                      Hi, @Scott-sumner and All,

                      OK, boss, done ! So, here is, below, the second version of the Scott script, that I called LineUpMultipleLinesBySpecifiedCharacter_v2.py. However, just note that is, merely, a simple re-copy of Scott’s code :-(

                      def LUMLBSC_v2_main():
                      
                          ps_name = 'Line Up Multiple Lines By Specified Character'
                      
                          line_ending = ['\r\n', '\r', '\n'][notepad.getFormatType()]
                      
                          (first_line, last_line) = editor.getUserLineSelection()
                          if first_line == 0 and last_line == editor.getLineCount() - 1:
                              if notepad.messageBox('\r\n'.join([
                                  'Do you want to line up ALL lines in the file by the alignment character',
                                  '(which you will specify in a moment)',
                                  '?',
                                  '\r\n',
                                  'If not, create a selection touching lines to affect, and re-run...',
                                  ]),
                                  ps_name, MESSAGEBOXFLAGS.YESNO) != MESSAGEBOXFLAGS.RESULTYES: return
                      
                          result = notepad.prompt('Enter delimiter:', ps_name, ',')
                          if result == None or len(result) == 0: return
                          delimiter = result
                      
                          separator = notepad.prompt('Enter the separator string, between columns:', ps_name, ',')
                          if separator == None or len(result) == 0: return
                      
                          line_interdelim_list_of_lists = []
                          longest_length_list = []
                      
                          (selection_start, selection_end) = editor.getUserCharSelection()
                          start_position_selected_lines = editor.positionFromLine(editor.lineFromPosition(selection_start))
                          end_position_selected_lines = editor.getLineEndPosition(editor.lineFromPosition(selection_end))
                      
                          lines = editor.getTextRange(start_position_selected_lines, end_position_selected_lines).splitlines()
                      
                          # find the longest interdelimiter piece between each delimiter:
                          for line in lines:
                              interdelimiter_list = line.split(delimiter)
                              line_interdelim_list_of_lists.append(interdelimiter_list)
                              num_delimiters_this_line = len(interdelimiter_list) - 1
                              if num_delimiters_this_line > 0:
                                  if len(longest_length_list) < num_delimiters_this_line: longest_length_list += [0] * (num_delimiters_this_line - len(longest_length_list))
                                  for (j, interdelimiter_string) in enumerate(interdelimiter_list):
                                      if j != len(interdelimiter_list) - 1:
                                          if len(interdelimiter_string) > longest_length_list[j]: longest_length_list[j] = len(interdelimiter_string)
                      
                          # build up new lines:
                          new_lines_list = []
                          for old_interdelimiter_list in line_interdelim_list_of_lists:
                              if len(old_interdelimiter_list) - 1 > 0:
                                  new_interdelimiter_list = []
                                  for (j, interdelimiter_string) in enumerate(old_interdelimiter_list):
                                      if (j != len(old_interdelimiter_list) - 1) and (len(interdelimiter_string) < longest_length_list[j]):
                                          new_interdelimiter_list.append(interdelimiter_string + ' ' * (longest_length_list[j] - len(interdelimiter_string)))
                                      else:
                                          new_interdelimiter_list.append(interdelimiter_string)
                                  line = separator.join(new_interdelimiter_list)
                              else:
                                  line = separator.join(old_interdelimiter_list)
                              new_lines_list.append(line)
                      
                          # replace original lines with new lines:
                          editor.setTarget(start_position_selected_lines, end_position_selected_lines)
                          editor.replaceTarget(line_ending.join(new_lines_list))
                      
                      LUMLBSC_v2_main()
                      

                      Strangely, if I chose an empty separator string, I thought that the script would exit without doing nothing. but I did get a text, without any separator

                      So, from this sample text ( which is the exact translation of my previous French text ! ) :

                      summer,automobile,space,table
                      warehouse,plane,wellbeing,knife
                      member of parliament,you,conjurer,fork
                      

                      It gives that text, without any separator between columns !

                      summer              automobilespace    table
                      warehouse           plane     wellbeingknife
                      member of parliamentyou       conjurer fork
                      

                      BR

                      guy038

                      P.S. :

                      But, I’m still short of ideas, regarding the accentuated characters ;-))

                      S 1 Reply Last reply Jun 30, 2018, 10:35 AM Reply Quote 2
                      • S
                        Scott Sumner @guy038
                        last edited by Jun 30, 2018, 10:35 AM

                        @guy038 said:

                        merely, a simple re-copy of Scott’s code

                        Wha? You made no changes except to add v2 in the name??

                        1 Reply Last reply Reply Quote 1
                        • G
                          guy038
                          last edited by guy038 Jul 8, 2018, 7:14 PM Jun 30, 2018, 12:09 PM

                          Hi, @Scott-sumner

                          I do not understand what you mean ?

                          I did added the part :

                              separator = notepad.prompt('Enter the separator string, between columns:', ps_name, ',')
                              if separator == None or len(result) == 0: return
                          

                          and I changed the lines :

                                      line = delimiter.join(new_interdelimiter_list)
                                  else:
                                      line = delimiter.join(old_interdelimiter_list)
                          

                          as :

                                      line = separator.join(new_interdelimiter_list)
                                  else:
                                      line = separator.join(old_interdelimiter_list)
                          

                          Not a great task, I agree, but, however, significant… and it works nice ;-))

                          BR

                          guy038

                          1 Reply Last reply Reply Quote 2
                          • First post
                            Last post
                          The Community of users of the Notepad++ text editor.
                          Powered by NodeBB | Contributors