Klimi's new dotfiles with stow.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

129 lines
4.8 KiB

4 years ago
  1. ;;; slime-macrostep.el -- fancy macro-expansion via macrostep.el
  2. ;; Authors: Luís Oliveira <luismbo@gmail.com>
  3. ;; Jon Oddie <j.j.oddie@gmail.com
  4. ;;
  5. ;; License: GNU GPL (same license as Emacs)
  6. ;;; Description:
  7. ;; Fancier in-place macro-expansion using macrostep.el (originally
  8. ;; written for Emacs Lisp). To use, position point before the
  9. ;; open-paren of the macro call in a SLIME source or REPL buffer, and
  10. ;; type `C-c M-e' or `M-x macrostep-expand'. The pretty-printed
  11. ;; result of `macroexpand-1' will be inserted inline in the current
  12. ;; buffer, which is temporarily read-only while macro expansions are
  13. ;; visible. If the expansion is itself a macro call, expansion can be
  14. ;; continued by typing `e'. Expansions are collapsed to their
  15. ;; original macro forms by typing `c' or `q'. Other macro- and
  16. ;; compiler-macro calls in the expansion will be font-locked
  17. ;; differently, and point can be moved there quickly by typing `n' or
  18. ;; `p'. For more details, see the documentation of
  19. ;; `macrostep-expand'.
  20. ;;; Code:
  21. (require 'slime)
  22. (eval-and-compile
  23. (require 'macrostep nil t)
  24. ;; Use bundled version if not separately installed
  25. (require 'macrostep "../lib/macrostep"))
  26. (eval-when-compile (require 'cl-lib))
  27. (defvar slime-repl-mode-hook)
  28. (defvar slime-repl-mode-map)
  29. (define-slime-contrib slime-macrostep
  30. "Interactive macro expansion via macrostep.el."
  31. (:authors "Luís Oliveira <luismbo@gmail.com>"
  32. "Jon Oddie <j.j.oddie@gmail.com>")
  33. (:license "GPL")
  34. (:swank-dependencies swank-macrostep)
  35. (:on-load
  36. (easy-menu-add-item slime-mode-map '(menu-bar SLIME Debugging)
  37. ["Macro stepper..." macrostep-expand (slime-connected-p)]
  38. "Create Trace Buffer")
  39. (add-hook 'slime-mode-hook #'macrostep-slime-mode-hook)
  40. (define-key slime-mode-map (kbd "C-c M-e") #'macrostep-expand)
  41. (eval-after-load 'slime-repl
  42. '(progn
  43. (add-hook 'slime-repl-mode-hook #'macrostep-slime-mode-hook)
  44. (define-key slime-repl-mode-map (kbd "C-c M-e") #'macrostep-expand)))))
  45. (defun macrostep-slime-mode-hook ()
  46. (setq macrostep-sexp-at-point-function #'macrostep-slime-sexp-at-point)
  47. (setq macrostep-environment-at-point-function #'macrostep-slime-context)
  48. (setq macrostep-expand-1-function #'macrostep-slime-expand-1)
  49. (setq macrostep-print-function #'macrostep-slime-insert)
  50. (setq macrostep-macro-form-p-function #'macrostep-slime-macro-form-p))
  51. (defun macrostep-slime-sexp-at-point (&rest _ignore)
  52. (slime-sexp-at-point))
  53. (defun macrostep-slime-context ()
  54. (let (defun-start defun-end)
  55. (save-excursion
  56. (while
  57. (condition-case nil
  58. (progn (backward-up-list) t)
  59. (scan-error nil)))
  60. (setq defun-start (point))
  61. (setq defun-end (scan-sexps (point) 1)))
  62. (list (buffer-substring-no-properties
  63. defun-start (point))
  64. (buffer-substring-no-properties
  65. (scan-sexps (point) 1) defun-end))))
  66. (defun macrostep-slime-expand-1 (string context)
  67. (slime-dcase
  68. (slime-eval
  69. `(swank-macrostep:macrostep-expand-1
  70. ,string ,macrostep-expand-compiler-macros ',context))
  71. ((:error error-message)
  72. (error "%s" error-message))
  73. ((:ok expansion positions)
  74. (list expansion positions))))
  75. (defun macrostep-slime-insert (result _ignore)
  76. "Insert RESULT at point, indenting to match the current column."
  77. (cl-destructuring-bind (expansion positions) result
  78. (let ((start (point))
  79. (column-offset (current-column)))
  80. (insert expansion)
  81. (macrostep-slime--propertize-macros start positions)
  82. (indent-rigidly start (point) column-offset))))
  83. (defun macrostep-slime--propertize-macros (start-offset positions)
  84. "Put text properties on macro forms."
  85. (dolist (position positions)
  86. (cl-destructuring-bind (operator type start)
  87. position
  88. (let ((open-paren-position
  89. (+ start-offset start)))
  90. (put-text-property open-paren-position
  91. (1+ open-paren-position)
  92. 'macrostep-macro-start
  93. t)
  94. ;; this assumes that the operator starts right next to the
  95. ;; opening parenthesis. We could probably be more robust.
  96. (let ((op-start (1+ open-paren-position)))
  97. (put-text-property op-start
  98. (+ op-start (length operator))
  99. 'font-lock-face
  100. (if (eq type :macro)
  101. 'macrostep-macro-face
  102. 'macrostep-compiler-macro-face)))))))
  103. (defun macrostep-slime-macro-form-p (string context)
  104. (slime-dcase
  105. (slime-eval
  106. `(swank-macrostep:macro-form-p
  107. ,string ,macrostep-expand-compiler-macros ',context))
  108. ((:error error-message)
  109. (error "%s" error-message))
  110. ((:ok result)
  111. result)))
  112. (provide 'slime-macrostep)