dotemacs

My Emacs configuration
git clone git://git.entf.net/dotemacs
Log | Files | Refs | LICENSE

README-elpa (10191B)


      1 1 macrostep: interactive macro-expander
      2 ═══════════════════════════════════════
      3 
      4   `macrostep' is an Emacs minor mode for interactively stepping through
      5   the expansion of macros in Emacs Lisp source code.  It lets you see
      6   exactly what happens at each step of the expansion process by
      7   pretty-printing the expanded forms inline in the source buffer, which
      8   is temporarily read-only while macro expansions are visible.  You can
      9   expand and collapse macro forms one step at a time, and evaluate or
     10   instrument the expansions for debugging with Edebug as normal (but see
     11   "Bugs and known limitations", below).  Single-stepping through the
     12   expansion is particularly useful for debugging macros that expand into
     13   another macro form.  These can be difficult to debug with Emacs'
     14   built-in `macroexpand', which continues expansion until the top-level
     15   form is no longer a macro call.
     16 
     17   Both globally-visible macros as defined by `defmacro' and local macros
     18   bound by `(cl-)macrolet' or another macro-defining form can be
     19   expanded.  Within macro expansions, calls to macros and compiler
     20   macros are fontified specially: macro forms using
     21   `macrostep-macro-face', and functions with compiler macros using
     22   `macrostep-compiler-macro-face'.  Uninterned symbols (gensyms) are
     23   fontified based on which step in the expansion created them, to
     24   distinguish them both from normal symbols and from other gensyms with
     25   the same print name.
     26 
     27   As of version 0.9, it is also possible to extend `macrostep' to work
     28   with other languages with macro systems in addition to Emacs Lisp.  An
     29   extension for Common Lisp (via SLIME) is in the works; contributions
     30   for other languages are welcome.  See "Extending macrostep" below for
     31   details.
     32 
     33 
     34 1.1 Key-bindings and usage
     35 ──────────────────────────
     36 
     37   The standard keybindings in `macrostep-mode' are the following:
     38 
     39   e, =, RET 
     40         expand the macro form following point one step
     41   c, u, DEL 
     42         collapse the form following point
     43   q, C-c C-c
     44         collapse all expanded forms and exit macrostep-mode
     45   n, TAB    
     46         jump to the next macro form in the expansion
     47   p, M-TAB  
     48         jump to the previous macro form in the expansion
     49 
     50   It's not very useful to enable and disable macrostep-mode directly.
     51   Instead, bind `macrostep-expand' to a key in `emacs-lisp-mode-map',
     52   for example C-c e:
     53 
     54   ┌────
     55   │ (define-key emacs-lisp-mode-map (kbd "C-c e") 'macrostep-expand)
     56   └────
     57 
     58   You can then enter macrostep-mode and expand a macro form completely
     59   by typing `C-c e e e ...' as many times as necessary.
     60 
     61   Exit macrostep-mode by typing `q' or `C-c C-c', or by successively
     62   typing `c' to collapse all surrounding expansions.
     63 
     64 
     65 1.2 Customization options
     66 ─────────────────────────
     67 
     68   Type `M-x customize-group RET macrostep RET' to customize options and
     69   faces.
     70 
     71   To display macro expansions in a separate window, instead of inline in
     72   the source buffer, customize `macrostep-expand-in-separate-buffer' to
     73   `t'.  The default is `nil'.  Whichever default behavior is selected,
     74   the alternative behavior can be obtained temporarily by giving a
     75   prefix argument to `macrostep-expand'.
     76 
     77   To have `macrostep' ignore compiler macros, customize
     78   `macrostep-expand-compiler-macros' to `nil'.  The default is `t'.
     79 
     80   Customize the faces `macrostep-macro-face',
     81   `macrostep-compiler-macro-face', and `macrostep-gensym-1' through
     82   `macrostep-gensym-5' to alter the appearance of macro expansions.
     83 
     84 
     85 1.3 Locally-bound macros
     86 ────────────────────────
     87 
     88   As of version 0.9, `macrostep' can expand calls to a locally-bound
     89   macro, whether defined by a surrounding `(cl-)macrolet' form, or by
     90   another macro-defining macro.  In other words, it is possible to
     91   expand the inner `local-macro' forms in both the following examples,
     92   whether `local-macro' is defined by an enclosing `cl-macrolet' –
     93 
     94   ┌────
     95   │ (cl-macrolet ((local-macro (&rest args)
     96   │ 		`(expansion of ,args)))
     97   │   (local-macro (do-something)))
     98   └────
     99 
    100   – or by a macro which expands into `cl-macrolet', provided that its
    101   definition of macro is evaluated prior to calling `macrostep-expand':
    102 
    103   ┌────
    104   │ (defmacro with-local-macro (&rest body)
    105   │   `(cl-macrolet ((local-macro (&rest args)
    106   │ 		   `(expansion of ,args)))
    107   │      ,@body))
    108    109   │ (with-local-macro
    110   │     (local-macro (do something (else)))
    111   └────
    112 
    113   See the `with-js' macro in Emacs's `js.el' for a real example of the
    114   latter kind of macro.
    115 
    116   Expansion of locally-bound macros is implemented by instrumenting
    117   Emacs Lisp's macro-expander to capture the environment at point.  A
    118   similar trick is used to detect macro- and compiler-macro calls within
    119   expanded text so that they can be fontified accurately.
    120 
    121 
    122 1.4 Expanding sub-forms
    123 ───────────────────────
    124 
    125   By moving point around in the macro expansion using
    126   `macrostep-next-macro' and `macrostep-prev-macro' (bound to the `n'
    127   and `p' keys), it is possible to expand other macro calls within the
    128   expansion before expanding the outermost form.  This can sometimes be
    129   useful, although it does not correspond to the real order of macro
    130   expansion in Emacs Lisp, which proceeds by fully expanding the outer
    131   form to a non-macro form before expanding sub-forms.
    132 
    133   The main reason to expand sub-forms out of order is to help with
    134   debugging macros which programmatically expand their arguments in
    135   order to rewrite them.  Expanding the arguments of such a macro lets
    136   you visualise what the macro definition would compute via
    137   `macroexpand-all'.
    138 
    139 
    140 1.5 Extending macrostep for other languages
    141 ───────────────────────────────────────────
    142 
    143   Since version 0.9, it is possible to extend macrostep to work with
    144   other languages besides Emacs Lisp.  In typical Emacs fashion, this is
    145   implemented by setting buffer-local variables to different function
    146   values.  Six buffer-local variables define the language-specific part
    147   of the implementation:
    148 
    149   • `macrostep-sexp-bounds-function'
    150   • `macrostep-sexp-at-point-function'
    151   • `macrostep-environment-at-point-function'
    152   • `macrostep-expand-1-function'
    153   • `macrostep-print-function'
    154   • `macrostep-macro-form-p-function'
    155 
    156   Typically, an implementation for another language would set these
    157   variables in a major-mode hook.  See the docstrings of each variable
    158   for details on how each one is called and what it should return.  At a
    159   minimum, another language implementation needs to provide
    160   `macrostep-sexp-at-point-function', `macrostep-expand-1-function', and
    161   `macrostep-print-function'.  Lisp-like languages may be able to reuse
    162   the default `macrostep-sexp-bounds-function' if they provide another
    163   implementation of `macrostep-macro-form-p-function'.  Languages which
    164   do not implement locally-defined macros can set
    165   `macrostep-environment-at-point-function' to `ignore'.
    166 
    167   Note that the core `macrostep' machinery only interprets the return
    168   value of `macrostep-sexp-bounds-function', so implementations for
    169   other languages can use any internal representations of code and
    170   environments which is convenient.  Although the terminology is
    171   Lisp-specific, there is no reason that implementations could not be
    172   provided for non-Lisp languages with macro systems, provided there is
    173   some way of identifying macro calls and calling the compiler /
    174   preprocessor to obtain their expansions.
    175 
    176 
    177 1.6 Bugs and known limitations
    178 ──────────────────────────────
    179 
    180   You can evaluate and edebug macro-expanded forms and step through the
    181   macro-expanded version, but the form that `eval-defun' and friends
    182   read from the buffer won't have the uninterned symbols of the real
    183   macro expansion.  This will probably work OK with CL-style gensyms,
    184   but may cause problems with `make-symbol' symbols if they have the
    185   same print name as another symbol in the expansion. It's possible that
    186   using `print-circle' and `print-gensym' could get around this.
    187 
    188   Please send other bug reports and feature requests to the author.
    189 
    190 
    191 1.7 Acknowledgements
    192 ────────────────────
    193 
    194   Thanks to:
    195   • John Wiegley for fixing a bug with the face definitions under Emacs
    196     24 & for plugging macrostep in his [EmacsConf presentation]!
    197   • George Kettleborough for bug reports, and patches to highlight the
    198     expanded region and properly handle backquotes.
    199   • Nic Ferrier for suggesting support for local definitions within
    200     macrolet forms
    201   • Luís Oliveira for suggesting and implementing SLIME support
    202 
    203   `macrostep' was originally inspired by J. V. Toups's 'Deep Emacs Lisp'
    204   articles ([part 1], [part 2], [screencast]).
    205 
    206 
    207 [EmacsConf presentation] <http://youtu.be/RvPFZL6NJNQ>
    208 
    209 [part 1]
    210 <http://dorophone.blogspot.co.uk/2011/04/deep-emacs-part-1.html>
    211 
    212 [part 2]
    213 <http://dorophone.blogspot.co.uk/2011/04/deep-emacs-lisp-part-2.html>
    214 
    215 [screencast]
    216 <http://dorophone.blogspot.co.uk/2011/05/monadic-parser-combinators-in-elisp.html>
    217 
    218 
    219 1.8 Changelog
    220 ─────────────
    221 
    222   • v0.9, 2015-10-01:
    223     • separate into Elisp-specific and generic components
    224     • highlight and expand compiler macros
    225     • improve local macro expansion and macro form identification by
    226       instrumenting `macroexpand(-all)'
    227   • v0.8, 2014-05-29: fix a bug with printing the first element of lists
    228   • v0.7, 2014-05-11: expand locally-defined macros within
    229     `(cl-)macrolet' forms
    230   • v0.6, 2013-05-04: better handling of quote and backquote
    231   • v0.5, 2013-04-16: highlight region, maintain cleaner buffer state
    232   • v0.4, 2013-04-07: only enter macrostep-mode on successful
    233     macro-expansion
    234   • v0.3, 2012-10-30: print dotted lists correctly. autoload
    235     definitions.