#+TITLE: Haskell contribution layer for Spacemacs [[file:img/haskell.png]] * Table of Contents :TOC@4: - [[#description][Description]] - [[#features][Features:]] - [[#install][Install]] - [[#layer][Layer]] - [[#dependencies][Dependencies]] - [[#setup-path][Setup PATH]] - [[#os-x][OS X]] - [[#optional-extras][Optional extras]] - [[#ghc-mod-support][ghc-mod support]] - [[#ghci-ng-support][GHCi-ng support]] - [[#structured-haskell-mode][structured-haskell-mode]] - [[#hindent][hindent]] - [[#key-bindings][Key bindings]] - [[#documentation][Documentation]] - [[#debug][Debug]] - [[#repl][REPL]] - [[#cabal-commands][Cabal commands]] - [[#cabal-files][Cabal files]] - [[#faq][FAQ]] - [[#repl-doesnt-work][REPL doesn't work.]] - [[#i-am-using-stack-and-ghc-mod-but-ghc-mod-doesnt-work][I am using =stack= and =ghc-mod=, but =ghc-mod= doesn't work.]] - [[#repl-is-stuck][REPL is stuck.]] * Description This layer adds support for the [[https://www.haskell.org/][Haskell]] language. ** Features: - auto-completion with [[https://github.com/iquiw/company-ghc][company-ghc]], - syntax highlighting for [[https://github.com/bgamari/cmm-mode][C-- source]]. *This layer is in construction, it needs your contributions and bug reports.* * Install ** Layer To use this contribution add it to your =~/.spacemacs= #+BEGIN_SRC emacs-lisp (setq-default dotspacemacs-configuration-layers '(haskell)) #+END_SRC ** Dependencies This layer requires some [[https://www.haskell.org/cabal/][cabal]] packages: - =hlint= - =stylish-haskell= - =hasktags= You can install them using =cabal= or =stack=. =Cabal= users should use following command: #+BEGIN_SRC sh $ cabal install stylish-haskell hlint hasktags #+END_SRC =Stack= users should use following command: #+BEGIN_SRC sh $ stack install stylish-haskell hlint hasktags #+END_SRC ** Setup PATH Make sure that your =$PATH= contains installation path for =cabal= packages. If you are using =cabal= it should be =~/.cabal/bin= or =/Users//Library/Haskell/bin= (for Haskell for Mac users). If you are using =stack= then it should be =~/.local/bin=. So if this path is not in =$PATH=, just add it and Spacemacs will automatically pick up shell =$PATH=. _Alternatively_, you can add it to the Emacs =exec-path= variable in the =dotspacemacs/user-config= function of your =.spacemacs= file: #+BEGIN_SRC emacs-lisp (add-to-list 'exec-path "~/.cabal/bin/") #+END_SRC Or for =stack= users: #+BEGIN_SRC emacs-lisp (add-to-list 'exec-path "~/.local/bin/") #+END_SRC ** OS X Note that =emacs.app= for OS X does not pick up =$PATH= from =~/.bashrc= or =~/.zshrc= when launched from outside a terminal. ** Optional extras The Haskell layer supports some extra features that can be enabled through layer variables. *** ghc-mod support [[http://www.mew.org/~kazu/proj/ghc-mod/][ghc-mod]] enhances =haskell-mode= with for example templates, case-splitting and much more. In order to use it you need to install the executable with #+BEGIN_SRC sh $ cabal install ghc-mod #+END_SRC =Stack= users should use following command: #+BEGIN_SRC sh $ stack install ghc-mod --resolver nightly-2015-10-07 #+END_SRC and set the layer variable: #+BEGIN_SRC emacs-lisp (setq-default dotspacemacs-configuration-layers '((haskell :variables haskell-enable-ghc-mod-support t))) #+END_SRC =Stack= users also should make sure that =dist/setup-config= doesn't exist in the project root. As it will confuse =ghc-mod=. For more troubleshooting, checkout this [[https://github.com/kazu-yamamoto/ghc-mod/wiki#known-issues-related-to-stack][document]]. *** GHCi-ng support [[https://github.com/chrisdone/ghci-ng][ghci-ng]] adds some nice features to =haskell-mode=, and is supported in Spacemacs by a layer variable: Follow the instructions to install [[https://github.com/chrisdone/ghci-ng][ghci-ng]] (remember to add =:set +c= in =~/.ghci=, next set the layer variable: #+BEGIN_SRC emacs-lisp (setq-default dotspacemacs-configuration-layers '((haskell :variables haskell-enable-ghci-ng-support t))) #+END_SRC Once ghci-ng is enabled, two of the old keybindings are overriden with improved versions from ghci-ng, and a new keybinding available: | Key Binding | Description | |-------------+---------------------------------------------------------------------------| | ~SPC m h t~ | gets the type of the identifier under the cursor or for the active region | | ~SPC m g g~ | go to definition | | ~SPC m u~ | finds uses of identifier | *** structured-haskell-mode [[https://github.com/chrisdone/structured-haskell-mode][structured-haskell-mode]], or shm, replaces default haskell-mode auto-indentation and adds some nice functionalities. To Install =shm= with cabal run following command: #+BEGIN_SRC sh $ cabal install structured-haskell-mode #+END_SRC =Stack= users should use following command: #+BEGIN_SRC sh $ stack install structured-haskell-mode #+END_SRC To enable =shm= set the layer variable: #+BEGIN_SRC emacs-lisp (setq-default dotspacemacs-configuration-layers '((haskell :variables haskell-enable-shm-support t))) #+END_SRC After shm has been enabled, some of the evil normal state bindings are overridden: | Key Binding | Description | |-------------+---------------------| | ~D~ | =shm/kill-line= | | ~R~ | =shm/raise= | | ~P~ | =shm/yank= | | ~(~ | =shm/forward-node= | | ~)~ | =shm/backward-node= | For a nice visualization of these functions, please refer to the github page for [[https://github.com/chrisdone/structured-haskell-mode#features][structured-haskell-mode]]. *** hindent [[https://github.com/chrisdone/hindent][hindent]] is an extensible Haskell pretty printer, which let's you reformat your code. You need to install the executable with =cabal install hindent= or =stack install hindent= To enable it you have to set the variable =haskell-enable-hindent-style= to a supported style. The available styles are: - fundamental - johan-tibell - chris-done - gibiansky See examples [[https://github.com/chrisdone/hindent#example][here]] #+BEGIN_SRC emacs-lisp (setq-default dotspacemacs-configuration-layers '((haskell :variables haskell-enable-hindent-style "johan-tibell"))) #+END_SRC * Key bindings All Haskell specific bindings are prefixed with the major-mode leader ~SPC m~. Top-level commands are prefixed by ~SPC m~: | Key Binding | Description | |-------------+-----------------------------------------------| | ~SPC m g g~ | go to definition or tag | | ~SPC m f~ | format buffer using haskell-stylish | | ~SPC m F~ | format declaration using hindent (if enabled) | ** Documentation Documentation commands are prefixed by ~SPC m h~ | Key Binding | Description | |-------------+----------------------------------------------------------------------------| | ~SPC m h d~ | find or generate Haddock documentation for the identifier under the cursor | | ~SPC m h h~ | do a Hoogle lookup | | ~SPC m h H~ | do a local Hoogle lookup | | ~SPC m h i~ | gets information for the identifier under the cursor | | ~SPC m h t~ | gets the type of the identifier under the cursor | | ~SPC m h y~ | do a Hayoo lookup | ** Debug Debug commands are prefixed by ~SPC m d~: | Key Binding | Description | |-------------+--------------------------------------------| | ~SPC m d d~ | start debug process, needs to be run first | | ~SPC m d b~ | insert breakpoint at function | | ~SPC m d n~ | next breakpoint | | ~SPC m d N~ | previous breakpoint | | ~SPC m d B~ | delete breakpoint | | ~SPC m d c~ | continue current process | | ~SPC m d a~ | abandon current process | | ~SPC m d r~ | refresh process buffer | ** REPL REPL commands are prefixed by ~SPC m s~: | Key Binding | Description | |-------------+-------------------------------------------------| | ~SPC m s b~ | load or reload the current buffer into the REPL | | ~SPC m s c~ | clear the REPL | | ~SPC m s s~ | show the REPL | | ~SPC m s S~ | show and switch to the REPL | ** Cabal commands Cabal commands are prefixed by ~SPC m c~: | Key Binding | Description | |-------------+------------------------------------------------------------| | ~SPC m c a~ | cabal actions | | ~SPC m c b~ | build the current cabal project, i.e. invoke =cabal build= | | ~SPC m c c~ | compile the current project, i.e. invoke =ghc= | | ~SPC m c v~ | visit the cabal file | ** Cabal files This commands are available in a cabal file. | Key Binding | Description | |-------------+---------------------------------------------| | ~SPC m d~ | add a dependency to the project | | ~SPC m b~ | go to benchmark section | | ~SPC m e~ | go to executable section | | ~SPC m t~ | go to test-suite section | | ~SPC m m~ | go to exposed modules | | ~SPC m l~ | go to libary section | | ~SPC m n~ | go to next subsection | | ~SPC m p~ | go to previous subsection | | ~SPC m N~ | go to next section | | ~SPC m P~ | go to previous section | | ~SPC m f~ | find or create source-file under the cursor | * FAQ ** REPL doesn't work. Usually =haskell-mode= is great at figuring out which interactive process to bring up. But if you are experiencing problems with it you can help =haskell-mode= by setting =haskell-process-type= as in following code: #+BEGIN_SRC emacs-lisp (setq-default dotspacemacs-configuration-layers '((haskell :variables haskell-process-type 'stack-ghci))) #+END_SRC Available options are: - ghci - cabal-repl - cabal-dev - cabal-ghci - stack-ghci ** I am using =stack= and =ghc-mod=, but =ghc-mod= doesn't work. Make sure that =dist= directory doesn't exist in your project root. So if it exists, just remove it and try again. ** REPL is stuck. Make sure that when you are typing anything in REPL there is a space between what you type and =λ=. This problem usually happens when you switch from normal mode to edit mode.