Skip to content

Instantly share code, notes, and snippets.

@emidln
Last active June 27, 2018 01:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save emidln/393eb7696516bc39de4a437d8067eb62 to your computer and use it in GitHub Desktop.
Save emidln/393eb7696516bc39de4a437d8067eb62 to your computer and use it in GitHub Desktop.
universal send-* and eval-* support for any mode
(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