diff options
Diffstat (limited to 'emacs/guix-devel.el')
-rw-r--r-- | emacs/guix-devel.el | 80 |
1 files changed, 70 insertions, 10 deletions
diff --git a/emacs/guix-devel.el b/emacs/guix-devel.el index 8a6fc1ec08..b8330289c5 100644 --- a/emacs/guix-devel.el +++ b/emacs/guix-devel.el @@ -43,6 +43,12 @@ "Face for a `modify-phases' keyword ('delete', 'replace', etc.)." :group 'guix-devel-faces) +(defface guix-devel-gexp-symbol + '((t :inherit font-lock-keyword-face)) + "Face for gexp symbols ('#~', '#$', etc.). +See Info node `(guix) G-Expressions'." + :group 'guix-devel-faces) + (defcustom guix-devel-activate-mode t "If non-nil, then `guix-devel-mode' is automatically activated in Scheme buffers." @@ -70,11 +76,14 @@ Interactively, use the module defined by the current scheme file." "Setup REPL for using `guix-devel-...' commands." (guix-devel-use-modules "(guix monad-repl)" "(guix scripts)" - "(guix store)") - ;; Without this workaround, the build output disappears. See + "(guix store)" + "(guix ui)") + ;; Without this workaround, the warning/build output disappears. See ;; <https://github.com/jaor/geiser/issues/83> for details. - (guix-geiser-eval-in-repl - "(current-build-output-port (current-error-port))" + (guix-geiser-eval-in-repl-synchronously + "(begin + (guix-warning-port (current-warning-port)) + (current-build-output-port (current-error-port)))" repl 'no-history 'no-display)) (defvar guix-devel-repl-processes nil @@ -88,12 +97,21 @@ Interactively, use the module defined by the current scheme file." (guix-devel-setup-repl repl) (push process guix-devel-repl-processes)))) +(defmacro guix-devel-with-definition (def-var &rest body) + "Run BODY with the current guile definition bound to DEF-VAR. +Bind DEF-VAR variable to the name of the current top-level +definition, setup the current REPL, use the current module, and +run BODY." + (declare (indent 1) (debug (symbolp body))) + `(let ((,def-var (guix-guile-current-definition))) + (guix-devel-setup-repl-maybe) + (guix-devel-use-modules (guix-guile-current-module)) + ,@body)) + (defun guix-devel-build-package-definition () "Build a package defined by the current top-level variable definition." (interactive) - (let ((def (guix-guile-current-definition))) - (guix-devel-setup-repl-maybe) - (guix-devel-use-modules (guix-guile-current-module)) + (guix-devel-with-definition def (when (or (not guix-operation-confirm) (guix-operation-prompt (format "Build '%s'?" def))) (guix-geiser-eval-in-repl @@ -104,6 +122,32 @@ Interactively, use the module defined by the current scheme file." guix-use-substitutes) "#:dry-run?" (guix-guile-boolean guix-dry-run))))))) +(defun guix-devel-build-package-source () + "Build the source of the current package definition." + (interactive) + (guix-devel-with-definition def + (when (or (not guix-operation-confirm) + (guix-operation-prompt + (format "Build '%s' package source?" def))) + (guix-geiser-eval-in-repl + (concat ",run-in-store " + (guix-guile-make-call-expression + "build-package-source" def + "#:use-substitutes?" (guix-guile-boolean + guix-use-substitutes) + "#:dry-run?" (guix-guile-boolean guix-dry-run))))))) + +(defun guix-devel-lint-package () + "Check the current package. +See Info node `(guix) Invoking guix lint' for details." + (interactive) + (guix-devel-with-definition def + (guix-devel-use-modules "(guix scripts lint)") + (when (or (not guix-operation-confirm) + (y-or-n-p (format "Lint '%s' package?" def))) + (guix-geiser-eval-in-repl + (format "(run-checkers %s)" def))))) + ;;; Font-lock @@ -126,11 +170,17 @@ This function is used as a MATCHER for `font-lock-keywords'." "Skip the next sexp, and return the end point of the current list. This function is used as a PRE-MATCH-FORM for `font-lock-keywords' to find 'modify-phases' keywords." - (ignore-errors (forward-sexp)) - (save-excursion (up-list) (point))) + (let ((in-comment? (nth 4 (syntax-ppss)))) + ;; If 'modify-phases' is commented, do not try to search for its + ;; keywords. + (unless in-comment? + (ignore-errors (forward-sexp)) + (save-excursion (up-list) (point))))) (defvar guix-devel-font-lock-keywords - `((,(guix-guile-keyword-regexp "modify-phases") + `((,(rx (or "#~" "#$" "#$@" "#+" "#+@")) . + 'guix-devel-gexp-symbol) + (,(guix-guile-keyword-regexp "modify-phases") (1 'font-lock-keyword-face) (guix-devel-modify-phases-font-lock-matcher (guix-devel-modify-phases-font-lock-pre) @@ -142,6 +192,8 @@ to find 'modify-phases' keywords." (defvar guix-devel-keys-map (let ((map (make-sparse-keymap))) (define-key map (kbd "b") 'guix-devel-build-package-definition) + (define-key map (kbd "s") 'guix-devel-build-package-source) + (define-key map (kbd "l") 'guix-devel-lint-package) (define-key map (kbd "k") 'guix-devel-copy-module-as-kill) (define-key map (kbd "u") 'guix-devel-use-module) map) @@ -184,6 +236,14 @@ bindings: (when guix-devel-activate-mode (guix-devel-mode))) + +(defvar guix-devel-emacs-font-lock-keywords + (eval-when-compile + `((,(rx "(" (group "guix-devel-with-definition") symbol-end) . 1)))) + +(font-lock-add-keywords 'emacs-lisp-mode + guix-devel-emacs-font-lock-keywords) + (provide 'guix-devel) ;;; guix-devel.el ends here |