[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)
- [elpa] branch externals/drepl created (now aeba86f820), ELPA Syncer, 2023/11/07
- [elpa] externals/drepl 5650fef65d 08/10: Buffer association logic, ELPA Syncer, 2023/11/07
- [elpa] externals/drepl eaced7db3b 01/10: Initial commit, ELPA Syncer, 2023/11/07
- [elpa] externals/drepl 936bbe1c27 03/10: Add OSC to comint-output-filter-functions, ELPA Syncer, 2023/11/07
- [elpa] externals/drepl f0e87367b3 02/10: Make prompt faces inherit from default, ELPA Syncer, 2023/11/07
- [elpa] externals/drepl b30295f6f9 04/10: Use defclass instead of defstruct,
ELPA Syncer <=
- [elpa] externals/drepl b6d3bd9183 05/10: Add setoptions method and getoptions notification, ELPA Syncer, 2023/11/07
- [elpa] externals/drepl b79b71d39b 06/10: Refactoring and documentation, ELPA Syncer, 2023/11/07
- [elpa] externals/drepl 8f96ca981a 07/10: Add commands to evaluate a region and a buffer, ELPA Syncer, 2023/11/07
- [elpa] externals/drepl 61d907e463 09/10: Use Eldoc to display documentation, ELPA Syncer, 2023/11/07
- [elpa] externals/drepl aeba86f820 10/10: Add readme and commentary, ELPA Syncer, 2023/11/07