This is the enhancement to `org-narrow-to-subtree' that I suggested back in May 
[1].

It allows you to choose what level subtree to narrow to.  There are two ways to 
specify the subtree: use repeated C-u's to select "upward" from the current 
subtree, or use a direct numeric prefix arg to specify the subtree "downward" 
from level 1.  (This is a somewhat unusual prefix argument usage, but it's 
useful to be able to choose from either direction, and the convenience of using 
C-u to select upward is quite enormous -- I expect it to be the common case, 
and it's pretty much the only way I use the feature.)

The prefix arg is optional, of course: if you don't pass it, then 
`org-narrow-to-subtree' behaves the same way it has always behaved.

Best regards,
-Karl

[1] https://lists.gnu.org/archive/html/emacs-orgmode/2019-05/msg00225.html

>From bbeca3c5444646685085c134b10f4883812068a0 Mon Sep 17 00:00:00 2001
From: Karl Fogel <kfo...@red-bean.com>
Date: Sat, 30 Nov 2019 01:33:15 -0600
Subject: [PATCH] Use prefix arg to narrow to a specific subtree

* lisp/org.el (org-narrow-to-subtree): Take a prefix arg and use
  it to choose which subtree to narrow to.  See thread for context:

  https://lists.gnu.org/archive/html/emacs-orgmode/2019-05/msg00225.html
  From: Karl Fogel
  To: Org Mode
  Subject: Re: [PROPOSAL] Use prefix arg to control scope \
           of org-narrow-to-subtree.
  Date: Fri, 31 May 2019 02:33:03 -0500
  Message-ID: <87y32ncc40....@red-bean.com>
---
 lisp/org.el | 41 ++++++++++++++++++++++++++++++++++++++---
 1 file changed, 38 insertions(+), 3 deletions(-)

diff --git a/lisp/org.el b/lisp/org.el
index 90f222c8b..9b16c59e6 100644
--- a/lisp/org.el
+++ b/lisp/org.el
@@ -7743,11 +7743,46 @@ If yes, remember the marker and the distance to BEG."
     (move-marker (car x) (+ beg (cdr x))))
   (setq org-markers-to-move nil))
 
-(defun org-narrow-to-subtree ()
-  "Narrow buffer to the current subtree."
-  (interactive)
+(defun org-narrow-to-subtree (&optional steps)
+  "Narrow buffer to current subtree or to one specified by prefix arg STEPS.
+
+Interactively, use the prefix argument in one of two ways to
+narrow to a specific subtree: either give one or more C-u's to
+specify a subtree that many levels upward from the current
+subtree (that is, go up as many levels as the number of C-u's
+given -- each C-u counts for one level), or give a strictly
+numeric argument to narrow to the subtree that is that many
+levels downward from the current top level (level 1) subtree.
+
+From Lisp, if you want the C-u (upward) behavior, pass STEPS as a
+list with the desired number as its sole element.  Otherwise,
+pass STEPS as a number to get the other (downward) behavior.
+
+If STEPS would specify a subtree higher than the current level 1
+subtree, then just narrow to that level 1 subtree (in other
+words, you can use \"a lot of\" C-u's to narrow quickly to the
+current top subtree).  If STEPS would specify a subtree deeper
+than the current subtree, just narrow to the current subtree."
+  (interactive "P")
   (save-excursion
     (save-match-data
+      (widen)
+      (if steps
+	  (if (listp steps)
+	      (progn
+		(setq steps (car steps))
+		(when (< steps 0)
+		  (error "Argument cannot be negative"))
+		(setq steps (round (log steps 4))))
+	    (when (< steps 0) ; awkward duplication, but hard to avoid
+	      (error "Argument cannot be negative"))
+	    (let ((cur-level (org-outline-level)))
+	      (setq steps (max (- cur-level steps) 0))))
+	(setq steps 0))
+      (while (> steps 0)
+	(if (org-up-heading-safe)
+	    (setq steps (1- steps))
+	  (setq steps 0)))
       (org-with-limited-levels
        (narrow-to-region
 	(progn (org-back-to-heading t) (point))
-- 
2.24.0

Reply via email to