Emacs as daemon on OS X with window-system

I'm running gnu emacs 23.3.1 cocoa build on OS X 10.6.
I added the following to ~/Library/LaunchAgents/gnu.emacs.daemon.plist so that it will start a daemon and automatically restart emacs if I inadvertently kill it.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" 
    "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> 
 <plist version="1.0">
  <dict> 
    <key>Label</key>
    <string>gnu.emacs.daemon</string>
    <key>ProgramArguments</key>
    <array>
      <string>/Applications/Emacs.app/Contents/MacOS/Emacs</string>
      <string>--daemon</string>
    </array>
   <key>RunAtLoad</key>
   <true/>
   <key>KeepAlive</key>
   <true/>
   <key>ServiceDescription</key>
   <string>Gnu Emacs Daemon</string>
  </dict>
</plist>

This sorta works but I noticed that my color theme wasn't working properly. Then I remembered I had added the following to my init file:

(when window-system 
  (require 'alpha)
  (require 'color-theme-ir-black)
  (modify-frame-parameters (selected-frame) '((alpha . 85)))
  (color-theme-ir-black))

When started as a daemon window-system is false apparently and that makes sense, however the reason I added this is because I occasionally like to start the normal emacs build in a terminal from ssh etc and this color scheme is completely unreadable in iTerm thus the (when window-system ...). Is there a way to force emacs to start window mode when start with --daemon?

Another issue I have noticed is that when I run press s-w (delete-frame) in dameon mode I don't get the error attempt to delete sole visible or iconified frame and emacs continues to run in the background. I like this for the most part however I have noticed that once the last frame is killed I can no longer reopen emacs from the doc and although emacs will activate and menus are displayed they don't work and I can't create a new frame except by using emacsclient from the commandline. Anyone else have this issue and or recommendation on workaround? perhaps I can bind s-w to detect if last frame and iconify-frame instead, but not sure why it thinks its not the last window and allowed me to kill it in the first place.

UPDATE:

I found a comment on the following blog by Steve Purcell with a fix for a very similar problem: http://emacs-fu.blogspot.com/2009/03/color-theming.html

The secret it seems is to use 'after-make-frame-functions hook to setup the newly created frame and also to (setq color-theme-is-global nil) so that each frame can have its own color theme. So the relevant sections of my init now looks like this:

(defvar after-make-console-frame-hooks '()
"Hooks to run after creating a new TTY frame")
(defvar after-make-window-system-frame-hooks '()
"Hooks to run after creating a new window-system frame")

(defun run-after-make-frame-hooks (frame)
"Selectively run either `after-make-console-frame-hooks' or
`after-make-window-system-frame-hooks'"
  (select-frame frame)
  (run-hooks (if window-system
               'after-make-window-system-frame-hooks
               'after-make-console-frame-hooks)))

(add-hook 'after-make-frame-functions 'run-after-make-frame-hooks)
(add-hook 'after-init-hook (lambda ()
  (run-after-make-frame-hooks (selected-frame))))


(setq color-theme-is-global nil)

(add-hook 'after-make-window-system-frame-hooks
          '(lambda ()
             (require 'alpha)
             (require 'color-theme-ir-black)
             (modify-frame-parameters (selected-frame) '((alpha . 85)))
             (color-theme-ir-black)
             (global-set-key (kbd "s-w") 'delete-frame)))

However, I am still having the issue where delete-frame closes the last frame when emacs was started as daemon and not allowing me to create a new frame other then by using emacsclient.

UPDATE:

If I eval (frame-list) I see there are 2 frames listed even though only one is visible. I noticed that this does not occur if I start Emacs with open /Applications/Emacs.app instead of emacsclient. I normally start emacs from the commandline with an alias e='emacsclient -c -n ' which is what creates the second frame. I can only seem to attach to the other frame by starting emacs with the open command. If I try emacsclient -n somefile without -c I get nothing, and if I run emacsclient -n -e '(frame-list)' I see there is a frame its just not visible until I use -c to create new frame or open emacs from the applications folder.


Solution 1:

Running a process or application as a launchd daemon gives it a very different environment from running it normally or on the command line. I wonder if it might not work better to instead use a shell script as a login item.

For example:

#!/bin/bash
while true
do
  open -W /Applications/Emacs.app
done

This script would need to be saved to a file with a .command extension and 755 permissions (chmod 0755 myemacsscript.command) and then added to the System Preferences : Login : Login Items pane.

When you login, Terminal will launch and run this script. You will probably want to setup a default terminal profile that excludes terminal from prompting on quit for this particular script, so that it doesn't hold you up when you log out.

I have no idea if this will fix the particular problems with Emacs.app, but it may at least provide an environment closer to what Emacs.app expects.