From e81a0d8692e9ca310063da2aee6938cb61749e8f Mon Sep 17 00:00:00 2001 From: Howard Abrams Date: Fri, 8 Aug 2025 19:08:29 -0700 Subject: [PATCH] Create an evennia-mode And break out the org-blocks into an ob-evennia source file. Allows us to have :session and C-c C-c evaluation behavior. Probably doesn't work flawlessly, and will need tweaks on my main system. --- pud.org | 148 +++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 124 insertions(+), 24 deletions(-) diff --git a/pud.org b/pud.org index 7c44742..98f4fc8 100644 --- a/pud.org +++ b/pud.org @@ -2,7 +2,7 @@ #+author: Howard X. Abrams #+date: 2025-01-18 #+filetags: emacs hamacs -#+lastmod: [2025-06-09 Mon] +#+lastmod: [2025-08-05 Tue] A literate programming file for a Comint-based MUD client. @@ -30,13 +30,13 @@ A literate programming file for a Comint-based MUD client. This project is a simple MUD client for Emacs, based on COM-INT MUD client I learn about on Mickey Petersen’s [[https://www.masteringemacs.org/article/comint-writing-command-interpreter][essay on Comint]]. -This uses eithr =ssh= or good ol’ =telnet= for the connection. Surprised that one can still install in on a Mac, like: +This uses either =ssh= or good ol’ =telnet= for the connection. Surprised that one can still install =telnet= on a Mac, like: #+BEGIN_SRC sh brew install telnet #+END_SRC -Use your favorite way to install Emacs’ packages, for instance, with Emacs 30, once can install it, and customize some settings in one go with =use-package=: +Use your favorite way to install Emacs’ packages, for instance, with Emacs 30, one could install and customize settings in one go with =use-package=: #+BEGIN_SRC emacs-lisp :tangle no :eval no (use-package pud @@ -428,9 +428,28 @@ Note that =comint-process-echoes=, depending on the mode and the circumstances, * Org Babel Wouldn’t it be nice to be able to write commands in an Org file, and send the command to the connected Mud? +#+begin_src emacs-lisp :exports none :tangle ~/.emacs.d/elisp/ob-evennia.el + ;;; ob-evennia --- Evennia source blocks in Org -*- lexical-binding: t; -*- + ;; + ;; © 2025 Howard X. Abrams + ;; Licensed under a Creative Commons Attribution 4.0 International License. + ;; See http://creativecommons.org/licenses/by/4.0/ + ;; + ;; Author: Howard X. Abrams + ;; Maintainer: Howard X. Abrams + ;; Created: January 18, 2025 + ;; + ;; While obvious, GNU Emacs does not include this file or project. + ;; + ;; *NB:* Do not edit this file. Instead, edit the original literate file at: + ;; /Users/howard/src/hamacs/pud.org + ;; And tangle the file to recreate this one. + ;; + ;;; Code: +#+end_src Since I’m connected to more than one MUD, or at least, I often log in with two different characters as two different characters. Let’s have a function that can return all PUD buffers: -#+BEGIN_SRC emacs-lisp +#+BEGIN_SRC emacs-lisp :tangle ~/.emacs.d/elisp/ob-evennia.el (defun pud-get-all-buffers () "Return a list of all buffers with a live PUD connection." (save-window-excursion @@ -444,7 +463,7 @@ Since I’m connected to more than one MUD, or at least, I often log in with two And a wrapper around =completing-read= for choosing one of the buffers: -#+BEGIN_SRC emacs-lisp +#+BEGIN_SRC emacs-lisp :tangle ~/.emacs.d/elisp/ob-evennia.el (defun pud-current-world () "Return buffer based on user choice of current PUD connections." (let ((pud-buffers (pud-get-all-buffers))) @@ -459,7 +478,7 @@ And a wrapper around =completing-read= for choosing one of the buffers: Given a buffer and a string, use the =comint-send-string=: -#+BEGIN_SRC emacs-lisp +#+BEGIN_SRC emacs-lisp :tangle ~/.emacs.d/elisp/ob-evennia.el (defun pud-send-string (buf-name text) "Send TEXT to a comint buffer, BUF-NAME." (save-window-excursion @@ -472,7 +491,7 @@ Given a buffer and a string, use the =comint-send-string=: Let’s send the current line or region. -#+BEGIN_SRC emacs-lisp :results silent +#+BEGIN_SRC emacs-lisp :tangle ~/.emacs.d/elisp/ob-evennia.el (defun pud-send-line (world) "Send the current line or region to WORLD." (interactive (list (pud-current-world))) @@ -491,7 +510,7 @@ Let’s send the current line or region. Let’s be able to send the current Org block, where all lines in the block are smooshed together to create a single line: -#+BEGIN_SRC emacs-lisp +#+BEGIN_SRC emacs-lisp :tangle ~/.emacs.d/elisp/ob-evennia.el (defun pud-send-block (world) "Send the current Org block to WORLD." (interactive (list (pud-current-world))) @@ -503,28 +522,109 @@ Let’s be able to send the current Org block, where all lines in the block are (pud-send-string world (replace-regexp-in-string (rx (one-or-more space)) " " text)))) - #+END_SRC +#+END_SRC + +And code so that we can =(require 'ob-evennia)= to get font-locking working in blocks. + +#+BEGIN_SRC emacs-lisp :tangle ~/.emacs.d/elisp/ob-evennia.el + (require 'ob) + + (defvar org-babel-default-header-args:evennia '()) + + (defun org-babel-execute:evennia (body params) + "Execute evennia BODY. + + PARAMS can contain the following: + :session - The buffer to send the block + + Called by `org-babel-execute-src-block'." + (let* ((session (cdr (assq :session params))) + (buffer (or session (pud-current-world)))) + (if session + (setq buffer (format "*%s*" session))) + + (pud-send-string buffer + (replace-regexp-in-string + (rx (one-or-more space)) " " body)) + (message "No connected world."))) + + (defun org-babel-prep-session:evennia (_session _params) + "Signal error; Evennia does not (currently) support sessions." + (error "Evennia sessions are nonsensical")) + + (provide 'ob-evennia) +#+END_SRC + +This should allow this client to simply =require= it: + +#+BEGIN_SRC emacs-lisp + (require 'ob-evennia) +#+END_SRC * Evennia Mode -Make a simple mode for basic highlighting of =ev= code. +#+begin_src emacs-lisp :exports none :tangle ~/.emacs.d/elisp/evennia-mode.el + ;;; evennia-mode --- Syntax coloring for Evennia code -*- lexical-binding: t; -*- + ;; + ;; © 2025 Howard X. Abrams + ;; Licensed under a Creative Commons Attribution 4.0 International License. + ;; See http://creativecommons.org/licenses/by/4.0/ + ;; + ;; Author: Howard X. Abrams + ;; Maintainer: Howard X. Abrams + ;; Created: January 18, 2025 + ;; + ;; While obvious, GNU Emacs does not include this file or project. + ;; + ;; *NB:* Do not edit this file. Instead, edit the original literate file at: + ;; /Users/howard/src/hamacs/pud.org + ;; And tangle the file to recreate this one. + ;; + ;;; Code: +#+end_src + +Make a simple mode for basic highlighting of =ev= code. Based on =ruby= (which seems to be close enough). + +#+BEGIN_SRC emacs-lisp :tangle ~/.emacs.d/elisp/evennia-mode.el + (define-derived-mode evennia-mode ruby-mode "Evennia" + "Major mode for editing evennia batch command files. + \\{evennia-mode-map} + Turning on Evennia mode runs the normal hook `evennia-mode-hook'." + (setq-local require-final-newline mode-require-final-newline) + (setq-local comment-start "# ") + (setq-local comment-start-skip "#+\\s-*")) +#+END_SRC + +And add it to org blocks: #+BEGIN_SRC emacs-lisp :tangle no - (define-derived-mode evennia-mode nil "Evennia" - "Major mode for editing evennia batch command files. - \\{evennia-mode-map} - Turning on Evennia mode runs the normal hook `evennia-mode-hook'." - (setq-local comment-start "# ") - (setq-local comment-start-skip "#+\\s-*") - - (setq-local require-final-newline mode-require-final-newline) - (add-hook 'conevennia-menu-functions 'evennia-mode-conevennia-menu 10 t)) - - (defvar evennia-mode-font-lock-keywords - `(,(rx line-start "@" (one-or-more alnum)) - ) - "Additional things to highlight in evennia output.") + (add-to-list 'org-babel-load-languages '(evennia . t)) #+END_SRC +Final stuff to require to include this major-mode: + +#+BEGIN_SRC emacs-lisp :tangle ~/.emacs.d/elisp/evennia-mode.el + ;; Add the mode to the auto-mode-alist for specific file extensions + (add-to-list 'auto-mode-alist '("\\.ev\\'" . evennia-mode)) + + ;; Provide the mode for use + (provide 'evennia-mode) +#+END_SRC + +How does this look? + +#+BEGIN_SRC evennia :tangle /tmp/testing.ev + # Comments, while not used much are comments. + + @one two = "three" :four +#+END_SRC + +This client can =require= to depend on this mode. + +#+BEGIN_SRC emacs-lisp export none + (require 'evennia-mode) +#+END_SRC + + * Technical Artifacts :noexport: Let's =provide= a name so we can =require= this file: