1

I use emacs and I have written a script which is half in bash and half in AppleScript in order to do the following (first I write the code and then the pseudocode). We assume that a emacs daemon is running.

pseudocode:

if (no emacs GUI process is active or a process is active but no window is present)
then 
    open a new emacs window using emacsclient 
    and 
    put that window in foreground
else
    open the app Emacs.app (so no new instance is created and we simply put 
                            the focus on the existing emacs window)

code for "switchToEmacs.sh"

#!/bin/bash
openedWindows=$(/usr/bin/osascript ~/emacsWindowsCount.scpt)
if [ $openedWindows -eq 0 ]; then
    /Applications/Emacs.app/Contents/MacOS/bin/emacsclient -n -c -e  "(select-frame-set-input-focus (selected-frame))"
else
    open -a Emacs   
fi

code for "emacsWindowsCount.scpt" (used in the previous script, I have compiled the code with osacompile for performance)

tell application "System Events"
    if exists (process "Emacs") then
    else
        return 0
    end if
    tell application "Emacs"
        set numberOfWindows to (count windows)
    end tell
    return numberOfWindows
end tell    

I have mapped switchToEmacs.sh to a shortcut using Alfred 3 and it does what I expect it to do, but it is slow! Not extremely slow but the switch is not immediate and I have to wait about 0.3 seconds. Conversely if I have an emacs window opened and type "emacs" in the spotlight, then the transition is immediate, so I would like to remove that unnecessary waiting.

Since I hate that waiting time (it seems very short but when you need to navigate a lot trough applications it becomes awkward) for now I am doing the following: I have removed the emacs deamon, every time I log in I start emacs.app, when I need to close the emacs app I don't use CMD+Q but CMD+H, when I need to recall emacs I simply launch emacs.app (trough an Alfred 3 shortcut) so I get emacs focus. With this workaround the transition to emacs is immediate, but I would prefer my script for two reasons: first, with the script so I can use emacs from terminal before having launched an emacs instance opening emacs.app, but the real reason is that using this method if I type "emacsclient -t myFile" in terminal and then I close the buffer returning to the terminal, then the emacs windows (the emacs.app) will get the focus, even if I have not given it to it. This is really awkward.

IMPORTANT EDIT: I noticed that opening a new instance is immediate, what takes time is open -a Emacs. I have tried to replace it with tell application "Emacs" to activate window 1 (compiled) but it is still slow. Any ideas?

EDIT: I have achieved perfect performance using this free tool https://sabi.net/nriley/software/#appswitch Now there is still a little delay but it is due to the rest of the code.

  • I have investigated, opening a new instance is immediate, what takes time is open - a Emacs, see the edit – Nisba Jul 12 '17 at 13:49
  • You said "what takes time is open - a Emacs,", and on my system open -a Emacs is instantaneous. The emacsWindowsCount.scpt is where I see the big time lag, if Emacs is not open it takes 6 to 7 seconds for it to return 0 on my system. – user3439894 Jul 12 '17 at 14:04
  • Which Emacs GUI app are you using? Where did you acquire it? – user3439894 Jul 12 '17 at 14:18
  • @user3439894 I have downloaded this version emacsformacosx.com – Nisba Jul 12 '17 at 14:42
3

I usually just run

emacsclient -a emacs FILE

or

emacsclient -a SHELL-SCRIPT-WHICH-STARTS-EMACS-WITH-PARAMETERS FILE

and let emacsclient figure out the rest.

  • @user3439894 so SHELL-SCRIPT-WHICH-STARTS-EMACS-WITH-PARAMETERS can use open -a Emacs to get things rolling :-) – nohillside Jul 14 '17 at 22:15
-1

Is it the osa script that's taking the time?

I use a similar approach to you, but do all the processing in bash. Here's the bash function I use (in Linux, I'm not near my Mac to verify portability at the moment):

ec ()
{
    running=$(pgrep -u $USER -c emacs)
    if [ $running -eq 0 ]; then
        emacs --geometry 85 --fullheight $* &
        return 0
    fi
    emacsclient --no-wait $*
    return 0
}
  • it gives error on pgrep, later I will try modyfing it. For the moment thank you – Nisba Jul 12 '17 at 14:12
  • I have installed pgrep with brew install proctools but the code is not working for me, I keep trying – Nisba Jul 12 '17 at 14:15
  • @Nisba, pgrep is already a part of macOS, its the BSD version, and all you need is pgrep Emacs, for the GUI version, to return its PID, if it's running. – user3439894 Jul 12 '17 at 14:21
  • Sorry, it was only the command -c which did not work. I have found an acceptable solution, see the edit, but if you can make your code work on macOS I would be glad. – Nisba Jul 12 '17 at 15:02
  • 1
    @patrix The formatting is a bit messed up (I'll edit to correct it). It's a single ampersand because I want to run emacs in the background. – woolfie Jul 14 '17 at 16:16

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .