From 3dde41e0d4848567e4a7fbcd20f43d35ce8e2dbf Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Fri, 13 Sep 2024 21:58:13 +0200 Subject: [PATCH] Introduce a matcher for one or more matched digits --- lib/SlackBuilder/LatestVersionCheck.hs | 26 +++++++++++--------- tests/SlackBuilder/LatestVersionCheckSpec.hs | 7 +++++- 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/lib/SlackBuilder/LatestVersionCheck.hs b/lib/SlackBuilder/LatestVersionCheck.hs index a1ed946..523451e 100644 --- a/lib/SlackBuilder/LatestVersionCheck.hs +++ b/lib/SlackBuilder/LatestVersionCheck.hs @@ -62,8 +62,8 @@ data MatchState = MatchState data MatchToken = OpenParenMatchToken | CloseParenMatchToken - | AsteriskMatchToken | SymbolMatchToken Char + | AtLeastMatchToken [Char] | OneOfMatchToken [Char] deriving (Eq, Show) @@ -76,6 +76,7 @@ data MatchToken -- * ( ) - The text in parentheses is matched but no saved in the resulting -- string. -- * \\d - Matches zero or more digits. +-- * \\D - Matches one or more digits. -- * \\. - Matches zero or more digits or dots. -- * \\\\ - Matches a back slash. -- * * - Matches everything. @@ -103,20 +104,21 @@ match fullPattern = go startState go (state{ ignoring = True, pattern' = tokens }) input' go state@MatchState{ pattern' = CloseParenMatchToken : tokens } input' = go (state{ ignoring = False, pattern' = tokens }) input' - go state@MatchState{ pattern' = AsteriskMatchToken : tokens } input' - | Just (nextCharacter, leftOver) <- Text.uncons input' = - go (matchSymbolToken state nextCharacter) leftOver - | otherwise = go state{ pattern' = tokens } "" + go state@MatchState{ pattern' = SymbolMatchToken patternCharacter : tokens } input' + | Just (nextCharacter, leftOver) <- Text.uncons input' + , patternCharacter == nextCharacter = + go (matchSymbolToken state{ pattern' = tokens } nextCharacter) leftOver + | otherwise = Nothing go state@MatchState{ pattern' = OneOfMatchToken chars : tokens } input' | Just (nextCharacter, leftOver) <- Text.uncons input' , nextCharacter `elem` chars = go (matchSymbolToken state nextCharacter) leftOver | otherwise = go (state{ pattern' = tokens }) input' - go state@MatchState{ pattern' = SymbolMatchToken patternCharacter : tokens } input' + go state@MatchState{ pattern' = AtLeastMatchToken chars : tokens } input' | Just (nextCharacter, leftOver) <- Text.uncons input' - , patternCharacter == nextCharacter = - go (matchSymbolToken state{ pattern' = tokens } nextCharacter) leftOver + , nextCharacter `elem` chars = + go (matchSymbolToken state{ pattern' = OneOfMatchToken chars : tokens } nextCharacter) leftOver | otherwise = Nothing -- All tokens are processed, but there is still some input left. go MatchState{ pattern' = [] } _ = Nothing @@ -134,7 +136,9 @@ parsePattern input' Nothing -> [] Just ('d', remaining') -> OneOfMatchToken digits : parsePattern remaining' - Just ('.', remaining') -> OneOfMatchToken ('.' : digits) + Just ('D', remaining') -> AtLeastMatchToken digits + : parsePattern remaining' + Just ('.', remaining') -> AtLeastMatchToken ('.' : digits) : parsePattern remaining' Just ('\\', remaining') -> SymbolMatchToken '\\' : parsePattern remaining' @@ -147,11 +151,11 @@ parsePattern input' | Just (firstChar, remaining) <- Text.uncons input' = let token = case firstChar of - '*' -> AsteriskMatchToken + '*' -> OneOfMatchToken (toEnum <$> [32 .. 127]) '(' -> OpenParenMatchToken ')' -> CloseParenMatchToken s -> SymbolMatchToken s - in token : parsePattern remaining + in token : parsePattern remaining | otherwise = [] where digits = toEnum <$> [fromEnum '0' .. fromEnum '9'] diff --git a/tests/SlackBuilder/LatestVersionCheckSpec.hs b/tests/SlackBuilder/LatestVersionCheckSpec.hs index cfdd195..54901c1 100644 --- a/tests/SlackBuilder/LatestVersionCheckSpec.hs +++ b/tests/SlackBuilder/LatestVersionCheckSpec.hs @@ -27,7 +27,7 @@ spec = do actual = match "(v)2.6.\\d" "v2.6.0" in actual `shouldBe` expected - it "matches digits and dot" $ + it "matches digits and dots" $ let expected = Just "2.6.0" actual = match "(v)\\." "v2.6.0" in actual `shouldBe` expected @@ -46,3 +46,8 @@ spec = do let expected = Just "abc" actual = match "abc\\d\\d" "abc" in actual `shouldBe` expected + + it "matches at least one digit" $ + let expected = Nothing + actual = match "1.\\D.3" "1..3" + in actual `shouldBe` expected