;; syd-strategies.el -*- lexical-binding: t; -*-

(require 'syd-text)

(comment
 "For demonstration:"
 (setq syd-strat--strategies
       '((:documentation syd-emacs-lisp-lookup-documentation)
         (:definition evil-goto-definition))))

;; :documentation : Identifier -> Marker
(defvar-local syd-strat--strategies nil)

(defun syd-strat-try-functions-wrapped (wrapper fns &rest args)
  "For each FN in FNS, call WRAPPER with the arguments FN followed by ARGS,
until a FN returns non-nil."
  (cl-loop for fn in fns
           with r = nil
           do (setq r (apply wrapper fn args))
           until r
           finally return r))

(defun syd-strat--set-strategies (category strategies)
  (cl-loop for ref in-ref syd-strat--strategies
           until (eq category (car ref))
           finally do (pp ref)))

(defun syd-set-strategies (modes &rest args)
  (dolist (mode (ensure-list modes))
    (let ((hook (intern (format "%s-hook" mode)))
          (fn-name (intern (format "syd-strat--init-for-%s-h" mode))))
      (unless (cl-evenp (length args))
        (signal 'wrong-number-of-arguments args))
      ;; We use this `defalias' incantation instead of a raw `fset' because the
      ;; former will properly associate a source location to the definition.
      (defalias fn-name
        (function
         (lambda ()
           (cl-loop for (category strategies) on args by (lambda (x) (-drop 2 x))
                    do (syd-strat--set-strategies category strategies)))))
      (add-hook hook fn-name))))

(provide 'syd-strategies)
