Skip to content

Commit df31c3a

Browse files
p-alikjship
authored andcommitted
an attempt to make haskell-vim-now usable with newer GHC (#297)
* replace outdated ghc-mod modules by coc use neoclide/coc.nvim instead of eagletmt/ghcmod-vim, eagletmt/neco-ghc and mpickering/hlint-refactor-vim * remove redundant imports * add coc settings content * install ghcide stack install https://github.com/digital-asset/ghcide * update resolver to lts-14.12 do not install brocken helpers - codex - git-hscope - hasktags - hscope - pointfree - pointful * write .vim/coc-settings.json * omment out codex.tag's * switch to native stack installation as proposed in https://docs.haskellstack.org/en/stable/README/#how-to-install * Revert "Warn about ghc-mod" This reverts commit f55a720. * remove unsupported keybindings - ,ht - ,hT * use again mpickering/hlint-refactor-vim for refactoring coc based approach described in http://marco-lopes.com/articles/Vim-and-Haskell-in-2019/ isn't applicable for ghcide * key binding ',hc' runs ghcide instead of ghc-mod * remove Pointfree and Pointful key bindings * remove key bindings for tags * remove obsolete code blocks * setup vim's ghcide compile configuration - .vim/compiler/ghcide.vim - .vim/after/ftplugin/haskell.vim * rewrite ,hc keybinding * setup errorformat the solution was provided by user @user938271 at stackoverflow https://stackoverflow.com/q/58998632/2789312 * improve makeprg and errorformat - sed removes escape characters - no need to match escape characters in errorformat * Determine temporary directory reliable getTemporaryDirectory supports Window and Unix also * remove obsolete codexTemplate * update list of necessary binaries
1 parent f55a720 commit df31c3a

File tree

5 files changed

+118
-210
lines changed

5 files changed

+118
-210
lines changed

.travis.yml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,12 @@ before_install:
2121
fi
2222
- |
2323
if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then
24-
echo 'deb http://download.fpcomplete.com/ubuntu xenial main'|sudo tee /etc/apt/sources.list.d/fpco.list
24+
curl -sSL https://get.haskellstack.org/ | sh
25+
stack --version
2526
sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 575159689BEFB442
2627
sudo add-apt-repository ppa:nmi/vim-snapshots -y
2728
sudo apt-get -qq update -y
28-
sudo apt-get install vim stack ctags -y
29+
sudo apt-get install vim ctags -y
2930
fi
3031
# emulating upgrade procedure (due to install.sh cloning from begriffs/master)
3132
- cp -r $TRAVIS_BUILD_DIR $XDG_CONFIG_HOME/

.vimrc

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,7 @@ Plug 'christoomey/vim-tmux-navigator'
117117
" Haskell
118118
Plug 'neovimhaskell/haskell-vim', { 'for': 'haskell' }
119119
Plug 'enomsg/vim-haskellConcealPlus', { 'for': 'haskell' }
120-
Plug 'eagletmt/ghcmod-vim', { 'for': 'haskell' }
121-
Plug 'eagletmt/neco-ghc', { 'for': 'haskell' }
120+
Plug 'neoclide/coc.nvim', { 'do': { -> coc#util#install() } }
122121
Plug 'Twinside/vim-hoogle', { 'for': 'haskell' }
123122
Plug 'mpickering/hlint-refactor-vim', { 'for': 'haskell' }
124123

@@ -510,16 +509,6 @@ map <Leader>a<bar> :Align <bar><CR>
510509
map <leader>ap :Align
511510
" }}}
512511

513-
" Tags {{{
514-
515-
map <leader>tt :TagbarToggle<CR>
516-
517-
set tags=tags;/
518-
set cst
519-
set csverb
520-
521-
" }}}
522-
523512
" Git {{{
524513

525514
let g:extradite_width = 60

README.md

Lines changed: 1 addition & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,10 @@
66

77
<br />
88

9-
### Notice: this project is broken
10-
11-
Due to the fragile Haskell ecosystem, most notably ghc-mod, this vim configuration no longer works. You'll just spend lots of time waiting for its helper binaries to build, and be left with used disk space and regret.
12-
13-
<hr />
14-
15-
### Original readme:
16-
179
In less than **ten minutes** your Vim will transform into a beautiful
1810
Haskell paradise. (Don't worry, it backs up your original
1911
configuration to `~/.config/haskell-vim-now/backup/.vimrc.yearmonthdate_time`.) It also builds all necessary support binaries
20-
including `codex`, `hscope`, `ghc-mod`, `hasktags`, `hoogle` and more.
12+
including `ghcide`, `hlint`, `hoogle` and more.
2113

2214
No more wading through plugins trying to make them all work together.
2315
In ten minutes you will have a fully functional Vim that looks great
@@ -60,12 +52,6 @@ them.
6052
<tr>
6153
<td>&lt;C-space&gt;</td><td>Autocomplete with symbols in your Cabal sandbox</td>
6254
</tr>
63-
<tr>
64-
<td>,ht</td><td>Show type of expression under cursor</td>
65-
</tr>
66-
<tr>
67-
<td>,hT</td><td>Insert type of expression into previous line</td>
68-
</tr>
6955
<tr>
7056
<td>,hr</td><td>Apply one refactoring hint at cursor position</td>
7157
</tr>
@@ -204,38 +190,6 @@ selections to it. This works well for evaluating things in GHCI.
204190
</tbody>
205191
</table>
206192

207-
### Tags
208-
209-
<table>
210-
<tbody>
211-
<tr>
212-
<td>,tg</td><td>Generate tags with codex</td>
213-
</tr>
214-
<tr>
215-
<td>,tt</td><td>Open/close the tag bar</td>
216-
</tr>
217-
<tr>
218-
<td>C-]</td><td>Jump to definition of symbol (codex + hasktags)</td><td>Note: You must generate the tags for your project (with <code>,tg</code>) prior to using the jump command.</td>
219-
</tr>
220-
<tr>
221-
<td>C-\</td><td>Show uses of symbol (hscope)</td>
222-
</tr>
223-
</tbody>
224-
</table>
225-
226-
### Conversions
227-
228-
<table>
229-
<tbody>
230-
<tr>
231-
<td>,h.</td><td>Transform visual selection to pointfree style</td>
232-
</tr>
233-
<tr>
234-
<td>,h&gt;</td><td>Transform visual selection to pointed style</td>
235-
</tr>
236-
</tbody>
237-
</table>
238-
239193
### Buffers
240194

241195
<table>

scripts/setup_haskell.hs

Lines changed: 111 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
#!/usr/bin/env stack
22
{- stack
33
script
4-
--resolver lts-8.14
4+
--resolver lts-14.12
55
--package aeson
66
--package ansi-terminal
7+
--package directory
78
--package foldl
89
--package mtl
10+
--package raw-strings-qq
911
--package stache
1012
--package system-filepath
1113
--package text
@@ -14,6 +16,7 @@
1416
-}
1517

1618
{-# LANGUAGE FlexibleContexts #-}
19+
{-# LANGUAGE LambdaCase #-}
1720
{-# LANGUAGE NamedFieldPuns #-}
1821
{-# LANGUAGE OverloadedStrings #-}
1922
{-# LANGUAGE QuasiQuotes #-}
@@ -23,24 +26,25 @@ import Control.Exception (bracket_)
2326
import qualified Control.Foldl as Foldl
2427
import Control.Monad (mfilter, unless, when)
2528
import Control.Monad.IO.Class (MonadIO, liftIO)
26-
import Control.Monad.Reader (MonadReader, ask, runReaderT)
27-
import Control.Monad.Trans.Maybe (MaybeT(..), runMaybeT)
29+
import Control.Monad.Reader (MonadReader, ask, asks, runReaderT)
2830
import Data.Aeson ((.=), object)
2931
import Data.Foldable (forM_)
30-
import Data.Maybe (isJust, listToMaybe)
32+
import Data.Maybe (listToMaybe)
3133
import Data.Monoid ((<>))
3234
import qualified Data.Text as Text
3335
import Data.Text (Text)
3436
import qualified Data.Text.IO as Text.IO
3537
import Data.Text.Lazy (toStrict)
36-
import Filesystem.Path.CurrentOS (FilePath, (</>))
38+
import Filesystem.Path.CurrentOS (FilePath, (</>), decodeString)
3739
import qualified Filesystem.Path.CurrentOS as FS
3840
import Prelude hiding (FilePath)
3941
import qualified System.Console.ANSI as ANSI
4042
import qualified System.IO
4143
import System.Info (os)
44+
import System.Directory (getTemporaryDirectory)
4245
import Text.Mustache (Template, renderMustache)
4346
import Text.Mustache.Compile.TH (mustache)
47+
import Text.RawString.QQ (r)
4448
import qualified Turtle
4549

4650
data HvnConfig = HvnConfig
@@ -61,7 +65,7 @@ main = do
6165
Turtle.options "Haskell Vim Now - setup Haskell specifics" cliParser
6266
print HvnArgs {hvnArgsNoHoogleDb, hvnArgsNoHelperBinaries}
6367
hvnCfgHome <- hvnHomeDir
64-
let hvnCfgDest = hvnCfgHome </> "haskell-vim-now"
68+
let hvnCfgDest = hvnCfgHome </> textToFilePath hvn
6569
hvnCfgHoogleDb = not hvnArgsNoHoogleDb
6670
hvnCfgHelperBinaries = not hvnArgsNoHelperBinaries
6771
runReaderT setup HvnConfig { hvnCfgHome
@@ -129,13 +133,13 @@ setupHaskell = do
129133
Turtle.cd hvnHelperBinDir
130134
stackYamlExists <- Turtle.testfile (hvnHelperBinDir </> "stack.yaml")
131135
unless stackYamlExists $ do
132-
-- Install ghc-mod via active stack resolver for maximum
136+
-- Install ghcide from source for maximum
133137
-- out-of-the-box compatibility.
134-
stackInstall stackResolver "ghc-mod" False
138+
installGhcide
135139
-- Stack dependency solving requires cabal to be on the PATH.
136-
stackInstall "lts-7.24" "cabal-install" True
137-
-- Install hindent via pinned LTS to ensure we have version 5.
138-
stackInstall "lts-8.14" "hindent" True
140+
stackInstall stackResolver "cabal-install" True
141+
-- Install hindent via default LTS
142+
stackInstall stackResolver "hindent" True
139143
let helperDependenciesCabalText =
140144
renderMustache helperDependenciesCabalTemplate $
141145
object ["dependencies" .= helperDependencies]
@@ -144,7 +148,7 @@ setupHaskell = do
144148
"dependencies.cabal"
145149
(toStrict helperDependenciesCabalText)
146150
Turtle.stdout (Turtle.input "dependencies.cabal")
147-
let solverCommand = "stack init --solver --resolver lts-7.24"
151+
let solverCommand = "stack init --resolver " <> stackResolver
148152
<> " --install-ghc"
149153
-- XXX for best results we should solve and install each one of them
150154
-- independently rather than solving them together. It becomes more
@@ -172,33 +176,18 @@ setupHaskell = do
172176
-- XXX I could not figure out how to keep the ">" sign unescaped in
173177
-- mustache, so had to treat this especially. If we can do that then
174178
-- we can push this as well in helperDependencies.
175-
stackInstall "lts-7.24" "hscope" True
176179
forM_ (map (head . Text.words) helperDependencies) $
177-
\dep -> stackInstall "lts-7.24" dep True
180+
\dep -> stackInstall stackResolver dep True
178181
-- XXX we should remove the temporary dir after installing to reclaim
179182
-- unnecessary space.
180-
msg "Installing git-hscope..."
181-
-- TODO: The 'git-hscope' file won't do much good on Windows as it
182-
-- is a bash script.
183-
Turtle.cp
184-
(hvnCfgDest </> "git-hscope")
185-
(textToFilePath stackBinPath </> "git-hscope")
186183
when hvnCfgHoogleDb $ do
187184
msg "Building Hoogle database..."
188185
Turtle.sh
189186
(Turtle.shell
190187
(filePathToText (textToFilePath stackBinPath </> "hoogle") <>
191188
" generate")
192189
empty)
193-
msg "Configuring codex to search in stack..."
194-
let codexText =
195-
renderMustache codexTemplate $
196-
object [ "stackHackageIndicesDir" .=
197-
filePathToText (textToFilePath stackGlobalDir
198-
</> "indices" </> "Hackage") ]
199-
homePath <- Turtle.home
200-
liftIO
201-
(Turtle.writeTextFile (homePath </> ".codex") (toStrict codexText))
190+
liftIO $ Turtle.writeTextFile (hvnCfgDest </> ".vim" </> "coc-settings.json") cocSettings
202191

203192
stackResolverText :: (MonadIO m) => FilePath -> m Text
204193
stackResolverText stackYamlPath = do
@@ -240,21 +229,14 @@ stackInstall resolver package exitOnFailure = do
240229
True -> Turtle.exit (Turtle.ExitFailure 1)
241230
False -> handleFailure package where
242231
handleFailure :: (MonadIO m) => Text -> m ()
243-
handleFailure "ghc-mod" =
244-
msg $ "To install \"ghc-mod\" manually, see here: " <>
245-
"https://github.com/DanielG/ghc-mod/issues/900"
246232
handleFailure _ = pure()
247233
Turtle.ExitSuccess -> pure ()
248234

249235
helperDependencies :: [Text]
250236
helperDependencies =
251237
[ "apply-refact"
252-
, "codex"
253-
, "hasktags"
254238
, "hlint"
255239
, "hoogle"
256-
, "pointfree"
257-
, "pointful"
258240
]
259241

260242
helperDependenciesCabalTemplate :: Template
@@ -270,22 +252,13 @@ build-type: Simple
270252
cabal-version: >=1.10
271253

272254
library
273-
-- hscope 0.4 does not compile with most resolvers so use newer
274-
build-depends: base >=4.9 && <4.11
275-
, hscope > 0.4
255+
build-depends: base >=4.9 && < 5
276256
{{#dependencies}}
277257
, {{.}}
278258
{{/dependencies}}
279259
default-language: Haskell2010
280260
|]
281261

282-
codexTemplate :: Template
283-
codexTemplate = [mustache|hackagePath: {{stackHackageIndicesDir}}
284-
tagsFileHeader: false
285-
tagsFileSorted: false
286-
tagsCmd: hasktags --extendedctag --ignore-close-implementation --ctags --tags-absolute --output="$TAGS" "$SOURCES"
287-
|]
288-
289262
msg :: (MonadIO m) => Text -> m ()
290263
msg =
291264
consoleLog
@@ -352,3 +325,95 @@ filePathToText = Turtle.format Turtle.fp
352325

353326
textToFilePath :: Text -> FilePath
354327
textToFilePath = FS.fromText
328+
329+
hvn :: Text
330+
hvn = "haskell-vim-now"
331+
332+
type HelperRepository = Text
333+
type HelperTool = Text
334+
type Resolver = Text
335+
336+
-- install ghcide, write compiler and file type plugin files
337+
installGhcide :: (MonadIO m, MonadReader HvnConfig m) => m ()
338+
installGhcide = do
339+
hvnCfgDest' <- asks hvnCfgDest
340+
gitCloneInstall "https://github.com/digital-asset/ghcide.git" "ghcide" Nothing
341+
let vimDir = hvnCfgDest' <> ".vim"
342+
writeCompilerFile vimDir
343+
writeaFtPluginFile vimDir
344+
where
345+
mkdir' d = Turtle.testpath d >>= \exists -> unless exists (Turtle.mktree d)
346+
toFile f c = liftIO $ Turtle.writeTextFile f c
347+
writeaFtPluginFile d = do
348+
let d' = d </> "after" </> "ftplugin"
349+
mkdir' d'
350+
toFile (d' </> "haskell.vim") "compiler ghcide"
351+
writeCompilerFile d = do
352+
let d' = d <> "compiler"
353+
mkdir' d'
354+
toFile (d' </> "ghcide.vim") [r|
355+
CompilerSet errorformat=%-Gghcide\ %s
356+
CompilerSet errorformat+=%-GReport\ bugs\ at\ %s
357+
CompilerSet errorformat+=%-GStep\ %s
358+
CompilerSet errorformat+=%-GFound\ %s
359+
CompilerSet errorformat+=%-GCradle\ %s
360+
CompilerSet errorformat+=%-GRange:\ %s
361+
CompilerSet errorformat+=%-GFile:\ %s
362+
CompilerSet errorformat+=%-GSource:\ %s
363+
CompilerSet errorformat+=%-GSeverity:\ %s
364+
CompilerSet errorformat+=%-GCompleted\ %s
365+
" exclude empty or whitespace-only lines
366+
CompilerSet errorformat+=%-G\\s%#
367+
CompilerSet errorformat+=%EMessage:%\\s%#%>
368+
CompilerSet errorformat+=%C%\\s%#%f:%l:%c:%\\s%#error:%\\s%#%>
369+
CompilerSet errorformat+=%C%m
370+
CompilerSet errorformat+=%ZCompleted%m
371+
372+
setlocal makeprg=ghcide\ %\ 2>&1\ \\\|\ sed\ 's/\\x1B\\[[0-9;]*m//g'
373+
|]
374+
375+
gitCloneInstall :: MonadIO m => HelperRepository -> HelperTool -> Maybe Resolver -> m ()
376+
gitCloneInstall repo tool maybeResolver = Turtle.sh $ do
377+
liftIO $ msg (unwords' ["clone", repo, "and install", tool])
378+
tmp <- liftIO getTemporaryDirectory >>= return . decodeString
379+
Turtle.mktempdir tmp hvn >>= Turtle.pushd
380+
inShell (unwords' ["git clone", repo, tool])
381+
Turtle.pushd (textToFilePath tool)
382+
inShell (unwords' ["stack", resolver, "install"])
383+
where
384+
resolver = case maybeResolver of
385+
Nothing -> ""
386+
Just x -> unwords'["--resolver ", x]
387+
unwords' = Text.intercalate " "
388+
inShell cmd =
389+
Turtle.shell cmd empty
390+
>>= \case
391+
Turtle.ExitSuccess -> return ()
392+
Turtle.ExitFailure n ->
393+
err (unwords' [cmd, "failed with exit code:", Turtle.repr n])
394+
>> Turtle.exit (Turtle.ExitFailure 1)
395+
396+
cocSettings :: Text
397+
cocSettings = [r|{
398+
"languageserver": {
399+
"haskell": {
400+
"command": "ghcide",
401+
"args": [
402+
"--lsp"
403+
],
404+
"rootPatterns": [
405+
".stack.yaml",
406+
".hie-bios",
407+
"BUILD.bazel",
408+
"cabal.config",
409+
"package.yaml"
410+
],
411+
"filetypes": [
412+
"hs",
413+
"lhs",
414+
"haskell"
415+
]
416+
}
417+
}
418+
}
419+
|]

0 commit comments

Comments
 (0)