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

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

我在 OS X 10.6 上运行 gnu emacs 23.3.1 cocoa build。
我在 ~/Library/LaunchAgents/gnu.emacs.daemon.plist 中添加了以下内容,这样如果我不小心杀死了 emacs,它就会启动一个守护进程并自动重新启动 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>

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

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

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

我注意到的另一个问题是,当我在守护进程模式下运行 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)))

但是,我仍然遇到这样的问题:当 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任何操作,则不会得到任何结果,如果我运行,我会看到有一个框架,只是在我使用它创建新框架或从应用程序文件夹打开 emacsemacsclient -n -e '(frame-list)'之前它是不可见的。-c

答案1

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

例如:

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

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

当您登录时,终端将启动并运行此脚本。您可能希望设置一个默认终端配置文件,使终端在退出时不提示此特定脚本,这样它就不会在您注销时耽误您的时间。

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

相关内容