From 227802f5c3bf62d8527b4f7b653a4fde57aeaf2b Mon Sep 17 00:00:00 2001 From: garlic0x1 Date: Sat, 17 Feb 2024 10:51:46 -0600 Subject: [PATCH 01/22] interactive markdown --- extensions/markdown-mode/interactive.lisp | 77 +++++++++++++++++++ .../markdown-mode/lem-markdown-mode.asd | 5 +- 2 files changed, 80 insertions(+), 2 deletions(-) create mode 100644 extensions/markdown-mode/interactive.lisp diff --git a/extensions/markdown-mode/interactive.lisp b/extensions/markdown-mode/interactive.lisp new file mode 100644 index 000000000..86bbcd521 --- /dev/null +++ b/extensions/markdown-mode/interactive.lisp @@ -0,0 +1,77 @@ +(defpackage :lem-markdown-mode/interactive + (:use :cl :lem) + (:import-from #:alexandria :if-let :when-let)) +(in-package :lem-markdown-mode/interactive) + +(defvar *block-evaluators* (make-hash-table :test #'equal) + "Dispatch table for block evaluators per language.") + +(defmacro register-block-evaluator (language (string callback) &body body) + "Convenience macro to register block evaluators, wraps setf." + `(setf (gethash ,language *block-evaluators*) + (lambda (,string ,callback) + ,@body))) + +(defmacro with-constant-position (&body body) + "This allows you to move around the buffer point without worry." + `(let* ((buf (current-buffer)) + (p (copy-point (buffer-point buf)))) + (prog1 ,@body + (move-point (buffer-point buf) p)))) + +(defun pop-up-buffer (name text) + "Create a popup with name containing text." + (let ((buffer (make-buffer name))) + (erase-buffer buffer) + (with-buffer-read-only buffer nil + (insert-string (buffer-point buffer) text) + (with-pop-up-typeout-window (s buffer) + (declare (ignore s)))))) + +(defun block-fence-lang (fence) + "Get language from a block fence string." + (let ((str (coerce (cdddr (coerce fence 'list)) 'string))) + (unless (str:emptyp str) + str))) + +(defun block-at-point (point) + "Ugly hack to get the string in a code block at point." + (search-backward-regexp point "```") + (when-let ((lang (block-fence-lang (str:trim (line-string (current-point)))))) + (search-forward (current-point) (format nil "~%")) + (let ((start (copy-point (current-point)))) + (search-forward-regexp (current-point) "```") + (search-backward (current-point) (format nil "~%")) + (let ((end (current-point))) + (values lang (points-to-string start end)))))) + +(defun handle-eval-result (result) + "Display results of evaluation." + (pop-up-buffer "*literate*" (format nil "~a" result))) + +(define-command eval-block () () + "Evaluate current markdown code block and display results in popup." + (with-constant-position + (multiple-value-bind (lang block) (block-at-point (current-point)) + (when lang + (if-let ((evaluator (gethash lang *block-evaluators*))) + (funcall evaluator block #'handle-eval-result) + (message "No evaluator registered for ~a" lang)))))) + +(register-block-evaluator "bash" (string callback) + "Register evaluator for Bash blocks." + (bt:make-thread + (lambda () + (funcall callback (uiop:run-program string :output :string))))) + +(register-block-evaluator "lisp" (string callback) + "Register evaluator for Lisp blocks." + (lem-lisp-mode:check-connection) + (lem-lisp-mode:lisp-eval-async + (read-from-string + (format nil "(progn ~a)" string)) + (lambda (result) + (funcall callback result)))) + +(define-key lem-markdown-mode::*markdown-mode-keymap* + "C-c C-c" 'eval-block) diff --git a/extensions/markdown-mode/lem-markdown-mode.asd b/extensions/markdown-mode/lem-markdown-mode.asd index 023f559e8..ed468630a 100644 --- a/extensions/markdown-mode/lem-markdown-mode.asd +++ b/extensions/markdown-mode/lem-markdown-mode.asd @@ -1,4 +1,5 @@ -(defsystem "lem-markdown-mode" +(asdf:defsystem "lem-markdown-mode" :depends-on ("lem") :serial t - :components ((:file "markdown-mode"))) + :components ((:file "markdown-mode") + (:file "interactive"))) From 64be4e533230b08f57413ac44ebfe0f227b7e11a Mon Sep 17 00:00:00 2001 From: garlic0x1 Date: Sat, 17 Feb 2024 10:59:08 -0600 Subject: [PATCH 02/22] eval-block-and-insert --- extensions/markdown-mode/interactive.lisp | 26 +++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/extensions/markdown-mode/interactive.lisp b/extensions/markdown-mode/interactive.lisp index 86bbcd521..b327c13b8 100644 --- a/extensions/markdown-mode/interactive.lisp +++ b/extensions/markdown-mode/interactive.lisp @@ -45,19 +45,32 @@ (let ((end (current-point))) (values lang (points-to-string start end)))))) -(defun handle-eval-result (result) +(defun pop-up-eval-result (result) "Display results of evaluation." (pop-up-buffer "*literate*" (format nil "~a" result))) -(define-command eval-block () () - "Evaluate current markdown code block and display results in popup." +(defun insert-eval-result (result) + (search-forward-regexp (current-point) "```") + (insert-string (current-point) + (format nil "~%~%```result~%~a~%```" result)) + (redraw-display)) + +(defun eval-block-internal (handler) (with-constant-position (multiple-value-bind (lang block) (block-at-point (current-point)) (when lang (if-let ((evaluator (gethash lang *block-evaluators*))) - (funcall evaluator block #'handle-eval-result) + (funcall evaluator block handler) (message "No evaluator registered for ~a" lang)))))) +(define-command eval-block () () + "Evaluate current markdown code block and display results in popup." + (eval-block-internal #'pop-up-eval-result)) + +(define-command eval-block-and-insert () () + "Evaluate current markdown code block and display results in popup." + (eval-block-internal #'insert-eval-result)) + (register-block-evaluator "bash" (string callback) "Register evaluator for Bash blocks." (bt:make-thread @@ -73,5 +86,6 @@ (lambda (result) (funcall callback result)))) -(define-key lem-markdown-mode::*markdown-mode-keymap* - "C-c C-c" 'eval-block) +(define-keys lem-markdown-mode::*markdown-mode-keymap* + ("C-c C-c" 'eval-block) + ("C-c C-e" 'eval-block-and-insert)) From f219d9d7debfe94262efd33ab872ad009ec57df1 Mon Sep 17 00:00:00 2001 From: garlic0x1 Date: Sat, 17 Feb 2024 11:08:23 -0600 Subject: [PATCH 03/22] delete old result on insert --- extensions/markdown-mode/interactive.lisp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/extensions/markdown-mode/interactive.lisp b/extensions/markdown-mode/interactive.lisp index b327c13b8..d1ce05816 100644 --- a/extensions/markdown-mode/interactive.lisp +++ b/extensions/markdown-mode/interactive.lisp @@ -45,11 +45,24 @@ (let ((end (current-point))) (values lang (points-to-string start end)))))) +(defun delete-old-result () + "Searches for a result block below the current code block, and kills it." + (with-constant-position + (search-forward-regexp (current-point) "```") + (line-offset (current-point) 2) + (when (equal "result" (block-fence-lang (line-string (current-point)))) + (loop :while (not (equal "```" (line-string (current-point)))) + :do (kill-whole-line) + :do (line-offset (current-point) 1)) + (kill-whole-line) + (kill-whole-line)))) + (defun pop-up-eval-result (result) "Display results of evaluation." (pop-up-buffer "*literate*" (format nil "~a" result))) (defun insert-eval-result (result) + (delete-old-result) (search-forward-regexp (current-point) "```") (insert-string (current-point) (format nil "~%~%```result~%~a~%```" result)) From 4157854c07b16a1a06d328146b70a555fd192a64 Mon Sep 17 00:00:00 2001 From: garlic0x1 Date: Sat, 17 Feb 2024 11:18:50 -0600 Subject: [PATCH 04/22] kill-block-eval-result command --- extensions/markdown-mode/interactive.lisp | 30 ++++++++++++----------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/extensions/markdown-mode/interactive.lisp b/extensions/markdown-mode/interactive.lisp index d1ce05816..fbd5d0dfe 100644 --- a/extensions/markdown-mode/interactive.lisp +++ b/extensions/markdown-mode/interactive.lisp @@ -45,27 +45,29 @@ (let ((end (current-point))) (values lang (points-to-string start end)))))) -(defun delete-old-result () +(define-command kill-block-eval-result () () "Searches for a result block below the current code block, and kills it." - (with-constant-position - (search-forward-regexp (current-point) "```") - (line-offset (current-point) 2) - (when (equal "result" (block-fence-lang (line-string (current-point)))) - (loop :while (not (equal "```" (line-string (current-point)))) - :do (kill-whole-line) - :do (line-offset (current-point) 1)) - (kill-whole-line) - (kill-whole-line)))) + (when (with-constant-position (block-at-point (current-point))) + (with-constant-position + (search-forward-regexp (current-point) "```") + (line-offset (current-point) 2) + (when (equal "result" (block-fence-lang (line-string (current-point)))) + (loop :while (not (equal "```" (line-string (current-point)))) + :do (kill-whole-line) + :do (line-offset (current-point) 1)) + (kill-whole-line) + (kill-whole-line))))) (defun pop-up-eval-result (result) "Display results of evaluation." (pop-up-buffer "*literate*" (format nil "~a" result))) (defun insert-eval-result (result) - (delete-old-result) - (search-forward-regexp (current-point) "```") - (insert-string (current-point) - (format nil "~%~%```result~%~a~%```" result)) + (with-constant-position + (kill-block-eval-result) + (search-forward-regexp (current-point) "```") + (insert-string (current-point) + (format nil "~%~%```result~%~a~%```" result))) (redraw-display)) (defun eval-block-internal (handler) From 6cc8a964efbec0e7b5e6fbdcc242ebda32108a90 Mon Sep 17 00:00:00 2001 From: garlic0x1 Date: Sat, 17 Feb 2024 11:22:32 -0600 Subject: [PATCH 05/22] keybindings --- extensions/markdown-mode/interactive.lisp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/extensions/markdown-mode/interactive.lisp b/extensions/markdown-mode/interactive.lisp index fbd5d0dfe..ea639fdbe 100644 --- a/extensions/markdown-mode/interactive.lisp +++ b/extensions/markdown-mode/interactive.lisp @@ -102,5 +102,6 @@ (funcall callback result)))) (define-keys lem-markdown-mode::*markdown-mode-keymap* - ("C-c C-c" 'eval-block) - ("C-c C-e" 'eval-block-and-insert)) + ("C-c C-e" 'eval-block) + ("C-c C-c" 'eval-block-and-insert) + ("C-c C-d" 'kill-block-eval-result)) From ca28c1135edd5d5fafcface94e75322b73fcc6f8 Mon Sep 17 00:00:00 2001 From: garlic0x1 Date: Sat, 17 Feb 2024 11:37:43 -0600 Subject: [PATCH 06/22] ensure markdown mode --- extensions/markdown-mode/interactive.lisp | 34 +++++++++++++++-------- 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/extensions/markdown-mode/interactive.lisp b/extensions/markdown-mode/interactive.lisp index ea639fdbe..40ee82a34 100644 --- a/extensions/markdown-mode/interactive.lisp +++ b/extensions/markdown-mode/interactive.lisp @@ -19,6 +19,13 @@ (prog1 ,@body (move-point (buffer-point buf) p)))) +(defmacro when-markdown-mode (&body body) + "Ensure the major mode is markdown-mode and alert the user if not." + `(if (eq 'lem-markdown-mode:markdown-mode + (buffer-major-mode (current-buffer))) + (progn ,@body) + (message "Not in markdown mode."))) + (defun pop-up-buffer (name text) "Create a popup with name containing text." (let ((buffer (make-buffer name))) @@ -47,16 +54,17 @@ (define-command kill-block-eval-result () () "Searches for a result block below the current code block, and kills it." - (when (with-constant-position (block-at-point (current-point))) + (when-markdown-mode (with-constant-position - (search-forward-regexp (current-point) "```") - (line-offset (current-point) 2) - (when (equal "result" (block-fence-lang (line-string (current-point)))) - (loop :while (not (equal "```" (line-string (current-point)))) - :do (kill-whole-line) - :do (line-offset (current-point) 1)) - (kill-whole-line) - (kill-whole-line))))) + (when (block-at-point (current-point)) + (search-forward-regexp (current-point) "```") + (line-offset (current-point) 2) + (when (equal "result" (block-fence-lang (line-string (current-point)))) + (loop :while (not (equal "```" (line-string (current-point)))) + :do (kill-whole-line) + :do (line-offset (current-point) 1)) + (kill-whole-line) + (kill-whole-line)))))) (defun pop-up-eval-result (result) "Display results of evaluation." @@ -76,15 +84,17 @@ (when lang (if-let ((evaluator (gethash lang *block-evaluators*))) (funcall evaluator block handler) - (message "No evaluator registered for ~a" lang)))))) + (message "No evaluator registered for ~a." lang)))))) (define-command eval-block () () "Evaluate current markdown code block and display results in popup." - (eval-block-internal #'pop-up-eval-result)) + (when-markdown-mode + (eval-block-internal #'pop-up-eval-result))) (define-command eval-block-and-insert () () "Evaluate current markdown code block and display results in popup." - (eval-block-internal #'insert-eval-result)) + (when-markdown-mode + (eval-block-internal #'insert-eval-result))) (register-block-evaluator "bash" (string callback) "Register evaluator for Bash blocks." From 4e36d99f1e4e6842eedfae50d3db0363cf185aa6 Mon Sep 17 00:00:00 2001 From: garlic0x1 Date: Sat, 17 Feb 2024 11:56:08 -0600 Subject: [PATCH 07/22] bugfix --- extensions/markdown-mode/interactive.lisp | 24 ++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/extensions/markdown-mode/interactive.lisp b/extensions/markdown-mode/interactive.lisp index 40ee82a34..0333f7429 100644 --- a/extensions/markdown-mode/interactive.lisp +++ b/extensions/markdown-mode/interactive.lisp @@ -1,6 +1,6 @@ (defpackage :lem-markdown-mode/interactive (:use :cl :lem) - (:import-from #:alexandria :if-let :when-let)) + (:import-from #:alexandria :if-let :when-let :curry)) (in-package :lem-markdown-mode/interactive) (defvar *block-evaluators* (make-hash-table :test #'equal) @@ -67,18 +67,20 @@ (kill-whole-line)))))) (defun pop-up-eval-result (result) - "Display results of evaluation." + "Display results of evaluation in a popup buffer." (pop-up-buffer "*literate*" (format nil "~a" result))) -(defun insert-eval-result (result) +(defun insert-eval-result (point result) + "Insert results of evaluation in a code block." (with-constant-position (kill-block-eval-result) - (search-forward-regexp (current-point) "```") - (insert-string (current-point) - (format nil "~%~%```result~%~a~%```" result))) + (block-at-point point) + (search-forward-regexp point "```") + (insert-string point (format nil "~%~%```result~%~a~%```" result))) (redraw-display)) (defun eval-block-internal (handler) + "Evaluate code block and apply handler to result." (with-constant-position (multiple-value-bind (lang block) (block-at-point (current-point)) (when lang @@ -94,7 +96,11 @@ (define-command eval-block-and-insert () () "Evaluate current markdown code block and display results in popup." (when-markdown-mode - (eval-block-internal #'insert-eval-result))) + (eval-block-internal (curry #'insert-eval-result (current-point))))) + +;; +;; Default evaluators: +;; (register-block-evaluator "bash" (string callback) "Register evaluator for Bash blocks." @@ -111,6 +117,10 @@ (lambda (result) (funcall callback result)))) +;; +;; Keybindings +;; + (define-keys lem-markdown-mode::*markdown-mode-keymap* ("C-c C-e" 'eval-block) ("C-c C-c" 'eval-block-and-insert) From d54c2a2cc35785a3fe6562d83fb4c5d059d84db5 Mon Sep 17 00:00:00 2001 From: garlic0x1 Date: Sat, 17 Feb 2024 13:26:15 -0600 Subject: [PATCH 08/22] kinda fixed kill and eval --- extensions/markdown-mode/interactive.lisp | 62 ++++++++++++----------- 1 file changed, 33 insertions(+), 29 deletions(-) diff --git a/extensions/markdown-mode/interactive.lisp b/extensions/markdown-mode/interactive.lisp index 0333f7429..08a6b7444 100644 --- a/extensions/markdown-mode/interactive.lisp +++ b/extensions/markdown-mode/interactive.lisp @@ -12,12 +12,11 @@ (lambda (,string ,callback) ,@body))) -(defmacro with-constant-position (&body body) - "This allows you to move around the buffer point without worry." - `(let* ((buf (current-buffer)) - (p (copy-point (buffer-point buf)))) - (prog1 ,@body - (move-point (buffer-point buf) p)))) +(defmacro with-constant-position ((point) &body body) + "This allows you to move around the point without worry." + `(let ((tmp (copy-point ,point))) + (prog1 (progn ,@body) + (move-point ,point tmp)))) (defmacro when-markdown-mode (&body body) "Ensure the major mode is markdown-mode and alert the user if not." @@ -44,59 +43,64 @@ (defun block-at-point (point) "Ugly hack to get the string in a code block at point." (search-backward-regexp point "```") - (when-let ((lang (block-fence-lang (str:trim (line-string (current-point)))))) - (search-forward (current-point) (format nil "~%")) - (let ((start (copy-point (current-point)))) - (search-forward-regexp (current-point) "```") - (search-backward (current-point) (format nil "~%")) - (let ((end (current-point))) + (when-let ((lang (block-fence-lang (str:trim (line-string point))))) + (search-forward point (format nil "~%")) + (let ((start (copy-point point))) + (search-forward-regexp point "```") + (search-backward point (format nil "~%")) + (let ((end point)) (values lang (points-to-string start end)))))) -(define-command kill-block-eval-result () () +(define-command kill-block-eval-result (&optional (point (current-point))) () "Searches for a result block below the current code block, and kills it." (when-markdown-mode - (with-constant-position - (when (block-at-point (current-point)) - (search-forward-regexp (current-point) "```") - (line-offset (current-point) 2) - (when (equal "result" (block-fence-lang (line-string (current-point)))) - (loop :while (not (equal "```" (line-string (current-point)))) + (with-constant-position (point) + (when (block-at-point point) + (search-forward-regexp point "```") + (line-offset point 2) + (when (equal "result" (block-fence-lang (line-string point))) + (loop :while (not (equal "```" (line-string point))) :do (kill-whole-line) - :do (line-offset (current-point) 1)) + :do (line-offset point 1)) (kill-whole-line) (kill-whole-line)))))) -(defun pop-up-eval-result (result) +(defun pop-up-eval-result (point result) "Display results of evaluation in a popup buffer." + (declare (ignore point)) (pop-up-buffer "*literate*" (format nil "~a" result))) (defun insert-eval-result (point result) "Insert results of evaluation in a code block." - (with-constant-position - (kill-block-eval-result) + (with-constant-position (point) (block-at-point point) (search-forward-regexp point "```") (insert-string point (format nil "~%~%```result~%~a~%```" result))) (redraw-display)) -(defun eval-block-internal (handler) +(defun eval-block-internal (point handler) "Evaluate code block and apply handler to result." - (with-constant-position - (multiple-value-bind (lang block) (block-at-point (current-point)) + (with-constant-position (point) + (multiple-value-bind (lang block) (block-at-point (copy-point point)) (when lang (if-let ((evaluator (gethash lang *block-evaluators*))) - (funcall evaluator block handler) + (funcall evaluator block (curry handler point)) (message "No evaluator registered for ~a." lang)))))) (define-command eval-block () () "Evaluate current markdown code block and display results in popup." (when-markdown-mode - (eval-block-internal #'pop-up-eval-result))) + (eval-block-internal + (copy-point (current-point)) + #'pop-up-eval-result))) (define-command eval-block-and-insert () () "Evaluate current markdown code block and display results in popup." (when-markdown-mode - (eval-block-internal (curry #'insert-eval-result (current-point))))) + (kill-block-eval-result) + (eval-block-internal + (copy-point (current-point)) + #'insert-eval-result))) ;; ;; Default evaluators: From 58f11c5da237db95c9b4c49dbecd8c48cfe6605b Mon Sep 17 00:00:00 2001 From: garlic0x1 Date: Sat, 17 Feb 2024 13:44:13 -0600 Subject: [PATCH 09/22] add message and clean up --- extensions/markdown-mode/interactive.lisp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/extensions/markdown-mode/interactive.lisp b/extensions/markdown-mode/interactive.lisp index 08a6b7444..36147eb6e 100644 --- a/extensions/markdown-mode/interactive.lisp +++ b/extensions/markdown-mode/interactive.lisp @@ -76,12 +76,12 @@ (block-at-point point) (search-forward-regexp point "```") (insert-string point (format nil "~%~%```result~%~a~%```" result))) - (redraw-display)) + (message "Block evaluated.")) (defun eval-block-internal (point handler) "Evaluate code block and apply handler to result." (with-constant-position (point) - (multiple-value-bind (lang block) (block-at-point (copy-point point)) + (multiple-value-bind (lang block) (block-at-point point) (when lang (if-let ((evaluator (gethash lang *block-evaluators*))) (funcall evaluator block (curry handler point)) From 186633a0e603cd733ff6790ad15f9af2142ee33e Mon Sep 17 00:00:00 2001 From: garlic0x1 Date: Sat, 17 Feb 2024 14:06:21 -0600 Subject: [PATCH 10/22] export register macro and remove extra with-constant's --- extensions/markdown-mode/interactive.lisp | 34 ++++++++++------------- 1 file changed, 14 insertions(+), 20 deletions(-) diff --git a/extensions/markdown-mode/interactive.lisp b/extensions/markdown-mode/interactive.lisp index 36147eb6e..88c3d0695 100644 --- a/extensions/markdown-mode/interactive.lisp +++ b/extensions/markdown-mode/interactive.lisp @@ -1,6 +1,7 @@ (defpackage :lem-markdown-mode/interactive (:use :cl :lem) - (:import-from #:alexandria :if-let :when-let :curry)) + (:import-from #:alexandria :if-let :when-let :curry) + (:export :register-block-evaluator)) (in-package :lem-markdown-mode/interactive) (defvar *block-evaluators* (make-hash-table :test #'equal) @@ -41,7 +42,7 @@ str))) (defun block-at-point (point) - "Ugly hack to get the string in a code block at point." + "Get the language of a code block and its contents." (search-backward-regexp point "```") (when-let ((lang (block-fence-lang (str:trim (line-string point))))) (search-forward point (format nil "~%")) @@ -72,35 +73,29 @@ (defun insert-eval-result (point result) "Insert results of evaluation in a code block." - (with-constant-position (point) - (block-at-point point) - (search-forward-regexp point "```") - (insert-string point (format nil "~%~%```result~%~a~%```" result))) + (block-at-point point) + (search-forward-regexp point "```") + (insert-string point (format nil "~%~%```result~%~a~%```" result)) (message "Block evaluated.")) (defun eval-block-internal (point handler) "Evaluate code block and apply handler to result." - (with-constant-position (point) - (multiple-value-bind (lang block) (block-at-point point) - (when lang - (if-let ((evaluator (gethash lang *block-evaluators*))) - (funcall evaluator block (curry handler point)) - (message "No evaluator registered for ~a." lang)))))) + (multiple-value-bind (lang block) (block-at-point point) + (when lang + (if-let ((evaluator (gethash lang *block-evaluators*))) + (funcall evaluator block (curry handler point)) + (message "No evaluator registered for ~a." lang))))) (define-command eval-block () () "Evaluate current markdown code block and display results in popup." (when-markdown-mode - (eval-block-internal - (copy-point (current-point)) - #'pop-up-eval-result))) + (eval-block-internal (copy-point (current-point)) #'pop-up-eval-result))) (define-command eval-block-and-insert () () "Evaluate current markdown code block and display results in popup." (when-markdown-mode (kill-block-eval-result) - (eval-block-internal - (copy-point (current-point)) - #'insert-eval-result))) + (eval-block-internal (copy-point (current-point)) #'insert-eval-result))) ;; ;; Default evaluators: @@ -116,8 +111,7 @@ "Register evaluator for Lisp blocks." (lem-lisp-mode:check-connection) (lem-lisp-mode:lisp-eval-async - (read-from-string - (format nil "(progn ~a)" string)) + (read-from-string (format nil "(progn ~a)" string)) (lambda (result) (funcall callback result)))) From 43a071a445b46e518a445ec2b5d1d3858adf548a Mon Sep 17 00:00:00 2001 From: garlic0x1 Date: Sat, 17 Feb 2024 15:08:48 -0600 Subject: [PATCH 11/22] retry tests --- extensions/markdown-mode/interactive.lisp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/markdown-mode/interactive.lisp b/extensions/markdown-mode/interactive.lisp index 88c3d0695..d1805a4a7 100644 --- a/extensions/markdown-mode/interactive.lisp +++ b/extensions/markdown-mode/interactive.lisp @@ -69,7 +69,7 @@ (defun pop-up-eval-result (point result) "Display results of evaluation in a popup buffer." (declare (ignore point)) - (pop-up-buffer "*literate*" (format nil "~a" result))) + (pop-up-buffer "*result*" (format nil "~a" result))) (defun insert-eval-result (point result) "Insert results of evaluation in a code block." From a897c62d42e0776524850b6f3eeebb483560a6a8 Mon Sep 17 00:00:00 2001 From: garlic0x1 Date: Sat, 17 Feb 2024 17:40:47 -0600 Subject: [PATCH 12/22] delay read-from-string for micros env --- extensions/markdown-mode/interactive.lisp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/markdown-mode/interactive.lisp b/extensions/markdown-mode/interactive.lisp index d1805a4a7..8a0347486 100644 --- a/extensions/markdown-mode/interactive.lisp +++ b/extensions/markdown-mode/interactive.lisp @@ -111,7 +111,7 @@ "Register evaluator for Lisp blocks." (lem-lisp-mode:check-connection) (lem-lisp-mode:lisp-eval-async - (read-from-string (format nil "(progn ~a)" string)) + `(eval (read-from-string ,(format nil "(progn ~a)" string))) (lambda (result) (funcall callback result)))) From 069481e8bd62e4c4918ffdb841f625caad228633 Mon Sep 17 00:00:00 2001 From: garlic0x1 Date: Sat, 17 Feb 2024 17:53:45 -0600 Subject: [PATCH 13/22] simplify lambda/funcall --- extensions/markdown-mode/interactive.lisp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/extensions/markdown-mode/interactive.lisp b/extensions/markdown-mode/interactive.lisp index 8a0347486..5c707c204 100644 --- a/extensions/markdown-mode/interactive.lisp +++ b/extensions/markdown-mode/interactive.lisp @@ -112,8 +112,7 @@ (lem-lisp-mode:check-connection) (lem-lisp-mode:lisp-eval-async `(eval (read-from-string ,(format nil "(progn ~a)" string))) - (lambda (result) - (funcall callback result)))) + callback)) ;; ;; Keybindings From 477139ba1f71f3dc135f564308b3c7a7f0095900 Mon Sep 17 00:00:00 2001 From: garlic0x1 Date: Sun, 18 Feb 2024 06:27:30 -0600 Subject: [PATCH 14/22] vindarel style --- extensions/markdown-mode/interactive.lisp | 22 ++++++++----------- .../markdown-mode/lem-markdown-mode.asd | 2 +- 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/extensions/markdown-mode/interactive.lisp b/extensions/markdown-mode/interactive.lisp index 5c707c204..c463a9b96 100644 --- a/extensions/markdown-mode/interactive.lisp +++ b/extensions/markdown-mode/interactive.lisp @@ -4,6 +4,11 @@ (:export :register-block-evaluator)) (in-package :lem-markdown-mode/interactive) +(define-keys lem-markdown-mode::*markdown-mode-keymap* + ("C-c C-e" 'eval-block) + ("C-c C-c" 'eval-block-and-insert) + ("C-c C-d" 'kill-block-eval-result)) + (defvar *block-evaluators* (make-hash-table :test #'equal) "Dispatch table for block evaluators per language.") @@ -27,7 +32,7 @@ (message "Not in markdown mode."))) (defun pop-up-buffer (name text) - "Create a popup with name containing text." + "Create a pop-up with name containing text." (let ((buffer (make-buffer name))) (erase-buffer buffer) (with-buffer-read-only buffer nil @@ -67,7 +72,7 @@ (kill-whole-line)))))) (defun pop-up-eval-result (point result) - "Display results of evaluation in a popup buffer." + "Display results of evaluation in a pop-up buffer." (declare (ignore point)) (pop-up-buffer "*result*" (format nil "~a" result))) @@ -87,12 +92,12 @@ (message "No evaluator registered for ~a." lang))))) (define-command eval-block () () - "Evaluate current markdown code block and display results in popup." + "Evaluate current markdown code block and display results in pop-up." (when-markdown-mode (eval-block-internal (copy-point (current-point)) #'pop-up-eval-result))) (define-command eval-block-and-insert () () - "Evaluate current markdown code block and display results in popup." + "Evaluate current markdown code block and display results in pop-up." (when-markdown-mode (kill-block-eval-result) (eval-block-internal (copy-point (current-point)) #'insert-eval-result))) @@ -113,12 +118,3 @@ (lem-lisp-mode:lisp-eval-async `(eval (read-from-string ,(format nil "(progn ~a)" string))) callback)) - -;; -;; Keybindings -;; - -(define-keys lem-markdown-mode::*markdown-mode-keymap* - ("C-c C-e" 'eval-block) - ("C-c C-c" 'eval-block-and-insert) - ("C-c C-d" 'kill-block-eval-result)) diff --git a/extensions/markdown-mode/lem-markdown-mode.asd b/extensions/markdown-mode/lem-markdown-mode.asd index ed468630a..cc5c5645e 100644 --- a/extensions/markdown-mode/lem-markdown-mode.asd +++ b/extensions/markdown-mode/lem-markdown-mode.asd @@ -1,4 +1,4 @@ -(asdf:defsystem "lem-markdown-mode" +(defsystem "lem-markdown-mode" :depends-on ("lem") :serial t :components ((:file "markdown-mode") From 2964a959dc45af6f1482a7b98743c03641fc256f Mon Sep 17 00:00:00 2001 From: garlic0x1 Date: Sun, 18 Feb 2024 07:10:58 -0600 Subject: [PATCH 15/22] add prefixes to commands --- extensions/markdown-mode/interactive.lisp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/extensions/markdown-mode/interactive.lisp b/extensions/markdown-mode/interactive.lisp index c463a9b96..0041dced0 100644 --- a/extensions/markdown-mode/interactive.lisp +++ b/extensions/markdown-mode/interactive.lisp @@ -5,9 +5,9 @@ (in-package :lem-markdown-mode/interactive) (define-keys lem-markdown-mode::*markdown-mode-keymap* - ("C-c C-e" 'eval-block) - ("C-c C-c" 'eval-block-and-insert) - ("C-c C-d" 'kill-block-eval-result)) + ("C-c C-e" 'markdown-eval-block) + ("C-c C-c" 'markdown-eval-block-and-insert) + ("C-c C-d" 'markdown-kill-block-result)) (defvar *block-evaluators* (make-hash-table :test #'equal) "Dispatch table for block evaluators per language.") @@ -57,7 +57,7 @@ (let ((end point)) (values lang (points-to-string start end)))))) -(define-command kill-block-eval-result (&optional (point (current-point))) () +(define-command markdown-kill-block-result (&optional (point (current-point))) () "Searches for a result block below the current code block, and kills it." (when-markdown-mode (with-constant-position (point) @@ -91,15 +91,15 @@ (funcall evaluator block (curry handler point)) (message "No evaluator registered for ~a." lang))))) -(define-command eval-block () () +(define-command markdown-eval-block () () "Evaluate current markdown code block and display results in pop-up." (when-markdown-mode (eval-block-internal (copy-point (current-point)) #'pop-up-eval-result))) -(define-command eval-block-and-insert () () +(define-command markdown-eval-block-and-insert () () "Evaluate current markdown code block and display results in pop-up." (when-markdown-mode - (kill-block-eval-result) + (markdown-kill-block-result) (eval-block-internal (copy-point (current-point)) #'insert-eval-result))) ;; From 384abd326f891f8eef03d80a3718b0de2b60a87a Mon Sep 17 00:00:00 2001 From: garlic0x1 Date: Mon, 19 Feb 2024 09:59:28 -0600 Subject: [PATCH 16/22] delete copied points --- extensions/markdown-mode/interactive.lisp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/extensions/markdown-mode/interactive.lisp b/extensions/markdown-mode/interactive.lisp index 0041dced0..0fddd89c9 100644 --- a/extensions/markdown-mode/interactive.lisp +++ b/extensions/markdown-mode/interactive.lisp @@ -22,7 +22,8 @@ "This allows you to move around the point without worry." `(let ((tmp (copy-point ,point))) (prog1 (progn ,@body) - (move-point ,point tmp)))) + (move-point ,point tmp) + (delete-point tmp)))) (defmacro when-markdown-mode (&body body) "Ensure the major mode is markdown-mode and alert the user if not." @@ -54,8 +55,9 @@ (let ((start (copy-point point))) (search-forward-regexp point "```") (search-backward point (format nil "~%")) - (let ((end point)) - (values lang (points-to-string start end)))))) + (let ((string (points-to-string start point))) + (delete-point start) + (values lang string))))) (define-command markdown-kill-block-result (&optional (point (current-point))) () "Searches for a result block below the current code block, and kills it." @@ -73,15 +75,16 @@ (defun pop-up-eval-result (point result) "Display results of evaluation in a pop-up buffer." - (declare (ignore point)) - (pop-up-buffer "*result*" (format nil "~a" result))) + (pop-up-buffer "*result*" (format nil "~a" result)) + (delete-point point)) (defun insert-eval-result (point result) "Insert results of evaluation in a code block." (block-at-point point) (search-forward-regexp point "```") (insert-string point (format nil "~%~%```result~%~a~%```" result)) - (message "Block evaluated.")) + (message "Block evaluated.") + (delete-point point)) (defun eval-block-internal (point handler) "Evaluate code block and apply handler to result." From fa32311b6e9400d1cbc87e76d6fdc5406ca6ba5b Mon Sep 17 00:00:00 2001 From: garlic0x1 Date: Wed, 21 Feb 2024 20:15:58 -0600 Subject: [PATCH 17/22] eval and do nothing command --- extensions/markdown-mode/interactive.lisp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/extensions/markdown-mode/interactive.lisp b/extensions/markdown-mode/interactive.lisp index 0fddd89c9..949c9350f 100644 --- a/extensions/markdown-mode/interactive.lisp +++ b/extensions/markdown-mode/interactive.lisp @@ -6,6 +6,7 @@ (define-keys lem-markdown-mode::*markdown-mode-keymap* ("C-c C-e" 'markdown-eval-block) + ("C-c C-r" 'markdown-eval-block-nop) ("C-c C-c" 'markdown-eval-block-and-insert) ("C-c C-d" 'markdown-kill-block-result)) @@ -86,6 +87,12 @@ (message "Block evaluated.") (delete-point point)) +(defun nop-eval-result (point result) + "Evaluate block and do nothing with result." + (declare (ignore result)) + (message "Block evaluated.") + (delete-point point)) + (defun eval-block-internal (point handler) "Evaluate code block and apply handler to result." (multiple-value-bind (lang block) (block-at-point point) @@ -99,6 +106,11 @@ (when-markdown-mode (eval-block-internal (copy-point (current-point)) #'pop-up-eval-result))) +(define-command markdown-eval-block-nop () () + "Evaluate current markdown code block and display results in pop-up." + (when-markdown-mode + (eval-block-internal (copy-point (current-point)) #'nop-eval-result))) + (define-command markdown-eval-block-and-insert () () "Evaluate current markdown code block and display results in pop-up." (when-markdown-mode From 8983947206b00ab96df14536a1c494decfb98d90 Mon Sep 17 00:00:00 2001 From: garlic0x1 Date: Wed, 21 Feb 2024 20:17:23 -0600 Subject: [PATCH 18/22] docstrings --- extensions/markdown-mode/interactive.lisp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/extensions/markdown-mode/interactive.lisp b/extensions/markdown-mode/interactive.lisp index 949c9350f..039cefed2 100644 --- a/extensions/markdown-mode/interactive.lisp +++ b/extensions/markdown-mode/interactive.lisp @@ -88,7 +88,7 @@ (delete-point point)) (defun nop-eval-result (point result) - "Evaluate block and do nothing with result." + "Clean up and do nothing with result." (declare (ignore result)) (message "Block evaluated.") (delete-point point)) @@ -107,7 +107,7 @@ (eval-block-internal (copy-point (current-point)) #'pop-up-eval-result))) (define-command markdown-eval-block-nop () () - "Evaluate current markdown code block and display results in pop-up." + "Evaluate current markdown code block and do nothing with result." (when-markdown-mode (eval-block-internal (copy-point (current-point)) #'nop-eval-result))) From 91b679faa13fdb7eba41b6af1e2117be20f875ed Mon Sep 17 00:00:00 2001 From: garlic0x1 Date: Wed, 21 Feb 2024 20:39:06 -0600 Subject: [PATCH 19/22] dedupe cleanup logic and mode check --- extensions/markdown-mode/interactive.lisp | 43 +++++++++++++---------- 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/extensions/markdown-mode/interactive.lisp b/extensions/markdown-mode/interactive.lisp index 039cefed2..20598d0e1 100644 --- a/extensions/markdown-mode/interactive.lisp +++ b/extensions/markdown-mode/interactive.lisp @@ -76,46 +76,51 @@ (defun pop-up-eval-result (point result) "Display results of evaluation in a pop-up buffer." - (pop-up-buffer "*result*" (format nil "~a" result)) - (delete-point point)) + (declare (ignore point)) + (pop-up-buffer "*result*" (format nil "~a" result))) (defun insert-eval-result (point result) "Insert results of evaluation in a code block." (block-at-point point) (search-forward-regexp point "```") (insert-string point (format nil "~%~%```result~%~a~%```" result)) - (message "Block evaluated.") - (delete-point point)) + (message "Block evaluated.")) (defun nop-eval-result (point result) "Clean up and do nothing with result." - (declare (ignore result)) - (message "Block evaluated.") - (delete-point point)) + (declare (ignore point result)) + (message "Block evaluated.")) + +(defun cleanup-after-handler (handler) + "Wrap handlers to delete the point when they are done." + (lambda (point result) + (funcall handler point result) + (delete-point point))) (defun eval-block-internal (point handler) "Evaluate code block and apply handler to result." - (multiple-value-bind (lang block) (block-at-point point) - (when lang - (if-let ((evaluator (gethash lang *block-evaluators*))) - (funcall evaluator block (curry handler point)) - (message "No evaluator registered for ~a." lang))))) + (when-markdown-mode + (multiple-value-bind (lang block) (block-at-point point) + (when lang + (if-let ((evaluator (gethash lang *block-evaluators*))) + (funcall evaluator block (curry handler point)) + (message "No evaluator registered for ~a." lang)))))) (define-command markdown-eval-block () () "Evaluate current markdown code block and display results in pop-up." - (when-markdown-mode - (eval-block-internal (copy-point (current-point)) #'pop-up-eval-result))) + (eval-block-internal (copy-point (current-point)) + (cleanup-after-handler #'pop-up-eval-result))) (define-command markdown-eval-block-nop () () "Evaluate current markdown code block and do nothing with result." - (when-markdown-mode - (eval-block-internal (copy-point (current-point)) #'nop-eval-result))) + (eval-block-internal (copy-point (current-point)) + (cleanup-after-handler #'nop-eval-result))) (define-command markdown-eval-block-and-insert () () "Evaluate current markdown code block and display results in pop-up." - (when-markdown-mode - (markdown-kill-block-result) - (eval-block-internal (copy-point (current-point)) #'insert-eval-result))) + (markdown-kill-block-result) + (eval-block-internal (copy-point (current-point)) + (cleanup-after-handler #'insert-eval-result))) ;; ;; Default evaluators: From 00f20d9970a3151ee672628de968845f62bd2f95 Mon Sep 17 00:00:00 2001 From: garlic0x1 Date: Thu, 22 Feb 2024 01:09:36 -0600 Subject: [PATCH 20/22] unify handler wrappers --- extensions/markdown-mode/interactive.lisp | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/extensions/markdown-mode/interactive.lisp b/extensions/markdown-mode/interactive.lisp index 20598d0e1..61f0f0873 100644 --- a/extensions/markdown-mode/interactive.lisp +++ b/extensions/markdown-mode/interactive.lisp @@ -1,6 +1,6 @@ (defpackage :lem-markdown-mode/interactive (:use :cl :lem) - (:import-from #:alexandria :if-let :when-let :curry) + (:import-from #:alexandria :if-let :when-let) (:export :register-block-evaluator)) (in-package :lem-markdown-mode/interactive) @@ -91,9 +91,9 @@ (declare (ignore point result)) (message "Block evaluated.")) -(defun cleanup-after-handler (handler) - "Wrap handlers to delete the point when they are done." - (lambda (point result) +(defun wrap-handler (handler point) + "Wrap handlers to capture and delete the point when they are done." + (lambda (result) (funcall handler point result) (delete-point point))) @@ -103,24 +103,21 @@ (multiple-value-bind (lang block) (block-at-point point) (when lang (if-let ((evaluator (gethash lang *block-evaluators*))) - (funcall evaluator block (curry handler point)) + (funcall evaluator block (wrap-handler handler point)) (message "No evaluator registered for ~a." lang)))))) (define-command markdown-eval-block () () "Evaluate current markdown code block and display results in pop-up." - (eval-block-internal (copy-point (current-point)) - (cleanup-after-handler #'pop-up-eval-result))) + (eval-block-internal (copy-point (current-point)) #'pop-up-eval-result)) (define-command markdown-eval-block-nop () () "Evaluate current markdown code block and do nothing with result." - (eval-block-internal (copy-point (current-point)) - (cleanup-after-handler #'nop-eval-result))) + (eval-block-internal (copy-point (current-point)) #'nop-eval-result)) (define-command markdown-eval-block-and-insert () () "Evaluate current markdown code block and display results in pop-up." (markdown-kill-block-result) - (eval-block-internal (copy-point (current-point)) - (cleanup-after-handler #'insert-eval-result))) + (eval-block-internal (copy-point (current-point)) #'insert-eval-result)) ;; ;; Default evaluators: From 250adf57d91dc91dfe79f5ed59e96b23f86a03d3 Mon Sep 17 00:00:00 2001 From: garlic0x1 Date: Sat, 9 Mar 2024 11:02:30 -0600 Subject: [PATCH 21/22] s/prog1/unwind-protect --- extensions/markdown-mode/interactive.lisp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/extensions/markdown-mode/interactive.lisp b/extensions/markdown-mode/interactive.lisp index 61f0f0873..7d2a01937 100644 --- a/extensions/markdown-mode/interactive.lisp +++ b/extensions/markdown-mode/interactive.lisp @@ -22,7 +22,7 @@ (defmacro with-constant-position ((point) &body body) "This allows you to move around the point without worry." `(let ((tmp (copy-point ,point))) - (prog1 (progn ,@body) + (unwind-protect (progn ,@body) (move-point ,point tmp) (delete-point tmp)))) @@ -133,5 +133,6 @@ "Register evaluator for Lisp blocks." (lem-lisp-mode:check-connection) (lem-lisp-mode:lisp-eval-async - `(eval (read-from-string ,(format nil "(progn ~a)" string))) + `(handler-case (eval (read-from-string (format nil "(progn ~a)" ,string))) + (error (c) (format nil "Error: ~a" c))) callback)) From fa781690686f1fa244809edd310fab3ca769b053 Mon Sep 17 00:00:00 2001 From: garlic0x1 Date: Sun, 10 Mar 2024 00:37:13 -0600 Subject: [PATCH 22/22] wtf --- extensions/markdown-mode/interactive.lisp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/extensions/markdown-mode/interactive.lisp b/extensions/markdown-mode/interactive.lisp index 7d2a01937..88c444979 100644 --- a/extensions/markdown-mode/interactive.lisp +++ b/extensions/markdown-mode/interactive.lisp @@ -133,6 +133,8 @@ "Register evaluator for Lisp blocks." (lem-lisp-mode:check-connection) (lem-lisp-mode:lisp-eval-async - `(handler-case (eval (read-from-string (format nil "(progn ~a)" ,string))) - (error (c) (format nil "Error: ~a" c))) + (read-from-string (format nil "(progn ~a)" string)) callback)) + +;; `(handler-case (eval (read-from-string (format nil "(progn ~a)" ,string))) +;; (error (c) (format nil "Error: ~a" c)))