;;;  -*- lexical-binding: t; -*-

(require 'syd/base)

;; Smartparens, most importantly to me, automatically closes opened delimiters.
;; It additionally offers a lot of Paredit-like functionality, but we do not yet
;; use any of it.
;; FIXME: If the first buffer visited is the eval minibuffer, smartparens is not
;; activated.
(use-package smartparens
  :hook (on-first-buffer . smartparens-global-mode)
  :commands (sp-pair sp-local-pair sp-with-modes
		     sp-point-in-comment sp-point-in-string)
  :custom
  ;; Overlays are too distracting and not terribly helpful. show-parens does
  ;; this for us already (and is faster), so...
  ((sp-highlight-pair-overlay nil)
   (sp-highlight-wrap-overlay nil)
   (sp-highlight-wrap-tag-overlay nil)

   ;; The default is 100. because smartparen's scans are relatively expensive
   ;; (especially with large pair lists for some modes), we reduce it, as a
   ;; better compromise between performance and accuracy.
   (sp-max-prefix-length 25)

   ;; No pair has any business being longer than 4 characters; if they must, set
   ;; it buffer-locally. It's less work for smartparens.
   (sp-max-pair-length 4))
  :config
  ;; Load default config.
  (require 'smartparens-config)
  ;; Silence some harmless but annoying echo-area spam
  (dolist (key '(:unmatched-expression :no-matching-tag))
    (setf (alist-get key sp-message-alist) nil))

  (syd-add-hook 'eval-expression-minibuffer-setup-hook
    (defun syd-init-smartparens-in-eval-expression-h ()
      "Enable `smartparens-mode' in the minibuffer for `eval-expression'. This
includes everything that calls `read--expression', e.g. `edebug-eval-expression'
It is only enabled it if `smartparens-global-mode' is on."
      (when smartparens-global-mode
        (smartparens-mode 1))))

  (syd-add-hook 'minibuffer-setup-hook
    (defun syd-init-smartparens-in-minibuffer-maybe-h ()
      "Enable `smartparens' for non-`eval-expression' commands. Only enable
`smartparens-mode' if `smartparens-global-mode' is on."
      (when (and smartparens-global-mode (memq this-command '(evil-ex)))
        (smartparens-mode 1))))

  ;; You're likely writing lisp in the minibuffer, therefore, disable these
  ;; quote pairs, which lisps doesn't use for strings:
  (sp-local-pair
   '(minibuffer-mode minibuffer-inactive-mode) "'" nil :actions nil)
  (sp-local-pair
   '(minibuffer-mode minibuffer-inactive-mode) "`" nil :actions nil)
  (dolist (pair '(("⟨" . "⟩")
                  ("⟪" . "⟫")
                  ("⟅" . "⟆")))
    (sp-pair (car pair) (cdr pair)))

  (sp-with-modes '(js-mode nix-mode)
    (sp-local-pair "{" nil :post-handlers '(("||\n[i]" "RET")))
    (sp-local-pair "[" nil :post-handlers '(("||\n[i]" "RET")))))

(provide 'syd/smartparens)
