From a7754a250b74c17e1f63194e601f20fdb911dd7c Mon Sep 17 00:00:00 2001 From: Damien Cassou Date: Sun, 9 Apr 2017 12:46:57 +0200 Subject: [PATCH] Add absolute optional parameter to line-number-at-pos (Bug#26417) * lisp/simple.el (line-number-at-pos): Add a second optional argument 'absolute'. * test/list/simple-tests.el: Add tests for 'line-number-at-pos'. --- doc/lispref/positions.texi | 11 ++++++--- etc/NEWS | 7 ++++++ lisp/simple.el | 29 +++++++++++++--------- test/lisp/simple-tests.el | 49 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 82 insertions(+), 14 deletions(-) diff --git a/doc/lispref/positions.texi b/doc/lispref/positions.texi index 7c30fe977ca..9fd4bd8fe8e 100644 --- a/doc/lispref/positions.texi +++ b/doc/lispref/positions.texi @@ -432,11 +432,16 @@ prints a message reporting the number of lines, words, and characters in the buffer, or in the region if the region is active. @end deffn -@defun line-number-at-pos &optional pos +@defun line-number-at-pos &optional pos absolute @cindex line number This function returns the line number in the current buffer -corresponding to the buffer position @var{pos}. If @var{pos} is @code{nil} -or omitted, the current buffer position is used. +corresponding to the buffer position @var{pos}. If @var{pos} is +@code{nil} or omitted, the current buffer position is used. If +@var{absolute} is @code{nil}, the default, counting starts at +@code{(point-min)}, so the value refers to the contents of the +accessible portion of the (potentially narrowed) buffer. If +@var{absolute} is non-@code{nil}, ignore any narrowing and return +the absolute line number. @end defun @ignore diff --git a/etc/NEWS b/etc/NEWS index 39c88c60e77..2afed2d2534 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1228,6 +1228,13 @@ or its files before 'delete-directory' gets to them. *** New error type 'user-search-failed' like 'search-failed' but avoids debugger like 'user-error'. ++++ +** The function 'line-number-at-pos' now takes a second optional +argument 'absolute'. If this parameter is nil, the default, this +function keeps on returning the line number taking potential narrowing +into account. If this parameter is non-nil, the function ignores +narrowing and returns the absolute line number. + ** Changes in Frame- and Window- Handling +++ diff --git a/lisp/simple.el b/lisp/simple.el index a5565ab6e73..1db14a859d6 100644 --- a/lisp/simple.el +++ b/lisp/simple.el @@ -1270,18 +1270,25 @@ and the greater of them is not at the start of a line." done))) (- (buffer-size) (forward-line (buffer-size))))))) -(defun line-number-at-pos (&optional pos) - "Return (narrowed) buffer line number at position POS. +(defun line-number-at-pos (&optional pos absolute) + "Return buffer line number at position POS. If POS is nil, use current buffer location. -Counting starts at (point-min), so the value refers -to the contents of the accessible portion of the buffer." - (let ((opoint (or pos (point))) start) - (save-excursion - (goto-char (point-min)) - (setq start (point)) - (goto-char opoint) - (forward-line 0) - (1+ (count-lines start (point)))))) + +If ABSOLUTE is nil, the default, counting starts +at (point-min), so the value refers to the contents of the +accessible portion of the (potentially narrowed) buffer. If +ABSOLUTE is non-nil, ignore any narrowing and return the +absolute line number." + (save-restriction + (when absolute + (widen)) + (let ((opoint (or pos (point))) start) + (save-excursion + (goto-char (point-min)) + (setq start (point)) + (goto-char opoint) + (forward-line 0) + (1+ (count-lines start (point))))))) (defun what-cursor-position (&optional detail) "Print info on cursor position (on screen and within buffer). diff --git a/test/lisp/simple-tests.el b/test/lisp/simple-tests.el index 180dcc0a209..ad7aee1db17 100644 --- a/test/lisp/simple-tests.el +++ b/test/lisp/simple-tests.el @@ -448,5 +448,54 @@ See Bug#21722." (call-interactively #'eval-expression) (should (equal (current-message) "66 (#o102, #x42, ?B)")))))) +(ert-deftest line-number-at-pos-in-widen-buffer () + (let ((target-line 3)) + (with-temp-buffer + (insert "a\nb\nc\nd\n") + (goto-char (point-min)) + (forward-line (1- target-line)) + (should (equal (line-number-at-pos) target-line)) + (should (equal (line-number-at-pos nil t) target-line))))) + +(ert-deftest line-number-at-pos-in-narrow-buffer () + (let ((target-line 3)) + (with-temp-buffer + (insert "a\nb\nc\nd\n") + (goto-char (point-min)) + (forward-line (1- target-line)) + (narrow-to-region (line-beginning-position) (line-end-position)) + (should (equal (line-number-at-pos) 1)) + (should (equal (line-number-at-pos nil t) target-line))))) + +(ert-deftest line-number-at-pos-keeps-restriction () + (with-temp-buffer + (insert "a\nb\nc\nd\n") + (goto-char (point-min)) + (forward-line 2) + (narrow-to-region (line-beginning-position) (line-end-position)) + (should (equal (line-number-at-pos) 1)) + (line-number-at-pos nil t) + (should (equal (line-number-at-pos) 1)))) + +(ert-deftest line-number-at-pos-keeps-point () + (let (pos) + (with-temp-buffer + (insert "a\nb\nc\nd\n") + (goto-char (point-min)) + (forward-line 2) + (setq pos (point)) + (line-number-at-pos) + (line-number-at-pos nil t) + (should (equal pos (point)))))) + +(ert-deftest line-number-at-pos-when-passing-point () + (let (pos) + (with-temp-buffer + (insert "a\nb\nc\nd\n") + (should (equal (line-number-at-pos 1) 1)) + (should (equal (line-number-at-pos 3) 2)) + (should (equal (line-number-at-pos 5) 3)) + (should (equal (line-number-at-pos 7) 4))))) + (provide 'simple-test) ;;; simple-test.el ends here -- 2.39.2