Complete handling of comment syntax

* lisp/org.el (org-mode): Set comments related variables.
(org-insert-comment, org-comment-or-uncomment-region): New functions.
* testing/lisp/test-org.el: Add test.
This commit is contained in:
Nicolas Goaziou 2012-07-31 13:21:38 +02:00
parent 0202adb1c0
commit 4d00c5bf4d
2 changed files with 121 additions and 6 deletions

View File

@ -5060,6 +5060,13 @@ The following commands are available:
(org-set-local 'indent-line-function 'org-indent-line)
(org-set-local 'indent-region-function 'org-indent-region)
(org-update-radio-target-regexp)
;; Comments
(org-set-local 'comment-use-syntax nil)
(org-set-local 'comment-start "#+")
(org-set-local 'comment-start-skip "\\(?:^#\\|#\\+\\)\\(?: \\|$\\)")
(org-set-local 'comment-insert-comment-function 'org-insert-comment)
(org-set-local 'comment-region-function 'org-comment-or-uncomment-region)
(org-set-local 'uncomment-region-function 'org-comment-or-uncomment-region)
;; Beginning/end of defun
(org-set-local 'beginning-of-defun-function 'org-beginning-of-defun)
(org-set-local 'end-of-defun-function 'org-end-of-defun)
@ -20616,8 +20623,7 @@ If point is in an inline task, mark that task instead."
(push-mark (point) nil t)
(goto-char beg)))
;;; Paragraph filling stuff.
;; We want this to be just right, so use the full arsenal.
;;; Indentation
(defun org-indent-line ()
"Indent line depending on context."
@ -20785,12 +20791,16 @@ If point is in an inline task, mark that task instead."
(t (call-interactively 'org-indent-line)))
(move-beginning-of-line 2)))))
;;; Filling
;; We use our own fill-paragraph and auto-fill functions. These
;; functions will shadow `fill-prefix' (computed internally with
;; `org-fill-context-prefix') and pass through to
;; `fill-region-as-paragraph' and `do-auto-fill' as appropriate.
(defun org-set-autofill-regexps ()
(interactive)
;; We use our own fill-paragraph and auto-fill functions. These
;; functions will shadow `fill-prefix' (computed internally with
;; `org-fill-context-prefix') and pass through to
;; `fill-region-as-paragraph' and `do-auto-fill' as appropriate.
(org-set-local 'fill-paragraph-function 'org-fill-paragraph)
;; Prevent auto-fill from inserting unwanted new items.
(when (boundp 'fill-nobreak-predicate)
@ -20964,6 +20974,54 @@ width for filling."
(let ((fill-prefix (org-fill-context-prefix (point))))
(when fill-prefix (do-auto-fill))))))
;;; Comments
;; Since difference between comments and keywords is subtle, we cannot
;; trust `comment-only-p' when applying `comment-dwim'. Hence, both
;; `comment-region-function' and `uncomment-region-function' point to
;; `org-comment-or-uncomment-region', which can tell when region only
;; contains comments or not.
(defun org-insert-comment ()
"Insert an empty comment above current line.
If the line is empty, insert comment at its beginning."
(beginning-of-line)
(if (looking-at "\\s-*$") (replace-match "") (open-line 1))
(org-indent-line)
(insert "#+ "))
(defun org-comment-or-uncomment-region (beg end &rest ignore)
"Comment or uncomment each non-blank line in the region.
Uncomment each non-blank line between BEG and END if it only
contains commented lines. Otherwise, comment them."
(save-excursion
(goto-char beg)
(skip-chars-forward " \r\t\n" end)
(beginning-of-line)
(let ((uncommentp
;; UNCOMMENTP is non-nil when every non blank line between
;; BEG and END is a comment.
(save-excursion
(while (progn (and (not (eobp))
(let ((element (org-element-at-point)))
(and (eq (org-element-type element) 'comment)
(goto-char (org-element-property
:end element)))))))
(>= (point) end)))
;; Remove or adding comment markers is going to change end
;; position so make it a marker.
(end (copy-marker end)))
(while (< (point) end)
(unless (looking-at "\\s-*$")
(if (not uncommentp) (progn (back-to-indentation) (insert "#+ "))
;; Only comments and blank lines in region: uncomment it.
(looking-at "[ \t]*\\(#\\+? ?\\)")
(replace-match "" nil nil nil 1)))
(forward-line))
(set-marker end nil))))
;;; Other stuff.
(defun org-toggle-fixed-width-section (arg)

View File

@ -261,6 +261,63 @@ http://article.gmane.org/gmane.emacs.orgmode/21459/"
(buffer-string))))))
;;; Comments
(ert-deftest test-org/comment-dwim ()
"Test `comment-dwim' behaviour in an Org buffer."
;; No region selected, no comment on current line and line not
;; empty: insert comment on line above.
(should
(equal "#+ \nComment"
(org-test-with-temp-text "Comment"
(progn (call-interactively 'comment-dwim)
(buffer-string)))))
;; No region selected, no comment on current line and line empty:
;; insert comment on this line.
(should
(equal "#+ \nParagraph"
(org-test-with-temp-text "\nParagraph"
(progn (call-interactively 'comment-dwim)
(buffer-string)))))
;; No region selected, and a comment on this line: indent it.
(should
(equal "* Headline\n #+ Comment"
(org-test-with-temp-text "* Headline\n#+ Comment"
(progn (forward-line)
(let ((org-adapt-indentation t))
(call-interactively 'comment-dwim))
(buffer-string)))))
;; Also recognize single # at column 0 as comments.
(should
(equal "# Comment"
(org-test-with-temp-text "# Comment"
(progn (forward-line)
(call-interactively 'comment-dwim)
(buffer-string)))))
;; Region selected and only comments and blank lines within it:
;; un-comment all commented lines.
(should
(equal "Comment 1\n\nComment 2"
(org-test-with-temp-text "#+ Comment 1\n\n#+ Comment 2"
(progn
(transient-mark-mode 1)
(push-mark (point) t t)
(goto-char (point-max))
(call-interactively 'comment-dwim)
(buffer-string)))))
;; Region selected without comments: comment all non-blank lines.
(should
(equal "#+ Comment 1\n\n#+ Comment 2"
(org-test-with-temp-text "Comment 1\n\nComment 2"
(progn
(transient-mark-mode 1)
(push-mark (point) t t)
(goto-char (point-max))
(call-interactively 'comment-dwim)
(buffer-string))))))
(provide 'test-org)
;;; test-org.el ends here