emacs-orgmode
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Orgmode] Re: [PATCH] indentation for section headings vs bulleted lists


From: Nicolas
Subject: [Orgmode] Re: [PATCH] indentation for section headings vs bulleted lists
Date: Mon, 21 Feb 2011 00:26:30 +0100

Hello,

Here is an attempt to solve the problem at hand.

Linus, would you mind testing it and reporting back?

>From 77aad13b9a322032763148b17dd9cb3073bdbf23 Mon Sep 17 00:00:00 2001
From: Nicolas Goaziou <address@hidden>
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

Regards,

-- 
Nicolas

reply via email to

[Prev in Thread] Current Thread [Next in Thread]