├── .gitignore ├── tests └── indent │ ├── test009 │ ├── test.hs │ ├── expected.hs │ └── test.vim │ ├── test014 │ ├── test.hs │ ├── test.vim │ └── expected.hs │ ├── test010 │ ├── test.hs │ ├── test.vim │ └── expected.hs │ ├── test013 │ ├── expected.hs │ ├── test.hs │ └── test.vim │ ├── test017 │ ├── test.hs │ ├── test.vim │ └── expected.hs │ ├── test001 │ ├── test.vim │ ├── test.hs │ └── expected.hs │ ├── test002 │ ├── test.vim │ ├── test.hs │ └── expected.hs │ ├── test007 │ ├── test.vim │ ├── test.hs │ └── expected.hs │ ├── test008 │ ├── test.vim │ ├── test.hs │ └── expected.hs │ ├── test011 │ ├── test.vim │ ├── test.hs │ └── expected.hs │ ├── test012 │ ├── test.vim │ ├── expected.hs │ └── test.hs │ ├── test015 │ ├── test.hs │ ├── expected.hs │ └── test.vim │ ├── test018 │ ├── test.vim │ ├── test.hs │ └── expected.hs │ ├── test004 │ ├── test.hs │ ├── test.vim │ └── expected.hs │ ├── test005 │ ├── test.vim │ ├── test.hs │ └── expected.hs │ ├── test006 │ ├── test.vim │ ├── test.hs │ └── expected.hs │ ├── test019 │ ├── test.hs │ ├── test.vim │ └── expected.hs │ ├── test016 │ ├── test.vim │ ├── test.hs │ └── expected.hs │ ├── test003 │ ├── test.vim │ ├── test.hs │ └── expected.hs │ └── run.sh ├── after └── ftplugin │ ├── haskell.vim │ └── cabal.vim ├── ftdetect └── haskell.vim ├── indent ├── cabal.vim └── haskell.vim ├── LICENSE ├── syntax ├── cabal.vim └── haskell.vim ├── README.md └── doc └── haskell-vim.txt /.gitignore: -------------------------------------------------------------------------------- 1 | tags 2 | -------------------------------------------------------------------------------- /tests/indent/test009/test.hs: -------------------------------------------------------------------------------- 1 | let x = 2 | -------------------------------------------------------------------------------- /tests/indent/test014/test.hs: -------------------------------------------------------------------------------- 1 | foo :: Monad m 2 | -------------------------------------------------------------------------------- /tests/indent/test009/expected.hs: -------------------------------------------------------------------------------- 1 | let x = 2 | 123 3 | -------------------------------------------------------------------------------- /tests/indent/test010/test.hs: -------------------------------------------------------------------------------- 1 | SomeRecord { name = ")" 2 | -------------------------------------------------------------------------------- /tests/indent/test013/expected.hs: -------------------------------------------------------------------------------- 1 | -- 2 | type F k = [k] 3 | -------------------------------------------------------------------------------- /tests/indent/test013/test.hs: -------------------------------------------------------------------------------- 1 | -- 2 | type F k = [k] 3 | -------------------------------------------------------------------------------- /tests/indent/test017/test.hs: -------------------------------------------------------------------------------- 1 | where countUntilClosed (x:xs) 2 | -------------------------------------------------------------------------------- /tests/indent/test001/test.vim: -------------------------------------------------------------------------------- 1 | =G 2 | :saveas! result.hs 3 | :q! 4 | -------------------------------------------------------------------------------- /tests/indent/test002/test.vim: -------------------------------------------------------------------------------- 1 | =G 2 | :saveas! result.hs 3 | :q! 4 | -------------------------------------------------------------------------------- /tests/indent/test007/test.vim: -------------------------------------------------------------------------------- 1 | =G 2 | :saveas! result.hs 3 | :q! 4 | -------------------------------------------------------------------------------- /tests/indent/test008/test.vim: -------------------------------------------------------------------------------- 1 | =G 2 | :saveas! result.hs 3 | :q! 4 | -------------------------------------------------------------------------------- /tests/indent/test011/test.vim: -------------------------------------------------------------------------------- 1 | =G 2 | :saveas! result.hs 3 | :q! 4 | -------------------------------------------------------------------------------- /tests/indent/test012/test.vim: -------------------------------------------------------------------------------- 1 | =G 2 | :saveas! result.hs 3 | :q! 4 | -------------------------------------------------------------------------------- /tests/indent/test013/test.vim: -------------------------------------------------------------------------------- 1 | =G 2 | :saveas! result.hs 3 | :q! 4 | -------------------------------------------------------------------------------- /tests/indent/test015/test.hs: -------------------------------------------------------------------------------- 1 | f x = y 2 | where 3 | y = 2 * x 4 | -------------------------------------------------------------------------------- /tests/indent/test018/test.vim: -------------------------------------------------------------------------------- 1 | G== 2 | :saveas! result.hs 3 | :q! 4 | -------------------------------------------------------------------------------- /tests/indent/test004/test.hs: -------------------------------------------------------------------------------- 1 | foo = 2 | { field = bar "(" 3 | } 4 | -------------------------------------------------------------------------------- /tests/indent/test005/test.vim: -------------------------------------------------------------------------------- 1 | ja  2 | :saveas! result.hs 3 | :q! 4 | -------------------------------------------------------------------------------- /tests/indent/test006/test.vim: -------------------------------------------------------------------------------- 1 | obar 2 | :saveas! result.hs 3 | :q! 4 | -------------------------------------------------------------------------------- /tests/indent/test009/test.vim: -------------------------------------------------------------------------------- 1 | o123 2 | :saveas! result.hs 3 | :q! 4 | -------------------------------------------------------------------------------- /tests/indent/test010/test.vim: -------------------------------------------------------------------------------- 1 | o,  2 | :saveas! result.hs 3 | :q! 4 | -------------------------------------------------------------------------------- /tests/indent/test011/test.hs: -------------------------------------------------------------------------------- 1 | add1 x = x + y 2 | where 3 | y = 1 4 | -------------------------------------------------------------------------------- /tests/indent/test017/test.vim: -------------------------------------------------------------------------------- 1 | o| x 2 | :saveas! result.hs 3 | :q! 4 | -------------------------------------------------------------------------------- /tests/indent/test019/test.hs: -------------------------------------------------------------------------------- 1 | foo x 2 | | x == x = True 3 | 4 | -------------------------------------------------------------------------------- /tests/indent/test010/expected.hs: -------------------------------------------------------------------------------- 1 | SomeRecord { name = ")" 2 | , 3 | -------------------------------------------------------------------------------- /tests/indent/test011/expected.hs: -------------------------------------------------------------------------------- 1 | add1 x = x + y 2 | where 3 | y = 1 4 | -------------------------------------------------------------------------------- /tests/indent/test015/expected.hs: -------------------------------------------------------------------------------- 1 | f x = y 2 | where 3 | y = 2 * x 4 | -------------------------------------------------------------------------------- /tests/indent/test016/test.vim: -------------------------------------------------------------------------------- 1 | Gofoo x = x 2 | :saveas! result.hs 3 | :q! 4 | -------------------------------------------------------------------------------- /tests/indent/test004/test.vim: -------------------------------------------------------------------------------- 1 | jo, quux = "" 2 | :saveas! result.hs 3 | :q! 4 | -------------------------------------------------------------------------------- /tests/indent/test006/test.hs: -------------------------------------------------------------------------------- 1 | foo = doSomething 123 -- Do something important. 2 | -------------------------------------------------------------------------------- /tests/indent/test017/expected.hs: -------------------------------------------------------------------------------- 1 | where countUntilClosed (x:xs) 2 | | x 3 | -------------------------------------------------------------------------------- /tests/indent/test019/test.vim: -------------------------------------------------------------------------------- 1 | Go| o ,o =  2 | :saveas! result.hs 3 | :q! 4 | -------------------------------------------------------------------------------- /tests/indent/test003/test.vim: -------------------------------------------------------------------------------- 1 | 2jfIi{-# UNPACK #-} ! 2 | :saveas! result.hs 3 | :q! 4 | -------------------------------------------------------------------------------- /tests/indent/test004/expected.hs: -------------------------------------------------------------------------------- 1 | foo = 2 | { field = bar "(" 3 | , quux = "" 4 | } 5 | -------------------------------------------------------------------------------- /tests/indent/test018/test.hs: -------------------------------------------------------------------------------- 1 | let foo = 1 2 | bar = baz 3 | quux 4 | in 5 | -------------------------------------------------------------------------------- /tests/indent/test002/test.hs: -------------------------------------------------------------------------------- 1 | -- | This is a function. 2 | fun -- this shouldn't be indented 3 | -------------------------------------------------------------------------------- /tests/indent/test006/expected.hs: -------------------------------------------------------------------------------- 1 | foo = doSomething 123 -- Do something important. 2 | bar 3 | -------------------------------------------------------------------------------- /tests/indent/test018/expected.hs: -------------------------------------------------------------------------------- 1 | let foo = 1 2 | bar = baz 3 | quux 4 | in 5 | -------------------------------------------------------------------------------- /after/ftplugin/haskell.vim: -------------------------------------------------------------------------------- 1 | setlocal comments=s1fl:{-,mb:\ \ ,ex:-},:-- 2 | setlocal iskeyword+=' 3 | -------------------------------------------------------------------------------- /tests/indent/test002/expected.hs: -------------------------------------------------------------------------------- 1 | -- | This is a function. 2 | fun -- this shouldn't be indented 3 | -------------------------------------------------------------------------------- /tests/indent/test005/test.hs: -------------------------------------------------------------------------------- 1 | [ (NS spotify spotify (className =? "Spotify") doFullFloat ) 2 | ,] 3 | -------------------------------------------------------------------------------- /tests/indent/test001/test.hs: -------------------------------------------------------------------------------- 1 | data Foo = Foo 2 | { foo :: Int 3 | -- comment 4 | , bar :: Int 5 | } 6 | -------------------------------------------------------------------------------- /tests/indent/test003/test.hs: -------------------------------------------------------------------------------- 1 | data Test = Test 2 | { x :: {-# UNPACK #-} !Int 3 | , y :: Int 4 | } 5 | -------------------------------------------------------------------------------- /tests/indent/test005/expected.hs: -------------------------------------------------------------------------------- 1 | [ (NS spotify spotify (className =? "Spotify") doFullFloat ) 2 | , ] 3 | -------------------------------------------------------------------------------- /tests/indent/test012/expected.hs: -------------------------------------------------------------------------------- 1 | add2 x = let y = 1 2 | z = 1 3 | in = x + y + z 4 | -------------------------------------------------------------------------------- /tests/indent/test012/test.hs: -------------------------------------------------------------------------------- 1 | add2 x = let y = 1 2 | z = 1 3 | in = x + y + z 4 | -------------------------------------------------------------------------------- /tests/indent/test001/expected.hs: -------------------------------------------------------------------------------- 1 | data Foo = Foo 2 | { foo :: Int 3 | -- comment 4 | , bar :: Int 5 | } 6 | -------------------------------------------------------------------------------- /tests/indent/test014/test.vim: -------------------------------------------------------------------------------- 1 | o=> Functor m => MonadIO m -> Int foo x = x 2 | :saveas! result.hs 3 | :q! 4 | -------------------------------------------------------------------------------- /tests/indent/test014/expected.hs: -------------------------------------------------------------------------------- 1 | foo :: Monad m 2 | => Functor m 3 | => MonadIO m 4 | -> Int 5 | foo x = x 6 | -------------------------------------------------------------------------------- /tests/indent/test003/expected.hs: -------------------------------------------------------------------------------- 1 | data Test = Test 2 | { x :: {-# UNPACK #-} !Int 3 | , y :: {-# UNPACK #-} !Int 4 | } 5 | -------------------------------------------------------------------------------- /tests/indent/test016/test.hs: -------------------------------------------------------------------------------- 1 | where 2 | foo :: Monad m 3 | => Functor m 4 | => MonadIO m 5 | -> Int 6 | -------------------------------------------------------------------------------- /tests/indent/test019/expected.hs: -------------------------------------------------------------------------------- 1 | foo x 2 | | x == x = True 3 | 4 | | 5 | 6 | , 7 | 8 | = 9 | -------------------------------------------------------------------------------- /after/ftplugin/cabal.vim: -------------------------------------------------------------------------------- 1 | setlocal comments=s1fl:{-,mb:-,ex:-},:-- 2 | setlocal iskeyword+=-,.,* 3 | setlocal commentstring=--\ %s 4 | -------------------------------------------------------------------------------- /tests/indent/test008/test.hs: -------------------------------------------------------------------------------- 1 | data Foo 2 | = Foo 3 | { foo :: Int 4 | , bar :: Char 5 | , baz :: Int 6 | } deriving (Eq, Ord) 7 | -------------------------------------------------------------------------------- /tests/indent/test016/expected.hs: -------------------------------------------------------------------------------- 1 | where 2 | foo :: Monad m 3 | => Functor m 4 | => MonadIO m 5 | -> Int 6 | foo x = x 7 | -------------------------------------------------------------------------------- /tests/indent/test008/expected.hs: -------------------------------------------------------------------------------- 1 | data Foo 2 | = Foo 3 | { foo :: Int 4 | , bar :: Char 5 | , baz :: Int 6 | } deriving (Eq, Ord) 7 | -------------------------------------------------------------------------------- /tests/indent/test015/test.vim: -------------------------------------------------------------------------------- 1 | :set sw=4 2 | :let g:haskell_indent_before_where=2 3 | :let g:haskell_indent_after_bare_where=2 4 | =G 5 | :saveas! result.hs 6 | :q! 7 | -------------------------------------------------------------------------------- /ftdetect/haskell.vim: -------------------------------------------------------------------------------- 1 | au BufRead,BufNewFile *.hsc set filetype=haskell 2 | au BufRead,BufNewFile *.bpk set filetype=haskell 3 | au BufRead,BufNewFile *.hsig set filetype=haskell 4 | -------------------------------------------------------------------------------- /tests/indent/test007/test.hs: -------------------------------------------------------------------------------- 1 | data Customer = Customer 2 | { customerID :: CustomerID 3 | , customerName :: String 4 | , customerAddress :: Address 5 | } deriving (Show) 6 | -------------------------------------------------------------------------------- /tests/indent/test007/expected.hs: -------------------------------------------------------------------------------- 1 | data Customer = Customer 2 | { customerID :: CustomerID 3 | , customerName :: String 4 | , customerAddress :: Address 5 | } deriving (Show) 6 | -------------------------------------------------------------------------------- /tests/indent/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | for i in test???; do 4 | cd $i 5 | nvim --headless -s test.vim test.hs 2> /dev/null 6 | diff expected.hs result.hs 7 | if [ $? -eq 0 ]; then 8 | echo "$(basename $PWD) succeded" 9 | rm result.hs 10 | else 11 | echo "$(basename $PWD) failed" 12 | fi 13 | cd .. 14 | done 15 | -------------------------------------------------------------------------------- /indent/cabal.vim: -------------------------------------------------------------------------------- 1 | " indentation for cabal 2 | " 3 | " author: raichoo (raichoo@googlemail.com) 4 | " 5 | if exists('b:did_indent') 6 | finish 7 | endif 8 | 9 | let b:did_indent = 1 10 | 11 | if !exists('g:cabal_indent_section') 12 | "executable name 13 | ">>main-is: Main.hs 14 | ">>hs-source-dirs: src 15 | let g:cabal_indent_section = 2 16 | elseif exists('g:cabal_indent_section') && g:cabal_indent_section > 4 17 | let g:cabal_indent_section = 4 18 | endif 19 | 20 | setlocal indentexpr=GetCabalIndent() 21 | setlocal indentkeys=!^F,o,O, 22 | 23 | function! GetCabalIndent() 24 | let l:prevline = getline(v:lnum - 1) 25 | 26 | if l:prevline =~ '\C^\(executable\|library\|flag\|source-repository\|test-suite\|benchmark\)' 27 | return g:cabal_indent_section 28 | else 29 | return match(l:prevline, '\S') 30 | endif 31 | endfunction 32 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014, raichoo 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 5 | 6 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | 8 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 9 | 10 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 11 | -------------------------------------------------------------------------------- /syntax/cabal.vim: -------------------------------------------------------------------------------- 1 | " syntax highlighting for cabal 2 | " 3 | " author: raichoo (raichoo@googlemail.com) 4 | 5 | if version < 600 6 | syn clear 7 | elseif exists("b:current_syntax") 8 | finish 9 | endif 10 | 11 | syn match cabalLineComment "---*\([^-!#$%&\*\+./<=>\?@\\^|~].*\)\?$" contains=@Spell 12 | syn match cabalIdentifier "[A-Za-z\-]*" contained 13 | syn match cabalOperator "[<=>&|!]" 14 | syn match cabalColon ":" contained 15 | syn match cabalNumber "\<[0-9][0-9\.*]*\>" 16 | syn match cabalDelimiter "[,()]" 17 | syn keyword cabalBool True False 18 | syn keyword cabalConditional if else 19 | syn match cabalCompilerFlag "\s\+-[^ -][^ ]*" 20 | syn match cabalDocBulletPoint "^\s\+\*" 21 | syn match cabalDocHeadline "^\s\+=.*$" 22 | syn match cabalDocCode "^\s\+>.*$" 23 | syn match cabalDocNewline "^\s\+\.\s*$" 24 | syn match cabalSection "^\c\(executable\|library\|flag\|source-repository\|test-suite\|benchmark\|common\)" 25 | syn match cabalEntry "^\s*[A-Za-z][a-zA-Z\-]*:" contains=cabalIdentifier,cabalColon 26 | 27 | syn region cabalDescription start="^\s*[dD]escription:" end="^\<" keepend 28 | \ contains= 29 | \ cabalEntry, 30 | \ cabalLineComment, 31 | \ cabalDocBulletPoint, 32 | \ cabalDocHeadline, 33 | \ cabalDocNewline, 34 | \ cabalDocCode 35 | 36 | highlight def link cabalIdentifier Identifier 37 | highlight def link cabalLineComment Comment 38 | highlight def link cabalOperator Operator 39 | highlight def link cabalColon Operator 40 | highlight def link cabalNumber Number 41 | highlight def link cabalSection Structure 42 | highlight def link cabalDelimiter Delimiter 43 | highlight def link cabalBool Boolean 44 | highlight def link cabalCompilerFlag Macro 45 | highlight def link cabalConditional Conditional 46 | highlight def link cabalDocBulletPoint Structure 47 | highlight def link cabalDocHeadline Include 48 | highlight def link cabalDocNewline Operator 49 | highlight def link cabalDocCode Macro 50 | 51 | let b:current_syntax = "cabal" 52 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Syntax Highlighting and Indentation for Haskell and Cabal 2 | ========================================================= 3 | 4 | I was unhappy with the Haskell scripts that are 5 | shipped with vim, therefore I decided to make my 6 | own based on [idris-vim][]. 7 | 8 | I hope you find this useful. 9 | 10 | ![Screenshot](http://raichoo.github.io/images/haskell-vim.png) 11 | 12 | ## Features 13 | 14 | * Covers a broader spectrum of keywords 15 | * Highlighting for new features like type families, pattern synonyms, arrow syntax, recursive do, role annotations, QuasiQuotation 16 | * More contextual highlighting (e.g. highlight 'as' or 'family' only in appropriate places) 17 | * Smarter indentation 18 | * Better Cabal support 19 | 20 | ## Installation 21 | 22 | I recommend using [Pathogen][] for installation. Simply clone 23 | this repo into your `~/.vim/bundle` directory and you are ready to go. 24 | 25 | cd ~/.vim/bundle 26 | git clone https://github.com/neovimhaskell/haskell-vim.git 27 | 28 | Be sure that the following lines are in your 29 | `.vimrc` 30 | 31 | 32 | syntax on 33 | filetype plugin indent on 34 | 35 | ### Manual Installation 36 | 37 | Copy content into your `~/.vim` directory. 38 | 39 | ## Configuration 40 | 41 | ### Features 42 | 43 | To enable the features you would like to use, just add the according line to your 44 | `.vimrc`. 45 | 46 | ```viml 47 | let g:haskell_enable_quantification = 1 " to enable highlighting of `forall` 48 | let g:haskell_enable_recursivedo = 1 " to enable highlighting of `mdo` and `rec` 49 | let g:haskell_enable_arrowsyntax = 1 " to enable highlighting of `proc` 50 | let g:haskell_enable_pattern_synonyms = 1 " to enable highlighting of `pattern` 51 | let g:haskell_enable_typeroles = 1 " to enable highlighting of type roles 52 | let g:haskell_enable_static_pointers = 1 " to enable highlighting of `static` 53 | let g:haskell_backpack = 1 " to enable highlighting of backpack keywords 54 | ``` 55 | 56 | ### Highlighting 57 | 58 | `haskell-vim` has an opinionated highlighting. If you do not like that you can switch to 59 | a more traditional mode by setting `g:haskell_classic_highlighting` to `1`. 60 | 61 | Disabling Template Haskell and Quasiquoting syntax is possible by setting 62 | `g:haskell_disable_TH` to `1`. 63 | 64 | ### Indentation 65 | 66 | To configure indentation in `haskell-vim` you can use the following variables to change indentation depth, just add the according line to your `.vimrc`. 67 | 68 | If you dislike how indentation works you can disable it by setting `g:haskell_indent_disable` to 69 | `1`. 70 | 71 | Additionally you can use the 72 | [vim-hindent](https://github.com/alx741/vim-hindent) plugin to achieve automatic 73 | indentation using *hindent*. 74 | 75 | #### Haskell 76 | 77 | * `let g:haskell_indent_if = 3` 78 | 79 | if bool 80 | >>>then ... 81 | >>>else ... 82 | 83 | * `let g:haskell_indent_case = 2` 84 | 85 | case xs of 86 | >>[] -> ... 87 | >>(y:ys) -> ... 88 | 89 | * `let g:haskell_indent_let = 4` 90 | 91 | let x = 0 in 92 | >>>>x 93 | 94 | * `let g:haskell_indent_where = 6` 95 | 96 | where f :: Int -> Int 97 | >>>>>>f x = x 98 | 99 | * `let g:haskell_indent_before_where = 2` 100 | 101 | foo 102 | >>where 103 | 104 | * `let g:haskell_indent_after_bare_where = 2` 105 | 106 | where 107 | >>foo 108 | 109 | * `let g:haskell_indent_do = 3` 110 | 111 | do x <- a 112 | >>>y <- b 113 | 114 | * `let g:haskell_indent_in = 1` 115 | 116 | let x = 1 117 | >in x 118 | 119 | * `let g:haskell_indent_guard = 2` 120 | 121 | f x y 122 | >>| 123 | 124 | `haskell-vim` also supports an alterative style for `case` indentation. 125 | 126 | * `let g:haskell_indent_case_alternative = 1` 127 | 128 | f xs ys = case xs of 129 | >>[] -> ... 130 | >>(y:ys) -> ... 131 | 132 | 133 | #### Cabal 134 | 135 | * `let g:cabal_indent_section = 2` (limited to max. 4 spaces) 136 | 137 | executable name 138 | >>main-is: Main.hs 139 | 140 | 141 | [Pathogen]: https://github.com/tpope/vim-pathogen 142 | [idris-vim]: https://github.com/idris-hackers/idris-vim 143 | -------------------------------------------------------------------------------- /doc/haskell-vim.txt: -------------------------------------------------------------------------------- 1 | *haskell-vim.txt* Last Change 2016 March 14 2 | =============================================================================== 3 | =============================================================================== 4 | 5 | =============================================================================== 6 | CONTENTS *haskell-vim-contents* 7 | 8 | 1. Features |haskell-vim-features| 9 | 2. Configuration |haskell-vim-configuration| 10 | 3. Highlighting |haskell-vim-indentation| 11 | 12 | =============================================================================== 13 | FEATURES *haskell-vim-features* 14 | 15 | * Covers a broader spectrum of keywords 16 | * Highlighting for new features like type families, pattern synonyms, 17 | arrow syntax, recursive do, role annotations, QuasiQuotation 18 | * More contextual highlighting 19 | (e.g. highlight "as" or "family" only in appropriate places) 20 | * Smarter indentation 21 | * Better Cabal support 22 | 23 | =============================================================================== 24 | CONFIGURATION *haskell-vim-configuration* 25 | 26 | To enable the features you would like to use, just add the according line to 27 | your `.vimrc`. 28 | 29 | =============================================================================== 30 | HIGHLIGHTING *haskell-vim-highlighting* 31 | 32 | `haskell-vim` can highlight additional keywords. This is enabled by setting 33 | the according variable to 1 in the `.vimrc`. 34 | 35 | * |haskell-vim-enable-quantification| 36 | * |haskell-vim-enable-recursivedo| 37 | * |haskell-vim-enable-arrowsyntax| 38 | * |haskell-vim-enable-pattern-synonyms| 39 | * |haskell-vim-enable-typeroles| 40 | * |haskell-vim-enable-static-pointers| 41 | * |haskell-vim-classic-highlighting| 42 | * |haskell-vim-disable-TH| 43 | 44 | *haskell-vim-enable-quantification* 45 | `g:haskell_enable_quantification` Enables highlighting of `forall`. 46 | 47 | *haskell-vim-enable-recursivedo* 48 | `g:haskell_enable_recursivedo` Enables highlighting of `mdo` and `rec`. 49 | 50 | *haskell-vim-enable-arrowsyntax* 51 | `g:haskell_enable_arrowsyntax` Enables highlighting of `proc`. 52 | 53 | *haskell-vim-enable-pattern-synonyms* 54 | `g:haskell_enable_pattern_synonyms` Enables highlighting of the `pattern` keyword. 55 | 56 | *haskell-vim-enable-typeroles* 57 | `g:haskell_enable_typeroles` Enables highlighting of the `role` keyword, as 58 | well as `phantom`, `norminal` and 59 | `representational`. 60 | 61 | *haskell-vim-enable-static-pointers* 62 | `g:haskell_enable_static_pointers` Enables highlighting of the `static` keyword. 63 | 64 | *haskell-vim-classic-highlighting* 65 | `haskell-vim` has an opinionated highlighting. If you do not like that you can 66 | switch to a more traditional mode by setting `g:haskell_classic_highlighting` 67 | to 1. 68 | 69 | *haskell-vim-disable-TH* 70 | Disabling Template Haskell and Quasiquoting syntax is possible by setting 71 | `g:haskell_disable_TH` to `1`. 72 | 73 | =============================================================================== 74 | INDENTATION *haskell-vim-indentation* 75 | 76 | To configure indentation in `haskell-vim` you can use the following variables to 77 | change indentation depth, just add the according line to your `.vimrc`. 78 | 79 | You can disable the indentation by setting `g:haskell_indent_disable` to `1`. 80 | 81 | Haskell~ 82 | 83 | * |haskell-vim-indent-if| 84 | * |haskell-vim-indent-case| 85 | * |haskell-vim-indent-let| 86 | * |haskell-vim-indent-where| 87 | * |haskell-vim-indent-before-where| 88 | * |haskell-vim-indent-after-bare-where| 89 | * |haskell-vim-indent-do| 90 | * |haskell-vim-indent-in| 91 | * |haskell-vim-indent-guard| 92 | *haskell-vim-indent-if* 93 | * let g:haskell_indent_if = 3 > 94 | 95 | if bool 96 | >>>then ... 97 | >>>else ... 98 | < 99 | 100 | *haskell-vim-indent-case* 101 | * let g:haskell_indent_case = 2 > 102 | 103 | case xs of 104 | >>[] -> ... 105 | >>(y:ys) -> ... 106 | < 107 | *haskell-vim-indent-let* 108 | * let g:haskell_indent_let = 4 > 109 | 110 | let x = 0 in 111 | >>>>x 112 | < 113 | *haskell-vim-indent-where* 114 | * let g:haskell_indent_where = 6 > 115 | 116 | where f :: Int -> Int 117 | >>>>>>f x = x 118 | < 119 | *haskell-vim-indent-before-where* 120 | * let g:haskell_indent_before_where = 2 > 121 | 122 | foo 123 | >>where 124 | < 125 | *haskell-vim-indent-after-bare-where* 126 | * let g:haskell_indent_after_bare_where = 2 > 127 | 128 | where 129 | >>foo 130 | < 131 | *haskell-vim-indent-do* 132 | * let g:haskell_indent_do = 3 > 133 | 134 | do x <- a 135 | >>>y <- b 136 | < 137 | *haskell-vim-indent-in* 138 | * let g:haskell_indent_in = 1 > 139 | 140 | let x = 1 141 | >in x 142 | < 143 | *haskell-vim-indent-guard* 144 | * let g:haskell_indent_guard = 2 > 145 | 146 | f x y 147 | >>| 148 | < 149 | 150 | Cabal~ 151 | 152 | * |cabal-vim-indent-section| 153 | 154 | *cabal-vim-indent-section* 155 | * let g:cabal_indent_section = 2 (limited to max. 4 spaces) > 156 | 157 | executable name 158 | >>main-is: Main.hs 159 | < 160 | -------------------------------------------------------------------------------- /syntax/haskell.vim: -------------------------------------------------------------------------------- 1 | " syntax highlighting for haskell 2 | " 3 | " Heavily modified version of the haskell syntax 4 | " highlighter to support haskell. 5 | " 6 | " author: raichoo (raichoo@googlemail.com) 7 | 8 | if version < 600 9 | syn clear 10 | elseif exists("b:current_syntax") 11 | finish 12 | endif 13 | 14 | if get(g:, 'haskell_backpack', 0) 15 | syn keyword haskellBackpackStructure unit signature 16 | syn keyword haskellBackpackDependency dependency 17 | endif 18 | 19 | syn spell notoplevel 20 | syn match haskellRecordField contained containedin=haskellBlock 21 | \ "[_a-z][a-zA-Z0-9_']*\(,\s*[_a-z][a-zA-Z0-9_']*\)*\_s\+::\_s" 22 | \ contains= 23 | \ haskellIdentifier, 24 | \ haskellOperators, 25 | \ haskellSeparator, 26 | \ haskellParens 27 | syn match haskellTypeSig 28 | \ "^\s*\(where\s\+\|let\s\+\|default\s\+\)\?[_a-z][a-zA-Z0-9_']*#\?\(,\s*[_a-z][a-zA-Z0-9_']*#\?\)*\_s\+::\_s" 29 | \ contains= 30 | \ haskellWhere, 31 | \ haskellLet, 32 | \ haskellDefault, 33 | \ haskellIdentifier, 34 | \ haskellOperators, 35 | \ haskellSeparator, 36 | \ haskellParens 37 | syn keyword haskellWhere where 38 | syn keyword haskellLet let 39 | syn keyword haskellDeriveKeyword deriving anyclass instance newtype stock via contained 40 | syn match haskellDerive "deriving\(\s\+instance\)\?\(\s\+anyclass\|\s\+newtype\|\s\+stock\|\s\+.\{-}\_s\+via\)\?" 41 | \ contains= 42 | \ haskellDeriveKeyword, 43 | \ haskellParens, 44 | \ haskellType 45 | syn keyword haskellDeclKeyword module class instance newtype in 46 | syn match haskellDecl "\<\(type\|data\)\>\s\+\(\\)\?" 47 | syn keyword haskellDefault default 48 | syn keyword haskellImportKeywords import qualified safe as hiding contained 49 | syn keyword haskellForeignKeywords foreign export import ccall safe unsafe interruptible capi prim contained 50 | syn region haskellForeignImport start="\" end="\_s\+::\s" keepend 51 | \ contains= 52 | \ haskellString, 53 | \ haskellOperators, 54 | \ haskellForeignKeywords, 55 | \ haskellIdentifier 56 | syn match haskellImport "^\s*\\s\+\(\\s\+\)\?\(\\s\+\)\?.\+\(\s\+\\s\+.\+\)\?\(\s\+\\)\?" 57 | \ contains= 58 | \ haskellParens, 59 | \ haskellOperators, 60 | \ haskellImportKeywords, 61 | \ haskellType, 62 | \ haskellLineComment, 63 | \ haskellBlockComment, 64 | \ haskellString, 65 | \ haskellPragma 66 | syn keyword haskellKeyword do case of 67 | if get(g:, 'haskell_enable_static_pointers', 0) 68 | syn keyword haskellStatic static 69 | endif 70 | syn keyword haskellConditional if then else 71 | syn match haskellNumber "\<[0-9]\+\>\|\<[0-9_]\+\>\|\<0[xX][0-9a-fA-F_]\+\>\|\<0[oO][0-7_]\+\>\|\<0[bB][10_]\+\>" 72 | syn match haskellFloat "\<[0-9]\+\.[0-9_]\+\([eE][-+]\=[0-9_]\+\)\=\>" 73 | syn match haskellSeparator "[,;]" 74 | syn region haskellParens matchgroup=haskellDelimiter start="(" end=")" contains=TOP,haskellTypeSig,@Spell 75 | syn region haskellBrackets matchgroup=haskellDelimiter start="\[" end="]" contains=TOP,haskellTypeSig,@Spell 76 | syn region haskellBlock matchgroup=haskellDelimiter start="{" end="}" contains=TOP,@Spell 77 | syn keyword haskellInfix infix infixl infixr 78 | syn keyword haskellBottom undefined error 79 | syn match haskellOperators "[-!#$%&\*\+/<=>\?@\\^|~:.]\+\|\<_\>" 80 | syn match haskellQuote "\<'\+" contained 81 | syn match haskellQuotedType "[A-Z][a-zA-Z0-9_']*\>" contained 82 | syn region haskellQuoted start="\<'\+" end="\>" 83 | \ contains= 84 | \ haskellType, 85 | \ haskellQuote, 86 | \ haskellQuotedType, 87 | \ haskellSeparator, 88 | \ haskellParens, 89 | \ haskellOperators, 90 | \ haskellIdentifier 91 | syn match haskellLineComment "---*\([^-!#$%&\*\+./<=>\?@\\^|~].*\)\?$" 92 | \ contains= 93 | \ haskellTodo, 94 | \ @Spell 95 | syn match haskellBacktick "`[A-Za-z_][A-Za-z0-9_\.']*#\?`" 96 | syn region haskellString start=+"+ skip=+\\\\\|\\"+ end=+"+ 97 | \ contains=@Spell 98 | syn match haskellIdentifier "[_a-z][a-zA-Z0-9_']*" contained 99 | syn match haskellChar "\<'[^'\\]'\|'\\.'\|'\\u[0-9a-fA-F]\{4}'\>" 100 | syn match haskellType "\<[A-Z][a-zA-Z0-9_']*\>" 101 | syn region haskellBlockComment start="{-" end="-}" 102 | \ contains= 103 | \ haskellBlockComment, 104 | \ haskellTodo, 105 | \ @Spell 106 | syn region haskellPragma start="{-#" end="#-}" 107 | syn region haskellLiquid start="{-@" end="@-}" 108 | syn match haskellPreProc "^#.*$" 109 | syn keyword haskellTodo TODO FIXME contained 110 | " Treat a shebang line at the start of the file as a comment 111 | syn match haskellShebang "\%^#!.*$" 112 | if !get(g:, 'haskell_disable_TH', 0) 113 | syn match haskellQuasiQuoted "." containedin=haskellQuasiQuote contained 114 | syn region haskellQuasiQuote matchgroup=haskellTH start="\[[_a-zA-Z][a-zA-Z0-9._']*|" end="|\]" 115 | syn region haskellTHBlock matchgroup=haskellTH start="\[\(d\|t\|p\)\?|" end="|]" contains=TOP 116 | syn region haskellTHDoubleBlock matchgroup=haskellTH start="\[||" end="||]" contains=TOP 117 | endif 118 | if get(g:, 'haskell_enable_typeroles', 0) 119 | syn keyword haskellTypeRoles phantom representational nominal contained 120 | syn region haskellTypeRoleBlock matchgroup=haskellTypeRoles start="type\s\+role" end="$" keepend 121 | \ contains= 122 | \ haskellType, 123 | \ haskellTypeRoles 124 | endif 125 | if get(g:, 'haskell_enable_quantification', 0) 126 | syn keyword haskellForall forall 127 | endif 128 | if get(g:, 'haskell_enable_recursivedo', 0) 129 | syn keyword haskellRecursiveDo mdo rec 130 | endif 131 | if get(g:, 'haskell_enable_arrowsyntax', 0) 132 | syn keyword haskellArrowSyntax proc 133 | endif 134 | if get(g:, 'haskell_enable_pattern_synonyms', 0) 135 | syn keyword haskellPatternKeyword pattern 136 | endif 137 | 138 | highlight def link haskellBottom Macro 139 | highlight def link haskellTH Boolean 140 | highlight def link haskellIdentifier Identifier 141 | highlight def link haskellForeignKeywords Structure 142 | highlight def link haskellKeyword Keyword 143 | highlight def link haskellDefault Keyword 144 | highlight def link haskellConditional Conditional 145 | highlight def link haskellNumber Number 146 | highlight def link haskellFloat Float 147 | highlight def link haskellSeparator Delimiter 148 | highlight def link haskellDelimiter Delimiter 149 | highlight def link haskellInfix Keyword 150 | highlight def link haskellOperators Operator 151 | highlight def link haskellQuote Operator 152 | highlight def link haskellShebang Comment 153 | highlight def link haskellLineComment Comment 154 | highlight def link haskellBlockComment Comment 155 | highlight def link haskellPragma SpecialComment 156 | highlight def link haskellLiquid SpecialComment 157 | highlight def link haskellString String 158 | highlight def link haskellChar String 159 | highlight def link haskellBacktick Operator 160 | highlight def link haskellQuasiQuoted String 161 | highlight def link haskellTodo Todo 162 | highlight def link haskellPreProc PreProc 163 | highlight def link haskellAssocType Type 164 | highlight def link haskellQuotedType Type 165 | highlight def link haskellType Type 166 | highlight def link haskellImportKeywords Include 167 | if get(g:, 'haskell_classic_highlighting', 0) 168 | highlight def link haskellDeclKeyword Keyword 169 | highlight def link haskellDeriveKeyword Keyword 170 | highlight def link haskellDecl Keyword 171 | highlight def link haskellWhere Keyword 172 | highlight def link haskellLet Keyword 173 | else 174 | highlight def link haskellDeclKeyword Structure 175 | highlight def link haskellDeriveKeyword Structure 176 | highlight def link haskellDecl Structure 177 | highlight def link haskellWhere Structure 178 | highlight def link haskellLet Structure 179 | endif 180 | 181 | if get(g:, 'haskell_enable_quantification', 0) 182 | highlight def link haskellForall Operator 183 | endif 184 | if get(g:, 'haskell_enable_recursivedo', 0) 185 | highlight def link haskellRecursiveDo Keyword 186 | endif 187 | if get(g:, 'haskell_enable_arrowsyntax', 0) 188 | highlight def link haskellArrowSyntax Keyword 189 | endif 190 | if get(g:, 'haskell_enable_static_pointers', 0) 191 | highlight def link haskellStatic Keyword 192 | endif 193 | if get(g:, 'haskell_classic_highlighting', 0) 194 | if get(g:, 'haskell_enable_pattern_synonyms', 0) 195 | highlight def link haskellPatternKeyword Keyword 196 | endif 197 | if get(g:, 'haskell_enable_typeroles', 0) 198 | highlight def link haskellTypeRoles Keyword 199 | endif 200 | else 201 | if get(g:, 'haskell_enable_pattern_synonyms', 0) 202 | highlight def link haskellPatternKeyword Structure 203 | endif 204 | if get(g:, 'haskell_enable_typeroles', 0) 205 | highlight def link haskellTypeRoles Structure 206 | endif 207 | endif 208 | 209 | if get(g:, 'haskell_backpack', 0) 210 | highlight def link haskellBackpackStructure Structure 211 | highlight def link haskellBackpackDependency Include 212 | endif 213 | let b:current_syntax = "haskell" 214 | -------------------------------------------------------------------------------- /indent/haskell.vim: -------------------------------------------------------------------------------- 1 | " indentation for haskell 2 | " 3 | " author: raichoo (raichoo@googlemail.com) 4 | " 5 | " Modify g:haskell_indent_if and g:haskell_indent_case to 6 | " change indentation for `if'(default 3) and `case'(default 5). 7 | " Example (in .vimrc): 8 | " > let g:haskell_indent_if = 2 9 | 10 | if exists('b:did_indent') 11 | finish 12 | endif 13 | 14 | if get(g:, 'haskell_indent_disable', 0) 15 | finish 16 | endif 17 | 18 | let b:did_indent = 1 19 | 20 | if !exists('g:haskell_indent_if') 21 | " if x 22 | " >>>then ... 23 | " >>>else ... 24 | let g:haskell_indent_if = 3 25 | endif 26 | 27 | if !exists('g:haskell_indent_case') 28 | " case xs of 29 | " >>[] -> ... 30 | " >>(y:ys) -> ... 31 | let g:haskell_indent_case = 2 32 | endif 33 | 34 | if !exists('g:haskell_indent_let') 35 | " let x = 0 in 36 | " >>>>x 37 | " 38 | " let x = 0 39 | " y = 1 40 | let g:haskell_indent_let = 4 41 | endif 42 | 43 | if !exists('g:haskell_indent_where') 44 | " where f :: Int -> Int 45 | " >>>>>>f x = x 46 | let g:haskell_indent_where = 6 47 | endif 48 | 49 | if !exists('g:haskell_indent_do') 50 | " do x <- a 51 | " >>>y <- b 52 | let g:haskell_indent_do = 3 53 | endif 54 | 55 | if !exists('g:haskell_indent_in') 56 | " let x = 1 57 | " >in x 58 | let g:haskell_indent_in = 1 59 | endif 60 | 61 | if !exists('g:haskell_indent_guard') 62 | " f x y 63 | " >>| 64 | let g:haskell_indent_guard = 2 65 | endif 66 | 67 | setlocal indentexpr=GetHaskellIndent() 68 | setlocal indentkeys=!^F,o,O,0{,0},0(,0),0[,0],0,,0=where,0=let,0=deriving,0=in\ ,0=::\ ,0=\-\>\ ,0=\=\>\ ,0=\|\ ,=\=\ 69 | 70 | function! s:isInBlock(hlstack) 71 | return index(a:hlstack, 'haskellDelimiter') > -1 || index(a:hlstack, 'haskellParens') > -1 || index(a:hlstack, 'haskellBrackets') > -1 || index(a:hlstack, 'haskellBlock') > -1 || index(a:hlstack, 'haskellBlockComment') > -1 || index(a:hlstack, 'haskellPragma') > -1 72 | endfunction 73 | 74 | function! s:stripComment(line) 75 | if a:line =~ '^\s*--\(-*\s\+\|$\)' 76 | return '' 77 | else 78 | let l:stripped = split(a:line, '-- ') 79 | if len(l:stripped) > 1 80 | return substitute(l:stripped[0], '\s*$', '', '') 81 | else 82 | return a:line 83 | endif 84 | endif 85 | endfunction 86 | 87 | function! s:isSYN(grp, line, col) 88 | return index(s:getHLStack(a:line, a:col), a:grp) != -1 89 | endfunction 90 | 91 | function! s:getNesting(hlstack) 92 | return filter(a:hlstack, 'v:val == "haskellBlock" || v:val == "haskellBrackets" || v:val == "haskellParens" || v:val == "haskellBlockComment" || v:val == "haskellPragma" ') 93 | endfunction 94 | 95 | function! s:getHLStack(line, col) 96 | return map(synstack(a:line, a:col), 'synIDattr(v:val, "name")') 97 | endfunction 98 | 99 | " indent matching character 100 | function! s:indentMatching(char) 101 | normal! 0 102 | call search(a:char, 'cW') 103 | normal! % 104 | return col('.') - 1 105 | endfunction 106 | 107 | " backtrack to find guard clause 108 | function! s:indentGuard(pos, prevline) 109 | let l:l = a:prevline 110 | let l:c = v:lnum - 1 111 | let l:s = indent(l:c) 112 | 113 | while l:c >= 1 114 | if l:s == 0 && strlen(l:l) > 0 115 | " top-level start, stop looking 116 | return g:haskell_indent_guard 117 | elseif l:l =~ '^\s\+[|,=]\s\+' 118 | " guard block found 119 | return match(l:l, '[|,=]') 120 | else 121 | if l:s > 0 && l:s <= a:pos 122 | " found less deeper indentation (not starting with `,` or `=`) 123 | " stop looking 124 | return l:s + g:haskell_indent_guard 125 | endif 126 | endif 127 | let l:c -= 1 128 | let l:l = getline(l:c) 129 | let l:s = indent(l:c) 130 | endwhile 131 | 132 | return -1 133 | endfunction 134 | 135 | function! GetHaskellIndent() 136 | let l:hlstack = s:getHLStack(line('.'), col('.')) 137 | 138 | " do not indent in strings and quasiquotes 139 | if index(l:hlstack, 'haskellQuasiQuote') > -1 || index(l:hlstack, 'haskellBlockComment') > -1 140 | return -1 141 | endif 142 | 143 | let l:prevline = s:stripComment(getline(v:lnum - 1)) 144 | let l:line = getline(v:lnum) 145 | 146 | " indent multiline strings 147 | if index(l:hlstack, 'haskellString') > -1 148 | if l:line =~ '^\s*\\' 149 | return match(l:prevline, '["\\]') 150 | else 151 | return - 1 152 | endif 153 | endif 154 | 155 | " reset 156 | if l:prevline =~ '^\s*$' && l:line !~ '^\s*\S' 157 | return 0 158 | endif 159 | 160 | " { foo :: Int 161 | " >>, 162 | " 163 | " | 164 | " ... 165 | " >>, 166 | if l:line =~ '^\s*,' 167 | if s:isInBlock(s:getHLStack(line('.'), col('.'))) 168 | normal! 0 169 | call search(',', 'cW') 170 | let l:n = s:getNesting(s:getHLStack(line('.'), col('.'))) 171 | call search('[([{]', 'bW') 172 | let l:cl = line('.') 173 | let l:cc = col('.') 174 | 175 | while l:n != s:getNesting(s:getHLStack(l:cl, l:cc)) || s:isSYN('haskellString', l:cl, l:cc) || s:isSYN('haskellChar', l:cl, l:cc) 176 | call search('[([{]', 'bW') 177 | let l:cl = line('.') 178 | let l:cc = col('.') 179 | endwhile 180 | 181 | return l:cc - 1 182 | else 183 | let l:s = s:indentGuard(match(l:line, ','), l:prevline) 184 | if l:s > -1 185 | return l:s 186 | end 187 | endif 188 | endif 189 | 190 | " operator at end of previous line 191 | if l:prevline =~ '[!#$%&*+./<>?@\\^|~-]\s*$' 192 | return indent(v:lnum - 1) + shiftwidth() 193 | endif 194 | 195 | " let foo = 196 | " >>>>>>bar 197 | if l:prevline =~ '\C\\s\+[^=]\+=\s*$' 198 | return match(l:prevline, '\C\') + g:haskell_indent_let + shiftwidth() 199 | endif 200 | 201 | " let x = 1 in 202 | " >>>>x 203 | if l:prevline =~ '\C\.\{-}\\s*$' && l:line !~ '\C^\s*\' 204 | return match(l:prevline, '\C\') + g:haskell_indent_let 205 | endif 206 | 207 | " let x = 1 208 | " let y = 2 209 | " 210 | " let x = 1 211 | " >>>>y = 2 212 | " 213 | " let x = 1 214 | " y 2 215 | if l:prevline =~ '\C\\s\+.\+$' 216 | if l:line =~ '\C^\s*\' 217 | let l:s = match(l:prevline, '\C\') 218 | if s:isSYN('haskellLet', v:lnum - 1, l:s + 1) 219 | return l:s 220 | endif 221 | elseif l:line =~ '\s=\s' 222 | let l:s = match(l:prevline, '\C\') 223 | if s:isSYN('haskellLet', v:lnum - 1, l:s + 1) 224 | return l:s + g:haskell_indent_let 225 | endif 226 | endif 227 | endif 228 | 229 | " if handling 230 | if l:prevline !~ '\C\' 231 | let l:s = match(l:prevline, '\C\.*\&.*\zs\') 232 | if l:s > 0 233 | return l:s 234 | endif 235 | 236 | let l:s = match(l:prevline, '\C\') 237 | if l:s > 0 238 | return l:s + g:haskell_indent_if 239 | endif 240 | endif 241 | 242 | " where 243 | " >>foo 244 | " 245 | if l:prevline =~ '\C\\s*$' 246 | return indent(v:lnum - 1) + get(g:, 'haskell_indent_after_bare_where', shiftwidth()) 247 | endif 248 | 249 | " do 250 | " >>foo 251 | " 252 | " foo = 253 | " >>bar 254 | if l:prevline =~ '\C\(\\|=\)\s*$' 255 | return indent(v:lnum - 1) + shiftwidth() 256 | endif 257 | 258 | " do foo 259 | " >>>bar 260 | if l:prevline =~ '\C\\s\+\S\+.*$' 261 | let l:s = match(l:prevline, '\C\') 262 | if s:isSYN('haskellKeyword', v:lnum - 1, l:s + 1) 263 | return l:s + g:haskell_indent_do 264 | endif 265 | endif 266 | 267 | " case foo of 268 | " >>bar -> quux 269 | if l:prevline =~ '\C\.\+\\s*$' 270 | if get(g:,'haskell_indent_case_alternative', 0) 271 | return indent(v:lnum - 1) + shiftwidth() 272 | else 273 | return match(l:prevline, '\C\') + g:haskell_indent_case 274 | endif 275 | endif 276 | 277 | "" where foo 278 | "" >>>>>>bar 279 | "" 280 | "" where foo :: Int 281 | "" >>>>>>>>>>-> Int 282 | "" 283 | "" where foo x 284 | "" >>>>>>>>| 285 | if l:prevline =~ '\C\\s\+\S\+.*$' 286 | if l:line =~ '^\s*[=-]>\s' && l:prevline =~ ' :: ' 287 | return match(l:prevline, ':: ') 288 | elseif l:line =~ '^\s*|\s' 289 | let l:s = match(l:prevline, '\C\') 290 | if s:isSYN('haskellWhere', v:lnum - 1, l:s + 1) 291 | return l:s + g:haskell_indent_where + g:haskell_indent_guard 292 | endif 293 | else 294 | let l:s = match(l:prevline, '\C\') 295 | if s:isSYN('haskellWhere', v:lnum - 1, l:s + 1) 296 | return l:s + g:haskell_indent_where 297 | endif 298 | endif 299 | endif 300 | 301 | " newtype Foo = Foo 302 | " >>deriving 303 | if l:prevline =~ '\C^\s*\<\(newtype\|data\)\>[^{]\+' && l:line =~ '\C^\s*\' 304 | return indent(v:lnum - 1) + shiftwidth() 305 | endif 306 | 307 | " foo :: Int 308 | " >>>>-> Int 309 | " 310 | " foo 311 | " :: Int 312 | " foo 313 | if l:prevline =~ '\s::\s' 314 | if l:line =~ '^\s*[-=]>' 315 | return match(l:prevline, '::\s') 316 | elseif match(l:prevline, '^\s\+::') > -1 317 | return match(l:prevline, '::\s') - shiftwidth() 318 | endif 319 | endif 320 | 321 | " foo :: Int 322 | " -> Int 323 | " >>>>-> Int 324 | " 325 | " foo :: Monad m 326 | " => Functor f 327 | " >>>>=> Int 328 | " 329 | " foo :: Int 330 | " -> Int 331 | " foo x 332 | " 333 | " foo 334 | " :: Int 335 | " -> Int 336 | " foo x 337 | if l:prevline =~ '^\s*[-=]>' 338 | if l:line =~ '^\s*[-=]>' 339 | return match(l:prevline, '[-=]') 340 | else 341 | if s:isInBlock(l:hlstack) 342 | return match(l:prevline, '[^-=]') 343 | else 344 | let l:m = matchstr(l:line, '^\s*\zs\<\S\+\>\ze') 345 | let l:l = l:prevline 346 | let l:c = v:lnum - 1 347 | 348 | while l:c >= 1 349 | " fun decl 350 | if l:l =~ ('^\s*' . l:m . '\(\s*::\|\n\s\+::\)') 351 | let l:s = match(l:l, l:m) 352 | if match(l:l, '\C^\s*\') > -1 353 | return l:s - 8 354 | else 355 | return l:s 356 | endif 357 | " empty line, stop looking 358 | elseif l:l =~ '^$' 359 | return 0 360 | endif 361 | let l:c -= 1 362 | let l:l = getline(l:c) 363 | endwhile 364 | 365 | return 0 366 | endif 367 | endif 368 | endif 369 | 370 | " | otherwise = ... 371 | " foo 372 | " 373 | " | foo 374 | " >>, bar 375 | " 376 | " | foo 377 | " >>= bar 378 | " 379 | " | Foo 380 | " >>deriving 381 | if l:prevline =~ '^\s\+|' && !s:isInBlock(l:hlstack) 382 | if l:line =~ '\s*[,=]' 383 | return match(l:prevline, '|') 384 | elseif l:line =~ '\C^\s*\' 385 | return match(l:prevline, '|') 386 | elseif l:line !~ '^\s*|' 387 | return match(l:prevline, '|') - g:haskell_indent_guard 388 | endif 389 | endif 390 | 391 | " foo :: ( Monad m 392 | " , Functor f 393 | " ) 394 | ">>>>>=> Int 395 | if l:prevline =~ '^\s*)' && l:line =~ '^\s*=>' 396 | let l:s = match(l:prevline, ')') 397 | return l:s - (shiftwidth() + 1) 398 | endif 399 | 400 | " module Foo 401 | " >>( bar 402 | if l:prevline =~ '\C^\' 403 | return shiftwidth() 404 | endif 405 | 406 | " foo 407 | " >>{ 408 | if l:line =~ '^\s*{' 409 | let l:s = indent(v:lnum - 1) 410 | if l:s >= 0 411 | return l:s + shiftwidth() 412 | endif 413 | endif 414 | 415 | " in foo 416 | " where bar 417 | " 418 | " or 419 | " 420 | " foo 421 | " >>where 422 | if l:line =~ '\C^\s*\' 423 | if match(l:prevline, '\C^\s\+in\s\+') == 0 424 | return match(l:prevline, 'in') - g:haskell_indent_in 425 | endif 426 | 427 | return indent(v:lnum - 1) + get(g:, 'haskell_indent_before_where', shiftwidth()) 428 | endif 429 | 430 | " let x = 1 431 | " y = 2 432 | " >in x + 1 433 | if l:line =~ '\C^\s*\' 434 | let l:s = 0 435 | let l:c = v:lnum - 1 436 | 437 | while l:s <= 0 && l:c >= 1 438 | let l:l = getline(l:c) 439 | let l:s = match(l:l, '\C\') 440 | if l:s >= 1 && s:isSYN('haskellLet', l:c, l:s + 1) 441 | break 442 | elseif l:l =~ '^\S' 443 | return -1 444 | endif 445 | let l:c -= 1 446 | endwhile 447 | return l:s + g:haskell_indent_in 448 | endif 449 | 450 | " data Foo 451 | " >>= Bar 452 | " 453 | " | 454 | " ... 455 | " >>= 456 | " 457 | " foo 458 | " >>= 459 | if l:line =~ '^\s*=' 460 | if l:prevline =~ '\C^\\s\+[^=]\+\s*$' 461 | return match(l:prevline, '\C\') + shiftwidth() 462 | else 463 | let l:s = s:indentGuard(match(l:line, '='), l:prevline) 464 | if l:s > 0 465 | return l:s 466 | else 467 | return shiftwidth() 468 | endif 469 | endif 470 | endif 471 | 472 | " | 473 | " ... 474 | " >>| 475 | " 476 | " data Foo = Bar 477 | " >>>>>>>>>| 478 | if l:line =~ '^\s*|\s' 479 | if l:prevline =~ '\C^\s*\.\+=.\+$' 480 | return match(l:prevline, '=') 481 | else 482 | let l:s = s:indentGuard(match(l:line, '|'), l:prevline) 483 | if l:s > -1 484 | return l:s 485 | endif 486 | endif 487 | endif 488 | 489 | " foo 490 | " >>:: Int 491 | if l:line =~ '^\s*::\s' 492 | return indent(v:lnum - 1) + shiftwidth() 493 | endif 494 | 495 | " indent closing brace, paren or bracket 496 | if l:line =~ '^\s*}' 497 | return s:indentMatching('}') 498 | endif 499 | 500 | if l:line =~ '^\s*)' 501 | return s:indentMatching(')') 502 | endif 503 | 504 | if l:line =~ '^\s*]' 505 | return s:indentMatching(']') 506 | endif 507 | 508 | return -1 509 | endfunction 510 | --------------------------------------------------------------------------------