all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
* Detecting if the Emacs server is running
@ 2011-03-18  6:11 PJ Weisberg
  2011-03-18  6:47 ` Deniz Dogan
                   ` (2 more replies)
  0 siblings, 3 replies; 8+ messages in thread
From: PJ Weisberg @ 2011-03-18  6:11 UTC (permalink / raw)
  To: help-gnu-emacs

Is there a way, in GNU/Linux, to detect whether Emacs is running in
server mode from a shell script?

I'd like to write a script that creates a new frame with emacsclient
if the user is already running an emacs server, but just starts up a
regular Emacs instance if he isn't.

-- 

-PJ



^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Detecting if the Emacs server is running
  2011-03-18  6:11 PJ Weisberg
@ 2011-03-18  6:47 ` Deniz Dogan
  2011-03-18  7:38   ` PJ Weisberg
  2011-03-18  7:18 ` Leo
       [not found] ` <mailman.5.1300430901.25014.help-gnu-emacs@gnu.org>
  2 siblings, 1 reply; 8+ messages in thread
From: Deniz Dogan @ 2011-03-18  6:47 UTC (permalink / raw)
  To: PJ Weisberg; +Cc: help-gnu-emacs

2011/3/18 PJ Weisberg <pjweisberg@gmail.com>:
> Is there a way, in GNU/Linux, to detect whether Emacs is running in
> server mode from a shell script?
>
> I'd like to write a script that creates a new frame with emacsclient
> if the user is already running an emacs server, but just starts up a
> regular Emacs instance if he isn't.
>

See e.g. (info "(emacs) emacsclient Options").

   The other optional arguments recognized by `emacsclient' are listed
below:

`-a COMMAND'
`--alternate-editor=COMMAND'
     Specify a command to run if `emacsclient' fails to contact Emacs.
     This is useful when running `emacsclient' in a script.  For
     example, the following setting for the `EDITOR' environment
     variable will always give you an editor, even if no Emacs server is
     running:

          EDITOR="emacsclient --alternate-editor emacs +%d %s"

     As a special exception, if COMMAND is the empty string, then
     `emacsclient' starts Emacs in daemon mode and then tries
     connecting again.

     The environment variable `ALTERNATE_EDITOR' has the same effect as
     the `-a' option.  If both are present, the latter takes precedence.

-- 
Deniz Dogan



^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Detecting if the Emacs server is running
  2011-03-18  6:11 PJ Weisberg
  2011-03-18  6:47 ` Deniz Dogan
@ 2011-03-18  7:18 ` Leo
       [not found] ` <mailman.5.1300430901.25014.help-gnu-emacs@gnu.org>
  2 siblings, 0 replies; 8+ messages in thread
From: Leo @ 2011-03-18  7:18 UTC (permalink / raw)
  To: help-gnu-emacs

On 2011-03-18 14:11 +0800, PJ Weisberg wrote:
> Is there a way, in GNU/Linux, to detect whether Emacs is running in
> server mode from a shell script?
>
> I'd like to write a script that creates a new frame with emacsclient
> if the user is already running an emacs server, but just starts up a
> regular Emacs instance if he isn't.

emacsclient option:

-a, --alternate-editor=EDITOR
    Editor to fallback to if server is not running

-- 
Oracle is the new evil




