summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarsten Dominik <carsten.dominik@gmail.com>2010-04-21 15:52:01 +0200
committerCarsten Dominik <carsten.dominik@gmail.com>2010-04-23 10:26:15 +0200
commit11baa7cf77245cc2a5f44dd55e034157896ad08d (patch)
treec53fe6962fa602f6589513e3126af567e667cfe7
parent9b6eeb4d2d7799fa35d4454f889f28199dea26e9 (diff)
downloadorg-mode-11baa7cf77245cc2a5f44dd55e034157896ad08d.tar.gz
Make M-left and M-right affect only the item, not its children
This behavior is now parallel to the treatment of outline nodes. This commit also introduces another change. When an outline node or a plain list item is folded by outline and contains hidden children, M-left/right will refuse to act on this item. You must either open the tree, or use the subtree commands M-S-left and M-S-right. Based on a patch by Matti De Craene, but significantly modified after a discussion involving Bernt Hansen and others.
-rw-r--r--doc/ChangeLog5
-rw-r--r--doc/org.texi5
-rwxr-xr-xlisp/ChangeLog17
-rw-r--r--lisp/org-list.el61
-rw-r--r--lisp/org.el40
5 files changed, 112 insertions, 16 deletions
diff --git a/doc/ChangeLog b/doc/ChangeLog
index 971454d..41ff00b 100644
--- a/doc/ChangeLog
+++ b/doc/ChangeLog
@@ -1,3 +1,8 @@
+2010-04-23 Carsten Dominik <carsten.dominik@gmail.com>
+
+ * org.texi (Plain lists): Document the commands to promote/demote
+ an item without affecting children.
+
2010-04-22 Carsten Dominik <carsten.dominik@gmail.com>
* org.texi (Sitemap): Document sitemap sorting.
diff --git a/doc/org.texi b/doc/org.texi
index fe443bf..69e23e0 100644
--- a/doc/org.texi
+++ b/doc/org.texi
@@ -1321,6 +1321,11 @@ similar effect.
Move the item including subitems up/down (swap with previous/next item
of same indentation). If the list is ordered, renumbering is
automatic.
+@kindex M-@key{left}
+@kindex M-@key{right}
+@item M-@key{left}
+@itemx M-@key{right}
+Decrease/increase the indentation of an item, leaving children alone.
@kindex M-S-@key{left}
@kindex M-S-@key{right}
@item M-S-@key{left}
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index 0b45639..a14a75d 100755
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,5 +1,22 @@
2010-04-23 Carsten Dominik <carsten.dominik@gmail.com>
+ * org.el (org-shiftmetaleft, org-shiftmetaright): Call the subtree
+ indentation commands.
+ (org-hidden-tree-error): New defsubst.
+ (org-metaleft, org-metaright): Check for hidden stuff and throw an
+ error.
+ (org-check-for-hidden): New function.
+
+ * org-list.el (org-item-re): New function.
+ (org-at-item-p): Use `org-item-re'.
+ (org-end-of-item-text-before-children): New function.
+ (org-outdent-item, org-indent-item): Arrange for leaving the
+ subtree alone.
+ (org-outdent-item-tree, org-indent-item-tree): New argument
+ NO-SUBTREE.
+ (org-indent-item-tree): Use `org-end-of-item-text-before-children'
+ to find the end for processing while ignoring the subtree.
+
* org-publish.el (org-publish-sitemap-sort-alphabetically)
(org-publish-sitemap-sort-folders)
(org-publish-sitemap-sort-ignore-case): New options.
diff --git a/lisp/org-list.el b/lisp/org-list.el
index 79c939c..212d172 100644
--- a/lisp/org-list.el
+++ b/lisp/org-list.el
@@ -197,17 +197,25 @@ list, obtained by prompting the user."
;;; Plain list items
+(defun org-item-re (&optional general)
+ "Return the correct regular expression for plain lists.
+If GENERAL is non-nil, return the general regexp independent of the value
+of `org-plain-list-ordered-item-terminator'."
+ (cond
+ ((or general (eq org-plain-list-ordered-item-terminator t))
+ "\\([ \t]*\\([-+]\\|\\([0-9]+[.)]\\)\\)\\|[ \t]+\\*\\)\\( \\|$\\)")
+ ((= org-plain-list-ordered-item-terminator ?.)
+ "\\([ \t]*\\([-+]\\|\\([0-9]+\\.\\)\\)\\|[ \t]+\\*\\)\\( \\|$\\)")
+ ((= org-plain-list-ordered-item-terminator ?\))
+ "\\([ \t]*\\([-+]\\|\\([0-9]+)\\)\\)\\|[ \t]+\\*\\)\\( \\|$\\)")
+ (t (error "Invalid value of `org-plain-list-ordered-item-terminator'"))))
+
(defun org-at-item-p ()
"Is point in a line starting a hand-formatted item?"
- (let ((llt org-plain-list-ordered-item-terminator))
- (save-excursion
- (goto-char (point-at-bol))
- (looking-at
- (cond
- ((eq llt t) "\\([ \t]*\\([-+]\\|\\([0-9]+[.)]\\)\\)\\|[ \t]+\\*\\)\\( \\|$\\)")
- ((= llt ?.) "\\([ \t]*\\([-+]\\|\\([0-9]+\\.\\)\\)\\|[ \t]+\\*\\)\\( \\|$\\)")
- ((= llt ?\)) "\\([ \t]*\\([-+]\\|\\([0-9]+)\\)\\)\\|[ \t]+\\*\\)\\( \\|$\\)")
- (t (error "Invalid value of `org-plain-list-ordered-item-terminator'")))))))
+
+ (save-excursion
+ (goto-char (point-at-bol))
+ (looking-at (org-item-re))))
(defun org-at-item-bullet-p ()
"Is point at the bullet of a plain list item?"
@@ -590,6 +598,16 @@ If the cursor is not in an item, throw an error."
(goto-char pos)
(error "Not in an item"))))
+(defun org-end-of-item-text-before-children ()
+ "Move to the end of the item text, stops before the first child if any.
+Assumes that the cursor is in the first ine of an item."
+ (goto-char
+ (min (save-excursion (org-end-of-item) (point))
+ (save-excursion
+ (goto-char (point-at-eol))
+ (re-search-forward (concat "^" (org-item-re t)) nil t)
+ (match-beginning 0)))))
+
(defun org-next-item ()
"Move to the beginning of the next item in the current plain list.
Error if not at a plain list, or if this is the last item in the list."
@@ -961,12 +979,24 @@ I.e. to the text after the last item."
(defvar org-last-indent-end-marker (make-marker))
(defun org-outdent-item (arg)
- "Outdent a local list item."
+ "Outdent a local list item, but not its children."
(interactive "p")
- (org-indent-item (- arg)))
+ (org-indent-item-tree (- arg) 'no-subtree))
(defun org-indent-item (arg)
- "Indent a local list item."
+ "Indent a local list item, but not its children."
+ (interactive "p")
+ (org-indent-item-tree arg 'no-subtree))
+
+(defun org-outdent-item-tree (arg &optional no-subtree)
+ "Outdent a local list item including its children.
+If NO-SUBTREE is set, only outdend the item itself, not its children."
+ (interactive "p")
+ (org-indent-item-tree (- arg) no-subtree))
+
+(defun org-indent-item-tree (arg &optional no-subtree)
+ "Indent a local list item including its children.
+If NO-SUBTREE is set, only indent the item itself, not its children."
(interactive "p")
(and (org-region-active-p) (org-cursor-to-region-beginning))
(unless (org-at-item-p)
@@ -975,12 +1005,15 @@ I.e. to the text after the last item."
(setq firstp (org-first-list-item-p))
(save-excursion
(setq end (and (org-region-active-p) (region-end)))
- (if (memq last-command '(org-shiftmetaright org-shiftmetaleft))
+ (if (and (memq last-command '(org-shiftmetaright org-shiftmetaleft))
+ (memq this-command '(org-shiftmetaright org-shiftmetaleft)))
(setq beg org-last-indent-begin-marker
end org-last-indent-end-marker)
(org-beginning-of-item)
(setq beg (move-marker org-last-indent-begin-marker (point)))
- (org-end-of-item)
+ (if no-subtree
+ (org-end-of-item-text-before-children)
+ (org-end-of-item))
(setq end (move-marker org-last-indent-end-marker (or end (point)))))
(goto-char beg)
(setq ind-bul (org-item-indent-positions)
diff --git a/lisp/org.el b/lisp/org.el
index 0eaf326..f21e5bb 100644
--- a/lisp/org.el
+++ b/lisp/org.el
@@ -15970,7 +15970,7 @@ See the individual commands for more information."
((run-hook-with-args-until-success 'org-shiftmetaleft-hook))
((org-at-table-p) (call-interactively 'org-table-delete-column))
((org-on-heading-p) (call-interactively 'org-promote-subtree))
- ((org-at-item-p) (call-interactively 'org-outdent-item))
+ ((org-at-item-p) (call-interactively 'org-outdent-item-tree))
(t (org-modifier-cursor-error))))
(defun org-shiftmetaright ()
@@ -15983,7 +15983,7 @@ See the individual commands for more information."
((run-hook-with-args-until-success 'org-shiftmetaright-hook))
((org-at-table-p) (call-interactively 'org-table-insert-column))
((org-on-heading-p) (call-interactively 'org-demote-subtree))
- ((org-at-item-p) (call-interactively 'org-indent-item))
+ ((org-at-item-p) (call-interactively 'org-indent-item-tree))
(t (org-modifier-cursor-error))))
(defun org-shiftmetaup (&optional arg)
@@ -16012,6 +16012,10 @@ commands for more information."
((org-at-item-p) (call-interactively 'org-move-item-down))
(t (org-modifier-cursor-error))))
+(defsubst org-hidden-tree-error ()
+ (error
+ "Hidden subtree, open with TAB or use subtree command M-S-<left>/<right>"))
+
(defun org-metaleft (&optional arg)
"Promote heading or move table column to left.
Calls `org-do-promote' or `org-table-move-column', depending on context.
@@ -16026,12 +16030,14 @@ See the individual commands for more information."
(save-excursion
(goto-char (region-beginning))
(org-on-heading-p))))
+ (when (org-check-for-hidden 'headlines) (org-hidden-tree-error))
(call-interactively 'org-do-promote))
((or (org-at-item-p)
(and (org-region-active-p)
(save-excursion
(goto-char (region-beginning))
(org-at-item-p))))
+ (when (org-check-for-hidden 'items) (org-hidden-tree-error))
(call-interactively 'org-outdent-item))
(t (call-interactively 'backward-word))))
@@ -16049,15 +16055,45 @@ See the individual commands for more information."
(save-excursion
(goto-char (region-beginning))
(org-on-heading-p))))
+ (when (org-check-for-hidden 'headlines) (org-hidden-tree-error))
(call-interactively 'org-do-demote))
((or (org-at-item-p)
(and (org-region-active-p)
(save-excursion
(goto-char (region-beginning))
(org-at-item-p))))
+ (when (org-check-for-hidden 'items) (org-hidden-tree-error))
(call-interactively 'org-indent-item))
(t (call-interactively 'forward-word))))
+(defun org-check-for-hidden (what)
+ "Check if there are hidden headlines/items in the current visual line.
+WHAT can be either `headlines' or `items'. If the current line is
+an outline or item heading and it has a folded subtree below it,
+this fucntion returns t, nil otherwise."
+ (let ((re (cond
+ ((eq what 'headlines) (concat "^" org-outline-regexp))
+ ((eq what 'items) (concat "^" (org-item-re t)))
+ (t (error "This should not happen"))))
+ beg end)
+ (save-excursion
+ (catch 'exit
+ (if (org-region-active-p)
+ (setq beg (region-beginning) end (region-end))
+ (setq beg (point-at-bol))
+ (beginning-of-line 2)
+ (while (and (not (eobp)) ;; this is like `next-line'
+ (get-char-property (1- (point)) 'invisible))
+ (beginning-of-line 2))
+ (setq end (point)))
+ (goto-char beg)
+ (goto-char (point-at-eol))
+ (setq end (max end (point)))
+ (while (re-search-forward re end t)
+ (if (get-char-property (match-beginning 0) 'invisible)
+ (throw 'exit t)))
+ nil))))
+
(defun org-metaup (&optional arg)
"Move subtree up or move table row up.
Calls `org-move-subtree-up' or `org-table-move-row' or