• Login
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.
  • A
    Alan Kilborn
    last edited by Jan 11, 2017, 2:57 PM

    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
    • P
      PeterJones
      last edited by Jan 11, 2017, 3:09 PM

      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
      • A
        Alan Kilborn
        last edited by Jan 11, 2017, 6:28 PM

        @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!

        S 1 Reply Last reply Jan 11, 2017, 6:32 PM Reply Quote 0
        • S
          Scott Sumner @Alan Kilborn
          last edited by Jan 11, 2017, 6:32 PM

          @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
          • B
            botman99
            last edited by Jan 11, 2017, 10:47 PM

            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
            • C
              Claudia Frank
              last edited by Jan 12, 2017, 12:40 AM

              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
              • B
                botman99
                last edited by Jan 12, 2017, 4:38 PM

                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
                • C
                  Claudia Frank
                  last edited by Jan 12, 2017, 4:40 PM

                  but then you won’t select the eol.

                  Cheers
                  Claudia

                  1 Reply Last reply Reply Quote 0
                  • S
                    Scott Sumner
                    last edited by Scott Sumner Jan 14, 2017, 1:31 PM Jan 14, 2017, 1:30 PM

                    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
                    6 out of 9
                    • First post
                      6/9
                      Last post
                    The Community of users of the Notepad++ text editor.
                    Powered by NodeBB | Contributors