Compare commits

...

18 commits

Author SHA1 Message Date
29f6eac7cb Added missing cabal-update steps
Some checks failed
Haskell CI / build (pull_request) Successful in 2m50s
Haskell CI / fourmolu (pull_request) Failing after 7m13s
Haskell CI / hlint (pull_request) Failing after 13m38s
Haskell CI / test (pull_request) Successful in 2m41s
2025-09-27 09:37:36 +02:00
0d35907d53 Remove hlint hard-coded version
Some checks failed
Haskell CI / test (pull_request) Has been cancelled
Haskell CI / fourmolu (pull_request) Has been cancelled
Haskell CI / hlint (pull_request) Has been cancelled
Haskell CI / build (pull_request) Has been cancelled
2025-09-27 09:35:46 +02:00
9db8fd3957 Improved makefile, formatting
Some checks failed
Haskell CI / build (pull_request) Successful in 2m51s
Haskell CI / fourmolu (pull_request) Failing after 20s
Haskell CI / hlint (pull_request) Failing after 19s
Haskell CI / test (pull_request) Successful in 2m46s
2025-09-27 09:27:30 +02:00
ad0dafa841 Try more steps
Some checks failed
Haskell CI / fourmolu (pull_request) Failing after 22s
Haskell CI / hlint (pull_request) Failing after 21s
Haskell CI / build (pull_request) Failing after 14m58s
Haskell CI / test (pull_request) Has been cancelled
2025-09-27 09:14:30 +02:00
c9f6358254 Split jobs
Some checks failed
Haskell CI / build (pull_request) Successful in 2m40s
Haskell CI / test (pull_request) Failing after 1s
2025-09-27 09:00:43 +02:00
3e829d126c Added cabal-gild to format cmd
All checks were successful
Haskell CI / build (pull_request) Successful in 3m7s
2025-09-27 08:57:27 +02:00
b8eac2856c Formatting 2025-09-27 08:57:27 +02:00
afc9a3b211 Added Makefile 2025-09-27 08:57:27 +02:00
9edd5cb436 Update .forgejo/workflows/test.yaml
All checks were successful
Haskell CI / build (pull_request) Successful in 2m53s
2025-09-26 21:55:59 +00:00
2fc7948112 try again
Some checks failed
Haskell CI / build (pull_request) Failing after 2m2s
2025-09-26 23:45:32 +02:00
10469b3677 Fixed ci.yml
Some checks failed
Haskell CI / build (pull_request) Failing after 39s
2025-09-26 23:39:34 +02:00
1b360e3592 Updated ci
Some checks failed
Haskell CI / build (pull_request) Failing after 56s
2025-09-26 23:25:05 +02:00
f452197fca update ci action
Some checks failed
Haskell CI / build (pull_request) Failing after 10s
2025-09-26 23:22:36 +02:00
9d4e278b91 Run on docker
Some checks failed
Haskell CI / build (pull_request) Failing after 33s
2025-09-26 23:22:08 +02:00
d012a8e396 Renamed file
Some checks failed
Haskell CI / build (pull_request) Has been cancelled
2025-09-26 23:21:19 +02:00
0f03f9eb7a New rules
Some checks failed
Haskell CI / build (pull_request) Has been cancelled
2025-09-26 22:50:54 +02:00
20c78cf015 Updated ci.yml 2025-09-26 22:49:48 +02:00
f1cb583d0f Runner base config 2025-09-26 22:47:21 +02:00
7 changed files with 494 additions and 323 deletions

View 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
View 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

View file

@ -46,10 +46,10 @@ test-suite haddock2-test
type: exitcode-stdio-1.0 type: exitcode-stdio-1.0
main-is: Spec.hs main-is: Spec.hs
build-depends: build-depends:
parsec ^>=3.1.18.0,
base >=4.20.1.0, base >=4.20.1.0,
haddock2:{haddock2-lib}, haddock2:{haddock2-lib},
hspec ^>=2.11.0, hspec ^>=2.11.0,
parsec ^>=3.1.18.0,
text ^>=2.1.2, text ^>=2.1.2,
hs-source-dirs: test hs-source-dirs: test

View file

