Function: combobulate-procedure-apply
combobulate-procedure-apply is a natively compiled function defined in
combobulate-procedure.el.
Signature
(combobulate-procedure-apply PROCEDURE NODE)
Documentation
Apply PROCEDURE to NODE.
PROCEDURE is a form matching the following pattern:
(:activation-nodes (ACTIVATION-NODE-RULES ...))
:selector SELECTOR-RULES)
Where ACTIVATION-NODE-RULES is a list of activation nodes, each of which is a form matching the following pattern:
(:nodes RULES
[:position POSITION-RULE]
[:has-parent HAS-PARENT-RULE]
[:has-fields FIELDS]
[:has-ancestor HAS-ANCESTOR-RULE])
Where RULES is one or more rules outlined in
combobulate-procedure-expand-rules, and POSITION-RULE is one
of:
any, meaning point is anywhere in the node, and is the default;
in, that it is *not* at the beginning;
and at, that it must be at the exact beginning of the node.
HAS-PARENT-RULE and HAS-ANCESTOR-RULE are optional, though at most one can be used in an activation node rule. They each take a list of RULES.
HAS-PARENT-RULE checks if the immediate parent of the action node matches the rules, while HAS-ANCESTOR-RULE checks if any ancestor of the action node matches the rules.
HAS-FIELD-RULE is a list of fields the action node be considered to be inside of.
SELECTOR-RULES is a form matching the following pattern:
(:choose <CHOICE>
<MATCHER PROPERTY>)
Where <MATCHER PROPERTY> is one of:
:match-query <QUERY-MATCHER>
:match-children <NODE-MATCHER>
:match-siblings <NODE-MATCHER>
And CHOICE is either node or parent (the default), indicating whether the
selector should operate on the action node or its matching
parent.
NODE-MATCHER must be either t, indicating all node types (but
not anonymous nodes); or a form of the following pattern:
(:match-rules <RULES|t>
:discard-rules <RULES|t>
[:anonymous <nil|t>]
[:default-mark <@match|@discard>])
Only one of :match-rules or :discard-rules can be used in
NODE-MATCHER. :anonymous is a boolean and defaults to nil, and
:default-mark is a symbol and defaults to
@match. :default-mark is the tie-breaker when a node is not
matched by :match-rules or :discard-rules.
QUERY-MATCHER must be of the form:
(:query <QUERY
[:engine <combobulate|treesitter>]
[:discard-rules <RULES>])
Note that QUERY can be either Combobulate's internal query
language to non-recursively match against NODE, or a regular
tree-sitter query that recursively matches against NODE and any
children of NODE. The :engine flag determines which, and it
defaults to combobulate. :discard-rules is a list of rules
(or t indicating match everything, but not anonymous nodes).
Source Code
;; Defined in /nix/store/b5fvrwzi3zvkabyzx0in6gw1cj963z46-emacs-packages-deps/share/emacs/site-lisp/combobulate-procedure.el
(defun combobulate-procedure-apply (procedure node)
"Apply PROCEDURE to NODE.
PROCEDURE is a form matching the following pattern:
(:activation-nodes (ACTIVATION-NODE-RULES ...))
:selector SELECTOR-RULES)
Where ACTIVATION-NODE-RULES is a list of activation nodes, each
of which is a form matching the following pattern:
(:nodes RULES
[:position POSITION-RULE]
[:has-parent HAS-PARENT-RULE]
[:has-fields FIELDS]
[:has-ancestor HAS-ANCESTOR-RULE])
Where RULES is one or more rules outlined in
`combobulate-procedure-expand-rules', and POSITION-RULE is one
of:
`any', meaning point is anywhere in the node, and is the default;
`in', that it is *not* at the beginning;
and `at', that it must be at the exact beginning of the node.
HAS-PARENT-RULE and HAS-ANCESTOR-RULE are optional, though at
most one can be used in an activation node rule. They each take a
list of RULES.
HAS-PARENT-RULE checks if the immediate parent of the action node
matches the rules, while HAS-ANCESTOR-RULE checks if any ancestor
of the action node matches the rules.
HAS-FIELD-RULE is a list of fields the action node be considered
to be inside of.
SELECTOR-RULES is a form matching the following pattern:
(:choose <CHOICE>
<MATCHER PROPERTY>)
Where <MATCHER PROPERTY> is one of:
:match-query <QUERY-MATCHER>
:match-children <NODE-MATCHER>
:match-siblings <NODE-MATCHER>
And CHOICE is either `node' or `parent' (the default), indicating whether the
selector should operate on the action node or its matching
parent.
NODE-MATCHER must be either `t', indicating all node types (but
not anonymous nodes); or a form of the following pattern:
(:match-rules <RULES|t>
:discard-rules <RULES|t>
[:anonymous <nil|t>]
[:default-mark <@match|@discard>])
Only one of `:match-rules' or `:discard-rules' can be used in
NODE-MATCHER. `:anonymous' is a boolean and defaults to nil, and
`:default-mark' is a symbol and defaults to
`@match'. `:default-mark' is the tie-breaker when a node is not
matched by `:match-rules' or `:discard-rules'.
QUERY-MATCHER must be of the form:
(:query <QUERY
[:engine <combobulate|treesitter>]
[:discard-rules <RULES>])
Note that QUERY can be either Combobulate's internal query
language to non-recursively match against NODE, or a regular
tree-sitter query that recursively matches against NODE and any
children of NODE. The `:engine' flag determines which, and it
defaults to `combobulate'. `:discard-rules' is a list of rules
(or `t' indicating match everything, but not anonymous nodes)."
(combobulate-procedure-validate procedure)
(map-let (:activation-nodes :selector)
procedure
(when-let (procedure-result (combobulate-procedure-apply-activation-nodes
activation-nodes node))
(cl-assert (and (combobulate-procedure-result-p procedure-result)
(combobulate-procedure-result-matched-activation procedure-result))
nil "Expected `combobulate-procedure-apply-activation-nodes' to return a
procedure result with a matched activation node")
(if selector
(map-let (:choose :match-query :match-children :match-siblings) selector
;; use `:choose' to determine whether to operate on the
;; action node or its parent
(when-let ((chosen-node
(cond
((equal choose 'node)
(combobulate-procedure-result-action-node procedure-result))
((or (equal choose 'parent) (null choose))
(combobulate-procedure-result-parent-node procedure-result))
(t (error "Unknown `:choose' specifier `%s'" choose)))))
(setf
;; store the result of the selector filter in the procedure result
(combobulate-procedure-result-selected-nodes procedure-result)
(ensure-list
(cond
(match-query
(combobulate-procedure--filter-nodes-by-query match-query chosen-node))
((or match-siblings match-children)
(combobulate-procedure--filter-nodes-by-relationship
(or match-children match-siblings)
chosen-node
(if match-siblings
#'combobulate-linear-siblings
#'combobulate-node-children)))
(t (error "Invalid selector: %s" selector))))
;; acknowledge that the selector filter was used
(combobulate-procedure-result-matched-selection procedure-result) t)))
;; if there is no selector, then the action node is the selected node
(setf (combobulate-procedure-result-matched-selection procedure-result) 'n/a))
;; do a final bit of clean-up: get all the nodes marked `@match'
;; and also put them in the `matched-nodes' slot and then remove
;; the mark.
(setf (combobulate-procedure-result-matched-nodes procedure-result)
(combobulate-procedure--filter-marked-nodes
(combobulate-procedure-result-selected-nodes procedure-result) t nil))
procedure-result)))