diff options
Diffstat (limited to 'emacs/.emacs.d/wpc/entr.el')
-rw-r--r-- | emacs/.emacs.d/wpc/entr.el | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/emacs/.emacs.d/wpc/entr.el b/emacs/.emacs.d/wpc/entr.el new file mode 100644 index 000000000000..ac2a5812c328 --- /dev/null +++ b/emacs/.emacs.d/wpc/entr.el @@ -0,0 +1,115 @@ +;;; entr.el --- Working with terminals and entr -*- lexical-binding: t -*- +;; Author: William Carroll <wpcarro@gmail.com> + +;;; Commentary: +;; Help make watch commands easier. +;; +;; This should be entirely temporary because in reality we should be able to use +;; Emacs's buffer watching abilities to run commands. +;; TODO: Explore Emacs integration that obviates `entr`. + +;;; Code: + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Dependencies +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(require 'f) +(require 'buffer) +(require 'prelude) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Library +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; TODO: Support a generic file-watcher for commonly used languages. +(defconst entr/major-mode->save-handler + '((python-mode . entr/handle-python3)) + "Mapping of language to the `after-save-hook' function it should register.") + +(defun entr/shell-command-to-buffer (cmd name) + "Run CMD in a shell and output to the buffer NAME. +The buffer is a find-or-create operation. +The buffer is erased between runs with `erase-buffer'." + (let ((b (buffer/find-or-create name))) + (with-current-buffer b (erase-buffer)) + (shell-command cmd b) + (buffer/show b))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Python +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; TODO: This should be a top-level function. +(defconst entr/handle-python3 + (lambda () + (entr/shell-command-to-buffer + (format "python3 %s" (buffer-file-name)) + "*python3*")) + "Function that is registered as the `after-save-hook' for python3.") + +(defun entr/register-python3 () + "Register a buffer-local `after-save-hook' for calling python3 with filename." + (interactive) + (add-hook 'after-save-hook entr/handle-python3 nil t)) + +(defun entr/deregister-python3 () + "Remove the buffer-local `after-save-hook' for python3." + (interactive) + (remove-hook 'after-save-hook entr/handle-python3 t)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Protobuf +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(defun entr/format-protobuf () + "Formats a protobuf buffer." + (call-interactively #'clang-format)) + +;; TODO: Run this automatically with .proto file extensions. Do this after +;; verifying that `clang-format' complies with Google's style guide. +(defun entr/register-protobuf () + "Register a buffer-local `before-save-hook' for formatting protobuf buffers." + (interactive) + (add-hook + 'before-save-hook + #'entr/format-protobuf + nil + t)) + +;; TODO: Is there an interactive way to remove hooks in Emacs? +(defun entr/deregister-protobuf () + "Remove the buffer-local `before-save-hook' for protobuf." + (interactive) + (remove-hook + 'before-save-hook + #'entr/format-protobuf + t)) + +;; TODO: Support this. Currently the `intern' call is the problem. +;; (defun entr/ivy-remove-hook (hook) +;; "Use Counsel to remove a handler from HOOK." +;; (interactive) +;; (ivy-read +;; "Remove hook: " +;; (intern (prelude/prompt "Hook name: ")) +;; :action (lambda (x) (message x)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Miscellaneous +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(defun entr/command (command) + "Create a terminal instance with entr running COMMAND. +COMMAND is a function that is called with the current filename." + ;; Algorithm: + ;; - Get buffer's filename. + ;; - Open terminator running: `echo entr <filename> | entr <command>`. + (interactive) + (with-current-buffer (current-buffer) + (let ((filename (buffer-file-name))) + (prelude/inspect + (format "echo %s | entr %s" filename (funcall command filename)))))) + +(provide 'entr) +;;; entr.el ends here |