packages feed

hydra-kernel-0.16.0: src/main/haskell/Hydra/Formatting.hs

-- Note: this is an automatically generated file. Do not edit.
-- | String formatting types and functions.

module Hydra.Formatting where
import qualified Hydra.Ast as Ast
import qualified Hydra.Coders as Coders
import qualified Hydra.Core as Core
import qualified Hydra.Error.Checking as Checking
import qualified Hydra.Error.Core as ErrorCore
import qualified Hydra.Error.Packaging as ErrorPackaging
import qualified Hydra.Errors as Errors
import qualified Hydra.Graph as Graph
import qualified Hydra.Json.Model as Model
import qualified Hydra.Haskell.Lib.Chars as Chars
import qualified Hydra.Haskell.Lib.Equality as Equality
import qualified Hydra.Haskell.Lib.Lists as Lists
import qualified Hydra.Haskell.Lib.Logic as Logic
import qualified Hydra.Haskell.Lib.Maps as Maps
import qualified Hydra.Haskell.Lib.Math as Math
import qualified Hydra.Haskell.Lib.Optionals as Optionals
import qualified Hydra.Haskell.Lib.Pairs as Pairs
import qualified Hydra.Haskell.Lib.Sets as Sets
import qualified Hydra.Haskell.Lib.Strings as Strings
import qualified Hydra.Packaging as Packaging
import qualified Hydra.Parsing as Parsing
import qualified Hydra.Paths as Paths
import qualified Hydra.Query as Query
import qualified Hydra.Relational as Relational
import qualified Hydra.Tabular as Tabular
import qualified Hydra.Testing as Testing
import qualified Hydra.Topology as Topology
import qualified Hydra.Typed as Typed
import qualified Hydra.Typing as Typing
import qualified Hydra.Util as Util
import qualified Hydra.Validation as Validation
import qualified Hydra.Variants as Variants
import Prelude hiding  (Enum, Ordering, decodeFloat, encodeFloat, fail, map, pure, sum)
import qualified Data.Scientific as Sci
import qualified Data.Set as S
-- | Capitalize the first letter of a string
capitalize :: String -> String
capitalize = mapFirstLetter Strings.toUpper
-- | Convert a string from one case convention to another
convertCase :: Util.CaseConvention -> Util.CaseConvention -> String -> String
convertCase from to original =

      let parts =

                let byCaps =

                          let splitOnUppercase =
                                  \acc -> \c -> Lists.concat2 (Logic.ifElse (Chars.isUpper c) [
                                    []] []) (Optionals.fromOptional acc (Optionals.map (\uc -> Lists.cons (Lists.cons c (Pairs.first uc)) (Pairs.second uc)) (Lists.uncons acc)))
                          in (Lists.map Strings.fromList (Lists.foldl splitOnUppercase [
                            []] (Lists.reverse (Strings.toList (decapitalize original)))))
                    byUnderscores = Strings.splitOn "_" original
                in case from of
                  Util.CaseConventionCamel -> byCaps
                  Util.CaseConventionPascal -> byCaps
                  Util.CaseConventionLowerSnake -> byUnderscores
                  Util.CaseConventionUpperSnake -> byUnderscores
      in case to of
        Util.CaseConventionCamel -> decapitalize (Strings.cat (Lists.map (\arg_ -> capitalize (Strings.toLower arg_)) parts))
        Util.CaseConventionPascal -> Strings.cat (Lists.map (\arg_ -> capitalize (Strings.toLower arg_)) parts)
        Util.CaseConventionLowerSnake -> Strings.intercalate "_" (Lists.map Strings.toLower parts)
        Util.CaseConventionUpperSnake -> Strings.intercalate "_" (Lists.map Strings.toUpper parts)
-- | Convert a string from camel case (possibly with underscores) to lower snake case. Splits on underscores first, then converts each part from camel case.
convertCaseCamelOrUnderscoreToLowerSnake :: String -> String
convertCaseCamelOrUnderscoreToLowerSnake s =

      let parts = Strings.splitOn "_" s
          snakeParts = Lists.map (\p -> convertCaseCamelToLowerSnake p) parts
      in (Strings.intercalate "_" snakeParts)
-- | Convert a string from camel case to lower snake case
convertCaseCamelToLowerSnake :: String -> String
convertCaseCamelToLowerSnake = convertCase Util.CaseConventionCamel Util.CaseConventionLowerSnake
-- | Convert a string from camel case to upper snake case
convertCaseCamelToUpperSnake :: String -> String
convertCaseCamelToUpperSnake = convertCase Util.CaseConventionCamel Util.CaseConventionUpperSnake
-- | Convert a string from pascal case to upper snake case
convertCasePascalToUpperSnake :: String -> String
convertCasePascalToUpperSnake = convertCase Util.CaseConventionPascal Util.CaseConventionUpperSnake
-- | Decapitalize the first letter of a string
decapitalize :: String -> String
decapitalize = mapFirstLetter Strings.toLower
-- | Escape reserved words by appending an underscore
escapeWithUnderscore :: S.Set String -> String -> String
escapeWithUnderscore reserved s = Logic.ifElse (Sets.member s reserved) (Strings.cat2 s "_") s
-- | Indent each line of a string with four spaces
indentLines :: String -> String
indentLines s =

      let indent = \l -> Strings.cat2 "    " l
      in (Strings.unlines (Lists.map indent (Strings.lines s)))
