Create a gist now

Instantly share code, notes, and snippets.

Start Emacs.app from CLI
#!/usr/bin/perl
# Emacs starter for Emacs mac port
# Thanks to Aquamacs Project and David Reitter
my $args = "";
my $tmpfiles = "";
for my $f (@ARGV) {
$args .= '"'.$f.'" ';
$tmpfiles .= '"'.$f.'" ' if (! -e $f);
}
system("touch $args") if ($tmpfiles);
system("open -a /Applications/Emacs.app $args");
# delay deletion because AE drag&drop doesn't work with non-existing documents
system("(sleep 3; rm $tmpfiles) &") if ($tmpfiles);
exit;
@ptb
ptb commented May 19, 2015

I rewrote this as a shell script and added the capability to accommodate filenames with spaces:

#!/bin/sh

if [ -e '/Applications/Emacs.app' ]; then
  t=()

  if [ ${#@} -ne 0 ]; then
    while IFS= read -r file; do
      [ ! -f "$file" ] && t+=("$file") && /usr/bin/touch "$file"
      file=$(echo $(cd $(dirname "$file") && pwd -P)/$(basename "$file"))
      $(/usr/bin/osascript <<-END
        if application "Emacs.app" is running then
          tell application id (id of application "Emacs.app") to open POSIX file "$file"
        else
          tell application ((path to applications folder as text) & "Emacs.app")
            activate
            open POSIX file "$file"
          end tell
        end if
END
      ) &  # Note: END on the previous line may be indented with tabs but not spaces
    done <<<"$(printf '%s\n' "$@")"
  fi

  if [ ! -z "$t" ]; then
    $(/bin/sleep 10; for file in "${t[@]}"; do
      [ ! -s "$file" ] && /bin/rm "$file";
    done) &
  fi
else
  vim -No "$@"
fi

Since I switched from vi, I can't help but to type vi filename every time, so I saved this script as /usr/local/bin/vi. In the off chance I haven't yet installed Emacs.app, it uses the built in system vim instead.

@railwaycat
Owner

Thanks @ptb :)

@lmartins
lmartins commented Jun 8, 2015

Sorry to ask guys, how can I install this?

@InAbsentia

@lmartins Paste into a file named emacs (or whatever you want the command to be) in a directory in your path (ahead of the location of the existing emacs command). Then chmod +x /path/to/emacs.

@jasonm23
jasonm23 commented Oct 1, 2016

It'd be better to use emacsclient (and kick off Emacs.app as the alternate editor if it's not running already.)

@tasmo
tasmo commented Oct 25, 2016

The command open with the argument -a does not need the full application path. It's not useless but if you have installed Emacs in a different location I would consider just to use

system("open -a Emacs $args");
@mwolson
mwolson commented Nov 24, 2016

Here's a variation that ensures Emacs.app is launched, waits for it to be ready, and then uses emacsclient to open the file in a GUI frame and wait for edits to be completed.

#!/bin/sh

CLIENT=/Applications/Emacs.app/Contents/MacOS/bin/emacsclient

$(/usr/bin/osascript <<-END
  tell application ((path to applications folder as text) & "Emacs.app")
    activate
  end tell
END
)

while ! "$CLIENT" -e '"pass"' 2>&1 | grep '"pass"' > /dev/null; do
    sleep 0.3
done

if test "$#" -gt 0; then
    exec "$CLIENT" -c $@
fi
@railwaycat
Owner

Hi @mwolson, thanks for the update. I believe your starter script works for Nextstep port (although I haven't verify that by myself), but it not works for Mac port. Because Emacs Mac port lacks multi-tty support, which means, emacsclient from mac port can only able to create tty frames but not GUI frames.

@ivanbrennan
ivanbrennan commented Jan 26, 2017 edited

@ptb Just curious, why do you use a sub-shell to initialize t in your script? Any reason not to use t="" instead?

Edit: After some digging, I see I was misinterpreting the parentheses and mistaking an array assignment for a sub-shell.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment