feat(emacs): haskell-ts-mode

This commit is contained in:
2026-09-02 07:55:33 -06:00
parent 28cc8474cd
commit cffe715e30
5 changed files with 110 additions and 11 deletions
+14 -2
View File
@@ -12,8 +12,20 @@ in {
builtins.readFile ./haskell/ghc-with-packages.sh;
home.file.".ghc/ghci.conf".text = ''
:set prompt "\x1b[38;5;5mλ>\x1b[0m "
:set prompt-cont "\x1b[38;5;5m|>\x1b[0m "
:{
ghci_set_prompt :: IO String
ghci_set_prompt = do
term <- System.Environment.Blank.getEnvDefault "TERM" ""
let (prompt,promptCont) =
if Data.List.isPrefixOf "xterm-" term
then ("\x1b[38;5;5mλ>\x1b[0m ", "\x1b[38;5;5m|>\x1b[0m ")
else ("λ> ", "|> ")
pure . unlines $
[ ":set prompt " ++ show prompt
, ":set prompt-cont " ++ show promptCont
]
:}
:cmd ghci_set_prompt
:set -interactive-print=Text.Pretty.Simple.pPrint
:m + Text.Show.Functions
:unset +r
@@ -18,7 +18,8 @@
:states '(normal insert)
"C-k" #'comint-previous-input
"C-j" #'comint-next-input
"C-s" #'consult-history)
"C-s" #'consult-history
"<return>" #'comint-send-input)
(general-def
:keymaps 'comint-mode-map
:states 'insert
@@ -9,6 +9,18 @@
(require 'inf-haskell)
(run-haskell))
(defun syd-haskell-ts-open-repl ()
"Open a Haskell REPL."
(interactive)
(haskell-ts-run)
(pop-to-buffer haskell-ts-ghci-buffer-name))
(defun syd-haskell-ts-eval-region (beg end)
(haskell-ts--send-region beg end))
(defun syd-haskell-ts-load-buffer ()
(haskell-ts-load-file))
(defun syd-haskell-evil-open-above ()
"Opens a line above the current, following Haskell-mode's indentation"
(interactive)
@@ -38,7 +50,9 @@
: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))
(haskell-process-auto-import-loaded-modules t)
(haskell-ts-inferior-history-file
(file-name-concat syd-data-dir "haskell-ts-inferior-history")))
:general
(:keymaps 'haskell-mode-map
:states '(normal visual motion emacs insert)
@@ -62,13 +76,56 @@
(add-to-list 'haskell-font-lock-quasi-quote-modes '("wats" . wat-mode))
(add-to-list 'haskell-font-lock-quasi-quote-modes '("expr" . wat-mode)))
(use-package consult-hoogle
:config
(syd-push shackle-rules
`("*hoogle-search*"
:select t :size 0.5 :popup t :align bottom)))
(use-package haskell-ts-mode
:straight (:type git
:host github
:repo "dschrempf/haskell-ts-mode")
:custom ((haskell-ts-font-lock-level 4)
(haskell-ts-ghci "ghci")
(haskell-ts-inferior-prompt-regexp
(rx bol (or "λ> " "|> "))))
:general
(:keymaps 'haskell-ts-mode-map
:states '(normal motion)
:major-modes t
:prefix syd-localleader-key
:non-normal-prefix syd-alt-localleader-key
"h s" #'syd-haskell-hoogle-start-server
"h q" #'haskell-hoogle-kill-server
"c" #'haskell-cabal-visit-file)
:config
(add-to-list 'completion-ignored-extensions ".hi")
(syd-add-hook 'haskell-ts-mode-hook
(defun syd-haskell-configure-indent-h ()
(setq-local tab-width 2)
;; (setq-local indent-line-function #'tab-to-tab-stop)
(indent-tabs-mode -1))
(defun syd-haskell-configure-evil-h ()
(setq-local evil-symbol-word-search nil)))
(syd-handle '(haskell-ts-mode)
:repl #'syd-haskell-ts-open-repl
:eval-region #'syd-haskell-ts-eval-region
:load-buffer #'syd-haskell-ts-load-buffer)
(syd-defadvice syd-haskell-hide-repl-h (old &rest rs)
:around #'haskell-ts-show-repl
(save-window-excursion
(apply old rs))))
(use-package lsp-haskell
:defer t
:custom ((lsp-haskell-server-path "haskell-language-server"))
:init
(add-hook 'haskell-mode-hook #'lsp-deferred 'append)
(add-hook 'haskell-literate-mode-hook #'lsp-deferred 'append)
(syd-add-hook '(haskell-mode-hook haskell-literate-mode-hook)
(add-hook 'haskell-ts-mode-hook #'lsp-deferred 'append)
(syd-add-hook '(haskell-ts-mode-hook
haskell-mode-hook haskell-literate-mode-hook)
(defun syd-haskell-configure-lsp-h ()
;; it often highlights list literals and quasiquotes which
;; gets reaaaally annoying.
@@ -1,7 +1,11 @@
;;; -*- lexical-binding: t -*-
(require 'syd/base)
;; Disable tabs by default.
;; Tabs, not spaces.
(setq-default indent-tabs-mode nil)
(setq-default tab-width 2)
(use-package kakapo-mode
:hook ((prog-mode . kakapo-mode)))
(provide 'syd/tabs)
+30 -5
View File
@@ -6,9 +6,34 @@ in {
enable = lib.mkEnableOption "Treesitter grammars";
};
config = lib.mkIf cfg.enable {
sydnix.emacs.emacsPackages = epkgs: [
epkgs.treesit-grammars.with-all-grammars
];
};
config = lib.mkIf cfg.enable
# https://github.com/dschrempf/haskell-ts-mode/blob/1c236f00dc214e546124a5dac90902ba62500c15/flake.nix#L40-L55
(let
grammars = pkgs.tree-sitter-grammars.overrideScope (ts-final: ts-prev: {
tree-sitter-haskell = ts-prev.tree-sitter-haskell.overrideAttrs (prev:
let rev = "1ad6077a1fb776c255836e00aeb6da57ba564b6a";
in {
version = "unstable-2026-07-07-${builtins.substring 0 7 rev}";
src = pkgs.fetchFromGitHub {
owner = "dschrempf";
repo = "tree-sitter-haskell";
inherit rev;
hash = "sha256-kC6HwImFRx5HUY7NDLAA0I/DaSstQ94dWxA9+lMx2gI=";
};
nativeBuildInputs = (prev.nativeBuildInputs or [ ]) ++ [
pkgs.nodejs
pkgs.tree-sitter
];
preBuild = ''
tree-sitter generate
'';
});
});
in {
sydnix.emacs.emacsPackages = epkgs: [
(epkgs.treesit-grammars.with-grammars (_ps:
grammars.allGrammars
))
];
});
}