{-# LANGUAGE ViewPatterns #-}
module Shrun.Utils
(
breakStripPoint,
truncateIfNeeded,
stripControlAll,
stripControlSmart,
escapeDoubleQuotes,
diffTime,
timeSpecToRelTime,
hWithHidden,
withHiddenInput,
hHide,
drainStdin,
inverseMap,
inverseMapFail,
inversePretty,
inversePrettyFail,
atomicReadWrite,
fmtUnrecognizedError,
mkMetaStr,
parseByteText,
readIncCounter,
surroundJust,
whileM_,
whenLeft,
untilJust,
(∸),
readStripUnderscores,
indexPos,
)
where
import Data.Bytes (Conversion (convert_), SomeSize, parse)
import Data.Char (isControl, isLetter)
import Data.Either (either)
import Data.List qualified as L
import Data.Map qualified as Map
import Data.Sequence qualified as Seq
import Data.Text qualified as T
import Data.Text.Lazy qualified as TL
import Data.Text.Lazy.Builder (Builder)
import Data.Text.Lazy.Builder qualified as TLB
import Data.Time.Relative (RelativeTime, fromSeconds)
import Effects.FileSystem.Handle qualified as H
import Effects.FileSystem.HandleReader qualified as HR
import Effects.FileSystem.HandleWriter qualified as HW
import Effects.Time (TimeSpec, diffTimeSpec)
import Optics.Core qualified as O
import Shrun.Prelude
import Text.Read (Read)
import Text.Read qualified as TR
diffTime :: TimeSpec -> TimeSpec -> Natural
diffTime :: TimeSpec -> TimeSpec -> Natural
diffTime TimeSpec
t1 TimeSpec
t2 = Optic' A_Lens NoIx TimeSpec Natural -> TimeSpec -> Natural
forall k (is :: IxList) s a.
Is k A_Getter =>
Optic' k is s a -> s -> a
view Optic' A_Lens NoIx TimeSpec Natural
#sec (TimeSpec -> Natural) -> TimeSpec -> Natural
forall a b. (a -> b) -> a -> b
$ TimeSpec -> TimeSpec -> TimeSpec
diffTimeSpec TimeSpec
t1 TimeSpec
t2
timeSpecToRelTime :: TimeSpec -> RelativeTime
timeSpecToRelTime :: TimeSpec -> RelativeTime
timeSpecToRelTime = Natural -> RelativeTime
fromSeconds (Natural -> RelativeTime)
-> (TimeSpec -> Natural) -> TimeSpec -> RelativeTime
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> Type) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Optic' A_Lens NoIx TimeSpec Natural -> TimeSpec -> Natural
forall k (is :: IxList) s a.
Is k A_Getter =>
Optic' k is s a -> s -> a
view Optic' A_Lens NoIx TimeSpec Natural
#sec
breakStripPoint :: Text -> Text -> Tuple2 Text Text
breakStripPoint :: Text -> Text -> (Text, Text)
breakStripPoint Text
point Text
txt = case HasCallStack => Text -> Text -> (Text, Text)
Text -> Text -> (Text, Text)
T.breakOn Text
point Text
txt of
(Text
x, Text -> Text -> Maybe Text
T.stripPrefix Text
point -> Just Text
y) -> (Text
x, Text
y)
(Text, Text)
pair -> (Text, Text)
pair
truncateIfNeeded :: Int -> Text -> Text
truncateIfNeeded :: Int -> Text -> Text
truncateIfNeeded Int
n Text
txt
| Text -> Int
T.length Text
txt Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
n = Text
txt
| Bool
otherwise = Text
txt'
where
txt' :: Text
txt' = Int -> Text -> Text
T.take (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
3) Text
txt Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"..."
stripControlAll :: Text -> Text
stripControlAll :: Text -> Text
stripControlAll =
(Char -> Bool) -> Text -> Text
T.filter (Bool -> Bool
not (Bool -> Bool) -> (Char -> Bool) -> Char -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> Type) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Char -> Bool
isControl) (Text -> Text) -> (Text -> Text) -> Text -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> Type) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Text -> Text
stripAnsiAll
stripControlSmart :: Text -> Text
stripControlSmart :: Text -> Text
stripControlSmart =
(Char -> Bool) -> Text -> Text
T.filter Char -> Bool
ctrlToFilter (Text -> Text) -> (Text -> Text) -> Text -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> Type) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Text -> Text
stripAnsiControl
where
ctrlToFilter :: Char -> Bool
ctrlToFilter Char
c
| Char -> Bool
isControl Char
c = Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'\ESC'
| Bool
otherwise = Bool
True
stripAnsiAll :: Text -> Text
stripAnsiAll :: Text -> Text
stripAnsiAll = [Text] -> Text
T.concat ([Text] -> Text) -> (Text -> [Text]) -> Text -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> Type) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. ((Text, Text, Text) -> Text) -> [(Text, Text, Text)] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
fmap (Optic' A_Lens NoIx (Text, Text, Text) Text
-> (Text, Text, Text) -> Text
forall k (is :: IxList) s a.
Is k A_Getter =>
Optic' k is s a -> s -> a
view Optic' A_Lens NoIx (Text, Text, Text) Text
forall s t a b. Field1 s t a b => Lens s t a b
_1) ([(Text, Text, Text)] -> [Text])
-> (Text -> [(Text, Text, Text)]) -> Text -> [Text]
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> Type) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Text -> [(Text, Text, Text)]
splitAnsi
stripAnsiControl :: Text -> Text
stripAnsiControl :: Text -> Text
stripAnsiControl Text
txt =
(Text -> (Text, Text, Text) -> Text)
-> Text -> [(Text, Text, Text)] -> Text
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: Type -> Type) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' Text -> (Text, Text, Text) -> Text
forall {a}. Semigroup a => a -> (a, Text, a) -> a
f Text
"" [(Text, Text, Text)]
splitTxt
where
splitTxt :: [(Text, Text, Text)]
splitTxt = Text -> [(Text, Text, Text)]
splitAnsi Text
txt
f :: a -> (a, Text, a) -> a
f a
acc (a
preAnsi, Text
code, a
withAnsi)
| Text -> Bool
nonControlAnsi Text
code = a
acc a -> a -> a
forall a. Semigroup a => a -> a -> a
<> a
withAnsi
| Bool
otherwise = a
acc a -> a -> a
forall a. Semigroup a => a -> a -> a
<> a
preAnsi
nonControlAnsi :: Text -> Bool
nonControlAnsi :: Text -> Bool
nonControlAnsi Text
ansi = case Text -> Maybe (Text, Char)
T.unsnoc Text
ansi of
Just (Text
_, Char
'm') -> Bool
True
Maybe (Text, Char)
_ -> Bool
False
splitAnsi :: Text -> [(Text, Text, Text)]
splitAnsi :: Text -> [(Text, Text, Text)]
splitAnsi Text
"" = []
splitAnsi Text
t =
(Text
preAnsi, Text
ansiCode, Text
preAnsi Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
ansiCode) (Text, Text, Text) -> [(Text, Text, Text)] -> [(Text, Text, Text)]
forall a. a -> [a] -> [a]
: [(Text, Text, Text)]
rest
where
(!Text
preAnsi, !Text
withAnsiFull) = HasCallStack => Text -> Text -> (Text, Text)
Text -> Text -> (Text, Text)
T.breakOn Text
"\ESC[" Text
t
(!Text
ansiCodeNoChar, !Text
withAnsiChar) = (Char -> Bool) -> Text -> (Text, Text)
T.break Char -> Bool
isLetter Text
withAnsiFull
(!Text
ansiCode, ![(Text, Text, Text)]
rest) = case Text -> Maybe (Char, Text)
T.uncons Text
withAnsiChar of
Just (!Char
ansiChar, !Text
rest') -> (Text -> Char -> Text
T.snoc Text
ansiCodeNoChar Char
ansiChar, Text -> [(Text, Text, Text)]
splitAnsi Text
rest')
Maybe (Char, Text)
Nothing -> (Text
ansiCodeNoChar, [])
parseByteText :: Text -> Either Text (Bytes B Natural)
parseByteText :: Text -> Either Text (Bytes 'B Natural)
parseByteText Text
txt =
case forall a. Parser a => Text -> Either Text a
parse @(SomeSize Natural) Text
txt of
Right SomeSize Natural
b -> Bytes 'B Natural -> Either Text (Bytes 'B Natural)
forall a b. b -> Either a b
Right (Bytes 'B Natural -> Either Text (Bytes 'B Natural))
-> Bytes 'B Natural -> Either Text (Bytes 'B Natural)
forall a b. (a -> b) -> a -> b
$ forall a (t :: Size). (Conversion a, SingI t) => a -> Converted t a
convert_ @_ @B SomeSize Natural
b
Left Text
_ -> case forall a. Parser a => Text -> Either Text a
parse @(SomeSize Double) Text
txt of
Right SomeSize Double
b -> Bytes 'B Natural -> Either Text (Bytes 'B Natural)
forall a b. b -> Either a b
Right (Double -> Natural
forall b. Integral b => Double -> b
forall a b. (RealFrac a, Integral b) => a -> b
truncate (Double -> Natural) -> Bytes 'B Double -> Bytes 'B Natural
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a (t :: Size). (Conversion a, SingI t) => a -> Converted t a
convert_ @_ @B SomeSize Double
b)
Left Text
err -> Text -> Either Text (Bytes 'B Natural)
forall a b. a -> Either a b
Left Text
err
whenLeft :: (Applicative f) => Either a b -> (a -> f ()) -> f ()
whenLeft :: forall (f :: Type -> Type) a b.
Applicative f =>
Either a b -> (a -> f ()) -> f ()
whenLeft Either a b
e a -> f ()
action = (a -> f ()) -> (b -> f ()) -> Either a b -> f ()
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either a -> f ()
action (f () -> b -> f ()
forall a b. a -> b -> a
const (() -> f ()
forall a. a -> f a
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure ())) Either a b
e
{-# INLINEABLE whenLeft #-}
whileM_ :: (Monad m) => m Bool -> m a -> m ()
whileM_ :: forall (m :: Type -> Type) a. Monad m => m Bool -> m a -> m ()
whileM_ m Bool
mb m a
ma = m ()
go
where
go :: m ()
go =
m Bool
mb m Bool -> (Bool -> m ()) -> m ()
forall a b. m a -> (a -> m b) -> m b
forall (m :: Type -> Type) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
Bool
True -> m a
ma m a -> m () -> m ()
forall a b. m a -> m b -> m b
forall (f :: Type -> Type) a b. Applicative f => f a -> f b -> f b
*> m ()
go
Bool
False -> () -> m ()
forall a. a -> m a
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure ()
{-# INLINEABLE whileM_ #-}
untilJust :: (Monad m) => m (Maybe b) -> m b
untilJust :: forall (m :: Type -> Type) b. Monad m => m (Maybe b) -> m b
untilJust m (Maybe b)
m = m b
go
where
go :: m b
go =
m (Maybe b)
m m (Maybe b) -> (Maybe b -> m b) -> m b
forall a b. m a -> (a -> m b) -> m b
forall (m :: Type -> Type) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
Maybe b
Nothing -> m b
go
Just b
x -> b -> m b
forall a. a -> m a
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure b
x
{-# INLINEABLE untilJust #-}
escapeDoubleQuotes :: Text -> Text
escapeDoubleQuotes :: Text -> Text
escapeDoubleQuotes = LazyText -> Text
TL.toStrict (LazyText -> Text) -> (Text -> LazyText) -> Text -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> Type) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Builder -> LazyText
TLB.toLazyText (Builder -> LazyText) -> (Text -> Builder) -> Text -> LazyText
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> Type) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. (Builder -> Char -> Builder) -> Builder -> Text -> Builder
forall a. (a -> Char -> a) -> a -> Text -> a
T.foldl' Builder -> Char -> Builder
go Builder
""
where
go :: Builder -> Char -> Builder
go :: Builder -> Char -> Builder
go Builder
acc Char
'"' = Builder
acc Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
"\\\""
go Builder
acc Char
c = Builder
acc Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Char -> Builder
TLB.singleton Char
c
(∸) :: (Ord a, Num a) => a -> a -> a
a
x ∸ :: forall a. (Ord a, Num a) => a -> a -> a
∸ a
y =
if a
y a -> a -> Bool
forall a. Ord a => a -> a -> Bool
> a
x
then a
0
else a
x a -> a -> a
forall a. Num a => a -> a -> a
- a
y
infixl 6 ∸
readStripUnderscores :: (MonadFail m, Read a) => Text -> m a
readStripUnderscores :: forall (m :: Type -> Type) a. (MonadFail m, Read a) => Text -> m a
readStripUnderscores Text
t = case String -> Either String a
forall a. Read a => String -> Either String a
TR.readEither String
s of
Left String
err -> String -> m a
forall a. String -> m a
forall (m :: Type -> Type) a. MonadFail m => String -> m a
fail (String -> m a) -> String -> m a
forall a b. (a -> b) -> a -> b
$ String
"Could not read '" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
s String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"': " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
err
Right a
x -> a -> m a
forall a. a -> m a
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure a
x
where
noUnderscores :: Text
noUnderscores = HasCallStack => Text -> Text -> Text -> Text
Text -> Text -> Text -> Text
T.replace Text
"_" Text
"" Text
t
s :: String
s = Text -> String
T.unpack Text
noUnderscores
{-# INLINEABLE readStripUnderscores #-}
fmtUnrecognizedError ::
( IsString a,
Monoid a
) =>
a ->
(Bool, List a) ->
a ->
a
fmtUnrecognizedError :: forall a. (IsString a, Monoid a) => a -> (Bool, [a]) -> a -> a
fmtUnrecognizedError a
fieldName (Bool, [a])
meta a
badValue =
[a] -> a
forall a. Monoid a => [a] -> a
mconcat
[ a
"Error parsing ",
a
fieldName,
a
": '",
a
badValue,
a
"'. Expected one of ",
(Bool, [a]) -> a
forall a. (IsString a, Monoid a) => (Bool, [a]) -> a
mkMetaStr (Bool, [a])
meta,
a
"."
]
mkMetaStr :: (IsString a, Monoid a) => Tuple2 Bool (List a) -> a
mkMetaStr :: forall a. (IsString a, Monoid a) => (Bool, [a]) -> a
mkMetaStr (Bool
includeOff, [a]
xs) =
(\a
s -> a
"(" a -> a -> a
forall a. Semigroup a => a -> a -> a
<> a
s a -> a -> a
forall a. Semigroup a => a -> a -> a
<> a
")")
(a -> a) -> ([a] -> a) -> [a] -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> Type) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. [a] -> a
forall a. Monoid a => [a] -> a
mconcat
([a] -> a) -> ([a] -> [a]) -> [a] -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> Type) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. a -> [a] -> [a]
forall a. a -> [a] -> [a]
L.intersperse a
" | "
([a] -> [a]) -> ([a] -> [a]) -> [a] -> [a]
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> Type) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. [a] -> [a]
appendOff
([a] -> a) -> [a] -> a
forall a b. (a -> b) -> a -> b
$ [a]
xs
where
appendOff :: [a] -> [a]
appendOff =
if Bool
includeOff
then ([a] -> [a] -> [a]
forall a. [a] -> [a] -> [a]
++ [a
"off"])
else [a] -> [a]
forall a. a -> a
id
atomicReadWrite ::
( HasCallStack,
MonadAtomic m,
MonadMask m
) =>
TBQueue a ->
(a -> m b) ->
m ()
atomicReadWrite :: forall (m :: Type -> Type) a b.
(HasCallStack, MonadAtomic m, MonadMask m) =>
TBQueue a -> (a -> m b) -> m ()
atomicReadWrite TBQueue a
queue a -> m b
logAction =
((forall a. m a -> m a) -> m ()) -> m ()
forall b. HasCallStack => ((forall a. m a -> m a) -> m b) -> m b
forall (m :: Type -> Type) b.
(MonadMask m, HasCallStack) =>
((forall a. m a -> m a) -> m b) -> m b
mask (((forall a. m a -> m a) -> m ()) -> m ())
-> ((forall a. m a -> m a) -> m ()) -> m ()
forall a b. (a -> b) -> a -> b
$ \forall a. m a -> m a
restore -> m a -> m a
forall a. m a -> m a
restore (TBQueue a -> m a
forall (m :: Type -> Type) a.
(HasCallStack, MonadAtomic m) =>
TBQueue a -> m a
readTBQueueA' TBQueue a
queue) m a -> (a -> m ()) -> m ()
forall a b. m a -> (a -> m b) -> m b
forall (m :: Type -> Type) a b. Monad m => m a -> (a -> m b) -> m b
>>= m b -> m ()
forall (f :: Type -> Type) a. Functor f => f a -> f ()
void (m b -> m ()) -> (a -> m b) -> a -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> Type) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. a -> m b
logAction
{-# INLINEABLE atomicReadWrite #-}
indexPos :: NESeq a -> NESeq (Positive Int, a)
indexPos :: forall a. NESeq a -> NESeq (Positive Int, a)
indexPos (a
x :<|| Seq a
xs) = (Positive Int
forall m. MMonoid m => m
one, a
x) (Positive Int, a)
-> Seq (Positive Int, a) -> NESeq (Positive Int, a)
forall a. a -> Seq a -> NESeq a
:<|| Seq (Positive Int, a)
ys
where
ys :: Seq (Positive Int, a)
ys = Seq (Positive Int) -> Seq a -> Seq (Positive Int, a)
forall a b. Seq a -> Seq b -> Seq (a, b)
Seq.zip (Int -> Positive Int
forall a.
(AMonoid a, HasCallStack, Ord a, Show a) =>
a -> Positive a
unsafePositive (Int -> Positive Int) -> Seq Int -> Seq (Positive Int)
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> [Int] -> Seq Int
forall a. [a] -> Seq a
Seq.fromList [Int
2 .. Int
len]) Seq a
xs
len :: Int
len = Seq a -> Int
forall a. Seq a -> Int
forall (t :: Type -> Type) a. Foldable t => t a -> Int
length Seq a
xs Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1
surroundJust ::
( O.JoinKinds k A_Prism m,
O.JoinKinds A_Prism l k
) =>
Optic l ks u v (Maybe a) (Maybe b) ->
Optic m ks (Maybe u) (Maybe v) a b
surroundJust :: forall k m l (ks :: IxList) u v a b.
(JoinKinds k A_Prism m, JoinKinds A_Prism l k) =>
Optic l ks u v (Maybe a) (Maybe b)
-> Optic m ks (Maybe u) (Maybe v) a b
surroundJust Optic l ks u v (Maybe a) (Maybe b)
l = Prism (Maybe u) (Maybe v) u v
forall a b. Prism (Maybe a) (Maybe b) a b
_Just Prism (Maybe u) (Maybe v) u v
-> Optic l ks u v (Maybe a) (Maybe b)
-> Optic k ks (Maybe u) (Maybe v) (Maybe a) (Maybe b)
forall k l m (is :: IxList) (js :: IxList) (ks :: IxList) s t u v a
b.
(JoinKinds k l m, AppendIndices is js ks) =>
Optic k is s t u v -> Optic l js u v a b -> Optic m ks s t a b
% Optic l ks u v (Maybe a) (Maybe b)
l Optic k ks (Maybe u) (Maybe v) (Maybe a) (Maybe b)
-> Optic A_Prism NoIx (Maybe a) (Maybe b) a b
-> Optic m ks (Maybe u) (Maybe v) a b
forall k l m (is :: IxList) (js :: IxList) (ks :: IxList) s t u v a
b.
(JoinKinds k l m, AppendIndices is js ks) =>
Optic k is s t u v -> Optic l js u v a b -> Optic m ks s t a b
% Optic A_Prism NoIx (Maybe a) (Maybe b) a b
forall a b. Prism (Maybe a) (Maybe b) a b
_Just
withHiddenInput ::
( MonadMask m,
MonadHandleReader m,
MonadHandleWriter m
) =>
m a ->
m a
withHiddenInput :: forall (m :: Type -> Type) a.
(MonadMask m, MonadHandleReader m, MonadHandleWriter m) =>
m a -> m a
withHiddenInput = Handle 'HandleModeReadWrite -> m a -> m a
forall (p :: HandleMode) (m :: Type -> Type) a.
(CanRead p, CanWrite p, MonadMask m, MonadHandleReader m,
MonadHandleWriter m) =>
Handle p -> m a -> m a
hWithHidden Handle 'HandleModeReadWrite
H.stdin
{-# INLINEABLE withHiddenInput #-}
hWithHidden ::
( CanRead p,
CanWrite p,
MonadMask m,
MonadHandleReader m,
MonadHandleWriter m
) =>
Handle p ->
m a ->
m a
hWithHidden :: forall (p :: HandleMode) (m :: Type -> Type) a.
(CanRead p, CanWrite p, MonadMask m, MonadHandleReader m,
MonadHandleWriter m) =>
Handle p -> m a -> m a
hWithHidden Handle p
h m a
m = m (BufferMode, Bool)
-> ((BufferMode, Bool) -> m ())
-> ((BufferMode, Bool) -> m a)
-> m a
forall (m :: Type -> Type) a c b.
(HasCallStack, MonadMask m) =>
m a -> (a -> m c) -> (a -> m b) -> m b
bracket m (BufferMode, Bool)
hideInput (BufferMode, Bool) -> m ()
unhideInput (m a -> (BufferMode, Bool) -> m a
forall a b. a -> b -> a
const m a
m)
where
hideInput :: m (BufferMode, Bool)
hideInput = do
BufferMode
buffMode <- Handle p -> m BufferMode
forall (p :: HandleMode).
(CanRead p, HasCallStack) =>
Handle p -> m BufferMode
forall (m :: Type -> Type) (p :: HandleMode).
(MonadHandleReader m, CanRead p, HasCallStack) =>
Handle p -> m BufferMode
HR.hGetBuffering Handle p
h
Bool
echoMode <- Handle p -> m Bool
forall (p :: HandleMode).
(CanRead p, HasCallStack) =>
Handle p -> m Bool
forall (m :: Type -> Type) (p :: HandleMode).
(MonadHandleReader m, CanRead p, HasCallStack) =>
Handle p -> m Bool
HR.hGetEcho Handle p
h
Handle p -> m ()
forall (p :: HandleMode) (m :: Type -> Type).
(CanWrite p, MonadHandleWriter m) =>
Handle p -> m ()
hHide Handle p
h
pure (BufferMode
buffMode, Bool
echoMode)
unhideInput :: (BufferMode, Bool) -> m ()
unhideInput (BufferMode
buffMode, Bool
echoMode) = do
Handle p -> BufferMode -> m ()
forall (p :: HandleMode).
(CanWrite p, HasCallStack) =>
Handle p -> BufferMode -> m ()
forall (m :: Type -> Type) (p :: HandleMode).
(MonadHandleWriter m, CanWrite p, HasCallStack) =>
Handle p -> BufferMode -> m ()
HW.hSetBuffering Handle p
h BufferMode
buffMode
Handle p -> Bool -> m ()
forall (p :: HandleMode).
(CanWrite p, HasCallStack) =>
Handle p -> Bool -> m ()
forall (m :: Type -> Type) (p :: HandleMode).
(MonadHandleWriter m, CanWrite p, HasCallStack) =>
Handle p -> Bool -> m ()
HW.hSetEcho Handle p
h Bool
echoMode
{-# INLINEABLE hWithHidden #-}
hHide ::
(CanWrite p, MonadHandleWriter m) =>
Handle p ->
m ()
hHide :: forall (p :: HandleMode) (m :: Type -> Type).
(CanWrite p, MonadHandleWriter m) =>
Handle p -> m ()
hHide Handle p
h = do
Handle p -> BufferMode -> m ()
forall (p :: HandleMode).
(CanWrite p, HasCallStack) =>
Handle p -> BufferMode -> m ()
forall (m :: Type -> Type) (p :: HandleMode).
(MonadHandleWriter m, CanWrite p, HasCallStack) =>
Handle p -> BufferMode -> m ()
HW.hSetBuffering Handle p
h BufferMode
HW.NoBuffering
Handle p -> Bool -> m ()
forall (p :: HandleMode).
(CanWrite p, HasCallStack) =>
Handle p -> Bool -> m ()
forall (m :: Type -> Type) (p :: HandleMode).
(MonadHandleWriter m, CanWrite p, HasCallStack) =>
Handle p -> Bool -> m ()
HW.hSetEcho Handle p
h Bool
False
{-# INLINEABLE hHide #-}
drainStdin ::
( MonadCatch m,
MonadHandleReader m
) =>
m ()
drainStdin :: forall (m :: Type -> Type).
(MonadCatch m, MonadHandleReader m) =>
m ()
drainStdin =
m () -> m ()
forall (m :: Type -> Type) a.
(HasCallStack, MonadCatch m) =>
m a -> m ()
tryMySync_
(m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$ Handle 'HandleModeReadWrite -> m Bool
forall (p :: HandleMode).
(CanRead p, HasCallStack) =>
Handle p -> m Bool
forall (m :: Type -> Type) (p :: HandleMode).
(MonadHandleReader m, CanRead p, HasCallStack) =>
Handle p -> m Bool
HR.hIsClosed Handle 'HandleModeReadWrite
H.stdin
m Bool -> (Bool -> m ()) -> m ()
forall a b. m a -> (a -> m b) -> m b
forall (m :: Type -> Type) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
Bool
True -> () -> m ()
forall a. a -> m a
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure ()
Bool
False ->
Handle 'HandleModeReadWrite -> m Bool
forall (p :: HandleMode).
(CanRead p, HasCallStack) =>
Handle p -> m Bool
forall (m :: Type -> Type) (p :: HandleMode).
(MonadHandleReader m, CanRead p, HasCallStack) =>
Handle p -> m Bool
HR.hIsReadable Handle 'HandleModeReadWrite
H.stdin m Bool -> (Bool -> m ()) -> m ()
forall a b. m a -> (a -> m b) -> m b
forall (m :: Type -> Type) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
Bool
False -> () -> m ()
forall a. a -> m a
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure ()
Bool
True -> m ByteString -> m ()
forall (f :: Type -> Type) a. Functor f => f a -> f ()
void (m ByteString -> m ()) -> m ByteString -> m ()
forall a b. (a -> b) -> a -> b
$ Handle 'HandleModeReadWrite -> Int -> m ByteString
forall (p :: HandleMode).
(CanRead p, HasCallStack) =>
Handle p -> Int -> m ByteString
forall (m :: Type -> Type) (p :: HandleMode).
(MonadHandleReader m, CanRead p, HasCallStack) =>
Handle p -> Int -> m ByteString
HR.hGetNonBlocking Handle 'HandleModeReadWrite
H.stdin Int
1_000
{-# INLINEABLE drainStdin #-}
readIncCounter :: TVar Word16 -> STM Word16
readIncCounter :: TVar Word16 -> STM Word16
readIncCounter TVar Word16
counter = do
Word16
c <- TVar Word16 -> STM Word16
forall a. TVar a -> STM a
readTVar' TVar Word16
counter
TVar Word16 -> Word16 -> STM ()
forall a. TVar a -> a -> STM ()
writeTVar' TVar Word16
counter (Word16
c Word16 -> Word16 -> Word16
forall a. Num a => a -> a -> a
+ Word16
1)
pure Word16
c
inverseMap ::
forall a k.
(Bounded a, Enum a, Ord k) =>
(a -> k) ->
k ->
Maybe a
inverseMap :: forall a k. (Bounded a, Enum a, Ord k) => (a -> k) -> k -> Maybe a
inverseMap a -> k
inj = \k
k -> k -> Map k a -> Maybe a
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup k
k Map k a
m
where
m :: Map k a
m = [(k, a)] -> Map k a
forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList ([(k, a)] -> Map k a) -> [(k, a)] -> Map k a
forall a b. (a -> b) -> a -> b
$ (\a
x -> (a -> k
inj a
x, a
x)) (a -> (k, a)) -> [a] -> [(k, a)]
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> [a
forall a. Bounded a => a
minBound .. a
forall a. Bounded a => a
maxBound]
inversePretty ::
forall a.
(Bounded a, Enum a, Pretty a) =>
Text ->
Maybe a
inversePretty :: forall a. (Bounded a, Enum a, Pretty a) => Text -> Maybe a
inversePretty = (a -> Text) -> Text -> Maybe a
forall a k. (Bounded a, Enum a, Ord k) => (a -> k) -> k -> Maybe a
inverseMap a -> Text
forall a. Pretty a => a -> Text
prettyToText
inverseMapFail ::
forall a m.
(Bounded a, Enum a, MonadFail m) =>
(a -> Text) ->
Text ->
Tuple2 Bool (List Text) ->
Text ->
m a
inverseMapFail :: forall a (m :: Type -> Type).
(Bounded a, Enum a, MonadFail m) =>
(a -> Text) -> Text -> (Bool, [Text]) -> Text -> m a
inverseMapFail a -> Text
inj Text
name (Bool, [Text])
meta = \Text
t -> case (a -> Text) -> Text -> Maybe a
forall a k. (Bounded a, Enum a, Ord k) => (a -> k) -> k -> Maybe a
inverseMap a -> Text
inj Text
t of
Just a
v -> a -> m a
forall a. a -> m a
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure a
v
Maybe a
Nothing ->
String -> m a
forall a. String -> m a
forall (m :: Type -> Type) a. MonadFail m => String -> m a
fail
(String -> m a) -> (Text -> String) -> Text -> m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> Type) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Text -> String
unpack
(Text -> m a) -> Text -> m a
forall a b. (a -> b) -> a -> b
$ Text -> (Bool, [Text]) -> Text -> Text
forall a. (IsString a, Monoid a) => a -> (Bool, [a]) -> a -> a
fmtUnrecognizedError
Text
name
(Bool, [Text])
meta
Text
t
inversePrettyFail ::
forall a m.
(Bounded a, Enum a, MonadFail m, Pretty a) =>
Text ->
Tuple2 Bool (List Text) ->
Text ->
m a
inversePrettyFail :: forall a (m :: Type -> Type).
(Bounded a, Enum a, MonadFail m, Pretty a) =>
Text -> (Bool, [Text]) -> Text -> m a
inversePrettyFail = (a -> Text) -> Text -> (Bool, [Text]) -> Text -> m a
forall a (m :: Type -> Type).
(Bounded a, Enum a, MonadFail m) =>
(a -> Text) -> Text -> (Bool, [Text]) -> Text -> m a
inverseMapFail a -> Text
forall a. Pretty a => a -> Text
prettyToText