Emacs 作为具有窗口系统的 OS X 上的守护进程

Kur*_*ger 13 emacs osx-snow-leopard

我在 OS X 10.6 上运行 gnu emacs 23.3.1 cocoa build。
我将以下内容添加到 ~/Library/LaunchAgents/gnu.emacs.daemon.plist 以便它会启动一个守护进程并在我无意中杀死它时自动重新启动 emacs。

<?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>
Run Code Online (Sandbox Code Playgroud)

这有点工作,但我注意到我的颜色主题不能正常工作。然后我记得我在我的 init 文件中添加了以下内容:

(when window-system 
  (require 'alpha)
  (require 'color-theme-ir-black)
  (modify-frame-parameters (selected-frame) '((alpha . 85)))
  (color-theme-ir-black))
Run Code Online (Sandbox Code Playgroud)

当作为守护程序窗口系统启动时,显然是错误的,这是有道理的,但是我添加它的原因是因为我偶尔喜欢从 ssh 等在终端中启动正常的 emacs 构建,而这种配色方案在 iTerm 中完全不可读,因此(当窗口系统......)。有没有办法在使用 --daemon 启动时强制 emacs 启动窗口模式?

我注意到的另一个问题是,当我在 dameon 模式下运行 press sw (delete-frame) 时,我没有收到错误尝试删除唯一可见或图标化的框架,并且 emacs 继续在后台运行。我在很大程度上喜欢这个,但是我注意到,一旦最后一帧被杀死,我就无法再从文档中重新打开 emacs,虽然 emacs 会激活并显示菜单,但它们不起作用,我无法创建新框架除了从命令行使用 emacsclient。其他人有这个问题和/或有关解决方法的建议吗?也许我可以绑定 sw 来检测是否为最后一帧和 iconify-frame,但不知道为什么它认为它不是最后一个窗口并允许我首先杀死它。

更新:

我在以下博客上找到了 Steve Purcell 的评论,其中修复了一个非常相似的问题:http : //emacs-fu.blogspot.com/2009/03/color-theming.html

秘密似乎是使用 'after-make-frame-functions 钩子来设置新创建的框架以及 (setq color-theme-is-global nil) 以便每个框架都可以有自己的颜色主题。所以我的 init 的相关部分现在看起来像这样:

(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)))
Run Code Online (Sandbox Code Playgroud)

但是,我仍然遇到以下问题:当 emacs 作为守护程序启动时,delete-frame 关闭最后一帧,并且不允许我使用 emacsclient 创建新帧。

更新:

如果我eval (frame-list)看到列出了 2 个框架,即使只有一个可见。我注意到如果我使用 open/Applications/Emacs.app而不是 emacsclient启动 Emacs,则不会发生这种情况。我通常从命令行启动 emacs,并使用别名e='emacsclient -c -n '创建第二帧。我似乎只能通过使用 open 命令启动 emacs 来附加到另一个框架。如果我尝试 emacsclient -n somefile 没有-c我什么都没有,如果我运行emacsclient -n -e '(frame-list)'我看到有一个框架它只是不可见,直到我-c用来创建新框架或从应用程序文件夹打开 emacs。

小智 2

作为 launchd 守护进程运行进程或应用程序会为其提供与正常运行或在命令行上运行截然不同的环境。我想知道使用 shell 脚本作为登录项是否会更好。

例如:

#!/bin/bash
while true
do
  open -W /Applications/Emacs.app
done
Run Code Online (Sandbox Code Playgroud)

该脚本需要保存到具有.command扩展名和 755 权限 ( chmod 0755 myemacsscript.command) 的文件中,然后添加到系统首选项:登录:登录项窗格。

当您登录时,终端将启动并运行此脚本。您可能需要设置一个默认的终端配置文件,以排除终端在退出此特定脚本时的提示,这样当您注销时它就不会阻止您。

我不知道这是否会解决 Emacs.app 的特定问题,但它至少可以提供一个更接近 Emacs.app 期望的环境。