Skip to content

Introduce purs-tidy formatter #85

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 19, 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 (#85 by @thomashoneyman)
- Update readme to show how to use newtypes (#57 by @brodeuralexis and @JordanMartinez)

## [v10.0.1](https://github.com/purescript-contrib/purescript-routing/releases/tag/v10.0.1) - 2021-05-06
Expand Down
2 changes: 1 addition & 1 deletion src/Routing.purs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import Prelude
import Data.Either (Either)
import Data.Maybe (fromJust)
import JSURI (decodeURIComponent)
import Partial.Unsafe(unsafePartial)
import Partial.Unsafe (unsafePartial)
import Routing.Match (Match, runMatch)
import Routing.Parser (parse)

Expand Down
33 changes: 17 additions & 16 deletions src/Routing/Match.purs
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,12 @@ instance matchAlternative :: Alternative Match
instance matchApply :: Apply Match where
apply (Match r2a2b) (Match r2a) =
Match $ (\r -> validation (processFnErr r) processFnRes (r2a2b r))
where processFnErr r err =
invalid $ err * validation identity (const one) (r2a r)
processFnRes (Tuple rs a2b) =
validation invalid (\(Tuple rss a) -> pure $ Tuple rss (a2b a)) (r2a rs)
where
processFnErr r err =
invalid $ err * validation identity (const one) (r2a r)

processFnRes (Tuple rs a2b) =
validation invalid (\(Tuple rss a) -> pure $ Tuple rss (a2b a)) (r2a rs)

instance matchApplicative :: Applicative Match where
pure a = Match \r -> pure $ Tuple r a
Expand All @@ -61,7 +63,7 @@ lit input = Match \route ->
Cons (Path i) rs | i == input ->
pure $ Tuple rs unit
Cons (Path _) _ ->
invalid $ free $ UnexpectedPath input
invalid $ free $ UnexpectedPath input
_ ->
invalid $ free ExpectedPathPart

Expand Down Expand Up @@ -119,9 +121,8 @@ param key = Match \route ->
Just el -> do
let remainingParams = M.delete key map
pure $
if M.isEmpty remainingParams
then Tuple rs el
else Tuple (Cons (Query remainingParams) rs) el
if M.isEmpty remainingParams then Tuple rs el
else Tuple (Cons (Query remainingParams) rs) el
_ ->
invalid $ free ExpectedQuery

Expand Down Expand Up @@ -158,12 +159,13 @@ nonempty =
list :: forall a. Match a -> Match (List a)
list (Match r2a) =
Match $ go Nil
where go :: List a -> Route -> V (Free MatchError) (Tuple Route (List a))
go accum r =
validation
(const $ pure (Tuple r (reverse accum)))
(\(Tuple rs a) -> go (Cons a accum) rs)
(r2a r)
where
go :: List a -> Route -> V (Free MatchError) (Tuple Route (List a))
go accum r =
validation
(const $ pure (Tuple r (reverse accum)))
(\(Tuple rs a) -> go (Cons a accum) rs)
(r2a r)

-- It groups `Free MatchError` -> [[MatchError]] -map with showMatchError ->
-- [[String]] -fold with semicolon-> [String] -fold with newline-> String
Expand All @@ -174,8 +176,7 @@ runMatch (Match fn) route =
foldErrors errs =
Left $ foldl (\b a -> a <> "\n" <> b) "" do
es <- reverse <$> unwrap errs
pure $ foldl (\b a -> a <> ";" <> b) "" $ showMatchError <$> es

pure $ foldl (\b a -> a <> ";" <> b) "" $ showMatchError <$> es

-- | if we match something that can fail then we have to
-- | match `Either a b`. This function converts matching on such
Expand Down
10 changes: 0 additions & 10 deletions src/Routing/Match/Error.purs
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,15 @@ module Routing.Match.Error where
import Prelude ((<>))

data MatchError
-- expected other path part
= UnexpectedPath String
-- expected "true" or "false"
| ExpectedBoolean
-- expected end
| ExpectedEnd
-- expected numeric literal
| ExpectedNumber
-- expected integer literal
| ExpectedInt
-- expected string literal (found query probably or eol)
| ExpectedString
-- expected query found path part or eol
| ExpectedQuery
-- expected path part found query or eol
| ExpectedPathPart
-- there is no such key in query
| KeyNotFound String
-- custom fail
| Fail String

showMatchError :: MatchError -> String
Expand Down
22 changes: 10 additions & 12 deletions src/Routing/Parser.purs
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@ parseQueryPart :: (String -> String) -> String -> Maybe (M.Map String String)
parseQueryPart decoder =
map M.fromFoldable <<< traverse part2tuple <<< S.split (S.Pattern "&")
where
part2tuple :: String -> Maybe (Tuple String String)
part2tuple input = do
let keyVal = decoder <$> S.split (S.Pattern "=") input
guard $ A.length keyVal <= 2
Tuple <$> A.head keyVal <*> keyVal A.!! 1
part2tuple :: String -> Maybe (Tuple String String)
part2tuple input = do
let keyVal = decoder <$> S.split (S.Pattern "=") input
guard $ A.length keyVal <= 2
Tuple <$> A.head keyVal <*> keyVal A.!! 1

-- | Parse hash string to `Route` with `decoder` function
-- | applied to every hash part (usually `decodeURIComponent`)
Expand All @@ -36,10 +36,8 @@ parse decoder hash =
Nothing ->
pathParts hash
where
pathParts str =
let
parts = L.fromFoldable $ map (Path <<< decoder) (S.split (S.Pattern "/") str)
in
case L.unsnoc parts of
Just { init, last: Path "" } -> init
_ -> parts
pathParts str = do
let parts = L.fromFoldable $ map (Path <<< decoder) (S.split (S.Pattern "/") str)
case L.unsnoc parts of
Just { init, last: Path "" } -> init
_ -> parts
15 changes: 8 additions & 7 deletions src/Routing/PushState.purs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ makeInterface = do
-- interface to behave as similarly as possible, so we use `makeImmediate`
-- which will execute `notify` maximum once per event loop.
schedule <- makeImmediate $ notify =<< locationState

let
stateFn op state path = do
DOM.window
Expand All @@ -102,7 +103,7 @@ makeInterface = do

DOM.window
>>= Window.toEventTarget
>>> DOM.addEventListener ET.popstate listener false
>>> DOM.addEventListener ET.popstate listener false

pure
{ pushState: stateFn History.pushState
Expand Down Expand Up @@ -188,17 +189,17 @@ matchesWith parser cb = foldPaths go (go Nothing)
-- | from: https://github.com/natefaubion/purescript-spork/blob/3b56c4d36e84866ed9b1bc27afa7ab4762ffdd01/src/Spork/Scheduler.purs#L20
makeImmediate :: Effect Unit -> Effect (Effect Unit)
makeImmediate run = do
document
document <-
DOM.window
>>= Window.document
>>> map HTMLDocument.toDocument
nextTick Ref.new (Right 0)
obsvNode Text.toNode <$> DOM.createTextNode "" document
observer DOM.mutationObserver \_ _ do
>>> map HTMLDocument.toDocument
nextTick <- Ref.new (Right 0)
obsvNode <- Text.toNode <$> DOM.createTextNode "" document
observer <- DOM.mutationObserver \_ _ -> do
Ref.modify_ (either (Right <<< add 1) Right) nextTick
run
DOM.observe obsvNode { characterData: true } observer
pure do
Ref.read nextTick >>= traverse_ \tick do
Ref.read nextTick >>= traverse_ \tick -> do
Ref.write (Left (tick + 1)) nextTick
DOM.setNodeValue (show tick) obsvNode
26 changes: 12 additions & 14 deletions test/Test/Browser.purs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ type TestInterface =

withTest :: (TestInterface -> Effect Unit) -> Effect Unit
withTest k = do
doc <- window >>= Window.document
doc <- window >>= Window.document
body <- HTMLDocument.body doc >>= maybe (throwException (error "Body not found")) pure

let
Expand Down Expand Up @@ -82,30 +82,28 @@ withTest k = do

assertEq :: forall a. Show a => Eq a => String -> a -> a -> Effect Unit
assertEq testName a b = do
if a == b
then do
void $ flip Node.appendChild (HTMLElement.toNode body) =<< renderSuccess testName
else do
let err = show a <> " /= " <> show b
_ <- flip Node.appendChild (HTMLElement.toNode body) =<< renderError testName err
throwException (error $ testName <> ": " <> err)
if a == b then do
void $ flip Node.appendChild (HTMLElement.toNode body) =<< renderSuccess testName
else do
let err = show a <> " /= " <> show b
_ <- flip Node.appendChild (HTMLElement.toNode body) =<< renderError testName err
throwException (error $ testName <> ": " <> err)

assert :: String -> Boolean -> Effect Unit
assert testName = assertEq testName true

k { assert, assertEq }


runHashTests :: Effect Unit -> Effect Unit
runHashTests next = withTest \{ assert } -> do
doneRef <- Ref.new (pure unit)
let done = join (Ref.read doneRef) *> next
flip Ref.write doneRef =<< hashes case _, _ of
Nothing, "" -> assert "Hashes: Initial value" true
Just "", "a" -> assert "Hashes: ? -> a" true *> setHash "b"
Nothing, "" -> assert "Hashes: Initial value" true
Just "", "a" -> assert "Hashes: ? -> a" true *> setHash "b"
Just "a", "b" -> assert "Hashes: a -> b" true *> setHash ""
Just "b", "" -> assert "Hashes: b -> ?" true *> done
_, _ -> assert "Hashes: fail" false
Just "b", "" -> assert "Hashes: b -> ?" true *> done
_, _ -> assert "Hashes: fail" false
setHash "a"

runPushStateTests :: Effect Unit
Expand Down Expand Up @@ -157,4 +155,4 @@ main = do
listener <- eventListener \_ -> runHashTests runPushStateTests
window
>>= Window.toEventTarget
>>> addEventListener load listener false
>>> addEventListener load listener false
13 changes: 7 additions & 6 deletions test/Test/Main.purs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ data MyRoutes

derive instance eqMyRoutes :: Eq MyRoutes
derive instance genericMyRoutes :: Generic MyRoutes _
instance showMyRoutes :: Show MyRoutes where show = genericShow
instance showMyRoutes :: Show MyRoutes where
show = genericShow

routing :: Match MyRoutes
routing = oneOf
Expand All @@ -47,11 +48,11 @@ main :: Effect Unit
main = do
assertEqual
{ actual: match routing "foo/12/?welp='hi'&b=false"
, expected: Right (Foo 12.0 (M.fromFoldable [Tuple "welp" "'hi'", Tuple "b" "false"]))
, expected: Right (Foo 12.0 (M.fromFoldable [ Tuple "welp" "'hi'", Tuple "b" "false" ]))
}
assertEqual
{ actual: match routing "foo/12?welp='hi'&b=false"
, expected: Right (Foo 12.0 (M.fromFoldable [Tuple "welp" "'hi'", Tuple "b" "false"]))
, expected: Right (Foo 12.0 (M.fromFoldable [ Tuple "welp" "'hi'", Tuple "b" "false" ]))
}
assertEqual
{ actual: match routing "bar/true?baz=test"
Expand Down Expand Up @@ -91,11 +92,11 @@ main = do
}
assertEqual
{ actual: match routing "list/123/"
, expected: Right (Baz (L.fromFoldable [123.0]))
, expected: Right (Baz (L.fromFoldable [ 123.0 ]))
}
assertEqual
{ actual: match routing "list/123/456"
, expected: Right (Baz (L.fromFoldable [123.0, 456.0]))
, expected: Right (Baz (L.fromFoldable [ 123.0, 456.0 ]))
}
assertEqual
{ actual: match routing "list/"
Expand All @@ -111,5 +112,5 @@ main = do
}
assertEqual
{ actual: match routing "foo/0/?test=a/b/c"
, expected: Right (Foo 0.0 (M.fromFoldable [Tuple "test" "a/b/c"]))
, expected: Right (Foo 0.0 (M.fromFoldable [ Tuple "test" "a/b/c" ]))
}