Emacs 23, OS X, multi-tty and emacsclient

限于喜欢 提交于 2019-12-30 06:49:05

问题


How can I get emacs 23 working nicely in multi-tty mode on OS X?

I've added (server-start) to my .emacs, and have discovered that running /Applications/Emacs.app/Contents/MacOS/bin/emacsclient -n ~/myfile.txt will open it in my emacs.app, but it doesn't bring emacs to the front.

So, how can I get emacs.app to come to the front when I run emacsclient? (I've considered writing a function that puts the current frame to the front every time a file is opened, or maybe writing an Applescript to do a similar job that could be called at the same time as emacsclient)

Is the emacsclient within emacs.app the best one to use? I assume I'll write an alias to it if so, but it seems weird to be using that rather than something in /usr/local/bin

Has anyone got any other tips or examples of getting this working?


回答1:


The AppleScript would be simple:

tell app "Emacs" to activate



回答2:


I have an alias from emacs to

open -a /Applications/Emacs.app "$@"

If you are annoyed by the fact that it opens a new frame (window) for each file -- add

(setq ns-pop-up-frames nil)

to your .emacs and fixed.




回答3:


Perhaps this would work, just calling raise-frame when the client attaches:

(add-hook 'server-visit-hook 'call-raise-frame)
(defun call-raise-frame ()
  (raise-frame))

(It happens to be redundant on my Linux machine.)




回答4:


Some of the proposed solutions suggest using 'raise-frame'. That will raise the emacs frame, but it will not give it focus. When you start emacs from a terminal window, emacs will still be beneath the terminal window because the terminal window retains the focus. I use 'select-frame-set-input-focus' to raise and give focus.

Examples:

/Applications/Emacs.app/Contents/MacOS/bin/emacsclient -n ~/myfile.txt \
    --eval '(select-frame-set-input-focus (nth 0 (frame-list)))'

I prefer to run separate instance of emacs, so when I exit with "^X^C" I don't lose all windows. To accomplish this I have a shell script:

#!/bin/bash
/Applications/Emacs.app/Contents/MacOS/Emacs \
    --eval '(select-frame-set-input-focus (nth 0 (frame-list)))' \
    "$@"



回答5:


I use something like this in my .emacs to only call server-start if the server isn't already running:

(if (file-exists-p
 (concat (getenv "TMPDIR") "emacs"
         (number-to-string
          (user-real-uid)) "/server"))
nil (server-start))

Then a couple of changes to my .zshrc so that I can mindlessly run ec as my editor command from the shell:

# I use the Emacs package from emacsformacosx.com
alias emacs='open -a emacs'
alias emacsclient='/Applications/Emacs.app/Contents/MacOS/bin/emacsclient'
alias ec='emacsclient -a /Applications/Emacs.app/Contents/MacOS/Emacs'
export EDITOR='ec'



回答6:


To expand on the answers given by Trey Jackson and the comment by Singletoned: I have the following in my .emacs file

;;;
;;; Run in server-mode so other sessions can connet
;;;
(defun call-raise-frame ()
   (raise-frame))
(defun end-server-edit ()
   (shell-command "osascript -e \"tell application \\\"System Events\\\" to keystroke tab using command down\""))
(add-hook 'server-visit-hook 'call-raise-frame)
(add-hook 'server-done-hook 'end-server-edit)
(server-start)

And in my shell init file I have the following aliases:

alias e='emacsclient'      # edit
alias enw='emacsclient -n' #edit (no wait)

Now I can have a shell open side-by-side with my CocoaEmacs instance and use the two seamlessly together. I can call the editor "inline" with my current terminal flow by using the e alias and once I finish editing in emacs focus will be returned to the calling terminal.




回答7:


I define this function in my .emacs

(defun ns-raise-emacs ()
  (ns-do-applescript "tell application \"Emacs\" to activate"))

Then use this to raise the frame:

emacsclient -e '(ns-raise-emacs)'

I recommend doing it this way instead of calling osascript. It seems to respond faster (significantly faster sometimes) than using osascript.




回答8:


fwiw, here's my solution:
step 1: create a script at /usr/local/bin/emacs with the following contents:

#!/usr/bin/bash
emacsclient -c --alternate-editor='/Applications/Emacs.app/Contents/MacOS/Emacs'  "$@" 2>/dev/null

step 2. make it executable via: chmod +x /usr/local/bin/emacs

step 3. in your ~/.emacs file add the following:

(server-start)  

(defun ns-raise-emacs ()  
(ns-do-applescript "tell application \"Emacs\" to activate"))  

(ns-raise-emacs)  

(add-hook 'server-visit-hook 'raise-frame)  
;;(add-hook 'server-visit-hook 'ns-raise-emacs)

explanation:

If the emacs script at /usr/local/bin/emacs is invoked and there's no emacs server currently running, the emacsclient will invoke the alternate editor, which in this case is the Emacs editor (/Applications/Emacs.app/Contents/MacOS/Emacs).

In step 3, the initial call to (ns-raise-emacs) seems to be necessary for the initial Emacs window to show in front of everything else.

The (add-hook 'server-visit-hook 'raise-frame) is so that subsequent frames show up in front of everything else.

Alternatively, if you prefer that all Emacs frames show up in front of everything else each time you invoke emacs from the command line, you can uncomment the (add-hook 'server-visit-hook 'ns-raise-emacs) line.



来源:https://stackoverflow.com/questions/945709/emacs-23-os-x-multi-tty-and-emacsclient

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!