module Text.Authoring.Combinator.Ref where
import Control.Lens
import Control.Monad.State
import Control.Monad.Writer
import Data.Char (isAlphaNum)
import qualified Data.Map as Map
import qualified Data.Set as Set
import Data.Text (Text, pack)
import Text.Authoring.Document
import Text.Authoring.State
import Text.Authoring.Label
import Text.Authoring.Combinator.Writer
import Text.Authoring.Combinator.Meta
ref :: (MonadState s m, HasAuthorState s, MonadWriter w m, HasDocument w) => Label -> m ()
ref lab = do
ret <- getReference lab
command1 "ref" $ raw ret
label :: (MonadState s m, HasAuthorState s, MonadWriter w m, HasDocument w) => Label -> m ()
label lab = do
ret <- getReference lab
command1 "label" $ raw ret
getReference :: (MonadState s m, HasAuthorState s) => Label -> m Text
getReference lab = do
map0 <- use labelMap
case Map.lookup lab map0 of
Just str -> return str
Nothing -> do
let cands :: [String]
cands = cand0 : [s ++ [c]| s <- cands, c <- ['0'..'9']]
cand0 = map modify $ show lab
modify :: Char -> Char
modify c
| isAlphaNum c = c
| otherwise = '.'
takens :: Set.Set Text
takens = Set.fromList $ Map.elems map0
isTaken x = Set.member (pack x) takens
freeStr :: Text
freeStr = pack $ head $ filter (not . isTaken) cands
labelMap %= (Map.insert lab freeStr)
return freeStr