Closed Dima-369 closed 9 months ago
I haven't tried an e-lisp tree-sitter, but in principle it should work the same as any other language. Please give it a try and comment back.; you'll need to use treesit-explore-mode and pick some relevant node types for indent-bars-treesit-wrap
. The problem with lisp languages is that they do not respect indentation spacing really at all. I.e. most lines are lined up with opening parens of lines before them, not a fixed indent spacing.
For a fringe indicator, that shouldn't be too hard, but that should be a separate package.
Please give it a try and comment back.; you'll need to use treesit-explore-mode and pick some relevant node types for indent-bars-treesit-wrap.
I tried with https://github.com/Wilfred/tree-sitter-elisp
Here is a code-dump if anyone wants to try it out as well. It doesn't seem to work well on nested structures apparently Maybe you have improvement ideas?
(dolist (grammar
'((elisp "https://github.com/Wilfred/tree-sitter-elisp")))
(add-to-list 'treesit-language-source-alist grammar)
(unless (treesit-language-available-p (car grammar))
(treesit-install-language-grammar (car grammar))))
(dolist (mapping '((emacs-lisp-mode . emacs-lisp-ts-mode)))
(add-to-list 'major-mode-remap-alist mapping))
(define-derived-mode emacs-lisp-ts-mode emacs-lisp-mode "Emacs Lisp"
"Major mode for editing Emacs Lisp files, using tree-sitter library."
(when (treesit-ready-p 'elisp)
(treesit-parser-create 'elisp)
(treesit-major-mode-setup)))
;; remap
(defun dima-indent-bars-emacs-lisp-setup ()
"Setup for `emacs-lisp-ts-mode'."
(setq-local indent-bars-treesit-support t)
(setq-local indent-bars-treesit-wrap '((elisp list)))
(setq-local indent-bars-treesit-ignore-blank-lines-types '("source_file"))
(indent-bars-mode))
(add-hook 'emacs-lisp-ts-mode-hook #'dima-indent-bars-emacs-lisp-setup)
I stuffed in more into indent-bars-treesit-wrap
, but it doesn't get any better: (setq-local indent-bars-treesit-wrap '((elisp special_form quote list symbol)))
Lots of list
s as expected ;)
(defmacro async-let (bindings &rest forms)
"Implements `let', but each binding is established asynchronously.
For example:
(async-let ((x (foo))
(y (bar)))
(message \"%s %s\" x y))
expands to ==>
(async-start (foo)
(lambda (x)
(async-start (bar)
(lambda (y)
(message \"%s %s\" x y)))))"
(declare (indent 1))
(async--fold-left
(lambda (acc binding)
(let ((fun (pcase (cadr binding)
((and (pred functionp) f) f)
(f `(lambda () ,f)))))
`(async-start ,fun
(lambda (,(car binding))
,acc))))
`(progn ,@forms)
(reverse bindings)))
(defun test ()
(if t
(let ((yoyo)
(bobo 123))
(if t
1
2))
2))
Here is a screenshot how PyCharm does it (to me that's the reference implementation since it's the most advanced):
As an idea, I used https://github.com/sogaiu/tree-sitter-clojure for emacs-lisp-ts-mode
, but it just doesn't work out at all. As soon as anything is in indent-bars-treesit-wrap
, no indent bars are shown.
(setq-local indent-bars-treesit-wrap '((clojure list_lit)))
(setq-local indent-bars-treesit-ignore-blank-lines-types '("source"))
Yeah. If you put list
into wrap, indent-bars will simply avoid descending into any list further than the top level. So the result is not surprising. What did you expect to see?
I don't see PyCharm as being a reference here. The bar structure here looks strange, e.g. why doesn't the fun
binding have its own bar?
I'll leave this open in case anyone has some ideas for a sensible skip/resume bar algorithm. With tree-sitter we have fast access to all containing nodes matching the wrap type, along with their starting buffer positions.
I suppose one first needs to install https://github.com/Wilfred/tree-sitter-elisp or https://github.com/Alhadis/language-emacs-lisp and then test out if
indent-bars
behaves correctly withindent-bars-treesit-support: t
?Or is there a easier 'Lisp' mode in
indent-bars
?For instance, if I open up a
.el
file in PyCharm, the indent bars correctly nest and excessive ones are hidden (I am a bit surprised that it even works out of the box and even inside the doc string) and here the indent bars are highly useful, even without proper syntax highlighting:Here, one also sees the nice usage of skipping indent bars for the
(lambda
as noted in https://github.com/jdtsmith/indent-bars/issues/18I also noticed when one places the cursor over one parentheses (starting or closing), that the fringe shows the length of the entire wrapped expression (but this should be out-of-scope for this package, I think).
Text: