This guide covers our recommended options for FLO (Free/Libre/Open) text-editors and IDE development tools for hacking on Snowdrift (NB: most of this applies equally to any Yesod-based project).
NB: notice the section about jumping to definitions. It's down a ways.
Atom is a modern, graphical, highly-extensible text-editor,
good for beginners and advanced alike.
We recommend installing the atom-haskell
package and then following the
Binaries section of atom-haskell's README,
choosing brittany
as the beautifier. Please note the blurb about
atom-hasklig
above Quick configuration. NB: these "packages" are Atom
plugins, not distro packages.
For more thorough doc, see the official Atom-Haskell documentation.
NB: provided we have stack.yaml
right, you should be able to ignore any blurb
boxes about specific versions of GHC / lts.
Some general settings:
- In the main Atom settings, leave soft tabs checked and set 4-space tabs.
- Packages/Tree View: consider "Hide Ignored Names" and "Hide VCS Ignored Files".
- Various Git-related tools:
- tree-view-git-status
- git-blame
- show-origin
- search the packages for other git tools worth considering
- Built-in terminal: platformio-ide-terminal
- "Ergonomic" improvements like move-tab-or-split
- vim-mode-plus (if you like vim style editing)
- consider the Clipboard as Default Register and Smartcase Search options
- incidentally, many normal Atom editing operations still work as well
- search packages for "vim-mode" to see extra related addons
- General nice tools like minimap, cursor-history, clipboard-history, multi-cursor
GNU Emacs is a traditional, robust, keyboard-centric text editor with substantial Haskell support.
If you are new to Emacs, Emacs Prelude is an enhanced distribution of Emacs with better default configuration. It includes things like Helm and Projectile by default.
If you are coming from Vim, consider Spacemacs, an Emacs distribution that includes Vim's modal keybindings by default along with much of Prelude's default configuration. Aside from Spacemacs, you can get the Vim keybindings in any Emacs distribution using evil-mode.
Our included .dir-locals.el
file
makes Emacs use
the recommended 4-space indentation.
Emacs users should install Haskell Mode and Shakespeare Mode.
Also of interest:
-
Magit is a high-quality Emacs git interface.
-
Structured Haskell Mode (same author as Haskell Mode) takes a lot of tedium out of Haskell editing.
-
HIndent (same author again) will pretty-print your Haskell-code along the same lines as SHM.
-
Hare automates renaming and changing among different Haskell code styles.
-
Haskell Interactive Mode will enable automatic regeneration of the TAGS file. (Our .dir-locals.el file tells haskell-interactive-mode to do that)
Leksah is a Haskell-dedicated complete IDE in the works, but we're waiting for integration with Stack before we fully recommend it.
Vim is a robust traditional editor with a command-line style interface and great Haskell support.
Note: we recommend all vim users install vim-gtk
to enable access to system
clipboards, regardless of then using terminal-based vim or the gvim interface
with visual menus.
For working on our code, your ~/.vimrc file should include:
set textwidth=80 expandtab shiftwidth=4 tabstop=4
au FileType hamlet setl sw=2 sts=2 et
au Filetype gitcommit setl spell textwidth=72
We also recommend the following minimal .vimrc settings:
set number title hlsearch ignorecase smartcase showbreak=↪
set wildmenu wildmode=longest,list,full
We recommend vim-plug for managing Vim plugins.
For syntax highlighting, we suggest everyone use the following plugins:
- vim-syntax-shakespeare
- vim-yesod
- add to ~/.vimrc:
let g:yesod_handlers_directories = ['Handler', 'src']
- add to ~/.vimrc:
- haskell-vim
- vim-markdown
- vim2hs
- optional: add
set nofoldenable
to .vimrc to stop vim2hs function folding
- optional: add
Given already using vim-plug, these are the lines to use in ~/.vimrc for the items above:
Plug 'pbrisbin/vim-syntax-shakespeare', { 'for': ['hamlet', 'cassius', 'julius', 'haskell'] }
Plug 'plasticboy/vim-markdown', { 'for': 'markdown' }
Plug 'neovimhaskell/haskell-vim', { 'for': 'haskell' }
Plug 'dag/vim2hs', { 'for': 'haskell' }
au FileType haskell set nofoldenable "stops vim2hs folding
For advanced Haskell error-checking and type information, install ghc-mod.
- Note: after many changes to snowdrift build process and file structure, ghc-mod may or may not work, testing is needed. Once working, the instructions are still as follows:
To set up ghc-mod, run stack install ghc-mod
(and make sure ~/.local/bin is on
your path). Then, add ghcmod-vim and
neco-ghc as well; for installation
via vim-plug, use these lines in ~/.vimrc:
Plug 'eagletmt/ghcmod-vim', { 'for': 'haskell' }
Plug 'eagletmt/neco-ghc', { 'for': 'haskell' }
Plug 'Shougo/vimproc.vim', {'do': 'make', 'for': 'haskell' } "neco-ghc dependency
" Disable haskell-vim omnifunc per neco-ghc recommendation
let g:haskellmode_completion_ghc = 0
autocmd FileType haskell setlocal omnifunc=necoghc#omnifunc
To have ghc-mod auto-check for errors on open or save, add syntastic and set it up as desired.
Another great Haskell tool: vim-HaRe
NB: to get HaRe itself, use stack install HaRe
instead of cabal install.
General vim plugins:
Other general vim plugins we suggest for consideration include many which are inobtrusive and take zero or near-zero learning to use (roughly in order by most strongly recommended):
- vim-sensible,
- vim-repeat,
- vim-supertab,
- ctrl-P,
- Recover.vim,
- vim-gitgutter,
- vim-surround,
- vim-commentary,
- vim-easyclip (NB: vim-easyclip alters common vim behavior),
- undotree,
- vim-fugitive,
- gitv,
- NERD tree &
- NERD tree git plugin;
- ack.vim
(NB: ack.vim requires system install of
ack-grep
orsilversearch-ag
), - vim-airline.
Many other options exist, although we'd rather contributors generally focus more on building Snowdrift than maximizing their Vim expertise.
NB: Stackage will have documentation on almost all of our dependencies, i.e., code that is not in the Snowdrift repo, but is used by the repo. Thus you may only want the ability to jump to definitions made in the repo, using online Stackage doc for the rest.
Alternatively, you may enable lookup ability for all Haskell terms used in the repo to hopefully stay in your text editor more, switching to a web browser less.
The following works for all text-editors that recognize tags files.
-
run
stack install hasktags
(and make sure ~/.local/bin is in your path) -
In the snowdrift directory, run this big command to generate your tags file:
git ls-tree -r HEAD --name-only | grep -E '*.hs' | xargs hasktags -x -c --ignore-close-implementation
- That command works for Atom, Vim, and other ctags-based editors.
- For Emacs, change
-x -c
to-e
For edification, that long command is a pipeline that finds all committed files in the git repository, filters to just the Haskell ones, and passes those for tag processing (technically, there are other types of Haskell files, such as *.hsc and *.lhs, but we don't have them in Snowdrift.)
For convenience, you can edit ~/.bashrc and add a line to make an alias for the long command above, as in:
alias git-hasktags="git ls-tree -r HEAD --name-only | grep -E '*.hs' | xargs hasktags -x -c --ignore-close-implementation"
To auto-update whenever you check out a new branch, put the command into .git/hooks/post-checkout and make the hook file executable:
cat >> .git/hooks/post-checkout <<EOF git ls-tree -r HEAD --name-only | grep -E '*.hs' | xargs hasktags -x -c --ignore-close-implementation EOF chmod u+x .git/hooks/post-checkout
Now, you can quickly jump to tags with whatever mechanism your text editor uses.
Simply run dev-tools/tag.sh
.
The tagging script uses Codex. You may wish to visit Codex's homepage to see its usage doc, which includes a vim-specific setting.
With tags generated, Atom uses Ctrl-Shift-R to search for any tag, Ctrl-Alt-Down to jump to the definition of the symbol under the cursor, and Ctrl-Alt-Up to return (with vim-mode, Ctrl-] and Ctrl-t also work).
We hope to document how to auto-update tags whenever saving files in Atom, but
until we have that clear, you'll need to manually re-run git-hasktags
(set as
alias in instructions above) as needed.
If you use Helm, as recommended above, you can run M-x helm-etags-select
to
select from the TAGS
file.
If you use haskell-interactive-mode, linked above, Emacs will automatically
regenerate the TAGS file for you (provided you have loaded a file with C-c C-l
beforehand). If you don't want to use haskell-interactive-mode for whatever
reason, you can generate the tags file with:
git ls-tree -r HEAD --name-only | grep -E '*.hs' | xargs hasktags -e --ignore-close-implementation
M-t
is a good keybinding for helm-etags-select
, provided you don't use
transpose-words
:
(global-set-key (kbd "M-t") 'helm-etags-select)
With a tags file in place, Vim can jump to the definition of the symbol under the cursor with Ctrl-] and jump back with Ctrl-t. Also, when typing in insert mode, Ctrl-x followed by Ctrl-] will offer autocompletion for known tags.
To auto-update tags in Vim whenever a Haskell file gets written, use fast-tags:
-
run
stack install fast-tags
-
add an autocommand to the Haskell plugin file:
mkdir -p ~/.vim/after/ftplugin cat >> ~/.vim/after/ftplugin/haskell.vim <<EOF augroup fasttag autocmd! autocmd BufWritePost <buffer> silent !fast-tags % augroup END EOF
NB: so that we don't generate extra tags files in internal directories, make sure to only open vim from the main snowdrift project directory from now on.