Act as a share target for opening things in daemon mode Emacs, providing more macOS app-like behaviour:
- ensure the Emacs daemon is running
- ensure an Emacs frame is open
- open the given thing in Emacs
- raise the Emacs frame to the front
Handles files, web links, web page selection (Safari), and org-protocol://
links.
Targeting macOS Emacs formulas which run in daemon mode via brew service
communicating via emacsclient
, initially Emacs Plus.
- To make opening things in Emacs and opening Emacs itself “Just Work”, without having to think about what state Emacs is currently in, and without having to always leave an Emacs frame open.
- To be able to open more things in Emacs than is supported natively, including web links (for org-capture) and
org-protocol://
links, to support easier sharing from other apps to Emacs. - To achieve the above in a single tool with minimal configuration.
- Initial app and CLI build
- Most of the CLI variants implemented, without daemon management.
- Expect frequent history rewrites.
- See roadmap below for rough plan.
- Not ready for public use.
- Syntax:
emacsopen [OPTIONS] [FILE...]
OPTIONS: [--tty/-t] | [--eval/-e] | [--block/-b] [--create-frame/-c]
--tty/-t
Use Emacs in terminal mode.--eval/-e
Evaluate Emacs Lisp commands.--block/-b
Block (wait) until Emacs has finished handling the given file or link. Default is to not wait.--create-frame/-c
Always create a new frame rather than the default of reusing an existing one.- The
--tty/-t
and--eval/-e
options are mutually exclusive, and incompatible with--block/-b
and--create-frame/-c
.
FILE...
A set of files or an org-protocol link to open in Emacs.
- Examples:
- To activate an Emacs frame, preferring to reuse an one:
emacsopen
- To open a file or org-protocol link in the GUI:
emacsopen file.org
emacsopen org-protocol://...
- To open a file in the terminal:
emacsopen --tty README.org
- To just ensure that the Emacs daemon is ready for commands:
emacsopen --eval nil
- To activate an Emacs frame, preferring to reuse an one:
- To just ensure that emacsclient is ready:
emacsopen --eval nil
- [X] Address potential roadblocks to see if viable at all: try calling
emacsclient
from the app - [X] Skeleton app
- [X] Skeleton
emacsopen
command - [X] XCode project for app, using CLI/library as internal dependency
- [X] Skeleton
- [ ] Read config (see also ‘Auto detection’ below)
- [ ] Location of
emacsclient
- Can rely on PATH for the terminal case.
- [ ] Name of brew service to use for starting Emacs daemon
- [ ]
org-protocol://
scheme config- Follow the most popular convention by default.
- [ ] Location of
- [ ] Handle opening files via drag and drop and opening via Finder (with frame already open). Or maybe just as ‘Open With…’
- [ ] Handle reactivation via
tell application "EmacsOpen" to activate
when open and when closed - [ ] Register as default handler for
*.org
files - [-] Handle
org-protocol://
links (with frame already open)- [ ] To open an existing Org node by its Org ID
- [ ] To capture a web page, with url, title, and optional selected text
- [X] To trigger
org-capture
, eg to add an inbox item
- [ ] Consider adding an additional URL handler too. Options
org-id://foo&create-frame=n
org://open?id=foo&create-frame=n
emacs://open?id=foo
emacsopen://quit
- [X] Always activate Emacs top window
- [X] Open frame if necessary
- [ ] Start daemon if necessary, waiting until ready for
emacsclient
commands - [X]
open -a EmacsOpen
should open Emacs, creating a frame if necessary, and activate Emacs - [X]
open -a EmacsOpen foo.txt
should open Emacs, creating a frame if necessary, and activate Emacs, with the given (existing) file - [ ] Ensure useful for emacs restart
- Eg support
brew services stop emacs-plus@30; doom sync; emacsopen activate-frame
- Eg support
- [ ] Act as a share target to invoke the command org-protocol convention of url, title, and text.
- [ ] Act as a Safari extension with support for sharing current page (including text selection) via
org-protocol
, including keyboard shortcut support - [X] Add
eval
support (usingemacsclient -e
) - [ ] Add a Homebrew formula, including shell completions
- [X] Support in-terminal case:
emacsclient --tty
- [X] Shell autocompletion of CLI arguments using apple/swift-argument-parser
- [ ] Docs (expand this README)
- [ ] Tests
- [ ] CI (build, test, dependabot checks)
- [ ] Show visual feedback when getting Emacs ready (eg a HUD spinner) when taking too long (GUI case only)
- [ ] Companion project on iOS to route
org-protocol://
links to chosen iOS apps with their own URL schemes, such asbeorg://
- Auto-detect Emacs brew service name if not configured, eg using
brew services list --json
- Auto-detect emacsclient path if not configured if at
/opt/homebrew/bin/emacsclient
Currently Shortcuts.app can’t use emacsclient
in Emacs Plus due to socket/env related issues.
Support some way of opening a file or link via EmacsOpen either via CLI or a Siri Shortcut action.
- No GUI
- All user interactions should be via a share action, or the
emacsopen
CLI command. - All configuration should be a text file, probably TOML format.
- All responses should be via stdout (CLI), macOS error notification/alert, and maybe logging.
- All user interactions should be via a share action, or the
- No AppleScript support
- Use Emacs lisp instead:
emacsopen -e COMMAND
- Use Emacs lisp instead:
This started as a discussion on an Emacs Plus PR thread.