emacs-orgmode@gnu.org archives
 help / color / mirror / code / Atom feed
From: Nicolas Goaziou <mail@nicolasgoaziou.fr>
To: Marco Wahl <marcowahlsoft@gmail.com>
Cc: emacs-orgmode@gnu.org
Subject: Re: [RFC] Org Num library
Date: Sun, 03 Feb 2019 10:41:47 +0100	[thread overview]
Message-ID: <87pns9b44k.fsf@nicolasgoaziou.fr> (raw)
In-Reply-To: <84k1ikludt.fsf@gmail.com> (Marco Wahl's message of "Thu, 31 Jan 2019 16:27:42 +0100")

[-- Attachment #1: Type: text/plain, Size: 481 bytes --]

Hello,

Marco Wahl <marcowahlsoft@gmail.com> writes:

> Just one idea came to my mind.  What about adding an option to restart
> the numbering at 1 for the first heading in the case when narrowing is
> in effect?

AFAICT, detecting narrowing changes requires using `post-command-hook'.
Therefore an update to numbering, when such change happens, might get in
the way, e.g., if it slows down input.

Anyway, here is a POC, if anyone wants to test it.

Regards,

-- 
Nicolas Goaziou

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: Number headlinges according to buffer narrowing --]
[-- Type: text/x-diff, Size: 6737 bytes --]

From 1659484513fd4badb1fca867810a87756d1d46b5 Mon Sep 17 00:00:00 2001
From: Nicolas Goaziou <mail@nicolasgoaziou.fr>
Date: Sun, 3 Feb 2019 10:33:47 +0100
Subject: [PATCH] org-num: Add an option to start numbering according to
 narrowing

* lisp/org-num.el (org-num-visible-only):
(org-num--start): New variables.
(org-num--current-numbering): Change signature.
(org-num--number-region):
(org-num--update): Apply signature change.
(org-num--check-narrowing): New function.
(org-num-mode): Add, or remove, new function in `post-command-hook'.
---
 lisp/org-num.el | 80 ++++++++++++++++++++++++++++++++-----------------
 1 file changed, 53 insertions(+), 27 deletions(-)

diff --git a/lisp/org-num.el b/lisp/org-num.el
index f062526a0..de0a4ad48 100644
--- a/lisp/org-num.el
+++ b/lisp/org-num.el
@@ -135,6 +135,12 @@ control tag inheritance."
   :type 'boolean
   :safe #'booleanp)
 
+(defcustom org-num-visible-only nil
+  "Non-nil restricts numbering to the visible part of the buffer."
+  :group 'org-appearance
+  :type 'boolean
+  :safe #'booleanp)
+
 \f
 ;;; Internal Variables
 
@@ -154,6 +160,9 @@ inheritance of no-numbering attributes.")
 A numbering is a list of integers, in reverse order.  So numbering
 for headline \"1.2.3\" is (3 2 1).")
 
+(defvar-local org-num--start 1
+  "Buffer position where headlines start to be numbered.")
+
 (defvar-local org-num--missing-overlay nil
   "Buffer position signaling a headline without an overlay.")
 
@@ -255,16 +264,22 @@ otherwise."
              (org-entry-get (point) "UNNUMBERED")
              t))))
 
