feat(emacs): Haskell
This commit is contained in:
@@ -51,11 +51,13 @@
|
|||||||
#'cider-eval-region))
|
#'cider-eval-region))
|
||||||
:custom ((cider-show-error-buffer nil))
|
:custom ((cider-show-error-buffer nil))
|
||||||
:general
|
:general
|
||||||
|
;; DEPRECATED: Remove once a `map!' equivalent is implemented.
|
||||||
(:keymaps 'cider-repl-mode-map
|
(:keymaps 'cider-repl-mode-map
|
||||||
:states '(normal insert)
|
:states '(normal insert)
|
||||||
"C-k" #'cider-repl-backward-input
|
"C-k" #'cider-repl-backward-input
|
||||||
"C-j" #'cider-repl-forward-input
|
"C-j" #'cider-repl-forward-input
|
||||||
"C-s" #'cider-repl-previous-matching-input)
|
"C-s" #'cider-repl-previous-matching-input)
|
||||||
|
;; DEPRECATED: Remove once a `map!' equivalent is implemented.
|
||||||
(:keymaps 'clojure-mode-map
|
(:keymaps 'clojure-mode-map
|
||||||
:states '(normal visual motion emacs insert)
|
:states '(normal visual motion emacs insert)
|
||||||
:major-modes t
|
:major-modes t
|
||||||
|
|||||||
69
users/crumb/programs/emacs/modules/lang/syd-lang-haskell.el
Normal file
69
users/crumb/programs/emacs/modules/lang/syd-lang-haskell.el
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
;;; 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))
|
||||||
|
|
||||||
|
(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" #'haskell-hoogle-start-server
|
||||||
|
"h q" #'haskell-hoogle-kill-server)
|
||||||
|
(general-def :keymaps 'interactive-haskell-mode-map
|
||||||
|
:states '(normal insert)
|
||||||
|
"C-j" #'haskell-interactive-mode-history-next
|
||||||
|
"C-k" #'haskell-interactive-mode-history-previous)
|
||||||
|
: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))
|
||||||
|
|
||||||
|
(use-package lsp-haskell
|
||||||
|
:defer t
|
||||||
|
:init
|
||||||
|
(add-hook 'haskell-mode-local-vars-hook #'lsp 'append)
|
||||||
|
(add-hook 'haskell-literate-mode-local-vars-hook #'lsp 'append))
|
||||||
|
|
||||||
|
(provide 'syd-lang-haskell)
|
||||||
@@ -4,5 +4,6 @@
|
|||||||
(require 'syd-lang-emacs-lisp)
|
(require 'syd-lang-emacs-lisp)
|
||||||
(require 'syd-lang-clojure)
|
(require 'syd-lang-clojure)
|
||||||
(require 'syd-lang-nix)
|
(require 'syd-lang-nix)
|
||||||
|
(require 'syd-lang-haskell)
|
||||||
|
|
||||||
(provide 'syd-lang)
|
(provide 'syd-lang)
|
||||||
|
|||||||
@@ -79,6 +79,9 @@
|
|||||||
;; REVIEW: Is it safe to make this be async? We require that the command
|
;; REVIEW: Is it safe to make this be async? We require that the command
|
||||||
;; has finished before Git initialises.
|
;; has finished before Git initialises.
|
||||||
(skeletor-shell-command "nix run github:jlesquembre/clj-nix#deps-lock"
|
(skeletor-shell-command "nix run github:jlesquembre/clj-nix#deps-lock"
|
||||||
dir))))
|
dir)))
|
||||||
|
(skeletor-define-template "haskell-flake"
|
||||||
|
:title "Haskell (Flake)"
|
||||||
|
:license-file-name "LICENSE"))
|
||||||
|
|
||||||
(provide 'syd-projects)
|
(provide 'syd-projects)
|
||||||
|
|||||||
@@ -1,5 +1,17 @@
|
|||||||
;;; syd-tooling.el -*- lexical-binding: t; -*-
|
;;; syd-tooling.el -*- lexical-binding: t; -*-
|
||||||
|
|
||||||
|
(defun syd-lsp-lookup-documentation ()
|
||||||
|
(interactive)
|
||||||
|
(when-let* ((buf (get-buffer "*lsp-help*")))
|
||||||
|
(kill-buffer buf))
|
||||||
|
(call-interactively #'lsp-describe-thing-at-point)
|
||||||
|
(let ((buf (get-buffer "*lsp-help*")))
|
||||||
|
(when (get-buffer-window-list buf)
|
||||||
|
;; Bury the buffer so the popup system has full control over how it's
|
||||||
|
;; selected.
|
||||||
|
(bury-buffer buf)
|
||||||
|
buf)))
|
||||||
|
|
||||||
(use-package lsp-mode
|
(use-package lsp-mode
|
||||||
:init
|
:init
|
||||||
;; We'll bind things ourselves.
|
;; We'll bind things ourselves.
|
||||||
@@ -25,7 +37,13 @@
|
|||||||
(user-error (concat "Ignoring a call to `lsp-install-server'"
|
(user-error (concat "Ignoring a call to `lsp-install-server'"
|
||||||
" — tell the caller to use Nix!")))
|
" — tell the caller to use Nix!")))
|
||||||
(set-popup-rule! (rx line-start "*lsp-" (or "help" "install"))
|
(set-popup-rule! (rx line-start "*lsp-" (or "help" "install"))
|
||||||
:size 0.35 :quit t :select nil))
|
:size 13 :quit t :select nil)
|
||||||
|
|
||||||
|
;; DEPRECATED: Remove once syd-strategies is working.
|
||||||
|
(syd-add-hook 'lsp-mode
|
||||||
|
(defun syd-lsp-set-handlers-h ()
|
||||||
|
(setq-local syd-lookup-documentation-handlers
|
||||||
|
(list #'syd-lsp-lookup-documentation)))))
|
||||||
|
|
||||||
(use-package envrc
|
(use-package envrc
|
||||||
;; REVIEW: Can we load this any later/better?
|
;; REVIEW: Can we load this any later/better?
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
use flake
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
cabal-version: 3.0
|
||||||
|
name: __PROJECT-NAME__
|
||||||
|
version: 0.1.0.0
|
||||||
|
synopsis: __DESCRIPTION__
|
||||||
|
description: __DESCRIPTION__
|
||||||
|
license: GPL-3.0-only
|
||||||
|
license-file: LICENSE
|
||||||
|
author: __USER-NAME__
|
||||||
|
maintainer: __USER-MAIL-ADDRESS__
|
||||||
|
|
||||||
|
-- copyright:
|
||||||
|
category: Language
|
||||||
|
build-type: Simple
|
||||||
|
extra-doc-files:
|
||||||
|
|
||||||
|
common common
|
||||||
|
ghc-options: -Wno-typed-holes -fdefer-typed-holes
|
||||||
|
|
||||||
|
default-extensions:
|
||||||
|
BlockArguments
|
||||||
|
DataKinds
|
||||||
|
DeriveDataTypeable
|
||||||
|
DeriveGeneric
|
||||||
|
DeriveTraversable
|
||||||
|
DerivingVia
|
||||||
|
FlexibleContexts
|
||||||
|
GADTs
|
||||||
|
GeneralisedNewtypeDeriving
|
||||||
|
LambdaCase
|
||||||
|
MultiWayIf
|
||||||
|
NoFieldSelectors
|
||||||
|
OverloadedLabels
|
||||||
|
OverloadedRecordDot
|
||||||
|
OverloadedStrings
|
||||||
|
PartialTypeSignatures
|
||||||
|
PatternSynonyms
|
||||||
|
StandaloneDeriving
|
||||||
|
TypeApplications
|
||||||
|
TypeFamilies
|
||||||
|
|
||||||
|
default-language: GHC2021
|
||||||
|
|
||||||
|
library
|
||||||
|
import: common
|
||||||
|
|
||||||
|
-- cabal-fmt: expand sydml/src/ -Main
|
||||||
|
exposed-modules:
|
||||||
|
|
||||||
|
default-language: GHC2021
|
||||||
|
|
||||||
|
build-depends:
|
||||||
|
, base ^>=4.19.1.0
|
||||||
|
, containers
|
||||||
|
, hashable
|
||||||
|
, mtl
|
||||||
|
, lens
|
||||||
|
, pretty-simple
|
||||||
|
, text >=2.0 && <2.2
|
||||||
|
, transformers
|
||||||
|
, unordered-containers
|
||||||
|
|
||||||
|
hs-source-dirs: src
|
||||||
|
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
{
|
||||||
|
inputs = {
|
||||||
|
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
|
||||||
|
flake-utils.url = "github:numtide/flake-utils";
|
||||||
|
};
|
||||||
|
|
||||||
|
outputs = { self, nixpkgs, ... }@inputs:
|
||||||
|
inputs.flake-utils.lib.eachDefaultSystem (system:
|
||||||
|
let
|
||||||
|
pkgs = import nixpkgs { inherit system; };
|
||||||
|
hlib = pkgs.haskell.lib.compose;
|
||||||
|
hpkgs = pkgs.haskell.packages.ghc98.extend (final: prev: {
|
||||||
|
__PROJECT-NAME__ =
|
||||||
|
hlib.dontCheck (final.callCabal2nix "__PROJECT-NAME__" ./. {});
|
||||||
|
});
|
||||||
|
in {
|
||||||
|
packages = rec {
|
||||||
|
__PROJECT-NAME__ = hpkgs.__PROJECT-NAME__;
|
||||||
|
default = __PROJECT-NAME__;
|
||||||
|
};
|
||||||
|
|
||||||
|
devShells.default = hpkgs.shellFor {
|
||||||
|
packages = p: [
|
||||||
|
p.__PROJECT-NAME__
|
||||||
|
];
|
||||||
|
nativeBuildInputs = [
|
||||||
|
hpkgs.cabal-fmt
|
||||||
|
hpkgs.fourmolu
|
||||||
|
hpkgs.haskell-language-server
|
||||||
|
hpkgs.cabal-install
|
||||||
|
hpkgs.hasktags
|
||||||
|
];
|
||||||
|
withHoogle = true;
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
{ config, lib, pkgs, ... }:
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
let
|
let
|
||||||
|
# TODO: Move somewhere else.
|
||||||
my-email = "lomiskiam@gmail.com";
|
my-email = "lomiskiam@gmail.com";
|
||||||
my-name = "Madeleine Sydney";
|
my-name = "Madeleine Sydney";
|
||||||
in lib.mkMerge [
|
in lib.mkMerge [
|
||||||
|
|||||||
46
users/crumb/programs/haskell.nix
Normal file
46
users/crumb/programs/haskell.nix
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
# Convenient shorthand for quickly opening Haskell REPLs.
|
||||||
|
programs.bash.profileExtra = ''
|
||||||
|
# Start a GHCi REPL with the given packages made available.
|
||||||
|
ghci-with-packages () {
|
||||||
|
nix-shell -p "haskellPackages.ghcWithPackages (p: with p; [ $@ ])" \
|
||||||
|
--run ghci
|
||||||
|
}
|
||||||
|
|
||||||
|
# Run GHC with the given packages made available.
|
||||||
|
ghc-with-packages () {
|
||||||
|
getopt -o "p" -- "$@"
|
||||||
|
while true; do
|
||||||
|
case "$1" in
|
||||||
|
-p)
|
||||||
|
packages="$1"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
--)
|
||||||
|
shift
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "Invalid options provided"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
eval set -- "$options"
|
||||||
|
|
||||||
|
nix-shell -p "haskellPackages.ghcWithPackages (p: with p; [ $packages ])" \
|
||||||
|
--run "ghc $@"
|
||||||
|
}
|
||||||
|
'';
|
||||||
|
|
||||||
|
# Some global Cabal configuration.
|
||||||
|
xdg.configFile.".cabal/config".text = ''
|
||||||
|
-- Globally-enable Nix integration. See
|
||||||
|
-- https://cabal.readthedocs.io/en/3.4/nix-integration.html
|
||||||
|
nix: True
|
||||||
|
'';
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user