packages feed

AutoForms-0.4.0: src/Graphics/UI/AF/General/PriLabel.hs

module Graphics.UI.AF.General.PriLabel
    ( PriLabel(..)
    , Priority(..)
    , badConstrLabel, goodConstrLabel, fieldNameLabel, userDefinedLabel
    , bestLabel, humanizeLabel
    , defaultLabel, labelless
    )
where

import Char

-- |Prioritized label. If two 'PriLabel' can be used for some
--  component, then the one with highest priority is used.
data PriLabel = PriLabel { priority :: Priority, labelString :: String } deriving (Show)
-- |The label priority.
data Priority = BadConstr | GoodConstr | FieldName | UserDefined deriving (Show, Ord, Eq)

badConstrLabel, goodConstrLabel, fieldNameLabel, userDefinedLabel :: String -> PriLabel
badConstrLabel   label = PriLabel BadConstr   label
goodConstrLabel  label = PriLabel GoodConstr  label
fieldNameLabel   label = PriLabel FieldName   label
userDefinedLabel label = PriLabel UserDefined label

-- |Creates a default (lowest priority) PriLabel
defaultLabel :: String -> PriLabel
defaultLabel label = PriLabel BadConstr label

labelless :: PriLabel
labelless = defaultLabel ""

-- |Choose label with highest priority. If equal then choose the left
-- |(first parameter) label.
bestLabel :: PriLabel -> PriLabel -> PriLabel
bestLabel left@(PriLabel priL _) right@(PriLabel priR _)
    | priL >= priR  = left
    | otherwise     = right

-- |Humanized label strings, by turning labels like "someLabelName"
-- into "Some label name".
humanizeLabel :: PriLabel -> PriLabel
humanizeLabel (PriLabel pri label) = PriLabel pri label'
    where
    label' | pri == UserDefined || elem ' ' label -- safegaurd against accidentally calling humanizeLabel twice 
                                = label
           | elem '_' label     = (first toUpper . nonCamel) label
           | otherwise          = camelCase label
    -- humanizing non-camel case identifiers
    nonCamel []             = []
    nonCamel ('_':[])       = []
    nonCamel (x:[])         = x:[]
    nonCamel ('_':x:[])     = ' ':toUpper x:[]
    nonCamel (x:y:[])       = x:nonCamel [y]
    nonCamel ('_':x:y:xs)
        | isUpper y         = ' ':toUpper x:nonCamel (y:xs)
        | otherwise         = ' ':toLower x:nonCamel (y:xs)
    nonCamel (x:xs)         = x:nonCamel xs
    --
    camelCase xs            = (first toUpper . drop 1 . seperateWords [] . first toUpper) xs
    seperateWords cs []           = cs
    seperateWords [] (x:xs)
        | isUpper x               = ' ':seperateWords [x] xs
        | otherwise               =   x:seperateWords [] xs
    seperateWords (c:[]) (x:xs)
        | isUpper x               = seperateWords (c:x:[]) xs
        | otherwise               = toLower c:x:seperateWords [] (xs)
    seperateWords (cs) (x:xs)
        | isUpper x               = seperateWords (cs ++ [x]) xs
        | otherwise               = (init cs) ++ ' ':(toLower $ last cs):x:seperateWords [] xs
    first _ []     = []
    first f (x:xs) = (f x):xs


{-

testHumanizeLabel :: IO ()
testHumanizeLabel = putStr $ unlines $ map testLabel tests
    where
      testLabel (actual, expected)
          = let (PriLabel _ result) = humanizeLabel (PriLabel GoodConstr actual)
            in (if result == expected then "True" else "Error (" ++ result ++ ")") ++ ": " ++ actual ++ " " ++ expected
      tests = [-- Underscore upper case
                ("download_Site_URI", "Download site URI")
              , ("default_Contents_Author", "Default contents author")
              , ("default_Contents_License", "Default contents license")
              , ("foobar_ASD_Foo", "Foobar ASD foo")
              -- Underscore lower case 
              , ("download_site", "Download site")
              , ("foobar_ASD_foo", "Foobar ASD foo")
              -- Camel case
              , ("FooBarSky", "Foo bar sky")
              , ("FooBASky", "Foo BA sky")
              , ("foobarASDFoo", "Foobar ASD foo")
              --
              , ("a", "A")
              , ("A", "A")
              , ("", "")
              , ("FOO", "FOO")
              ] ++ map (\x -> (x,x)) [ "Download FOO site", "Download something", "Foo" ]
      
-}

{- Rest is trash:

    replace _ _ []                = []
    replace this with (x:xs)
        | this == x               = with:replace this with xs   
        | otherwise               = x:replace this with xs

           -- | elem '_' label     = (first toUpper . replace '_' ' ') label
-}