Replace feature/eval build system with def-menu!
This commit is contained in:
parent
63d5fec4aa
commit
d0fcb23314
15 changed files with 51 additions and 160 deletions
|
@ -1,13 +1,12 @@
|
||||||
#+TITLE: :feature eval
|
#+TITLE: :feature eval
|
||||||
|
|
||||||
This modules adds support for REPLs, build tasks and code evaluation.
|
This modules adds support for evaluating code from inside Emacs. This includes REPLs and direct access to the interpreters and compilers of many languages.
|
||||||
|
|
||||||
* Table of Contents :TOC:
|
* Table of Contents :TOC:
|
||||||
- [[#install][Install]]
|
- [[#install][Install]]
|
||||||
- [[#usage][Usage]]
|
- [[#usage][Usage]]
|
||||||
- [[#configuration][Configuration]]
|
- [[#configuration][Configuration]]
|
||||||
- [[#repls][REPLs]]
|
- [[#repls][REPLs]]
|
||||||
- [[#build-tasks][Build Tasks]]
|
|
||||||
- [[#code-evaluation][Code Evaluation]]
|
- [[#code-evaluation][Code Evaluation]]
|
||||||
|
|
||||||
* Install
|
* Install
|
||||||
|
@ -20,15 +19,8 @@ Check the README.org in that language's module for details.
|
||||||
Invoked via:
|
Invoked via:
|
||||||
+ ~:repl~ (evil ex-command)
|
+ ~:repl~ (evil ex-command)
|
||||||
+ =<leader> o r= in normal mode (or visual mode, which sends the selection to the open REPL)
|
+ =<leader> o r= in normal mode (or visual mode, which sends the selection to the open REPL)
|
||||||
+ ~M-x +eval/repl~
|
+ ~M-x +eval/open-repl~
|
||||||
+ ~M-x +eval/repl-send-region~ while a selection (and REPL) is active
|
+ ~M-x +eval/send-region-to-repl~ while a selection (and REPL) is active
|
||||||
|
|
||||||
+ *Build Tasks*
|
|
||||||
You will be prompted to select a task. Only the ones that meet the predicate will be listed.
|
|
||||||
+ ~:build~ (evil ex-command)
|
|
||||||
+ =M-b= (by default)
|
|
||||||
+ =<leader> o b= in normal mode
|
|
||||||
+ ~M-x +eval/build~
|
|
||||||
|
|
||||||
+ *Code Evaluation*
|
+ *Code Evaluation*
|
||||||
Quickrun can be invoked via:
|
Quickrun can be invoked via:
|
||||||
|
@ -60,35 +52,6 @@ FUNCTION must return the repl buffer. Any window changes are ignored, then hande
|
||||||
(set! :repl 'emacs-lisp-mode #'+emacs-lisp/repl)
|
(set! :repl 'emacs-lisp-mode #'+emacs-lisp/repl)
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
|
|
||||||
** Build Tasks
|
|
||||||
A build task is little more than a major-mode-local interactive command that performs a task, such as compiling the current project or running unit tests. A predicate function can be supplied to ensure a command is only available when it is appropriate.
|
|
||||||
|
|
||||||
#+BEGIN_SRC emacs-lisp
|
|
||||||
(defun +lua/run-love ()
|
|
||||||
"Run the current project in love 10.0."
|
|
||||||
(async-shell-command
|
|
||||||
(format "/usr/bin/love %s"
|
|
||||||
(shell-quote-argument (doom-project-root)))))
|
|
||||||
|
|
||||||
(defun +lua/build ()
|
|
||||||
"Run a build script in the project root."
|
|
||||||
(let ((default-directory (doom-project-root)))
|
|
||||||
(compile "luajit build.lua")))
|
|
||||||
|
|
||||||
(defun +lua/generate-docs ()
|
|
||||||
"Generate project documentation."
|
|
||||||
(let ((default-directory (doom-project-root)))
|
|
||||||
(compile "luadoc *.lua")))
|
|
||||||
|
|
||||||
(defun +lua-love-p ()
|
|
||||||
"Returns non-nil if the current project is a love project."
|
|
||||||
(doom-project-has! (and "main.lua" "config.lua")))
|
|
||||||
|
|
||||||
(set! :build 'run 'lua-mode #'+lua/run-love :when (+lua-love-p))
|
|
||||||
(set! :build 'build-project 'lua-mode #'+lua/build :when (+lua-love-p))
|
|
||||||
(set! :build 'generate-docs 'lua-mode #'+lua/generate-docs)
|
|
||||||
#+END_SRC
|
|
||||||
|
|
||||||
** Code Evaluation
|
** Code Evaluation
|
||||||
Run regions or entire buffers with [[https://github.com/syohex/emacs-quickrun][Quickrun]]. Output will be sent to a popup window.
|
Run regions or entire buffers with [[https://github.com/syohex/emacs-quickrun][Quickrun]]. Output will be sent to a popup window.
|
||||||
|
|
||||||
|
|
|
@ -1,45 +0,0 @@
|
||||||
;;; feature/eval/autoload/build.el -*- lexical-binding: t; -*-
|
|
||||||
|
|
||||||
(defvar-local +eval-last-builder nil
|
|
||||||
"The last builder run in the current buffer.")
|
|
||||||
|
|
||||||
(defvar +eval-current-builder nil
|
|
||||||
"The spec for the currently running builder. Available from inside builder
|
|
||||||
functions.")
|
|
||||||
|
|
||||||
(defun +eval--read-builder ()
|
|
||||||
(when-let (builders
|
|
||||||
(cl-remove-if-not
|
|
||||||
(lambda (plist)
|
|
||||||
(if-let (pred (plist-get plist :when))
|
|
||||||
(and (or (symbolp pred)
|
|
||||||
(functionp pred))
|
|
||||||
(funcall pred))
|
|
||||||
t))
|
|
||||||
(cl-delete-duplicates
|
|
||||||
(reverse (cdr (assq major-mode +eval-builders)))
|
|
||||||
:key 'car)
|
|
||||||
:key 'cdr))
|
|
||||||
(if (= (length builders) 1)
|
|
||||||
(car builders)
|
|
||||||
(when-let (builder (completing-read "Build: " (mapcar #'car builders) nil t))
|
|
||||||
(assq (intern builder) builders)))))
|
|
||||||
|
|
||||||
;;;###autoload
|
|
||||||
(defun +eval/build (builder)
|
|
||||||
"TODO"
|
|
||||||
(interactive
|
|
||||||
(list (or +eval-last-builder
|
|
||||||
(+eval--read-builder)
|
|
||||||
(error "No builder for this buffer"))))
|
|
||||||
(unless builder
|
|
||||||
(error "Builder not found in registered builders"))
|
|
||||||
(let ((name (car builder))
|
|
||||||
(fn (plist-get (cdr builder) :fn)))
|
|
||||||
(message "Running %s" name)
|
|
||||||
(if (or (functionp fn)
|
|
||||||
(and (symbolp fn) (fboundp fn)))
|
|
||||||
(let ((+eval-current-builder builder))
|
|
||||||
(funcall fn))
|
|
||||||
(error "'%s' builder is invalid" name))))
|
|
||||||
|
|
|
@ -4,22 +4,22 @@
|
||||||
(defun +eval/buffer ()
|
(defun +eval/buffer ()
|
||||||
"Evaluate the whole buffer."
|
"Evaluate the whole buffer."
|
||||||
(interactive)
|
(interactive)
|
||||||
(cond ((assq major-mode +eval-runners-alist)
|
(cond ((assq major-mode +eval-runners)
|
||||||
(+eval/region (point-min) (point-max)))
|
(+eval/region (point-min) (point-max)))
|
||||||
(t (quickrun))))
|
(t (quickrun))))
|
||||||
|
|
||||||
;;;###autoload
|
;;;###autoload
|
||||||
(defun +eval/region (beg end)
|
(defun +eval/region (beg end)
|
||||||
"Evaluate a region and, if large enough, prints its output to a popup buffer (if an
|
"Evaluate a region between BEG and END and display the output."
|
||||||
elisp buffer). Otherwise forward the region to Quickrun."
|
|
||||||
(interactive "r")
|
(interactive "r")
|
||||||
(let ((load-file-name buffer-file-name))
|
(let ((load-file-name buffer-file-name))
|
||||||
(if-let (runner (cdr (assq major-mode +eval-runners-alist)))
|
(if-let (runner (cdr (assq major-mode +eval-runners)))
|
||||||
(funcall runner beg end)
|
(funcall runner beg end)
|
||||||
(quickrun-region beg end))))
|
(quickrun-region beg end))))
|
||||||
|
|
||||||
;;;###autoload
|
;;;###autoload
|
||||||
(defun +eval/region-and-replace (beg end)
|
(defun +eval/region-and-replace (beg end)
|
||||||
|
"Evaluation a region between BEG and END, and replace it with the result."
|
||||||
(interactive "r")
|
(interactive "r")
|
||||||
(cond ((eq major-mode 'emacs-lisp-mode)
|
(cond ((eq major-mode 'emacs-lisp-mode)
|
||||||
(kill-region beg end)
|
(kill-region beg end)
|
||||||
|
|
|
@ -18,5 +18,5 @@
|
||||||
:move-point nil
|
:move-point nil
|
||||||
(interactive "<r><!>")
|
(interactive "<r><!>")
|
||||||
(if (evil-normal-state-p)
|
(if (evil-normal-state-p)
|
||||||
(+eval/repl)
|
(+eval/open-repl)
|
||||||
(+eval/repl-send-region beg end bang)))
|
(+eval/send-region-to-repl beg end bang)))
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
t))))
|
t))))
|
||||||
|
|
||||||
;;;###autoload
|
;;;###autoload
|
||||||
(defun +eval/repl ()
|
(defun +eval/open-repl ()
|
||||||
"Opens (or reopens) the REPL associated with the current major-mode and place
|
"Opens (or reopens) the REPL associated with the current major-mode and place
|
||||||
the cursor at the prompt."
|
the cursor at the prompt."
|
||||||
(interactive)
|
(interactive)
|
||||||
|
@ -36,7 +36,7 @@ the cursor at the prompt."
|
||||||
t)))
|
t)))
|
||||||
|
|
||||||
;;;###autoload
|
;;;###autoload
|
||||||
(defun +eval/repl-send-region (beg end &optional auto-execute-p)
|
(defun +eval/send-region-to-repl (beg end &optional auto-execute-p)
|
||||||
"REPL must be open! Sends a selected region to it. If AUTO-EXECUTE-P, then
|
"REPL must be open! Sends a selected region to it. If AUTO-EXECUTE-P, then
|
||||||
execute it immediately after."
|
execute it immediately after."
|
||||||
(interactive "r")
|
(interactive "r")
|
||||||
|
|
|
@ -1,39 +1,15 @@
|
||||||
;;; feature/eval/config.el -*- lexical-binding: t; -*-
|
;;; feature/eval/config.el -*- lexical-binding: t; -*-
|
||||||
|
|
||||||
;;
|
|
||||||
;; Code building
|
|
||||||
;;
|
|
||||||
|
|
||||||
(defvar +eval-builders nil
|
|
||||||
"A nested alist, mapping major modes to build function plists. Used by
|
|
||||||
`+eval/build' and filled with the `:build' setting.")
|
|
||||||
|
|
||||||
(def-setting! :build (name modes fn &rest plist)
|
|
||||||
"Define a build function (FN) for MODES (can be major or minor) called NAME.
|
|
||||||
|
|
||||||
PLIST accepts the following properties:
|
|
||||||
|
|
||||||
:when FORM A predicate to determine if the builder is appropriate for this
|
|
||||||
buffer."
|
|
||||||
`(dolist (mode ',(doom-enlist (doom-unquote modes)) +eval-builders)
|
|
||||||
(unless (assq mode +eval-builders)
|
|
||||||
(push (list mode) +eval-builders))
|
|
||||||
(cl-pushnew (cons ,name (append (list :fn ,fn) (list ,@plist)))
|
|
||||||
(cdr (assq mode +eval-builders))
|
|
||||||
:test #'eq :key #'car)))
|
|
||||||
|
|
||||||
|
|
||||||
;;
|
;;
|
||||||
;; REPLs
|
;; REPLs
|
||||||
;;
|
;;
|
||||||
|
|
||||||
(defvar +eval-repls nil
|
(defvar +eval-repls nil
|
||||||
"An alist mapping major modes to plists that describe REPLs. Used by
|
"An alist mapping major modes to plists that describe REPLs. Used by
|
||||||
`+eval/repl' and filled with the `:repl' setting.")
|
`+eval/open-repl' and filled with the `:repl' setting.")
|
||||||
|
|
||||||
(define-minor-mode +eval-repl-mode
|
(define-minor-mode +eval-repl-mode
|
||||||
"A minor mode for REPL buffers."
|
"A minor mode for REPL buffers.")
|
||||||
:init-value nil)
|
|
||||||
|
|
||||||
(def-setting! :repl (mode command)
|
(def-setting! :repl (mode command)
|
||||||
"Define a REPL for a mode. MODE is a major mode symbol and COMMAND is a
|
"Define a REPL for a mode. MODE is a major mode symbol and COMMAND is a
|
||||||
|
@ -53,7 +29,7 @@ function that creates and returns the REPL buffer."
|
||||||
(setq eval-expression-print-length nil
|
(setq eval-expression-print-length nil
|
||||||
eval-expression-print-level nil)
|
eval-expression-print-level nil)
|
||||||
|
|
||||||
(defvar +eval-runners-alist nil
|
(defvar +eval-runners nil
|
||||||
"Alist mapping major modes to interactive runner functions.")
|
"Alist mapping major modes to interactive runner functions.")
|
||||||
|
|
||||||
(def-setting! :eval (mode command)
|
(def-setting! :eval (mode command)
|
||||||
|
@ -67,10 +43,10 @@ function that creates and returns the REPL buffer."
|
||||||
3. If MODE is not a string and COMMAND is an alist, see `quickrun-add-command':
|
3. If MODE is not a string and COMMAND is an alist, see `quickrun-add-command':
|
||||||
(quickrun-add-command MODE COMMAND :mode MODE).
|
(quickrun-add-command MODE COMMAND :mode MODE).
|
||||||
4. If MODE is not a string and COMMANd is a symbol, add it to
|
4. If MODE is not a string and COMMANd is a symbol, add it to
|
||||||
`+eval-runners-alist', which is used by `+eval/region'."
|
`+eval-runners', which is used by `+eval/region'."
|
||||||
(let ((command (doom-unquote command)))
|
(let ((command (doom-unquote command)))
|
||||||
(cond ((symbolp command)
|
(cond ((symbolp command)
|
||||||
`(push (cons ,mode ',command) +eval-runners-alist))
|
`(push (cons ,mode ',command) +eval-runners))
|
||||||
((stringp command)
|
((stringp command)
|
||||||
`(after! quickrun
|
`(after! quickrun
|
||||||
(push (cons ,mode ',command)
|
(push (cons ,mode ',command)
|
||||||
|
|
|
@ -29,12 +29,7 @@
|
||||||
|
|
||||||
|
|
||||||
(def-package! dockerfile-mode
|
(def-package! dockerfile-mode
|
||||||
:mode "/Dockerfile$"
|
:mode "/Dockerfile$")
|
||||||
:config
|
|
||||||
;; TODO
|
|
||||||
;; (set! :build 'build-image 'dockerfile-mode '+data/dockerfile-build
|
|
||||||
;; :when '+data-dockerfile-p)
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
;; For ROM hacking or debugging
|
;; For ROM hacking or debugging
|
||||||
|
|
|
@ -1,9 +1,5 @@
|
||||||
;;; lang/go/autoload.el -*- lexical-binding: t; -*-
|
;;; lang/go/autoload.el -*- lexical-binding: t; -*-
|
||||||
|
|
||||||
;;;###autoload
|
|
||||||
;; TODO (defun +go/build ())
|
|
||||||
|
|
||||||
|
|
||||||
;;
|
;;
|
||||||
;; Tests
|
;; Tests
|
||||||
;;
|
;;
|
||||||
|
|
|
@ -184,17 +184,3 @@
|
||||||
:modes (html-mode css-mode web-mode js2-mode markdown-mode)
|
:modes (html-mode css-mode web-mode js2-mode markdown-mode)
|
||||||
:files "package.json")
|
:files "package.json")
|
||||||
|
|
||||||
(def-project-mode! +javascript-lb6-mode
|
|
||||||
:modes (web-mode js2-mode nxml-mode markdown-mode)
|
|
||||||
:match "\\.lb\\(action\\|ext\\)/"
|
|
||||||
:init
|
|
||||||
;; TODO
|
|
||||||
;; (when IS-MAC
|
|
||||||
;; (set! :build 'launchbar-action '+javascript-lb6-mode
|
|
||||||
;; (lambda ()
|
|
||||||
;; (when-let (dir (f-traverse-upwards (lambda (f) (f-ext? f "lbaction"))))
|
|
||||||
;; (shell-command (format "open '%s'" dir))))
|
|
||||||
;; :when
|
|
||||||
;; (lambda () (f-traverse-upwards (lambda (f) (f-ext? f "lbaction"))))))
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
|
@ -7,3 +7,13 @@
|
||||||
(lua-start-process "lua" "lua")
|
(lua-start-process "lua" "lua")
|
||||||
(pop-to-buffer lua-process-buffer))
|
(pop-to-buffer lua-process-buffer))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun +lua/run-love-game ()
|
||||||
|
"Run the current project with Love2D."
|
||||||
|
(interactive)
|
||||||
|
(async-shell-command
|
||||||
|
(format "%s %s"
|
||||||
|
(or (executable-find "love")
|
||||||
|
(if IS-MAC "open -a love.app"))
|
||||||
|
(shell-quote-argument (doom-project-root)))))
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,16 @@
|
||||||
(set! :repl 'lua-mode #'+lua/repl)
|
(set! :repl 'lua-mode #'+lua/repl)
|
||||||
|
|
||||||
;; sp's lua-specific rules are obnoxious, so we disable them
|
;; sp's lua-specific rules are obnoxious, so we disable them
|
||||||
(setq sp-pairs (delete (assq 'lua-mode sp-pairs) sp-pairs)))
|
(setq sp-pairs (delete (assq 'lua-mode sp-pairs) sp-pairs))
|
||||||
|
|
||||||
|
(def-menu! +lua/build-menu
|
||||||
|
"Build/compilation commands for `lua-mode' buffers."
|
||||||
|
'(("Run Love app" :exec +lua/run-love-game :when +lua-love-mode))
|
||||||
|
:prompt "Build tasks: ")
|
||||||
|
|
||||||
|
(map! :map lua-mode-map
|
||||||
|
:localleader
|
||||||
|
"b" #'+lua/build-menu))
|
||||||
|
|
||||||
|
|
||||||
(def-package! company-lua
|
(def-package! company-lua
|
||||||
|
@ -32,9 +41,5 @@
|
||||||
|
|
||||||
(def-project-mode! +lua-love-mode
|
(def-project-mode! +lua-love-mode
|
||||||
:modes (lua-mode markdown-mode json-mode)
|
:modes (lua-mode markdown-mode json-mode)
|
||||||
:files (and "main.lua" "conf.lua")
|
:files (and "main.lua" "conf.lua"))
|
||||||
:init
|
|
||||||
(set! :build 'run-love-app '+lua-love-mode
|
|
||||||
(lambda ()
|
|
||||||
(async-shell-command (format "open -a love.app '%s'" (doom-project-root))))))
|
|
||||||
|
|
||||||
|
|
|
@ -2,4 +2,7 @@
|
||||||
|
|
||||||
;; TODO (defun +rust/run-cargo () (interactive))
|
;; TODO (defun +rust/run-cargo () (interactive))
|
||||||
|
|
||||||
;; TODO (defun +rust-cargo-project-p ())
|
;;;###autoload
|
||||||
|
(defun +rust-cargo-project-p ()
|
||||||
|
"Return t if this is a cargo project."
|
||||||
|
(doom-project-has! "Cargo.toml"))
|
||||||
|
|
|
@ -11,8 +11,11 @@
|
||||||
(def-package! rust-mode
|
(def-package! rust-mode
|
||||||
:mode "\\.rs$"
|
:mode "\\.rs$"
|
||||||
:config
|
:config
|
||||||
(set! :build 'run-cargo '(rust-mode toml-mode) #'+rust/run-cargo
|
(def-menu! +rust/build-menu
|
||||||
:when #'+rust-cargo-project-p))
|
"TODO"
|
||||||
|
'(("run" :exec "cargo run" :cwd t :when (+rust-cargo-project-p))
|
||||||
|
("build" :exec "cargo build" :cwd t :when (+rust-cargo-project-p)))
|
||||||
|
:prompt "Cargo: "))
|
||||||
|
|
||||||
|
|
||||||
(def-package! racer
|
(def-package! racer
|
||||||
|
|
|
@ -36,15 +36,14 @@
|
||||||
:mode ("\\.scss$" . scss-mode)
|
:mode ("\\.scss$" . scss-mode)
|
||||||
:config
|
:config
|
||||||
(set! :company-backend '(css-mode scss-mode) '(company-css company-yasnippet))
|
(set! :company-backend '(css-mode scss-mode) '(company-css company-yasnippet))
|
||||||
(set! :build 'compile-to-css 'scss-mode #'+css/scss-build))
|
(map! :map scss-mode-map :localleader "b" #'+css/scss-build))
|
||||||
|
|
||||||
|
|
||||||
(def-package! sass-mode
|
(def-package! sass-mode
|
||||||
:mode "\\.sass$"
|
:mode "\\.sass$"
|
||||||
:config
|
:config
|
||||||
(setq sass-command-options '("--style compressed"))
|
|
||||||
(set! :company-backend 'sass-mode '(company-css company-yasnippet))
|
(set! :company-backend 'sass-mode '(company-css company-yasnippet))
|
||||||
(set! :build 'compile-to-css 'sass-mode #'+css/sass-build))
|
(map! :map scss-mode-map :localleader "b" #'+css/sass-build))
|
||||||
|
|
||||||
|
|
||||||
(def-package! less-css-mode
|
(def-package! less-css-mode
|
||||||
|
|
|
@ -168,7 +168,7 @@
|
||||||
:desc "Build tasks" :nv "b" #'+eval/build
|
:desc "Build tasks" :nv "b" #'+eval/build
|
||||||
:desc "Jump to definition" :n "d" #'+jump/definition
|
:desc "Jump to definition" :n "d" #'+jump/definition
|
||||||
:desc "Jump to references" :n "D" #'+jump/references
|
:desc "Jump to references" :n "D" #'+jump/references
|
||||||
:desc "Open REPL" :n "r" #'+eval/repl
|
:desc "Open REPL" :n "r" #'+eval/open-repl
|
||||||
:v "r" #'+eval:repl)
|
:v "r" #'+eval:repl)
|
||||||
|
|
||||||
(:desc "file" :prefix "f"
|
(:desc "file" :prefix "f"
|
||||||
|
@ -233,7 +233,7 @@
|
||||||
(:desc "open" :prefix "o"
|
(:desc "open" :prefix "o"
|
||||||
:desc "Default browser" :n "b" #'browse-url-of-file
|
:desc "Default browser" :n "b" #'browse-url-of-file
|
||||||
:desc "Debugger" :n "d" #'+debug/open
|
:desc "Debugger" :n "d" #'+debug/open
|
||||||
:desc "REPL" :n "r" #'+eval/repl
|
:desc "REPL" :n "r" #'+eval/open-repl
|
||||||
:v "r" #'+eval:repl
|
:v "r" #'+eval:repl
|
||||||
:desc "Neotree" :n "n" #'+neotree/toggle
|
:desc "Neotree" :n "n" #'+neotree/toggle
|
||||||
:desc "Terminal" :n "t" #'+term/open-popup
|
:desc "Terminal" :n "t" #'+term/open-popup
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue