From 13db2dd4b9c6c2e46af9b7bcc105e0a19725eddc Mon Sep 17 00:00:00 2001 From: Konstantin Nazarov Date: Sat, 12 Oct 2024 19:13:42 +0100 Subject: [PATCH] Add a simple and hacky implemenation of org-babel mode --- ob-valeri.el | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++ valeri-mode.el | 47 +++++++++++++++--------- 2 files changed, 128 insertions(+), 18 deletions(-) create mode 100644 ob-valeri.el diff --git a/ob-valeri.el b/ob-valeri.el new file mode 100644 index 0000000..b0a36d3 --- /dev/null +++ b/ob-valeri.el @@ -0,0 +1,99 @@ +;;; ob-valeri.el --- org-babel functions for valeri evaluation + +(require 'ob) +(require 'valeri-mode) + +(defvar valeri-eoe-indicator "valeri-eoe") + +(defvar org-babel-valeri-prompt "valeri> " + "String used for unique prompt.") + +(defvar org-babel-valeri-command "valeri" + "Name of command to use for executing Valeri code. +It's possible to override it by using a header argument `:valeri'") + +(defun org-babel-valeri-initiate-session (&optional session params) + "Initiate a valeri session. +If there is not a current inferior-process-buffer in SESSION +then create one. Return the initialized session. +Session settings (`:valeri' header arg value) are taken from PARAMS." + (unless (string= session "none") + (org-require-package 'valeri-mode) + (let* ((command (cdr (or (assq :valeri params) + '(nil . "valeri")))) + (buffer (get-buffer (format "*%s*" session))) + (new-session? (not buffer)) + (session-buffer (or buffer (save-window-excursion + (run-valeri-or-pop-to-buffer + (if (functionp command) + (funcall command) + command) + (or session "valeri") + ) + (current-buffer))))) + (if (org-babel-comint-buffer-livep session-buffer) + (progn + (sit-for .25) + ;; Setup machine-readable prompt: no echo, prompts matching + ;; uniquely by regexp. + (when new-session? + (with-current-buffer session-buffer + (setq-local + org-babel-comint-prompt-regexp-fallback comint-prompt-regexp + comint-prompt-regexp (concat "^" org-babel-valeri-prompt)) + (comint-send-input nil t) + )) + session-buffer) + (sit-for .5) + (org-babel-valeri-initiate-session session))))) + + +(defun org-babel-valeri-evaluate (buffer body) + "Pass BODY to the Valeri process in BUFFER." + (let ((escaped-body (format "\x1b[200~%s\x1b[201~" body)) + (eoe-string (format "\n(println \"%s\")\n" valeri-eoe-indicator))) + (mapconcat + #'identity + (butlast + (split-string + (mapconcat + #'org-trim + (org-babel-comint-with-output + (buffer valeri-eoe-indicator t escaped-body) + (insert (org-babel-chomp escaped-body) eoe-string) + (comint-send-input nil t)) + "\n") "[\r\n]")) "\n") + ) + ) + +(defun org-babel-execute:valeri (body params) + "Execute Valeri BODY according to PARAMS. +This function is called by `org-babel-execute-src-block'." + (let* ((session (org-babel-valeri-initiate-session + (cdr (assq :session params)) params)) + (org-babel-valeri-command + (or (cdr (assq :valeri params)) + org-babel-valeri-command)) + (result + (org-babel-valeri-evaluate session body))) + result + )) + +(defun org-babel-prep-session:valeri (session params) + "Prepare SESSION according to the header arguments specified in PARAMS." + ;; (message "params=%S" params) ;; debugging + (let* ((session (org-babel-valeri-initiate-session session)) + ) + session)) + +(defun org-babel-load-session:valeri (session body params) + "Load BODY into SESSION." + (save-window-excursion + (let ((buffer (org-babel-prep-session:valeri session params))) + (with-current-buffer buffer + (goto-char (process-mark (get-buffer-process (current-buffer)))) + (insert (org-babel-chomp body))) + buffer))) + +(provide 'ob-valeri) +;;; ob-valeri.el ends here diff --git a/valeri-mode.el b/valeri-mode.el index 298d87d..1fbe25b 100644 --- a/valeri-mode.el +++ b/valeri-mode.el @@ -43,30 +43,12 @@ Should be a list of strings." "Buffer-local flag saying if this is a Valeri REPL buffer.") (make-variable-buffer-local 'valeri--repl-buffer-p) -(defvar valeri-eoe-indicator "valeri-eoe") (defun valeri-get-create-process () "Return active Valeri process creating one if necessary." (valeri-start-process) valeri-process) -(defun valeri-send-string (buffer body) - "Pass BODY to the Valeri process in BUFFER." - (let ((escaped-body (format "\x1b[200~%s\x1b[201~" body)) - (eoe-string (format "\n(println \"%s\")\n" valeri-eoe-indicator))) - (mapconcat - #'identity - (butlast - (split-string - (mapconcat - #'org-trim - (org-babel-comint-with-output - (buffer valeri-eoe-indicator t escaped-body) - (insert (org-babel-chomp escaped-body) eoe-string) - (comint-send-input nil t)) - "\n") "[\r\n]")) "\n") - ) - ) ;;;###autoload (define-derived-mode valeri-mode lisp-mode "Valeri" @@ -135,6 +117,35 @@ When called interactively, switch to the process buffer." (rx eos)) output)) +(defun valeri-choose-buffer-name (name) + (generate-new-buffer-name (format "*%s*" name))) + +(defun run-valeri-new (command &optional name) + "Create a new inferior Valeri process in a new or existing buffer. + +COMMAND is the command to call. NAME will be used for the name of +the buffer, defaults to \"valeri\"." + (setq name (or name "valeri")) + + (let ((commandlist (split-string-and-unquote command)) + (buffer (current-buffer)) + (process-environment (copy-sequence process-environment))) + (set-buffer (apply 'make-comint-in-buffer + name + (valeri-choose-buffer-name name) + (car commandlist) + nil (cdr commandlist))) + ) + + + (pop-to-buffer (current-buffer))) + +(defun run-valeri-or-pop-to-buffer (command &optional name buffer) + (if (not (and buffer + (comint-check-proc buffer))) + (run-valeri-new command name) + (pop-to-buffer buffer) + )) (provide 'valeri-mode)