(uiop:define-package #:ambrevar/emacs (:documentation "Communication with Emacs") (:use #:common-lisp) (:use #:trivia) (:import-from #:serapeum #:export-always)) (in-package #:ambrevar/emacs) (eval-when (:compile-toplevel :load-toplevel :execute) (trivial-package-local-nicknames:add-package-local-nickname :alex :alexandria) (trivial-package-local-nicknames:add-package-local-nickname :sera :serapeum)) (export-always 'with-emacs-eval) (defmacro with-emacs-eval (&body body) "Evaluate BODY (s-expressions) with `emacsclient'. Example: (with-emacs-eval (switch-to-buffer (get-buffer-create \"foobar\")) (insert \"Hello\"))" `(let ((*package* (find-package :ambrevar/emacs))) (cmd:cmd "emacsclient" "-e" (let ((*print-case* :downcase)) (format nil "'~s'" '(progn ,@body)))))) (defun %emacs-eval (caller &rest s-exp) "See `emacs-eval'." (let ((*package* (find-package :ambrevar/emacs))) (funcall caller "emacsclient" "-e" (let ((*print-case* :downcase)) (format nil "'~s'" `(progn ,@s-exp)))))) (export-always 'emacs-eval) (defun emacs-eval (&rest s-exp) "Evaluate (quoted) s-expressions with `emacsclient'. Example: (let ((buffer \"foobar\") (content \" world!\")) (emacs-eval `(switch-to-buffer (get-buffer-create ,buffer)) `(insert ,conent)))" (apply #'%emacs-eval #'cmd:cmd s-exp)) (export-always 'emacs-$eval) (defun emacs-$eval (&rest s-exp) "Like `emacs-eval' but return a string." (apply #'%emacs-eval #'cmd:$cmd s-exp)) (export-always 'emacs-eval>) (defun emacs-eval> (&rest s-exp) "Like `emacs-eval' but return a stream." (apply #'%emacs-eval #'ambrevar/shell:cmd> s-exp)) (export-always 'write-emacs-buffer) (defun write-emacs-buffer (buffer-or-name thing) "Write THING to Emacs' BUFFER-OR-NAME using `write-to-string'. This means string double quotes are included. See `princ-emacs-buffer'." (emacs-eval `(with-current-buffer (get-buffer-create ,buffer-or-name) (insert ,(write-to-string thing))))) (export-always 'princ-emacs-buffer) (defun princ-emacs-buffer (buffer-or-name thing) "Like `write-emacs-buffer' but using `princ-to-string'." (emacs-eval `(with-current-buffer (get-buffer-create ,buffer-or-name) (insert ,(princ-to-string thing))))) (export-always 'emacs-buffer-stream) (defun emacs-buffer-stream (buffer-or-name) "Return Emacs' BUFFER-OR-NAME content as a stream." (emacs-eval> `(with-current-buffer (get-buffer-create ,buffer-or-name) (buffer-string)))) (export-always 'emacs-buffer-string) (defun emacs-buffer-string (buffer-or-name) "Return Emacs' BUFFER-OR-NAME content as a string." (emacs-$eval `(with-current-buffer (get-buffer-create ,buffer-or-name) (buffer-string)))) ;; TODO: Make Emacs buffer output stream.