-(defun org-num--current-numbering (level skip)
+(defun org-num--current-numbering (pos level skip)
   "Return numbering for current headline.
-LEVEL is headline's level, and SKIP its skip value.  Return nil
-if headline should be skipped."
+
+POS is headline's beginning position, LEVEL its level, and SKIP
+its skip value.
+
+Numbering starts from `org-num--start' position.  Return nil if
+headline should not be numbered."
   (cond
    ;; Skipped by inheritance.
    ((and org-num--skip-level (> level org-num--skip-level)) nil)
    ;; Skipped by a non-nil skip value; set `org-num--skip-level'
    ;; to skip the whole sub-tree later on.
    (skip (setq org-num--skip-level level) nil)
+   ;; Skipped because it is before visible part of the buffer.
+   ((and org-num-visible-only (< pos org-num--start)) nil)
    (t
     (setq org-num--skip-level nil)
     ;; Compute next numbering, and update `org-num--numbering'.
@@ -296,10 +311,12 @@ first."
     (let ((regexp (org-num--headline-regexp))
           (new nil))
       (while (re-search-forward regexp end t)
-        (let* ((level (org-reduced-level
-                       (- (match-end 0) (match-beginning 0) 1)))
-               (skip (org-num--skip-value))
-               (numbering (org-num--current-numbering level skip)))
+        (let* ((pos (line-beginning-position))
+	       (level (org-reduced-level
+		       (- (match-end 0) (match-beginning 0) 1)))
+	       (skip (org-num--skip-value))
+	       (numbering
+		(org-num--current-numbering pos level skip)))
           ;; Apply numbering to current headline.  Store overlay for
           ;; the return value.
           (push (org-num--make-overlay numbering level skip)
@@ -324,26 +341,26 @@ missing overlays to that list."
        ;; last known overlay, make sure to parse the buffer between
        ;; these two overlays.
        ((org-num--valid-overlay-p overlay)
-        (let ((next (overlay-start overlay))
-              (last (and new-overlays (overlay-start (car new-overlays)))))
-          (cond
-           ((null org-num--missing-overlay))
-           ((> org-num--missing-overlay next))
-           ((or (null last) (> org-num--missing-overlay last))
-            (setq org-num--missing-overlay nil)
-            (setq new-overlays (nconc (org-num--number-region last next)
-                                      new-overlays)))
-           ;; If it is already after the last known overlay, reset it:
-           ;; some previous invalid overlay already triggered the
-           ;; necessary parsing.
-           (t
-            (setq org-num--missing-overlay nil))))
-        ;; Update OVERLAY's numbering.
-        (let* ((level (overlay-get overlay 'level))
-               (skip (overlay-get overlay 'skip))
-               (numbering (org-num--current-numbering level skip)))
-          (org-num--refresh-display overlay numbering)
-          (push overlay new-overlays)))
+        (let ((next (overlay-start overlay)))
+	  (let ((last (and new-overlays (overlay-start (car new-overlays)))))
+            (cond
+             ((null org-num--missing-overlay))
+             ((> org-num--missing-overlay next))
+             ((or (null last) (> org-num--missing-overlay last))
+              (setq org-num--missing-overlay nil)
+              (setq new-overlays (nconc (org-num--number-region last next)
+					new-overlays)))
+             ;; If it is already after the last known overlay, reset it:
+             ;; some previous invalid overlay already triggered the
+             ;; necessary parsing.
+             (t
+              (setq org-num--missing-overlay nil))))
+          ;; Update OVERLAY's numbering.
+          (let* ((level (overlay-get overlay 'level))
+		 (skip (overlay-get overlay 'skip))
+		 (numbering (org-num--current-numbering next level skip)))
+            (org-num--refresh-display overlay numbering)
+            (push overlay new-overlays))))
        ;; Invalid overlay.  It indicates that the buffer needs to be
        ;; parsed again between the two surrounding valid overlays or
        ;; buffer boundaries.
@@ -430,6 +447,13 @@ See this variable for the meaning of BEG and END."
     (when (or org-num--missing-overlay org-num--invalid-flag)
       (org-num--update))))
 
+(defun org-num--check-narrowing ()
+  "Check buffer narrowing; update numbering if necessary.
+This function is meant to be used in `post-command-hook'."
+  (when (and org-num-visible-only (/= org-num--start (point-min)))
+    (setq org-num--start (point-min))
+    (org-num--update)))
+
 \f
 ;;; Public Functions
 
@@ -450,10 +474,12 @@ NUMBERING is a list of numbers."
     (setq org-num--numbering nil)
     (setq org-num--overlays (nreverse (org-num--number-region nil nil)))
     (add-hook 'after-change-functions #'org-num--verify nil t)
+    (add-hook 'post-command-hook #'org-num--check-narrowing nil t)
     (add-hook 'change-major-mode-hook #'org-num--clear nil t))
    (t
     (org-num--clear)
     (remove-hook 'after-change-functions #'org-num--verify t)
+    (remove-hook 'post-command-hook #'org-num--check-narrowing t)
     (remove-hook 'change-major-mode-hook #'org-num--clear t))))
 
 
-- 
2.20.1


  reply	other threads:[~2019-02-03  9:41 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-11-20 18:22 [RFC] Org Num library Nicolas Goaziou
2018-11-20 22:29 ` Neil Jerram
2018-11-21  6:31 ` Eric S Fraga
2019-01-31 15:27 ` Marco Wahl
2019-02-03  9:41   ` Nicolas Goaziou [this message]
2019-02-04  6:35     ` stardiviner
2019-02-04 11:23       ` Marco Wahl
2019-02-04 19:36         ` Nicolas Goaziou

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.orgmode.org/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87pns9b44k.fsf@nicolasgoaziou.fr \
    --to=mail@nicolasgoaziou.fr \
    --cc=emacs-orgmode@gnu.org \
    --cc=marcowahlsoft@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).