From mboxrd@z Thu Jan 1 00:00:00 1970 From: Alex Kost Subject: [PATCH] emacs: Use socket instead of port. Date: Sat, 12 Dec 2015 11:50:19 +0300 Message-ID: <87y4d08304.fsf@gmail.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" Return-path: Received: from eggs.gnu.org ([2001:4830:134:3::10]:35037) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1a7fsh-0004Om-OQ for guix-devel@gnu.org; Sat, 12 Dec 2015 03:50:21 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1a7fsd-0004d4-La for guix-devel@gnu.org; Sat, 12 Dec 2015 03:50:19 -0500 Received: from mail-lf0-x234.google.com ([2a00:1450:4010:c07::234]:35856) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1a7fsd-0004cz-98 for guix-devel@gnu.org; Sat, 12 Dec 2015 03:50:15 -0500 Received: by lfed137 with SMTP id d137so41960644lfe.3 for ; Sat, 12 Dec 2015 00:50:14 -0800 (PST) List-Id: "Development of GNU Guix and the GNU System distribution." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: guix-devel-bounces+gcggd-guix-devel=m.gmane.org@gnu.org Sender: guix-devel-bounces+gcggd-guix-devel=m.gmane.org@gnu.org To: guix-devel@gnu.org --=-=-= Content-Type: text/plain Currently, if you try to run a repl command (for example, "M-x guix-installed-packages") in a second Emacs instance, you'll get an unfriendly error. That's because `guix-default-port' is busy already (by another Guix REPL), so you either have to change it manually or use (setq guix-use-guile-server nil). So with the attached patch, a socket file with a generated name will be used instead of a port, which allows you to run as many Emacs instances with Guix REPLs as you want. Many thanks to Florian for the great idea! There is one small thing though: Guile does not remove socket file after exiting from "guile --listen=/tmp/foo" so these dead sockets will stay in /tmp dir. As there is no `comint-exit-hook' or alike, I don't see how a socket file can be removed after the REPL is killed. --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0001-emacs-Use-socket-instead-of-port.patch >From d12c0e0909491b5522cf08015c8dbd684d526d51 Mon Sep 17 00:00:00 2001 From: Alex Kost Date: Sat, 12 Dec 2015 11:23:03 +0300 Subject: [PATCH] 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): New procedure. (guix-get-guile-program): Take socket as an optional argument. (guix-start-repl-maybe): Adjust accordingly. --- emacs/guix-backend.el | 60 ++++++++++++++++++++++++++++----------------------- 1 file changed, 33 insertions(+), 27 deletions(-) diff --git a/emacs/guix-backend.el b/emacs/guix-backend.el index 82383e4..9612193 100644 --- a/emacs/guix-backend.el +++ b/emacs/guix-backend.el @@ -36,18 +36,13 @@ ;; running code in the REPL (see ;; ). ;; -;; 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 ;; `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 ;; intermediate between "Guix/Guile level" and "Emacs interface level". ;; 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 -;; connect-to-guile" (connect to "localhost" and `guix-default-port') to +;; auxiliary scheme-files for "guix.el". You can just use +;; `geiser-connect-local' command with `guix-repl-current-socket' to ;; have a usual Geiser REPL with all stuff defined by "guix.el" package. ;;; Code: @@ -98,11 +93,17 @@ REPL while some packages are being installed/removed in the main REPL." :type 'boolean :group 'guix-repl) -(defcustom guix-default-port 37246 - "Default port used if `guix-use-guile-server' is non-nil." - :type 'integer +(defcustom guix-repl-socket-file-name-function + #'guix-repl-socket-file-name + "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) +(defvar guix-repl-current-socket nil + "Name of a socket file used by the current Guix REPL.") + (defvar guix-repl-buffer nil "Main Geiser REPL buffer used for communicating with Guix. This REPL is used for processing package actions and for @@ -139,17 +140,20 @@ See `guix-eval-in-repl' for details.") "Message telling about successful Guix operation." (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'." - (if (or internal - (not guix-use-guile-server)) + (if (null socket) guix-guile-program (append (if (listp guix-guile-program) guix-guile-program (list guix-guile-program)) - ;; Guile understands "--listen=..." but not "--listen ..." - (list (concat "--listen=" - (number-to-string guix-default-port)))))) + (list (concat "--listen=" socket))))) + +(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-start-process-maybe (&optional start-msg end-msg) "Start Geiser REPL configured for Guix if needed. @@ -176,19 +180,21 @@ display messages." (get-buffer-process repl)) (and start-msg (message start-msg)) (setq guix-repl-operation-p nil) - (let ((geiser-guile-binary (guix-get-guile-program internal)) - (geiser-guile-init-file (or internal guix-helper-file)) + (unless internal + (if guix-repl-current-socket + ;; Guile leaves socket file after exit, so remove it if it + ;; exists (after the REPL restart). + (when (file-exists-p guix-repl-current-socket) + (delete-file guix-repl-current-socket)) + (setq 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 (guix-get-repl-buffer-name internal)))) - (condition-case err - (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)))) + (guix-start-repl repl (and internal guix-repl-current-socket)) (set repl-var repl) (and end-msg (message end-msg)) (unless internal -- 2.6.3 --=-=-=--