;;; syd-lang-nix.el -*- lexical-binding: t; -*-

(require 'syd-handle-repl)
(require 'syd-handle-lookup)

(defun syd-nix-open-nix-repl ()
  (interactive)
  ;; If possible, cd to the project root.  Flakes force you to use relative
  ;; paths, which can be annoying in combination with
  ;;
  ;; REVIEW: Should this be something handled by `syd--call-repl-handler'?
  (-some-> (syd-project-root) cd)
  (nix-repl)
  (current-buffer))

(evil-define-text-object syd-nix-obj-outer-binding (count _beg _end _type)
  "TODO"
  :type 'inclusive
  (let* ((cleanup-p (memq evil-this-operator '(evil-delete)))
         (node (treesit-thing-at-point "binding" "nested")))
    (list (treesit-node-start node)
          (treesit-node-end node))))

(use-package nix-mode
  ;; :mode "\\.nix\\'"
  :init
  (add-to-list 'auto-mode-alist
               (cons (rx "/flake.lock'")
                     (if (fboundp 'json-mode)
                         'json-mode
                       'js-mode)))
  :config
  (add-hook 'nix-mode-hook #'lsp)
  (set-popup-rule! (rx bol "*nixos-options-doc*" eol) :ttl 0 :quit t)
  (set-repl-handler! '(nix-mode nix-ts-mode) #'syd-nix-open-nix-repl)
  (dolist (c '(?- ?_))
    (modify-syntax-entry c "w" nix-mode-syntax-table))
  
  ;; Inform Smartparens and Evil-surround of Nix's alternative string syntax.
  (with-eval-after-load 'smartparens
    (sp-local-pair '(nix-mode nix-ts-mode) "''" "''"))
  (syd-add-hook '(nix-mode-hook nix-ts-mode-hook)
    (defun syd-nix--configure-evil-surround-h ()
      (with-eval-after-load 'evil-surround
        (push '(?Q . ("''" . "''"))
              evil-surround-pairs-alist)))))

(use-package nix-ts-mode
  :mode "\\.nix\\'"
  :config
  (require 'nix-mode)
  (general-def
    :keymaps 'nix-ts-mode-map
    :states '(visual operator)
    "ad" #'syd-nix-obj-outer-binding)
  (syd-add-hook 'nix-ts-mode-hook
    (defun syd-nix-set-syntax-table-h ()
      "Set the syntax table in `nix-ts-mode' buffers to `nix-mode-syntax-table'."
      (set-syntax-table nix-mode-syntax-table))))

(provide 'syd-lang-nix)
