25

OS: OS X 10.9.5, Mavericks

GNU Emacs 24.3.1 (x86_64-apple-darwin13.1.0, Carbon Version 1.6.0 AppKit 1265.19) of 2014-04-03 on Rainers-MacBook-Pro-3.local

I installed emacs via homebrew from railwaycat and it works nicely - no complaints. I do not use emacs in the termoinal, and I usually start it via the Application.

As I said - I am happy so far.

I just have one thing I did not manage to get right (which worked nicely under linux before), which is:

  1. get emacs daemon starting upon login
  2. using emacsclient to open
  3. close emacsdaemon and save al files upon logoff

Any working recipes which could help me to set this up?

Added information

To start an emacs daemon upon login

I created an Automator Application executing the bash command

/usr/local/bin/emacs --daemon

and added it to the Login Items which works nicely.

Utilising daemon from terminal

I can utilise the emacs daemon by using

emacsclient .bashrc

which opens .bashrc in an emacs terminal session.

Utilising from GUI

Now remains the question: how can I utilise it from the GUI?

As I understand the emacsclient, I can not open an emacsclient unless I specify a file to open.

I would like to open an emacsclient GUI and open all files which were previously opened? Is this possible?

I found out that I can use

emacsclient -c

in a terminal to do what I want - but can I do the same for the GUI?

  • I don't understand what "from the GUI" means here. It could mean "double clicking on a file in the Finder" or something else entirely. – tarsius Sep 25 '14 at 21:15
  • Using the App Launcher (e.g. via Spotlight) – Rainer Sep 26 '14 at 12:59
  • Does the App Launcher allow selecting files (which are then opened using the default application for the file type). Or only "Apps"? emacsclient isn't an App as far as OS X is concerned, only Emacs is (and only if it has been installed that way). Why don't you just use the system key bindings for selecting an open application/window? (Won't work if Emacs was started in daemon mode and there is no frame ("window") yet). – tarsius Sep 26 '14 at 13:39
  • I defined an app called Emacsclient which launches the emacsclient - so the app Emacsclient is there. I obviously could switch to a running emacs instance - but this is besides the point, looking at the workflow described above. – Rainer Sep 26 '14 at 18:54
  • 1
    This question is almost more helpful than its answers :) – Roy Truelove Nov 5 '15 at 16:37
6

I really don't mind Emacs.app always running, but the fact that I couldn't close the window without accidentally killing the Emacs server was annoying. And even if you try really hard to kill the last frame, it still doesn't let you: "Attempt to delete the sole visible or iconified frame". ...So we cheat.

This solution just hides Emacs (like Command+h) when you try to close the last window by clicking the close button.

Add the following to your Emacs init somewhere:

(defadvice handle-delete-frame (around my-handle-delete-frame-advice activate)
  "Hide Emacs instead of closing the last frame"
  (let ((frame   (posn-window (event-start event)))
        (numfrs  (length (frame-list))))
    (if (> numfrs 1)
      ad-do-it
      (do-applescript "tell application \"System Events\" to tell process \"Emacs\" to set visible to false"))))

And add Emacs to "Users & Groups > Login Items", and click the "Hide" checkbox.

Your Emacs init also needs to call (start-server) somewhere.

I'm using this emacsclient wrapper to bring Emacs to the front first:

#!/bin/sh
osascript -e 'tell application "Emacs" to activate'
exec emacsclient "$@"

Issues:

  • Activating/unhiding Emacs brings all windows to the front. This is slightly annoying.
  • Clicking the Emacs icon in the Dock seems to randomly create a new window sometimes. But not always.
  • TODO: Maybe make Command+w on the last frame also hide Emacs?
  • NEW with edit: clicking the dock icon when all windows are minimized doesn't automatically maximize one of them.

This is based off of @noaham's answer suggesting to minimize Emacs, and this answer explaining how to hook trying to close the last window.

EDIT:

Searching through the source, I found the "key binding" for mac-apple-event-map which calls mac-ae-reopen-application. mac-ae-reopen-application seems to check for visible and iconified frames and must somehow miss our hidden one. This is possibly a bug.

The easy fix is to just disable the key binding in your init:

(define-key mac-apple-event-map [core-event reopen-application] nil)

This introduces a new minor bug: clicking the dock icon when all windows are minimized doesn't automatically maximize one of them. The correct fix would be to rewrite mac-ae-reopen-application, but I barely know emacs and elisp.

  • If anybody figures out how to stop the random new window (bullet point two) please tell me. It's perhaps the only thing left that's still bugging me about this setup. – parent5446 Nov 19 '14 at 0:48
  • @parent5446, done! Just as hacky as the first fix, but it works. – bburky Nov 19 '14 at 9:17
  • Thanks! The hack part of it does not bother me since most of the time I do not initiate Emacs from the dock anyway. – parent5446 Nov 20 '14 at 9:30
4

The Yamamoto Mitsuharu port of emacs doesn't support multi-tty unfortunately (see this issue). This means that you can't start the emacs daemon from the terminal and launch a gui window with emacsclient.

Here is what I do: In my init.el I have (server-start)and I launch Emacs.app at login. The annoyance here is that this brings up a window which I have to manually minimise.

I then have a bash script called emacsc with the following

#!/bin/bash                                                                          
export PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin
emacsclient -n -c

I then create an app with applescript which contains the following

tell application "Emacs"
    activate
end tell
do shell script "~/bin/emacsc"

It is important to pass the -n flag to emacsclient otherwise you will only be able to use the emacsc app to open one client at a time. Setting the path variable makes sure that OS X can find the correct version of emacsclient.

Telling Emacs to "activate" ensures that your client window will be launched in the foreground.

As I said the annoyance is that you have to manually minimise the emacs window on login and then have it sitting down in the dock. One way to avoid this is to automatically "hide" Emacs after login but then having it activate will cause it to unhide.

2

I'm not sure how railwaycat Emacs is different from the regular home-brew formula, but with the latter you would do ln -sfv /usr/local/opt/emacs/*.plist ~/Library/LaunchAgents, which would run emacs --daemon on login.

The plist is included as a HERE-document in the formula. All you'd need to adopt it is change the path to your emacs app in the line <string>#{opt_bin}/emacs</string>.

BTW, you can also get Emacs as an OS X app with Homebrew Emacs if you install it with the --cocoa option. (You would also need to run brew linkapps afterwards, to link it to /Applications, or create the link yourself.

1

On the mac daemons are, 90% of the time, managed using launchd. It's can run them on many triggers, including user login/logout. There is a pretty Mac Application called Lingon for viewing and editing the various things launchd is managing. The emacs wiki has some mentions of this, including and example config file. But that looks like it doesn't address your concern, i.e. how to shut down the daemon on logout.

0

Create an AppleScript application like this:

tell application "Terminal"
do shell script "/usr/local/bin/emacsclient -c"
endtell

You might have to adjust the path, or you might be able to leave out the path completely. You could also use something fancier with starts the daemon if it isn't running yet.

  • @Rainer Having any success with this? You might also want to search for fancier implementation which even start the daemon if necessary before connecting to it using the emacsclient. "applescript emacsclient" gives good results with google search. – tarsius Oct 7 '14 at 15:25
  • Are you still waiting for a better answer or would it be possible to accept this one? – tarsius Oct 14 '14 at 16:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.