syl20bnr / spacemacs

A community-driven Emacs distribution - The best editor is neither Emacs nor Vim, it's Emacs *and* Vim!
http://spacemacs.org
GNU General Public License v3.0
23.69k stars 4.89k forks source link

smartparens throws an exception in clojure-mode #6375

Closed codahale closed 8 years ago

codahale commented 8 years ago

Description :octocat:

smartparens and clojure-mode are unhappy

Reproduction guide :beetle:

Observed behaviour: :eyes: :broken_heart: Open Clojure file, an exception is thrown. This error means almost all mode key bindings don't register.

Expected behaviour: :heart: :smile: Open Clojure file, start hacking, enjoy Spacemacs.

System Info :computer:

((auto-completion :variables auto-completion-enable-help-tooltip t auto-completion-enable-snippets-in-popup t auto-completion-enable-sort-by-usage t)
 (colors :variables colors-colorize-identifiers 'variables)
 (clojure :variables cljr-eagerly-cache-macro-occurrences-on-startup nil cider-refresh-before-fn "user/stop" cider-refresh-after-fn "user/start")
 docker emacs-lisp emoji git github
 (go :variables gofmt-command "goimports")
 helm
 (html :variables css-indent-offset 2 web-mode-markup-indent-offset 2 web-mode-css-indent-offset 2 web-mode-code-indent-offset 2 web-mode-attr-indent-offset 2 web-mode-enable-css-colorization t)
 imenu-list
 (javascript :variables js2-basic-offset 2 js-indent-level 2)
 markdown osx ruby
 (rust :variables rust-format-on-save t)
 (shell :variables shell-default-term-shell "/usr/local/bin/bash")
 shell-scripts spell-checking sql syntax-checking version-control yaml)

Backtrace :paw_prints:

File mode specification error: (wrong-number-of-arguments (lambda (modes open close &rest --cl-rest--) Add a local pair definition or override a global definition.

MODES can be a single mode or a list of modes where these settings
should be applied.

PREFIX is a regular expression matching an optional prefix for
this pair in the specified major modes.  If not specified, the
characters of expression prefix syntax class are automatically
considered instead.  This can be used to attach custom prefixes
to pairs, such as prefix "\function" in \function{arg} in
`LaTeX-mode'.

SUFFIX is a regular expression matching an optional suffix for
this pair in the specified major modes.  If not specified, the
characters of punctuation syntax class are automatically
considered instead.

The rest of the arguments have same semantics as in `sp-pair'.

If the pair is not defined globally, ACTIONS defaults to (wrap
insert) instead of (:add) (which inherits global settings)

The pairs are uniquely identified by the opening delimiter.  If you
replace the closing one with a different string in the local
definition, this will override the global closing delimiter.

The list arguments can optionally be of form starting with
":add" or ":rem" when these mean "add to the global list"
and "remove from the global list" respectivelly.  Otherwise,
the global list is replaced.  If you wish to both add and remove
things with single call, use "((:add ...) (:rem ...))" as an
argument.  Therefore,

  :when '(:add my-test)

would mean "use the global settings for this pair, but also this
additional test". If no value is provided for list arguments,
they default to "(:add)" which means they inherit the list from
the global definition.

To disable a pair in a major mode, simply set its actions set to
nil. This will ensure the pair is not even loaded when the mode is
activated.

If WRAP is non-nil, the binding is added into major mode keymap
called "foo-mode-map".  If the mode does not follow this
convention, you will need to bind the function manually (see
`sp-pair' to how the function is named for each particular pair).
The bindings are not added into `smartparens-mode-map' to prevent
clashes between different modes.

BIND is equivalent to WRAP.  It is a legacy setting and will be
removed soon.

The binding for INSERT follows the same convention as BIND.  See
`sp-pair' for more info.

You can provide a function SKIP-MATCH, that will take three
arguments: the currently matched delimiter, beginning of match
and end of match.  If this function returns true, the
`sp-get-paired-expression' matcher will ignore this match.  You
can use this to skip over expressions that serve multiple
functions, such as if/end pair or unary if in Ruby or * in
markdown when it signifies list item instead of emphasis.  In
addition, there is a global per major-mode option, see
`sp-navigate-skip-match'.

(fn MODES OPEN CLOSE &key TRIGGER (ACTIONS \='(:add)) (WHEN \='(:add)) (UNLESS \='(:add)) (PRE-HANDLERS \='(:add)) (POST-HANDLERS \='(:add)) WRAP BIND INSERT PREFIX SUFFIX SKIP-MATCH) (let* ((trigger (car (cdr (plist-member --cl-rest-- (quote :trigger))))) (actions (car (cdr (or (plist-member --cl-rest-- (quote :actions)) (quote (nil (:add))))))) (when (car (cdr (or (plist-member --cl-rest-- (quote :when)) (quote (nil (:add))))))) (unless (car (cdr (or (plist-member --cl-rest-- (quote :unless)) (quote (nil (:add))))))) (pre-handlers (car (cdr (or (plist-member --cl-rest-- (quote :pre-handlers)) (quote (nil (:add))))))) (post-handlers (car (cdr (or (plist-member --cl-rest-- (quote :post-handlers)) (quote (nil (:add))))))) (wrap (car (cdr (plist-member --cl-rest-- (quote :wrap))))) (bind (car (cdr (plist-member --cl-rest-- (quote :bind))))) (insert (car (cdr (plist-member --cl-rest-- (quote :insert))))) (prefix (car (cdr (plist-member --cl-rest-- (quote :prefix))))) (suffix (car (cdr (plist-member --cl-rest-- (quote :suffix))))) (skip-match (car (cdr (plist-member --cl-rest-- (quote :skip-match)))))) (progn (let ((--cl-keys-- --cl-rest--)) (while --cl-keys-- (cond ((memq (car --cl-keys--) (quote (:trigger :actions :when :unless :pre-handlers :post-handlers :wrap :bind :insert :prefix :suffix :skip-match :allow-other-keys))) (setq --cl-keys-- (cdr (cdr --cl-keys--)))) ((car (cdr (memq (quote :allow-other-keys) --cl-rest--))) (setq --cl-keys-- nil)) (t (error Keyword argument %s not one of (:trigger :actions :when :unless :pre-handlers :post-handlers :wrap :bind :insert :prefix :suffix :skip-match) (car --cl-keys--)))))) (progn (if (eq actions :rem) (let ((remove )) (let ((--dolist-tail-- (-flatten (list modes))) m) (while --dolist-tail-- (setq m (car --dolist-tail--)) (setq remove (concat remove (sp-get-pair-definition open m :open) (sp-get-pair-definition open m :close))) (let ((mode-pairs (assq m sp-pairs))) (setcdr mode-pairs (let (result) (let ((list (cdr mode-pairs)) (it-index 0)) (while list (let ((it (car list))) (if (not (equal (plist-get it :open) open)) (progn (setq result (cons it result))))) (setq it-index (1+ it-index)) (setq list (cdr list)))) (nreverse result)))) (setq --dolist-tail-- (cdr --dolist-tail--))))) (let ((--dolist-tail-- (-flatten (list modes))) m) (while --dolist-tail-- (setq m (car --dolist-tail--)) (let* ((pair nil)) (setq pair (plist-put pair :open open)) (if close (progn (plist-put pair :close close))) (if trigger (progn (plist-put pair :trigger trigger))) (if prefix (progn (plist-put pair :prefix prefix))) (if suffix (progn (plist-put pair :suffix suffix))) (if skip-match (progn (plist-put pair :skip-match skip-match))) (if (and (not (sp-get-pair-definition open t)) (equal actions (quote (:add)))) (progn (setq actions (quote (wrap insert autoskip navigate))))) (plist-put pair :actions actions) (plist-put pair :when when) (plist-put pair :unless unless) (plist-put pair :pre-handlers pre-handlers) (plist-put pair :post-handlers post-handlers) (sp--update-pair-list pair m) (let ((symbol (intern (concat (symbol-name m) -map)))) (if symbol (let ((map (and (boundp symbol) (symbol-value symbol)))) (if map (progn (if (or wrap bind) (progn (define-key map (read-kbd-macro (or wrap bind)) (list (quote lambda) (quote (&optional arg)) (quote (interactive P)) (list (quote sp-wrap-with-pair) open))))) (if insert (progn (define-key map (kbd insert) (list (quote lambda) nil (quote (interactive)) (list (quote sp-insert-pair) open))))))))))) (setq --dolist-tail-- (cdr --dolist-tail--))))) (sp--update-local-pairs-everywhere (-flatten (list modes))) sp-pairs)))) 2)
TheBB commented 8 years ago

Maybe you can delete the .elc file so that we can get a backtrace that is readable?

codahale commented 8 years ago

Done. I updated the backtrace in the main description.

codahale commented 8 years ago

Toggling debug mode on got me this:

(fn MODES OPEN CLOSE &key TRIGGER (ACTIONS \\='(:add)) (WHEN \\='(:add)) (UNLESS \\='(:add)) (PRE-HANDLERS \\='(:add)) (POST-HANDLERS \\='(:add)) WRAP BIND INSERT PREFIX SUFFIX SKIP-MATCH)" (let* ((trigger (car (cdr (plist-member --cl-rest-- (quote :trigger))))) (actions (car (cdr (or (plist-member --cl-rest-- (quote :actions)) (quote (nil (:add))))))) (when (car (cdr (or (plist-member --cl-rest-- (quote :when)) (quote (nil (:add))))))) (unless (car (cdr (or (plist-member --cl-rest-- (quote :unless)) (quote (nil (:add))))))) (pre-handlers (car (cdr (or (plist-member --cl-rest-- (quote :pre-handlers)) (quote (nil (:add))))))) (post-handlers (car (cdr (or (plist-member --cl-rest-- (quote :post-handlers)) (quote (nil (:add))))))) (wrap (car (cdr (plist-member --cl-rest-- (quote :wrap))))) (bind (car (cdr (plist-member --cl-rest-- (quote :bind))))) (insert (car (cdr (plist-member --cl-rest-- (quote :insert))))) (prefix (car (cdr (plist-member --cl-rest-- (quote :prefix))))) (suffix (car (cdr (plist-member --cl-rest-- (quote :suffix))))) (skip-match (car (cdr (plist-member --cl-rest-- (quote :skip-match)))))) (progn (let ((--cl-keys-- --cl-rest--)) (while --cl-keys-- (cond ((memq (car --cl-keys--) (quote (:trigger :actions :when :unless :pre-handlers :post-handlers :wrap :bind :insert :prefix :suffix :skip-match :allow-other-keys))) (setq --cl-keys-- (cdr (cdr --cl-keys--)))) ((car (cdr (memq (quote :allow-other-keys) --cl-rest--))) (setq --cl-keys-- nil)) (t (error "Keyword argument %s not one of (:trigger :actions :when :unless :pre-handlers :post-handlers :wrap :bind :insert :prefix :suffix :skip-match)" (car --cl-keys--)))))) (progn (if (eq actions :rem) (let ((remove "")) (let ((--dolist-tail-- (-flatten (list modes))) m) (while --dolist-tail-- (setq m (car --dolist-tail--)) (setq remove (concat remove (sp-get-pair-definition open m :open) (sp-get-pair-definition open m :close))) (let ((mode-pairs (assq m sp-pairs))) (setcdr mode-pairs (let (result) (let ((list (cdr mode-pairs)) (it-index 0)) (while list (let ((it (car list))) (if (not (equal (plist-get it :open) open)) (progn (setq result (cons it result))))) (setq it-index (1+ it-index)) (setq list (cdr list)))) (nreverse result)))) (setq --dolist-tail-- (cdr --dolist-tail--))))) (let ((--dolist-tail-- (-flatten (list modes))) m) (while --dolist-tail-- (setq m (car --dolist-tail--)) (let* ((pair nil)) (setq pair (plist-put pair :open open)) (if close (progn (plist-put pair :close close))) (if trigger (progn (plist-put pair :trigger trigger))) (if prefix (progn (plist-put pair :prefix prefix))) (if suffix (progn (plist-put pair :suffix suffix))) (if skip-match (progn (plist-put pair :skip-match skip-match))) (if (and (not (sp-get-pair-definition open t)) (equal actions (quote (:add)))) (progn (setq actions (quote (wrap insert autoskip navigate))))) (plist-put pair :actions actions) (plist-put pair :when when) (plist-put pair :unless unless) (plist-put pair :pre-handlers pre-handlers) (plist-put pair :post-handlers post-handlers) (sp--update-pair-list pair m) (let ((symbol (intern (concat (symbol-name m) "-map")))) (if symbol (let ((map (and (boundp symbol) (symbol-value symbol)))) (if map (progn (if (or wrap bind) (progn (define-key map (read-kbd-macro (or wrap bind)) (list (quote lambda) (quote (&optional arg)) (quote (interactive "P")) (list (quote sp-wrap-with-pair) open))))) (if insert (progn (define-key map (kbd insert) (list (quote lambda) nil (quote (interactive)) (list (quote sp-insert-pair) open))))))))))) (setq --dolist-tail-- (cdr --dolist-tail--))))) (sp--update-local-pairs-everywhere (-flatten (list modes))) sp-pairs)))) 2)
  sp-local-pair("#{" "}")
  clojure-smartparens-setup()
  run-hooks(smartparens-mode-hook smartparens-mode-on-hook)
  (let ((last-message (current-message))) (setq smartparens-mode (if (eq arg (quote toggle)) (not smartparens-mode) (> (prefix-numeric-value arg) 0))) (if smartparens-mode (progn (sp--init) (run-hooks (quote smartparens-enabled-hook))) (run-hooks (quote smartparens-disabled-hook))) (run-hooks (quote smartparens-mode-hook) (if smartparens-mode (quote smartparens-mode-on-hook) (quote smartparens-mode-off-hook))) (if (called-interactively-p (quote any)) (progn nil (if (and (current-message) (not (equal last-message (current-message)))) nil (let ((local " in current buffer")) (message "Smartparens mode %sabled%s" (if smartparens-mode "en" "dis") local))))))
  smartparens-mode()
  run-hooks(change-major-mode-after-body-hook prog-mode-hook clojure-mode-hook)
  apply(run-hooks (change-major-mode-after-body-hook prog-mode-hook clojure-mode-hook))
  run-mode-hooks(clojure-mode-hook)
  clojure-mode()
  set-auto-mode-0(clojure-mode nil)
  set-auto-mode()
  normal-mode(t)
[a bunch of other stuff]
codahale commented 8 years ago

Looks like the bug is in clojure-mode, so I'll report there.

codahale commented 8 years ago

Fixed upstream. Sorry for the trouble!