Skip to content

Introduce purs-tidy formatter #76

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Nov 20, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ jobs:

- name: Set up a PureScript toolchain
uses: purescript-contrib/setup-purescript@main
with:
purs-tidy: "latest"

- name: Cache PureScript dependencies
uses: actions/cache@v2
Expand All @@ -32,3 +34,6 @@ jobs:

- name: Run tests
run: spago test --no-install

- name: Check formatting
run: purs-tidy check src test
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
!.gitignore
!.github
!.editorconfig
!.tidyrc.json

output
generated-docs
Expand Down
10 changes: 10 additions & 0 deletions .tidyrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"importSort": "source",
"importWrap": "source",
"indent": 2,
"operatorsFile": null,
"ribbon": 1,
"typeArrowPlacement": "first",
"unicode": "never",
"width": null
}
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ New features:
Bugfixes:

Other improvements:
- Added `purs-tidy` formatter (#76 by @thomashoneyman)

- Run slowest tests last and print status updates (#72)

Expand Down
11 changes: 6 additions & 5 deletions src/Text/Parsing/StringParser.purs
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,9 @@ instance applicativeParser :: Applicative Parser where
instance altParser :: Alt Parser where
alt (Parser p1) (Parser p2) = Parser \s ->
case p1 s of
Left { error, pos } | s.pos == pos -> p2 s
| otherwise -> Left { error, pos }
Left { error, pos }
| s.pos == pos -> p2 s
| otherwise -> Left { error, pos }
right -> right

instance plusParser :: Plus Parser where
Expand All @@ -87,8 +88,8 @@ instance monadPlusParser :: MonadPlus Parser
instance monadRecParser :: MonadRec Parser where
tailRecM f a = Parser \str -> tailRecM (\st -> map split (unParser (f st.state) st.str)) { state: a, str }
where
split { result: Loop state, suffix: str } = Loop { state, str }
split { result: Done b, suffix } = Done { result: b, suffix }
split { result: Loop state, suffix: str } = Loop { state, str }
split { result: Done b, suffix } = Done { result: b, suffix }

instance lazyParser :: Lazy (Parser a) where
defer f = Parser $ \str -> unParser (f unit) str
Expand All @@ -101,7 +102,7 @@ fail error = Parser \{ pos } -> Left { pos, error }
-- |
-- | `try p` backtracks even if input was consumed.
try :: forall a. Parser a -> Parser a
try (Parser p) = Parser \(s@{ pos }) -> lmap (_ { pos = pos}) (p s)
try (Parser p) = Parser \(s@{ pos }) -> lmap (_ { pos = pos }) (p s)

instance semigroupParser :: Semigroup a => Semigroup (Parser a) where
append = lift2 append
Expand Down
56 changes: 24 additions & 32 deletions src/Text/Parsing/StringParser/CodePoints.purs
Original file line number Diff line number Diff line change
Expand Up @@ -55,15 +55,14 @@ anyChar = Parser \{ str, pos } ->
Nothing -> Left { pos, error: "CodePoint " <> show cp <> " is not a character" }
Nothing -> Left { pos, error: "Unexpected EOF" }
where
toChar = fromCharCode <<< fromEnum
toChar = fromCharCode <<< fromEnum

-- | Match any digit.
anyDigit :: Parser Char
anyDigit = try do
c <- anyChar
if c >= '0' && c <= '9'
then pure c
else fail $ "Character " <> show c <> " is not a digit"
if c >= '0' && c <= '9' then pure c
else fail $ "Character " <> show c <> " is not a digit"

-- | Match the specified string.
string :: String -> Parser String
Expand All @@ -76,9 +75,8 @@ string nt = Parser \s ->
satisfy :: (Char -> Boolean) -> Parser Char
satisfy f = try do
c <- anyChar
if f c
then pure c
else fail $ "Character " <> show c <> " did not satisfy predicate"
if f c then pure c
else fail $ "Character " <> show c <> " did not satisfy predicate"

-- | Match the specified character.
char :: Char -> Parser Char
Expand All @@ -87,7 +85,7 @@ char c = satisfy (_ == c) <?> "Could not match character " <> show c
-- | Match many whitespace characters.
whiteSpace :: Parser String
whiteSpace = do
cs <- many (satisfy \ c -> c == '\n' || c == '\r' || c == ' ' || c == '\t')
cs <- many (satisfy \c -> c == '\n' || c == '\r' || c == ' ' || c == '\t')
pure (foldMap singleton cs)

-- | Skip many whitespace characters.
Expand All @@ -106,17 +104,15 @@ noneOf = satisfy <<< flip notElem
lowerCaseChar :: Parser Char
lowerCaseChar = try do
c <- anyChar
if toCharCode c `elem` (97 .. 122)
then pure c
else fail $ "Expected a lower case character but found " <> show c
if toCharCode c `elem` (97 .. 122) then pure c
else fail $ "Expected a lower case character but found " <> show c

-- | Match any upper case character.
upperCaseChar :: Parser Char
upperCaseChar = try do
c <- anyChar
if toCharCode c `elem` (65 .. 90)
then pure c
else fail $ "Expected an upper case character but found " <> show c
if toCharCode c `elem` (65 .. 90) then pure c
else fail $ "Expected an upper case character but found " <> show c

-- | Match any letter.
anyLetter :: Parser Char
Expand All @@ -135,21 +131,17 @@ regex pat =
Right r ->
matchRegex r
where
-- ensure the pattern only matches the current position in the parse
pattern =
case stripPrefix (Pattern "^") pat of
Nothing ->
"^" <> pat
_ ->
pat
matchRegex :: Regex.Regex -> Parser String
matchRegex r =
Parser \{ str, pos } ->
let
remainder = drop pos str
in
case NEA.head <$> Regex.match r remainder of
Just (Just matched) ->
Right { result: matched, suffix: { str, pos: pos + length matched } }
_ ->
Left { pos, error: "no match" }
-- ensure the pattern only matches the current position in the parse
pattern =
case stripPrefix (Pattern "^") pat of
Nothing -> "^" <> pat
_ -> pat

matchRegex :: Regex.Regex -> Parser String
matchRegex r = Parser \{ str, pos } -> do
let remainder = drop pos str
case NEA.head <$> Regex.match r remainder of
Just (Just matched) ->
Right { result: matched, suffix: { str, pos: pos + length matched } }
_ ->
Left { pos, error: "no match" }
54 changes: 23 additions & 31 deletions src/Text/Parsing/StringParser/CodeUnits.purs
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,8 @@ anyChar = Parser \{ str, pos } ->
anyDigit :: Parser Char
anyDigit = try do
c <- anyChar
if c >= '0' && c <= '9'
then pure c
else fail $ "Character " <> show c <> " is not a digit"
if c >= '0' && c <= '9' then pure c
else fail $ "Character " <> show c <> " is not a digit"

-- | Match the specified string.
string :: String -> Parser String
Expand All @@ -71,9 +70,8 @@ string nt = Parser \s ->
satisfy :: (Char -> Boolean) -> Parser Char
satisfy f = try do
c <- anyChar
if f c
then pure c
else fail $ "Character " <> show c <> " did not satisfy predicate"
if f c then pure c
else fail $ "Character " <> show c <> " did not satisfy predicate"

-- | Match the specified character.
char :: Char -> Parser Char
Expand All @@ -82,7 +80,7 @@ char c = satisfy (_ == c) <?> "Could not match character " <> show c
-- | Match many whitespace characters.
whiteSpace :: Parser String
whiteSpace = do
cs <- many (satisfy \ c -> c == '\n' || c == '\r' || c == ' ' || c == '\t')
cs <- many (satisfy \c -> c == '\n' || c == '\r' || c == ' ' || c == '\t')
pure (foldMap singleton cs)

-- | Skip many whitespace characters.
Expand All @@ -101,17 +99,15 @@ noneOf = satisfy <<< flip notElem
lowerCaseChar :: Parser Char
lowerCaseChar = try do
c <- anyChar
if toCharCode c `elem` (97 .. 122)
then pure c
else fail $ "Expected a lower case character but found " <> show c
if toCharCode c `elem` (97 .. 122) then pure c
else fail $ "Expected a lower case character but found " <> show c

-- | Match any upper case character.
upperCaseChar :: Parser Char
upperCaseChar = try do
c <- anyChar
if toCharCode c `elem` (65 .. 90)
then pure c
else fail $ "Expected an upper case character but found " <> show c
if toCharCode c `elem` (65 .. 90) then pure c
else fail $ "Expected an upper case character but found " <> show c

-- | Match any letter.
anyLetter :: Parser Char
Expand All @@ -130,21 +126,17 @@ regex pat =
Right r ->
matchRegex r
where
-- ensure the pattern only matches the current position in the parse
pattern =
case SCU.stripPrefix (Pattern "^") pat of
Nothing ->
"^" <> pat
_ ->
pat
matchRegex :: Regex.Regex -> Parser String
matchRegex r =
Parser \{ str, pos } ->
let
remainder = SCU.drop pos str
in
case NEA.head <$> Regex.match r remainder of
Just (Just matched) ->
Right { result: matched, suffix: { str, pos: pos + SCU.length matched } }
_ ->
Left { pos, error: "no match" }
-- ensure the pattern only matches the current position in the parse
pattern =
case SCU.stripPrefix (Pattern "^") pat of
Nothing -> "^" <> pat
_ -> pat

matchRegex :: Regex.Regex -> Parser String
matchRegex r = Parser \{ str, pos } -> do
let remainder = SCU.drop pos str
case NEA.head <$> Regex.match r remainder of
Just (Just matched) ->
Right { result: matched, suffix: { str, pos: pos + SCU.length matched } }
_ ->
Left { pos, error: "no match" }
42 changes: 25 additions & 17 deletions src/Text/Parsing/StringParser/Combinators.purs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
-- | This module defines combinators for building string parsers.

module Text.Parsing.StringParser.Combinators
( lookAhead
, many
, many1
, withError, (<?>)
, withError
, (<?>)
, between
, option
, optional
Expand Down Expand Up @@ -97,9 +97,11 @@ sepEndBy p sep = map NEL.toList (sepEndBy1 p sep) <|> pure Nil
sepEndBy1 :: forall a sep. Parser a -> Parser sep -> Parser (NonEmptyList a)
sepEndBy1 p sep = do
a <- p
(do _ <- sep
( do
_ <- sep
as <- sepEndBy p sep
pure (cons' a as)) <|> pure (NEL.singleton a)
pure (cons' a as)
) <|> pure (NEL.singleton a)

-- | Parse one or more separated values, ending with a separator.
endBy1 :: forall a sep. Parser a -> Parser sep -> Parser (NonEmptyList a)
Expand All @@ -125,9 +127,12 @@ chainl1 p f = do

-- | Parse one or more values separated by a left-associative operator.
chainl1' :: forall a. Parser a -> Parser (a -> a -> a) -> a -> Parser a
chainl1' p f a = (do f' <- f
a' <- p
chainl1' p f (f' a a')) <|> pure a
chainl1' p f a =
( do
f' <- f
a' <- p
chainl1' p f (f' a a')
) <|> pure a

-- | Parse one or more values separated by a right-associative operator.
chainr1 :: forall a. Parser a -> Parser (a -> a -> a) -> Parser a
Expand All @@ -137,9 +142,12 @@ chainr1 p f = do

-- | Parse one or more values separated by a right-associative operator.
chainr1' :: forall a. Parser a -> Parser (a -> a -> a) -> a -> Parser a
chainr1' p f a = (do f' <- f
a' <- chainr1 p f
pure $ f' a a') <|> pure a
chainr1' p f a =
( do
f' <- f
a' <- chainr1 p f
pure $ f' a a'
) <|> pure a

-- | Parse using any of a collection of parsers.
choice :: forall f a. Foldable f => f (Parser a) -> Parser a
Expand All @@ -155,13 +163,13 @@ many1Till p end = do
x <- p
tailRecM inner (pure x)
where
ending acc = do
_ <- end
pure $ Done (NEL.reverse acc)
continue acc = do
c <- p
pure $ Loop (NEL.cons c acc)
inner acc = ending acc <|> continue acc
ending acc = do
_ <- end
pure $ Done (NEL.reverse acc)
continue acc = do
c <- p
pure $ Loop (NEL.cons c acc)
inner acc = ending acc <|> continue acc

cons' :: forall a. a -> List a -> NonEmptyList a
cons' h t = NonEmptyList (h :| t)
Loading