diff --git a/emacs/.emacs.d/init.org b/emacs/.emacs.d/init.org index 62ba386..f24638b 100755 --- a/emacs/.emacs.d/init.org +++ b/emacs/.emacs.d/init.org @@ -6504,6 +6504,164 @@ error: (add-to-list 'compilation-error-regexp-alist '("\\([^[:space:]]+\\):\\([[:digit:]]+\\)$" 1 2))) #+END_SRC +* Run-command +A [[https://github.com/bard/emacs-run-command][useful library]] that lets you define dynamic commands based on the +current buffer: +#+begin_src emacs-lisp + (use-package run-command + :straight (run-command :host github :repo "bard/emacs-run-command" + :fork (:host github :repo "jdormit/emacs-run-command")) + :config + (defun run-command-recipe-terraform () + (when (directory-files default-directory + nil + (rx (one-or-more any) + ".tf" + eol)) + (list + (list :command-name "plan" + :command-line "terraform plan") + (list :command-name "apply" + :command-line "terraform apply") + (list :command-name "destroy" + :command-line "terraform destroy")))) + + (defvar-local run-command-local-commands nil) + (put 'run-command-local-commands 'safe-local-variable (lambda (_) t)) + + (defun run-command-recipe-local () + (when run-command-local-commands + (mapcar (cl-function + (lambda ((name . spec)) + (let ((name (if (symbolp name) (symbol-name name) name))) + (list :command-name name + :command-line spec)))) + run-command-local-commands))) + + (defun run-command-recipe-package-json--get-scripts (package-json-file) + "Extract NPM scripts from `package-json-file'." + (with-temp-buffer + (insert-file-contents package-json-file) + (let* ((json-data (json-parse-buffer)) + (script-hash (gethash "scripts" json-data)) + (scripts '())) + (when script-hash + (maphash (lambda (key _value) (push key scripts)) script-hash)) + scripts))) + + (defun run-command-recipe-package-json () + (when-let* ((project-dir + (locate-dominating-file default-directory "package.json")) + (scripts + (run-command-recipe-package-json--get-scripts (concat project-dir "package.json"))) + (script-runner + (if (file-exists-p (concat project-dir "yarn.lock")) "yarn" "npm"))) + (mapcar (lambda (script) + (list :command-name script + :command-line (concat script-runner " run " script) + :display script + :working-dir project-dir)) + scripts))) + + (defun makefile-target-list-default (makefile) + "Return the target list for MAKEFILE by parsing it." + (let (targets) + (with-temp-buffer + (insert-file-contents makefile) + (goto-char (point-min)) + (while (re-search-forward "^\\([^: \n]+\\) *:\\(?: \\|$\\)" nil t) + (let ((str (match-string 1))) + (unless (string-match "^\\." str) + (push str targets))))) + (nreverse targets))) + + (defun run-command-recipe-makefile () + (when-let* ((project-dir (locate-dominating-file default-directory "Makefile")) + (makefile (concat project-dir "Makefile")) + (targets (makefile-target-list-default makefile))) + (mapcar (lambda (target) + (list :command-name target + :command-line (concat "make " target) + :display target + :working-dir project-dir)) + targets))) + + (defun run-command-recipe-project () + (when (projectile-project-root) + (mapcar (lambda (cmd) + (when-let ((cmd-val (symbol-value + (intern + (format "projectile-project-%s-cmd" cmd))))) + (list :command-name cmd + :command-line cmd-val + :working-dir (projectile-compilation-dir)))) + '("test" "run" "compilation" "configure" "install" "package")))) + + (defvar-local run-command-project-local-commands nil) + (put 'run-command-project-local-commands 'safe-local-variable (lambda (_) t)) + + (defun run-command-recipe-project-local () + (when (and run-command-project-local-commands (projectile-project-root)) + (mapcar (cl-function + (lambda ((name . spec)) + (let ((name (if (symbolp name) (symbol-name name) name))) + (list :command-name name + :command-line spec + :working-dir (projectile-compilation-dir))))) + run-command-project-local-commands))) + + + (defun run-command-recipe-executables () + (let* ((buffer-file (buffer-file-name)) + (executable-p (and buffer-file (file-executable-p buffer-file)))) + (list + (when executable-p + (list + :command-name "run-buffer-file" + :command-line buffer-file + :display "Run this buffer's file")) + (when (and executable-p (executable-find "entr")) + (list + :command-name "run-buffer-file-watch" + :command-line (format "echo %s | entr -c /_" buffer-file) + :display "Run this buffer's file (re-run on each save)"))))) + + (defun run-command-recipe-obelix () + (when-let* ((config (or (locate-dominating-file default-directory "obelix.json") + (locate-dominating-file default-directory "obelix.edn"))) + (dir (file-name-directory config))) + (list + (list :command-name "build" + :command-line "obelix build" + :working-dir dir) + (list :command-name "serve" + :command-line "obelix serve" + :working-dir dir)))) + + (defun run-command-recipe-kustomize () + (when-let* ((kustomization (locate-dominating-file default-directory "kustomization.yaml")) + (dir (file-name-directory kustomization))) + (list + (list :command-name "build" + :command-line "kustomize build --enable_alpha_plugins" + :working-dir dir)))) + + :general + (leader-map "\"" #'run-command) + (run-command-term-minor-mode-map [remap recompile] #'run-command-term-recompile) + :custom + (run-command-run-method 'term) + (run-command-recipes '(run-command-recipe-terraform + run-command-recipe-local + run-command-recipe-package-json + run-command-recipe-makefile + run-command-recipe-project + run-command-recipe-project-local + run-command-recipe-executables + run-command-recipe-obelix + run-command-recipe-kustomize))) +#+end_src + * Wallabag [[https://github.com/jdormit/emacs-wallabag-client][My Wallabag client]] is still a WIP, but it is useful enough to pull in right now: