Browse Source

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.
Nicolas Goaziou 12 years ago
parent
commit
4d00c5bf4d
2 changed files with 121 additions and 6 deletions
  1. 64 6
      lisp/org.el
  2. 57 0
      testing/lisp/test-org.el

+ 64 - 6
lisp/org.el

@@ -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)

+ 57 - 0
testing/lisp/test-org.el

@@ -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