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)))