In Emacs, Everything Looks Like a Service

Hacker News Top Tools

Summary

The article explains how Emacs can function as a client to various services, leveraging its built-in libraries for UI, network communication, and data management, supporting the idea that 'everything looks like a service' in Emacs.

No content available
Original Article
View Cached Full Text

Cached at: 07/10/26, 12:12 PM

# In Emacs, Everything Looks Like a Service Source: [http://yummymelon.com/devnull/in-emacs-everything-looks-like-a-service.html](http://yummymelon.com/devnull/in-emacs-everything-looks-like-a-service.html) A common refrain is that Emacs is an operating system \(OS\)\. This isn’t true, but what invites comparison to an OS is its ability to orchestrate applications and utilities above the OS kernel level\. The diagram below suggests a truer picture of how Emacs’ relates to an OS and its capabilities\. ![img](http://yummymelon.com/devnull/images/ieells/emacs-os-relationship.svg) Emacs’ built\-in access to OS system services \(file system, network, etc\.\) coupled with the ability to run other programs makes it routine to improvise client behavior within it\. Because of this, Emacs users are able to accomplish many of their computing needs from the different client modes that have been made for it\. This gives credence to the notion of “living only in Emacs\.” In this post, we’ll examine some of the ways Emacs lets you build a client\. By the end of this post, you’ll hopefully be convinced that from within Emacs, everything looks like a service\. ## Client\-Server Model Let’s first provide some definitions\. The[Client–Server model](https://en.wikipedia.org/wiki/Client%E2%80%93server_model)is a common computer interaction pattern where a task is partitioned between the provider of a resource \(the service\) and the requester of that resource \(the client\)\. The client issues a*request*to the server, and the server in turn returns a*response*as shown in the diagram below\. ![img](http://yummymelon.com/devnull/images/ieells/client-server.svg) Depending on the implementation, the transaction \(request \+ response\) can occur over a network or be local to a system\. Client\-server models using a network has been most elaborated upon with[REST\-style software architectures](https://en.wikipedia.org/wiki/REST)\. Shown in the sequence diagram below is a common implementation pattern for REST\-style client server architecture\. ![img](http://yummymelon.com/devnull/images/ieells/rest-client-arch.svg) ## Emacs as a Client From the diagram above, there are three concerns the client is typically responsible for: - **UI:**User interface \(if any\)\. - **Client Edge:**Sub\-system concerned with communication with the service\. For networked clients, this is the network sub\-system\. - **Local Database:**Representation of data that is exchanged or synchronized with the server\. How this data is managed is up to the implementation requirements\. For the above concerns, Emacs provides numerous libraries both built\-in and third\-party which can implement a client\. Listed below are some built\-in libraries with their respective links for further reading: - UI - [Minibuffers](https://www.gnu.org/software/emacs/manual/html_node/elisp/Minibuffers.html) - [Buffers](https://www.gnu.org/software/emacs/manual/html_node/elisp/Buffers.html) - [Completion](https://www.gnu.org/software/emacs/manual/html_node/elisp/Completion.html) - [Tabulated List Mode](https://www.gnu.org/software/emacs/manual/html_node/elisp/Tabulated-List-Mode.html) - [Variable Pitch Table \(vtable\)](https://www.gnu.org/software/emacs/manual/html_node/vtable/) - [Transient](https://www.gnu.org/software/emacs/manual/html_node/transient/) - Client Edge - [URL](https://www.gnu.org/software/emacs/manual/html_node/url/) - [Socket \(TCP/UDP\)](https://www.gnu.org/software/emacs/manual/html_node/elisp/Network.html) - [SMTP](https://www.gnu.org/software/emacs/manual/html_node/smtpmail/) - Serialization/Deserialization- [JSON](https://www.gnu.org/software/emacs/manual/html_node/elisp/Parsing-JSON.html) - [XML](https://www.gnu.org/software/emacs/manual/html_node/elisp/Parsing-HTML_002fXML.html) - Local Database - Collections- [Association Lists](https://www.gnu.org/software/emacs/manual/html_node/elisp/Association-Lists.html) - [Property Lists](https://www.gnu.org/software/emacs/manual/html_node/elisp/Property-Lists.html) - [Hash Tables](https://www.gnu.org/software/emacs/manual/html_node/elisp/Hash-Tables.html) - [SQLite](https://www.gnu.org/software/emacs/manual/html_node/elisp/Database.html) Requirements dictate the amount of complexity required to implement the Emacs client\. If there is an existing command line utility that can do the “heavy lifting”, said utility can be reframed as a “service” that can be accessed via a shell call\. ![img](http://yummymelon.com/devnull/images/ieells/delgated-rest-client-arch.svg) ## Elisp All the libraries mentioned above are accessed through the Emacs Lisp \([Elisp](https://www.gnu.org/software/emacs/manual/html_node/elisp/)\) programming language\. Elisp is a[dynamic programming language](https://en.wikipedia.org/wiki/Dynamic_programming_language)which allows for a high degree of improvisation during run\-time\. This capability allows for complex orchestration of any behavior that is available to Emacs, from Elisp functions to shell commands\. ## Example wttr\.in client [wttr\.in](https://github.com/chubin/wttr.in)is a console\-oriented weather forecast web\-service\. It supports[JSON output](https://github.com/chubin/wttr.in#different-output-formats)so we can build an Emacs`wttr`command which will prompt for a location, make the HTTP request, process the JSON response and display the result in the mini\-buffer\. The top\-level command`wttr`is shown below\. ``` 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ``` ``` (defun wttr (location) "Show weather conditions for LOCATION from `https://wttr.in' in mini-buffer. Result is also stored in `kill-ring'." (interactive "sWhere (default: local): ") (condition-case err (let* ((url (wttr--request-url location)) (jsondb (fetch-json-as-hash-table url)) (msg (wttr--report-message jsondb))) (kill-new msg) (message "%s" msg)) (error (message "ERROR: %s" (cdr err))))) ``` The wttr\.in URL is constructed by the function`wttr\-\-request\-url`shown below\. ``` (defun wttr--request-url (location) "Construct wttr.in URL with LOCATION." (let* ((base-url (url-generic-parse-url "https://wttr.in")) (encoded-location (string-replace " " "+" location)) (query (format "/%s?0&format=j1" encoded-location)) (_dummy (setf (url-filename base-url) query))) (url-recreate-url base-url))) ``` We can subsequently pass that URL into`fetch\-json\-as\-hash\-table`which does the heavy lifting of retrieving the URL and parsing the JSON response into an Elisp`hash\-table`\. ``` 1 2 3 4 5 6 7 8 9 10 11 12 13 ``` ``` (defun fetch-json-as-hash-table (url) "Fetch URL with expected JSON response and return a `hash-table'." (let ((data-buffer (url-retrieve-synchronously url))) (if (not data-buffer) (error "Failed to fetch data from %s" url) (unwind-protect (with-current-buffer data-buffer ;; Move point past the HTTP metadata headers (goto-char url-http-end-of-headers) ;; Parse the remaining JSON buffer into a hash-table (json-parse-buffer :object-type 'hash-table)) ;; Always kill the downloaded network buffer to prevent memory leaks (kill-buffer data-buffer))))) ``` Finally we can extract the desired values from the JSON response \(`jsondb`\) to populate the message that will sent to the mini\-buffer\. ``` 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 ``` ``` (defun wttr--report-message (jsondb) "Generate weather report message from JSONDB." (let* ((area-buflist ()) (nearest-area (wttr--get-first jsondb "nearest_area")) (area-name (map-elt (wttr--get-first nearest-area "areaName") "value")) (region (map-elt (wttr--get-first nearest-area "region") "value")) (country (map-elt (wttr--get-first nearest-area "country") "value")) (current-condition (wttr--get-first jsondb "current_condition")) (temp_c (map-elt current-condition "temp_C")) (temp_f (map-elt current-condition "temp_F")) (weather-description (map-elt (wttr--get-first current-condition "weatherDesc") "value"))) (mapc (lambda (x) (if (and x (not (string-equal x ""))) (push x area-buflist))) (list area-name region country)) (format "%s: %s°C, %s°F %s" (string-join (reverse area-buflist) ", ") temp_c temp_f weather-description))) ``` [wttr\.el source](https://gist.github.com/kickingvegas/40290cef2751c133666eb19921f91eee) ## Closing Thoughts At this point, hopefully you are convinced of the title assertion that from Emacs, everything looks like a service\. Furthermore, many of the APIs offered by Emacs work at a high\-level of abstraction\. Consider that the lines of code for`wttr\.el`weighs in at 67\. \(Result using the`cloc`utility\.\) If that’s too much, then imagine an alternate implementation where the actual network request and JSON processing is done in a Python script called`weather`\. Then the Elisp command to invoke it is just the code shown below\. ``` (defun weather (location) "Call weather script with LOCATION and show result in minibuffer." (interactive "sWhere (default: local): ") (let* ((weather-cmd "weather") (cmd (if location (format "%s %s" weather-cmd location) weather-cmd)) (result (shell-command-to-string cmd))) (kill-new result) (message result))) ``` With the above implementation, the shell command becomes effectively the “service” to make a request to\. As Elisp is a dynamic programming language, it can allow for integration of Elisp libraries with command line utilities in an improvised fashion\. This capability is compelling to users who recognize the opportunities it can offer\. [emacs](http://yummymelon.com/devnull/tag/emacs.html)

Similar Articles

Playing with Emacs

Lobsters Hottest

The author shares personal experiences with Emacs, emphasizing its playful and customizable nature, including ASCII art features and its integration into their daily computing workflow.

May I recommend… understanding Emacs's patterns

Lobsters Hottest

The article explains Emacs's architectural patterns, focusing on the universal buffer data model and incremental completing read (ICR), comparing them to a rose's roots and petals. It highlights how Emacs unifies interfaces and allows extensibility via Elisp.

May I recommend eww for Emacs’s innovative UI?

Lobsters Hottest

The article recommends using Emacs' eww web browser, highlighting how its lack of JavaScript improves many websites and how Emacs offers unique UI innovations like per-image resizing and keyboard navigation.

Emacs appearances in pop culture

Hacker News Top

A blog post cataloguing appearances of the Emacs text editor in films and TV, including The Social Network, Tron: Legacy, Arctic Blast, and Silicon Valley.

The Emacsification of Software

Hacker News Top

The author discusses the frustration of reading Markdown in the terminal and describes using Claude to quickly build a custom macOS Markdown viewer (MDV.app), illustrating how AI enables rapid creation of personal software tools.