From cae6554d6e95b3f7a3dbf9d85ba396edd8412543 Mon Sep 17 00:00:00 2001 From: Evgenii Klimov Date: Wed, 24 Sep 2025 23:22:39 +0100 Subject: [PATCH 1/6] Adjust lispy--function-parse to a new object representation. * lispy.el (lispy--function-parse): Update function to a newer object representation. Fix `lispy-flatten'. In Emacs 30, it began to use dedicated type to represent interpreted-function values, `read' function now returns Closure Function Type instead of simple lists for most types that `lispy--function-parse' tries to handle (except macros, at least). See: - https://git.sv.gnu.org/cgit/emacs.git/commit/?id=f2bccae22bd47a2e7e0937b78ea06131711b935a - (elisp) Closure Type - (elisp) Closure Objects Compare (defmacro test-macro (&rest body) ,@body) (symbol-function 'test-macro) ;; (macro . #[(&rest body) ((\,@ body)) (t)]) with (defun test-defun (x) (+ x 1)) (symbol-function 'test-defun) ;; #[(x) ((+ x 1)) (t)] There's alternative way to mitigate it, by changing end of `lispy--function-str' to: (error (let ((str (cl-prin1-to-string (symbol-function fun)))) (if (string-prefix-p "#f" str) (substring str 2) str))) But it hides the underlying change that needs to be addresed in the future. Partially fixes `lispy-let-flatten' as well, but keywords (&optional, &rest) in function's signature are not recognized correctly. --- lispy.el | 76 ++++++++++++++++++++++++++++++-------------------------- 1 file changed, 41 insertions(+), 35 deletions(-) diff --git a/lispy.el b/lispy.el index e2f20427..198661c3 100644 --- a/lispy.el +++ b/lispy.el @@ -7640,42 +7640,48 @@ Defaults to `error'." (defun lispy--function-parse (str) "Extract the function body and args from it's expression STR." (let ((body (lispy--read str)) - args) - (cond ((eq (car body) 'lambda) - (setq body (cons 'defun body))) - ((eq (car body) 'closure) - (setq body `(defun noname ,@(cddr body)))) - ((eq (car body) 'defsubst) - (setq body (cons 'defun (cdr body))))) - (cond ((memq (car body) '(defun defmacro)) - (setq body (lispy--whitespace-trim (cdr body)))) - ((eq (car body) 'defalias) - (let ((name (cadr (cadr (read str))))) - (setq body - (cons name (cdr (symbol-function name)))))) - (t - (error "Expected defun, defmacro, or defalias got %s" (car body)))) - (if (symbolp (car body)) - (setq body (lispy--whitespace-trim (cdr body))) - (error "Expected function name, got %s" (car body))) - (if (listp (car body)) - (progn - (setq args (car body)) + args) + (if (not (consp body)) + (progn (setq args (aref body 0)) + (setq body (aref body 1))) + ;; In Emacs 30, `read' returns a dedicated type, instead of + ;; simple list, for lambdas, defuns, closures, etc. And code + ;; below is only valid for `defmacro'. Keep it for Emacs < 30. + (cond ((eq (car body) 'lambda) + (setq body (cons 'defun body))) + ((eq (car body) 'closure) + (setq body `(defun noname ,@(cddr body)))) + ((eq (car body) 'defsubst) + (setq body (cons 'defun (cdr body))))) + (cond ((memq (car body) '(defun defmacro)) + (setq body (lispy--whitespace-trim (cdr body)))) + ((eq (car body) 'defalias) + (let ((name (cadr (cadr (read str))))) + (setq body + (cons name (cdr (symbol-function name)))))) + (t + (error "Expected defun, defmacro, or defalias got %s" (car body)))) + (if (symbolp (car body)) + (setq body (lispy--whitespace-trim (cdr body))) + (error "Expected function name, got %s" (car body))) + (if (listp (car body)) + (progn + (setq args (car body)) + (setq body (lispy--whitespace-trim (cdr body)))) + (error "Expected function arguments, got %s" (car body))) + ;; skip docstring + (if (and (listp (car body)) + (eq (caar body) 'ly-raw) + (eq (cadar body) 'string)) + (setq body (lispy--whitespace-trim (cdr body)))) + ;; skip declare + (if (and (listp (car body)) + (eq (caar body) 'declare)) (setq body (lispy--whitespace-trim (cdr body)))) - (error "Expected function arguments, got %s" (car body))) - ;; skip docstring - (if (and (listp (car body)) - (eq (caar body) 'ly-raw) - (eq (cadar body) 'string)) - (setq body (lispy--whitespace-trim (cdr body)))) - ;; skip declare - (if (and (listp (car body)) - (eq (caar body) 'declare)) - (setq body (lispy--whitespace-trim (cdr body)))) - ;; skip interactive - (if (and (listp (car body)) - (eq (caar body) 'interactive)) - (setq body (lispy--whitespace-trim (cdr body)))) + ;; skip interactive + (if (and (listp (car body)) + (eq (caar body) 'interactive)) + (setq body (lispy--whitespace-trim (cdr body))))) (list args body))) (defun lispy--flatten-function (fstr e-args) From b41e40744a4d1a06482db9b3e6dd43b63cf9abb8 Mon Sep 17 00:00:00 2001 From: Evgenii Klimov Date: Thu, 25 Sep 2025 01:10:23 +0100 Subject: [PATCH 2/6] Fix lispy-move-down, lispy-move-up for outlines * lispy.el (lispy--bounds-outline): Replace org-element function with the outline one. In new version of Org mode `org-element-at-point' works only in Org-like buffers --- lispy.el | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lispy.el b/lispy.el index 198661c3..b915ab2f 100644 --- a/lispy.el +++ b/lispy.el @@ -6639,7 +6639,9 @@ Otherwise return cons of current string, symbol or list bounds." (org-back-to-heading t) (point)) (progn - (org-end-of-subtree t t) + (outline-mark-subtree) + (exchange-point-and-mark) + (deactivate-mark) (when (and (org-at-heading-p) (not (eobp))) (backward-char 1)) From db4c8a885f86a42202397f0e581ba7970b63dc94 Mon Sep 17 00:00:00 2001 From: Benni Schwerdtner Date: Sat, 28 Oct 2023 10:05:54 +0200 Subject: [PATCH 3/6] Use locate-dominating-file instead of counsel --- le-python.el | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/le-python.el b/le-python.el index da7aa50b..57368da5 100644 --- a/le-python.el +++ b/le-python.el @@ -298,7 +298,8 @@ it at one time." (defvar lispy--python-init-file nil) (defun lispy--python-poetry-name () - (let ((pyproject (expand-file-name "pyproject.toml" (counsel-locate-git-root)))) + (let ((pyproject + (file-name-directory (locate-dominating-file (buffer-file-name) "pyproject.toml")))) (and (file-exists-p pyproject) (not (equal python-shell-interpreter "python")) (with-current-buffer (find-file-noselect pyproject) From 5d9a3d42557f1965fdc0216950b28ad1e7fabb91 Mon Sep 17 00:00:00 2001 From: Evgenii Klimov Date: Wed, 28 Feb 2024 10:33:49 +0000 Subject: [PATCH 4/6] le-python.el (lispy--python-poetry-name): Don't fail outside of project File can be outside of project (so no root) or may not use poetry/pyproject.toml. --- le-python.el | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/le-python.el b/le-python.el index 57368da5..cc4e578c 100644 --- a/le-python.el +++ b/le-python.el @@ -298,8 +298,8 @@ it at one time." (defvar lispy--python-init-file nil) (defun lispy--python-poetry-name () - (let ((pyproject - (file-name-directory (locate-dominating-file (buffer-file-name) "pyproject.toml")))) + (when-let* ((root (locate-dominating-file (buffer-file-name) "pyproject.toml")) + (pyproject (file-name-directory root))) (and (file-exists-p pyproject) (not (equal python-shell-interpreter "python")) (with-current-buffer (find-file-noselect pyproject) From c7bad675fde5f4307ee2d9602dc0e8c38a78a8fe Mon Sep 17 00:00:00 2001 From: Evgenii Klimov Date: Fri, 1 Mar 2024 21:16:49 +0000 Subject: [PATCH 5/6] Don't break in buffer not visiting a file * le-python.el (lispy--python-poetry-name): Fix --- le-python.el | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/le-python.el b/le-python.el index cc4e578c..71b75710 100644 --- a/le-python.el +++ b/le-python.el @@ -298,7 +298,8 @@ it at one time." (defvar lispy--python-init-file nil) (defun lispy--python-poetry-name () - (when-let* ((root (locate-dominating-file (buffer-file-name) "pyproject.toml")) + (when-let* ((bfn (buffer-file-name)) + (root (locate-dominating-file bfn "pyproject.toml")) (pyproject (file-name-directory root))) (and (file-exists-p pyproject) (not (equal python-shell-interpreter "python")) From aa1493176428e4a549d8cb65902bcc4624e4f47b Mon Sep 17 00:00:00 2001 From: Evgenii Klimov Date: Wed, 24 Sep 2025 17:37:02 +0100 Subject: [PATCH 6/6] Replace counsel function with built-in project alternative. * le-python.el (lispy--python-poetry-name): Fix logic. (lispy--python-proc): Replace counsel function with built-in project alternative. --- le-python.el | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/le-python.el b/le-python.el index 71b75710..c3f48e44 100644 --- a/le-python.el +++ b/le-python.el @@ -300,7 +300,7 @@ it at one time." (defun lispy--python-poetry-name () (when-let* ((bfn (buffer-file-name)) (root (locate-dominating-file bfn "pyproject.toml")) - (pyproject (file-name-directory root))) + (pyproject (expand-file-name "pyproject.toml" root))) (and (file-exists-p pyproject) (not (equal python-shell-interpreter "python")) (with-current-buffer (find-file-noselect pyproject) @@ -357,7 +357,8 @@ it at one time." (buffer (let ((python-shell-completion-native-enable nil) (default-directory (if poetry-name - (counsel-locate-git-root) + (expand-file-name + (project-root (project-current))) default-directory))) (python-shell-make-comint python-binary-name proc-name nil nil))))