From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!.POSTED!not-for-mail From: Keith David Bershatsky Newsgroups: gmane.emacs.bugs Subject: bug#28246: display line number width != length of line number at eob Date: Sun, 27 Aug 2017 18:46:42 -0700 Message-ID: References: NNTP-Posting-Host: blaine.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=US-ASCII X-Trace: blaine.gmane.org 1503884842 5674 195.159.176.226 (28 Aug 2017 01:47:22 GMT) X-Complaints-To: usenet@blaine.gmane.org NNTP-Posting-Date: Mon, 28 Aug 2017 01:47:22 +0000 (UTC) Cc: 28246@debbugs.gnu.org To: Eli Zaretskii Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Mon Aug 28 03:47:09 2017 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by blaine.gmane.org with esmtp (Exim 4.84_2) (envelope-from ) id 1dm98u-0000kh-1r for geb-bug-gnu-emacs@m.gmane.org; Mon, 28 Aug 2017 03:47:08 +0200 Original-Received: from localhost ([::1]:36465 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dm98z-0003UA-02 for geb-bug-gnu-emacs@m.gmane.org; Sun, 27 Aug 2017 21:47:13 -0400 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:40637) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dm98r-0003U4-OM for bug-gnu-emacs@gnu.org; Sun, 27 Aug 2017 21:47:07 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dm98o-0001gO-JM for bug-gnu-emacs@gnu.org; Sun, 27 Aug 2017 21:47:05 -0400 Original-Received: from debbugs.gnu.org ([208.118.235.43]:49771) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1dm98o-0001g0-EK for bug-gnu-emacs@gnu.org; Sun, 27 Aug 2017 21:47:02 -0400 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1dm98o-0001KG-1Z for bug-gnu-emacs@gnu.org; Sun, 27 Aug 2017 21:47:02 -0400 X-Loop: help-debbugs@gnu.org In-Reply-To: Resent-From: Keith David Bershatsky Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Mon, 28 Aug 2017 01:47:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 28246 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: Original-Received: via spool by 28246-submit@debbugs.gnu.org id=B28246.15038848105079 (code B ref 28246); Mon, 28 Aug 2017 01:47:01 +0000 Original-Received: (at 28246) by debbugs.gnu.org; 28 Aug 2017 01:46:50 +0000 Original-Received: from localhost ([127.0.0.1]:58452 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1dm98b-0001Jq-Ad for submit@debbugs.gnu.org; Sun, 27 Aug 2017 21:46:49 -0400 Original-Received: from gateway24.websitewelcome.com ([192.185.50.252]:11857) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1dm98Z-0001Ji-Vs for 28246@debbugs.gnu.org; Sun, 27 Aug 2017 21:46:48 -0400 Original-Received: from cm17.websitewelcome.com (cm17.websitewelcome.com [100.42.49.20]) by gateway24.websitewelcome.com (Postfix) with ESMTP id 7FF5624E88 for <28246@debbugs.gnu.org>; Sun, 27 Aug 2017 20:46:44 -0500 (CDT) Original-Received: from gator3053.hostgator.com ([50.87.144.69]) by cmsmtp with SMTP id m97qdgQLWc72gm97qdVqBq; Sun, 27 Aug 2017 20:46:03 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lawlist.com ; s=default; h=Content-Type:MIME-Version:Subject:Cc:To:From:Message-ID:Date: Sender:Reply-To:Content-Transfer-Encoding:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: In-Reply-To:References:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=UQY4yGCDIiredm1Pp0WasCUlNkEMOKyffCAsvWOKkz0=; b=IR6g+Hr4+9PqkXc8DJt7XrbJve GpMOxHNF++qMoBhGHTE5Wqc+N8EP3EXGPSgVuND2ZM9e25iHd8zQcWhuTeJEouL2Wsg510IvHp+C/ im62Abmzb7LZvRIjyb1GVdFHVikhxeLsUh4XcCDGFWrlBk/y8+rdmABCz1QyrnMyU84URCgOQdgwi kNEczeohXAZeUHmf+M2fJJVemfVs7jLMwbsY8xVDHH1RrllT6ohgRe65ppvR6ziSz2EAv8HpK7LjW jkZ4/NbaEGrpd6FsHiNQG58fcuDCjPhdIV9/mmwR8wiLOeM8iJMLom9xKZOiUQIyA1qke5hghSsJa /03E+GuA==; Original-Received: from cpe-45-48-239-195.socal.res.rr.com ([45.48.239.195]:53918 helo=server.private) by gator3053.hostgator.com with esmtpsa (TLSv1:DHE-RSA-AES256-SHA:256) (Exim 4.87) (envelope-from ) id 1dm98V-001DYH-4L; Sun, 27 Aug 2017 20:46:43 -0500 X-AntiAbuse: This header was added to track abuse, please include it with any abuse report X-AntiAbuse: Primary Hostname - gator3053.hostgator.com X-AntiAbuse: Original Domain - debbugs.gnu.org X-AntiAbuse: Originator/Caller UID/GID - [47 12] / [47 12] X-AntiAbuse: Sender Address Domain - lawlist.com X-BWhitelist: no X-Source-IP: 45.48.239.195 X-Exim-ID: 1dm98V-001DYH-4L X-Source: X-Source-Args: X-Source-Dir: X-Source-Sender: cpe-45-48-239-195.socal.res.rr.com (server.private) [45.48.239.195]:53918 X-Source-Auth: lawlist X-Email-Count: 1 X-Source-Cap: bGF3bGlzdDtsYXdsaXN0O2dhdG9yMzA1My5ob3N0Z2F0b3IuY29t X-Local-Domain: yes X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 208.118.235.43 X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Original-Sender: "bug-gnu-emacs" Xref: news.gmane.org gmane.emacs.bugs:136284 Archived-At: Thank you, Eli, for reviewing #28246 and for explaining that automatic adjustment of the width for line-number display is *estimated* based upon certain criteria. I do not know whether any other Emacs users would appreciate *precision* width based upon the length of the last line in the buffer. Inasmuch as I was hoping to achieve *precision* width every command loop, display-line-numbers-width-start and/or display-line-numbers-grow-only would not suffice in that regard. I am uncertain why it->lnum_width is *not* always equal to (save-excursion (goto-char (point-max)) (length (format-mode-line "%l")) The difference between it->lnum_width and the Lisp code above can be seen with messages in the echo area after evaluating the code in the opening bug report for #28246, and thereafter manually adding/removing lines from the buffer. linum.el is slow in large buffers primarily because it uses count-lines. In an emacs.stackexchange.com thread entitled "A faster method to obtain `line-number-at-pos` in large buffers" -- https://emacs.stackexchange.com/q/3821/2287 -- I learned that format-mode-line with the "%l" argument can be used to greatly enhance speed versus using count-lines. However, the window must be visible and some other limitations apply as discussed in the comments of the SE thread. After reading your comments (a few times to let it all sink in), I understand your concern about unnecessarily calculating the width each time that maybe_produce_line_number is called. In the example that was used at the outset of #28246, the width is calculated only once per command loop and stored in display_line_numbers_width. The following example function is a condensed version of what the mode-line code uses to determine the line number, which will be substantially faster than count-lines and/or line-number-at-pos. In addition, I found a little snippet on stackoverflow.com to get the length of an integer. Inasmuch as maybe_produce_line_number may be called more than one time each command loop, a different location needs to be found for internal_line_number_at_position -- so that it gets called just for each window per command loop -- and that value would need to be stored and subsequently used. I understand that internal_line_number_at_position may not be well written, but it is a working proof concept to demonstrate where I am coming from. /* Length of an Integer: https://stackoverflow.com/a/3068420/2112489 The log10, abs, and floor functions are provided by math.h */ TARGET_WIDTH = floor (log10 (abs (internal_line_number_at_position (XWINDOW (selected_window), ZV)))) + 1; static ptrdiff_t internal_line_number_at_position (struct window *w, ptrdiff_t pos) { Lisp_Object buf, value; struct buffer *b; struct buffer *old_buffer = NULL; buf = w->contents; CHECK_BUFFER (buf); b = XBUFFER (buf); ptrdiff_t line_number; if (b != current_buffer) { old_buffer = current_buffer; set_buffer_internal (b); } ptrdiff_t startpos, startpos_byte, line, linepos, linepos_byte, topline, nlines, height, junk, opoint; opoint = PT; if (opoint != pos) SET_PT (pos); startpos = marker_position (w->start); startpos_byte = marker_byte_position (w->start); /* If we decided that this buffer isn't suitable for line numbers, don't forget that too fast. */ if (MINI_WINDOW_P (w)) { line_number = 0; goto done; } if (w->base_line_pos == -1) { line_number = 0; goto done; } /* If the buffer is very big, don't waste time. */ if (INTEGERP (Vline_number_display_limit) && BUF_ZV (b) - BUF_BEGV (b) > XINT (Vline_number_display_limit)) { w->base_line_pos = 0; w->base_line_number = 0; line_number = 0; goto done; } if (w->base_line_number > 0 && w->base_line_pos > 0 && w->base_line_pos <= startpos) { line = w->base_line_number; linepos = w->base_line_pos; linepos_byte = buf_charpos_to_bytepos (b, linepos); } else { line = 1; linepos = BUF_BEGV (b); linepos_byte = BUF_BEGV_BYTE (b); } /* Count lines from base line to window start position. */ nlines = display_count_lines (linepos_byte, startpos_byte, startpos, &junk); topline = nlines + line; /* Determine a new base line, if the old one is too close or too far away, or if we did not have one. "Too close" means it's plausible a scroll-down would go back past it. */ if (startpos == BUF_BEGV (b)) { w->base_line_number = topline; w->base_line_pos = BUF_BEGV (b); } else if (nlines < height + 25 || nlines > height * 3 + 50 || linepos == BUF_BEGV (b)) { ptrdiff_t limit = BUF_BEGV (b); ptrdiff_t limit_byte = BUF_BEGV_BYTE (b); ptrdiff_t position; ptrdiff_t distance = (height * 2 + 30) * line_number_display_limit_width; if (startpos - distance > limit) { limit = startpos - distance; limit_byte = CHAR_TO_BYTE (limit); } nlines = display_count_lines (startpos_byte, limit_byte, - (height * 2 + 30), &position); /* If we couldn't find the lines we wanted within line_number_display_limit_width chars per line, give up on line numbers for this window. */ if (position == limit_byte && limit == startpos - distance) { w->base_line_pos = -1; w->base_line_number = 0; line_number = 0; goto done; } w->base_line_number = topline - nlines; w->base_line_pos = BYTE_TO_CHAR (position); } /* Now count lines from the start pos to point. */ nlines = display_count_lines (startpos_byte, PT_BYTE, PT, &junk); if (opoint != pos) SET_PT (opoint); line_number = topline + nlines; done: if (old_buffer) set_buffer_internal (old_buffer); return line_number; }