Emacs as a Service Orchestrator: Building Clients with Elisp

Emacs as a Service Orchestrator: Building Clients with Elisp

Emacs as a Service Orchestrator

Emacs is not an operating system, but it functions as a high-level orchestrator capable of managing applications and utilities above the OS kernel level. By leveraging built-in access to system services—such as the file system and network—and the ability to execute external programs, Emacs allows users to treat almost any external resource as a service, effectively turning the editor into a versatile client for diverse computing needs.

The Client-Server Model in Emacs

In a standard client-server model, a task is partitioned between a service (the provider) and a client (the requester). A client typically manages three primary concerns: the User Interface (UI), the Client Edge (communication), and a Local Database (data representation).

Emacs provides a comprehensive suite of built-in libraries to handle these three concerns:

User Interface (UI)

Emacs offers multiple ways to present data and interact with users, including:

  • Minibuffers and Buffers: For text input and data display.
  • Completion: For efficient command and value selection.
  • Tabulated List Mode: For structured data presentation.
  • Transient: For creating temporary, context-aware menus.

Client Edge (Communication)

Emacs can communicate with external services via several protocols and formats:

  • Networking: Built-in support for URL (HTTP/HTTPS), Sockets (TCP/UDP), and SMTP.
  • Data Serialization: Native support for parsing JSON and XML.

Local Database (Data Management)

For managing synchronized or exchanged data, Emacs provides:

  • Collections: Association Lists, Property Lists, and Hash Tables.
  • Persistent Storage: Built-in SQLite support.

Implementing a Service Client with Elisp

Because Emacs Lisp (Elisp) is a dynamic programming language, it allows for rapid improvisation and orchestration of these libraries. A service can be a remote API or a local command-line utility. If a CLI tool exists to perform a specific task, that tool can be reframed as a "service" accessed via a shell call.

Example: wttr.in Weather Client

To demonstrate this, a weather client for wttr.in can be implemented in approximately 67 lines of Elisp. The workflow involves:

  1. Request Construction: Using url-generic-parse-url to build the target URL.
  2. Data Retrieval: Utilizing url-retrieve-synchronously to fetch the JSON response.
  3. Parsing: Using json-parse-buffer to convert the response into an Elisp hash-table.
  4. Display: Formatting the extracted data and displaying it in the minibuffer via the message function.

Alternatively, if the network logic is handled by an external Python script, the Elisp implementation is reduced to a simple shell command call using shell-command-to-string, treating the script as the service provider.

Community Perspectives and Architectural Context

While the "everything is a service" model is a powerful way to view Emacs, the community offers diverse perspectives on its nature:

Lisp Machine Heritage

Some users argue that Emacs is less of a "service client" and more of a realization of the Lisp Machine philosophy, where the environment is a single, malleable image of Lisp.

"Emacs follows the idea of LISP machines... Emacs can be or do pretty much whatever you want."

Comparison to Modern Standards

The ability to interact with external processes predates modern standards like the Language Server Protocol (LSP). Emacs has long utilized long-running subprocesses, RPC-like interactions, and tools like TRAMP and GUD to achieve service-like behavior.

Emacs as a Server

Beyond acting as a client, Emacs can operate as a server itself. By starting the editor with the --daemon flag, users can use emacsclient to connect multiple terminal or GUI instances to a single running server process, sharing the same buffers and open files.

Sources