100

How do I launch GUI Emacs from the command line in OSX?

I have downloaded and installed Emacs from http://emacsformacosx.com/.

I'll accept an answer fulfilling all of the following criteria:

  1. The emacs window opens in front of my terminal window.
  2. Typing "emacs" launches a GUI Emacs window. Finding files in that window will default to looking in the directory from where I started Emacs.
  3. Typing "emacs foo.txt" when foo.txt exists launches a GUI Emacs window with foo.txt loaded.
  4. 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.
Johan Walles
  • 1,447
  • 2
  • 15
  • 23
  • Which of those criteria are not met by entering 'emacs' at a terminal prompt? Your requirements describe the default behaviour on Linux. I haven't used a Mac in a while, but I think the trick was just finding the right program to execute - emacs.app maybe? – Tyler Apr 16 '12 at 16:15
  • 8
    Tyler, coming from a Linux background I'm with you all the way; just typing "emacs" at the prompt should be all I need to do. Doing that on OSX launches the text mode Emacs in the terminal window however (thus failing criteria 1), and that's not what I want. – Johan Walles Apr 17 '12 at 06:46
  • 1
    Johan - have you found a solution in the meantime? I am struggling with the same problems and think about starting a bounty. Especially annoying is that calling emacs (and not the Emacs.app) from the command line opens a window in the background... – alexurba Oct 16 '12 at 19:44
  • @alexurba, no, no answer :(. I'm kind of getting used to the broken behaviors though... Why people keep upvoting the wrong answer below is also a mystery. – Johan Walles Oct 24 '12 at 09:50
  • @JohanWalles I upvoted the answer because this is more the emacs way (in my opinion). Your stringent requirements of how you expect Emacs to work don't match reality. I have one Emacs instance running all the time. I use emacsclient via an alias and set as my `EDITOR` environment variable to open new files within that. I also use emacs' `midnight-mode` to clear files out of that one emacs that haven't been touched in a few days. – Doug Harris Mar 21 '13 at 18:01
  • 1
    @DougHarris My requirements match reality on any Linux distro, that's where they come from. I'm happy you have a found a workflow that works for you. Cheers! – Johan Walles Apr 12 '13 at 13:50
  • 2
    I don't know whether it works on OSX but you could try: [`emacsclient -c -a "" "$@"` command](http://stackoverflow.com/a/4460943/4279) – jfs May 05 '13 at 04:43
  • @J.F.Sebastian, that's the best answer so far! It does fail criteria 2, but it's still better than any of the other suggestions here. And it still starts Emacs even in case 2, which is an improvement over some of the other candidates. If you put that as an answer I'm gonna upvote it! – Johan Walles May 14 '13 at 11:11
  • If you want an additional criteria -- namely, start Emacs in the background, then please see my answer which improves upon this one: http://stackoverflow.com/a/26565655/109618 – David J. Oct 25 '14 at 18:17

15 Answers15

120

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.

David Caldwell
  • 1,493
  • 1
  • 11
  • 7
  • 1
    Works great. Bounty forthcoming. – Tamzin Blake Jul 11 '13 at 17:30
  • 2
    On Mavericks if I am in folder `~/foo` and want to open `bar.txt` I type `gmacs bar.txt` but it creates a new file at `~/bar.txt` instead of opening `~foo/bar.txt`. Am I doing something wrong? – Daniel Compton Jan 29 '14 at 10:49
  • (x-focus-frame nil) doesn't work for me. I got this error:`Debugger entered--Lisp error: (void-function x-focus-frame) (x-focus-frame nil) eval-buffer(# nil "/Users/thaitrinh/.emacs.d/init.el" nil t) ; Reading at buffer position 20` when I run `emacs --debug init`. Please help! – hoang tran Oct 08 '14 at 14:07
  • I don't like the command blocking after I launch emacs (i.e., not returning to the prompt), so I made the following modification to launch from a backgrounded process (I can't put 2 lines of code ina comment nicely, so here's a pastebin link: http://pastebin.com/Wm17Hdhh ) – mpettis Apr 21 '15 at 02:54
  • 2
    Where is the .emacs file? – Bren Jul 04 '15 at 22:03
  • @Bren Typically .emacs is in your home directory, and can be referenced from the Bash command line as ~/.emacs where the tilde represents a shortcut for your home directory. – kmarsh Jul 15 '15 at 17:40
  • 1
    You can't add (x-focus-frame nil) just anywhere, it has to be within the (custom-set-variables) expression, which emacs will create for you once you set anything through customization. Just customize something from the menu bar, like setting "blinking cursor" on (then off if you dislike it) and that section will be created in your .emacs. Also, is this even tested? I'm not sure emacs on Cocoa will even respect this setting. – Chuck Adams Sep 24 '15 at 17:08
  • there is already a `emacs` with content inside. Should I overwrite it? – mengg Oct 18 '16 at 14:01
  • #1 is not quite working for me. I added (x-focus-frame nil) to the auto-generated .emacs file under the root directory, but no luck. I'm using Emacs 26.1. Any idea what am I missing? – Felipe Centeno Nov 07 '18 at 00:26
  • @ChuckAdams "x-focus-frame" is a function and not a customization. Putting it in the customization area does nothing. `C-h f x-focus-frame RET` for the docs. – David Caldwell Mar 22 '19 at 09:34
  • Thanks David! If you prefer using emacs in terminal (i.e. no X), I recommend changing the second line in the script to: ```/Applications/Emacs.app/Contents/MacOS/Emacs -nw "$@"``` – Mircea Jan 29 '20 at 10:42
  • what does `(x-focus-frame nil)` stands for? – alper Jan 24 '21 at 10:17
75

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!

David J.
  • 31,569
  • 22
  • 122
  • 174
Chris McMahan
  • 2,640
  • 1
  • 17
  • 10
  • 4
    Hi Chris! Your first answer fails criteria 2 and 4. Your second answer fails criterion 2. I'm looking for a solution that fulfills all of the numbered criteria. Regards /Johan – Johan Walles Apr 17 '12 at 06:43
  • 4
    It seems that all of your issues could be solved if you merely used emacs itself to load the files, rather than relying on a command-line to launch a new instance each time. I typically start emacs at the start of my day (if it's not still running), and use it to load files, change directories, create new files and whatever else I want without ever touching the terminal window. – Chris McMahan Apr 17 '12 at 14:59
  • I have to say, there are several of these questions on this site that deal with this question, but this is the only one that fully solves the problem of also opening a file, in a short eloquent manner. – tylerthemiler Jun 26 '12 at 00:08
  • 3
    @tylerthemiler, where's the answer that fully solves the problem? Both of the answers in this answer fail criterion 2 and the first one fails 4 as well. – Johan Walles Oct 24 '12 at 09:49
  • This solves everything except creating the file if it doesn't exist: alias emacs='open -a /Applications/Emacs.app $1' It will launch emacs if it is not open, and open a file if you give it a file argument. As far as creating the file if it doesn't exist. This is very easy to do once emacs opens, so this is a sufficient solution for me. – tylerthemiler Oct 25 '12 at 19:52
  • Which is of course, the answer listed above :P I think I was doing it wrong originally. – tylerthemiler Oct 25 '12 at 19:53
  • @tylerthemiler, neither answer here makes Emacs default to looking for files in the directory in which I started it (point 2). This makes not creating non-existing files (point 4) worse. I'm glad this solution is good enough for you though, happy hacking! – Johan Walles Nov 02 '12 at 09:34
  • Yeah, generally when I have emacs open I just use the emacs file browser to move around :) and I actually have the terminal based emacs installed to, and use "macs" as my alias, so if I do just want to edit a file quickly, I can just use traditional "emacs". Fits all my use cases. – tylerthemiler Nov 02 '12 at 19:27
  • 6
    A little tact goes a long way in getting a question answered. So does a little Googling. – duma Apr 03 '13 at 17:15
  • I like this solution. As per #2 above, why not just `emacs .` or `ec .` to open all files in directory in emacs instance? –  May 04 '13 at 18:23
  • I'm sure emacsclient is the way to go. In: http://www.xsteve.at/prg/emacs/power-user-tips.html (scroll down `function ec`) it a definition using pwd is shown. One could come up with a script that detects a call without arguments and uses pwd instead. – bdecaf May 29 '13 at 10:59
  • I'm using macOS 10.15 (Catalina), and it seems that this works the first time (when Emacs is not already open), but does not work the second time (when an Emacs window is already open). Do you know how to fix this? – user102008 Oct 18 '19 at 03:48
10

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 "$@" &
Community
  • 1
  • 1
David J.
  • 31,569
  • 22
  • 122
  • 174
  • 1
    This fixes a problem with OSX (perhaps starting with 10.9 Mavericks). As of 10.9, the "not recommended" method fails, where as up to at least 10.6, the not recommended did sync the shell $PWD and Emacs (pwd). David's answer might be elsewhere, but how do you get search engines to understand: "pwd not pwd"? – infogizmo Jan 08 '16 at 13:12
  • Both snippets in this answer don't start emacs in the correct directory when I tested on macOS 10.15.6 and Emacs 26.2. – gsgx Sep 11 '20 at 22:46
5

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
FooF
  • 4,323
  • 2
  • 31
  • 47
The Dave
  • 49
  • 1
  • 2
4

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.

mforbes
  • 7,062
  • 3
  • 16
  • 21
4

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

4

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
sbecker11
  • 107
  • 1
  • 6
  • This only works for an existing file, it wont create one if its not there –  May 08 '19 at 10:39
  • I'm using macOS 10.15 (Catalina), and it seems that this works the first time (when Emacs is not already open), but does not work the second time (when an Emacs window is already open). Do you know how to fix this? – user102008 Oct 18 '19 at 03:49
4

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.
ocodo
  • 29,401
  • 18
  • 105
  • 117
1

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.

jackkamm
  • 541
  • 1
  • 4
  • 11
  • 1
    My particular build/install doesn't have that issue, but there is an issue with your solution. If you try to open more than one file, only the first will expand to the PWD directory. The rest will not have a $PWD path prefixed. – kmarsh Jul 15 '15 at 17:51
0

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.

rake
  • 201
  • 2
  • 9
0

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
Koren.H
  • 9
  • 3
0

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.

user3696153
  • 568
  • 5
  • 15
  • For some reason, when I tested this on macOS 10.15.6 and Emacs 26.2 the emacs working directory was set to my home directory, meaning I couldn't open files using relative paths. This did fix the issue of open non-existent files though. – gsgx Sep 11 '20 at 22:50
0

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.

gsgx
  • 12,020
  • 25
  • 98
  • 149
  • The question explicitly requested Emacs in a GUI window, and this opens Emacs in a terminal session. – Johan Walles Sep 12 '20 at 07:36
  • @JohanWalles, this opens Emacs in a GUI window. – gsgx Sep 13 '20 at 20:45
  • `screen` threw me off, now that I read more carefully I realize you're right. My apologies @gsingh2011. – Johan Walles Sep 15 '20 at 04:15
  • Could you edit or comment to explain the effect of `screen -d -m` for this case? – Joshua Goldberg Nov 27 '20 at 17:19
  • @JoshuaGoldberg they start screen in detached mode, so it runs in the background and you can continue to use your terminal session as normal. I've edited the answer to include this. – gsgx Nov 29 '20 at 03:33
  • That explains why it doesn't start an interactive screen session, but what does it buy over not using screen at all? – Joshua Goldberg Nov 29 '20 at 07:04
  • 1
    @JoshuaGoldberg, I think I answered that in the answer. I wanted to run emacs in the background and retain use of my terminal. There are other answers that provided similar functionality, but they came with some downsides, like starting in the wrong directory or tying the emacs process lifetime to the terminal process lifetime. My answer (using screen) avoids those shortcomings. – gsgx Nov 30 '20 at 23:15
0
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.
alper
  • 2,919
  • 9
  • 53
  • 102
0

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

RobMac
  • 793
  • 9
  • 13