17ee0e400b
After moving off of Meta, Dotfiles has a greater responsibility to manage configs. Vim, Tmux, and Emacs are now within Stow's purview.
2425 lines
82 KiB
Text
2425 lines
82 KiB
Text
This is haskell-mode.info, produced by makeinfo version 6.1 from
|
||
haskell-mode.texi.
|
||
|
||
This manual is for Haskell mode, version 16.1-git
|
||
|
||
Copyright © 2013-2017 Haskell Mode contributors.
|
||
|
||
Permission is granted to copy, distribute and/or modify this
|
||
document under the terms of the GNU Free Documentation License
|
||
(http://www.gnu.org/licenses/fdl.html), Version 1.3 or any later
|
||
version published by the Free Software Foundation; with no
|
||
Invariant Sections, no Front-Cover Texts and no Back-Cover Texts.
|
||
INFO-DIR-SECTION Emacs
|
||
START-INFO-DIR-ENTRY
|
||
* Haskell Mode: (haskell-mode). Haskell Development Environment for Emacs(en)
|
||
END-INFO-DIR-ENTRY
|
||
|
||
|
||
File: haskell-mode.info, Node: Top, Next: Introduction, Up: (dir)
|
||
|
||
Haskell Mode
|
||
************
|
||
|
||
Haskell Mode is an Haskell development Environment for GNU Emacs version
|
||
24.3 or later. It provides syntax-based indentation, font locking,
|
||
editing cabal files, and supports running an inferior Haskell
|
||
interpreter (e.g. GHCi).
|
||
|
||
* Menu:
|
||
|
||
* Introduction:: An introduction to Haskell Mode
|
||
* Installation:: How to get started
|
||
* Editing Haskell Code:: How to edit code
|
||
* Syntax highlighting:: Haskell Mode has colors
|
||
* Completion support:: Autocomplete
|
||
* Unicode support:: How to use Unicode
|
||
* Indentation:: Notes about indentation
|
||
* External indentation:: Other ways to indent code
|
||
* Autoformating:: Using external formatters
|
||
* Module templates:: Module templates
|
||
* Declaration scanning:: How to navigate in a source file
|
||
* Compilation:: How to compile
|
||
* Interactive Haskell:: How to interact with GHCi
|
||
* Editing Cabal files:: Cabal support
|
||
* Browsing Haddocks:: Using ‘w3m’ to browse documentation
|
||
* Spell checking strings and comments:: Using ‘flyspell-prog-mode’
|
||
* Aligning code:: Aligning code using ‘align-regexp’
|
||
* Rectangular commands:: Manage indentation manually
|
||
* REPL:: GHCi REPL
|
||
* Collapsing Haskell code:: View more code on screen
|
||
* Getting Help and Reporting Bugs:: How to improve Haskell Mode
|
||
* Concept index:: Index of Haskell Mode concepts
|
||
* Function index:: Index of commands
|
||
* Variable index:: Index of options and types
|
||
|
||
|
||
File: haskell-mode.info, Node: Introduction, Next: Installation, Prev: Top, Up: Top
|
||
|
||
1 Introduction
|
||
**************
|
||
|
||
“Haskell Mode” is a major mode providing a convenient environment for
|
||
editing Haskell (http://www.haskell.org) programs.
|
||
|
||
Some of its major features are:
|
||
|
||
• Syntax highlighting (font lock),
|
||
• automatic semi-intelligent indentation,
|
||
• on-the-fly documentation,
|
||
• interaction with inferior GHCi/Hugs instance,
|
||
• project building with cabal and stack
|
||
• scanning declarations and placing them in a menu.
|
||
|
||
The name Haskell Mode refers to the whole collection of modules in
|
||
this package. There is specifically a file ‘haskell-mode.el’ which
|
||
defines a major mode called ‘haskell-mode’. Generally, in this
|
||
documentation they will be distinguished by normal font and title case
|
||
(Haskell Mode) and code font (‘haskell-mode’).
|
||
|
||
1.1 History
|
||
===========
|
||
|
||
‘haskell-mode’ has a long history. It goes all the way back to 1992.
|
||
Since then, it has received many contributions in many forms. Some
|
||
design choices that remain in haskell-mode today are historical. Some
|
||
modules are outdated or no longer used, or are used by a few people.
|
||
|
||
Historically there hasn’t been a single individual or set of
|
||
individuals directing the package’s architecture for a long period of
|
||
time, rather, patches and new modules were accepted in liberally and we
|
||
are left with a box full of interesting toys that may or may not work.
|
||
|
||
As of 2016 Haskell Mode is coordinated using Github at
|
||
<https://github.com/haskell/haskell-mode>.
|
||
|
||
|
||
File: haskell-mode.info, Node: Installation, Next: Editing Haskell Code, Prev: Introduction, Up: Top
|
||
|
||
2 Installation
|
||
**************
|
||
|
||
Haskell Mode is distributed as a package in MELPA repository
|
||
(https://melpa.org). To use MELPA as Emacs package archive do the
|
||
following:
|
||
|
||
1. Customize ‘package-archives’ using
|
||
M-x customize-option RET package-archives
|
||
2. Use ‘INS’ to add new archive, use:
|
||
Archive name: melpa-stable
|
||
URL or directory name: http://stable.melpa.org/packages/
|
||
3. Fetch new packages using:
|
||
M-x package-refresh-contents
|
||
4. Install Haskell Mode using:
|
||
M-x package-install RET haskell-mode RET
|
||
|
||
Voila! ‘haskell-mode’ is installed! You should be able to edit
|
||
Haskell source code in color now.
|
||
|
||
The above steps should result in the following snippet in your
|
||
‘.emacs’:
|
||
|
||
(require 'package)
|
||
(custom-set-variables
|
||
;; custom-set-variables was added by Custom.
|
||
;; If you edit it by hand, you could mess it up, so be careful.
|
||
;; Your init file should contain only one such instance.
|
||
;; If there is more than one, they won't work right.
|
||
'(package-archives
|
||
(quote
|
||
(("gnu" . "http://elpa.gnu.org/packages/")
|
||
("melpa-stable" . "http://stable.melpa.org/packages/")))))
|
||
|
||
Haskell Mode supports GNU Emacs versions 24.3+, including 25
|
||
(snapshot).
|
||
|
||
Haskell Mode is available from melpa-stable (releases)
|
||
(http://stable.melpa.org) and melpa (git snapshots) (http://melpa.org).
|
||
|
||
Other means of obtaining ‘haskell-mode’ include el-get
|
||
(https://github.com/dimitri/el-get), Emacs Prelude
|
||
(https://github.com/bbatsov/prelude) and Debian package
|
||
(https://packages.debian.org/search?keywords=haskell-mode).
|
||
|
||
Last version of ‘haskell-mode’ that supported Emacs 23, 24.1, and
|
||
24.2 is ‘haskell-mode’ 13.16 available at
|
||
<https://github.com/haskell/haskell-mode/releases/tag/v13.16>.
|
||
|
||
2.1 Customizing
|
||
===============
|
||
|
||
Most of Haskell Mode’s settings are configurable via customizable
|
||
variables (*note (emacs)Easy Customization::, for details). You can use
|
||
‘M-x customize-group <RET> haskell’ to browse the ‘haskell’
|
||
customization sub-tree.
|
||
|
||
One of the important setting you should customize is the
|
||
‘haskell-mode-hook’ variable (*note (emacs)Hooks::) which gets run right
|
||
after the ‘haskell-mode’ major mode is initialized for a buffer. You
|
||
can customize ‘haskell-mode-hook’ by
|
||
|
||
M-x customize-variable RET haskell-mode-hook
|
||
|
||
There you can enable or disable a couple of predefined options or add
|
||
any function to the list.
|
||
|
||
|
||
File: haskell-mode.info, Node: Editing Haskell Code, Next: Syntax highlighting, Prev: Installation, Up: Top
|
||
|
||
3 Editing Haskell Code
|
||
**********************
|
||
|
||
Haskell Mode as one of its components provides a major mode for editing
|
||
Haskell source code called ‘haskell-mode’, which gave the name to the
|
||
whole project. There is a derived mode provided called
|
||
‘literate-haskell-mode’ that support Literate Haskell source code both
|
||
in Bird and in Latex forms.
|
||
|
||
Haskell Mode supports files with the following extensions:
|
||
|
||
‘.hs’
|
||
official file extension for Haskell files. Haskell Mode out of the
|
||
box supports most of GHC extensions.
|
||
‘.lhs’
|
||
official file extension for Literate Haskell files. Both Bird and
|
||
Latex styles are supported.
|
||
‘.hsc’
|
||
Haskell interfaces to C code used by hsc2hs
|
||
(http://www.haskell.org/ghc/docs/latest/html/users_guide/hsc2hs.html)
|
||
pre-processor.
|
||
‘.cpphs’
|
||
Haskell source with CPP pragmas used with cpphs
|
||
(http://projects.haskell.org/cpphs) pre-processor.
|
||
‘.c2hs’
|
||
Haskell FFI bindings to C libraries used with c2hs
|
||
(https://github.com/haskell/c2hs) pre-processor.
|
||
|
||
Haskell Mode offers many productivity tools described in following
|
||
chapters in this manual.
|
||
|
||
3.1 Managing imports
|
||
====================
|
||
|
||
There are a few functions for managing imports.
|
||
|
||
3.1.1 Jump to imports
|
||
---------------------
|
||
|
||
To jump to your import list, run
|
||
|
||
‘M-x’ ‘haskell-navigate-imports’
|
||
|
||
It’s nicer to have a keybinding to do this, for example:
|
||
|
||
(define-key haskell-mode-map (kbd "<f8>") 'haskell-navigate-imports)
|
||
|
||
You can hit it repeatedly to jump between groups of imports. It will
|
||
cycle.
|
||
|
||
3.1.2 Format imports
|
||
--------------------
|
||
|
||
To generally format (sort, align) your imports, you can run
|
||
|
||
‘M-x’ ‘haskell-mode-format-imports’
|
||
|
||
Or ‘C-c C-,’.
|
||
|
||
3.1.3 Sort imports
|
||
------------------
|
||
|
||
To just sort imports, jump to an import section and run
|
||
|
||
‘M-x’ ‘haskell-sort-imports’
|
||
|
||
3.1.4 Align imports
|
||
-------------------
|
||
|
||
To just align imports, jump to an import section and run
|
||
|
||
‘M-x’ ‘haskell-align-imports’
|
||
|
||
3.1.5 stylish-haskell
|
||
---------------------
|
||
|
||
As an alternative to the elisp functions described above, haskell-mode
|
||
can use the program stylish-haskell
|
||
(http://hackage.haskell.org/package/stylish-haskell) to format imports.
|
||
You can set this behavior by typing: ‘M-x’ ‘customize-variable’ ‘RET’
|
||
‘haskell-stylish-on-save’. You can install ‘stylish-haskell’ by running
|
||
‘stack install stylish-haskell’, or if you have not installed ‘stack’,
|
||
‘cabal install stylish-haskell’.
|
||
|
||
3.2 Haskell Tags
|
||
================
|
||
|
||
‘haskell-mode’ can generate tags when saving source files. To generate
|
||
tags ‘haskell-mode’ uses external program — Hasktags
|
||
(https://github.com/MarcWeber/hasktags) (wiki-article
|
||
(https://wiki.haskell.org/Tags)). To turn on tags generatation
|
||
customize or set to ‘t’ ‘haskell-tags-on-save’ variable. Also, you may
|
||
find useful to revert tags tables automatically, this can be done by
|
||
customizing ‘tags-revert-without-query’ variable (either globally or for
|
||
Haskell buffers only).
|
||
|
||
3.3 Profiling and Debugging support
|
||
===================================
|
||
|
||
When profiling code with GHC, it is often useful to add cost centres
|
||
(https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/profiling.html#cost-centres)
|
||
by hand. These allow finer-grained information about program behavior.
|
||
‘haskell-mode’ provides the function ‘haskell-mode-toggle-scc-at-point’
|
||
to make this more convenient. It will remove an SCC annotation at point
|
||
if one is present, or add one if point is over whitespace. By default
|
||
it is bound to ‘C-c C-s’.
|
||
|
||
|
||
File: haskell-mode.info, Node: Syntax highlighting, Next: Completion support, Prev: Editing Haskell Code, Up: Top
|
||
|
||
4 Syntax highlighting
|
||
*********************
|
||
|
||
‘haskell-mode’ supports “syntax highlighting” via Emacs’ Font Lock minor
|
||
mode which should be enabled by default in current Emacsen. *Note
|
||
(emacs)Font Lock::, for more information on how to control
|
||
‘font-lock-mode’.
|
||
|
||
Syntax highlighting facilities parse strings and string escape
|
||
sequences and are able to highlight unrecognized constructs.
|
||
|
||
Haskell Mode shows keywords, identifiers, operators, constructors and
|
||
types in different colors.
|
||
|
||
There is also support to use mode-specific syntax highlighing for
|
||
quasiquotes.
|
||
|
||
At this point quasi quotes for HTML, XML, shell scripts, Hamlet
|
||
templates and SQL are supported out of the box. Customize
|
||
‘haskell-font-lock-quasi-quote-modes’ to make sure your quoters are
|
||
supported.
|
||
|
||
The following customization variables are responsible for faces
|
||
applied:
|
||
|
||
‘’ ‘haskell-keyword-face’: for keywords
|
||
‘’ ‘haskell-type-face’: for type names and type class names
|
||
‘’ ‘haskell-constructor-face’: for constructors
|
||
‘’ ‘haskell-definition-face’: function and operator name at the
|
||
definition place
|
||
‘’ ‘haskell-operator-face’: operators
|
||
‘’ ‘haskell-pragma-face’: GHC pragmas
|
||
‘’ ‘haskell-literate-comment-face’: literate comments
|
||
‘’ ‘haskell-quasi-quote-face’: quasi quotes unless using mode
|
||
specific highlighting
|
||
‘’ ‘haskell-c2hs-hook-pair-face’: c2hs hooks
|
||
‘’ ‘haskell-c2hs-hook-name-face’: c2hs hook names
|
||
|
||
All the above are available for customization.
|
||
|
||
GHC quasi quote syntax is ambiguous with list comprehension therefore
|
||
syntax highlighting might get confused with situations like these:
|
||
|
||
result = [html| html <- htmlList]
|
||
result = [html| <html><body>...</body></html> |]
|
||
|
||
Please use spaces around a list comprehension variable to make this
|
||
unambiguous. Any of the following will work:
|
||
|
||
result = [ html| html <- htmlList]
|
||
result = [html | html <- htmlList]
|
||
|
||
GHC’s ambiguity is an accident of the past but it is unlikely to be
|
||
fixed due to backward compatibility baggage.
|
||
|
||
|
||
File: haskell-mode.info, Node: Completion support, Next: Unicode support, Prev: Syntax highlighting, Up: Top
|
||
|
||
5 Completion support
|
||
********************
|
||
|
||
‘haskell-mode’ can complete symbols, pragma directives, language
|
||
extensions, and language keywords out-of-box. ‘haskell-mode’ completes
|
||
identifiers (symbols) using tags (see “Tags”), however you can get more
|
||
precise completions with ‘haskell-interactive-mode’. In interactive
|
||
mode completion candidates are produced by querying GHCi REPL.
|
||
|
||
If ‘haskell-interactive-mode’ is enabled and working Haskell mode
|
||
provides completions for import statements taking into account currently
|
||
loaded and available packages. Also it completes symbols querying REPL
|
||
with ‘:complete’ command, hence completion candidate list also includes
|
||
symbols from imported modules.
|
||
|
||
Unfortunatelly, it is not possible to provide candidates for
|
||
identifiers defined locally in ‘let’ and ‘where’ blocks even in
|
||
interactive mode. But if you’re using company-mode
|
||
(http://company-mode.github.io/) you can override ‘company-backends’
|
||
variable for Haskell buffers to combine completion candidates from
|
||
completion-at-point function (‘company-capf’ backend) and dynamic
|
||
abbrevs. ‘company-mode’ provides special backend for dabbrev code
|
||
completions, namely ‘company-dabbrev-code’. To combine completions from
|
||
diffrent backends you can create grouped backends, it is very easy — a
|
||
grouped backend is just a list of backends, for example:
|
||
|
||
(add-hook 'haskell-mode-hook
|
||
(lambda ()
|
||
(set (make-local-variable 'company-backends)
|
||
(append '((company-capf company-dabbrev-code))
|
||
company-backends))))
|
||
|
||
If you use a GHCi version prior to 8.0.1 you might want to set
|
||
‘haskell-completions-complete-operators’ to ‘nil’, if you experience
|
||
major slowdown while trying to complete after an Haskell operator (See
|
||
GHC-Bug 10576 (https://ghc.haskell.org/trac/ghc/ticket/10576)).
|
||
|
||
|
||
File: haskell-mode.info, Node: Unicode support, Next: Indentation, Prev: Completion support, Up: Top
|
||
|
||
6 Unicode support
|
||
*****************
|
||
|
||
See the Haskell Wiki’s entry on Unicode Symbols
|
||
(http://www.haskell.org/haskellwiki/Unicode-symbols) for general
|
||
information about Unicode support in Haskell.
|
||
|
||
As Emacs supports editing files containing Unicode out of the box, so
|
||
does Haskell Mode. As an add-on, Haskell Mode includes the
|
||
‘haskell-unicode’ input method which allows you to easily type a number
|
||
of Unicode symbols that are useful when writing Haskell code; *Note
|
||
(emacs)Input Methods::, for more details.
|
||
|
||
To automatically enable the ‘haskell-unicode’ input method in
|
||
haskell-mode buffers use ‘M-x customize-variable <RET>
|
||
haskell-mode-hook’ or put the following code in your ‘.emacs’ file:
|
||
|
||
(add-hook 'haskell-mode-hook 'turn-on-haskell-unicode-input-method)
|
||
|
||
To temporarily enable this input method for a single buffer you can use
|
||
‘M-x turn-on-haskell-unicode-input-method’.
|
||
|
||
When the ‘haskell-unicode’ input method is active, you can simply
|
||
type ‘->’ and it is immediately replaced with ‘→’. Use ‘C-\’ to toggle
|
||
the input method. To see a table of all key sequences use ‘M-x
|
||
describe-input-method <RET> haskell-unicode’. A sequence like ‘<=’ is
|
||
ambiguous and can mean either ‘⇐’ or ‘≤’. Typing it presents you with a
|
||
choice. Type ‘1’ or ‘2’ to select an option or keep typing to use the
|
||
default option.
|
||
|
||
Currently defined sequences are listed in the following table:
|
||
|
||
SequenceUnicode SequenceUnicode SequenceUnicode SequenceUnicode
|
||
----------------------------------------------------------------------------
|
||
alpha α Alpha Α beta β Beta Β
|
||
gamma γ Gamma Γ delta δ Delta Δ
|
||
epsilonε EpsilonΕ zeta ζ Zeta Ζ
|
||
eta η Eta Η theta θ Theta Θ
|
||
iota ι Iota Ι kappa κ Kappa Κ
|
||
lambda λ Lambda Λ lamda λ Lamda Λ
|
||
mu μ Mu Μ nu ν Nu Ν
|
||
xi ξ Xi Ξ omicronο OmicronΟ
|
||
pi π Pi Π rho ρ Rho Ρ
|
||
sigma σ Sigma Σ tau τ Tau Τ
|
||
upsilonυ UpsilonΥ phi φ Phi Φ
|
||
chi χ Chi Χ psi ψ Psi Ψ
|
||
omega ω Omega Ω digammaϝ DigammaϜ
|
||
san ϻ San Ϻ qoppa ϙ Qoppa Ϙ
|
||
sampi ϡ Sampi Ϡ stigma ϛ Stigma Ϛ
|
||
heta ͱ Heta Ͱ sho ϸ Sho Ϸ
|
||
|A| 𝔸 |B| 𝔹 |C| ℂ |D| 𝔻
|
||
|E| 𝔼 |F| 𝔽 |G| 𝔾 |H| ℍ
|
||
|I| 𝕀 |J| 𝕁 |K| 𝕂 |L| 𝕃
|
||
|M| 𝕄 |N| ℕ |O| 𝕆 |P| ℙ
|
||
|Q| ℚ |R| ℝ |S| 𝕊 |T| 𝕋
|
||
|U| 𝕌 |V| 𝕍 |W| 𝕎 |X| 𝕏
|
||
|Y| 𝕐 |Z| ℤ |gamma|ℽ |Gamma|ℾ
|
||
|pi| ℼ |Pi| ℿ :: ∷ forall ∀
|
||
exists ∃ -> → <- ← => ⇒
|
||
~> ⇝ <~ ⇜ && ∧ || ∨
|
||
== ≡ /= ≢, ≠ <= ≤ >= ≥
|
||
/< ≮ /> ≯ * ⋅ elem ∈
|
||
notElem∉ member ∈ notMember∉ union ∪
|
||
intersection∩ isSubsetOf⊆ isProperSubsetOf⊂ <<< ⋘
|
||
>>> ⋙ <| ⊲ |> ⊳ >< ⋈
|
||
mappend⊕ . ∘ undefined⊥ := ≔
|
||
=: ≕ =def ≝ =? ≟ ... …
|
||
_0 ₀ _1 ₁ _2 ₂ _3 ₃
|
||
_4 ₄ _5 ₅ _6 ₆ _7 ₇
|
||
_8 ₈ _9 ₉ ^0 ⁰ ^1 ¹
|
||
^2 ² ^3 ³ ^4 ⁴ ^5 ⁵
|
||
^6 ⁶ ^7 ⁷ ^8 ⁸ ^9 ⁹
|
||
|
||
If you don’t like the highlighting of partially matching tokens you
|
||
can turn it off by setting ‘input-method-highlight-flag’ to ‘nil’ via
|
||
‘M-x customize-variable’.
|
||
|
||
|
||
File: haskell-mode.info, Node: Indentation, Next: External indentation, Prev: Unicode support, Up: Top
|
||
|
||
7 Indentation
|
||
*************
|
||
|
||
In Haskell, code indentation has semantic meaning as it defines the
|
||
block structure. Haskell also supports braces and semicolons notation
|
||
for conveying the block structure. However, most Haskell programs
|
||
written by humans use indentation for block structuring.
|
||
|
||
Haskell Mode ships with two indentation modes:
|
||
|
||
• ‘haskell-indentation-mode’ (default).
|
||
|
||
This is a semi-intelligent indentation mode doing a decent job at
|
||
recognizing Haskell syntactical constructs. It is based on a
|
||
recursive descent Haskell parser. ‘TAB’ selects the next potential
|
||
indentation position, ‘S-TAB’ selects the previous one. If a block
|
||
is selected you can use ‘TAB’ to indent the block more and ‘S-TAB’
|
||
to indent the block less.
|
||
|
||
When ‘electric-indent-mode’ is enabled or the variable
|
||
‘haskell-indentation-electric-flag’ is non-nil, the insertion of
|
||
some characters (by default ‘,’ ‘;’ ‘)’ ‘}’ ‘]’) may trigger auto
|
||
reindentation under appropriate conditions. See the documentation
|
||
of ‘haskell-indentation-common-electric-command’ for more details.
|
||
|
||
• ‘haskell-indent-mode’ (optional).
|
||
|
||
This is a semi-intelligent indentation mode doing a decent job at
|
||
recognizing Haskell syntactical constructs. It is based on a
|
||
decision table. Sadly it is no longer developed and does not
|
||
recognize newer Haskell syntax. ‘TAB’ cycles through all available
|
||
indentation positions.
|
||
|
||
To use ‘haskell-indent-mode’, add this to your ‘~/.emacs’ file:
|
||
|
||
(add-hook 'haskell-mode-hook 'turn-on-haskell-indent)
|
||
|
||
Note that ‘turn-on-haskell-indent’ will disable
|
||
‘haskell-indentation-mode’.
|
||
|
||
For general information about indentation support in GNU Emacs, *note
|
||
(emacs)Indentation::.
|
||
|
||
7.1 Rectangle Commands
|
||
======================
|
||
|
||
GNU Emacs provides so-called “rectangle commands” which operate on
|
||
rectangular areas of text, which are particularly useful for languages
|
||
with a layout rule such as Haskell. *Note (emacs)Rectangles::, to learn
|
||
more about rectangle commands.
|
||
|
||
Moreover, CUA mode (*note (emacs)CUA Bindings::) provides enhanced
|
||
rectangle support with visible rectangle highlighting. When CUA mode is
|
||
active, you can initiate a rectangle selection by ‘C-RET’ and extend it
|
||
simply by movement commands. You don’t have to enable full CUA mode to
|
||
benefit from these enhanced rectangle commands; you can activate CUA
|
||
selection mode (without redefining ‘C-x’,‘C-c’,‘C-v’, and ‘C-z’) by
|
||
calling ‘M-x cua-selection-mode’ (or adding ‘(cua-selection-mode nil)’
|
||
to your ‘haskell-mode-hook’).
|
||
|
||
7.2 Region indent is a no-op
|
||
============================
|
||
|
||
There is a ‘indent-region’ function that supposedly could be used to
|
||
indent code region without changing its semantics. Sadly it does not
|
||
work that way because usual use case for ‘indent-region’ is:
|
||
|
||
1. Alter first line of code in region.
|
||
2. Call ‘indent-region’ to fix indentation for remaining lines.
|
||
|
||
Note that between 1 and 2 program is already semantically broken and
|
||
knowing how to indent it preserving semantic from before step 1 would
|
||
require time travel.
|
||
|
||
To stay on the safe side ‘indent-region-function’ is bound to a no-op
|
||
in ‘haskell-mode’.
|
||
|
||
|
||
File: haskell-mode.info, Node: External indentation, Next: Autoformating, Prev: Indentation, Up: Top
|
||
|
||
8 Other ways to indent code
|
||
***************************
|
||
|
||
8.1 Indentation with tabs, not spaces
|
||
=====================================
|
||
|
||
Some projects require indenting code with tabs and forbid indenting it
|
||
with spaces. For hacking on such projects, check out
|
||
haskell-tab-indent-mode
|
||
(https://spwhitton.name/tech/code/haskell-tab-indent).
|
||
|
||
8.2 Structured indentation
|
||
==========================
|
||
|
||
Another alternative is to install structured-haskell-mode
|
||
(https://github.com/chrisdone/structured-haskell-mode). which indents
|
||
code by parsing the code with a full Haskell parser and deciding where
|
||
to indent based on that.
|
||
|
||
|
||
File: haskell-mode.info, Node: Autoformating, Next: Module templates, Prev: External indentation, Up: Top
|
||
|
||
9 Using external formatters
|
||
***************************
|
||
|
||
You can enable stylish-haskell
|
||
(https://github.com/jaspervdj/stylish-haskell) by installing it:
|
||
|
||
$ cabal install stylish-haskell
|
||
|
||
And by enabling it with a customization
|
||
|
||
(custom-set-variables
|
||
'(haskell-stylish-on-save t))
|
||
|
||
Now when you run ‘save-buffer’ (or ‘C-x C-s’) the module will be
|
||
automatically formatted.
|
||
|
||
Alternatively, you can run the function directly on demand with ‘M-x’
|
||
‘haskell-mode-stylish-buffer’.
|
||
|
||
|
||
File: haskell-mode.info, Node: Module templates, Next: Declaration scanning, Prev: Autoformating, Up: Top
|
||
|
||
10 Module templates
|
||
*******************
|
||
|
||
To enable auto-insertion of module templates, enable:
|
||
|
||
(add-hook 'haskell-mode-hook 'haskell-auto-insert-module-template)
|
||
|
||
When you open a file called ‘Foo.hs’, it will auto-insert
|
||
|
||
-- |
|
||
|
||
module Foo where
|
||
|
||
And put your cursor in the comment section.
|
||
|
||
|
||
File: haskell-mode.info, Node: Declaration scanning, Next: Compilation, Prev: Module templates, Up: Top
|
||
|
||
11 Declaration scannning
|
||
************************
|
||
|
||
‘haskell-decl-scan-mode’ is a minor mode which performs declaration
|
||
scanning and provides ‘M-x imenu’ support (*note (emacs)Imenu:: for more
|
||
information).
|
||
|
||
For non-literate and TeX-style literate scripts, the common
|
||
convention that top-level declarations start at the first column is
|
||
assumed. For Bird-style literate scripts, the common convention that
|
||
top-level declarations start at the third column, ie. after ‘> ’, is
|
||
assumed.
|
||
|
||
When ‘haskell-decl-scan-mode’ is active, the standard Emacs top-level
|
||
definition movement commands (*note (emacs)Moving by Defuns::) are
|
||
enabled to operate on Haskell declarations:
|
||
|
||
‘C-M-a’
|
||
Move to beginning of current or preceding declaration
|
||
(‘beginning-of-defun’).
|
||
|
||
‘C-M-e’
|
||
Move to end of current or following declaration (‘end-of-defun’).
|
||
|
||
‘C-M-h’
|
||
Select whole current or following declaration (‘mark-defun’).
|
||
|
||
Moreover, if enabled via the option
|
||
‘haskell-decl-scan-add-to-menubar’, a menu item “Declarations” is added
|
||
to the menu bar listing the scanned declarations and allowing to jump to
|
||
declarations in the source buffer.
|
||
|
||
It’s recommended to have font lock mode enabled (*note (emacs)Font
|
||
Lock::) as ‘haskell-decl-scan-mode’ ignores text highlighted with
|
||
‘font-lock-comment-face’.
|
||
|
||
As usual, in order to activate ‘haskell-decl-scan-mode’ automatically
|
||
for Haskell buffers, add ‘haskell-decl-scan-mode’ to
|
||
‘haskell-mode-hook’:
|
||
|
||
(add-hook 'haskell-mode-hook 'haskell-decl-scan-mode)
|
||
|
||
‘haskell-decl-scan-mode’ enables the use of features that build upon
|
||
‘imenu’ support such as Speedbar Frames (*note (emacs)Speedbar::) or the
|
||
global “Which Function” minor mode (*note (emacs)Which Function::).
|
||
|
||
In order to enable ‘which-function-mode’ for Haskell buffers you need
|
||
to add the following to your Emacs initialization:
|
||
|
||
(eval-after-load "which-func"
|
||
'(add-to-list 'which-func-modes 'haskell-mode))
|
||
|
||
11.1 Speedbar
|
||
=============
|
||
|
||
Haskell-mode comes with declaration scanning support. This means that
|
||
if you enable Haskell support for speedbar:
|
||
|
||
(speedbar-add-supported-extension ".hs")
|
||
|
||
And open speedbar with
|
||
|
||
‘M-x speedbar’
|
||
|
||
It gives a listing of each module and under each module:
|
||
|
||
Imports
|
||
Instances
|
||
Data types
|
||
Classes
|
||
Bindings
|
||
|
||
You will get a bar that looks like this:
|
||
|
||
~/Projects/ace/src/ACE/
|
||
0:<+> Types
|
||
0:[+] Combinators.hs
|
||
0:[-] Datalog.hs
|
||
1: {-} Classes
|
||
2: > ToTerm
|
||
1: {-} Imports
|
||
2: > ACE.Types.Syntax
|
||
2: > Database.Datalog
|
||
1: {-} Instances
|
||
2: {+} ToTerm A
|
||
2: {+} ToTerm Co to ToTerm Gen
|
||
2: {+} ToTerm Intransitive to ToTerm N
|
||
2: {+} ToTerm P
|
||
2: {+} ToTerm Quotation to ToTerm Un
|
||
2: {+} ToTerm V
|
||
0:[-] Html.hs
|
||
1: {+} Imports
|
||
1: {+} Instances
|
||
1: > mtoMarkup
|
||
1: > toMarkupm
|
||
1: > wrap
|
||
0:[-] Parsers.hs
|
||
1: {+} Imports
|
||
1: {-} Datatypes
|
||
2: > ACEParser
|
||
0:[+] Pretty.hs
|
||
0:[+] Tokenizer.hs
|
||
|
||
The hierarchy is expandable/collapsible and each entry will jump to
|
||
the line in the right file when clicked/selected.
|
||
|
||
|
||
File: haskell-mode.info, Node: Compilation, Next: Interactive Haskell, Prev: Declaration scanning, Up: Top
|
||
|
||
12 Compilation
|
||
**************
|
||
|
||
Haskell mode comes equipped with a specialized “Compilation mode”
|
||
tailored to GHC’s compiler messages with optional support for Cabal
|
||
projects. *Note (emacs)Compilation Mode::, for more information about
|
||
the basic commands provided by the Compilation mode which are available
|
||
in the Haskell compilation sub-mode as well. The additional features
|
||
provided compared to Emacs’ basic Compilation mode are:
|
||
|
||
• DWIM-style auto-detection of compile command (including support for
|
||
CABAL projects)
|
||
• Support for GHC’s compile messages and recognizing error, warning
|
||
and info source locations (including ‘-ferror-spans’ syntax)
|
||
• Support for filtering out GHC’s uninteresting ‘Loading package...’
|
||
linker messages
|
||
|
||
In order to use it, invoke the ‘haskell-compile’ command instead of
|
||
‘compile’ as you would for the ordinary Compilation mode. It’s
|
||
recommended to bind ‘haskell-compile’ to a convenient key binding. For
|
||
instance, you can add the following to your Emacs initialization to bind
|
||
‘haskell-compile’ to ‘C-c C-c’.
|
||
|
||
(eval-after-load "haskell-mode"
|
||
'(define-key haskell-mode-map (kbd "C-c C-c") 'haskell-compile))
|
||
|
||
(eval-after-load "haskell-cabal"
|
||
'(define-key haskell-cabal-mode-map (kbd "C-c C-c") 'haskell-compile))
|
||
|
||
The following description assumes that ‘haskell-compile’ has been bound
|
||
to ‘C-c C-c’.
|
||
|
||
When invoked, ‘haskell-compile’ tries to guess how to compile the
|
||
Haskell program your currently visited buffer belongs to, by searching
|
||
for a ‘.cabal’ file in the current of enclosing parent folders. If a
|
||
‘.cabal’ file was found, the command defined in the
|
||
‘haskell-compile-cabal-build-command’ option is used. Note that to
|
||
compile a ‘stack’ based project you will need to set this variable to
|
||
‘stack build’. As usual you can do it using ‘M-x customize-variable’ or
|
||
with:
|
||
|
||
(setq haskell-compile-cabal-build-command "stack build")
|
||
|
||
Moreover, when requesting to compile a ‘.cabal’-file is detected and
|
||
a negative prefix argument (e.g. ‘C-- C-c C-c’) was given, the
|
||
alternative ‘haskell-compile-cabal-build-command-alt’ is invoked. By
|
||
default, ‘haskell-compile-cabal-build-command-alt’ contains a ‘cabal
|
||
clean -s’ command in order to force a full rebuild.
|
||
|
||
Otherwise if no ‘.cabal’ could be found, a single-module compilation
|
||
is assumed and ‘haskell-compile-command’ is used (_if_ the currently
|
||
visited buffer contains Haskell source code).
|
||
|
||
You can also inspect and modify the compile command to be invoked
|
||
temporarily by invoking ‘haskell-compile’ with a prefix argument (e.g.
|
||
‘C-u C-c C-c’). If later-on you want to recompile using the same
|
||
customized compile command, invoke ‘recompile’ (bound to ‘g’) inside the
|
||
‘*haskell-compilation*’ buffer.
|
||
|
||
12.1 Keybindings
|
||
================
|
||
|
||
Key Function
|
||
binding
|
||
------------
|
||
TAB compilation-next-error
|
||
|
||
RET compile-goto-error
|
||
|
||
C-o compilation-display-error
|
||
|
||
SPC scroll-up-command
|
||
|
||
- negative-argument
|
||
|
||
0 digit-argument
|
||
..
|
||
9
|
||
< beginning-of-buffer
|
||
|
||
> end-of-buffer
|
||
|
||
? describe-mode
|
||
|
||
g recompile
|
||
|
||
h describe-mode
|
||
|
||
q quit-window
|
||
|
||
DEL scroll-down-command
|
||
|
||
S-SPC scroll-down-command
|
||
|
||
<backtab>compilation-previous-error
|
||
|
||
<follow-link>mouse-face
|
||
|
||
<mouse-2>compile-goto-error
|
||
|
||
<remap>Prefix
|
||
Command
|
||
|
||
M-n compilation-next-error
|
||
|
||
M-p compilation-previous-error
|
||
|
||
M-{ compilation-previous-file
|
||
|
||
M-} compilation-next-file
|
||
|
||
C-c compile-goto-error
|
||
C-c
|
||
C-c next-error-follow-minor-mode
|
||
C-f
|
||
C-c kill-compilation
|
||
C-k
|
||
|
||
|
||
File: haskell-mode.info, Node: Interactive Haskell, Next: Editing Cabal files, Prev: Compilation, Up: Top
|
||
|
||
13 Interactive Haskell
|
||
**********************
|
||
|
||
REPL (read–eval–print loop) is provided both via Comint
|
||
(‘inferior-haskell-mode’) and an adhoc way called
|
||
‘haskell-interactive-mode’. The Comint based ‘inferior-haskell-mode’ is
|
||
just the REPL, it comes with the standard key bindings(like ‘ielm’ or
|
||
‘eshell’).
|
||
|
||
‘haskell-interactive-mode’ comes with a different set of features:
|
||
|
||
• Separate sessions per Cabal project ‘haskell-session.el’.
|
||
• A new inferior Haskell process handling code ‘haskell-process.el’.
|
||
• New REPL implementation similiar to SLIME/IELM
|
||
• Navigatable error overlays ‘haskell-interactive-mode.el’.
|
||
|
||
With ‘haskell-interactive-mode’, each Haskell source buffer is
|
||
associated with at most one GHCi session, so when you call
|
||
‘haskell-process-load-file’ for a Haskell source buffer which has no
|
||
session associated yet, you’re asked which GHCi session to create or
|
||
associate with.
|
||
|
||
13.1 Goto Error
|
||
===============
|
||
|
||
In a Haskell source buffer associated with a GHCi session, errors that
|
||
prevent the file from loading are highlighted with ‘haskell-error-face’.
|
||
You can move between these error lines with
|
||
|
||
‘M-n’
|
||
is bound to ‘haskell-goto-next-error’
|
||
‘M-p’
|
||
is bound to ‘haskell-goto-prev-error’
|
||
‘C-c M-p’
|
||
is bound to ‘haskell-goto-first-error’
|
||
|
||
13.2 Using GHCi 8+ or GHCi-ng
|
||
=============================
|
||
|
||
If you use either of the above, then you can use these functions:
|
||
|
||
(define-key interactive-haskell-mode-map (kbd "M-.") 'haskell-mode-goto-loc)
|
||
(define-key interactive-haskell-mode-map (kbd "C-c C-t") 'haskell-mode-show-type-at)
|
||
|
||
You have to load the module before it works, after that it will
|
||
remember for the current GHCi session.
|
||
|
||
13.3 Customizing
|
||
================
|
||
|
||
What kind of Haskell REPL ‘haskell-interactive-mode’ will start up
|
||
depends on the value of ‘haskell-process-type’. This can be one of the
|
||
symbols ‘auto’, ‘ghci’, ‘cabal-repl’, ‘cabal-new-repl’, or ‘stack-ghci’.
|
||
If it’s ‘auto’, the directory contents and available programs will be
|
||
used to make a best guess at the process type. The actual process type
|
||
will then determine which variables ‘haskell-interactive-mode’ will
|
||
access to determine the program to start and its arguments:
|
||
|
||
• If it’s ‘ghci’, ‘haskell-process-path-ghci’ and
|
||
‘haskell-process-args-ghci’ will be used.
|
||
• If it’s ‘cabal-repl’, ‘haskell-process-path-cabal’ and
|
||
‘haskell-process-args-cabal-repl’.
|
||
• If it’s ‘cabal-new-repl’, ‘haskell-process-path-cabal’ and
|
||
‘haskell-process-args-cabal-new-repl’.
|
||
• If it’s ‘stack-ghci’, ‘haskell-process-path-stack’ and
|
||
‘haskell-process-args-stack-ghci’ will be used.
|
||
|
||
With each of these pairs, the the ‘haskell-process-path-...’ variable
|
||
needs to be a string specifying the program path, or a list of strings
|
||
where the first element is the program path and the rest are initial
|
||
arguments. The ‘haskell-process-args-...’ is a list of strings
|
||
specifying (further) command-line arguments.
|
||
|
||
13.4 Haskell Interactive Mode Setup
|
||
===================================
|
||
|
||
The most straight-forward way to get setup with Interactive Mode is to
|
||
bind the right keybindings and set some customizations. This page
|
||
contains a good base setup.
|
||
|
||
To enable the minor mode which activates keybindings associated with
|
||
interactive mode, use:
|
||
|
||
(require 'haskell-interactive-mode)
|
||
(require 'haskell-process)
|
||
(add-hook 'haskell-mode-hook 'interactive-haskell-mode)
|
||
|
||
13.4.1 Customizations
|
||
---------------------
|
||
|
||
This enables some handy and benign features.
|
||
|
||
(custom-set-variables
|
||
'(haskell-process-suggest-remove-import-lines t)
|
||
'(haskell-process-auto-import-loaded-modules t)
|
||
'(haskell-process-log t))
|
||
|
||
13.4.2 Haskell-mode bindings
|
||
----------------------------
|
||
|
||
This gives the basic ways to start a session. In a Haskell buffer:
|
||
|
||
• Run ‘C-`’ to make a REPL open, this will create a session, start
|
||
GHCi, and open the REPL.
|
||
• Or: run ‘C-c C-l’ to load the file. This will first try to start a
|
||
session as the previous command does.
|
||
• Or: run any command which requires a running session. It will
|
||
always prompt to create one if there isn’t one already for the
|
||
current project.
|
||
|
||
(define-key haskell-mode-map (kbd "C-c C-l") 'haskell-process-load-or-reload)
|
||
(define-key haskell-mode-map (kbd "C-`") 'haskell-interactive-bring)
|
||
(define-key haskell-mode-map (kbd "C-c C-t") 'haskell-process-do-type)
|
||
(define-key haskell-mode-map (kbd "C-c C-i") 'haskell-process-do-info)
|
||
(define-key haskell-mode-map (kbd "C-c C-c") 'haskell-process-cabal-build)
|
||
(define-key haskell-mode-map (kbd "C-c C-k") 'haskell-interactive-mode-clear)
|
||
(define-key haskell-mode-map (kbd "C-c c") 'haskell-process-cabal)
|
||
|
||
13.4.3 Cabal-mode bindings
|
||
--------------------------
|
||
|
||
The below commands pretty much match the ones above, but are handy to
|
||
have in cabal-mode, too:
|
||
|
||
(define-key haskell-cabal-mode-map (kbd "C-`") 'haskell-interactive-bring)
|
||
(define-key haskell-cabal-mode-map (kbd "C-c C-k") 'haskell-interactive-mode-clear)
|
||
(define-key haskell-cabal-mode-map (kbd "C-c C-c") 'haskell-process-cabal-build)
|
||
(define-key haskell-cabal-mode-map (kbd "C-c c") 'haskell-process-cabal)
|
||
|
||
13.4.4 GHCi process type
|
||
------------------------
|
||
|
||
By default ‘haskell-process-type’ is set to ‘auto’. It is smart enough
|
||
to pick the right type based on your project structure and installed
|
||
tools, but in case something goes funky or you want to explicitly set
|
||
the process type and ignore the inferred type, you can customize this
|
||
setting by running ‘M-x’ ‘customize-variable’ ‘RET’
|
||
‘haskell-process-type’ ‘RET’, or by setting the code:
|
||
|
||
(custom-set-variables
|
||
'(haskell-process-type 'cabal-repl))
|
||
|
||
Here is a list of available process types:
|
||
|
||
• ghci
|
||
• cabal-repl
|
||
• cabal-new-repl
|
||
• cabal-dev
|
||
• cabal-ghci
|
||
• stack-ghci
|
||
|
||
Please, check the documentation for ‘haskell-process-type’ to see how
|
||
the real type is guessed, when it’s set to ‘auto’.
|
||
|
||
13.4.5 Troubleshooting
|
||
----------------------
|
||
|
||
Launching your GHCi process can fail when you’re first getting setup,
|
||
depending on the type you choose. If it does fail to launch, switch to
|
||
the buffer ‘*haskell-process-log*’ and see what’s up. The buffer
|
||
contains a log of incoming/outgoing messages to the GHCi process.
|
||
|
||
13.5 Haskell Interactive Mode Tags Using GHCi
|
||
=============================================
|
||
|
||
You can bind the following to use GHCi to find definitions of things:
|
||
|
||
(define-key haskell-mode-map (kbd "M-.") 'haskell-mode-jump-to-def)
|
||
|
||
The one problem with this approach is that if your code doesn’t
|
||
compile, GHCi doesn’t give any location info. So you need to make sure
|
||
your code compiles and the modules you want to jump to are loaded
|
||
byte-compiled.
|
||
|
||
Note: I think that when you restart GHCi you lose location
|
||
information, even if you have the ‘.o’ and ‘.hi’ files lying around.
|
||
I’m not sure. But sometimes ‘:i foo’ will give ‘foo is defined in Bar’
|
||
rather than ‘foo is defined in /foo/Bar.hs:123:23’.
|
||
|
||
Alternatively, you can use tags generation, which doesn’t require a
|
||
valid compile.
|
||
|
||
13.5.1 Tags Setup
|
||
-----------------
|
||
|
||
Make sure to install ‘hasktags’.
|
||
|
||
$ cabal install hasktags
|
||
|
||
Then add the customization variable to enable tags generation on
|
||
save:
|
||
|
||
(custom-set-variables
|
||
'(haskell-tags-on-save t))
|
||
|
||
And make sure ‘hasktags’ is in your ‘$PATH’ which Emacs can see.
|
||
|
||
13.5.2 Generating tags
|
||
----------------------
|
||
|
||
Now, every time you run ‘save-buffer’ (‘C-x C-s’), there is a hook that
|
||
will run and generate Emacs *Note (emacs)Tags:: for the whole project
|
||
directory. The resulting file will be called ‘TAGS’.
|
||
|
||
WARNING: You should be careful that your project root isn’t your home
|
||
directory or something, otherwise it will traverse all the way down and
|
||
take an impossibly long time.
|
||
|
||
13.5.3 Jumping to tags
|
||
----------------------
|
||
|
||
Bind the following keybinding:
|
||
|
||
(define-key haskell-mode-map (kbd "M-.") 'haskell-mode-tag-find)
|
||
|
||
To jump to the location of the top-level identifier at point, run
|
||
‘M-x’ ‘haskell-mode-tag-find’ or ‘M-.’.
|
||
|
||
13.5.4 Hybrid: GHCi and fallback to tags
|
||
----------------------------------------
|
||
|
||
To use GHCi first and then if that fails to fallback to tags for
|
||
jumping, use:
|
||
|
||
(define-key haskell-mode-map (kbd "M-.") 'haskell-mode-jump-to-def-or-tag)
|
||
|
||
13.5.5 Troubleshooting tags
|
||
---------------------------
|
||
|
||
Sometimes a ‘TAGS’ file is deleted (by you or some other process).
|
||
Emacs will complain that it doesn’t exist anymore. To resolve this
|
||
simply do ‘M-x’ ‘tags-reset-tags-tables’.
|
||
|
||
13.6 Sessions
|
||
=============
|
||
|
||
All commands in Haskell Interactive Mode work within a session.
|
||
Consider it like a “project” or a “solution” in popular IDEs. It tracks
|
||
the root of your project and an associated process and REPL.
|
||
|
||
13.6.1 Start a session
|
||
----------------------
|
||
|
||
To start a session run the following steps:
|
||
|
||
• Open some Cabal or Haskell file.
|
||
• Run ‘C-`’ to make a REPL open, this will create a session, start
|
||
GHCi, and open the REPL.
|
||
• Or: run ‘C-c C-l’ to load the file. This will first try to start a
|
||
session as the previous command does.
|
||
• Or: run any command which requires a running session. It will
|
||
always prompt to create one if there isn’t one already for the
|
||
current project.
|
||
|
||
It will prompt for a Cabal directory and a current directory. It
|
||
figures out where the cabal directory is and defaults for the current
|
||
directory, so you should be able to just hit RET twice.
|
||
|
||
13.6.2 Switch a session
|
||
-----------------------
|
||
|
||
Sometimes a particular file is used in two different sessions/projects.
|
||
You can run
|
||
|
||
M-x haskell-session-change
|
||
|
||
If it prompts you to make a new session, tell it no (that’s a bug).
|
||
It will ask you to choose from a list of sessions.
|
||
|
||
13.6.3 Killing a session
|
||
------------------------
|
||
|
||
To kill a session you can run
|
||
|
||
M-x haskell-session-kill
|
||
|
||
Which will prompt to kill all associated buffers, too. Hit ‘n‘ to
|
||
retain them.
|
||
|
||
Alternatively, you can switch to the REPL and just kill the buffer
|
||
normally with ‘C-x k RET’. It will prompt
|
||
|
||
Kill the whole session (y or n)?
|
||
|
||
You can choose ‘y’ to kill the session itself, or ‘n’ to just kill
|
||
the REPL buffer. You can bring it back with ‘M-x’
|
||
‘haskell-interactive-bring’.
|
||
|
||
13.6.4 Menu
|
||
-----------
|
||
|
||
To see a list of all sessions you have open with some simple statistics
|
||
about memory usage, etc. run
|
||
|
||
M-x haskell-menu
|
||
|
||
For example:
|
||
|
||
foo 14648 08:21:42 214MB /path/to/fpco/foo/ /path/to/fpco/foo/ ghci
|
||
bar 29119 00:22:03 130MB /path/to/bar/ /path/to/bar/ ghci
|
||
mu 22575 08:48:20 73MB /path/to/fpco/mu/ /path/to/fpco/mu/ ghci
|
||
|
||
13.7 Compiling
|
||
==============
|
||
|
||
There are a bunch of ways to compile Haskell modules. This page covers
|
||
a few of them.
|
||
|
||
13.7.1 Load into GHCi
|
||
---------------------
|
||
|
||
To compile and load a Haskell module into GHCi, run the following
|
||
|
||
M-x haskell-process-load
|
||
|
||
Or ‘C-c C-l’. You’ll see any compile errors in the REPL window.
|
||
|
||
13.7.2 Build the Cabal project
|
||
------------------------------
|
||
|
||
To compile the whole Cabal project, run the following
|
||
|
||
M-x haskell-process-cabal-build
|
||
|
||
Or ‘C-c C-c’. You’ll see any compile errors in the REPL window.
|
||
|
||
13.7.3 Reloading modules
|
||
------------------------
|
||
|
||
To reload the current module, even when you’re in other modules, you can
|
||
run ‘C-u M-x’ ‘haskell-process-load-or-reload’ or ‘C-u C-c C-l’. It
|
||
will now reload that module whenever you run ‘C-c C-l’ in the future
|
||
from whatever module you’re in. To disable this mode, just run ‘C-u C-c
|
||
C-l’ again.
|
||
|
||
13.7.4 Jumping to compile errors
|
||
--------------------------------
|
||
|
||
You can use the standard compile error navigation function ‘C-x `’ —
|
||
jump to the next error.
|
||
|
||
Or you can move your cursor to an error in the REPL and hit ‘RET’ to
|
||
jump to it.
|
||
|
||
13.7.5 Auto-removing imports
|
||
----------------------------
|
||
|
||
If the customization variable
|
||
‘haskell-process-suggest-remove-import-lines’ is enabled.
|
||
|
||
(custom-set-variables
|
||
'(haskell-process-suggest-remove-import-lines t))
|
||
|
||
Building and loading modules which output warnings like,
|
||
|
||
Warning: The import of `Control.Monad' is redundant
|
||
except perhaps to import instances from `Control.Monad'
|
||
To import instances alone, use: import Control.Monad()
|
||
|
||
will prompt the user with
|
||
|
||
> The import line `Control.Monad' is redundant. Remove? (y, n, c: comment out)
|
||
|
||
If you answer
|
||
|
||
• ‘y’: it will delete the import, but leave the empty line remaining
|
||
(this avoids messing with line positions in subsequent error
|
||
messages).
|
||
• ‘n’: it will leave the import.
|
||
• ‘c’: it will comment out the import (this is handy for when you
|
||
just want to temporarily hide an import).
|
||
|
||
13.7.6 Auto-adding of modules to import
|
||
---------------------------------------
|
||
|
||
Enable the customization variable
|
||
‘haskell-process-suggest-hoogle-imports’.
|
||
|
||
(custom-set-variables
|
||
'(haskell-process-suggest-hoogle-imports t))
|
||
|
||
Whenever GHC says something is not in scope, it will hoogle that
|
||
symbol. If there are results, it will prompt to add one of the modules
|
||
from Hoogle’s results.
|
||
|
||
You need to make sure you’ve generated your Hoogle database properly.
|
||
|
||
13.7.7 Auto-adding of extensions
|
||
--------------------------------
|
||
|
||
It you use an extension which is not enabled, GHC will often inform you.
|
||
For example, if you write:
|
||
|
||
newtype X a = X (IO a)
|
||
deriving (Monad)
|
||
|
||
Then you’ll see a message like:
|
||
|
||
x.hs:13:13: Can't make a derived instance of `Monad X': …
|
||
`Monad' is not a derivable class
|
||
Try -XGeneralizedNewtypeDeriving for GHC's newtype-deriving extension
|
||
In the newtype declaration for `X'
|
||
|
||
This ‘-XFoo’ pattern will be picked up and you will be prompted:
|
||
|
||
> Add `{-# LANGUAGE GeneralizedNewtypeDeriving #-}` to the top of the
|
||
> file? (y or n)
|
||
|
||
If you answer ‘y‘, it will temporarily jump to the buffer and it to
|
||
the top of the file.
|
||
|
||
13.7.8 Orphan instances
|
||
-----------------------
|
||
|
||
If GHC complains about orphan instances, you usually are doing it
|
||
intentionally, so it prompts to add ‘-fno-warn-orphans’ to the top of
|
||
the file with an ‘OPTIONS’ pragma.
|
||
|
||
13.7.9 Auto-adding of dependencies
|
||
----------------------------------
|
||
|
||
When doing a build, you will sometimes get a message from GHC like:
|
||
|
||
src/ACE/Tokenizer.hs:11:18: Could not find module `Data.Attoparsec.Text' …
|
||
It is a member of the hidden package `attoparsec-0.11.1.0'.
|
||
|
||
This message contains all the necessary information to add this to
|
||
your .cabal file, so you will be prompted to add it to your .cabal file:
|
||
|
||
Add `attoparsec' to ace.cabal? (y or n) y
|
||
|
||
If you hit ‘y’, it will prompt with this:
|
||
|
||
attoparsec >= 0.11.1.0
|
||
|
||
Which you can edit (e.g. do some PVP decision or remove constraints
|
||
entirely), and then it will open up your ‘.cabal’ file and go through
|
||
each section:
|
||
|
||
Add to library? (y or n) y
|
||
|
||
This will add it to the top of the ‘build-depends’ field in your
|
||
library section. If you have any executables, it will go through each
|
||
of those, prompting, too.
|
||
|
||
Now you can rebuild with ‘C-c C-c’ again.
|
||
|
||
13.8 Haskell Interactive Mode REPL
|
||
==================================
|
||
|
||
When GHCi has been launched, it works on a read-eval-print basis. So
|
||
you will be presented with the prompt:
|
||
|
||
The lambdas must flow.
|
||
Changed directory: /path/to/your/project/
|
||
λ>
|
||
|
||
13.8.1 Changing REPL target
|
||
---------------------------
|
||
|
||
With ‘haskell-session-change-target’ you can change the target for REPL
|
||
session.
|
||
|
||
After REPL session started, in ‘haskell-interactive-mode’ buffer
|
||
invoke the ‘haskell-session-change-target’ and select from available
|
||
targets for
|
||
|
||
- Testing
|
||
|
||
- Benchmark
|
||
|
||
- Executable
|
||
|
||
- Library
|
||
|
||
Answer “yes” to restart the session and run your tests, benchmarks,
|
||
executables.
|
||
|
||
TODO/WRITEME
|
||
|
||
13.8.2 Bringing the REPL
|
||
------------------------
|
||
|
||
If you don’t know where the REPL buffer is, you can always bring it
|
||
with:
|
||
|
||
M-x haskell-interactive-bring
|
||
|
||
Or ‘C-`’.
|
||
|
||
13.8.3 Evaluating expressions
|
||
-----------------------------
|
||
|
||
To evaluate expressions, simply type one out and hit ‘RET‘.
|
||
|
||
λ> 123
|
||
123
|
||
|
||
13.8.4 Evaluating multiline expressions
|
||
---------------------------------------
|
||
|
||
GHCi features two ways to evaluate multiline expressions. You can use
|
||
‘:set +m’ to enable multiline input
|
||
(https://www.haskell.org/ghc/docs/latest/html/users_guide/ghci.html#multiline-input)
|
||
for all expressions, or you can wrap your expression in ‘:{’ and ‘:}’
|
||
(they have to be on their own lines).
|
||
|
||
The prompt will change to indicate that you’re inputting a multiline
|
||
expression:
|
||
|
||
λ> :{
|
||
λ| let a = 10
|
||
λ| b = 20
|
||
λ| c = 30
|
||
λ| :}
|
||
|
||
You can also simulate multiline mode by having your input contain
|
||
newline characters. You can input a literal newline character with ‘C-q
|
||
C-j’, or you can use:
|
||
|
||
M-x haskell-interactive-mode-newline-indent
|
||
|
||
which is bound to ‘C-j’. This command indents after the newline.
|
||
You can simulate the above example like so:
|
||
|
||
λ> let a = 10
|
||
b = 20
|
||
c = 30
|
||
|
||
13.8.5 Type of expressions
|
||
--------------------------
|
||
|
||
You can use normal ‘:type’ which is part of GHCi to get the type of
|
||
something:
|
||
|
||
λ> :t id
|
||
id :: a -> a
|
||
|
||
But you can also just write out the value directly,
|
||
|
||
λ> id
|
||
id :: a -> a
|
||
|
||
and because there’s no ‘Show’ instance for ‘(a -> a)’. This would
|
||
normally yield a compile error:
|
||
|
||
No instance for (Show (a0 -> a0))
|
||
arising from a use of `print'
|
||
Possible fix: add an instance declaration for (Show (a0 -> a0))
|
||
In a stmt of an interactive GHCi command: print it
|
||
|
||
It will run ‘:type id’ in the background and print out the result.
|
||
The same is true for ambiguous things:
|
||
|
||
λ> :t read "a"
|
||
read "a" :: Read a => a
|
||
|
||
Because this would normally be an ambiguous constraint:
|
||
|
||
Ambiguous type variable `a0' in the constraint:
|
||
(Read a0) arising from a use of `read'
|
||
Probable fix: add a type signature that fixes these type variable(s)
|
||
In the expression: read \"a\"
|
||
In an equation for `it': it = read \"a\"
|
||
|
||
Which is less useful than just printing the type out.
|
||
|
||
You can disable this behaviour by disabling the customization option:
|
||
|
||
(custom-set-variables
|
||
'(haskell-interactive-types-for-show-ambiguous nil))
|
||
|
||
13.8.6 Printing mode
|
||
--------------------
|
||
|
||
You can choose between printing modes used for the results of evaluating
|
||
expressions. To do that, configure the variable
|
||
‘haskell-interactive-mode-eval-mode’. Example:
|
||
|
||
(setq haskell-interactive-mode-eval-mode 'haskell-mode)
|
||
|
||
A handy function you can use is:
|
||
|
||
(defun haskell-interactive-toggle-print-mode ()
|
||
(interactive)
|
||
(setq haskell-interactive-mode-eval-mode
|
||
(intern
|
||
(ido-completing-read "Eval result mode: "
|
||
'("fundamental-mode"
|
||
"haskell-mode"
|
||
"espresso-mode"
|
||
"ghc-core-mode"
|
||
"org-mode")))))
|
||
|
||
(Add whichever modes you want to use.)
|
||
|
||
And then run
|
||
|
||
M-x haskell-interactive-toggle-print-mode
|
||
|
||
Or ‘C-c C-v’:
|
||
|
||
(define-key haskell-interactive-mode-map (kbd "C-c C-v")
|
||
'haskell-interactive-toggle-print-mode)
|
||
|
||
There you can choose ‘haskell-mode‘, for example, to pretty print the
|
||
output as Haskell.
|
||
|
||
13.8.7 Presentations
|
||
--------------------
|
||
|
||
If you have the ‘present’ package installed, you can use the following
|
||
syntax to print anything which is an instance of ‘Data’:
|
||
|
||
λ> :present 123
|
||
123
|
||
|
||
It will print data structures lazily:
|
||
|
||
λ> :present [1..]
|
||
[1
|
||
,[Integer]]
|
||
|
||
It shows types when there is an unevaluated field in a constructor.
|
||
You can click the ‘[Integer]’ or press ‘RET’ on it to expand further:
|
||
|
||
λ> :present [1..]
|
||
[1
|
||
,2
|
||
,[Integer]]
|
||
|
||
Etc. Remember: this only works for instances of ‘Data.Data.Data’.
|
||
|
||
13.8.8 History
|
||
--------------
|
||
|
||
A history is maintained for the duration of the REPL buffer. To go up
|
||
and down in the history, run ‘M-p’ for previous and ‘M-n’ for next.
|
||
|
||
13.8.9 Cancelling commands
|
||
--------------------------
|
||
|
||
To cancel a running REPL command, run ‘C-c C-c’.
|
||
|
||
13.8.10 Clear the REPL
|
||
----------------------
|
||
|
||
Run ‘C-c C-k’ to clear the REPL.
|
||
|
||
13.8.11 Trick: Put Interactive REPL in Separate Frame
|
||
-----------------------------------------------------
|
||
|
||
The following ‘create-haskell-interactive-frame’ is a quick hack to move
|
||
the repl to a separate frame, for those that want a more predictable
|
||
layout of windows in Emacs.
|
||
|
||
(defun create-unfocused-frame ()
|
||
(let*
|
||
((prv (window-frame))
|
||
(created (make-frame)))
|
||
(select-frame-set-input-focus prv) created))
|
||
|
||
(defun create-haskell-interactive-frame ()
|
||
(interactive)
|
||
(haskell-interactive-bring)
|
||
(create-unfocused-frame)
|
||
(delete-window))
|
||
|
||
|
||
13.8.12 Troubleshooting
|
||
-----------------------
|
||
|
||
If the REPL ever goes funny, you can clear the command queue via:
|
||
|
||
M-x haskell-process-clear
|
||
|
||
Alternatively, you can just restart the process:
|
||
|
||
M-x haskell-process-restart
|
||
|
||
You can also switch to the buffer ‘*haskell-process-log*’, which can
|
||
be enabled and disabled with the customization variable
|
||
‘haskell-process-log‘, to see what the cause of your troubles are.
|
||
|
||
If the process fails and nothing unusual is in the process log, the
|
||
following command can dump the ‘haskell-process’ state:
|
||
|
||
M-: (haskell-process)
|
||
|
||
The output can be copied from the ‘*Messages*’ buffer.
|
||
|
||
13.9 Haskell Interactive Mode Querying
|
||
======================================
|
||
|
||
There a few ways GHCi lets you query information about your code.
|
||
|
||
13.9.1 Get identifer type
|
||
-------------------------
|
||
|
||
To print the type of the top-level identifier at point in the REPL and
|
||
in the message buffer, run the following command:
|
||
|
||
M-x haskell-process-do-type
|
||
|
||
or ‘C-c C-t’.
|
||
|
||
13.9.2 Insert identifier’s type as type signature
|
||
-------------------------------------------------
|
||
|
||
To print the type of the top-level identifier at point, run the
|
||
following command:
|
||
|
||
C-u M-x haskell-process-do-type
|
||
|
||
or ‘C-u C-c C-t’.
|
||
|
||
13.9.3 Get identifier info
|
||
--------------------------
|
||
|
||
To print the info of the identifier at point, run the following command:
|
||
|
||
M-x haskell-process-do-info
|
||
|
||
or ‘C-c C-i’.
|
||
|
||
13.9.4 Presentation mode
|
||
------------------------
|
||
|
||
When using ‘C-c C-i’ or ‘C-c C-t’ it will open a buffer in
|
||
haskell-presentation-mode. You can hit ‘q’ to close the buffer.
|
||
|
||
But you can also continue to use ‘C-c C-i’ inside the buffer to drill
|
||
further down data types and classes.
|
||
|
||
E.g. if you go to ‘Ord’ in your code buffer and ‘C-c C-i’, it will
|
||
popup a buffer containing
|
||
|
||
class Eq a => Ord a where
|
||
compare :: a -> a -> Ordering
|
||
(<) :: a -> a -> Bool
|
||
(>=) :: a -> a -> Bool
|
||
(>) :: a -> a -> Bool
|
||
(<=) :: a -> a -> Bool
|
||
max :: a -> a -> a
|
||
min :: a -> a -> a
|
||
-- Defined in `GHC.Classes'
|
||
|
||
And all the instances of that class. But then you can also move your
|
||
cursor to ‘Ordering’ and hit ‘C-c C-i’ again to get another popup:
|
||
|
||
data Ordering = LT | EQ | GT -- Defined in `GHC.Types'
|
||
instance Bounded Ordering -- Defined in `GHC.Enum'
|
||
instance Enum Ordering -- Defined in `GHC.Enum'
|
||
instance Eq Ordering -- Defined in `GHC.Classes'
|
||
instance Ord Ordering -- Defined in `GHC.Classes'
|
||
instance Read Ordering -- Defined in `GHC.Read'
|
||
instance Show Ordering -- Defined in `GHC.Show'
|
||
|
||
And so on. It’s a very good way of exploring a new codebase.
|
||
|
||
13.9.5 Browse import’s module
|
||
-----------------------------
|
||
|
||
To print all exported identifiers of the module imported by the import
|
||
line at point, run the following command:
|
||
|
||
M-x haskell-process-do-info
|
||
|
||
or ‘C-c C-i’. It will print all exports by running ‘:browse
|
||
The.Module’ in the GHCi process.
|
||
|
||
13.10 Haskell Interactive Mode Cabal integration
|
||
================================================
|
||
|
||
There’s some integration with Cabal in Haskell Interactive Mode. Once
|
||
you’ve started a session, the features below are available.
|
||
|
||
13.10.1 Cabal building
|
||
----------------------
|
||
|
||
The most common Cabal action is building, so that has a specific
|
||
command:
|
||
|
||
M-x haskell-process-cabal-build
|
||
|
||
Or ‘C-c C-c’. When building, it will hide unneccessary output.
|
||
|
||
For example, to build the ‘ace‘ package, the output is simply:
|
||
|
||
Compiling: ACE.Types.Tokens
|
||
Compiling: ACE.Combinators
|
||
Compiling: ACE.Tokenizer
|
||
Compiling: ACE.Parsers
|
||
Compiling: ACE.Pretty
|
||
Compiling: ACE
|
||
Complete: cabal build (0 compiler messages)
|
||
|
||
Whereas the complete output is normally:
|
||
|
||
Building ace-0.5...
|
||
Preprocessing library ace-0.5...
|
||
[4 of 9] Compiling ACE.Types.Tokens ( src/ACE/Types/Tokens.hs, dist/build/ACE/Types/Tokens.o )
|
||
[5 of 9] Compiling ACE.Combinators ( src/ACE/Combinators.hs, dist/build/ACE/Combinators.o ) [ACE.Types.Tokens changed]
|
||
[6 of 9] Compiling ACE.Tokenizer ( src/ACE/Tokenizer.hs, dist/build/ACE/Tokenizer.o ) [ACE.Types.Tokens changed]
|
||
[7 of 9] Compiling ACE.Parsers ( src/ACE/Parsers.hs, dist/build/ACE/Parsers.o )
|
||
[8 of 9] Compiling ACE.Pretty ( src/ACE/Pretty.hs, dist/build/ACE/Pretty.o )
|
||
[9 of 9] Compiling ACE ( src/ACE.hs, dist/build/ACE.o ) [ACE.Tokenizer changed]
|
||
In-place registering ace-0.5...
|
||
|
||
Which is considerably more verbose but rarely useful or interesting.
|
||
|
||
13.10.2 Arbitrary cabal commands
|
||
--------------------------------
|
||
|
||
To run an arbitrary Cabal command:
|
||
|
||
C-u M-x haskell-process-cabal
|
||
|
||
Or run ‘C-u C-c c’.
|
||
|
||
It will prompt for an input, so you can write ‘configure -fdev’, for
|
||
example.
|
||
|
||
13.10.3 Completing cabal commands
|
||
---------------------------------
|
||
|
||
To run some common Cabal commands, just run:
|
||
|
||
M-x haskell-process-cabal
|
||
|
||
Or ‘C-c c’. This is commonly used to do ‘install’, ‘haddock’,
|
||
‘configure’, etc.
|
||
|
||
13.11 Haskell Interactive Mode Debugger
|
||
=======================================
|
||
|
||
There is limited support for debugging in GHCi. Haskell Interactive
|
||
Mode provides an interface for interacting with this.
|
||
|
||
13.11.1 Opening the debug buffer
|
||
--------------------------------
|
||
|
||
To open the debug buffer run the following command from any buffer
|
||
associated with a session:
|
||
|
||
M-x haskell-debug
|
||
|
||
It will open a buffer that looks like this:
|
||
|
||
Debugging haskell
|
||
|
||
You have to load a module to start debugging.
|
||
|
||
g - refresh
|
||
|
||
Modules
|
||
|
||
No loaded modules.
|
||
|
||
13.11.2 Loading modules
|
||
-----------------------
|
||
|
||
To debug anything you need to load something into GHCi. Switch to a
|
||
normal file, for example:
|
||
|
||
main = do putStrLn "Hello!"
|
||
putStrLn "World"
|
||
|
||
and load it into GHCi (‘C-c C-l’). Now when you hit ‘g’ (to refresh)
|
||
in the debugging buffer, you’ll see something like:
|
||
|
||
|
||
Debugging haskell
|
||
|
||
b - breakpoint, g - refresh
|
||
|
||
Context
|
||
|
||
Not debugging right now.
|
||
|
||
Breakpoints
|
||
|
||
No active breakpoints.
|
||
|
||
Modules
|
||
|
||
Main - hello.hs
|
||
|
||
13.11.3 Setting a breakpoint
|
||
----------------------------
|
||
|
||
To set a breakpoint hit ‘b’ in the debugger buffer. It will prompt for
|
||
a name. Enter ‘main’ and hit ‘RET’.
|
||
|
||
Now the buffer will look like this:
|
||
|
||
Debugging haskell
|
||
|
||
s - step into an expression, b - breakpoint
|
||
d - delete breakpoint, g - refresh
|
||
|
||
Context
|
||
|
||
Not debugging right now.
|
||
|
||
Breakpoints
|
||
|
||
0 - Main (1:8)
|
||
|
||
Modules
|
||
|
||
Main - hello.hs
|
||
|
||
13.11.4 Start stepping
|
||
----------------------
|
||
|
||
Hit ‘s’ to step through an expression: it will prompt for an expression
|
||
to evaluate and step through. Enter ‘main’ and hit ‘RET’. Now the
|
||
buffer will look like this:
|
||
|
||
Debugging haskell
|
||
|
||
s - step into an expression, b - breakpoint
|
||
d - delete breakpoint, a - abandon context, c - continue
|
||
p - previous step, n - next step
|
||
g - refresh
|
||
|
||
Context
|
||
|
||
main - hello.hs (stopped)
|
||
|
||
do putStrLn "Hello!"
|
||
putStrLn "World"
|
||
|
||
_result :: IO () = _
|
||
|
||
1 do putStrLn "Hello!" putStrLn "World"
|
||
|
||
Breakpoints
|
||
|
||
0 - Main (1:8)
|
||
|
||
Modules
|
||
|
||
Main - hello.hs
|
||
|
||
What we see here is the current expression being evaluated:
|
||
|
||
do putStrLn "Hello!"
|
||
putStrLn "World"
|
||
|
||
And we see the type of it:
|
||
|
||
_result :: IO () = _
|
||
|
||
And we see a backtrace of steps so far:
|
||
|
||
1 do putStrLn "Hello!" putStrLn "World"
|
||
|
||
13.11.5 Continue stepping
|
||
-------------------------
|
||
|
||
To continue stepping, just hit ‘s’ again. Now the context will change
|
||
to:
|
||
|
||
main - hello.hs (stopped)
|
||
|
||
putStrLn "Hello!"
|
||
|
||
_result :: IO () = _
|
||
|
||
1 do putStrLn "Hello!" putStrLn "World"
|
||
|
||
Hitting ‘s’ once more, we see the context change to:
|
||
|
||
putStrLn "World"
|
||
|
||
_result :: IO () = _
|
||
|
||
2 putStrLn "Hello!"
|
||
1 do putStrLn "Hello!" putStrLn "World"
|
||
|
||
Finally hitting ‘s’ again will say "Computation finished". Hitting
|
||
‘s’ a final time will change the display back to:
|
||
|
||
Debugging haskell
|
||
|
||
s - step into an expression, b - breakpoint
|
||
d - delete breakpoint, g - refresh
|
||
|
||
Context
|
||
|
||
Finished debugging.
|
||
|
||
2 putStrLn "Hello!"
|
||
1 do putStrLn "Hello!" putStrLn "World"
|
||
|
||
Breakpoints
|
||
|
||
1 - Main (1:8)
|
||
|
||
Modules
|
||
|
||
Main - hello.hs
|
||
|
||
And you’re done debugging.
|
||
|
||
|
||
File: haskell-mode.info, Node: Editing Cabal files, Next: Browsing Haddocks, Prev: Interactive Haskell, Up: Top
|
||
|
||
14 Editing Cabal files
|
||
**********************
|
||
|
||
‘haskell-cabal-mode’ is a major mode for editing Cabal package
|
||
description files
|
||
(http://www.haskell.org/cabal/users-guide/developing-packages.html) and
|
||
is automatically associated with files having a ‘.cabal’ extension.
|
||
|
||
For quickly locating and jumping to the nearest ‘.cabal’ file from a
|
||
Haskell source buffer, you can use ‘M-x haskell-cabal-visit-file’; with
|
||
a prefix argument (i.e. ‘C-u’) ‘find-file-other-window’ is used to
|
||
visit the ‘.cabal’ file. ‘haskell-cabal-visit-file’ is bound to the key
|
||
sequence ‘C-c v c’.
|
||
|
||
TODO/WRITEME
|
||
|
||
|
||
File: haskell-mode.info, Node: Browsing Haddocks, Next: Spell checking strings and comments, Prev: Editing Cabal files, Up: Top
|
||
|
||
15 Browsing Haddocks using ‘w3m’
|
||
********************************
|
||
|
||
An experimental feature is use of the w3m browser to browse Haddock docs
|
||
inside Emacs.
|
||
|
||
15.1 Get w3m
|
||
============
|
||
|
||
Most Linux distributions will have a package for the binary:
|
||
|
||
$ sudo apt-get install w3m
|
||
|
||
Now grab ‘w3m.el’ from:
|
||
|
||
• <http://emacs-w3m.namazu.org/>
|
||
• ‘M-x’ ‘package-install’ ‘RET’ ‘w3m’ ‘RET’
|
||
|
||
Confirm installation by trying ‘M-x’ ‘w3m-browse-url’ ‘RET’
|
||
‘haskell.org’ ‘RET’.
|
||
|
||
If this works, you’re good to go.
|
||
|
||
15.2 Configure w3m
|
||
==================
|
||
|
||
Now that you have w3m, you probably want to configure it to be more of a
|
||
passive viewer than a full-fledged browser. For example:
|
||
|
||
(setq w3m-mode-map (make-sparse-keymap))
|
||
|
||
(define-key w3m-mode-map (kbd "RET") 'w3m-view-this-url)
|
||
(define-key w3m-mode-map (kbd "q") 'bury-buffer)
|
||
(define-key w3m-mode-map (kbd "<mouse-1>") 'w3m-maybe-url)
|
||
(define-key w3m-mode-map [f5] 'w3m-reload-this-page)
|
||
(define-key w3m-mode-map (kbd "C-c C-d") 'haskell-w3m-open-haddock)
|
||
(define-key w3m-mode-map (kbd "M-<left>") 'w3m-view-previous-page)
|
||
(define-key w3m-mode-map (kbd "M-<right>") 'w3m-view-next-page)
|
||
(define-key w3m-mode-map (kbd "M-.") 'w3m-haddock-find-tag)
|
||
|
||
(defun w3m-maybe-url ()
|
||
(interactive)
|
||
(if (or (equal '(w3m-anchor) (get-text-property (point) 'face))
|
||
(equal '(w3m-arrived-anchor) (get-text-property (point) 'face)))
|
||
(w3m-view-this-url)))
|
||
|
||
15.3 Import w3m-haddock
|
||
=======================
|
||
|
||
It’s not enabled by default in haskell-mode at present, so you need to
|
||
import it manually:
|
||
|
||
(require 'w3m-haddock)
|
||
|
||
15.4 Add a hook for w3m
|
||
=======================
|
||
|
||
In order to make haddock pages a little more palatable (and add syntax
|
||
highlighting to source view), you can add this hook:
|
||
|
||
(add-hook 'w3m-display-hook 'w3m-haddock-display)
|
||
|
||
It’s a little rough around the edges, but it’s a start.
|
||
|
||
15.5 Configure your package locations
|
||
=====================================
|
||
|
||
By default, the package locations is set to:
|
||
|
||
(defcustom haskell-w3m-haddock-dirs
|
||
'("~/.cabal/share/doc/"))
|
||
|
||
If you are using an hsenv or a custom package directory, you should
|
||
configure this variable with M-x customize-variable or by writing the
|
||
custom-set-variables code for it.
|
||
|
||
15.6 Finally
|
||
============
|
||
|
||
You did all that! Now you’re ready to bind a useful key:
|
||
|
||
(define-key haskell-mode-map (kbd "C-c C-d") 'haskell-w3m-open-haddock)
|
||
|
||
Now when you press ‘C-c’ ‘C-d’ it will prompt for a package to browse
|
||
to.
|
||
|
||
This feature will be improved gradually as time goes on.
|
||
|
||
|
||
File: haskell-mode.info, Node: Spell checking strings and comments, Next: Aligning code, Prev: Browsing Haddocks, Up: Top
|
||
|
||
16 Using with ‘flyspell-prog-mode’
|
||
**********************************
|
||
|
||
Strings and comments can be checked for spelling mistakes. There is a
|
||
standard Emacs mode for this purpose, ‘flyspell-prog-mode’, that can be
|
||
enabled in Haskell buffers. Spelling errors are underlined using
|
||
squiggly red lines.
|
||
|
||
Documentation for ‘flyspell-prog-mode’ can be found in *Note
|
||
(emacs)Spelling::. Here we point to a couple of useful keybindings:
|
||
|
||
• ‘M-$’ - Check and correct spelling of the word at point
|
||
(‘ispell-word’).
|
||
|
||
• ‘digit’ - Replace the word, just this time, with one of the
|
||
displayed near-misses. Each near-miss is listed with a digit; type
|
||
that digit to select it.
|
||
|
||
• ‘SPC’ - Skip this word—continue to consider it incorrect, but don’t
|
||
change it here.
|
||
|
||
To enable spell checking of strings and comments add this line to
|
||
your ‘~/.emacs’ file:
|
||
|
||
‘(add-hook 'haskell-mode-hook 'flyspell-prog-mode)’
|
||
|
||
|
||
File: haskell-mode.info, Node: Aligning code, Next: Rectangular commands, Prev: Spell checking strings and comments, Up: Top
|
||
|
||
17 Aligning code
|
||
****************
|
||
|
||
Select a region you want to align text within, ‘M-x’ ‘align-regexp’, and
|
||
type a regexp representing the alignment delimiter.
|
||
|
||
For example, I often line up my Haddock comments:
|
||
|
||
f :: a -- ^ does a
|
||
-> Foo b -- ^ and b
|
||
-> c -- ^ to c
|
||
|
||
Select the region, and let the regexp be ‘--’:
|
||
|
||
f :: a -- ^ does a
|
||
-> Foo b -- ^ and b
|
||
-> c -- ^ to c
|
||
|
||
Of course, this works for just about anything. Personally, I’ve
|
||
globally bound it to ‘C-x a r’:
|
||
|
||
(global-set-key (kbd "C-x a r") 'align-regexp)
|
||
|
||
Note that you can also just use the rules below for telling the
|
||
aligner about Haskell. Once you evaluate this, you can just use ‘M-x’
|
||
‘align’, which I like to bind to ‘M-[’.
|
||
|
||
(add-to-list 'align-rules-list
|
||
'(haskell-types
|
||
(regexp . "\\(\\s-+\\)\\(::\\|∷\\)\\s-+")
|
||
(modes quote (haskell-mode literate-haskell-mode))))
|
||
(add-to-list 'align-rules-list
|
||
'(haskell-assignment
|
||
(regexp . "\\(\\s-+\\)=\\s-+")
|
||
(modes quote (haskell-mode literate-haskell-mode))))
|
||
(add-to-list 'align-rules-list
|
||
'(haskell-arrows
|
||
(regexp . "\\(\\s-+\\)\\(->\\|→\\)\\s-+")
|
||
(modes quote (haskell-mode literate-haskell-mode))))
|
||
(add-to-list 'align-rules-list
|
||
'(haskell-left-arrows
|
||
(regexp . "\\(\\s-+\\)\\(<-\\|←\\)\\s-+")
|
||
(modes quote (haskell-mode literate-haskell-mode))))
|
||
|
||
|
||
File: haskell-mode.info, Node: Rectangular commands, Next: REPL, Prev: Aligning code, Up: Top
|
||
|
||
18 Using rectangular region commands
|
||
************************************
|
||
|
||
Emacs has a set of commands which operate on the region as if it were
|
||
rectangular. This turns out to be extremely useful when dealing with
|
||
whitespace sensitive languages.
|
||
|
||
• ‘C-x r o’ is "Open Rectangle".
|
||
|
||
It will shift any text within the rectangle to the right side.
|
||
Also see:
|
||
|
||
• ‘C-x r t’ is "String Rectangle".
|
||
|
||
It will replace any text within the rectangle with the given string
|
||
on all the lines in the region. If comment-region didn’t already
|
||
exist, you could use this instead, for example.
|
||
|
||
• ‘C-x r d’ is "Delete Rectangle".
|
||
|
||
It will delete the contents of the rectangle and move anything on
|
||
the right over.
|
||
|
||
• ‘C-x r r’ is "Copy Rectangle to Register".
|
||
|
||
It will prompt you for a register number so it can save it for
|
||
later.
|
||
|
||
• ‘C-x r g’ is "Insert register".
|
||
|
||
This will insert the contents of the given register, overwriting
|
||
whatever happens to be within the target rectangle. (So make room)
|
||
|
||
• ‘C-x r k’ is "Kill rectangle".
|
||
|
||
Delete rectangle and save contents for:
|
||
|
||
• ‘C-x r y’ is "Yank rectangle".
|
||
|
||
This will insert the contents of the last killed rectangle.
|
||
|
||
As with all Emacs modifier combos, you can type ‘C-x r C-h’ to find
|
||
out what keys are bound beginning with the ‘C-x r’ prefix.
|
||
|
||
|
||
File: haskell-mode.info, Node: REPL, Next: Collapsing Haskell code, Prev: Rectangular commands, Up: Top
|
||
|
||
19 Using GHCi REPL within Emacs
|
||
*******************************
|
||
|
||
To start the REPL you can run one of the following:
|
||
|
||
• ‘M-x run-haskell’
|
||
• ‘M-x switch-to-haskell’
|
||
|
||
This repl works with Comint
|
||
(https://www.emacswiki.org/emacs/ComintMode). So you will feel at home
|
||
if you are already using ‘M-x Shell’ or ‘M-x ielm’.
|
||
|
||
‘Inf-Haskell’ is a Major mode for running GHCi, with comint.
|
||
|
||
Important key bindings in ‘Inf-haskell’:
|
||
|
||
‘RET’
|
||
invokes ‘comint-send-input’. Sends the input to the GHCi process,
|
||
evaluates the line and returns the output.
|
||
|
||
‘C-d or <delete>’
|
||
deletes the forward character
|
||
|
||
‘<C-up> or M-p’
|
||
invokes ‘comint-previous-input’. Cycle backwards through input
|
||
history, saving input.
|
||
|
||
‘<C-down> or M-n’
|
||
invokes ‘comint-next-input’. Cycle forwards through input history.
|
||
|
||
‘C-c C-c’
|
||
invokes ‘comint-interrupt-subjob’. Sends KeyboardInterrupt signal.
|
||
|
||
‘C-c C-\’
|
||
invokes ‘comint-quit-subjob’. Sends KeyboardInterrupt signal.
|
||
|
||
‘C-c C-z’
|
||
invokes ‘comint-stop-subjob’. Kills the GHCi process.
|
||
|
||
‘C-c M-r’
|
||
invokes ‘comint-previous-matching-input-from-input’. If you are
|
||
familiar with ‘C-r’ in bash. This is the same as that. Searches
|
||
backwards through input history for match for current input.
|
||
|
||
‘C-c M-s’
|
||
invokes ‘comint-next-matching-input-from-input’. Searches forwards
|
||
through input history for match for current input.
|
||
|
||
‘C-c C-l’
|
||
invokes ‘comint-dynamic-list-input-ring’. Displays a list of
|
||
recent inputs entered into the current buffer.
|
||
|
||
‘C-c M-o’
|
||
invokes ‘comint-clear-buffer’. Clears the buffer (Only with Emacs
|
||
25.X and above)
|
||
|
||
‘C-c C-n’
|
||
invokes ‘comint-next-prompt’. Goes to the start of the previous
|
||
REPL prompt.
|
||
|
||
‘C-c C-p’
|
||
invokes ‘comint-previous-prompt’. Goes to the start of the next
|
||
REPL prompt.
|
||
|
||
‘C-c C-o’
|
||
invokes ‘comint-delete-output’. Clears the output of the most
|
||
recently evaluated expression.
|
||
|
||
‘C-c C-e’
|
||
invokes ‘comint-show-maximum-output’. Moves the point to the end
|
||
of the buffer.
|
||
|
||
‘C-c C-u’
|
||
invokes ‘comint-kill-input’. Kills backward, the line at point.
|
||
(Use this when you have typed in an expression into the prompt but
|
||
you dont want to evaluate it.)
|
||
|
||
‘C-c C-w’
|
||
invokes ‘backward-kill-word’. Kills backward, the word at point
|
||
|
||
‘C-c C-s’
|
||
invokes ‘comint-write-output’. Write output from interpreter since
|
||
last input to FILENAME. Any prompt at the end of the output is not
|
||
written.
|
||
|
||
19.1 Relevant defcustoms:
|
||
=========================
|
||
|
||
Interpreter (defcustom) Default Possible Values
|
||
Value
|
||
---------------------------------------------------------------------------
|
||
‘haskell-process-type’ ‘'auto’ ‘'stack-ghci, 'cabal-repl,
|
||
'ghci, 'auto’
|
||
‘inferior-haskell-hook’ ‘nil’ -
|
||
‘haskell-process-path-ghci’ ‘ghci’ -
|
||
‘haskell-process-args-ghci’ ‘-ferror-spans’-
|
||
‘haskell-process-path-cabal’ ‘cabal’ -
|
||
‘haskell-process-args-cabal-repl’‘--ghc-option=-ferror-spans’-
|
||
‘haskell-process-path-stack’ ‘stack’ -
|
||
‘haskell-process-args-stack-ghci’‘--ghci-options=-ferror-spans-
|
||
--no-build
|
||
--no-load’
|
||
|
||
19.2 More on ‘haskell-process-type’
|
||
===================================
|
||
|
||
The Haskell interpreter used by ‘Inf-Haskell’ is auto-detected by
|
||
default, but is customizable with defcustom ‘haskell-process-type’. The
|
||
values recognized by it are (default is ’auto):
|
||
|
||
• ‘'stack-ghci’
|
||
• ‘'cabal-repl’
|
||
• ‘'ghci’
|
||
• ‘'auto’
|
||
|
||
if the ‘haskell-process-type’ is ‘'auto’, the directories are
|
||
searched for ‘cabal.sandbox.config’ or ‘stack.yaml’ or ‘*.cabal’ file.
|
||
If the file is present, then appropriate process is started.
|
||
|
||
When ‘cabal.sandbox.config’ is found ‘haskell-process-type’ is
|
||
‘'cabal-repl’. Similarly, when ‘stack.yaml’ is found
|
||
‘haskell-process-type’ is ‘'stack-ghci’. Similarly, when ‘xyz.cabal’ is
|
||
found ‘haskell-process-type’ is ‘'cabal-repl’. When nothing is found
|
||
‘haskell-process-type’ is ‘'ghci’. When more than one file such as
|
||
‘cabal.sandbox.config’ and ‘stack.yaml’ are found the following
|
||
preference is followed.
|
||
|
||
‘cabal.sandbox.config’ > ‘stack.yaml’ > ‘*.cabal’
|
||
|
||
|
||
File: haskell-mode.info, Node: Collapsing Haskell code, Next: Getting Help and Reporting Bugs, Prev: REPL, Up: Top
|
||
|
||
20 Collapsing Haskell code
|
||
**************************
|
||
|
||
This is ‘hs-minor-mode’ for ‘haskell-mode’. This module uses hideshow
|
||
module.
|
||
|
||
To activate this minor mode (haskell-collapse-mode)
|
||
• ‘M-x haskell-collapse-mode’ is "To start haskell-collapse-mode".
|
||
This minor mode works with indentation.
|
||
|
||
In a quick glance:
|
||
|
||
‘C-c C-c’
|
||
is bound to ‘haskell-hide-toggle’
|
||
‘C-c C-M-c’
|
||
‘C-c C-M-h’
|
||
‘C-c C-M-s’
|
||
are all bound to ‘haskell-hide-toggle-all’
|
||
|
||
How to use ‘M-x haskell-hide-toggle’?
|
||
|
||
Place your point on the code block that you want to collapse and hit
|
||
the keybinding. Now the code collapses and you can see the first line
|
||
of the block and elipsis.
|
||
|
||
Take this example code (example usage of ‘M-x haskell-hide-toggle’):
|
||
when you place the cursor here, like this (notice the thick block in the
|
||
first line):
|
||
|
||
‘ f█x | rem i 3 == 0 = if i == 0 && (k /= 0) then (c k) else (h j) |
|
||
otherwise = 0 where i = sum x j = g x (div i 3) 0 0 [] k = zeroes x 0 ’
|
||
|
||
or
|
||
|
||
‘ f x | rem i 3 == 0 = if i == 0 && (k /= 0) then (c k) else (h j) █
|
||
| otherwise = 0 where i = sum x j = g x (div i 3) 0 0 [] k = zeroes x 0
|
||
’
|
||
|
||
then when you collapse it becomes something like this:
|
||
|
||
‘ f█x... ’
|
||
|
||
It works in terms of (indentation) blocks.
|
||
|
||
One more example:
|
||
|
||
‘ f x | rem i 3 == 0 = if i == 0 && (k /= 0) then (c k) else (h j) |
|
||
otherwise = 0 w█ere i = sum x j = g x (div i 3) 0 0 [] k = zeroes x 0 ’
|
||
|
||
or
|
||
|
||
‘ f x | rem i 3 == 0 = if i == 0 && (k /= 0) then (c k) else (h j) |
|
||
otherwise = 0 where i = sum x j = g x (div i 3) 0 0 [] █ k = zeroes x 0
|
||
’
|
||
|
||
this, will result in something like:
|
||
|
||
‘ f x | rem i 3 == 0 = if i == 0 && (k /= 0) then (c k) else (h j) |
|
||
otherwise = 0 where i = sum █... ’
|
||
|
||
The other functionality ‘M-x haskell-hide-toggle-all’ also works only
|
||
for indentation and it collapses all toplevel functions.
|
||
|
||
So a file that looks like this:
|
||
|
||
main = interact $ show.f. map read .words
|
||
f (x:xs) = dp x xs
|
||
|
||
dp money a | money < 0 || null a = [1..1000]
|
||
dp 0 a = []
|
||
dp money a @ (coin:coins)
|
||
| (length i) <= length j = i
|
||
| otherwise = j
|
||
where i = (coin:(dp (money-coin) a))
|
||
j = (dp money coins)
|
||
|
||
will turn into this:
|
||
|
||
main = interact $ show.f. map read .words
|
||
f (x:xs) = dp x xs
|
||
|
||
dp money a | money < 0 || null a = [1..1000]
|
||
dp 0 a = []
|
||
dp money a @ (coin:coins)...
|
||
|
||
|
||
File: haskell-mode.info, Node: Getting Help and Reporting Bugs, Next: Concept index, Prev: Collapsing Haskell code, Up: Top
|
||
|
||
21 Getting Help and Reporting Bugs
|
||
**********************************
|
||
|
||
Work on Haskell Mode is organized with Github ‘haskell-mode’ project.
|
||
To understand how the project is run please read the information in the
|
||
project wiki pages (https://github.com/haskell/haskell-mode/wiki).
|
||
|
||
To report any issues please use the Github’s issue mechanism
|
||
available from Haskell Mode’s GitHub Home
|
||
(https://github.com/haskell/haskell-mode).
|
||
|
||
For a quick question visit ‘#haskell-emacs’ channel on IRC
|
||
‘irc.freenode.net’.
|
||
|
||
There is also a (now defunct) Haskellmode-emacs mailing list
|
||
(http://projects.haskell.org/cgi-bin/mailman/listinfo/haskellmode-emacs),
|
||
also available on Gmane (http://gmane.org/) via the
|
||
gmane.comp.lang.haskell.emacs
|
||
(http://dir.gmane.org/gmane.comp.lang.haskell.emacs) newsgroup.
|
||
|
||
We welcome code and non-code contributions so that we can all enjoy
|
||
coding Haskell even more.
|
||
|
||
|
||
File: haskell-mode.info, Node: Concept index, Next: Function index, Prev: Getting Help and Reporting Bugs, Up: Top
|
||
|
||
Concept index
|
||
*************
|
||
|
||
|