I am trying to include support for smartparens in a major-mode package. I want that if a user is using smartparens, then he will get additional pair definitions, and if he isn't, he will not notice anything different.
For that, I am using instructions of the form:
(declare-function sp-with-modes "ext:smartparens.el" t t) (declare-function sp-local-pair "ext:smartparens.el" t t) (eval-after-load 'smartparens '(sp-with-modes '(test-mode) (sp-local-pair "<" ">" :actions '(insert wrap autoskip))))
This works fine if the file is not byte-compiled, or if it is byte-compiled by an emacs with smartparens loaded, or with emacs 24.3. However, with 24.5 (and probably with 24.4, though I cannot easily test it at the moment), and if it is compiled in a vanilla emacs (for example with
cask build), it gives an error, stating that the argument
(insert wrap autoskip) is not one of the keywords admissible by
If I remove the call to
sp-with-modes, and I replace the definition with
(sp-local-pair 'test-mode "<" ">" :actions '(insert wrap autoskip))
then it works fine. The macro
sp-with-modes is supposed to loop over its argument (a list), inserting each element as first argument to everything in the body, I suspect that it confuses the byte-compiler at some point.
Is there a way to include this kind of "maybe evaluation" in a byte-compiled file, without confusing the byte-compiler? For example, is it possible to tell the compiler "do not compile this form"?
Or what would be the idiomatic way of achieving this kind of third-party support in a package?
Please note that the question involves
smartparens because that's where I noticed the problem, but I suspect that it may happen with a lot of other packages.
The rest of the question is a MWE. I assumes that your regular emacs configuration has
(declare-function sp-with-modes "ext:smartparens.el" t t) (declare-function sp-local-pair "ext:smartparens.el" t t) (eval-after-load 'smartparens '(sp-with-modes '(test-mode) (sp-local-pair "<" ">" :actions '(insert wrap autoskip)))) (define-derived-mode test-mode fundamental-mode "Test" "Test mode") (provide 'test)
(require 'package) (setq package-enable-at-startup nil) (add-to-list 'package-archives '("melpa" . "http://melpa.org/packages/")) (package-initialize) (add-to-list 'load-path "~/.emacs.d/tests/") (require 'test) (require 'smartparens) (smartparens-global-mode t)
emacs -Q and evaluate
emacs -Q --load "~/.emacs.d/tests/init.el".
expand-regionpackage when adding a function
save-mark-and-excursionthat was introduced in emacs 25.0: Does a similar approach of using
eval-after-loadhas a compiler-macro which expands
quoted forms into a lambda-form, which is then compiled (This could be viewed as a bug.). Since the compiler does not know, that
sp-with-modesis a macro, it treats it as function, I believe. When the code gets evaluated, it'll be to late for any macro exansion and
sp-local-pairis eval'd as the first argument to the other function...