如何在 OSX 中从命令行启动 GUI Emacs?

如何从 OSX 的命令行启动 GUI Emacs?

我已经从 http://emacsformacosx.com/下载并安装了 Emacs。

我接受符合以下所有条件的回答:

  1. Emacs 窗口打开 我的终端窗口。
  2. 输入“ Emacs”会启动一个 GUI Emacs 窗口。在该窗口中查找文件的默认方式是查找启动 Emacs 的目录。
  3. 当 foo.txt 存在时,键入“ Emacs foo.txt”将启动一个加载 foo.txt 的 GUI Emacs 窗口。
  4. 当 foo.txt 存在 没有时,键入“ Emacs foo.txt”将启动一个 GUI Emacs 窗口,其中包含一个名为“ foo.txt”的空文本缓冲区。在该缓冲区中执行 ^ X ^ S 将在启动 Emacs 的目录中保存 foo.txt。
98237 次浏览

In your shell, alias the command 'emacs' to point to the OSX emacs application

In my shell (running the default bash), I have the following (in my .bashrc)

alias emacs='open -a /Applications/Emacs.app $1'

Then, typing emacs on the command line starts the emacs application.

I would, however, recommend that you open a copy of emacs and just keep it up and running. If that's the case, and you want to load a file into an existing copy of emacs, you can use the emacsclient by placing the following in your .bashrc:

alias ec='/Applications/Emacs.app/Contents/MacOS/bin/emacsclient'

Then add the following to your .emacs file to start the emacs server (which receives the emacsclient calls)

;;========================================
;; start the emacsserver that listens to emacsclient
(server-start)

Then you can type

ec .bashrc

to load a copy of .bashrc into an existing emacs session!

On Mountain Lion, I am using Yamamoto Mitsuharu's port https://github.com/railwaycat/emacs-mac-port with the following alias:

alias emacs=/Applications/Emacs.app/Contents/MacOS/Emacs

and it satisfies all of your criteria.

Call the following script "emacs" and put it in your PATH somewhere:

#!/bin/sh
/Applications/Emacs.app/Contents/MacOS/Emacs "$@"

That covers #2, #3, and #4.

For #1, put this somewhere in your .emacs file:

(x-focus-frame nil)

The emacsformacosx.com site now has a How-To page, which is where the top snippet came from. There's more info there about running emacsclient and hooking Emacs up to git mergetool.

Compile Emacs according to the following steps:

./configure --with-x --prefix=/usr
make
sudo make install

And your done! It may help to download and install XQuartz, but that's just my opinion.

Just built emacs with homebrew package manager according to this guide: http://www.emacswiki.org/emacs/EmacsForMacOS with brew install --cocoa emacs After that one should launch the .app version to get gui, which in my case was /usr/local/Cellar/emacs/24.3/Emacs.app/Contents/MacOS/Emacs

This improves on David Caldwell's answer by starting Emacs in the background:

#!/bin/sh
$(/Applications/Emacs.app/Contents/MacOS/Emacs "$@") &

As stated in the other answer, this covers #2, #3, and #4. For #1, put this somewhere in your .emacs file: (x-focus-frame nil).

Note that the following does not work for me -- it does not start Emacs in a directory specified on the command line (e.g. emacs .)

# NOT RECOMMENDED
#!/bin/sh
/Applications/Emacs.app/Contents/MacOS/Emacs "$@" &

Further improving on David James' response the following works for me:

Per instructions to open a file from a terminal found at http://www.emacswiki.org/emacs/EmacsForMacOS#toc20

open -a /Applications/Emacs.app <file-name>

combining this with David Jame's response I've created the following emax bash script and placed it in my path at ~/bin

#!/bin/bash
(open -a /Applications/Emacs.app "$@") &

Caveat: in order to get emacs to open the current directory in Dired by name mode, you need to use

emax .

Environment:

  • OS X Yosemite Version 10.10.2
  • GNU Emacs 24.4.2 (x86_64-apple-darwin14.0.0, NS apple-appkit-1343.14) of 2014-11-13

The other answers here didn't quite work for me. In particular, on my machine, the bash script

#!/bin/sh
/Applications/Emacs.app/Contents/MacOS/Emacs "$@"

always opens emacs in the home directory. To get it to open in the current working directory, I had to do

#!/bin/sh
/Applications/Emacs.app/Contents/MacOS/Emacs "$PWD/$@"

instead.

I assume you either:

  • Start the emacs daemon on login
  • Have (server-start) in your .emacs
  • Don't mind having lots of separate copies of emacs running

If so, then I think this satisfies the original four criteria, plus one more:

  1. The emacs window opens in front of my terminal window.

it will always open to the foreground (with x-focus-frame).

  1. Typing "emacs" launches a GUI Emacs window. Finding files in that window will default to looking in the directory from where I started Emacs.

It will open an existing emacs window in dired mode.

  1. Typing "emacs foo.txt" when foo.txt exists launches a GUI Emacs window with foo.txt loaded.

