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.
This commit is contained in:
Howard Abrams 2025-08-08 19:08:29 -07:00
parent 2731861d46
commit e81a0d8692

142
pud.org
View file

@ -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 Petersens [[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
Wouldnt 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 <http://gitlab.com/howardabrams>
;; 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 Im connected to more than one MUD, or at least, I often log in with two different characters as two different characters. Lets 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 Im 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=:
Lets 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 @@ Lets send the current line or region.
Lets 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 @@ Lets 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 <http://gitlab.com/howardabrams>
;; 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
#+BEGIN_SRC emacs-lisp :tangle no
(define-derived-mode evennia-mode nil "Evennia"
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 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.")
(setq-local comment-start "# ")
(setq-local comment-start-skip "#+\\s-*"))
#+END_SRC
And add it to org blocks:
#+BEGIN_SRC emacs-lisp :tangle no
(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: