Moving all of my Emacs-related files into their own directory at the root of this repository.
		
			
				
	
	
		
			115 lines
		
	
	
	
		
			3.9 KiB
		
	
	
	
		
			EmacsLisp
		
	
	
	
	
	
			
		
		
	
	
			115 lines
		
	
	
	
		
			3.9 KiB
		
	
	
	
		
			EmacsLisp
		
	
	
	
	
	
| ;;; 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
 |