branch: elpa/treesit-fold
commit 56e6743bacdc8ad4057c878e93baa792ceae601c
Author: Jen-Chieh Shen <[email protected]>
Commit: GitHub <[email protected]>
feat: Improve folding for C preproc operators (#46)
* feat: Improve folding for C preproc operators
* changelog
* imp
---
CHANGELOG.md | 1 +
ts-fold-util.el | 49 +++++++++++++++++++++++++++++++++++++++++++++++++
ts-fold.el | 33 +++++++++++++++++++--------------
3 files changed, 69 insertions(+), 14 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index b873d35944..19deaf481e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -16,6 +16,7 @@ Check [Keep a Changelog](http://keepachangelog.com/) for
recommendations on how
* Remove redundant fold node alist (#36)
* Change global mode to turn on with tree-sitter (#41)
* Add minor-mode `ts-fold-line-comment-mode` for line comment folding (#45)
+* Improve folding for C preprocessor operators (#46)
## 0.1.0
> Released Oct 18, 2021
diff --git a/ts-fold-util.el b/ts-fold-util.el
index 2cf7ae91fb..d9681320ac 100644
--- a/ts-fold-util.el
+++ b/ts-fold-util.el
@@ -25,6 +25,14 @@
;;; Code:
+;;
+;; (@* "Util" )
+;;
+
+(defun ts-fold-2-str (object)
+ "Convert OBJECT to string."
+ (format "%s" object))
+
;;
;; (@* "Cons" )
;;
@@ -86,5 +94,46 @@ Optional argument TRIM, see function `ts-fold--get-face'."
"Check to see if IN-VAL is between IN-MIN and IN-MAX."
(and (<= in-min in-val) (<= in-val in-max)))
+;;
+;; (@* "TS node" )
+;;
+
+(defun ts-fold--compare-type (node type)
+ "Compare NODE's type to TYPE."
+ (string= (ts-fold-2-str (tsc-node-type node)) type))
+
+(defun ts-fold-children (node)
+ "Return children from NODE."
+ (let (children)
+ (dotimes (index (tsc-count-children node))
+ (push (tsc-get-nth-child node index) children))
+ (reverse children)))
+
+(defun ts-fold-children-traverse (node)
+ "Return children from NODE but traverse it."
+ (let (nodes)
+ (tsc-traverse-mapc (lambda (next) (push next nodes)) node)
+ (reverse nodes)))
+
+(defun ts-fold-find-children (node type)
+ "Search node TYPE from children; this return a list."
+ (cl-remove-if-not (lambda (next) (ts-fold--compare-type next type))
+ (ts-fold-children node)))
+
+(defun ts-fold-find-children-traverse (node type)
+ "Like function `ts-fold-find-children' but traverse it."
+ (cl-remove-if-not (lambda (next) (ts-fold--compare-type next type))
+ (ts-fold-children-traverse node)))
+
+(defun ts-fold-find-parent (node type)
+ "Find the TYPE of parent from NODE."
+ (let ((parent (tsc-get-parent node))
+ (break))
+ (while (and parent (not break))
+ (setq break (ts-fold--compare-type parent type))
+ (unless break
+ (setq parent (tsc-get-parent parent))))
+ parent))
+
(provide 'ts-fold-util)
;;; ts-fold-util.el ends here
diff --git a/ts-fold.el b/ts-fold.el
index 09bc224a4c..0412d5cbd4 100644
--- a/ts-fold.el
+++ b/ts-fold.el
@@ -445,7 +445,8 @@ more information."
For arguments NODE and OFFSET, see function `ts-fold-range-seq' for
more information."
(let* ((named-node (tsc-get-child-by-field node :condition))
- (else (tsc-get-child-by-field node :alternative))
+ (else (or (tsc-get-child-by-field node :alternative)
+ (car (ts-fold-find-children node "#endif"))))
(beg (tsc-node-end-position named-node))
(end (1- (tsc-node-start-position else))))
(ts-fold--cons-add (cons beg end) offset)))
@@ -456,7 +457,8 @@ more information."
For arguments NODE and OFFSET, see function `ts-fold-range-seq' for
more information."
(when-let* ((named-node (tsc-get-child-by-field node :name))
- (else (tsc-get-child-by-field node :alternative))
+ (else (or (tsc-get-child-by-field node :alternative)
+ (car (ts-fold-find-children node "#endif"))))
(beg (tsc-node-end-position named-node))
(end (1- (tsc-node-start-position else))))
(ts-fold--cons-add (cons beg end) offset)))
@@ -467,9 +469,12 @@ more information."
For arguments NODE and OFFSET, see function `ts-fold-range-seq' for
more information."
(when-let* ((named-node (tsc-get-child-by-field node :condition))
- (else (tsc-get-child-by-field node :alternative))
+ (parent (or (ts-fold-find-parent node "preproc_if")
+ (ts-fold-find-parent node "preproc_ifdef")))
+ (next (or (tsc-get-child-by-field node :alternative)
+ (car (ts-fold-find-children parent "#endif"))))
(beg (tsc-node-end-position named-node))
- (end (1- (tsc-node-start-position else))))
+ (end (1- (tsc-node-start-position next))))
(ts-fold--cons-add (cons beg end) offset)))
(defun ts-fold-range-c-preproc-else (node offset)
@@ -477,10 +482,12 @@ more information."
For arguments NODE and OFFSET, see function `ts-fold-range-seq' for
more information."
- (when-let* ((target "#else")
- (len (length target))
- (beg (+ (tsc-node-start-position node) len))
- (end (tsc-node-end-position node)))
+ (when-let* ((else-str (car (split-string (tsc-node-text node) "\n")))
+ (parent (or (ts-fold-find-parent node "preproc_if")
+ (ts-fold-find-parent node "preproc_ifdef")))
+ (next (car (ts-fold-find-children parent "#endif")))
+ (beg (+ (tsc-node-start-position node) (length else-str)))
+ (end (1- (tsc-node-start-position next))))
(ts-fold--cons-add (cons beg end) offset)))
(defun ts-fold-range-html (node offset)
@@ -501,12 +508,10 @@ more information."
For arguments NODE and OFFSET, see function `ts-fold-range-seq' for
more information."
(unless (ts-fold--one-liner-node node)
- (when-let*
- ((text (tsc-node-text node))
- (beg (if (string-prefix-p "(* " text)
- (+ 2 (tsc-node-start-position node))
- (+ 3 (tsc-node-start-position node))))
- (end (- (tsc-node-end-position node) 2)))
+ (when-let* ((text (tsc-node-text node))
+ (beg (+ (if (string-prefix-p "(* " text) 2 3)
+ (tsc-node-start-position node)))
+ (end (- (tsc-node-end-position node) 2)))
(ts-fold--cons-add (cons beg end) offset))))
(defun ts-fold-range-ocaml-module-definition (node offset)