emacs: Use socket instead of port.

Suggested by Florian Paul Schmidt.

* emacs/guix-backend.el (guix-default-port): Remove.
  (guix-repl-socket-file-name-function, guix-repl-current-socket): New
  variables.
  (guix-repl-socket-file-name, guix-repl-delete-socket-maybe): New
  procedures.
  (guix-get-guile-program): Take socket as an optional argument.
  (guix-start-repl-maybe): Adjust accordingly.
This commit is contained in:
Alex Kost 2015-12-12 11:23:03 +03:00
parent 7ccb3ad3c1
commit 1ccdc7f0be
1 changed files with 41 additions and 27 deletions

View File

@ -36,18 +36,13 @@
;; running code in the REPL (see ;; running code in the REPL (see
;; <https://github.com/jaor/geiser/issues/28>). ;; <https://github.com/jaor/geiser/issues/28>).
;; ;;
;; If you need to use "guix.el" in another Emacs (i.e. when there is
;; a runnig "guile --listen..." REPL somewhere), you can either change
;; `guix-default-port' in that Emacs instance or set
;; `guix-use-guile-server' to t.
;;
;; Guix REPLs (unlike the usual Geiser REPLs) are not added to ;; Guix REPLs (unlike the usual Geiser REPLs) are not added to
;; `geiser-repl--repls' variable, and thus cannot be used for evaluating ;; `geiser-repl--repls' variable, and thus cannot be used for evaluating
;; while editing scm-files. The only purpose of Guix REPLs is to be an ;; while editing scm-files. The only purpose of Guix REPLs is to be an
;; intermediate between "Guix/Guile level" and "Emacs interface level". ;; intermediate between "Guix/Guile level" and "Emacs interface level".
;; That being said you can still want to use a Guix REPL while hacking ;; That being said you can still want to use a Guix REPL while hacking
;; auxiliary scheme-files for "guix.el". You can just use "M-x ;; auxiliary scheme-files for "guix.el". You can just use
;; connect-to-guile" (connect to "localhost" and `guix-default-port') to ;; `geiser-connect-local' command with `guix-repl-current-socket' to
;; have a usual Geiser REPL with all stuff defined by "guix.el" package. ;; have a usual Geiser REPL with all stuff defined by "guix.el" package.
;;; Code: ;;; Code:
@ -98,11 +93,17 @@ REPL while some packages are being installed/removed in the main REPL."
:type 'boolean :type 'boolean
:group 'guix-repl) :group 'guix-repl)
(defcustom guix-default-port 37246 (defcustom guix-repl-socket-file-name-function
"Default port used if `guix-use-guile-server' is non-nil." #'guix-repl-socket-file-name
:type 'integer "Function used to define a socket file name used by Guix REPL.
The function is called without arguments."
:type '(choice (function-item guix-repl-socket-file-name)
(function :tag "Other function"))
:group 'guix-repl) :group 'guix-repl)
(defvar guix-repl-current-socket nil
"Name of a socket file used by the current Guix REPL.")
(defvar guix-repl-buffer nil (defvar guix-repl-buffer nil
"Main Geiser REPL buffer used for communicating with Guix. "Main Geiser REPL buffer used for communicating with Guix.
This REPL is used for processing package actions and for This REPL is used for processing package actions and for
@ -139,17 +140,28 @@ See `guix-eval-in-repl' for details.")
"Message telling about successful Guix operation." "Message telling about successful Guix operation."
(message "Guix operation has been performed.")) (message "Guix operation has been performed."))
(defun guix-get-guile-program (&optional internal) (defun guix-get-guile-program (&optional socket)
"Return a value suitable for `geiser-guile-binary'." "Return a value suitable for `geiser-guile-binary'."
(if (or internal (if (null socket)
(not guix-use-guile-server))
guix-guile-program guix-guile-program
(append (if (listp guix-guile-program) (append (if (listp guix-guile-program)
guix-guile-program guix-guile-program
(list guix-guile-program)) (list guix-guile-program))
;; Guile understands "--listen=..." but not "--listen ..." (list (concat "--listen=" socket)))))
(list (concat "--listen="
(number-to-string guix-default-port)))))) (defun guix-repl-socket-file-name ()
"Return a name of a socket file used by Guix REPL."
(make-temp-name
(concat (file-name-as-directory temporary-file-directory)
"guix-repl-")))
(defun guix-repl-delete-socket-maybe ()
"Delete `guix-repl-current-socket' file if it exists."
(and guix-repl-current-socket
(file-exists-p guix-repl-current-socket)
(delete-file guix-repl-current-socket)))
(add-hook 'kill-emacs-hook 'guix-repl-delete-socket-maybe)
(defun guix-start-process-maybe (&optional start-msg end-msg) (defun guix-start-process-maybe (&optional start-msg end-msg)
"Start Geiser REPL configured for Guix if needed. "Start Geiser REPL configured for Guix if needed.
@ -176,19 +188,21 @@ display messages."
(get-buffer-process repl)) (get-buffer-process repl))
(and start-msg (message start-msg)) (and start-msg (message start-msg))
(setq guix-repl-operation-p nil) (setq guix-repl-operation-p nil)
(let ((geiser-guile-binary (guix-get-guile-program internal)) (unless internal
(geiser-guile-init-file (or internal guix-helper-file)) ;; Guile leaves socket file after exit, so remove it if it
;; exists (after the REPL restart).
(guix-repl-delete-socket-maybe)
(setq guix-repl-current-socket
(and guix-use-guile-server
(or guix-repl-current-socket
(funcall guix-repl-socket-file-name-function)))))
(let ((geiser-guile-binary (guix-get-guile-program
(unless internal
guix-repl-current-socket)))
(geiser-guile-init-file (unless internal guix-helper-file))
(repl (get-buffer-create (repl (get-buffer-create
(guix-get-repl-buffer-name internal)))) (guix-get-repl-buffer-name internal))))
(condition-case err (guix-start-repl repl (and internal guix-repl-current-socket))
(guix-start-repl repl
(and internal
(geiser-repl--read-address
"localhost" guix-default-port)))
(text-read-only
(error (concat "Couldn't start Guix REPL. Perhaps the port %s is busy.\n"
"See buffer '%s' for details")
guix-default-port (buffer-name repl))))
(set repl-var repl) (set repl-var repl)
(and end-msg (message end-msg)) (and end-msg (message end-msg))
(unless internal (unless internal