Fuco1 / smartparens

Minor mode for Emacs that deals with parens pairs and tries to be smart about it.
GNU General Public License v3.0
1.8k stars 193 forks source link

sp-unwrap-sexp throws wrong-type-argument nil in minibuffer #1158

Open zalky opened 1 year ago

zalky commented 1 year ago

Expected behavior

When working with list expressions in the minibuffer, if I have a set of parenthesis (), and the cursor is inside the expression, sp-unwrap-sexp should unwrap the expression.

Actual behavior

sp-unwrap-sexp throws a (wrong-type-argument stringp nil)

Steps to reproduce the problem

  1. Eval an elisp expression in the minibuffer
  2. Enter an empty expression ()
  3. Move the cursor inside the parenthesis
  4. Try sp-unwrap-sexp

Backtraces if necessary (M-x toggle-debug-on-error)

Debugger entered--Lisp error: (wrong-type-argument stringp nil)
  string-match("^[\n\11 ]+\\'" nil nil)
  string-match-p("^[\n\11 ]+\\'" nil)
  (if (string-match-p "^[\n\11 ]+\\'" (thing-at-point 'line)) (progn (let ((b (bounds-of-thing-at-point 'line))) (delete-region (car b) (cdr b)))))
  (save-excursion (goto-char new-end) (if (string-match-p "^[\n\11 ]+\\'" (thing-at-point 'line)) (progn (let ((b (bounds-of-thing-at-point 'line))) (delete-region (car b) (cdr b))))) (setq indent-to (point)) (goto-char new-start) (if (string-match-p "^[\n\11 ]+\\'" (thing-at-point 'line)) (progn (let ((b (bounds-of-thing-at-point 'line))) (delete-region (car b) (cdr b))))) (setq indent-from (point)))
  (let ((new-start (let ((struct sexp)) (- (plist-get struct :beg) (length (plist-get struct :prefix))))) (new-end (let ((struct sexp)) (- (- (plist-get struct :end) (length (plist-get struct :cl))) (length (plist-get struct :op)) (length (plist-get struct :prefix))))) indent-from indent-to) (save-excursion (goto-char new-end) (if (string-match-p "^[\n\11 ]+\\'" (thing-at-point 'line)) (progn (let ((b (bounds-of-thing-at-point ...))) (delete-region (car b) (cdr b))))) (setq indent-to (point)) (goto-char new-start) (if (string-match-p "^[\n\11 ]+\\'" (thing-at-point 'line)) (progn (let ((b (bounds-of-thing-at-point ...))) (delete-region (car b) (cdr b))))) (setq indent-from (point))) (if (memq major-mode sp-no-reindent-after-kill-modes) nil (let ((c (current-column)) (i (sp--current-indentation))) (sp--indent-region indent-from indent-to) (sp--back-to-indentation c i))))
  (if no-cleanup nil (let ((new-start (let ((struct sexp)) (- (plist-get struct :beg) (length (plist-get struct :prefix))))) (new-end (let ((struct sexp)) (- (- (plist-get struct :end) (length ...)) (length (plist-get struct :op)) (length (plist-get struct :prefix))))) indent-from indent-to) (save-excursion (goto-char new-end) (if (string-match-p "^[\n\11 ]+\\'" (thing-at-point 'line)) (progn (let ((b ...)) (delete-region (car b) (cdr b))))) (setq indent-to (point)) (goto-char new-start) (if (string-match-p "^[\n\11 ]+\\'" (thing-at-point 'line)) (progn (let ((b ...)) (delete-region (car b) (cdr b))))) (setq indent-from (point))) (if (memq major-mode sp-no-reindent-after-kill-modes) nil (let ((c (current-column)) (i (sp--current-indentation))) (sp--indent-region indent-from indent-to) (sp--back-to-indentation c i)))))
  sp--unwrap-sexp((:beg 7 :end 9 :op "(" :cl ")" :prefix "" :suffix ""))
  (progn (sp--unwrap-sexp ok))
  (if ok (progn (sp--unwrap-sexp ok)))
  (let ((ok (save-excursion (sp-forward-sexp arg)))) (if ok (progn (sp--unwrap-sexp ok))) ok)
  (let ((sp-navigate-consider-symbols nil)) (let ((ok (save-excursion (sp-forward-sexp arg)))) (if ok (progn (sp--unwrap-sexp ok))) ok))
  sp-unwrap-sexp(1)
  funcall-interactively(sp-unwrap-sexp 1)
  call-interactively(sp-unwrap-sexp nil nil)
  command-execute(sp-unwrap-sexp)

Environment & version information

In recent enough smartparens you can call M-x sp-describe-system to generate this report. Please fill manually what we could not detect automatically. Edit the output as you see fit to protect your privacy.

Lead and Potential Resolution

I think that thing-at-point is returning nil in the minibuffer for whatever reason in sp--unwrap-sexp on these lines.

I have no idea if this is expected behaviour for thing-at-point in this context. If it is, then there probably needs to be a check like the following:

        (if-let ((thing (thing-at-point 'line))
                 ((string-match-p "^[\n\t ]+\\'" thing))
                 (b (bounds-of-thing-at-point 'line)))
            (delete-region (car b) (cdr b)))

While this eliminates the error me, if thing-at-point is not supposed to return nil in this situation, then this might not be the right solution.