If emacs is already running and has a server, then it will open in the existing window and come to the foreground.

  1. Typing "emacs foo.txt" when foo.txt does not exist launches a GUI Emacs window with an empty text buffer named "foo.txt". Doing ^X^S in that buffer will save foo.txt in the directory from where I started Emacs.

Correct.

One extra:

Control returns to the terminal session immediately after typing the command.

~/bin/emacs

#!/bin/bash
EMACSPATH=/Applications/Emacs.app/Contents/MacOS


# Check if an emacs server is available
# (by checking to see if it will evaluate a lisp statement)


if ! (${EMACSPATH}/bin/emacsclient --eval "t"  2> /dev/null > /dev/null )
then
# There is no server available so,
# Start Emacs.app detached from the terminal
# and change Emac's directory to PWD


nohup ${EMACSPATH}/Emacs --chdir "${PWD}" "${@}" 2>&1 > /dev/null &
else
# The emacs server is available so use emacsclient


if [ -z "${@}" ]
then
# There are no arguments, so
# tell emacs to open a new window


${EMACSPATH}/bin/emacsclient --eval "(list-directory \"${PWD}\")"
else
# There are arguments, so
# tell emacs to open them


${EMACSPATH}/bin/emacsclient --no-wait "${@}"
fi


# Bring emacs to the foreground


${EMACSPATH}/bin/emacsclient --eval "(x-focus-frame nil)"
fi

This is my script for open emacs/emacsclient on osx.

#!/bin/bash


# Ensure (server-start) is added in your emacs init script.


EMACS=/Applications/MacPorts/Emacs.app/Contents/MacOS/Emacs
EMACSCLIENT=/Applications/Macports/Emacs.app/\
Contents/MacOS/bin/emacsclient


# test if client already exsit.
$EMACSCLIENT -e "(frames-on-display-list)" &>/dev/null


# use emacsclient to connect existing server.
if [ $? -eq 0 ]; then
$EMACSCLIENT -n "$@"
# open emacs.app instead.
else
`$EMACS "$@"` &
fi

Simple solution...

A lot of very complex solutions to this problem are posted here. That's fair because it seems non-trivial.

However, this solution works really well for me.

ec() {
emacsclient -n $@ 2> /dev/null
if [[ $? == 1 ]]; then
open -a Emacs.app  -- $@
fi
}

Usage

ec file [...]

Let's unpack what's happening:

  1. pass all the ec arguments to emacsclient and don't (-n) wait for emacs before continuing.
    1. If Emacs is already running, we're all done and you're editing.
  2. swallow up the error message posted by emacsclient when there's no emacs running. (2> /dev/null)
  3. Manually handle the exit code 1 ([[ $? == 1 ]])
    1. open Emacs.app and pass file arguments to it (paths will be correctly opened.)
    2. You're all done, and Emacs has opened your files.

In all of the above when using "open" - make sure you use the "--args" option

Do not do this:

alias emacs='open -a /Applications/Emacs.app $1'

Instead this:

alias emacs='open -a /Applications/Emacs.app --args $1'

the --args option prevents "open" from consuming various options intended for Emacs.

The top answer is good, but I wanted the emacs process to run in the background so I could still use my shell. This answer appeared to do what I wanted, but didn't start emacs in the right directory, meaning absolute paths were required (or hacks to append pwd to the paths which wouldn't work in all cases). Furthermore, simply using & meant that if I killed the terminal, emacs would also be killed.

I decided to use screen and a bash function, and the following solution works for me on macOS 10.15.6 and emacs 26.2 installed with brew:

function emacs() {
screen -d -m /Applications/Emacs.app/Contents/MacOS/Emacs "$@"
}

For the meaning of the -d -m command line flags, they have a special meaning when used together and so can essentially be thought of as one command line flag. The explanation is in the manpage:

Start screen in "detached" mode. This creates a new session but doesn't attach to it. This is useful for system startup scripts.

open_emacs() {
num=$(ps aux | grep -E "[E]macs-x86_64-10_14 --|[e]macs --" | wc -l)
if [ $num -eq 0 ]; then
echo "## starting emacs"
# Run in a subshell to remove notifications and close STDOUT and STDERR:
(&>/dev/null emacsclient -t -q &)
fi
}


alias e="open_emacs"

Following line (&>/dev/null emacsclient -t -q &) will start the emacs daemon if it is not running on the background.

  • macOS may have defined the app name starting with E (ex: Emacs-x86_64-10_14.app), based on that you can check whether the emacs daemon running on the background or not.

Just want to update a response to this question. Since it is still a relevant question, but now there is an easier solution:

brew install --cask emacs

When this installs Emacs, it does the behavior you requested, without further intervention. It even runs the Emacs Server on startup.

Files installed/linked by default:

ebrowse -> /Applications/Emacs.app/Contents/MacOS/bin/ebrowse
emacs -> /Applications/Emacs.app/Contents/MacOS/Emacs
emacsclient -> /Applications/Emacs.app/Contents/MacOS/bin/emacsclient
etags -> /Applications/Emacs.app/Contents/MacOS/bin/etags

BTW, this is now a recommended way of installing Emacs on MacOS:

https://www.gnu.org/software/emacs/download.html#nonfree