Replace feature/eval build system with def-menu!

This commit is contained in:
Henrik Lissner 2017-10-03 02:49:08 +02:00
parent 63d5fec4aa
commit d0fcb23314
No known key found for this signature in database
GPG key ID: 5F6C0EA160557395
15 changed files with 51 additions and 160 deletions

View file

@ -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.

View file

@ -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))))

View file

@ -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)

View file

@ -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)))

View file

@ -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")

View file

@ -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)

View file

@ -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

View file

@ -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
;; ;;

View file

@ -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"))))))
)

View file

@ -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)))))

View file

@ -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))))))

View file

@ -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"))

View file

@ -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

View file

@ -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

View file

@ -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