^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Detecting if the Emacs server is running
  2011-03-18  6:47 ` Deniz Dogan
@ 2011-03-18  7:38   ` PJ Weisberg
  2011-03-18  9:59     ` PJ Weisberg
  0 siblings, 1 reply; 8+ messages in thread
From: PJ Weisberg @ 2011-03-18  7:38 UTC (permalink / raw)
  To: Deniz Dogan; +Cc: help-gnu-emacs

On Thu, Mar 17, 2011 at 11:47 PM, Deniz Dogan <deniz.a.m.dogan@gmail.com> wrote:
> 2011/3/18 PJ Weisberg <pjweisberg@gmail.com>:
>> Is there a way, in GNU/Linux, to detect whether Emacs is running in
>> server mode from a shell script?
>>
>> I'd like to write a script that creates a new frame with emacsclient
>> if the user is already running an emacs server, but just starts up a
>> regular Emacs instance if he isn't.
>>
>
> See e.g. (info "(emacs) emacsclient Options").
>
>   The other optional arguments recognized by `emacsclient' are listed
> below:
>
> `-a COMMAND'
> `--alternate-editor=COMMAND'
>     Specify a command to run if `emacsclient' fails to contact Emacs.
>     This is useful when running `emacsclient' in a script.  For
>     example, the following setting for the `EDITOR' environment
>     variable will always give you an editor, even if no Emacs server is
>     running:
>
>          EDITOR="emacsclient --alternate-editor emacs +%d %s"
>
>     As a special exception, if COMMAND is the empty string, then
>     `emacsclient' starts Emacs in daemon mode and then tries
>     connecting again.
>
>     The environment variable `ALTERNATE_EDITOR' has the same effect as
>     the `-a' option.  If both are present, the latter takes precedence.
>
> --
> Deniz Dogan
>

Ok, I guess I wasn't clear.  I actually want to do MORE than just make
a new frame. :-)  Say I run this command:

emacsclient -a emacs -e "(progn (select-frame (make-frame-on-display
\"$DISPLAY\")) (insert \"Hello, world!\"))"

