From f117b5df4dc69a38a5568c5926c1e417a35314eb Mon Sep 17 00:00:00 2001 From: Lars Ingebrigtsen Date: Fri, 19 Aug 2022 15:22:29 +0200 Subject: [PATCH] Add new functions eol and bol * doc/lispref/positions.texi (Text Lines): Document them * lisp/emacs-lisp/shortdoc.el: Mention them, and also the buffer/line predicates. * src/editfns.c (bol): New function. (Fbol): New defun. (Fline_beginning_position): Use `bol'. (eol): New function. (Feol): New defun. (Fline_end_position): Use `eol'. --- doc/lispref/positions.texi | 10 ++++ etc/NEWS | 5 ++ lisp/emacs-lisp/shortdoc.el | 12 +++++ src/editfns.c | 98 +++++++++++++++++++++++++------------ 4 files changed, 93 insertions(+), 32 deletions(-) diff --git a/doc/lispref/positions.texi b/doc/lispref/positions.texi index 333c8e19a0e..53846ed2971 100644 --- a/doc/lispref/positions.texi +++ b/doc/lispref/positions.texi @@ -387,6 +387,16 @@ Return the position that @code{(end-of-line @var{count})} would move to. @end defun +@defun bol &optional count +Like @code{line-beginning-position}, but ignores fields (and is more +efficient). +@end defun + +@defun eol &optional count +Like @code{line-end-position}, but ignores fields (and is more +efficient). +@end defun + @deffn Command forward-line &optional count @cindex beginning of line This function moves point forward @var{count} lines, to the beginning of diff --git a/etc/NEWS b/etc/NEWS index 511687a1746..e5260e4e7e3 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -2587,6 +2587,11 @@ patcomp.el, pc-mode.el, pc-select.el, s-region.el, and sregex.el. * Lisp Changes in Emacs 29.1 ++++ +** New functions 'eol' and 'bol'. +These are like 'line-end-position' and 'line-beginning-position' +(respectively), but ignore fields (and are more efficient). + +++ ** New function 'compiled-function-p'. This returns non-nil if its argument is either a built-in, or a diff --git a/lisp/emacs-lisp/shortdoc.el b/lisp/emacs-lisp/shortdoc.el index d187af9ac83..acf294ede14 100644 --- a/lisp/emacs-lisp/shortdoc.el +++ b/lisp/emacs-lisp/shortdoc.el @@ -941,12 +941,24 @@ A FUNC form can have any number of `:no-eval' (or `:no-value'), :eval (point-min)) (point-max :eval (point-max)) + (eol + :eval (eol)) + (bol + :eval (bol)) + (bolp + :eval (bolp)) + (eolp + :eval (eolp)) (line-beginning-position :eval (line-beginning-position)) (line-end-position :eval (line-end-position)) (buffer-size :eval (buffer-size)) + (bobp + :eval (bobp)) + (eobp + :eval (eobp)) "Moving Around" (goto-char :no-eval (goto-char (point-max)) diff --git a/src/editfns.c b/src/editfns.c index 4fb82485abe..1e07b0b6557 100644 --- a/src/editfns.c +++ b/src/editfns.c @@ -709,9 +709,28 @@ Field boundaries are not noticed if `inhibit-field-text-motion' is non-nil. */) } -DEFUN ("line-beginning-position", - Fline_beginning_position, Sline_beginning_position, 0, 1, 0, - doc: /* Return the character position of the first character on the current line. +static ptrdiff_t +bol (Lisp_Object n, ptrdiff_t *out_count) +{ + ptrdiff_t bytepos, charpos, count; + + if (NILP (n)) + count = 0; + else if (FIXNUMP (n)) + count = clip_to_bounds (-BUF_BYTES_MAX, XFIXNUM (n) - 1, BUF_BYTES_MAX); + else + { + CHECK_INTEGER (n); + count = NILP (Fnatnump (n)) ? -BUF_BYTES_MAX : BUF_BYTES_MAX; + } + if (out_count) + *out_count = count; + scan_newline_from_point (count, &charpos, &bytepos); + return charpos; +} + +DEFUN ("bol", Fbol, Sbol, 0, 1, 0, + doc: /* Return the position of the first character on the current line. With optional argument N, scan forward N - 1 lines first. If the scan reaches the end of the buffer, return that position. @@ -720,6 +739,17 @@ position of the first character in logical order, i.e. the smallest character position on the logical line. See `vertical-motion' for movement by screen lines. +This function does not move point. Also see `line-beginning-position'. */) + (Lisp_Object n) +{ + return make_fixnum (bol (n, NULL)); +} + +DEFUN ("line-beginning-position", + Fline_beginning_position, Sline_beginning_position, 0, 1, 0, + doc: /* Return the position of the first character in the current line/field. +This function is like `bol' (which see), but respects fields. + This function constrains the returned position to the current field unless that position would be on a different line from the original, unconstrained result. If N is nil or 1, and a front-sticky field @@ -729,28 +759,33 @@ boundaries, bind `inhibit-field-text-motion' to t. This function does not move point. */) (Lisp_Object n) { - ptrdiff_t charpos, bytepos, count; + ptrdiff_t count, charpos = (bol (n, &count)); + /* Return END constrained to the current input field. */ + return Fconstrain_to_field (make_fixnum (charpos), make_fixnum (PT), + count != 0 ? Qt : Qnil, + Qt, Qnil); +} + +static ptrdiff_t +eol (Lisp_Object n) +{ + ptrdiff_t count; if (NILP (n)) - count = 0; + count = 1; else if (FIXNUMP (n)) - count = clip_to_bounds (-BUF_BYTES_MAX, XFIXNUM (n) - 1, BUF_BYTES_MAX); + count = clip_to_bounds (-BUF_BYTES_MAX, XFIXNUM (n), BUF_BYTES_MAX); else { CHECK_INTEGER (n); count = NILP (Fnatnump (n)) ? -BUF_BYTES_MAX : BUF_BYTES_MAX; } - - scan_newline_from_point (count, &charpos, &bytepos); - - /* Return END constrained to the current input field. */ - return Fconstrain_to_field (make_fixnum (charpos), make_fixnum (PT), - count != 0 ? Qt : Qnil, - Qt, Qnil); + return find_before_next_newline (PT, 0, count - (count <= 0), + NULL); } -DEFUN ("line-end-position", Fline_end_position, Sline_end_position, 0, 1, 0, - doc: /* Return the character position of the last character on the current line. +DEFUN ("eol", Feol, Seol, 0, 1, 0, + doc: /* Return the position of the last character on the current line. With argument N not nil or 1, move forward N - 1 lines first. If scan reaches end of buffer, return that position. @@ -758,6 +793,19 @@ This function ignores text display directionality; it returns the position of the last character in logical order, i.e. the largest character position on the line. +This function does not move point. Also see `line-end-position'. */) + (Lisp_Object n) +{ + return make_fixnum (eol (n)); +} + +DEFUN ("line-end-position", Fline_end_position, Sline_end_position, 0, 1, 0, + doc: /* Return the position of the last character in the current line/field. +With argument N not nil or 1, move forward N - 1 lines first. +If scan reaches end of buffer, return that position. + +This function is like `eol' (which see), but respects fields. + This function constrains the returned position to the current field unless that would be on a different line from the original, unconstrained result. If N is nil or 1, and a rear-sticky field ends @@ -767,24 +815,8 @@ boundaries bind `inhibit-field-text-motion' to t. This function does not move point. */) (Lisp_Object n) { - ptrdiff_t clipped_n; - ptrdiff_t end_pos; - ptrdiff_t orig = PT; - - if (NILP (n)) - clipped_n = 1; - else if (FIXNUMP (n)) - clipped_n = clip_to_bounds (-BUF_BYTES_MAX, XFIXNUM (n), BUF_BYTES_MAX); - else - { - CHECK_INTEGER (n); - clipped_n = NILP (Fnatnump (n)) ? -BUF_BYTES_MAX : BUF_BYTES_MAX; - } - end_pos = find_before_next_newline (orig, 0, clipped_n - (clipped_n <= 0), - NULL); - /* Return END_POS constrained to the current input field. */ - return Fconstrain_to_field (make_fixnum (end_pos), make_fixnum (orig), + return Fconstrain_to_field (make_fixnum (eol (n)), make_fixnum (PT), Qnil, Qt, Qnil); } @@ -4610,6 +4642,8 @@ with an optional argument LOCK non-nil. */); defsubr (&Sline_beginning_position); defsubr (&Sline_end_position); + defsubr (&Sbol); + defsubr (&Seol); defsubr (&Ssave_excursion); defsubr (&Ssave_current_buffer); -- 2.39.2