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

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

(defun syd-haskell-open-repl ()
  "Open a Haskell REPL."
  (interactive)
  (require 'inf-haskell)
  (run-haskell))

(defun syd-haskell-evil-open-above ()
  "Opens a line above the current, following Haskell-mode's indentation"
  (interactive)
  (evil-beginning-of-line)
  (haskell-indentation-newline-and-indent)
  (evil-previous-line)
  (haskell-indentation-indent-line)
  (evil-append-line nil))

(defun syd-haskell-evil-open-below ()
  "Opens a line below the current, following Haskell-mode's indentation"
  (interactive)
  (evil-append-line nil)
  (haskell-indentation-newline-and-indent))

(defun syd-haskell-hoogle-start-server ()
  (interactive)
  (haskell-hoogle-start-server)
  (message "Hoogle started on localhost:%d" haskell-hoogle-port-number))

(use-package haskell-mode
  :mode (("\\.l?hs'" . haskell-literate-mode)
         ("\\.hs'" . haskell-mode))
  :custom (; Show errors in REPL, not popup buffers.
           (haskell-interactive-popup-errors nil)
           (haskell-process-suggest-remove-import-line t)
           (haskell-process-auto-import-loaded-modules t))
  :general
  ;; DEPRECATED: Remove once a `map!' equivalent is implemented.
  (:keymaps 'haskell-mode-map
   :states '(normal visual motion emacs insert)
   :major-modes t
   :prefix syd-localleader-key
   :non-normal-prefix syd-alt-localleader-key
   "c" #'haskell-cabal-visit-file
   "h s" #'syd-haskell-hoogle-start-server
   "h q" #'haskell-hoogle-kill-server)
  (:keymaps 'interactive-haskell-mode-map
   :states '(normal insert)
   "C-j" #'haskell-interactive-mode-history-next
   "C-k" #'haskell-interactive-mode-history-previous)
  (:keymaps 'haskell-mode-map
   :states 'normal
   [remap evil-open-above] #'syd-haskell-evil-open-above
   [remap evil-open-below] #'syd-haskell-evil-open-below)
  :config
  (set-repl-handler! '(haskell-mode haskell-cabal-mode literate-haskell-mode)
    #'syd-haskell-open-repl
    ;; Haskell-mode provides IDE features by communicating with a persistent
    ;; REPL process à la Lisp.
    :persist t)
  (add-to-list 'completion-ignored-extensions ".hi")
  
  ;; Don't kill REPL popup on ESC/C-g
  (set-popup-rule! "^\\*haskell\\*" :quit nil)
  (syd-add-hook 'haskell-mode-local-vars-hook
    ;; Folding of Haskell sections.
    #'haskell-collapse-mode
    #'interactive-haskell-mode)
  (dolist (c '(?' ?_))
    (modify-syntax-entry c "w" haskell-mode-syntax-table)))

(use-package lsp-haskell
  :defer t
  :init
  (add-hook 'haskell-mode-hook #'lsp 'append)
  (add-hook 'haskell-literate-mode-hook #'lsp 'append))

(provide 'syd-lang-haskell)
