Better MacOS integration with Emacs
I run two instances of Emacs on my MacOS laptop ... one for "work" and another for IRC, et.al. This explains some of what I'm doing.
This commit is contained in:
parent
d24ce8b49c
commit
624125dc06
2 changed files with 221 additions and 2 deletions
219
README-MacOS.org
Normal file
219
README-MacOS.org
Normal file
|
@ -0,0 +1,219 @@
|
|||
#+title: Installing Emacs on MacOS
|
||||
#+author: Howard X. Abrams
|
||||
#+email: howard.abrams@gmail.com
|
||||
#+date: 2022-09-02 September
|
||||
#+tags: emacs macos
|
||||
|
||||
These instructions originally came from [[https://jherrlin.github.io/posts/emacs-on-macos-monterey/][this essay]], as it runs Emacs as dæmon with LaunchAgent. Also fetch mails periodically with =mbsync= via LaunchAgent.
|
||||
* Install
|
||||
Best success comes from using the [[https://github.com/d12frosted/homebrew-emacs-plus][emacs-plus]] installation from [[https://brew.sh/][Homebrew]]. To begin, add the /cask/:
|
||||
#+begin_src sh
|
||||
brew tap d12frosted/emacs-plus
|
||||
#+end_src
|
||||
I find that I need to … at least, on my work computer, install two different versions of Emacs that I use to distinguish one for “work” and the other for other activities, like IRC and [[file:ha-feed-reader.org][elfeed]]. To that end, I run the following commands to install Emacs:
|
||||
#+begin_src sh
|
||||
brew install emacs-plus@28 --with-native-comp --with-mailutils --with-imagemagick
|
||||
#+end_src
|
||||
And the following for “work”:
|
||||
#+begin_src sh
|
||||
brew install emacs-plus@29 --with-native-comp
|
||||
#+end_src
|
||||
* Supporting Packages
|
||||
Now install all the extras:
|
||||
#+begin_src sh
|
||||
brew install mu
|
||||
brew install isync
|
||||
brew install gpg
|
||||
#+end_src
|
||||
** Mu4a
|
||||
See [[file:ha-email.org][ha-email]] for better instructions.
|
||||
#+begin_src sh
|
||||
mkdir -p ~/.mail/work ~/.mail/gmail
|
||||
mu init --maildir=~/.mail --my-address=howard.abrams@gmail.com --my-address=howard@howardabrams.com
|
||||
mu index
|
||||
mbsync -Va
|
||||
mu index
|
||||
#+end_src
|
||||
** Mbsync config
|
||||
See [[file:ha-email.org][ha-email]] for better instructions.
|
||||
#+begin_src sh
|
||||
cat ~/.mbsyncrc
|
||||
#+end_src
|
||||
Basic configuration, that I actually supersede.
|
||||
#+begin_src conf
|
||||
# ========== Gmail ==========
|
||||
IMAPAccount gmail
|
||||
Host imap.gmail.com
|
||||
User username@gmail.com
|
||||
PassCmd "/opt/homebrew/bin/gpg --quiet --for-your-eyes-only --no-tty --decrypt ~/.password-store/mbsync/gmail.gpg"
|
||||
AuthMechs LOGIN
|
||||
SSLType IMAPS
|
||||
|
||||
IMAPStore gmail-remote
|
||||
Account gmail
|
||||
|
||||
MaildirStore gmail-local
|
||||
Subfolders Verbatim
|
||||
Path ~/.mail/gmail/
|
||||
Inbox ~/.mail/gmail/Inbox
|
||||
|
||||
Channel gmail
|
||||
Far :gmail-remote:
|
||||
Near :gmail-local:
|
||||
Patterns * ![Gmail]* "[Gmail]/Sent Mail" "[Gmail]/Starred" "[Gmail]/All Mail"
|
||||
Expunge None
|
||||
CopyArrivalDate yes
|
||||
Sync All
|
||||
Create Near
|
||||
SyncState *
|
||||
# ========== Gmail ==========
|
||||
#+end_src
|
||||
* Dæmon Processes
|
||||
On the Mac, =cron= has been removed and replaced with =LaunchAgent=. I find my [[file:ha-capturing-notes.org::*Push MacOS-Specific Content][ICanHazShortcut]] process pretty simple to start Emacs, so I’m not sure about this dæmon, but …
|
||||
** Emacs dæmon via LaunchAgent
|
||||
Notice that =UserName= section should be your =$USER= value.
|
||||
#+begin_src xml :tangle ~/Library/LaunchAgents/gnu.emacs.plist
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>KeepAlive</key>
|
||||
<true/>
|
||||
<key>Label</key>
|
||||
<string>gnu.emacs</string>
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>/opt/homebrew/bin/emacs</string>
|
||||
<string>--fg-dæmon</string>
|
||||
</array>
|
||||
<key>RunAtLoad</key>
|
||||
<true/>
|
||||
<key>StandardErrorPath</key>
|
||||
<string>/tmp/gnu-emacs-dæmon.log</string>
|
||||
<key>StandardOutPath</key>
|
||||
<string>/tmp/gnu-emacs-dæmon.log</string>
|
||||
<key>UserName</key>
|
||||
<string>howard</string>
|
||||
</dict>
|
||||
</plist>
|
||||
#+end_src
|
||||
|
||||
Verify that the plist file is correct.
|
||||
#+begin_src sh
|
||||
plutil -lint ~/Library/LaunchAgents/gnu.emacs.plist
|
||||
#+end_src
|
||||
|
||||
Start, stop and list service.
|
||||
#+begin_src sh
|
||||
launchctl load -w /Users/USERNAME/Library/LaunchAgents/gnu.emacs.plist
|
||||
launchctl unload /Users/USERNAME/Library/LaunchAgents/gnu.emacs.plist
|
||||
launchctl list
|
||||
#+end_src
|
||||
** Fetch mails periodically
|
||||
Let’s make another dæmon for fetching mail. Again, replace =UserName= with your user account name.
|
||||
#+begin_src xml :tangle ~/Library/LaunchAgents/periodic.mbsync.plist
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>KeepAlive</key>
|
||||
<true/>
|
||||
<key>Label</key>
|
||||
<string>periodic.mbsync</string>
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>/Users/USERNAME/.bin/mbsync-task</string>
|
||||
</array>
|
||||
|
||||
<key>StandardOutPath</key>
|
||||
<string>/tmp/mbsync-task.log</string>
|
||||
|
||||
<key>StandardErrorPath</key>
|
||||
<string>/tmp/mbsync-task.log</string>
|
||||
|
||||
<key>ThrottleInterval</key>
|
||||
<integer>180</integer>
|
||||
|
||||
<key>RunAtLoad</key>
|
||||
<true/>
|
||||
|
||||
<key>UserName</key>
|
||||
<string>howard</string>
|
||||
</dict>
|
||||
</plist>
|
||||
#+end_src
|
||||
|
||||
Verify that the plist file is correct.
|
||||
#+begin_src sh
|
||||
plutil -lint ~/Library/LaunchAgents/periodic.mbsync.plist
|
||||
#+end_src
|
||||
|
||||
Start, stop and list service.
|
||||
#+begin_src sh
|
||||
launchctl load -w /Users/USERNAME/Library/LaunchAgents/periodic.mbsync.plist
|
||||
launchctl unload /Users/USERNAME/Library/LaunchAgents/periodic.mbsync.plist
|
||||
launchctl list
|
||||
#+end_src
|
||||
|
||||
Script that fetches mails and updates the mail index.
|
||||
#+begin_src sh :tangle ~/.bin/mbsync-task :shebang #!/bin/bash
|
||||
echo ""
|
||||
echo "Running $(date +"%Y-%m-%d %H:%M")"
|
||||
/opt/homebrew/bin/mbsync -Va
|
||||
echo "Exit code:"
|
||||
echo $?
|
||||
/opt/homebrew/bin/emacsclient -e '(mu4e-update-index)'
|
||||
echo "Exit code:"
|
||||
echo $?
|
||||
#+end_src
|
||||
* Emacsclient
|
||||
Simple /Automator/ script that's wrapped into an application and placed in the =Applications= folder. Select *New Document*, then select *Application*. Open the *Library*, and drag the *Run Shell Script* to the /workflow/. In the box, add this:
|
||||
#+begin_src sh
|
||||
/usr/local/bin/emacsclient -nc --socket-name work $*
|
||||
#+end_src
|
||||
Change the *Pass Input* to =as arguments=.
|
||||
|
||||
Select to *Save* as =Emacsclient= into the *Applications* folder.
|
||||
** Utils
|
||||
Convert a plist XML file into a JSON file. Not sure why this is important to know…
|
||||
#+begin_src sh
|
||||
plutil -convert json -r ~/Library/LaunchAgents/gnu.emacs.plist
|
||||
#+end_src
|
||||
Which should look a bit like:
|
||||
#+begin_src js
|
||||
{
|
||||
"KeepAlive" : true,
|
||||
"Label" : "gnu.emacs",
|
||||
"ProgramArguments" : [
|
||||
"\/opt\/homebrew\/bin\/emacs",
|
||||
"--fg-dæmon"
|
||||
],
|
||||
"RunAtLoad" : true,
|
||||
"StandardErrorPath" : "\/tmp\/gnu-emacs-dæmon.log",
|
||||
"StandardOutPath" : "\/tmp\/gnu-emacs-dæmon.log",
|
||||
"UserName" : "USERNAME"
|
||||
}
|
||||
#+end_src
|
||||
|
||||
Convert it back to XML
|
||||
#+begin_src sh
|
||||
plutil -convert xml1 ~/Library/LaunchAgents/gnu.emacs.plist
|
||||
#+end_src
|
||||
** Resources
|
||||
#+begin_src sh
|
||||
man launchd
|
||||
man launchctl
|
||||
man launchd.plist
|
||||
man plutil
|
||||
man plist
|
||||
#+end_src
|
||||
|
||||
#+DESCRIPTION: A literate programming file for installing a dæmon version of Emacs on MacOS.
|
||||
|
||||
#+PROPERTY: header-args:sh :tangle no
|
||||
#+PROPERTY: header-args:emacs-lisp :tangle no
|
||||
#+PROPERTY: header-args :results none :eval no-export :comments no
|
||||
|
||||
#+OPTIONS: num:nil toc:nil todo:nil tasks:nil tags:nil date:nil
|
||||
#+OPTIONS: skip:nil author:nil email:nil creator:nil timestamp:nil
|
||||
#+INFOJS_OPT: view:nil toc:nil ltoc:t mouse:underline buttons:0 path:http://orgmode.org/org-info.js
|
|
@ -118,7 +118,7 @@ Next, on every reboot, start the agent:
|
|||
Since =brew link gpg= doesn’t always work, this helper function may find the executable:
|
||||
#+begin_src emacs-lisp
|
||||
(defun executable (path)
|
||||
"Return PATH if it is executable, see `file-executable-p'."
|
||||
"Return PATH if executable, see `file-executable-p'."
|
||||
(let ((epath (first (file-expand-wildcards path))))
|
||||
(when (file-executable-p epath) epath)))
|
||||
|
||||
|
@ -174,7 +174,7 @@ Sure the Emacs application will almost always have the =server-start= going, but
|
|||
the native-comp model, but I reserve the right to change this."
|
||||
(and (f-dir? "~/work")
|
||||
;; (string-match "emacs-plus@28" exec-directory)
|
||||
(string-match "Emacs-Work" exec-directory)))
|
||||
(string-match "emacs-plus@29" exec-directory)))
|
||||
#+end_src
|
||||
|
||||
And now start the server with an appropriate tag name:
|
||||
|
|
Loading…
Reference in a new issue