branch: elpa/smartparens
commit 0fe32ac56da6d8e725850e9c438904db24be0bb9
Author: Matus Goljer <matus.gol...@gmail.com>
Commit: Matus Goljer <matus.gol...@gmail.com>

    feat(lisp): insert space before opening paren after slurping
    
    This prevents some weirdly formatted code like (foo)(bar)
    becomnig (foo(bar)) instead of (foo (bar))
    
    Fixes #781
---
 smartparens-config.el          | 12 ++++++++++
 smartparens.el                 | 12 +++++++---
 test/smartparens-elisp-test.el | 51 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 72 insertions(+), 3 deletions(-)

diff --git a/smartparens-config.el b/smartparens-config.el
index c639e5e998..8709c52085 100644
--- a/smartparens-config.el
+++ b/smartparens-config.el
@@ -70,9 +70,21 @@ ID, ACTION, CONTEXT."
               ;; do not consider punctuation
               (not (looking-at "[?.,;!]"))))))))
 
+(defun sp-lisp-insert-space-after-slurp (_id action _context)
+  (-let (((&plist :ok-orig :next-thing) sp-handler-context))
+    (when (and (eq action 'slurp-forward)
+               (sp-get ok-orig (/= :beg-in :end-in)))
+      (save-excursion
+        (sp-get ok-orig (goto-char :end-in))
+        (skip-syntax-backward " ")
+        (unless (looking-at-p (rx (or whitespace eol)))
+          (insert " "))))))
+
 ;; emacs is lisp hacking environment, so we set up some most common
 ;; lisp modes too
 (sp-with-modes sp-lisp-modes
+  (sp-local-pair "(" nil :post-handlers '(:add 
sp-lisp-insert-space-after-slurp))
+  (sp-local-pair "[" nil :post-handlers '(:add 
sp-lisp-insert-space-after-slurp))
   ;; disable ', it's the quote character!
   (sp-local-pair "'" nil :actions nil))
 
diff --git a/smartparens.el b/smartparens.el
index f625190765..e10585f8ba 100644
--- a/smartparens.el
+++ b/smartparens.el
@@ -7362,7 +7362,12 @@ Examples:
       (let ((n (abs (prefix-numeric-value arg)))
             (enc (sp-get-enclosing-sexp))
             (in-comment (sp-point-in-comment))
-            next-thing ok)
+            next-thing ok
+            ;; At some places we mutate the value of `ok'
+            ;; destructively (updating the end).  The original value
+            ;; is useful in the handlers for manipulating the
+            ;; surroundings, so we copy it here.
+            ok-orig)
         (when enc
           (save-excursion
             (if (sp--raw-argument-p arg)
@@ -7387,6 +7392,7 @@ Examples:
                   (goto-char (sp-get next-thing :end-suf))
                   (setq ok next-thing)
                   (setq next-thing (sp-get-thing nil)))
+                (setq ok-orig (copy-sequence ok))
                 ;; do not allow slurping into a different context from
                 ;; inside a comment
                 (if (and in-comment
@@ -7427,14 +7433,14 @@ Examples:
                                 (insert " "))))
                           (sp--run-hook-with-args
                            (sp-get enc :op) :pre-handlers 'slurp-forward
-                           (list :arg arg :enc enc :ok ok :next-thing 
next-thing))
+                           (list :arg arg :enc enc :ok ok :ok-orig ok-orig 
:next-thing next-thing))
                           (sp-get ok (insert :cl :suffix))
                           (sp--indent-region (sp-get ok :beg-prf) (point))
                           ;; HACK: update the "enc" data structure if ok==enc
                           (when (= (sp-get enc :beg) (sp-get ok :beg)) 
(plist-put enc :end (point)))
                           (sp--run-hook-with-args
                            (sp-get enc :op) :post-handlers 'slurp-forward
-                           (list :arg arg :enc enc :ok ok :next-thing 
next-thing)))
+                           (list :arg arg :enc enc :ok ok :ok-orig ok-orig 
:next-thing next-thing)))
                         (setq n (1- n)))
                     (sp-message :cant-slurp)
                     (setq n -1))))))))
diff --git a/test/smartparens-elisp-test.el b/test/smartparens-elisp-test.el
index 9e1036e2df..334725c7c0 100644
--- a/test/smartparens-elisp-test.el
+++ b/test/smartparens-elisp-test.el
@@ -25,3 +25,54 @@ punctuation was considered invalid."
     (sp-backward-delete-char)
     (sp-backward-delete-char)
     (sp-buffer-equals ";; `a-symbol-name'? I|")))
+
+(prog1 "#781"
+  (ert-deftest sp-test-slurp-insert-space-for-style--next-sexp-paren-no-space 
()
+    (sp-test-with-temp-elisp-buffer "(foo|)(bar)"
+      (call-interactively 'sp-forward-slurp-sexp)
+      (sp-buffer-equals "(foo| (bar))")
+      (call-interactively 'sp-forward-barf-sexp)
+      (sp-buffer-equals "(foo|) (bar)")
+      (call-interactively 'sp-forward-slurp-sexp)
+      (sp-buffer-equals "(foo| (bar))")))
+
+  (ert-deftest sp-test-slurp-insert-space-for-style--next-sexp-paren-space ()
+    (sp-test-with-temp-elisp-buffer "(foo|) (bar)"
+      (call-interactively 'sp-forward-slurp-sexp)
+      (sp-buffer-equals "(foo| (bar))")
+      (call-interactively 'sp-forward-barf-sexp)
+      (sp-buffer-equals "(foo|) (bar)")
+      (call-interactively 'sp-forward-slurp-sexp)
+      (sp-buffer-equals "(foo| (bar))")))
+
+  (ert-deftest sp-test-slurp-insert-space-for-style--next-sexp-symbol-no-space 
()
+    (sp-test-with-temp-elisp-buffer "(foo|)bar"
+      (call-interactively 'sp-forward-slurp-sexp)
+      (sp-buffer-equals "(foo| bar)")
+      (call-interactively 'sp-forward-barf-sexp)
+      (sp-buffer-equals "(foo|) bar")
+      (call-interactively 'sp-forward-slurp-sexp)
+      (sp-buffer-equals "(foo| bar)")))
+
+  (ert-deftest sp-test-slurp-insert-space-for-style--next-sexp-symbol-space ()
+    (sp-test-with-temp-elisp-buffer "(foo|) bar"
+      (call-interactively 'sp-forward-slurp-sexp)
+      (sp-buffer-equals "(foo| bar)")
+      (call-interactively 'sp-forward-barf-sexp)
+      (sp-buffer-equals "(foo|) bar")
+      (call-interactively 'sp-forward-slurp-sexp)
+      (sp-buffer-equals "(foo| bar)")))
+
+  (ert-deftest 
sp-test-slurp-insert-space-for-style--no-extra-space-from-empty-sexp ()
+    (sp-test-with-temp-elisp-buffer "(|)foo"
+      (call-interactively 'sp-forward-slurp-sexp)
+      (sp-buffer-equals "(|foo)")
+      (call-interactively 'sp-forward-barf-sexp)
+      (sp-buffer-equals "(|)foo")))
+
+  (ert-deftest sp-test-slurp-insert-space-for-style--next-on-new-line ()
+    (sp-test-with-temp-elisp-buffer "(foo|)\n(bar)"
+      (call-interactively 'sp-forward-slurp-sexp)
+      (sp-buffer-equals "(foo|\n (bar))")
+      (call-interactively 'sp-forward-barf-sexp)
+      (sp-buffer-equals "(foo|)\n(bar)"))))

Reply via email to