-- | Format a string as a Java-style block comment
javaStyleComment :: String -> String
javaStyleComment s = Strings.cat2 (Strings.cat2 (Strings.cat2 "/**\n" " * ") s) "\n */"
-- | A helper which maps the first letter of a string to another string
mapFirstLetter :: (String -> String) -> String -> String
mapFirstLetter mapping s =
    Logic.ifElse (Strings.null s) s (
      let list = Strings.toList s
      in (Optionals.fromOptional s (Optionals.map (\uc ->
        let firstLetter = mapping (Strings.fromList (Lists.pure (Pairs.first uc)))
        in (Strings.cat2 firstLetter (Strings.fromList (Pairs.second uc)))) (Lists.uncons list))))
-- | Replace sequences of non-alphanumeric characters with single underscores
nonAlnumToUnderscores :: String -> String
nonAlnumToUnderscores input =

      let isAlnum =
              \c -> Logic.or (Logic.and (Equality.gte c 65) (Equality.lte c 90)) (Logic.or (Logic.and (Equality.gte c 97) (Equality.lte c 122)) (Logic.and (Equality.gte c 48) (Equality.lte c 57)))
          replace =
                  \p -> \c ->
                    let s = Pairs.first p
                        b = Pairs.second p
                    in (Logic.ifElse (isAlnum c) (Lists.cons c s, False) (Logic.ifElse b (s, True) (Lists.cons 95 s, True)))
          result = Lists.foldl replace ([], False) (Strings.toList input)
      in (Strings.fromList (Lists.reverse (Pairs.first result)))
-- | Normalize a comment string for consistent output across coders
normalizeComment :: String -> String
normalizeComment s =

      let stripped = stripLeadingAndTrailingWhitespace s
      in (Logic.ifElse (Strings.null stripped) "" (
        let lastIdx = Math.sub (Strings.length stripped) 1
            appended = Strings.cat2 stripped "."
        in (Optionals.cases (Strings.maybeCharAt lastIdx stripped) appended (\lastChar -> Logic.ifElse (Equality.equal lastChar 46) stripped appended))))
-- | Sanitize a string by replacing non-alphanumeric characters and escaping reserved words
sanitizeWithUnderscores :: S.Set String -> String -> String
sanitizeWithUnderscores reserved s = escapeWithUnderscore reserved (nonAlnumToUnderscores s)
-- | Format a list of elements as a bracketed, comma-separated string
showList :: (t0 -> String) -> [t0] -> String
showList f els =
    Strings.cat [
      "[",
      (Strings.intercalate ", " (Lists.map f els)),
      "]"]
-- | Remove leading and trailing whitespace from a string
stripLeadingAndTrailingWhitespace :: String -> String
stripLeadingAndTrailingWhitespace s =
    Strings.fromList (Lists.dropWhile Chars.isSpace (Lists.reverse (Lists.dropWhile Chars.isSpace (Lists.reverse (Strings.toList s)))))
-- | Replace special characters with their alphanumeric aliases
withCharacterAliases :: String -> String
withCharacterAliases original =

      let aliases =
              Maps.fromList [
                (32, "sp"),
                (33, "excl"),
                (34, "quot"),
                (35, "num"),
                (36, "dollar"),
                (37, "percnt"),
                (38, "amp"),
                (39, "apos"),
                (40, "lpar"),
                (41, "rpar"),
                (42, "ast"),
                (43, "plus"),
                (44, "comma"),
                (45, "minus"),
                (46, "period"),
                (47, "sol"),
                (58, "colon"),
                (59, "semi"),
                (60, "lt"),
                (61, "equals"),
                (62, "gt"),
                (63, "quest"),
                (64, "commat"),
                (91, "lsqb"),
                (92, "bsol"),
                (93, "rsqb"),
                (94, "circ"),
                (95, "lowbar"),
                (96, "grave"),
                (123, "lcub"),
                (124, "verbar"),
                (125, "rcub"),
                (126, "tilde")]
          alias = \c -> Optionals.fromOptional (Lists.pure c) (Optionals.map Strings.toList (Maps.lookup c aliases))
      in (Strings.fromList (Lists.filter Chars.isAlphaNum (Lists.concat (Lists.map alias (Strings.toList original)))))
-- | A simple soft line wrap which is suitable for code comments
wrapLine :: Int -> String -> String
wrapLine maxlen input =

      let helper =
              \prev -> \rem ->
                let trunc = Lists.take maxlen rem
                    spanResult =
                            Lists.span (\c -> Logic.and (Logic.not (Equality.equal c 32)) (Logic.not (Equality.equal c 9))) (Lists.reverse trunc)
                    prefix = Lists.reverse (Pairs.second spanResult)
                    suffix = Lists.reverse (Pairs.first spanResult)
                in (Logic.ifElse (Equality.lte (Lists.length rem) maxlen) (Lists.reverse (Lists.cons rem prev)) (Logic.ifElse (Lists.null prefix) (helper (Lists.cons trunc prev) (Lists.drop maxlen rem)) (Optionals.fromOptional (helper (Lists.cons trunc prev) (Lists.drop maxlen rem)) (Optionals.map (\pfxInit -> helper (Lists.cons pfxInit prev) (Lists.concat2 suffix (Lists.drop maxlen rem))) (Lists.maybeInit prefix)))))
      in (Strings.fromList (Lists.intercalate [
        10] (helper [] (Strings.toList input))))