Community
    • Login

    "Sel:" in status bar is off-by-1 on line count?

    Scheduled Pinned Locked Moved Help wanted · · · – – – · · ·
    9 Posts 5 Posters 7.4k 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.
    • Alan KilbornA
      Alan Kilborn
      last edited by

      Sometimes I want to select a certain number of whole lines.

      When I create my stream selection, the “Sel: X | Y” section of the status bar shows me the number of characters I have blocked (X) and the number of lines (Y).

      The problem is that “Y” seems to be off-by-one (too high) and I have to remember and compensate in my mind for this.

      For example, If I want to select 7 full lines (including all line endings), I have to select until the Y in the status bar shows 8.

      This seems an awful design to me as I can never remember if it is one too high or one too low when I need to use it.

      I can remember for the duration of writing this posting because I just looked at it in-depth, but…

      Is there a reason it just doesn’t show what I think it should show?

      1 Reply Last reply Reply Quote 2
      • PeterJonesP
        PeterJones
        last edited by

        1. On the right, I have selected from the beginning to the end of line 1, without selecting the EOL. My cursor has stayed on one line, so Sel: 3|1 tells me my selection of three characters (“o”, “n”, “e”) spans 1 line.
        2. On the left, I have selected all of line one, and moved the cursor to line two. Because the selection includes the EOL, and the cursor is on a second line compared to the start of the selection, Sel: 5|2 tells me that I’ve selected 5 characters (“o”, “n”, “e”, CR, LF) across a total of 2 lines.
        1 Reply Last reply Reply Quote 2
        • Alan KilbornA
          Alan Kilborn
          last edited by

          @PeterJones

          I don’t agree with the “spans lines” answer…if I select 7 lines by click-drag on the line numbers margin, I expect to see 7 in the status bar, not 8. There really isn’t a valid argument that this somehow “spans 8 lines” – I’ve got seven complete lines and seven line endings. Thus, off-by-1!

          Scott SumnerS 1 Reply Last reply Reply Quote 0
          • Scott SumnerS
            Scott Sumner @Alan Kilborn
            last edited by

            @Alan-Kilborn

            I also don’t like the way this works; I don’t know that I would call it a bug, just “how it works”. Some time ago I wrote some Pythonscript to “fix” it. I’ll look at that code when I get some time, and if it is fit for human consumption, I’ll post it. :-)

            1 Reply Last reply Reply Quote 0
            • botman99B
              botman99
              last edited by

              Selecting a line using the line number margin causes the cursor to move to the line below what you have selected. The line that the cursor is on seems to be included in the lines “selected” so this seems like a bug to me.

              1 Reply Last reply Reply Quote 0
              • Claudia FrankC
                Claudia Frank
                last edited by

                A bug, I don’t know - it depends how you look at it.
                As the whole line gets selected it means the EOL get selected as well.
                As the cursor needs to be placed to create a target for selection,
                it can only be placed after EOL which means next line.

                Cheers
                Claudia

                1 Reply Last reply Reply Quote 0
                • botman99B
                  botman99
                  last edited by

                  I guess if you use the line number margin to select lines, to get the proper selection information you would need to move the cursor back one position to move it to the end of the last selected line. Then the numbers would be correct.

                  1 Reply Last reply Reply Quote 0
                  • Claudia FrankC
                    Claudia Frank
                    last edited by

                    but then you won’t select the eol.

                    Cheers
                    Claudia

                    1 Reply Last reply Reply Quote 0
                    • Scott SumnerS
                      Scott Sumner
                      last edited by Scott Sumner

                      Here’s the Pythonscript I mentioned earlier.

                      After running it, it will update the “Sel:” area in the status bar as follows:

                      • If selection contains partial lines which do not include the first line’s first character, not the last line’s last character (non-line-ending), then NO CHANGE from normal Notepad++ behavior.

                      • If the selection contains the first line’s first character, the part after the vertical bar (|) in “Sel: X | Y” will have a caret character (^) before the number of lines, e.g. ^7

                      • If the selection contains the last line’s last character (but not the line ending character(s)), the part after the vertical bar will have a dollar sign character ($) after the number of lines, e.g. 7$

                      • If the selection contains the last line’s last character AND the line ending character(s), the part after the vertical bar will have a dollar sign character ($) and \R after the number of lines, e.g. 7$\R

                      • If the selection contains lines in their entirety, the part after the vertical bar will combine all of these symbols, an example being ^7$\R. Note that this example means that 7 FULL LINES are in the selection, fixing the original “bad” Notepad++ behavior for this case.

                      Regular expression users will feel very comfortable with the meaning behind the choice of special symbols used here.

                      Okay, so here’s the Pythonscript code:

                      # Sel : C | L in the status bar shows an off-by-one L (line count) sometimes (open to debate)
                      # make it better:
                      #  Sel : C | L      <-- selection spans L partial lines
                      #  Sel : C | ^L     <-- selection spans L partial lines and includes first character on its first line
                      #  Sel : C | L$     <-- selection spans L partial lines and includes last char (but not line-ending) on its last line
                      #  Sel : C | L$\R   <-- selection spans L partial lines and includes line-ending on its last line
                      #  Sel : C | ^L$\R  <-- selection spans L FULL lines and includes line-ending on its last line
                      
                      def StatusbarSelOverride(args):
                          curr_pos = editor.getCurrentPos()
                          curr_line = editor.lineFromPosition(curr_pos)
                          curr_col = editor.getColumn(curr_pos)
                          sel_part = 'N/A'
                          if editor.getSelections() == 1:
                              sel_mode = editor.getSelectionMode()
                              rect_sel_mode = True if (sel_mode == SELECTIONMODE.RECTANGLE or sel_mode == SELECTIONMODE.THIN) else False
                              if not rect_sel_mode:
                                  if editor.getSelectionEmpty():
                                      sel_part = '0 | 0'
                                  else:
                                      sel_start_pos = editor.getSelectionStart()
                                      sel_end_pos = editor.getSelectionEnd()
                                      sel_start_line = editor.lineFromPosition(sel_start_pos)
                                      sel_end_line = editor.lineFromPosition(editor.getSelectionEnd())
                                      lines_touched_by_sel = sel_end_line - sel_start_line + 1
                                      start_of_line_symbol = '^' if sel_start_pos == editor.positionFromLine(sel_start_line) else ''
                                      end_of_line_symbols = '$' if sel_end_pos == editor.getLineEndPosition(sel_end_line) else ''
                                      selected_text = editor.getSelText()
                                      line_ending = ['\r\n', '\r', '\n'][notepad.getFormatType()]
                                      if selected_text.endswith(line_ending): end_of_line_symbols = r'$\R'; lines_touched_by_sel -= 1
                                      sel_text_len = len(selected_text)
                                      sel_part = '{tl} | {sol}{lis}{eol}'.format(
                                          tl=sel_text_len,
                                          sol=start_of_line_symbol,
                                          lis=lines_touched_by_sel,
                                          eol=end_of_line_symbols,
                                          )
                          line_col_sel_info_for_sb = 'Ln : {user_line}     Col : {user_col}     Sel : {sel}'.format(
                              user_line=curr_line+1,
                              user_col=curr_col+1,
                              sel=sel_part,
                              )
                          notepad.setStatusBar(STATUSBARSECTION.CURPOS, line_col_sel_info_for_sb)
                      
                      editor.callback(StatusbarSelOverride, [SCINTILLANOTIFICATION.UPDATEUI])  # register callback
                      
                      1 Reply Last reply Reply Quote 4
                      • First post
                        Last post
                      The Community of users of the Notepad++ text editor.
                      Powered by NodeBB | Contributors