Compare commits
18 commits
de969f461b
...
29f6eac7cb
| Author | SHA1 | Date | |
|---|---|---|---|
| 29f6eac7cb | |||
| 0d35907d53 | |||
| 9db8fd3957 | |||
| ad0dafa841 | |||
| c9f6358254 | |||
| 3e829d126c | |||
| b8eac2856c | |||
| afc9a3b211 | |||
| 9edd5cb436 | |||
| 2fc7948112 | |||
| 10469b3677 | |||
| 1b360e3592 | |||
| f452197fca | |||
| 9d4e278b91 | |||
| d012a8e396 | |||
| 0f03f9eb7a | |||
| 20c78cf015 | |||
| f1cb583d0f |
7 changed files with 494 additions and 323 deletions
121
.forgejo/workflows/test.yaml
Normal file
121
.forgejo/workflows/test.yaml
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
name: Haskell CI
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- dev
|
||||
- main
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: docker
|
||||
container:
|
||||
image: haskell:9.10
|
||||
steps:
|
||||
- name: Install Node.js (for actions)
|
||||
run: |
|
||||
curl -fsSL https://deb.nodesource.com/setup_22.x | bash -
|
||||
apt-get install -y nodejs
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
- name: Check versions
|
||||
run: |
|
||||
ghc --version
|
||||
cabal --version
|
||||
node --version
|
||||
- name: Cache Cabal packages
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/.cabal/packages
|
||||
~/.cabal/store
|
||||
dist-newstyle
|
||||
key: ${{ runner.os }}-haskell-9.10-cabal-${{ hashFiles('**/*.cabal', '**/cabal.project') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-haskell-9.10-cabal-
|
||||
- name: Update Cabal package index
|
||||
run: cabal update
|
||||
- name: Configure project
|
||||
run: cabal configure --enable-tests --enable-benchmarks
|
||||
- name: Build dependencies
|
||||
run: cabal build --only-dependencies --enable-tests --enable-benchmarks
|
||||
- name: Build project
|
||||
run: cabal build --enable-tests --enable-benchmarks
|
||||
- name: Run documentation build
|
||||
run: cabal haddock
|
||||
|
||||
test:
|
||||
runs-on: docker
|
||||
container:
|
||||
image: haskell:9.10
|
||||
needs: build
|
||||
steps:
|
||||
- name: Install Node.js (for actions)
|
||||
run: |
|
||||
curl -fsSL https://deb.nodesource.com/setup_22.x | bash -
|
||||
apt-get install -y nodejs
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
- name: Cache Cabal packages
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/.cabal/packages
|
||||
~/.cabal/store
|
||||
dist-newstyle
|
||||
key: ${{ runner.os }}-haskell-9.10-cabal-${{ hashFiles('**/*.cabal', '**/cabal.project') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-haskell-9.10-cabal-
|
||||
- name: Update Cabal package index
|
||||
run: cabal update
|
||||
- name: Configure project
|
||||
run: cabal configure --enable-tests --enable-benchmarks
|
||||
- name: Build dependencies
|
||||
run: cabal build --only-dependencies --enable-tests --enable-benchmarks
|
||||
- name: Build project
|
||||
run: cabal build --enable-tests --enable-benchmarks
|
||||
- name: Run tests
|
||||
run: cabal test --test-show-details=direct
|
||||
|
||||
fourmolu:
|
||||
runs-on: docker
|
||||
container:
|
||||
image: haskell:9.10
|
||||
steps:
|
||||
- name: Install Node.js (for actions)
|
||||
run: |
|
||||
curl -fsSL https://deb.nodesource.com/setup_22.x | bash -
|
||||
apt-get install -y nodejs
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
- name: Update Cabal package index
|
||||
run: cabal update
|
||||
- name: Install fourmolu
|
||||
run: cabal install fourmolu-0.18.0.0
|
||||
- name: Run fourmolu
|
||||
run: |
|
||||
find src test app -name "*.hs" -exec fourmolu --check-idempotence {} \; 2>/dev/null || true
|
||||
find src test app -name "*.hs" -exec fourmolu --mode check {} \;
|
||||
|
||||
hlint:
|
||||
runs-on: docker
|
||||
container:
|
||||
image: haskell:9.10
|
||||
steps:
|
||||
- name: Install Node.js (for actions)
|
||||
run: |
|
||||
curl -fsSL https://deb.nodesource.com/setup_22.x | bash -
|
||||
apt-get install -y nodejs
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
- name: Update Cabal package index
|
||||
run: cabal update
|
||||
- name: Install hlint
|
||||
run: cabal install hlint
|
||||
- name: Run hlint
|
||||
run: |
|
||||
if [ -d src ]; then hlint src/; fi
|
||||
if [ -d test ]; then hlint test/; fi
|
||||
if [ -d app ]; then hlint app/; fi
|
||||
44
Makefile
Normal file
44
Makefile
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
.PHONY: help
|
||||
help: ## Show this help
|
||||
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
|
||||
|
||||
.PHONY: build
|
||||
build: ## Build the project
|
||||
cabal build
|
||||
|
||||
.PHONY: test
|
||||
test: ## Run tests
|
||||
cabal test --test-show-details=direct
|
||||
|
||||
.PHONY: clean
|
||||
clean: ## Clean build artifacts
|
||||
cabal clean
|
||||
|
||||
.PHONY: fourmolu
|
||||
fourmolu: ## Format Haskell code
|
||||
find . -type f -name "*.hs" ! -path "./dist-newstyle/*" -exec fourmolu -i {} +
|
||||
|
||||
.PHONY: fourmolu-check
|
||||
fourmolu-check: ## Check if code is formatted
|
||||
find . -type f -name "*.hs" ! -path "./dist-newstyle/*" -exec fourmolu --mode check {} \;
|
||||
|
||||
.PHONY: lint
|
||||
lint: ## Run hlint
|
||||
hlint src test app
|
||||
|
||||
.PHONY: cabal-gild
|
||||
cabal-gild: ## Format cabal file
|
||||
cabal-gild --io=haddock2.cabal
|
||||
|
||||
.PHONY: format
|
||||
format: fourmolu cabal-gild ## Run all formatters
|
||||
|
||||
.PHONY: check
|
||||
check: fourmolu-check lint ## Run all checks (CI-style)
|
||||
|
||||
.PHONY: ci
|
||||
ci: build test check ## Run full CI pipeline locally
|
||||
|
||||
.PHONY: docs
|
||||
docs: ## Generate documentation
|
||||
cabal haddock --haddock-hyperlink-source
|
||||
|
|
@ -46,10 +46,10 @@ test-suite haddock2-test
|
|||
type: exitcode-stdio-1.0
|
||||
main-is: Spec.hs
|
||||
build-depends:
|
||||
parsec ^>=3.1.18.0,
|
||||
base >=4.20.1.0,
|
||||
haddock2:{haddock2-lib},
|
||||
hspec ^>=2.11.0,
|
||||
parsec ^>=3.1.18.0,
|
||||
text ^>=2.1.2,
|
||||
|
||||
hs-source-dirs: test
|
||||
|
|
|
|||
10
src/Lexer.hs
10
src/Lexer.hs
|
|
@ -4,7 +4,8 @@ module Lexer (
|
|||
Token (..),
|
||||
lexer,
|
||||
emphasis,
|
||||
) where
|
||||
)
|
||||
where
|
||||
|
||||
import Control.Monad (mfilter, void)
|
||||
import Data.Functor (($>))
|
||||
|
|
@ -17,6 +18,7 @@ import Text.Parsec qualified as Parsec
|
|||
import Text.Parsec.Pos (updatePosChar)
|
||||
|
||||
type Located a = (SourcePos, a)
|
||||
|
||||
type LocatedToken = (SourcePos, Token)
|
||||
|
||||
type Lexer = Parser [LocatedToken]
|
||||
|
|
@ -67,7 +69,7 @@ located :: Parser a -> Parser (SourcePos, a)
|
|||
located p = (,) <$> getPosition <*> p
|
||||
|
||||
tokenise :: [Parser a] -> Parser [(SourcePos, a)]
|
||||
tokenise = sequence . map located
|
||||
tokenise = mapM located
|
||||
|
||||
lexer :: String -> Either ParseError [LocatedToken]
|
||||
lexer = Parsec.runParser lexText initialParserState "input" . Text.pack
|
||||
|
|
@ -144,7 +146,7 @@ delimitedNoTrailing openP closeP openTok = asList <$> delimitedAsTuple (openTok
|
|||
asList (a, tok, _) = [a, tok]
|
||||
|
||||
delimitedSymmetric :: Parser a -> Token -> Token -> Parser [LocatedToken]
|
||||
delimitedSymmetric s t1 t2 = delimited s s t1 t2
|
||||
delimitedSymmetric s = delimited s s
|
||||
|
||||
eol :: Parser ()
|
||||
eol = void "\n" <|> void "\r\n" <|> Parsec.eof
|
||||
|
|
@ -173,7 +175,6 @@ anchor = do
|
|||
x <- located $ between "#" "#" (Anchor <$> anyUntil "#")
|
||||
pure [x]
|
||||
|
||||
|
||||
moduleNames :: Parser Text
|
||||
moduleNames = intercalate "." . fmap Text.pack <$> upperId `sepBy1` char '.'
|
||||
|
||||
|
|
@ -302,6 +303,7 @@ scan ::
|
|||
Parser Text
|
||||
scan f initState = do
|
||||
parserState@State{stateInput = input, statePos = pos} <- Parsec.getParserState
|
||||
|
||||
(remaining, finalPos, ct) <- go input initState pos 0
|
||||
let newState = parserState{stateInput = remaining, statePos = finalPos}
|
||||
Parsec.setParserState newState $> Text.take ct input
|
||||
|
|
|
|||
|
|
@ -13,7 +13,9 @@ import Text.Parsec.Pos (updatePosChar)
|
|||
Return everything consumed except for the end pattern itself.
|
||||
-}
|
||||
takeUntil :: Text -> Parser Text
|
||||
takeUntil end_ = Text.dropEnd (Text.length end_) <$> requireEnd (scan p (False, end)) >>= gotSome
|
||||
takeUntil end_ =
|
||||
requireEnd (scan p (False, end))
|
||||
>>= gotSome . Text.dropEnd (Text.length end_)
|
||||
where
|
||||
end = Text.unpack end_
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,8 @@ module Types (
|
|||
)
|
||||
where
|
||||
|
||||
import Data.Foldable (fold)
|
||||
|
||||
newtype Document = Document
|
||||
{ meta :: Meta
|
||||
}
|
||||
|
|
@ -28,6 +30,7 @@ data Since = Since
|
|||
|
||||
-- Could have a better type?
|
||||
type Version = [Int]
|
||||
|
||||
type Package = String
|
||||
|
||||
data DocMarkup mod id
|
||||
|
|
@ -136,7 +139,7 @@ instance Semigroup (DocMarkup mod id) where
|
|||
|
||||
instance Monoid (DocMarkup mod id) where
|
||||
mempty = DocEmpty
|
||||
mconcat = foldr (<>) mempty
|
||||
mconcat = fold
|
||||
|
||||
data ModuleLink id = ModuleLink
|
||||
{ name :: String
|
||||
|
|
|
|||
17
test/Spec.hs
17
test/Spec.hs
|
|
@ -1,17 +1,15 @@
|
|||
{-# LANGUAGE OverloadedStrings #-}
|
||||
{-# OPTIONS_GHC -Wno-orphans #-}
|
||||
|
||||
import Test.Hspec
|
||||
|
||||
import Data.String (IsString (..))
|
||||
import Data.Text (Text)
|
||||
import GHC.Stack
|
||||
import Identifier (Identifier)
|
||||
import Lexer
|
||||
import Parser
|
||||
import Types
|
||||
|
||||
import Data.String (IsString (..))
|
||||
import Data.Text (Text)
|
||||
import Test.Hspec
|
||||
import Text.Parsec.Pos
|
||||
import GHC.Stack
|
||||
import Types
|
||||
|
||||
main :: IO ()
|
||||
main = hspec $ do
|
||||
|
|
@ -34,9 +32,9 @@ main = hspec $ do
|
|||
|
||||
describe "Parser" do
|
||||
it "Bold" do
|
||||
"__bold__" `shouldParseTo` (DocBold (DocString "bold"))
|
||||
"__bold__" `shouldParseTo` DocBold (DocString "bold")
|
||||
it "Emphasis" do
|
||||
"/emphasis/" `shouldParseTo` (DocEmphasis (DocString "emphasis"))
|
||||
"/emphasis/" `shouldParseTo` DocEmphasis (DocString "emphasis")
|
||||
|
||||
------------
|
||||
-- Tests
|
||||
|
|
@ -57,6 +55,7 @@ modules = do
|
|||
`shouldLexTo` [ (1, 2, Module "OtherModule.Name")
|
||||
, (1, 18, Anchor "myAnchor")
|
||||
]
|
||||
|
||||
link :: Expectation
|
||||
link =
|
||||
"[link to](http://some.website)"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue