Last active
June 27, 2018 01:15
-
-
Save emidln/393eb7696516bc39de4a437d8067eb62 to your computer and use it in GitHub Desktop.
universal send-* and eval-* support for any mode
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(require 'evil) | |
(require 'cider) | |
(require 'cider-scratch) | |
(require 'highlight) | |
(require 'eval-sexp-fu) | |
(defmacro comment (&rest body) | |
"ignore the body and return nil" | |
nil) | |
;; make wrapping friendly to Clojure/Pixie/Hy | |
(with-eval-after-load "evil-lisp-state" | |
;; undef SPC k w so we can generalize it | |
(evil-leader/set-key "kw" nil) | |
;; wrap using SPC k w ([{"'* | |
(evil-leader/set-key "kw(" | |
(lambda (&optional arg) (interactive "P") (sp-wrap-with-pair "("))) | |
(evil-leader/set-key "kw[" | |
(lambda (&optional arg) (interactive "P") (sp-wrap-with-pair "["))) | |
(evil-leader/set-key "kw{" | |
(lambda (&optional arg) (interactive "P") (sp-wrap-with-pair "{"))) | |
(evil-leader/set-key "kw\"" | |
(lambda (&optional arg) (interactive "P") (sp-wrap-with-pair "\""))) | |
(evil-leader/set-key "kw'" | |
(lambda (&optional arg) (interactive "P") (sp-wrap-with-pair "'"))) | |
(evil-leader/set-key "kw*" | |
(lambda (&optional arg) (interactive "P") (sp-wrap-with-pair "*")))) | |
(defun emidln//emacs-lisp-eval-region-and-print (beg end) | |
(interactive) | |
(let* ((raw-result (with-output-to-string | |
(eval-region beg end standard-output))) | |
(result (when (>= (length raw-result) 1) | |
(substring raw-result 1 -1)))) | |
(when result | |
(cider--display-interactive-eval-result result end)))) | |
(defun emidln//emacs-lisp-send-region-to-ielm (beg end) | |
(interactive) | |
(let ((text (buffer-substring-no-properties beg end))) | |
(with-current-buffer "*ielm*" | |
(insert | |
(format "(progn %s)" text)) | |
(ielm-send-input)))) | |
(defun emidln//cider-eval-in-repl-no-focus (beg end) | |
"Insert FORM in the REPL buffer and eval it." | |
(let ((form (buffer-substring-no-properties beg end))) | |
(progn | |
(while (string-match "\\`[ \t\n\r]+\\|[ \t\n\r]+\\'" form) | |
(setq form (replace-match "" t t form))) | |
(with-current-buffer (cider-current-repl) | |
(let ((pt-max (point-max))) | |
(goto-char pt-max) | |
(insert (format "(do %s)" form)) | |
(indent-region pt-max (point)) | |
(cider-repl-return)))))) | |
;; if t; generic-eval falls through to generic-send | |
(defvar emidln--generic-eval-region-fallback-to-send t) | |
;; if t; generic-send falls through to generic-eval | |
(defvar emidln--generic-send-region-fallback-to-eval t) | |
(defvar emidln--generic-eval-region-alist | |
'((clojure-mode . cider-eval-region) | |
(emacs-lisp-mode . emidln//emacs-lisp-eval-region-and-print) | |
(lisp-mode . lisp-eval-region))) | |
(defvar emidln--generic-send-region-alist | |
'((clojure-mode . emidln//cider-eval-in-repl-no-focus) | |
(emacs-lisp-mode . emidln//emacs-lisp-send-region-to-ielm) | |
(python-mode . python-shell-send-region) | |
(elixir-mode . alchemist-iex-send-region))) | |
(defun emidln//get-eval-region-for-current-mode () | |
(interactive) | |
(catch 'break | |
(dolist (test emidln--generic-eval-region-alist) | |
(let ((mode (car test)) | |
(val (cdr test))) | |
(when (and (symbolp mode) | |
(derived-mode-p mode) | |
(symbolp val)) | |
(throw 'break val)))))) | |
(defun emidln//get-send-region-for-current-mode () | |
(interactive) | |
(catch 'break | |
(dolist (test emidln--generic-send-region-alist) | |
(let ((mode (car test)) | |
(val (cdr test))) | |
(when (and (symbolp mode) | |
(derived-mode-p mode) | |
(symbolp val)) | |
(throw 'break val)))))) | |
(defun emidln//generic-eval-region (beg end) | |
(interactive) | |
(let* ((f (or (emidln//get-eval-region-for-current-mode) | |
(when emidln--generic-eval-region-fallback-to-send | |
(emidln//get-send-region-for-current-mode))))) | |
(when (functionp f) | |
(funcall f beg end)))) | |
(defun emidln//generic-send-region (beg end) | |
(interactive) | |
(let ((f (or (emidln//get-send-region-for-current-mode) | |
(when emidln--generic-send-region-fallback-to-eval | |
(emidln//get-eval-region-for-current-mode))))) | |
(when (functionp f) | |
(funcall f beg end)))) | |
(evil-define-operator emidln//generic-evil-eval-operator (beg end) | |
(emidln//generic-eval-region beg end)) | |
(evil-define-operator emidln//generic-evil-send-operator (beg end) | |
(emidln//generic-eval-region beg end)) | |
(defun emidln//generic-eval-line () | |
"Evals the current line as though you did (kbd \"ma^ SPC meo $`a\")" | |
(interactive) | |
;; we don't use execute-kbd-macro here, because popping the mark kills the overlay | |
(save-excursion | |
(let* ((beg (progn (beginning-of-line) (point))) | |
(end (progn (end-of-line) (point)))) | |
(emidln//generic-eval-region beg end)))) | |
(defun emidln//generic-send-line () | |
"Sends the current line as though you did (kbd \"ma^ SPC mso $`a\")" | |
(interactive) | |
;; we don't use execute-kbd-macro here, because popping the mark kills the overlay | |
(save-excursion | |
(let* ((beg (progn (beginning-of-line) (point))) | |
(end (progn (end-of-line) (point)))) | |
(emidln//generic-send-region beg end)))) | |
(defun emidln//generic-eval-paragraph () | |
"Evals the current paragraph as though you did (kbd \"ma SPC meo ap`a\")" | |
(interactive) | |
;; we don't use execute-kbd-macro here, because popping the mark kills the overlay | |
(save-excursion | |
(let* ((graph (evil-inner-paragraph)) | |
(beg (first graph)) | |
(end (second graph))) | |
(emidln//generic-eval-region beg end)))) | |
;; Enable highlighting of the area to be eval'd | |
(define-eval-sexp-fu-flash-command emidln//generic-eval-region | |
(eval-sexp-fu-flash (cons beg end))) | |
(defun emidln//generic-send-paragraph () | |
"Sends the current paragraph as though you did (kbd \"ma SPC mso ap`a\")" | |
(interactive) | |
;; we don't use execute-kbd-macro here, because popping the mark kills the overlay | |
(save-excursion | |
(let* ((graph (evil-inner-paragraph)) | |
(beg (first graph)) | |
(end (second graph))) | |
(emidln//generic-send-region beg end)))) | |
(defun emidln//generic-eval-active-region-or-paragraph () | |
"Evals the current active region or paragraph" | |
(interactive) | |
(if (use-region-p) | |
(emidln//generic-eval-region (region-beginning) | |
(region-end)) | |
(emidln//generic-eval-paragraph))) | |
(defun emidln//generic-send-active-region-or-paragraph () | |
"Sends the current active region or paragraph" | |
(interactive) | |
(if (use-region-p) | |
(emidln//generic-send-region (region-beginning) | |
(region-end)) | |
(emidln//generic-send-paragraph))) | |
;; These eval/send buffer are mostly provided for modes which are too poor to have their own native funcs | |
(defun emidln//generic-eval-buffer () | |
"Evals the current buffer as though you did (kbd \"ma gg SPC meo VG`a\")" | |
(interactive) | |
;; we don't use execute-kbd-macro here, because popping the mark kills the overlay | |
(save-excursion | |
(let* ((beg (progn (beginning-of-buffer) | |
(point))) | |
(end (progn (end-of-buffer) | |
(point)))) | |
(emidln//generic-eval-region beg end)))) | |
(defun emidln//generic-send-buffer () | |
"Sends the current buffer as though you did (kbd \"ma gg SPC mso VG`a\")" | |
(interactive) | |
;; we don't use execute-kbd-macro here, because popping the mark kills the overlay | |
(save-excursion | |
(let* ((beg (progn (beginning-of-buffer) | |
(point))) | |
(end (progn (end-of-buffer) | |
(point)))) | |
(emidln//generic-send-region beg end)))) | |
(defun emidln//setup-emacs-lisp-mode () | |
(interactive) | |
;; treat - as part of words | |
(modify-syntax-entry ?- "w" emacs-lisp-mode-syntax-table) | |
;; enable SPC meo as eval operator | |
(evil-leader/set-key "meo" 'emidln//generic-evil-eval-operator) | |
;; enable SPC mso as send operator | |
(evil-leader/set-key "mso" 'emidln//generic-evil-send-operator) | |
;; setup custom keybindings | |
(define-key emacs-lisp-mode-map (kbd "C-c C-c") nil) | |
(define-key emacs-lisp-mode-map (kbd "C-c C-l") nil) | |
(define-key emacs-lisp-mode-map (kbd "C-c C-L") nil) | |
(define-key emacs-lisp-mode-map (kbd "C-c C-r") nil) | |
(evil-define-key 'normal emacs-lisp-mode-map | |
(kbd "C-c C-c") 'emidln//generic-eval-active-region-or-paragraph | |
(kbd "C-c C-l") 'emidln//generic-eval-line | |
(kbd "C-c C-L") 'eval-buffer | |
(kbd "C-c C-r") 'emidln//generic-eval-region) | |
(evil-define-key 'visual emacs-lisp-mode-map | |
(kbd "C-c C-c") 'emidln//generic-eval-active-region-or-paragraph) | |
(spacemacs/set-leader-keys-for-major-mode 'emacs-lisp-mode | |
"er" 'emidln//generic-eval-region | |
"ep" 'emidln//generic-eval-paragraph | |
"el" 'emidln//generic-eval-line | |
"eb" 'eval-buffer | |
"sp" 'emidln//generic-send-paragraph | |
"sl" 'emidln//generic-send-line | |
"sb" 'emidln//generic-send-buffer)) | |
(emidln//setup-emacs-lisp-mode) | |
(add-hook 'emacs-lisp-mode-hook 'emidln//setup-emacs-lisp-mode) | |
(defun emidln//setup-lisp-mode () | |
(interactive) | |
;; treat - as part of words | |
(modify-syntax-entry ?- "w" emacs-lisp-mode-syntax-table) | |
;; enable SPC meo as eval operator | |
(evil-leader/set-key "meo" 'emidln//generic-evil-eval-operator) | |
;; enable SPC mso as send operator | |
(evil-leader/set-key "mso" 'emidln//generic-evil-send-operator) | |
;; setup custom keybindings | |
(define-key lisp-mode-map (kbd "C-c C-c") nil) | |
(define-key lisp-mode-map (kbd "C-c C-l") nil) | |
(define-key lisp-mode-map (kbd "C-c C-L") nil) | |
(define-key lisp-mode-map (kbd "C-c C-r") nil) | |
(evil-define-key 'normal lisp-mode-map | |
(kbd "C-c C-c") 'emidln//generic-eval-active-region-or-paragraph | |
(kbd "C-c C-l") 'emidln//generic-eval-line | |
(kbd "C-c C-L") 'eval-buffer | |
(kbd "C-c C-r") 'emidln//generic-eval-region) | |
(evil-define-key 'visual lisp-mode-map | |
(kbd "C-c C-c") 'emidln//generic-eval-active-region-or-paragraph) | |
(spacemacs/set-leader-keys-for-major-mode 'lisp-mode | |
"er" 'emidln//generic-eval-region | |
"ep" 'emidln//generic-eval-paragraph | |
"el" 'emidln//generic-eval-line | |
"sp" 'emidln//generic-send-paragraph | |
"sl" 'emidln//generic-send-line | |
"sb" 'emidln//generic-send-buffer)) | |
(emidln//setup-lisp-mode) | |
(add-hook 'lisp-mode 'emidln//setup-lisp-mode) | |
(defun cider-show-cider-buffer () | |
(interactive) | |
(command-execute 'cider-switch-to-repl-buffer) | |
(command-execute 'cider-switch-to-last-clojure-buffer)) | |
(defun emidln//setup-clojure-mode () | |
(interactive) | |
;; treat - as part of words | |
(modify-syntax-entry ?- "w" clojure-mode-syntax-table) | |
;; enable SPC meo as eval operator | |
(evil-leader/set-key "meo" 'emidln//generic-evil-eval-operator) | |
(evil-leader/set-key "mso" 'emidln//generic-evil-send-operator) | |
;; setup custom bindings | |
(define-key cider-mode-map (kbd "C-c C-c") nil) | |
(define-key cider-mode-map (kbd "C-c C-l") nil) | |
(define-key cider-mode-map (kbd "C-c C-L") nil) | |
(define-key cider-mode-map (kbd "C-c C-i") nil) | |
(define-key cider-clojure-interaction-mode-map (kbd "C-c C-l") nil) | |
(define-key cider-clojure-interaction-mode-map (kbd "C-c C-L") nil) | |
(evil-define-key 'normal cider-mode-map | |
(kbd "C-c C-c") 'emidln//generic-eval-active-region-or-paragraph | |
(kbd "C-c C-l") 'emidln//generic-eval-line | |
(kbd "C-c C-L") 'cider-eval-buffer | |
(kbd "C-c C-r") 'emidln//generic-eval-region) | |
(evil-define-key 'visual cider-mode-map | |
(kbd "C-c C-c") 'emidln//generic-eval-active-region-or-paragraph) | |
(evil-define-key 'normal cider-clojure-interaction-mode-map | |
(kbd "C-c C-l") 'emidln//generic-eval-line | |
(kbd "C-c C-L") 'cider-eval-buffer) | |
(spacemacs/set-leader-keys-for-major-mode 'clojure-mode | |
"ep" 'emidln//generic-eval-paragraph | |
"sp" 'emidln//generic-send-paragraph | |
"sl" 'emidln//generic-send-line | |
"el" 'emidln//generic-eval-line | |
"sb" 'emidln//generic-send-buffer | |
"eb" 'cider-eval-buffer | |
"sS" 'cider-show-cider-buffer | |
"dl" 'cider-inspect-last-result) | |
(comment | |
(define-key cider-mode-map (kbd "C-c C-c") 'spacemacs//generic-eval-active-region-or-paragraph) | |
(define-key cider-mode-map (kbd "C-c C-l") 'spacemacs//generic-eval-line) | |
(define-key cider-mode-map (kbd "C-c C-L") 'cider-load-buffer) | |
(define-key cider-mode-map (kbd "C-c C-i") 'cider-inspect-last-result) | |
(define-key cider-clojure-interaction-mode-map (kbd "C-c C-l") 'spacemacs//generic-eval-line) | |
(define-key cider-clojure-interaction-mode-map (kbd "C-c C-L") 'cider-load-buffer))) | |
(emidln//setup-clojure-mode) | |
(with-eval-after-load "clojure-mode" | |
(emidln//setup-clojure-mode)) | |
(defadvice cider-scratch (after cider-scratch-advise activate) | |
(with-current-buffer (get-buffer cider-scratch-buffer-name) | |
(clojure-mode) | |
(cider-jack-in))) | |
(defun emidln//setup-python-mode () | |
(interactive) | |
;; enable SPC meo as eval operator | |
(evil-leader/set-key "meo" 'emidln//generic-evil-eval-operator) | |
(evil-leader/set-key "mso" 'emidln//generic-evil-send-operator) | |
;; setup custom bindings | |
(define-key python-mode-map (kbd "C-c C-c") 'emidln//generic-eval-active-region-or-paragraph) | |
(define-key python-mode-map (kbd "C-c C-l") 'emidln//generic-eval-line) | |
(define-key python-mode-map (kbd "C-c C-L") 'python-shell-send-buffer) | |
(spacemacs/set-leader-keys-for-major-mode 'python-mode | |
"ep" 'emidln//generic-eval-paragraph | |
"sp" 'emidln//generic-send-paragraph | |
"sl" 'emidln//generic-send-line | |
"sb" 'emidln//generic-send-buffer | |
"eb" 'emidln//generic-eval-buffer | |
"el" 'emidln//generic-eval-line)) | |
;;(emidln//setup-python-mode) | |
(with-eval-after-load "python-mode" | |
(emidln//setup-python-mode)) | |
(defun emidln//setup-elixir-mode () | |
(interactive) | |
;; enable SPC meo as eval operator | |
(evil-leader/set-key "meo" 'emidln//generic-evil-eval-operator) | |
(evil-leader/set-key "mso" 'emidln//generic-evil-send-operator) | |
;; setup custom keybindings | |
(define-key elixir-mode-map (kbd "C-c C-c") nil) | |
(define-key elixir-mode-map (kbd "C-c C-l") nil) | |
(define-key elixir-mode-map (kbd "C-c C-L") nil) | |
(define-key elixir-mode-map (kbd "C-c C-r") nil) | |
(evil-define-key 'normal elixir-mode-map | |
(kbd "C-c C-c") 'emidln//generic-eval-active-region-or-paragraph | |
(kbd "C-c C-l") 'emidln//generic-eval-line | |
(kbd "C-c C-L") 'emidln//generic-eval-buffer | |
(kbd "C-c C-r") 'emidln//generic-eval-region) | |
(spacemacs/set-leader-keys-for-major-mode 'elixir-mode-map | |
"er" 'emidln//generic-eval-region | |
"ep" 'emidln//generic-eval-paragraph | |
"el" 'emidln//generic-eval-line | |
"eb" 'emidln//generic-eval-buffer | |
"sp" 'emidln//generic-send-paragraph | |
"sl" 'emidln//generic-send-line | |
"sb" 'emidln//generic-send-buffer)) | |
;(emidln//setup-elixir-mode) | |
(with-eval-after-load "elixir-mode" | |
(emidln//setup-elixir-mode)) | |
(which-key-add-key-based-replacements | |
"SPC m s b" "load buffer" | |
"SPC m s B" "send buffer and focus" | |
"SPC m s c" "connect" | |
"SPC m s e" "eval last sexp" | |
"SPC m s E" "send last sexp and focus" | |
"SPC m s f" "send function" | |
"SPC m s F" "send function and focus" | |
"SPC m s i" "start repl" | |
"SPC m s I" "start cljs repl" | |
"SPC m s l" "eval line" | |
"SPC m e l" "eval line" | |
"SPC m s n" "send ns form" | |
"SPC m s N" "send ns form and focus" | |
"SPC m s o" "switch repls" | |
"SPC m s p" "eval paragraph" | |
"SPC m e p" "eval paragraph" | |
"SPC m s q" "quit repl" | |
"SPC m s r" "send region" | |
"SPC m s R" "send region and focus" | |
"SPC m s s" "focus repl" | |
"SPC m s S" "show repl" | |
"SPC m s x" "refresh repl" | |
"SPC m d l" "inspect last result") | |
;; quick window navigation vim-style | |
(evil-global-set-key 'normal (kbd "C-w w") 'next-multiframe-window) | |
(evil-global-set-key 'normal (kbd "C-w C-w") 'next-multiframe-window) | |
(evil-global-set-key 'emacs (kbd "C-w w") 'next-multiframe-window) | |
(evil-global-set-key 'emacs (kbd "C-w C-w") 'next-multiframe-window) | |
(spacemacs/set-leader-keys (kbd "ww") 'next-multiframe-window) | |
;; make text-scale-increase/text-scale-decrease global across buffers | |
(defadvice text-scale-increase (around all-buffers (arg) activate) | |
(dolist (buffer (buffer-list)) | |
(with-current-buffer buffer | |
ad-do-it))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment