Skip to content

Commit

Permalink
Improve arg parsing error messages
Browse files Browse the repository at this point in the history
  • Loading branch information
tbidne committed Nov 27, 2024
1 parent 0d140e9 commit 3b03f13
Show file tree
Hide file tree
Showing 14 changed files with 115 additions and 55 deletions.
4 changes: 2 additions & 2 deletions src/Shrun/Configuration/Args/Parsing/ConsoleLogging.hs
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ lineTruncParser = Utils.withDisabledParser mainParser "console-log-line-trunc"
( mconcat
[ OA.long "console-log-line-trunc",
Utils.mkHelp helpTxt,
OA.metavar "(NATURAL | detect)"
OA.metavar Trunc.lineTruncStr
]
)
helpTxt =
Expand All @@ -124,7 +124,7 @@ stripControlParser =
( mconcat
[ OA.long "console-log-strip-control",
Utils.mkHelp helpTxt,
OA.metavar "(all | smart | none)"
OA.metavar StripControl.stripControlStr
]
)
helpTxt =
Expand Down
2 changes: 1 addition & 1 deletion src/Shrun/Configuration/Args/Parsing/Core.hs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ timeoutParser = Utils.withDisabledParser mainParser "timeout"
[ OA.long "timeout",
OA.short 't',
Utils.mkHelp helpTxt,
OA.metavar "(NATURAL | STRING)"
OA.metavar Timeout.timeoutStr
]
)
helpTxt =
Expand Down
6 changes: 3 additions & 3 deletions src/Shrun/Configuration/Args/Parsing/FileLogging.hs
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ lineTruncParser = Utils.withDisabledParser mainParser "file-log-line-trunc"
( mconcat
[ OA.long "file-log-line-trunc",
Utils.mkHelp helpTxt,
OA.metavar "(NATURAL | detect)"
OA.metavar Trunc.lineTruncStr
]
)
helpTxt = "Like --console-log-line-trunc, but for --file-log."
Expand All @@ -153,7 +153,7 @@ fileLogStripControlParser =
( mconcat
[ OA.long "file-log-strip-control",
Utils.mkHelp helpTxt,
OA.metavar "(all | smart | none)"
OA.metavar StripControl.stripControlStr
]
)
helpTxt =
Expand Down Expand Up @@ -192,7 +192,7 @@ fileLogSizeModeParser = Utils.withDisabledParser mainParser "file-log-size-mode"
( mconcat
[ OA.long "file-log-size-mode",
Utils.mkHelp helpTxt,
OA.metavar FileSizeMode.expectedStr
OA.metavar FileSizeMode.fileSizeModeStr
]
)
helpTxt =
Expand Down
13 changes: 6 additions & 7 deletions src/Shrun/Configuration/Data/CommandLogging/ReadStrategy.hs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ where

import Shrun.Data.Command (CommandP1)
import Shrun.Prelude
import Shrun.Utils qualified as Utils

-- | Different read strategies for simplicity vs. potential prettier
-- formatting.
Expand Down Expand Up @@ -42,14 +43,12 @@ parseReadStrategy getTxt =
getTxt >>= \case
"block" -> pure ReadBlock
"block-line-buffer" -> pure ReadBlockLineBuffer
other ->
bad ->
fail
$ mconcat
[ "Unrecognized read strategy: '",
unpack other,
"'. Expected one of ",
readStrategyStr
]
$ Utils.fmtUnrecognizedError
"read strategy"
readStrategyStr
(unpack bad)
{-# INLINEABLE parseReadStrategy #-}

-- | Available 'ReadStrategy' strings.
Expand Down
8 changes: 7 additions & 1 deletion src/Shrun/Configuration/Data/ConsoleLogging/TimerFormat.hs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import Data.Time.Relative qualified as RT
import Shrun.Configuration.Default (Default (def))
import Shrun.Data.Text (UnlinedText (UnsafeUnlinedText))
import Shrun.Prelude
import Shrun.Utils qualified as Utils

-- | Determines how to format the timer.
data TimerFormat
Expand All @@ -50,7 +51,12 @@ parseTimerFormat getTxt =
"digital_full" -> pure DigitalFull
"prose_compact" -> pure ProseCompact
"prose_full" -> pure ProseFull
bad -> fail $ "Unrecognized timer-format: " <> unpack bad
bad ->
fail
$ Utils.fmtUnrecognizedError
"timer format"
timerFormatStr
(unpack bad)
{-# INLINEABLE parseTimerFormat #-}

-- | Available 'TimerFormat' strings.
Expand Down
12 changes: 11 additions & 1 deletion src/Shrun/Configuration/Data/Core/Timeout.hs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@ module Shrun.Configuration.Data.Core.Timeout
( Timeout (..),
parseTimeout,
parseTimeoutStr,
timeoutStr,
)
where

import Data.Time.Relative qualified as RT
import Shrun.Prelude
import Shrun.Utils qualified as Utils

-- | Represents a timeout, which is a non-negative integer.
newtype Timeout = MkTimeout
Expand Down Expand Up @@ -45,7 +47,15 @@ parseTimeout getNat getTxt =
parseTimeoutStr :: (MonadFail f) => Text -> f Timeout
parseTimeoutStr txt = case RT.fromString str of
Right n -> pure $ MkTimeout $ RT.toSeconds n
Left err -> fail $ "Error reading time string: " <> err
Left bad ->
fail
$ Utils.fmtUnrecognizedError
"timeout"
timeoutStr
bad
where
str = unpack txt
{-# INLINEABLE parseTimeoutStr #-}

timeoutStr :: String
timeoutStr = "(NATURAL | STRING)"
18 changes: 8 additions & 10 deletions src/Shrun/Configuration/Data/FileLogging/FileSizeMode.hs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
module Shrun.Configuration.Data.FileLogging.FileSizeMode
( FileSizeMode (..),
parseFileSizeMode,
expectedStr,
fileSizeModeStr,
)
where

Expand All @@ -12,6 +12,7 @@ import Data.Text qualified as T
import Shrun.Configuration.Default (Default (def))
import Shrun.Prelude
import Shrun.Utils qualified as U
import Shrun.Utils qualified as Utils

-- | Determines what to do if the log file surpasses the given size
-- threshold.
Expand Down Expand Up @@ -39,13 +40,10 @@ parseFileSizeMode getTxt = do
"delete" -> pure FileSizeModeDelete
bad ->
fail
$ mconcat
[ "Expected file-log-size-mode as one of ",
expectedStr,
" received: '",
unpack bad,
"'"
]
$ Utils.fmtUnrecognizedError
"size mode"
fileSizeModeStr
(unpack bad)
case U.parseByteText byteTxt of
Right b -> pure $ cons b
Left err -> fail $ "Could not parse --file-log-size-mode size: " <> unpack err
Expand All @@ -57,5 +55,5 @@ instance Default FileSizeMode where
defBytes :: Bytes M Natural
defBytes = MkBytes 50

expectedStr :: String
expectedStr = "(warn BYTES | delete BYTES | nothing)"
fileSizeModeStr :: String
fileSizeModeStr = "(warn BYTES | delete BYTES | nothing)"
14 changes: 6 additions & 8 deletions src/Shrun/Configuration/Data/Notify/Action.hs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ module Shrun.Configuration.Data.Notify.Action
)
where

import Data.Text qualified as T
import Shrun.Prelude
import Shrun.Utils qualified as Utils

-- | Determines for which actions we should send notifications.
data NotifyAction
Expand All @@ -29,14 +29,12 @@ parseNotifyAction getTxt =
"final" -> pure NotifyFinal
"command" -> pure NotifyCommand
"all" -> pure NotifyAll
other ->
bad ->
fail
$ mconcat
[ "Unrecognized notify action: '",
T.unpack other,
"'. Expected one of ",
notifyActionStr
]
$ Utils.fmtUnrecognizedError
"notify action"
notifyActionStr
(unpack bad)
{-# INLINEABLE parseNotifyAction #-}

-- | Available 'NotifyAction' strings.
Expand Down
14 changes: 6 additions & 8 deletions src/Shrun/Configuration/Data/Notify/System.hs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ module Shrun.Configuration.Data.Notify.System
where

import DBus.Client (Client)
import Data.Text qualified as T
import Shrun.Configuration.Data.ConfigPhase
( ConfigPhase
( ConfigPhaseArgs,
Expand All @@ -37,6 +36,7 @@ import Shrun.Configuration.Data.WithDisabled
)
import Shrun.Configuration.Default (Default (def))
import Shrun.Prelude
import Shrun.Utils qualified as Utils

-- | Maps DBus to its phased param.
type DBusF :: ConfigPhase -> Type
Expand Down Expand Up @@ -113,14 +113,12 @@ parseNotifySystem getTxt =
"dbus" -> pure $ DBus ()
"notify-send" -> pure NotifySend
"apple-script" -> pure AppleScript
other ->
bad ->
fail
$ mconcat
[ "Unrecognized notify system: '",
T.unpack other,
"'. Expected one of ",
notifySystemStr
]
$ Utils.fmtUnrecognizedError
"notify system"
notifySystemStr
(unpack bad)
{-# INLINEABLE parseNotifySystem #-}

-- | Available 'NotifySystem' strings.
Expand Down
29 changes: 25 additions & 4 deletions src/Shrun/Configuration/Data/Notify/Timeout.hs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import GHC.Num (Num (fromInteger))
import Shrun.Configuration.Default (Default (def))
import Shrun.Prelude
import Shrun.Utils qualified as U
import Shrun.Utils qualified as Utils
import TOML (Value (Integer, String))

-- | Determines notification timeout.
Expand All @@ -37,19 +38,39 @@ instance DecodeTOML NotifyTimeout where
String bad -> invalidValue strErr (String bad)
Integer i -> case toIntegralSized i of
Just i' -> pure $ NotifyTimeoutSeconds i'
Nothing -> invalidValue tooLargeErr (Integer i)
Nothing -> invalidValue (tooLargeErr Nothing) (Integer i)
badTy -> typeMismatch badTy
where
tooLargeErr = "Timeout integer too large. Max is: " <> showt maxW16
strErr = "Unexpected timeout. Only valid string is 'never'."
maxW16 = maxBound @Word16

tooLargeErr :: Maybe Integer -> Text
tooLargeErr Nothing = "Timeout integer too large. Max is: " <> showt maxW16
tooLargeErr (Just i) =
mconcat
[ "Timeout integer '",
showt i,
"' too large. Max is: ",
showt maxW16
]

maxW16 :: Word16
maxW16 = maxBound

-- | Parses 'NotifyTimeout'.
parseNotifyTimeout :: (MonadFail m) => m Text -> m NotifyTimeout
parseNotifyTimeout getTxt =
getTxt >>= \case
"never" -> pure NotifyTimeoutNever
other -> NotifyTimeoutSeconds <$> U.readStripUnderscores other
other -> case U.readStripUnderscores @_ @Integer other of
Just nInt -> case toIntegralSized nInt of
Just nW16 -> pure $ NotifyTimeoutSeconds nW16
Nothing -> fail (unpack $ tooLargeErr (Just nInt))
Nothing ->
fail
$ Utils.fmtUnrecognizedError
"notify timeout"
notifyTimeoutStr
(unpack other)
{-# INLINEABLE parseNotifyTimeout #-}

-- | Available 'NotifyTimeout' strings.
Expand Down
13 changes: 9 additions & 4 deletions src/Shrun/Configuration/Data/StripControl.hs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ module Shrun.Configuration.Data.StripControl
parseStripControl,
ConsoleLogStripControl,
FileLogStripControl,
stripControlStr,
)
where

import Shrun.Configuration.Default (Default (def))
import Shrun.Prelude
import Shrun.Utils qualified as Utils

data StripControlType
= StripControlConsoleLog
Expand Down Expand Up @@ -41,13 +43,16 @@ parseStripControl getTxt =
"smart" -> pure StripControlSmart
bad ->
fail
$ mconcat
[ "Wanted one of (all|none|smart), received: ",
unpack bad
]
$ Utils.fmtUnrecognizedError
"strip control"
stripControlStr
(unpack bad)

instance Default ConsoleLogStripControl where
def = StripControlSmart

instance Default FileLogStripControl where
def = StripControlAll

stripControlStr :: String
stripControlStr = "(all | none | smart)"
17 changes: 16 additions & 1 deletion src/Shrun/Configuration/Data/Truncation.hs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ module Shrun.Configuration.Data.Truncation
decodeCommandNameTrunc,
decodeLineTrunc,
configToLineTrunc,
lineTruncStr,
)
where

Expand All @@ -23,6 +24,7 @@ import Shrun.Configuration.Data.WithDisabled
),
)
import Shrun.Prelude
import Shrun.Utils qualified as Utils

-- | The different regions to apply truncation rules.
data TruncRegion
Expand Down Expand Up @@ -77,16 +79,29 @@ parseLineTruncation ::
parseLineTruncation getNat getTxt =
Undetected
<$> parseTruncation getNat
-- NOTE: [Detect second parser]
<|> parseDetected getTxt
{-# INLINEABLE parseLineTruncation #-}

-- Because this parser is used second, its error message is what will be
-- displayed.
--
-- see NOTE: [Detect second parser]
parseDetected :: (MonadFail m) => m Text -> m LineTruncation
parseDetected getTxt =
getTxt >>= \case
"detect" -> pure Detected
other -> fail $ "Wanted other, received: " <> unpack other
bad ->
fail
$ Utils.fmtUnrecognizedError
"line truncation"
lineTruncStr
(unpack bad)
{-# INLINEABLE parseDetected #-}

lineTruncStr :: String
lineTruncStr = "(NATURAL | detect)"

decodeCommandNameTrunc :: Decoder (Maybe (Truncation TruncCommandName))
decodeCommandNameTrunc = getFieldOptWith tomlDecoder "command-name-trunc"

Expand Down
7 changes: 4 additions & 3 deletions src/Shrun/Utils.hs
Original file line number Diff line number Diff line change
Expand Up @@ -330,16 +330,17 @@ fmtUnrecognizedError ::
a ->
-- | Valid values.
a ->
-- | Bad unrecognized value.
-- | Bad unrecognized value or error message.
a ->
-- | Error message.
a
fmtUnrecognizedError fieldName validVals badValue =
mconcat
[ "Unrecognized ",
[ "Error parsing ",
fieldName,
": '",
badValue,
"'. Expected one of ",
validVals
validVals,
"."
]
Loading

0 comments on commit 3b03f13

Please sign in to comment.