emacs-orgmode@gnu.org archives
 help / color / mirror / code / Atom feed
From: Nicolas <n.goaziou@gmail.com>
To: Linus Arver <linusarver@gmail.com>
Cc: emacs-orgmode@gnu.org, Bastien <bastien.guerry@wikimedia.fr>
Subject: Re: [PATCH] indentation for section headings vs bulleted lists
Date: Mon, 21 Feb 2011 00:26:30 +0100	[thread overview]
Message-ID: <874o7yz3rt.fsf_-_@gmail.com> (raw)
In-Reply-To: <20110220195133.GA28370@aether.rnxn4ps> (Linus Arver's message of "Sun, 20 Feb 2011 11:51:35 -0800")

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

Hello,

Here is an attempt to solve the problem at hand.

Linus, would you mind testing it and reporting back?


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: patch to integrate lists with org-indent-mode --]
[-- Type: text/x-patch, Size: 10938 bytes --]

From 77aad13b9a322032763148b17dd9cb3073bdbf23 Mon Sep 17 00:00:00 2001
From: Nicolas Goaziou <n.goaziou@gmail.com>
Date: Sun, 20 Feb 2011 13:44:00 +0100
Subject: [PATCH] Integrate lists with org-indent-mode and visual-line-mode

* lisp/org-list.el (org-list-insert-item): keep prefix properties when
  inserting a new item.
  (org-list-struct-apply-struct): keep prefix properties when
  modifying an item.
* lisp/org-indent.el (org-indent-mode): promoting and demoting should
  refresh subtree.
  (org-indent-add-properties): Add lists support. Refactor and comment
  code.
  (org-indent-refresh-subtree): No need to remove properties before
  refreshing. Also, make sure beg is at beginning of line.
  (org-indent-refresh-to, org-indent-refresh-section): Refactor. No
  need to remove properties before refreshing either.
---
 lisp/org-indent.el |  132 ++++++++++++++++++++++-----------------------------
 lisp/org-list.el   |   18 ++++++-
 2 files changed, 73 insertions(+), 77 deletions(-)

diff --git a/lisp/org-indent.el b/lisp/org-indent.el
index a177a6f..4411cd2 100644
--- a/lisp/org-indent.el
+++ b/lisp/org-indent.el
@@ -39,6 +39,7 @@
   (require 'cl))
 
 (defvar org-inlinetask-min-level)
+(declare-function org-in-item-p "org-list" ())
 (declare-function org-inlinetask-get-task-level "org-inlinetask" ())
 (declare-function org-inlinetask-in-task-p "org-inlinetask" ())
 
@@ -161,13 +162,12 @@ FIXME:  How to update when broken?"
     (add-to-list 'buffer-substring-filters
 		 'org-indent-remove-properties-from-string)
     (org-add-hook 'org-after-demote-entry-hook
-		  'org-indent-refresh-section nil 'local)
+		  'org-indent-refresh-subtree nil 'local)
     (org-add-hook 'org-after-promote-entry-hook
-		  'org-indent-refresh-section nil 'local)
+		  'org-indent-refresh-subtree nil 'local)
     (org-add-hook 'org-font-lock-hook
 		  'org-indent-refresh-to nil 'local)
-    (and font-lock-mode (org-restart-font-lock))
-    )
+    (and font-lock-mode (org-restart-font-lock)))
    (t
     ;; mode was turned off (or we refused to turn it on)
     (save-excursion
@@ -181,9 +181,9 @@ FIXME:  How to update when broken?"
 	      (delq 'org-indent-remove-properties-from-string
 		    buffer-substring-filters))
 	(remove-hook 'org-after-promote-entry-hook
-		     'org-indent-refresh-section 'local)
+		     'org-indent-refresh-subtree 'local)
 	(remove-hook 'org-after-demote-entry-hook
-		     'org-indent-refresh-section 'local)
+		     'org-indent-refresh-subtree 'local)
 	(and font-lock-mode (org-restart-font-lock))
 	(redraw-display))))))
 