@ -4,7 +4,8 @@ module Lexer (
Token (..), Token (..),
lexer, lexer,
emphasis, emphasis,
) where )
where
import Control.Monad (mfilter, void) import Control.Monad (mfilter, void)
import Data.Functor (($>)) import Data.Functor (($>))
@ -17,6 +18,7 @@ import Text.Parsec qualified as Parsec
import Text.Parsec.Pos (updatePosChar) import Text.Parsec.Pos (updatePosChar)
type Located a = (SourcePos, a) type Located a = (SourcePos, a)
type LocatedToken = (SourcePos, Token) type LocatedToken = (SourcePos, Token)
type Lexer = Parser [LocatedToken] type Lexer = Parser [LocatedToken]
@ -67,7 +69,7 @@ located :: Parser a -> Parser (SourcePos, a)
located p = (,) <$> getPosition <*> p located p = (,) <$> getPosition <*> p
tokenise :: [Parser a] -> Parser [(SourcePos, a)] tokenise :: [Parser a] -> Parser [(SourcePos, a)]
tokenise = sequence . map located tokenise = mapM located
lexer :: String -> Either ParseError [LocatedToken] lexer :: String -> Either ParseError [LocatedToken]
lexer = Parsec.runParser lexText initialParserState "input" . Text.pack lexer = Parsec.runParser lexText initialParserState "input" . Text.pack
@ -144,7 +146,7 @@ delimitedNoTrailing openP closeP openTok = asList <$> delimitedAsTuple (openTok
asList (a, tok, _) = [a, tok] asList (a, tok, _) = [a, tok]
delimitedSymmetric :: Parser a -> Token -> Token -> Parser [LocatedToken] delimitedSymmetric :: Parser a -> Token -> Token -> Parser [LocatedToken]
delimitedSymmetric s t1 t2 = delimited s s t1 t2 delimitedSymmetric s = delimited s s
eol :: Parser () eol :: Parser ()
eol = void "\n" <|> void "\r\n" <|> Parsec.eof eol = void "\n" <|> void "\r\n" <|> Parsec.eof
@ -173,7 +175,6 @@ anchor = do
x <- located $ between "#" "#" (Anchor <$> anyUntil "#") x <- located $ between "#" "#" (Anchor <$> anyUntil "#")
pure [x] pure [x]
moduleNames :: Parser Text moduleNames :: Parser Text
moduleNames = intercalate "." . fmap Text.pack <$> upperId `sepBy1` char '.' moduleNames = intercalate "." . fmap Text.pack <$> upperId `sepBy1` char '.'
@ -228,7 +229,7 @@ labeledLink = do
labelRes <- located $ Token <$> anyUntil ">" labelRes <- located $ Token <$> anyUntil ">"
close <- located $ LabeledLinkClose <$ ">" close <- located $ LabeledLinkClose <$ ">"
pure $ pure $
open : linkRes <> [ labelRes , close ] open : linkRes <> [labelRes, close]
mathMultiline :: Lexer mathMultiline :: Lexer
mathMultiline = delimited "\\[" "\\]" MathMultilineOpen MathMultilineClose mathMultiline = delimited "\\[" "\\]" MathMultilineOpen MathMultilineClose
@ -302,6 +303,7 @@ scan ::
Parser Text Parser Text
scan f initState = do scan f initState = do
parserState@State{stateInput = input, statePos = pos} <- Parsec.getParserState parserState@State{stateInput = input, statePos = pos} <- Parsec.getParserState
(remaining, finalPos, ct) <- go input initState pos 0 (remaining, finalPos, ct) <- go input initState pos 0
let newState = parserState{stateInput = remaining, statePos = finalPos} let newState = parserState{stateInput = remaining, statePos = finalPos}
Parsec.setParserState newState $> Text.take ct input Parsec.setParserState newState $> Text.take ct input

View file

@ -13,7 +13,9 @@ import Text.Parsec.Pos (updatePosChar)
Return everything consumed except for the end pattern itself. Return everything consumed except for the end pattern itself.
-} -}
takeUntil :: Text -> Parser Text 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 where
end = Text.unpack end_ end = Text.unpack end_

View file

@ -9,6 +9,8 @@ module Types (
) )
where where
import Data.Foldable (fold)
newtype Document = Document newtype Document = Document
{ meta :: Meta { meta :: Meta
} }
@ -28,6 +30,7 @@ data Since = Since
-- Could have a better type? -- Could have a better type?
type Version = [Int] type Version = [Int]
type Package = String type Package = String
data DocMarkup mod id data DocMarkup mod id
@ -136,7 +139,7 @@ instance Semigroup (DocMarkup mod id) where
instance Monoid (DocMarkup mod id) where instance Monoid (DocMarkup mod id) where
mempty = DocEmpty mempty = DocEmpty
mconcat = foldr (<>) mempty mconcat = fold
data ModuleLink id = ModuleLink data ModuleLink id = ModuleLink
{ name :: String { name :: String

View file

@ -1,17 +1,15 @@
{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE OverloadedStrings #-}
{-# OPTIONS_GHC -Wno-orphans #-} {-# OPTIONS_GHC -Wno-orphans #-}
import Test.Hspec import Data.String (IsString (..))
import Data.Text (Text)
import GHC.Stack
import Identifier (Identifier) import Identifier (Identifier)
import Lexer import Lexer
import Parser import Parser
import Types import Test.Hspec
import Data.String (IsString (..))
import Data.Text (Text)
import Text.Parsec.Pos import Text.Parsec.Pos
import GHC.Stack import Types
main :: IO () main :: IO ()
main = hspec $ do main = hspec $ do
@ -34,9 +32,9 @@ main = hspec $ do
describe "Parser" do describe "Parser" do
it "Bold" do it "Bold" do
"__bold__" `shouldParseTo` (DocBold (DocString "bold")) "__bold__" `shouldParseTo` DocBold (DocString "bold")
it "Emphasis" do it "Emphasis" do
"/emphasis/" `shouldParseTo` (DocEmphasis (DocString "emphasis")) "/emphasis/" `shouldParseTo` DocEmphasis (DocString "emphasis")
------------ ------------
-- Tests -- Tests
@ -57,6 +55,7 @@ modules = do
`shouldLexTo` [ (1, 2, Module "OtherModule.Name") `shouldLexTo` [ (1, 2, Module "OtherModule.Name")
, (1, 18, Anchor "myAnchor") , (1, 18, Anchor "myAnchor")
] ]
link :: Expectation link :: Expectation
link = link =
"[link to](http://some.website)" "[link to](http://some.website)"