emacs-orgmode@gnu.org archives
 help / color / mirror / code / Atom feed
* [PATCH] make comment-dwim in source code blocks more DWIM-ish
@ 2013-10-28 21:40 Aaron Ecay
  2013-11-04 11:29 ` Bastien
  0 siblings, 1 reply; 3+ messages in thread
From: Aaron Ecay @ 2013-10-28 21:40 UTC (permalink / raw)
  To: emacs-orgmode

* lisp/org.el (org-insert-comment, org-comment-or-uncomment-region):
use the relevant language’s major mode comment function if called from
within a source block.

This patch makes it easier to (un)comment lines of babel source.  Now
M-; in a soucre code block should Just Work.

The modification to ‘org-insert-comment’ also fixes a bug, whereby the
function would eat blank lines after it.  The first block, where ! is
the point, would lead to the second instead of the third:

 #+name: orig
 #+begin_src org
 xxxxxxx
 !

 yyyyyy
 #+end_src

 #+name: bad
 #+begin_src org
 xxxxxxx
 #
 yyyyyy
 #+end_src

 #+name: desired
 #+begin_src org
 xxxxxxx
 #

 yyyyyy
 #+end_src

Also, the ‘org-comment-or-uncomment-region’ change results in an
undesirably move of the point after the comment is created.  This is
because ‘comment-region’ wraps the call to ‘comment-region-function’
in a ‘save-excursion’.  The org mode code deletes and reinserts the
whole babel block, which confuses save-excursion.  Org carefully puts
the point back in the proper place, but comment-region’s
save-excursion then substitutes its own erroneous placement.
---
 lisp/org.el | 126 +++++++++++++++++++++++++++++++++++-------------------------
 1 file changed, 74 insertions(+), 52 deletions(-)

diff --git a/lisp/org.el b/lisp/org.el
index 43172c8..4aeeada 100644
--- a/lisp/org.el
+++ b/lisp/org.el
@@ -22478,64 +22478,86 @@ non-nil."
 (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 "# "))
+  (if (org-in-src-block-p t)
+      (progn
+	(require 'ob-core)
+	(org-babel-do-in-edit-buffer
+	 (call-interactively #'comment-dwim)))
+    (beginning-of-line)
+    (if (looking-at "\\s-*$")
+	(delete-region (point) (point-at-eol))
+      (open-line 1))
+    (org-indent-line)
+    (insert "# ")))
 
 (defvar comment-empty-lines)		; From newcomment.el.
 (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-restriction
-    ;; Restrict region
-    (narrow-to-region (save-excursion (goto-char beg)
-				      (skip-chars-forward " \r\t\n" end)
-				      (line-beginning-position))
-		      (save-excursion (goto-char end)
-				      (skip-chars-backward " \r\t\n" beg)
-				      (line-end-position)))
-    (let ((uncommentp
-	   ;; UNCOMMENTP is non-nil when every non blank line between
-	   ;; BEG and END is a comment.
-	   (save-excursion
-	     (goto-char (point-min))
-	     (while (and (not (eobp))
-			 (let ((element (org-element-at-point)))
-			   (and (eq (org-element-type element) 'comment)
-				(goto-char (min (point-max)
-						(org-element-property
-						 :end element)))))))
-	     (eobp))))
-      (if uncommentp
-	  ;; Only blank lines and comments in region: uncomment it.
-	  (save-excursion
-	    (goto-char (point-min))
-	    (while (not (eobp))
-	      (when (looking-at "[ \t]*\\(#\\(?: \\|$\\)\\)")
-		(replace-match "" nil nil nil 1))
-	      (forward-line)))
-	;; Comment each line in region.
-	(let ((min-indent (point-max)))
-	  ;; First find the minimum indentation across all lines.
-	  (save-excursion
-	    (goto-char (point-min))
-	    (while (and (not (eobp)) (not (zerop min-indent)))
-	      (unless (looking-at "[ \t]*$")
-		(setq min-indent (min min-indent (current-indentation))))
-	      (forward-line)))
-	  ;; Then loop over all lines.
-	  (save-excursion
-	    (goto-char (point-min))
-	    (while (not (eobp))
-	      (unless (and (not comment-empty-lines) (looking-at "[ \t]*$"))
-		;; Don't get fooled by invisible text (e.g. link path)
-		;; when moving to column MIN-INDENT.
-		(let ((buffer-invisibility-spec nil))
-		  (org-move-to-column min-indent t))
-		(insert comment-start))
-	      (forward-line))))))))
+  (let* ((pt (point-marker))
+	 (head (and (org-in-src-block-p t)
+		    (require 'ob-core)
+		    (org-babel-where-is-src-block-head)))
+	 (foot (and head
+		    (save-excursion
+		      (goto-char head)
+		      (looking-at org-babel-src-block-regexp)
+		      (goto-char (match-end 0))
+		      (point-at-bol)))))
+    (if (and head foot
+	     (> beg head)
+	     (< end foot))
+	(org-babel-do-in-edit-buffer
+	 (call-interactively #'comment-dwim))
+      (save-restriction
+	;; Restrict region
+	(narrow-to-region (save-excursion (goto-char beg)
+					  (skip-chars-forward " \r\t\n" end)
+					  (line-beginning-position))
+			  (save-excursion (goto-char end)
+					  (skip-chars-backward " \r\t\n" beg)
+					  (line-end-position)))
+	(let ((uncommentp
+	       ;; UNCOMMENTP is non-nil when every non blank line between
+	       ;; BEG and END is a comment.
+	       (save-excursion
+		 (goto-char (point-min))
+		 (while (and (not (eobp))
+			     (let ((element (org-element-at-point)))
+			       (and (eq (org-element-type element) 'comment)
+				    (goto-char (min (point-max)
+						    (org-element-property
+						     :end element)))))))
+		 (eobp))))
+	  (if uncommentp
+	      ;; Only blank lines and comments in region: uncomment it.
+	      (save-excursion
+		(goto-char (point-min))
+		(while (not (eobp))
+		  (when (looking-at "[ \t]*\\(#\\(?: \\|$\\)\\)")
+		    (replace-match "" nil nil nil 1))
+		  (forward-line)))
+	    ;; Comment each line in region.
+	    (let ((min-indent (point-max)))
+	      ;; First find the minimum indentation across all lines.
+	      (save-excursion
+		(goto-char (point-min))
+		(while (and (not (eobp)) (not (zerop min-indent)))
+		  (unless (looking-at "[ \t]*$")
+		    (setq min-indent (min min-indent (current-indentation))))
+		  (forward-line)))
+	      ;; Then loop over all lines.
+	      (save-excursion
+		(goto-char (point-min))
+		(while (not (eobp))
+		  (unless (and (not comment-empty-lines) (looking-at "[ \t]*$"))
+		    ;; Don't get fooled by invisible text (e.g. link path)
+		    ;; when moving to column MIN-INDENT.
+		    (let ((buffer-invisibility-spec nil))
+		      (org-move-to-column min-indent t))
+		    (insert comment-start))
+		  (forward-line))))))))))
 
 
 ;;; Planning
-- 
1.8.4.1

^ permalink raw reply related	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2013-11-07  9:28 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-10-28 21:40 [PATCH] make comment-dwim in source code blocks more DWIM-ish Aaron Ecay
2013-11-04 11:29 ` Bastien
2013-11-07  9:28   ` Sebastien Vauban

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).