(with-eval-after-load 'geiser-guile
(define-key scheme-mode-map
(kbd "<f6>")
(lambda ()
(interactive)
(let ((win (selected-window)))
(save-excursion
(guix-devel-lint-package)
(end-of-buffer))
(select-window win)))))
(defun guix-package-name-at-point ()
"Return the name of package at point, as a string"
(save-excursion
(beginning-of-defun)
(forward-char) (forward-sexp) (forward-comment (point-max))
(symbol-name (symbol-at-point))))
(defun guix-package-sexp-at-point ()
"Return the package at point, as a string."
(save-mark-and-excursion
(mark-defun)
(buffer-substring-no-properties
(region-beginning)
(region-end))))
(defun guix-geiser-eval-in-repl-synchronously (str &optional repl
no-history no-display)
"Evaluate STR in Geiser REPL synchronously, i.e., wait until the
REPL operation will be finished.
See `guix-geiser-eval-in-repl' for the meaning of arguments."
(let* ((repl (if repl (get-buffer repl) (guix-geiser-repl)))
(proc (get-buffer-process repl))
(running? nil)
(filter (lambda (output)
(setq running?
(and (get-buffer-process repl)
(not (guix-guile-prompt? output))))))
(comint-output-filter-functions
(cons filter comint-output-filter-functions)))
(guix-geiser-eval-in-repl str repl no-history no-display)
(while running?
(accept-process-output proc 0.1)
(unless no-display
(redisplay t)
(end-of-buffer)))))
(defun guix-build-package-at-point ()
"Evaluate sexp at point and build it in Geiser."
(interactive)
(let* ((name (guix-package-name-at-point))
(sexp-string (guix-package-sexp-at-point))
(build-command (format ",build %s" name))
(register-last-value-hook
(format
"%s"
'(add-hook! before-print-hook
(lambda (v)
(if (not (unspecified? v))
(let ((history (resolve-module '(value-history)))
(last '$0))
(module-define! history last v)
(module-export! history (list last)))))))))
(geiser-mode-switch-to-repl-and-enter) (geiser-repl-switch) (guix-geiser-eval sexp-string)
(guix-geiser-eval "(use-modules (guix))")
(guix-geiser-eval register-last-value-hook)
(guix-geiser-eval-in-repl-synchronously build-command)
(let ((repl-text (save-mark-and-excursion
(end-of-buffer)
(mark)
(search-backward build-command)
(buffer-substring-no-properties
(region-beginning)
(region-end)))))
(geiser-repl-switch) (cond ((string-match (rx "View build log at '" (group (+ graphic)) "'.")
repl-text)
(let ((revert-without-query '(".*")))
(guix-build-log-find-file (match-string 1 repl-text))
(end-of-buffer)))
((string-search "error" repl-text)
nil)
(guix-geiser-eval-in-repl-synchronously
"\
(when (module-variable (current-module) '$0)
(format #t \"Build succeeded; log at `~a'~%\"
(with-store store (log-file store $0)))
$0)")))))
(with-eval-after-load 'scheme
(define-key scheme-mode-map
(kbd "<f7>")
#'guix-build-package-at-point))
(defun guix-commit-package-at-point ()
"Commit a new package NAME at point."
(interactive)
(save-buffer)
(save-window-excursion
(save-mark-and-excursion
(let* ((name (guix-package-name-at-point))
(package-text (guix-package-sexp-at-point))
(diff-text (replace-regexp-in-string
"^" "+" (string-trim-left package-text)))
(magit-save-repository-buffers 'dontask))
(magit-diff-unstaged)
(beginning-of-buffer)
(let* ((end (search-forward diff-text))
(beg (- end (length diff-text))))
(set-mark end)
(goto-char beg))
(magit-stage)
(let ((commit-message (format "gnu: Add %s.
* %s (%s): New variable." name (car (magit-staged-files)) name)))
(magit-call-git "commit" "-m" commit-message))
(magit-refresh)
(message "Package %s committed." name))))
(revert-buffer t t))
(with-eval-after-load 'scheme
(define-key scheme-mode-map
(kbd "<f8>")
#'guix-commit-package-at-point))