@@ -222,82 +222,66 @@ useful to make it ever so slightly different."
 
 (defun org-indent-add-properties (beg end)
   "Add indentation properties between BEG and END.
-Assumes that BEG is at the beginning of a line."
+Assume BEG is at an headline, inline task, or at beginning of buffer."
   (let* ((inhibit-modification-hooks t)
 	 (inlinetaskp (featurep 'org-inlinetask))
-	 (get-real-level (lambda (pos lvl)
-			   (save-excursion
-			     (goto-char pos)
-			     (if (and inlinetaskp (org-inlinetask-in-task-p))
-				 (org-inlinetask-get-task-level)
-			       lvl))))
-	 (b beg)
-	 (e end)
-	 (level 0)
-	 (n 0)
-	 exit nstars)
+	 (m end))
     (with-silent-modifications
+      ;; 1. Starting from END, move to each headline and inline task,
+      ;;    and set prefixes point and the headline/inline task below
+      ;;    (saved in M). `line-prefix' property is only set on inner
+      ;;    part of that area, not on headlines.
       (save-excursion
+	(goto-char end)
+	(while (re-search-backward org-indent-outline-re beg 'move)
+	  (let ((pf (aref org-indent-strings
+			  (if (and inlinetaskp (org-inlinetask-at-task-p))
+			      (1+ (org-inlinetask-get-task-level))
+			    (1+ (org-current-level))))))
+	    (add-text-properties (point) m `(wrap-prefix ,pf))
+	    (add-text-properties (point-at-eol) m `(line-prefix ,pf))
+	    (setq m (point))))
+	;; Special case for area before first headline.
+	(when (bobp)
+	  (add-text-properties (point) m '(wrap-prefix nil line-prefix nil)))
+	;; 2. Set `wrap-prefix' in lists between BEG and END. For each
+	;;    item, length of prefix is the sum of length of
+	;;    `line-prefix', indentation and size of bullet.
 	(goto-char beg)
-	(while (not exit)
-	  (setq e end)
-	  (if (not (re-search-forward org-indent-outline-re nil t))
-	      (setq e (point-max) exit t)
-	    (setq e (match-beginning 0))
-	    (if (>= e end) (setq exit t))
-	    (unless (and inlinetaskp (org-inlinetask-in-task-p))
-	      (setq level (- (match-end 0) (match-beginning 0) 1)))
-	    (setq nstars (* (1- (funcall get-real-level e level))
-			    (1- org-indent-indentation-per-level)))
-	    (add-text-properties
-	     (point-at-bol) (point-at-eol)
-	     (list 'line-prefix
-		   (aref org-indent-stars nstars)
-		   'wrap-prefix
-		   (aref org-indent-strings
-			 (* (funcall get-real-level e level)
-			    org-indent-indentation-per-level)))))
-	  (when (> e b)
-	    (add-text-properties
-	     b  e (list 'line-prefix (aref org-indent-strings n)
-			'wrap-prefix (aref org-indent-strings n))))
-	  (setq b (1+ (point-at-eol))
-		n (* (funcall get-real-level b level)
-		     org-indent-indentation-per-level)))))))
+	(while (org-list-search-forward (org-item-beginning-re) end t)
+	  (let ((struct (org-list-struct)))
+	    (mapc (lambda (itm)
+		    (let ((pf (aref org-indent-strings
+				    (+ (length (get-text-property
+						(car itm) 'line-prefix))
+				       (nth 1 itm)
+				       (length (nth 2 itm))))))
+		      (add-text-properties (car itm) (1- (nth 6 itm))
+					   `(wrap-prefix ,pf))))
+		  struct)
+	    (goto-char (org-list-get-bottom-point struct))))))))
 
 (defvar org-inlinetask-min-level)
 (defun org-indent-refresh-section ()
-  "Refresh indentation properties in the current outline section.
-Point is assumed to be at the beginning of a headline."
+  "Refresh indentation properties between point and end next outline section."
   (interactive)
   (when org-indent-mode
-    (let (beg end)
-      (save-excursion
-	(when (ignore-errors (let ((outline-regexp (format "\\*\\{1,%s\\}[ \t]+"
-				(if (featurep 'org-inlinetask)
-				    (1- org-inlinetask-min-level)
-				  ""))))
-			       (org-back-to-heading)))
-	  (setq beg (point))
-	  (setq end (or (save-excursion (or (outline-next-heading) (point)))))
-	  (org-indent-remove-properties beg end)
-	  (org-indent-add-properties beg end))))))
+    (save-excursion
+      (org-with-limited-levels
+       (let ((beg (or (ignore-errors (org-back-to-heading))
+		      (point-min)))
+	     (end (progn (outline-next-heading) (point))))
+	 (org-indent-add-properties beg end))))))
 
 (defun org-indent-refresh-to (limit)
-  "Refresh indentation properties in the current outline section.
-Point is assumed to be at the beginning of a headline."
+  "Refresh indentation properties in the current outline section."
   (interactive)
   (when org-indent-mode
-    (let ((beg (point)) (end limit))
-      (save-excursion
-	(and (ignore-errors (let ((outline-regexp (format "\\*\\{1,%s\\}[ \t]+"
-				(if (featurep 'org-inlinetask)
-				    (1- org-inlinetask-min-level)
-				  ""))))
-			      (org-back-to-heading)))
-	     (setq beg (point))))
-      (org-indent-remove-properties beg end)
-      (org-indent-add-properties beg end)))
+    (save-excursion
+      (org-with-limited-levels
+       (let ((beg (or (and (ignore-errors (org-back-to-heading)) (point))
+		     (point-min))))
+	(org-indent-add-properties beg limit)))))
   (goto-char limit))
 
 (defun org-indent-refresh-subtree ()
@@ -306,15 +290,13 @@ Point is assumed to be at the beginning of a headline."
   (interactive)
   (when org-indent-mode
     (save-excursion
-      (let (beg end)
-	(setq beg (point))
-	(setq end (save-excursion (org-end-of-subtree t t)))
-	(org-indent-remove-properties beg end)
-	(org-indent-add-properties beg end)))))
+      (org-with-limited-levels
+       (let ((beg (point-at-bol))
+	    (end (save-excursion (org-end-of-subtree t t))))
+	 (org-indent-add-properties beg end))))))
 
 (defun org-indent-refresh-buffer ()
-  "Refresh indentation properties in the current outline subtree.
-Point is assumed to be at the beginning of a headline."
+  "Refresh indentation properties in the current outline subtree."
   (interactive)
   (when org-indent-mode
     (org-indent-mode -1)
diff --git a/lisp/org-list.el b/lisp/org-list.el
index 4700477..8ffe4d0 100644
--- a/lisp/org-list.el
+++ b/lisp/org-list.el
@@ -1156,9 +1156,12 @@ This function modifies STRUCT."
     ;;    functions, position of point with regards to item start
     ;;    (BEFOREP), blank lines number separating items (BLANK-NB),
     ;;    position of split (POS) if we're allowed to (SPLIT-LINE-P).
+    ;;    Also, save prefix properties for `org-indent-mode'.
     (let* ((item (goto-char (org-list-get-item-begin)))
 	   (item-end (org-list-get-item-end item struct))
 	   (item-end-no-blank (org-list-get-item-end-before-blank item struct))
+	   (wrap (get-text-property (point) 'wrap-prefix))
+	   (line (get-text-property (point) 'line-prefix))
 	   (beforep (and (looking-at org-list-full-item-re)
 			 (<= pos (match-end 0))))
 	   (split-line-p (org-get-alist-option org-M-RET-may-split-line 'item))
@@ -1194,6 +1197,9 @@ This function modifies STRUCT."
       (goto-char item)
       (org-indent-to-column ind)
       (insert body)
+      (when (and (featurep 'org-indent) org-indent-mode)
+	(add-text-properties item (point)
+			     `(line-prefix ,line wrap-prefix ,wrap)))
       (insert item-sep)
       ;; 5. Add new item to STRUCT.
       (mapc (lambda (e)
@@ -1628,7 +1634,9 @@ Initial position of cursor is restored after the changes."
 		    (new-bul (org-list-bullet-string
 			      (org-list-get-bullet item struct)))
 		    (old-bul (org-list-get-bullet item old-struct))
-		    (new-box (org-list-get-checkbox item struct)))
+		    (new-box (org-list-get-checkbox item struct))
+		    (wrap (get-text-property (point) 'wrap-prefix))
+		    (line (get-text-property (point) 'line-prefix)))
 	       (looking-at org-list-full-item-re)
 	       ;; a. Replace bullet
 	       (unless (equal old-bul new-bul)
@@ -1652,7 +1660,13 @@ Initial position of cursor is restored after the changes."
 	       (unless (= new-ind old-ind)
 		 (delete-region (goto-char (point-at-bol))
 				(progn (skip-chars-forward " \t") (point)))
-		 (indent-to new-ind)))))))
+		 (indent-to new-ind))
+	       ;; d. If `org-indent-mode' is on, keep prefix
+	       ;;    properties.
+	       (when (and (featurep 'org-indent) org-indent-mode)
+		 (add-text-properties
+		  (point-at-bol) (point-at-eol)
+		  `(line-prefix ,line wrap-prefix ,wrap))))))))
     ;; 1. First get list of items and position endings. We maintain
     ;;    two alists: ITM-SHIFT, determining indentation shift needed
     ;;    at item, and END-POS, a pseudo-alist where key is ending
