emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[elpa] externals/drepl b30295f6f9 04/10: Use defclass instead of defstru


From: ELPA Syncer
Subject: [elpa] externals/drepl b30295f6f9 04/10: Use defclass instead of defstruct
Date: Tue, 7 Nov 2023 03:58:04 -0500 (EST)

branch: externals/drepl
commit b30295f6f9ddd65ec1b89074dc290bb132b22db4
Author: Augusto Stoffel <arstoffel@gmail.com>
Commit: Augusto Stoffel <arstoffel@gmail.com>

    Use defclass instead of defstruct
---
 drepl-ipython.el |  58 ++++++++++++-------------
 drepl-lua.el     |  40 ++++++-----------
 drepl.el         | 129 +++++++++++++++++++++++++++++++++++++++++--------------
 3 files changed, 137 insertions(+), 90 deletions(-)

diff --git a/drepl-ipython.el b/drepl-ipython.el
index ea84083ccb..02f768e9ef 100644
--- a/drepl-ipython.el
+++ b/drepl-ipython.el
@@ -24,11 +24,12 @@
 
 ;;; Code:
 
-;;; Customization options
 (require 'comint-mime)
 (require 'drepl)
 (require 'python)
 
+;;; Customization options
+
 (defgroup drepl-ipython nil
   "IPython shell implemented via dREPL"
   :group 'drepl
@@ -46,18 +47,6 @@
                       default-directory))
   "File name of the startup script.")
 
-(cl-defstruct (drepl-ipython (:include drepl)))
-
-(cl-defmethod drepl--restart :around ((repl drepl-ipython))
-  (if (eq (drepl-status repl) 'ready)
-      (with-current-buffer (drepl-buffer repl)
-        (save-excursion)
-        (goto-char (process-mark (drepl-process repl)))
-        (insert-before-markers "%reset -f")
-        (drepl--eval repl "%reset -f"))
-    (cl-call-next-method)
-    (drepl-ipython)))
-
 (define-derived-mode drepl-ipython-mode drepl-mode "IPython"
   "Major mode for the IPython shell.
 
@@ -67,26 +56,33 @@
   (setq-local comint-indirect-setup-function #'python-mode)
   (push '("5151" . comint-mime-osc-handler) ansi-osc-handlers))
 
+(defclass drepl-ipython (drepl-base) nil)
+
 ;;;###autoload
-(defun drepl-ipython ()
-  "Run the IPython interpreter in an inferior process."
+(defun drepl-run-ipython ()
   (interactive)
-  (let* ((buffer (get-buffer-create drepl-ipython-buffer-name)))
-    (unless (comint-check-proc buffer)
-      (make-comint-in-buffer
-       (buffer-name buffer)
-       buffer
-       python-interpreter nil
-       "-c"
-       "import sys; exec(''.join(sys.stdin)); DRepl.instance().mainloop()")
-      (with-current-buffer buffer
-        (drepl-ipython-mode)
-        (setq-local drepl--current (make-drepl-ipython :buffer buffer))
-        (with-temp-buffer
-          (insert-file-contents drepl-ipython--start-file)
-          (process-send-string buffer (buffer-string))
-          (process-send-eof buffer))))
-    (pop-to-buffer buffer display-comint-buffer-action)))
+  (drepl--run 'drepl-ipython t))
+
+(cl-defmethod drepl--command ((_ drepl-ipython))
+  `(,python-interpreter "-c"
+    "import sys; exec(''.join(sys.stdin)); DRepl.instance().mainloop()"))
+
+(cl-defmethod drepl--init ((_ drepl-ipython))
+  (drepl-ipython-mode)
+  (let ((buffer (current-buffer)))
+    (with-temp-buffer
+      (insert-file-contents drepl-ipython--start-file)
+      (process-send-string buffer (buffer-string))
+      (process-send-eof buffer))))
+
+(cl-defmethod drepl--restart :around ((repl drepl-ipython) hard)
+  (if (and (not hard) (eq (drepl--status repl) 'ready))
+      (with-current-buffer (drepl--buffer repl)
+        (save-excursion)
+        (goto-char (process-mark (drepl--process repl)))
+        (insert-before-markers "%reset -f")
+        (drepl--eval repl "%reset -f"))
+    (cl-call-next-method)))
 
 (provide 'drepl-ipython)
 
diff --git a/drepl-lua.el b/drepl-lua.el
index acfbf8ee68..e13e13c755 100644
--- a/drepl-lua.el
+++ b/drepl-lua.el
@@ -45,10 +45,12 @@
                       default-directory))
   "File name of the startup script.")
 
-(cl-defstruct (drepl-lua (:include drepl)))
+(defclass drepl-lua (drepl-base) nil)
 
-(cl-defmethod drepl--restart :after ((_repl drepl-lua))
-  (drepl-lua))
+;;;###autoload
+(defun drepl-run-lua ()
+  (interactive)
+  (drepl--run 'drepl-lua t))
 
 (define-derived-mode drepl-lua-mode drepl-mode "Lua"
   "Major mode for the Lua shell.
@@ -58,30 +60,16 @@
   :interactive nil
   (setq-local comint-indirect-setup-function #'lua-mode))
 
-;;; User commands
+(cl-defmethod drepl--command ((_ drepl-lua))
+  '("lua" "-v" "-e" "loadfile()():main()"))
 
-;;;###autoload
-(defun drepl-lua ()
-  "Run the Lua interpreter in an inferior process."
-  (interactive)
-  (cl-letf* ((buffer (get-buffer-create drepl-lua-buffer-name))
-             ((default-value 'process-environment) process-environment)
-             ((default-value 'exec-path) exec-path))
-    (unless (comint-check-proc buffer)
-      (make-comint-in-buffer
-       (buffer-name buffer)
-       buffer
-       "lua" nil "-v" "-e" "loadfile()():main()")
-      (with-current-buffer buffer
-        (drepl-lua-mode)
-        (setq-local process-environment process-environment) ;FIXME
-        (setq-local exec-path exec-path)
-        (setq-local drepl--current (make-drepl-lua :buffer buffer))
-        (with-temp-buffer
-          (insert-file-contents drepl-lua--start-file)
-          (process-send-string buffer (buffer-string))
-          (process-send-eof buffer))))
-    (pop-to-buffer buffer display-comint-buffer-action)))
+(cl-defmethod drepl--init ((_ drepl-lua))
+  (drepl-lua-mode)
+  (let ((buffer (current-buffer)))
+    (with-temp-buffer
+      (insert-file-contents drepl-lua--start-file)
+      (process-send-string buffer (buffer-string))
+      (process-send-eof buffer))))
 
 (provide 'drepl-lua)
 
diff --git a/drepl.el b/drepl.el
index 875cd51219..0da1068d4a 100644
--- a/drepl.el
+++ b/drepl.el
@@ -24,8 +24,10 @@
 
 ;;; Code:
 
+(require 'eieio)
 (require 'cl-lib)
 (require 'comint)
+(require 'project)
 (eval-when-compile (require 'subr-x))
 
 ;;; Variables and customization options
@@ -41,6 +43,13 @@
 (defface drepl-prompt-invalid '((t :inherit (error default)))
   "Face for continuation prompts when input is invalid.")
 
+(defcustom drepl-directory #'drepl--project-directory
+  "Directory in which to run the REPL process.
+It can be a string (the directory name) or a function returning a
+directory name.  The function should accept one argument ASK
+which determines whether to ask or return nil when in doubt."
+  :type '(choice string function))
+
 (defvar-local drepl--current nil
   "dREPL associated to the current buffer.")
 
@@ -48,22 +57,23 @@
 
 ;;; Basic definitions
 
-(cl-defstruct drepl
-  "Base dREPL object."
-  buffer
-  status
-  (last-request-id 0)
-  requests
-  pending)
+(defclass drepl-base ()
+  ((buffer :initarg :buffer :reader drepl--buffer)
+   (status :initform nil :accessor drepl--status)
+   (last-request-id :initform 0)
+   (requests :initform nil)
+   (pending :initform nil))
+  :abstract t
+  :documentation "Base dREPL class.")
 
-(cl-defgeneric drepl-process (repl)
-  (get-buffer-process (drepl-buffer repl)))
+(defun drepl--process (repl)
+  (get-buffer-process (drepl--buffer repl)))
 
 (defun drepl--get-repl (&optional status)
   (let ((repl drepl--current))          ;TODO: choose one interactively, maybe
     (when (or (not status)
-              (and (memq (process-status (drepl-process repl)) '(run open))
-                   (eq status (drepl-status repl))))
+              (and (memq (process-status (drepl--process repl)) '(run open))
+                   (eq status (drepl--status repl))))
       repl)))
 
 (defsubst drepl--message (format-string &rest args)
@@ -85,32 +95,32 @@
 
 (cl-defgeneric drepl--send-request (repl data)
   (drepl--message "OUT: %s" (json-serialize data))
-  (setf (drepl-status repl) 'busy)
-  (process-send-string (drepl-process repl)
+  (setf (drepl--status repl) 'busy)
+  (process-send-string (drepl--process repl)
                        (format "\e%%%s\n" (json-serialize data))))
 
 (cl-defgeneric drepl--communicate (repl callback op &rest args)
   (if (eq callback 'sync)
-      (progn (unless (eq (drepl-status repl) 'ready)
+      (progn (unless (eq (drepl--status repl) 'ready)
                (user-error "%s is busy" repl))
              (let* ((result :none)
                     (cb (lambda (data) (setq result data))))
                (apply #'drepl--communicate repl cb op args)
                (while (eq result :none) (accept-process-output))
                result))
-    (let* ((id (cl-incf (drepl-last-request-id repl)))
+    (let* ((id (cl-incf (oref repl last-request-id)))
            (data `(:id ,id :op ,(symbol-name op) ,@args)))
-      (push (cons id callback) (if-let ((reqs (drepl-requests repl)))
+      (push (cons id callback) (if-let ((reqs (oref repl requests)))
                                    (cdr reqs)
-                                 (drepl-requests repl)))
-      (if (eq 'ready (drepl-status repl))
+                                 (oref repl requests)))
+      (if (eq 'ready (drepl--status repl))
           (drepl--send-request repl data)
-        (push (cons id data) (drepl-pending repl)))
+        (push (cons id data) (oref repl pending)))
       id)))
 
 (cl-defgeneric drepl--handle-notification (repl data)
   (pcase (alist-get 'op data)
-    ("status" (setf (drepl-status repl)
+    ("status" (setf (drepl--status repl)
                     (intern (alist-get 'status data))))
     ("log" (drepl--message "dREPL buffer %s: %s"
                            (buffer-name)
@@ -122,14 +132,14 @@
          (id (alist-get 'id data))
          (callback (if id
                        (prog1
-                           (alist-get id (drepl-requests drepl--current))
-                         (setf (alist-get id (drepl-requests drepl--current)
+                           (alist-get id (oref drepl--current requests))
+                         (setf (alist-get id (oref drepl--current requests)
                                           nil 'remove)
                                nil))
                      (apply-partially #'drepl--handle-notification
                                       drepl--current))))
-    (when-let ((nextreq (and (eq (drepl-status drepl--current) 'ready)
-                             (pop (drepl-pending drepl--current)))))
+    (when-let ((nextreq (and (eq (drepl--status drepl--current) 'ready)
+                             (pop (oref drepl--current pending)))))
       (drepl--send-request drepl--current nextreq))
     (when callback
       (funcall callback data))))
@@ -201,7 +211,7 @@ insert start a continuation line instead."
   (unless (derived-mode-p 'drepl-mode)
     (user-error "Can't run this command here."))
   (let-alist (when-let ((repl (unless force (drepl--get-repl 'ready)))
-                        (pmark (process-mark (drepl-process repl)))
+                        (pmark (process-mark (drepl--process repl)))
                         (code (and (>= (point) pmark)
                                    (buffer-substring-no-properties
                                     pmark (field-end)))))
@@ -250,16 +260,68 @@ insert start a continuation line instead."
 
 ;;; Initialization and restart
 
-(cl-defgeneric drepl--restart (drepl)
+(defun drepl--project-directory (ask)
+  "Return the current project root directory.
+If it can be determined and ASK is non-nil, ask for a project;
+otherwise fall back to `default-directory'."
+  (if-let ((proj (project-current ask)))
+      (project-root proj)
+    default-directory))
+
+(defun drepl--buffer-name (class dir)
+  (format "%s/*%s*"
+          (file-name-nondirectory
+           (directory-file-name dir))
+          class))
+
+(defun drepl--get-buffer-create (class ask)
+  "Get or create a dREPL buffer of the given CLASS.
+The directory of the buffer is determined by
+`drepl-directory'. If ASK is non-nil, allow an interactive query
+if needed."
+  (if (eq (type-of drepl--current) class)
+      (drepl--buffer drepl--current)
+    (let ((default-directory (if (stringp drepl-directory)
+                                 drepl-directory
+                               (funcall drepl-directory ask))))
+      (get-buffer-create (drepl--buffer-name class default-directory)))))
+
+(cl-defgeneric drepl--command (repl)
+  (ignore repl)
+  (error "This needs an implementation"))
+
+(cl-defgeneric drepl--init (repl)
+  (ignore repl)
+  (error "This needs an implementation"))
+
+(cl-defgeneric drepl--restart (repl _hard)
   "Restart the REPL."
-  (with-current-buffer (drepl-buffer drepl)
-    (kill-process (drepl-process drepl--current))
-    (while (accept-process-output (drepl-process drepl--current)))))
+  (with-current-buffer (drepl--buffer repl)
+    (kill-process (drepl--process repl))
+    (while (accept-process-output (drepl--process repl)))
+    (drepl--run (type-of repl) nil)))
 
-(defun drepl-restart ()
-  (interactive)
-  (when-let ((repl (drepl--get-repl)))
-    (drepl--restart repl)))
+(defun drepl-restart (&optional hard)
+  (interactive "P")
+  (if-let ((repl (drepl--get-repl)))
+      (drepl--restart repl hard)
+    (user-error "No REPL to restart")))
+
+(defun drepl--run (class may-prompt)
+  (let ((buffer (drepl--get-buffer-create class may-prompt)))
+    (unless (comint-check-proc buffer)
+      (cl-letf* (((default-value 'process-environment) process-environment)
+                 ((default-value 'exec-path) exec-path)
+                 (repl (make-instance class :buffer buffer))
+                 (command (drepl--command repl)))
+        (with-current-buffer buffer
+          (apply #'make-comint-in-buffer
+               (buffer-name buffer) buffer
+               (car command) nil
+               (cdr command))
+          (drepl--init repl)
+          (setq drepl--current repl))))
+    (pop-to-buffer buffer display-comint-buffer-action)))
 
 ;;; Base major mode
 
@@ -277,6 +339,7 @@ insert start a continuation line instead."
   (push '("5161" . drepl--osc-handler) ansi-osc-handlers)
   (setq-local comint-input-sender #'drepl--send-string)
   (setq-local indent-line-function #'comint-indent-input-line-default)
+  (setq-local list-buffers-directory default-directory)
   (add-hook 'completion-at-point-functions 'drepl--complete nil t))
 
 (provide 'drepl)



reply via email to

[Prev in Thread] Current Thread [Next in Thread]