summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolas Goaziou <n.goaziou@gmail.com>2011-01-30 17:42:38 +0100
committerNicolas Goaziou <n.goaziou@gmail.com>2011-02-18 12:45:12 +0100
commitb7f6a916b347eb0e766d02b24d444f081c11fc94 (patch)
treeaeadb25453bc8b53f50c24847520f4c95334182a
parent69cc51fa43851dd6fcd856aea8e39805f46a26c1 (diff)
downloadorg-mode-b7f6a916b347eb0e766d02b24d444f081c11fc94.tar.gz
Fix toggling and cycling visibility for items and inline tasks
* lisp/org-inlinetask.el (org-inlinetask-at-task-p, org-inlinetask-toggle-visibility): new functions. * lisp/org-list.el (org-list-set-item-visibility): new function. * lisp/org.el (org-cycle, org-cycle-internal-local): separate lists and inline tasks from headlines. (org-outline-level): do not consider lists as headlines. Cycling visibility is using different tools.
-rw-r--r--lisp/org-inlinetask.el27
-rw-r--r--lisp/org-list.el24
-rw-r--r--lisp/org.el125
3 files changed, 122 insertions, 54 deletions
diff --git a/lisp/org-inlinetask.el b/lisp/org-inlinetask.el
index 483ce5f..31a5dbe 100644
--- a/lisp/org-inlinetask.el
+++ b/lisp/org-inlinetask.el
@@ -42,7 +42,9 @@
;;
;; Export commands do not treat these nodes as part of the sectioning
;; structure, but as a special inline text that is either removed, or
-;; formatted in some special way.
+;; formatted in some special way. This in handled by
+;; `org-inlinetask-export' and `org-inlinetask-export-templates'
+;; variables.
;;
;; Special fontification of inline tasks, so that they can be immediately
;; recognized. From the stars of the headline, only the first and the
@@ -197,6 +199,13 @@ The number of levels is controlled by `org-inlinetask-min-level'."
org-inlinetask-min-level)))
(format "^\\(\\*\\{%d,\\}\\)[ \t]+" nstars)))
+(defun org-inlinetask-at-task-p ()
+ "Return true if point is at beginning of an inline task."
+ (save-excursion
+ (beginning-of-line)
+ (and (looking-at (concat (org-inlinetask-outline-regexp) "\\(.*\\)"))
+ (not (string-match "^end[ \t]*$" (downcase (match-string 2)))))))
+
(defun org-inlinetask-in-task-p ()
"Return true if point is inside an inline task."
(save-excursion
@@ -335,6 +344,22 @@ Either remove headline and meta data, or do special formatting."
(add-text-properties (match-beginning 3) (match-end 3)
'(face shadow font-lock-fontified t)))))
+(defun org-inlinetask-toggle-visibility ()
+ "Toggle visibility of inline task at point."
+ (let ((end (save-excursion
+ (org-inlinetask-goto-end)
+ (if (bolp) (1- (point)) (point))))
+ (start (save-excursion
+ (org-inlinetask-goto-beginning)
+ (point-at-eol))))
+ (cond
+ ;; Nothing to show/hide.
+ ((= end start))
+ ;; Inlinetask was folded: expand it.
+ ((get-char-property (1+ start) 'invisible)
+ (outline-flag-region start end nil))
+ (t (outline-flag-region start end t)))))
+
(defun org-inlinetask-remove-END-maybe ()
"Remove an END line when present."
(when (looking-at (format "\\([ \t]*\n\\)*\\*\\{%d,\\}[ \t]+END[ \t]*$"
diff --git a/lisp/org-list.el b/lisp/org-list.el
index eec719d..a186c63 100644
--- a/lisp/org-list.el
+++ b/lisp/org-list.el
@@ -1774,6 +1774,30 @@ beginning of the item."
(goto-char item)
value))
+(defun org-list-set-item-visibility (item struct view)
+ "Set visibility of ITEM in STRUCT.
+
+Symbol VIEW determines visibility. Possible values are: `folded',
+`children' or `subtree'. See `org-cycle' for more information."
+ (cond
+ ((eq view 'folded)
+ (let ((item-end (org-list-get-item-end-before-blank item struct)))
+ ;; Hide from eol
+ (outline-flag-region (save-excursion (goto-char item) (point-at-eol))
+ item-end t)))
+ ((eq view 'children)
+ ;; First show everything.
+ (org-list-set-item-visibility item struct 'subtree)
+ ;; Then fold every child.
+ (let* ((parents (org-list-parents-alist struct))
+ (children (org-list-get-children item struct parents)))
+ (mapc (lambda (e)
+ (org-list-set-item-visibility e struct 'folded))
+ children)))
+ ((eq view 'subtree)
+ ;; Show everything
+ (let ((item-end (org-list-get-item-end item struct)))
+ (outline-flag-region item item-end nil)))))
;;; Interactive functions
diff --git a/lisp/org.el b/lisp/org.el
index 8ef3bf5..2dd5cb3 100644
--- a/lisp/org.el
+++ b/lisp/org.el
@@ -5455,14 +5455,10 @@ between words."
This function assumes that the cursor is at the beginning of a line matched
by `outline-regexp'. Otherwise it returns garbage.
If this is called at a normal headline, the level is the number of stars.
-Use `org-reduced-level' to remove the effect of `org-odd-levels'.
-For plain list items, if they are matched by `outline-regexp', this returns
-1000 plus the line indentation."
+Use `org-reduced-level' to remove the effect of `org-odd-levels'."
(save-excursion
(looking-at outline-regexp)
- (if (match-beginning 1)
- (+ (org-get-string-indentation (match-string 1)) 1000)
- (1- (- (match-end 0) (match-beginning 0))))))
+ (1- (- (match-end 0) (match-beginning 0)))))
(defvar org-font-lock-keywords nil)
@@ -5839,14 +5835,9 @@ in special contexts.
(and limit-level (1- (* limit-level 2)))
limit-level)))
(outline-regexp
- (cond
- ((not (org-mode-p)) outline-regexp)
- ((or (eq org-cycle-include-plain-lists 'integrate)
- (and org-cycle-include-plain-lists (org-at-item-p)))
- (concat "\\(?:\\*"
- (if nstars (format "\\{1,%d\\}" nstars) "+")
- " \\|\\([ \t]*\\)\\([-+*]\\|[0-9]+[.)]\\) \\)"))
- (t (concat "\\*" (if nstars (format "\\{1,%d\\} " nstars) "+ ")))))
+ (if (not (org-mode-p))
+ outline-regexp
+ (concat "\\*" (if nstars (format "\\{1,%d\\} " nstars) "+ "))))
(bob-special (and org-cycle-global-at-bob (not arg) (bobp)
(not (looking-at outline-regexp))))
(org-cycle-hook
@@ -5871,8 +5862,8 @@ in special contexts.
(show-all)
(message "Entire buffer visible, including drawers"))
+ ;; Table: enter it or move to the next field.
((org-at-table-p 'any)
- ;; Enter the table or move to the next field in the table
(if (org-at-table.el-p)
(message "Use C-c ' to edit table.el tables")
(if arg (org-table-edit-field t)
@@ -5882,31 +5873,39 @@ in special contexts.
((run-hook-with-args-until-success
'org-tab-after-check-for-table-hook))
- ((eq arg t) ;; Global cycling
- (org-cycle-internal-global))
+ ;; Global cycling: delegate to `org-cycle-internal-global'.
+ ((eq arg t) (org-cycle-internal-global))
+ ;; Drawers: delegate to `org-flag-drawer'.
((and org-drawers org-drawer-regexp
(save-excursion
(beginning-of-line 1)
(looking-at org-drawer-regexp)))
- ;; Toggle block visibility
- (org-flag-drawer
+ (org-flag-drawer ; toggle block visibility
(not (get-char-property (match-end 0) 'invisible))))
+ ;; Show-subtree, ARG levels up from here.
((integerp arg)
- ;; Show-subtree, ARG levels up from here.
(save-excursion
(org-back-to-heading)
(outline-up-heading (if (< arg 0) (- arg)
(- (funcall outline-level) arg)))
(org-show-subtree)))
- ((and (save-excursion (beginning-of-line 1) (looking-at outline-regexp))
+ ;; Inline task: delegate to `org-inlinetask-toggle-visibility'.
+ ((and (featurep 'org-inlinetask)
+ (org-inlinetask-at-task-p)
(or (bolp) (not (eq org-cycle-emulate-tab 'exc-hl-bol))))
+ (org-inlinetask-toggle-visibility))
+ ;; At an item/headline: delegate to `org-cycle-internal-local'.
+ ((and (or (and org-cycle-include-plain-lists (org-at-item-p))
+ (save-excursion (beginning-of-line 1)
+ (looking-at outline-regexp)))
+ (or (bolp) (not (eq org-cycle-emulate-tab 'exc-hl-bol))))
(org-cycle-internal-local))
- ;; TAB emulation and template completion
+ ;; From there: TAB emulation and template completion.
(buffer-read-only (org-back-to-heading))
((run-hook-with-args-until-success
@@ -5971,38 +5970,44 @@ in special contexts.
(defun org-cycle-internal-local ()
"Do the local cycling action."
- (let ((goal-column 0) eoh eol eos level has-children children-skipped)
- ;; First, some boundaries
+ (let ((goal-column 0) eoh eol eos has-children children-skipped struct)
+ ;; First, determine end of headline (EOH), end of subtree or item
+ ;; (EOS), and if item or heading has children (HAS-CHILDREN).
(save-excursion
- (org-back-to-heading)
- (setq level (funcall outline-level))
- (save-excursion
- (beginning-of-line 2)
- (if (or (featurep 'xemacs) (<= emacs-major-version 21))
- ; XEmacs does not have `next-single-char-property-change'
- ; I'm not sure about Emacs 21.
- (while (and (not (eobp)) ;; this is like `next-line'
- (get-char-property (1- (point)) 'invisible))
- (beginning-of-line 2))
+ (if (org-at-item-p)
+ (progn
+ (beginning-of-line)
+ (setq struct (org-list-struct))
+ (setq eoh (point-at-eol))
+ (setq eos (org-list-get-item-end-before-blank (point) struct))
+ (setq has-children (org-list-has-child-p (point) struct)))
+ (org-back-to-heading)
+ (setq eoh (save-excursion (outline-end-of-heading) (point)))
+ (setq eos (save-excursion
+ (org-end-of-subtree t)
+ (unless (eobp)
+ (skip-chars-forward " \t\n"))
+ (if (eobp) (point) (1- (point)))))
+ (setq has-children
+ (or (save-excursion
+ (let ((level (funcall outline-level)))
+ (outline-next-heading)
+ (and (org-at-heading-p t)
+ (> (funcall outline-level) level))))
+ (save-excursion
+ (org-list-search-forward (org-item-beginning-re) eos t)))))
+ ;; Determine end invisible part of buffer (EOL)
+ (beginning-of-line 2)
+ ;; XEmacs doesn't have `next-single-char-property-change'
+ (if (featurep 'xemacs)
(while (and (not (eobp)) ;; this is like `next-line'
(get-char-property (1- (point)) 'invisible))
- (goto-char (next-single-char-property-change (point) 'invisible))
- (and (eolp) (beginning-of-line 2))))
- (setq eol (point)))
- (outline-end-of-heading) (setq eoh (point))
- (save-excursion
- (outline-next-heading)
- (setq has-children (and (org-at-heading-p t)
- (> (funcall outline-level) level))))
- ;; if we're in a list, org-end-of-subtree is in fact org-end-of-item.
- (if (org-at-item-p)
- (setq eos (if (and (org-end-of-item) (bolp))
- (1- (point))
- (point)))
- (org-end-of-subtree t)
- (unless (eobp)
- (skip-chars-forward " \t\n"))
- (setq eos (if (eobp) (point) (1- (point))))))
+ (beginning-of-line 2))
+ (while (and (not (eobp)) ;; this is like `next-line'
+ (get-char-property (1- (point)) 'invisible))
+ (goto-char (next-single-char-property-change (point) 'invisible))
+ (and (eolp) (beginning-of-line 2))))
+ (setq eol (point)))
;; Find out what to do next and set `this-command'
(cond
((= eos eoh)
@@ -6021,8 +6026,22 @@ in special contexts.
org-cycle-skip-children-state-if-no-children))))
;; Entire subtree is hidden in one line: children view
(run-hook-with-args 'org-pre-cycle-hook 'children)
- (org-show-entry)
- (show-children)
+ (if (org-at-item-p)
+ (org-list-set-item-visibility (point-at-bol) struct 'children)
+ (org-show-entry)
+ (show-children)
+ ;; Fold every list in subtree to top-level items.
+ (when (eq org-cycle-include-plain-lists 'integrate)
+ (save-excursion
+ (org-back-to-heading)
+ (while (org-list-search-forward (org-item-beginning-re) eos t)
+ (beginning-of-line 1)
+ (let* ((struct (org-list-struct))
+ (prevs (org-list-prevs-alist struct))
+ (end (org-list-get-bottom-point struct)))
+ (mapc (lambda (e) (org-list-set-item-visibility e struct 'folded))
+ (org-list-get-all-items (point) struct prevs))
+ (goto-char end))))))
(message "CHILDREN")
(save-excursion
(goto-char eos)