-- 
1.7.4.1


[-- Attachment #3: Type: text/plain, Size: 23 bytes --]


Regards,

-- 
Nicolas

[-- Attachment #4: Type: text/plain, Size: 201 bytes --]

_______________________________________________
Emacs-orgmode mailing list
Please use `Reply All' to send replies to the list.
Emacs-orgmode@gnu.org
http://lists.gnu.org/mailman/listinfo/emacs-orgmode

  reply	other threads:[~2011-02-20 23:26 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-02-18  6:39 indentation for section headings vs bulleted lists Linus Arver
2011-02-18  8:52 ` Bastien
2011-02-19  2:34   ` Linus Arver
2011-02-19  9:35     ` Bastien
2011-02-20  7:22       ` Linus Arver
2011-02-20 12:19         ` Nicolas
2011-02-20 12:39           ` Carsten Dominik
2011-02-20 13:27             ` Nicolas
2011-02-20 19:51           ` Linus Arver
2011-02-20 23:26             ` Nicolas [this message]
2011-02-21  1:04               ` [PATCH] " Linus Arver
2011-02-21 10:59                 ` Giovanni Ridolfi
2011-02-21 17:32                   ` Nicolas
2011-02-18 18:18 ` Darlan Cavalcante Moreira
2011-02-19  2:46   ` Linus Arver

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=874o7yz3rt.fsf_-_@gmail.com \
    --to=n.goaziou@gmail.com \
    --cc=bastien.guerry@wikimedia.fr \
    --cc=emacs-orgmode@gnu.org \
    --cc=linusarver@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).