From 90c7eda317d3633b3c59ac45ac926f5b4a6fe363 Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Fri, 17 Sep 2010 20:42:44 +0000 Subject: Revive `paredit-semicolon', with better behaviour. Ignore-this: 2ebf74083c75ef978f8f4e15070002e3 darcs-hash:20100917204244-00fcc-b698a185d46aaf792f065e98e0b1509eaee4f0a3 --- paredit.el | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) (limited to 'paredit.el') diff --git a/paredit.el b/paredit.el index 848312d..4fa5c7d 100644 --- a/paredit.el +++ b/paredit.el @@ -323,6 +323,15 @@ Paredit behaves badly if parentheses are imbalanced, so exercise "(string #\\x|)") ("\"foo|bar\"\n ; Escaping character... (\")" "\"foo\\\"|bar\"")) + (";" paredit-semicolon + ("|(frob grovel)" + ";|(frob grovel)") + ("(frob |grovel)" + "(frob ;grovel\n)") + ("(frob |grovel (bloit\n zargh))" + "(frob ;|grovel\n (bloit\n zargh))") + ("(frob grovel) |" + "(frob grovel) ;|")) ("M-;" paredit-comment-dwim ("(foo |bar) ; baz" "(foo bar) ; |baz") @@ -1012,6 +1021,64 @@ If the point is in a string or a comment, fill the paragraph instead, ;;;; Comment Insertion +(defun paredit-semicolon (&optional n) + "Insert a semicolon. +With a prefix argument N, insert N semicolons. +If in a string, do just that and nothing else. +If in a character literal, move to the beginning of the character + literal before inserting the semicolon. +If the enclosing list ends on the line after the point, break the line + after the last S-expression following the point. +If a list begins on the line after the point but ends on a different + line, break the line after the last S-expression following the point + before the list." + (interactive "p") + (if (or (paredit-in-string-p) (paredit-in-comment-p)) + (insert (make-string (or n 1) ?\; )) + (if (paredit-in-char-p) + (backward-char 2)) + (let ((line-break-point (paredit-semicolon-find-line-break-point))) + (if line-break-point + (paredit-semicolon-with-line-break line-break-point (or n 1)) + (insert (make-string (or n 1) ?\; )))))) + +(defun paredit-semicolon-find-line-break-point () + (let ((line-break-point nil) + (eol (point-at-eol))) + (and (save-excursion + (paredit-handle-sexp-errors + (progn + (while + (progn + (setq line-break-point (point)) + (forward-sexp) + (and (eq eol (point-at-eol)) + (not (eobp))))) + (backward-sexp) + (eq eol (point-at-eol))) + ;; If we hit the end of an expression, but the closing + ;; delimiter is on another line, don't break the line. + (save-excursion + (paredit-skip-whitespace t (point-at-eol)) + (not (or (eolp) (eq (char-after) ?\; )))))) + line-break-point))) + +(defun paredit-semicolon-with-line-break (line-break-point n) + (let ((line-break-marker (make-marker))) + (set-marker line-break-marker line-break-point) + (set-marker-insertion-type line-break-marker t) + (insert (make-string (or n 1) ?\; )) + (save-excursion + (goto-char line-break-marker) + (set-marker line-break-marker nil) + (newline) + (lisp-indent-line) + ;; This step is redundant if we are inside a list, but even if we + ;; are at the top level, we want at least to indent whatever we + ;; bumped off the line. + (paredit-ignore-sexp-errors (indent-sexp)) + (paredit-indent-sexps)))) + ;;; This is all a horrible, horrible hack, primarily for GNU Emacs 21, ;;; in which there is no `comment-or-uncomment-region'. -- cgit v1.2.1