If emacs is running in server mode it does what I wanted (make a
frame, select it, run some elisp), but if emacs isn't running in
server mode, I find myself editing a new file named '(progn
(select-frame (make-frame-on-display ":0.0")) (insert "Hello,
world!"))'

Any thoughts on a better way I could go about this?

Thanks,
PJ



^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Detecting if the Emacs server is running
       [not found] ` <mailman.5.1300430901.25014.help-gnu-emacs@gnu.org>
@ 2011-03-18  8:14   ` Ilya Zakharevich
  0 siblings, 0 replies; 8+ messages in thread
From: Ilya Zakharevich @ 2011-03-18  8:14 UTC (permalink / raw)
  To: help-gnu-emacs

On 2011-03-18, Deniz Dogan <deniz.a.m.dogan@gmail.com> wrote:
> `--alternate-editor=COMMAND'
>      Specify a command to run if `emacsclient' fails to contact Emacs.
>      This is useful when running `emacsclient' in a script.  For
>      example, the following setting for the `EDITOR' environment
>      variable will always give you an editor, even if no Emacs server is
>      running:
>
>           EDITOR="emacsclient --alternate-editor emacs +%d %s"
>
>      As a special exception, if COMMAND is the empty string, then
>      `emacsclient' starts Emacs in daemon mode and then tries
>      connecting again.

Unfortunately, AFAIK, this piece of documentation is wrong.  One is
forced to use much more baroque ways to do "the right thing".  The bug
I suspect is emacsclient using some unportable switch (like
--daemon) for emacs, instead of using
  -f server-start
on platforms which do not support --daemon.  I needed to create a
batch file which does
   emacs -f server-start %*
and give its name as the argument to --alternate-editor...

Ilya


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Detecting if the Emacs server is running
       [not found] <mailman.2.1300428697.25014.help-gnu-emacs@gnu.org>
@ 2011-03-18  9:43 ` Pascal J. Bourguignon
  2011-03-18 20:46   ` PJ Weisberg
  0 siblings, 1 reply; 8+ messages in thread
From: Pascal J. Bourguignon @ 2011-03-18  9:43 UTC (permalink / raw)
  To: help-gnu-emacs

PJ Weisberg <pjweisberg@gmail.com> writes:

> Is there a way, in GNU/Linux, to detect whether Emacs is running in
> server mode from a shell script?
>
> I'd like to write a script that creates a new frame with emacsclient
> if the user is already running an emacs server, but just starts up a
> regular Emacs instance if he isn't.

I have in general three emacs instances running, so I use different
socket file names.  I use the following script to detect the emacs
instances running with an active server.  

Once you get the list of emacsen with an actitve server, you may compare
it with the list of running emacs processes.


------------------------------------------------------------------------
#!/usr/bin/clisp -ansi -q -Kfull -E iso-8859-1
;;;; -*- mode:lisp;coding:utf-8 -*-
;;;;**************************************************************************
;;;;FILE:               mfod.lisp
;;;;LANGUAGE:           Common-Lisp
;;;;SYSTEM:             Common-Lisp
;;;;USER-INTERFACE:     NONE
;;;;DESCRIPTION
;;;;    
;;;;    Shows all the emacs servers available, and let the user select one
;;;;    on which to open a new frame.
;;;;    
;;;;AUTHORS
;;;;    <PJB> Pascal J. Bourguignon <pjb@informatimago.com>
;;;;MODIFICATIONS
;;;;    2010-08-30 <PJB> Translated from bash...
;;;;    2009-09-12 <PJB> Created as a bash script.
;;;;BUGS
;;;;LEGAL
;;;;    GPL
;;;;    
;;;;    Copyright Pascal J. Bourguignon 2010 - 2010
;;;;    
;;;;    This program is free software; you can redistribute it and/or
;;;;    modify it under the terms of the GNU General Public License
;;;;    as published by the Free Software Foundation; either version
;;;;    2 of the License, or (at your option) any later version.
;;;;    
;;;;    This program is distributed in the hope that it will be
;;;;    useful, but WITHOUT ANY WARRANTY; without even the implied
;;;;    warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
;;;;    PURPOSE.  See the GNU General Public License for more details.
;;;;    
;;;;    You should have received a copy of the GNU General Public
;;;;    License along with this program; if not, write to the Free
;;;;    Software Foundation, Inc., 59 Temple Place, Suite 330,
;;;;    Boston, MA 02111-1307 USA
;;;;**************************************************************************
(in-package "COMMON-LISP-USER")

;; Clean the packages imported into COMMON-LISP-USER:
(MAPC (LAMBDA (package) (UNUSE-PACKAGE package "COMMON-LISP-USER"))
      (set-difference
       (COPY-SEQ (PACKAGE-USE-LIST "COMMON-LISP-USER"))
       (delete nil (list ;; A list of all the "CL" packages possible:
                    (FIND-PACKAGE "COMMON-LISP")
                    (FIND-PACKAGE "IMAGE-BASED-COMMON-LISP")))))


(load (make-pathname :name "SCRIPT" :type nil :version NIL :case :common
                      :defaults *load-pathname*))
(use-package "SCRIPT")

(setf *program-name* (pname))


;; (redirecting-stdout-to-stderr (load #p"/etc/gentoo-init.lisp"))
;; (redirecting-stdout-to-stderr
;;  (let ((*load-verbose* nil)
;;        (*compile-verbose* nil))
;;    (load (make-pathname :name ".clisprc" :type "lisp" :case :local
;;                         :defaults (user-homedir-pathname)))
;;    ;; (setf *features* (delete :testing-script *features*))
;;    ))
;; (redirecting-stdout-to-stderr (asdf:oos 'asdf:load-op :split-sequence)
;;                               (asdf:oos 'asdf:load-op :cl-ppcre))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(defun function-named (sname pname)
  (let ((pack (find-package pname)))
    (and pack
         (let ((sym (find-symbol sname pack)))
           (and sym
                (fboundp sym)
                sym)))))

(defun getuid ()
  (funcall (or (function-named "UID" "POSIX")
               (function-named "getuid" "LINUX")
               (function-named "GETUID" "LINUX")
               (error "Cannot get the UID."))))

(defparameter *sockets*
  (let ((uid (getuid)))
    (sort
     (mapcar (function namestring)
             (remove-if-not (function probe-file)
                            (remove-duplicates
                             ;; getting server is not so useful since directory will
                             ;; return the truename...
                             (append (directory (format nil "/tmp/emacs~A/server"   uid))
                                     (directory (format nil "/tmp/emacs~A/server-*" uid)))
                             :test (function equalp))))
     (function string-lessp))))


(defparameter *emacsen*
  (let ((emacsen '()))
    (dolist (socket *sockets* (reverse emacsen))
      (let ((frames
             (with-open-stream (frames (ext:run-program
                                        "emacsclient"
                                        :arguments (list (format nil "--socket-name=~A" socket)
                                                         "--eval"
                                                         "(mapcar (lambda (f) (list (frame-name f) (frame-display f))) (frame-list))")
                                        :output :stream))
               (read frames nil nil))))
        (if frames
            (push (list socket frames) emacsen)
            (multiple-value-bind (all pid) (regexp:match "^.*server-\\([0-9]\\+\\)$" socket)
              (if all
                  (let ((pid (regexp:match-string socket  pid)))
                    (with-open-stream (ps (ext:run-program "ps" :arguments (list "-p" pid) :output :stream))
                      (unless (loop
                                 :named search-emacs
                                 :for line = (read-line ps nil nil)
                                 :while line
                                 :if (regexp:match "emacs" line)
                                 :do (return-from search-emacs t)
                                 :finally  (return-from search-emacs nil))
                        (delete-file socket)
                        (setf *sockets* (delete socket *sockets*))))))))))))


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


(define-option ("list" "-l" "--list") ()
  "List the available emacs servers."
  (loop
     :for i :from 1
     :for (server frames) :in *emacsen*
     :do (format t "~2D) ~30A ~:{~1@*~16A ~0@*~S~:^~%~35T~}~%"
                 i server frames)))


(define-option ("select" "-s" "--select") (index)
  "Select the server at the given index (from 1 up) as the default server."
  (let* ((index (parse-integer index))
         (uid    (getuid))
         (server (ignore-errors (nth (1- index) *emacsen*))))
    (if server
        (ext:run-program "ln" :arguments (list "-sf"
                                               (first server)
                                               (format nil "/tmp/emacs~A/server" uid)))
        (error "~A is not a server index. Please give an index between 1 and ~A"
               index (length *emacsen*)))))



(defun xor (a b) (or (and a (not b)) (and (not a) b)))

(defun make-frame (socket-name &key on-display on-terminal)
  (assert (xor on-display on-terminal))
  (ext:run-program "emacsclient"
                   :arguments  (cond
                                 (on-display
                                  (list
                                   (format nil "--socket-name=~A" socket-name)
                                   "--no-wait"
                                   ;; "--eval" (format nil "(make-frame-on-display \"~A\")"
                                   ;;                  )
                                   "--create-frame"
                                   "--display" on-display))
                                 (on-terminal
                                  (list
                                   (format nil "--socket-name=~A" socket-name)
                                   "--tty")))))


(define-option ("open" "-o" "--open") (index)
  "Make a new frame from the server at the given index (from 1 up) on the current DISPLAY."
  (let* ((index   (parse-integer index))
         (uid     (getuid))
         (server  (ignore-errors (nth (1- index) *emacsen*)))
         (display (ext:getenv "DISPLAY")))
    (cond
      ((null server)
       (error "~A is not a server index. Please give an index between 1 and ~A"
              index (length *emacsen*)))
      ((null display)
       (error "There is no DISPLAY environment variable."))
      (t
       (make-frame (first server) :on-display display)))))


(define-option ("terminal" "-t" "--open-on-terminal") (index)
  "Make a new frame from the server at the given index (from 1 up) in the terminal."
  (let* ((index (parse-integer index))
         (uid    (getuid))
         (server (ignore-errors (nth (1- index) *emacsen*))))
    (cond
      ((null server)
       (error "~A is not a server index. Please give an index between 1 and ~A"
              index (length *emacsen*)))
      (t
       (make-frame (first server) :on-terminal t)))))



(ext:exit
 (if (null *emacsen*)
     (progn
       (format t "There is no emacs server~%")
       EX-UNAVAILABLE)
     (parse-options ext:*args*
                    (lambda ()
                      (call-option-function "help" '())
                      EX-NOINPUT))))

;;;; THE END ;;;;
------------------------------------------------------------------------



-- 
__Pascal Bourguignon__                     http://www.informatimago.com/
A bad day in () is better than a good day in {}.


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Detecting if the Emacs server is running
  2011-03-18  7:38   ` PJ Weisberg
@ 2011-03-18  9:59     ` PJ Weisberg
  0 siblings, 0 replies; 8+ messages in thread
From: PJ Weisberg @ 2011-03-18  9:59 UTC (permalink / raw)
  To: help-gnu-emacs

On Fri, Mar 18, 2011 at 12:38 AM, PJ Weisberg <pjweisberg@gmail.com> wrote:

> Ok, I guess I wasn't clear.  I actually want to do MORE than just make
> a new frame. :-)  Say I run this command:
>
> emacsclient -a emacs -e "(progn (select-frame (make-frame-on-display
> \"$DISPLAY\")) (insert \"Hello, world!\"))"
>
> If emacs is running in server mode it does what I wanted (make a
> frame, select it, run some elisp), but if emacs isn't running in
> server mode, I find myself editing a new file named '(progn
> (select-frame (make-frame-on-display ":0.0")) (insert "Hello,
> world!"))'
>
> Any thoughts on a better way I could go about this?
>
> Thanks,
> PJ

Ok, I had an idea that seems to work:

======================================================================
#!/bin/sh

lisp="(insert \"Hello, world!\")"

emacsclient -a false --eval "(progn (select-frame
(make-frame-on-display \"$DISPLAY\")) $lisp)" 2>/dev/null

if [ $? != 0 ]; then
    emacs --eval "$lisp"
fi
======================================================================

It feels like a kludge to use -a like that, but it does what I wanted
in the case that I was wondering about.  I'm sure I'll think of more
corner cases (e.g., if ALTERNATE_EDITOR is set to "" in the
environment I should let emacsclient start the server instead of
forcing it to false), but for now I know what I'm doing. :-)

-PJ



^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Detecting if the Emacs server is running
  2011-03-18  9:43 ` Detecting if the Emacs server is running Pascal J. Bourguignon
@ 2011-03-18 20:46   ` PJ Weisberg
  0 siblings, 0 replies; 8+ messages in thread
From: PJ Weisberg @ 2011-03-18 20:46 UTC (permalink / raw)
  To: Pascal J. Bourguignon; +Cc: help-gnu-emacs

On Fri, Mar 18, 2011 at 2:43 AM, Pascal J. Bourguignon
<pjb@informatimago.com> wrote:

> I have in general three emacs instances running, so I use different
> socket file names.  I use the following script to detect the emacs
> instances running with an active server.
>
> Once you get the list of emacsen with an actitve server, you may compare
> it with the list of running emacs processes.

I haven't had time to look through the code yet, but thanks for
posting that script.  Multiple server processes isn't a case I'm
directly familiar with, so it's good to have an example of how to
handle it.

Thanks!

-PJ



^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2011-03-18 20:46 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <mailman.2.1300428697.25014.help-gnu-emacs@gnu.org>
2011-03-18  9:43 ` Detecting if the Emacs server is running Pascal J. Bourguignon
2011-03-18 20:46   ` PJ Weisberg
2011-03-18  6:11 PJ Weisberg
2011-03-18  6:47 ` Deniz Dogan
2011-03-18  7:38   ` PJ Weisberg
2011-03-18  9:59     ` PJ Weisberg
2011-03-18  7:18 ` Leo
     [not found] ` <mailman.5.1300430901.25014.help-gnu-emacs@gnu.org>
2011-03-18  8:14   ` Ilya Zakharevich

Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/emacs.git
	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.