Skip to content

Commit 92ea85a

Browse files
committed
seito: Add --vim-config
1 parent 680271e commit 92ea85a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+516
-13
lines changed

.gitattributes

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
*.cabal linguist-generated=true
22
/ghc-diagnostics/test/fixtures/**/*.yaml linguist-generated=true
33
/ghc-diagnostics/test/fixtures/**/Foo.hs linguist-generated=true
4+
/vim/test/assets/*.errors linguist-generated=true

.github/workflows/build.yml

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,32 @@ jobs:
7070
compression-level: 0
7171
if: matrix.ghc == 'latest'
7272

73+
- shell: bash
74+
run: |
75+
for GHC in 9.4
76+
do
77+
ghcup install ghc $GHC --no-set
78+
SENSEI_GHC=ghc-$GHC $(cabal list-bin spec)
79+
done
80+
if: matrix.ghc == 'latest'
81+
82+
- run: vim/test/run.vim
83+
if: runner.os == 'Linux'
84+
85+
- run: vim/test/assets/generate.sh
86+
if: ${{ runner.os == 'Linux' && matrix.ghc != '9.4' }}
87+
88+
- run: git diff --exit-code
89+
90+
- shell: bash
91+
run: |
92+
untracked=$(git ls-files --others --exclude-standard)
93+
if [ -n "$untracked" ]; then
94+
echo "Untracked files:"
95+
echo "$untracked"
96+
exit 1
97+
fi
98+
7399
success:
74100
needs: build
75101
runs-on: ubuntu-latest
@@ -81,7 +107,7 @@ jobs:
81107

82108
- uses: actions/checkout@v4
83109
- name: Check for trailing whitespace
84-
run: '! git grep -I "\s\+$"'
110+
run: "! git grep -nI '[[:blank:]]$' -- . ':!vim/test/assets'"
85111

86112
- run: curl -sSL https://raw.githubusercontent.com/sol/hpack/main/get-hpack.sh | bash
87113
- run: hpack && git diff --exit-code

README.md

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,13 +55,14 @@ instead:
5555

5656
### Vim integration
5757

58-
You can use `sensei` to load the result of the last test run into your quickfix
58+
You can use `seito` to load the results of the last test run into your quickfix
5959
list by executing `:make` in Vim.
6060

61-
For this to work, you can either create a `Makefile` or set `makeprg` to a
62-
custom value.
61+
For this to work, you can choose one out of three options:
6362

64-
(In both cases, `sed` is used to strip ANSI color sequences.)
63+
1. Create a `Makefile`
64+
2. Set `makeprg` to a custom value
65+
3. Use [`sensei.vim`](vim/sensei.vim)
6566

6667
#### Option 1: Create a `Makefile`
6768

@@ -82,6 +83,15 @@ Add the following to your Vim configuration (e.g.
8283
:set makeprg=seito
8384
```
8485

86+
#### Option 3: Use `sensei.vim`:
87+
88+
Add the following to your Vim configuration (e.g.
89+
`~/.vim/after/ftplugin/haskell.vim`):
90+
91+
```vim
92+
execute 'source ' . system('seito --vim-config')
93+
```
94+
8595
### Emacs integration
8696

8797
Similarly, you can use `sensei` to load the result of the last test run into an

driver/seito.hs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,12 @@ import System.Environment
77
import Control.Monad
88
import qualified Data.ByteString.Lazy as L
99

10+
import Paths_sensei (getDataFileName)
11+
1012
import Client
1113

1214
main :: IO ()
1315
main = do
14-
(success, output) <- getArgs >>= client ""
16+
(success, output) <- getArgs >>= client getDataFileName ""
1517
L.putStr output
1618
unless success exitFailure

package.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ default-extensions:
2222
- PackageImports
2323
- DerivingVia
2424

25+
data-files: vim/sensei.vim
26+
2527
dependencies:
2628
- ghc-diagnostics
2729

@@ -74,6 +76,7 @@ executables:
7476

7577
seito:
7678
source-dirs: driver
79+
generated-other-modules: Paths_sensei
7780
main: seito.hs
7881

7982
tests:

sensei.cabal

Lines changed: 6 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Client.hs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,17 @@ import Network.HTTP.Client
88
import HTTP.Util (makeRequest)
99
import Sensei.API qualified as API
1010

11-
client :: FilePath -> [String] -> IO (Bool, LazyByteString)
12-
client dir args = case args of
11+
client :: (FilePath -> IO FilePath) -> FilePath -> [String] -> IO (Bool, LazyByteString)
12+
client getDataFileName dir args = case args of
1313
[] -> hIsTerminalDevice stdout >>= run
1414
["--no-color"] -> run False
1515
["--color"] -> run True
1616
["trigger"] -> API.trigger dir
17+
["--vim-config"] -> (,) True . fromString <$> getDataFileName "vim/sensei.vim"
1718
_ -> do
1819
hPutStrLn stderr $ "Usage: seito [ --color | --no-color ]"
1920
hPutStrLn stderr $ " seito trigger"
21+
hPutStrLn stderr $ " seito --vim-config"
2022
return (False, "")
2123
where
2224
run :: Bool -> IO (Bool, LazyByteString)

test/ClientSpec.hs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,17 +24,21 @@ spec = do
2424
describe "client" $ do
2525
it "accepts --color" $ do
2626
withSuccess $ \ dir -> do
27-
client dir ["--color"] `shouldReturn` (True, fromString $ withColor Green "success")
27+
client return dir ["--color"] `shouldReturn` (True, fromString $ withColor Green "success")
2828

2929
it "accepts --no-color" $ do
3030
withSuccess $ \ dir -> do
31-
client dir ["--no-color"] `shouldReturn` (True, "success")
31+
client return dir ["--no-color"] `shouldReturn` (True, "success")
3232

3333
it "indicates failure" $ do
3434
withFailure $ \ dir -> do
35-
client dir ["--color"] `shouldReturn` (False, fromString $ withColor Red "failure")
35+
client return dir ["--color"] `shouldReturn` (False, fromString $ withColor Red "failure")
3636

3737
context "when server socket is missing" $ do
3838
it "reports error" $ do
3939
withTempDirectory $ \ dir -> do
40-
client dir [] `shouldReturn` (False, "could not connect to " <> fromString (socketName dir) <> "\n")
40+
client return dir [] `shouldReturn` (False, "could not connect to " <> fromString (socketName dir) <> "\n")
41+
42+
context "with --vim-config" $ do
43+
it "returns a path to a Vim support file" $ do
44+
client return undefined ["--vim-config"] `shouldReturn` (True, "vim/sensei.vim")

vim/sensei.test.vim

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
source vim/sensei.vim
2+
3+
function Require(actual, required)
4+
for i in range(len(a:required))
5+
if a:actual[i] > a:required[i]
6+
return 1
7+
elseif a:actual[i] < a:required[i]
8+
return 0
9+
endif
10+
endfor
11+
return 1
12+
endfunction
13+
14+
function GhcVersion(name)
15+
return matchlist(a:name, '\vghc-(\d+)\.(\d+)\.(\d+)\.errors')[1:3]
16+
endfunction
17+
18+
function PopulateQuickFixList(name)
19+
SUCCESS a:name
20+
execute "cgetfile " . a:name
21+
return filter(getqflist(), 'v:val.valid')
22+
endfunction
23+
24+
function GhcErrorsFor(name)
25+
let errors = glob("vim/test/assets/" . a:name . ".*.errors", v:true, v:true)
26+
call ShouldBe(len(errors), 5)
27+
return errors
28+
endfunction
29+
30+
for name in GhcErrorsFor("lexical-error.hs")
31+
let errors = PopulateQuickFixList(name)
32+
call ShouldBe(len(errors), 1)
33+
34+
let err = errors[0]
35+
call ShouldBe(bufname(err.bufnr), "lexical-error.hs")
36+
call ShouldBe(err.lnum, 1)
37+
call ShouldBe(err.col, 11)
38+
call ShouldBe(err.end_lnum, 0)
39+
call ShouldBe(err.end_col, 0)
40+
call ShouldBe(err.type, 'e')
41+
if Require(GhcVersion(name), [9,6])
42+
call ShouldBe(err.nr, 21231)
43+
else
44+
call ShouldBe(err.nr, -1)
45+
endif
46+
call ShouldBe(err.text, "\n lexical error in string/character literal at character '\\n'")
47+
endfor
48+
49+
for name in GhcErrorsFor("parse-error.hs")
50+
let errors = PopulateQuickFixList(name)
51+
call ShouldBe(len(errors), 1)
52+
53+
let err = errors[0]
54+
call ShouldBe(bufname(err.bufnr), "parse-error.hs")
55+
call ShouldBe(err.lnum, 1)
56+
call ShouldBe(err.col, 1)
57+
call ShouldBe(err.end_lnum, 0)
58+
call ShouldBe(err.end_col, 0)
59+
call ShouldBe(err.type, 'e')
60+
if Require(GhcVersion(name), [9,8])
61+
call ShouldBe(err.nr, 25277)
62+
else
63+
call ShouldBe(err.nr, -1)
64+
endif
65+
call ShouldBe(err.text, "\n Parse error: module header, import declaration\n or top-level declaration expected.")
66+
endfor
67+
68+
for name in GhcErrorsFor("type-error.hs")
69+
let errors = PopulateQuickFixList(name)
70+
call ShouldBe(len(errors), 1)
71+
72+
let err = errors[0]
73+
call ShouldBe(bufname(err.bufnr), "type-error.hs")
74+
call ShouldBe(err.lnum, 2)
75+
call ShouldBe(err.col, 7)
76+
call ShouldBe(err.end_lnum, 0)
77+
call ShouldBe(err.end_col, 0)
78+
call ShouldBe(err.type, 'e')
79+
if Require(GhcVersion(name), [9,6])
80+
call ShouldBe(err.nr, 83865)
81+
call ShouldBe(err.text, "\n Couldn't match type ‘Int’ with ‘[Char]’\n Expected: String\n Actual: Int")
82+
else
83+
call ShouldBe(err.nr, -1)
84+
call ShouldBe(err.text, "\n • Couldn't match type ‘Int’ with ‘[Char]’\n Expected: String\n Actual: Int\n • In the expression: 23 :: Int\n In an equation for ‘foo’: foo = 23 :: Int")
85+
endif
86+
endfor
87+
88+
for name in GhcErrorsFor("suggested-fix.hs")
89+
let errors = PopulateQuickFixList(name)
90+
call ShouldBe(len(errors), 2)
91+
92+
let err = errors[0]
93+
call ShouldBe(bufname(err.bufnr), "suggested-fix.hs")
94+
call ShouldBe(err.lnum, 1)
95+
call ShouldBe(err.col, 1)
96+
call ShouldBe(err.end_lnum, 0)
97+
call ShouldBe(err.end_col, 0)
98+
call ShouldBe(err.type, 'e')
99+
if Require(GhcVersion(name), [9,6])
100+
call ShouldBe(err.nr, 44432)
101+
else
102+
call ShouldBe(err.nr, -1)
103+
endif
104+
call ShouldBe(err.text, "\n The type signature for ‘foo’ lacks an accompanying binding")
105+
106+
let err = errors[1]
107+
call ShouldBe(bufname(err.bufnr), "suggested-fix.hs")
108+
call ShouldBe(err.lnum, 4)
109+
call ShouldBe(err.col, 1)
110+
call ShouldBe(err.end_lnum, 0)
111+
call ShouldBe(err.end_col, 0)
112+
call ShouldBe(err.type, 'e')
113+
if Require(GhcVersion(name), [9,6])
114+
call ShouldBe(err.nr, 44432)
115+
else
116+
call ShouldBe(err.nr, -1)
117+
endif
118+
call ShouldBe(err.text, "\n The type signature for ‘bar’ lacks an accompanying binding")
119+
endfor
120+
121+
for name in GhcErrorsFor("suggested-fix-multiline.hs")
122+
let errors = PopulateQuickFixList(name)
123+
call ShouldBe(len(errors), 2)
124+
125+
let err = errors[0]
126+
call ShouldBe(bufname(err.bufnr), "suggested-fix-multiline.hs")
127+
call ShouldBe(err.lnum, 1)
128+
call ShouldBe(err.col, 1)
129+
call ShouldBe(err.end_lnum, 0)
130+
call ShouldBe(err.end_col, 0)
131+
call ShouldBe(err.type, 'e')
132+
if Require(GhcVersion(name), [9,6])
133+
call ShouldBe(err.nr, 44432)
134+
else
135+
call ShouldBe(err.nr, -1)
136+
endif
137+
call ShouldBe(err.text, "\n The type signature for ‘foo’ lacks an accompanying binding")
138+
139+
let err = errors[1]
140+
call ShouldBe(bufname(err.bufnr), "suggested-fix-multiline.hs")
141+
call ShouldBe(err.lnum, 4)
142+
call ShouldBe(err.col, 1)
143+
call ShouldBe(err.end_lnum, 0)
144+
call ShouldBe(err.end_col, 0)
145+
call ShouldBe(err.type, 'e')
146+
if Require(GhcVersion(name), [9,6])
147+
call ShouldBe(err.nr, 44432)
148+
else
149+
call ShouldBe(err.nr, -1)
150+
endif
151+
call ShouldBe(err.text, "\n The type signature for ‘bar’ lacks an accompanying binding")
152+
endfor
153+
154+
let errors = PopulateQuickFixList("vim/test/assets/hspec.hs.errors")
155+
call ShouldBe(len(errors), 1)
156+
157+
let err = errors[0]
158+
call ShouldBe(bufname(err.bufnr), "vim/test/assets/hspec.hs")
159+
call ShouldBe(err.lnum, 6)
160+
call ShouldBe(err.col, 11)
161+
call ShouldBe(err.end_lnum, 0)
162+
call ShouldBe(err.end_col, 0)
163+
call ShouldBe(err.type, '')
164+
call ShouldBe(err.nr, -1)
165+
call ShouldBe(err.text, "")

vim/sensei.vim

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
setlocal makeprg=seito
2+
3+
" GHC
4+
setlocal errorformat=%A%f:%l:%c:\ %t%*[^:]:\ [GHC-%n]
5+
setlocal errorformat^=%A%f:%l:%c:\ %t%*[^:]: " GHC 9.6
6+
7+
" lines that start with a space continue the previous message
8+
setlocal errorformat^=%+C\ %.%#
9+
10+
" empty lines terminate a message
11+
setlocal errorformat^=%Z
12+
13+
" ignore this part of the message
14+
setlocal errorformat^=%-G\ \ \ \ Suggested\ fix:%.%#
15+
setlocal errorformat^=%-G\ \ \ \ \ \ Perhaps\ you\ meant\ %.%# " GHC 9.2
16+
17+
" Hspec
18+
setlocal errorformat^=\ \ %f:%l:%c:\ .%#

0 commit comments

Comments
 (0)