├── .vader ├── README.md ├── demo.gif ├── plugin └── haskell-refactor.vim └── vader-tests.png /.vader: -------------------------------------------------------------------------------- 1 | Given haskell (Setup with function example): 2 | f = if n > 3 then 3 else n 3 | 4 | Do (Highlight text and run ExtractHaskellFuncton): 5 | o\k 6 | 03w 7 | vwe 8 | :ExtractHaskellFunction g n\ 9 | 10 | Expect haskell (ExtractHaskellFunction extracts a function correctly): 11 | f = if g n then 3 else n 12 | 13 | g :: _ -> _ 14 | g n = n > 3 15 | 16 | Given haskell (Setup with type example): 17 | f :: Int -> Maybe Int -> Int 18 | 19 | Do (Highlight text and run ExtractHaskellType): 20 | O\j 21 | 02w 22 | v3we 23 | :ExtractHaskellType IntMaybeInt\ 24 | 25 | Expect haskell (ExtractHaskellType extracts a function correctly): 26 | 27 | type IntMaybeInt = Int -> Maybe Int 28 | 29 | f :: IntMaybeInt -> Int 30 | 31 | Given haskell (Setup with multiline function example): 32 | f = do 33 | contents <- readFile "test" 34 | print contents 35 | 36 | Do (Highlight text and run ExtractHaskellFuncton): 37 | 2jo\3k 38 | 02w 39 | v2jwe 40 | :ExtractHaskellFunction g\ 41 | 42 | Expect haskell (ExtractHaskellFunction extracts a multiline function correctly): 43 | f = g 44 | 45 | g :: _ 46 | g = do 47 | contents <- readFile "test" 48 | print contents 49 | 50 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Haskell Refactor 2 | 3 | A lightweight vim plugin that helps you refactor Haskell code. 4 | 5 | ![Demo](https://github.com/chris-bacon/haskell-refactor/raw/master/demo.gif "Demo") 6 | 7 | ## Installation 8 | 9 | With `Plug` add, 10 | 11 | ```vim 12 | Plug 'chris-bacon/haskell-refactor' 13 | ``` 14 | 15 | to your vimrc. 16 | 17 | Alternatively, you can clone this repo. 18 | 19 | ## Usage 20 | 21 | ### Commands 22 | 23 | Select the code you wish to refactor in visual mode. You can then use the following commands: 24 | 25 | ```vim 26 | :ExtractHaskellFunction 27 | :ExtractHaskellType 28 | ``` 29 | 30 | All options are optional. Every command will default to a prompt if no args are provided, so you do not need to provide any arguments. This also means you can use the following mappings. 31 | 32 | ### Mappings 33 | 34 | You following are examples of mappings you could create for each command: 35 | 36 | ```vim 37 | vnoremap ef :ExtractHaskellFunction 38 | vnoremap et :ExtractHaskellType 39 | ``` 40 | 41 | ## Contributing 42 | 43 | _Please feel free to raise any issues or PRs._ 44 | 45 | ### Tests 46 | 47 | There are some tests to ensure regressions are not added. 48 | 49 | You will need to have [vader](https://github.com/junegunn/vader.vim) installed. Then you will be able to run `:Vader .vader` and hopefully see the following output: 50 | 51 | ![Tests Image](https://github.com/chris-bacon/haskell-refactor/raw/master/vader-tests.png "Vader Tests") 52 | 53 | Unfortunately, the tests are sensitive to whitespace so you will have to be vigilent with regards to whitespace. 54 | 55 | -------------------------------------------------------------------------------- /demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrisgrounds/haskell-refactor/316f5630a6d4e3cada3ff833cc6aa9c2129d7739/demo.gif -------------------------------------------------------------------------------- /plugin/haskell-refactor.vim: -------------------------------------------------------------------------------- 1 | let g:equals = "\=\" 2 | 3 | function! FindNextEmptyLine() 4 | return "/^$\" 5 | endfunction 6 | 7 | function! FindPreviousEmptyLine() 8 | return "/^$\N" 9 | endfunction 10 | 11 | function! CreateType(name) 12 | return "type\" . a:name . g:equals 13 | endfunction 14 | 15 | function! GetInput(msg) 16 | call inputsave() 17 | let i = input(a:msg) 18 | call inputrestore() 19 | return i 20 | endfunction 21 | 22 | function! ExtractHaskellType(...) 23 | let requiresPrompt = a:0 < 1 24 | 25 | let name = requiresPrompt ? GetInput('Name type: ') : a:1 26 | 27 | let cmd = "normal! gvdmm" 28 | let cmd .= FindPreviousEmptyLine() 29 | let cmd .= "o" 30 | let cmd .= CreateType(name) 31 | let cmd .= "\po\`mi" 32 | let cmd .= name 33 | let cmd .= "\:noh" 34 | 35 | execute cmd 36 | endfunction 37 | 38 | function! CreateTypeSignature(name, numArgs) 39 | let typeSig = "\::" 40 | let i = 1 41 | while i <= a:numArgs 42 | let typeSig .= "\_\->" 43 | let i += 1 44 | endwhile 45 | let typeSig .= "\_" 46 | return a:name . typeSig 47 | endfunction 48 | 49 | function! CreateFunction(name, params) 50 | return a:name . (a:params != "" ? " " . a:params : "") . g:equals 51 | endfunction 52 | 53 | function! ExtractHaskellFunction(...) 54 | let requiresPrompt = a:0 < 1 55 | 56 | if requiresPrompt 57 | let fName = GetInput('Rename function to: ') 58 | let providedArgs = GetInput('Give arguments (seperated by space): ') 59 | 60 | let args = split(providedArgs, " ") 61 | let numArgs = len(args) 62 | let numFParams = numArgs 63 | let fParams = args != [] ? join(args, " ") : "" 64 | else 65 | let args = a:0 > 0 ? split(a:000[0], " ") : [] 66 | let numArgs = len(args) 67 | let fName = numArgs > 0 ? args[0] : "f" 68 | let numFParams = numArgs - 1 69 | let fParams = args != [] ? join(args[1:], " ") : "" 70 | endif 71 | 72 | let cmd = "normal! gvdmm" 73 | let cmd .= FindNextEmptyLine() 74 | let cmd .= "o" 75 | let cmd .= CreateTypeSignature(fName, numFParams) 76 | let cmd .= "\o" 77 | let cmd .= CreateFunction(fName, fParams) 78 | let cmd .= "\p\`mi" 79 | let cmd .= fName . (fParams != "" ? " " . fParams : "") 80 | let cmd .= "\:noh" 81 | 82 | execute cmd 83 | endfunction 84 | 85 | command! -range -nargs=? ExtractHaskellType call ExtractHaskellType() 86 | command! -range -nargs=? ExtractHaskellFunction call ExtractHaskellFunction() 87 | 88 | -------------------------------------------------------------------------------- /vader-tests.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrisgrounds/haskell-refactor/316f5630a6d4e3cada3ff833cc6aa9c2129d7739/vader-tests.png --------------------------------------------------------------------------------