August 4, 2022

Emacs on Macos Monterey

Intro

Got a new computer from work, this is some quick notes on how my Emacs setup looks.

Run Emacs as daemon with LaunchAgent. Fetch mails periodically with mbsync via LaunchAgent.

Install

  brew install --cask emacs
  brew install mu
  brew install isync
  brew install gpg
  brew ls --verbose emacs
  brew ls --verbose mu

Mu4a

Replace USERNAME with your info.

  mkdir -p ~/.mail/work ~/.mail/gmail
  mu init --maildir=~/.mail --my-address=USERNAME@gmail.com --my-address=USERNAME@work.com
  mu index
  mbsync -Va
  mu index

Mbsync config

  cat ~/.mbsyncrc
  # ========== 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 ==========

Emacs daemon via LaunchAgent

  cat ~/Library/LaunchAgents/gnu.emacs.plist

Replace USERNAME with your info.

  <?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-daemon</string>
      </array>
      <key>RunAtLoad</key>
      <true/>
      <key>StandardErrorPath</key>
      <string>/tmp/gnu-emacs-daemon.log</string>
      <key>StandardOutPath</key>
      <string>/tmp/gnu-emacs-daemon.log</string>
      <key>UserName</key>
      <string>USERNAME</string>
    </dict>
  </plist>

Verify that the plist file is correct.

  plutil -lint ~/Library/LaunchAgents/gnu.emacs.plist
  /Users/USERNAME/Library/LaunchAgents/gnu.emacs.plist: OK

Start, stop and list service.

  launchctl load -w /Users/USERNAME/Library/LaunchAgents/gnu.emacs.plist
  launchctl unload /Users/USERNAME/Library/LaunchAgents/gnu.emacs.plist
  launchctl list

Fetch mails periodically

  cat ~/Library/LaunchAgents/periodic.mbsync.plist

Replace USERNAME with your info.

  <?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>USERNAME</string>
    </dict>
  </plist>

Verify that the plist file is correct.

  plutil -lint ~/Library/LaunchAgents/periodic.mbsync.plist
  /Users/USERNAME/Library/LaunchAgents/periodic.mbsync.plist: OK

Start, stop and list service.

  launchctl load -w /Users/USERNAME/Library/LaunchAgents/periodic.mbsync.plist
  launchctl unload /Users/USERNAME/Library/LaunchAgents/periodic.mbsync.plist
  launchctl list

Script that fetches mails and updates the mail index.

  cat ~/.bin/mbsync-task
  #!/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 $?

Emacsclient

Automator script that's wrapped into an application and placed in the Applications folder.

  emacsclient -nc

Utils

Convert a plist XML file into a JSON file.

  plutil -convert json -r ~/Library/LaunchAgents/gnu.emacs.plist
  cat ~/Library/LaunchAgents/gnu.emacs.plist
  {
      "KeepAlive" : true,
      "Label" : "gnu.emacs",
      "ProgramArguments" : [
          "\/opt\/homebrew\/bin\/emacs",
          "--fg-daemon"
      ],
      "RunAtLoad" : true,
      "StandardErrorPath" : "\/tmp\/gnu-emacs-daemon.log",
      "StandardOutPath" : "\/tmp\/gnu-emacs-daemon.log",
      "UserName" : "USERNAME"
  }

Convert it back to XML

  plutil -convert xml1 ~/Library/LaunchAgents/gnu.emacs.plist

Resources

  man launchd
  man launchctl
  man launchd.plist
  man plutil
  man plist

Powered by Hugo & Kiss.