bricks-0.0.0.1: src/Bricks/UnquotedString.hs
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE OverloadedStrings #-}
module Bricks.UnquotedString
(
-- * Type
Str'Unquoted (..)
-- * Constructor
, str'tryUnquoted
, str'unquoted'orThrow
-- * Predicates
, str'canRenderUnquoted
, char'canRenderUnquoted
) where
-- Bricks
import Bricks.Keyword
-- Bricks internal
import Bricks.Internal.Prelude
import Bricks.Internal.Text (Text)
import qualified Bricks.Internal.Text as Text
-- Base
import qualified Data.Char as Char
import qualified Data.List as List
import Prelude (error)
{- | A string that can be rendered unquoted. Unquoted strings are restricted to
a conservative set of characters; see 'str'canRenderUnquoted' for the full
rules.
The constructor is tagged "unsafe" because it lets you construct and invalid
value. Prefer 'str'tryUnquoted' which does validate the text. -}
newtype Str'Unquoted = Str'Unquoted'Unsafe { str'unquotedToStatic :: Text }
instance Show Str'Unquoted
where
showsPrec _ x = ("unquoted " <>) . shows (str'unquotedToStatic x)
str'tryUnquoted :: Text -> Maybe Str'Unquoted
str'tryUnquoted x =
if str'canRenderUnquoted x then Just (Str'Unquoted'Unsafe x) else Nothing
-- | Throws an exception if the string cannot render unquoted.
str'unquoted'orThrow :: Text -> Str'Unquoted
str'unquoted'orThrow x =
if str'canRenderUnquoted x then Str'Unquoted'Unsafe x else
error $ "String " <> show x <> " cannot render unquoted"
{- | Whether a string having this name can be rendered without quoting it.
We allow a string to render unquoted if all these conditions are met:
- The string is nonempty
- All characters satify 'char'canRenderUnquoted'
- The string is not a keyword
>>> str'canRenderUnquoted "-ab_c"
True
>>> str'canRenderUnquoted ""
False
>>> str'canRenderUnquoted "a\"b"
False
>>> str'canRenderUnquoted "let"
False
-}
str'canRenderUnquoted :: Text -> Bool
str'canRenderUnquoted x =
Text.all char'canRenderUnquoted x
&& not (Text.null x)
&& List.all ((/= x) . keywordText) keywords
-- | Letters, @-@, and @_@.
char'canRenderUnquoted :: Char -> Bool
char'canRenderUnquoted c =
Char.isLetter c || c == '-' || c == '_'