{-# LANGUAGE OverloadedStrings, CPP #-}
module Text.LaTeX.Base.Warnings (
Warning (..)
, TeXCheck
, check
, checkFromFunction
, checkLabels
, checkClass
, checkDoc
, checkAll
) where
import Text.LaTeX.Base.Syntax
import Control.Monad.Trans.State
import Data.Text
import Data.Maybe
import Control.Arrow
#if !MIN_VERSION_base(4,8,0)
import Data.Monoid
#endif
import qualified Data.Semigroup as SG
data Warning =
UnusedLabel Text
| UndefinedLabel Text
| NoClassSelected
| NoDocumentInserted
| CustomWarning Text
deriving (Warning -> Warning -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Warning -> Warning -> Bool
$c/= :: Warning -> Warning -> Bool
== :: Warning -> Warning -> Bool
$c== :: Warning -> Warning -> Bool
Eq,Int -> Warning -> ShowS
[Warning] -> ShowS
Warning -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Warning] -> ShowS
$cshowList :: [Warning] -> ShowS
show :: Warning -> String
$cshow :: Warning -> String
showsPrec :: Int -> Warning -> ShowS
$cshowsPrec :: Int -> Warning -> ShowS
Show)
newtype TeXCheck = TC { TeXCheck -> LaTeX -> [Warning]
check :: LaTeX -> [Warning]
}
checkFromFunction :: (LaTeX -> [Warning]) -> TeXCheck
checkFromFunction :: (LaTeX -> [Warning]) -> TeXCheck
checkFromFunction = (LaTeX -> [Warning]) -> TeXCheck
TC
instance SG.Semigroup TeXCheck where
<> :: TeXCheck -> TeXCheck -> TeXCheck
(<>) = forall a. Monoid a => a -> a -> a
mappend
instance Monoid TeXCheck where
mempty :: TeXCheck
mempty = (LaTeX -> [Warning]) -> TeXCheck
TC forall a b. (a -> b) -> a -> b
$ forall a b. a -> b -> a
const []
mappend :: TeXCheck -> TeXCheck -> TeXCheck
mappend (TC LaTeX -> [Warning]
tc1) (TC LaTeX -> [Warning]
tc2) = (LaTeX -> [Warning]) -> TeXCheck
TC forall a b. (a -> b) -> a -> b
$ forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry forall a. Monoid a => a -> a -> a
mappend forall b c a. (b -> c) -> (a -> b) -> a -> c
. (LaTeX -> [Warning]
tc1 forall (a :: * -> * -> *) b c c'.
Arrow a =>
a b c -> a b c' -> a b (c, c')
&&& LaTeX -> [Warning]
tc2)
checkAll :: TeXCheck
checkAll :: TeXCheck
checkAll = forall a. Monoid a => [a] -> a
mconcat [ TeXCheck
checkLabels , TeXCheck
checkClass , TeXCheck
checkDoc ]
type BoolSt = State Bool
checkClass :: TeXCheck
checkClass :: TeXCheck
checkClass = (LaTeX -> [Warning]) -> TeXCheck
TC forall a b. (a -> b) -> a -> b
$ \LaTeX
l -> if forall s a. State s a -> s -> s
execState (LaTeX -> BoolSt ()
classcheck LaTeX
l) Bool
False then [] else [Warning
NoClassSelected]
classcheck :: LaTeX -> BoolSt ()
classcheck :: LaTeX -> BoolSt ()
classcheck (TeXComm String
c [TeXArg]
_) =
case String
c of
String
"documentclass" -> forall (m :: * -> *) s. Monad m => s -> StateT s m ()
put Bool
True
String
_ -> forall (m :: * -> *) a. Monad m => a -> m a
return ()
classcheck (TeXBraces LaTeX
l) = LaTeX -> BoolSt ()
classcheck LaTeX
l
classcheck (TeXSeq LaTeX
l1 LaTeX
l2) = LaTeX -> BoolSt ()
classcheck LaTeX
l1 forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> LaTeX -> BoolSt ()
classcheck LaTeX
l2
classcheck LaTeX
_ = forall (m :: * -> *) a. Monad m => a -> m a
return ()
checkDoc :: TeXCheck
checkDoc :: TeXCheck
checkDoc = (LaTeX -> [Warning]) -> TeXCheck
TC forall a b. (a -> b) -> a -> b
$ \LaTeX
l -> if forall s a. State s a -> s -> s
execState (LaTeX -> BoolSt ()
doccheck LaTeX
l) Bool
False then [] else [Warning
NoDocumentInserted]
doccheck :: LaTeX -> BoolSt ()
doccheck :: LaTeX -> BoolSt ()
doccheck (TeXEnv String
n [TeXArg]
_ LaTeX
_) =
case String
n of
String
"document" -> forall (m :: * -> *) s. Monad m => s -> StateT s m ()
put Bool
True
String
_ -> forall (m :: * -> *) a. Monad m => a -> m a
return ()
doccheck (TeXBraces LaTeX
l) = LaTeX -> BoolSt ()
doccheck LaTeX
l
doccheck (TeXSeq LaTeX
l1 LaTeX
l2) = LaTeX -> BoolSt ()
doccheck LaTeX
l1 forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> LaTeX -> BoolSt ()
doccheck LaTeX
l2
doccheck LaTeX
_ = forall (m :: * -> *) a. Monad m => a -> m a
return ()
data LabWarn =
RefNoLabel Text
| LabelNoRef Text
| LabelRef Text
labWarnToWarning :: LabWarn -> Maybe Warning
labWarnToWarning :: LabWarn -> Maybe Warning
labWarnToWarning (RefNoLabel Text
n) = forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ Text -> Warning
UndefinedLabel Text
n
labWarnToWarning (LabelNoRef Text
n) = forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ Text -> Warning
UnusedLabel Text
n
labWarnToWarning LabWarn
_ = forall a. Maybe a
Nothing
type LabSt = State [LabWarn]
checkLabels :: TeXCheck
checkLabels :: TeXCheck
checkLabels = (LaTeX -> [Warning]) -> TeXCheck
TC forall a b. (a -> b) -> a -> b
$ \LaTeX
l -> forall a. [Maybe a] -> [a]
catMaybes forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap LabWarn -> Maybe Warning
labWarnToWarning forall a b. (a -> b) -> a -> b
$ forall s a. State s a -> s -> s
execState (LaTeX -> LabSt ()
labcheck LaTeX
l) []
labcheck :: LaTeX -> LabSt ()
labcheck :: LaTeX -> LabSt ()
labcheck (TeXComm String
c [FixArg (TeXRaw Text
n)]) =
case String
c of
String
"label" -> Text -> LabSt ()
newlab Text
n
String
"ref" -> Text -> LabSt ()
newref Text
n
String
"pageref" -> Text -> LabSt ()
newref Text
n
String
_ -> forall (m :: * -> *) a. Monad m => a -> m a
return ()
labcheck (TeXEnv String
_ [TeXArg]
_ LaTeX
l) = LaTeX -> LabSt ()
labcheck LaTeX
l
labcheck (TeXMath MathType
_ LaTeX
l) = LaTeX -> LabSt ()
labcheck LaTeX
l
labcheck (TeXBraces LaTeX
l) = LaTeX -> LabSt ()
labcheck LaTeX
l
labcheck (TeXSeq LaTeX
l1 LaTeX
l2) = LaTeX -> LabSt ()
labcheck LaTeX
l1 forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> LaTeX -> LabSt ()
labcheck LaTeX
l2
labcheck LaTeX
_ = forall (m :: * -> *) a. Monad m => a -> m a
return ()
newlab :: Text -> LabSt ()
newlab :: Text -> LabSt ()
newlab Text
t = do
[LabWarn]
st <- forall (m :: * -> *) s. Monad m => StateT s m s
get
let addLab :: Text -> [LabWarn] -> [LabWarn]
addLab :: Text -> [LabWarn] -> [LabWarn]
addLab Text
n [] = [Text -> LabWarn
LabelNoRef Text
n]
addLab Text
n l :: [LabWarn]
l@(LabWarn
x:[LabWarn]
xs) = let ys :: [LabWarn]
ys = LabWarn
x forall a. a -> [a] -> [a]
: Text -> [LabWarn] -> [LabWarn]
addLab Text
n [LabWarn]
xs in
case LabWarn
x of
RefNoLabel Text
m -> if Text
n forall a. Eq a => a -> a -> Bool
== Text
m then Text -> LabWarn
LabelRef Text
n forall a. a -> [a] -> [a]
: [LabWarn]
xs
else [LabWarn]
ys
LabelNoRef Text
m -> if Text
n forall a. Eq a => a -> a -> Bool
== Text
m then [LabWarn]
l
else [LabWarn]
ys
LabelRef Text
m -> if Text
n forall a. Eq a => a -> a -> Bool
== Text
m then [LabWarn]
l
else [LabWarn]
ys
forall (m :: * -> *) s. Monad m => s -> StateT s m ()
put forall a b. (a -> b) -> a -> b
$ Text -> [LabWarn] -> [LabWarn]
addLab Text
t [LabWarn]
st
newref :: Text -> LabSt ()
newref :: Text -> LabSt ()
newref Text
t = do
[LabWarn]
st <- forall (m :: * -> *) s. Monad m => StateT s m s
get
let addRef :: Text -> [LabWarn] -> [LabWarn]
addRef :: Text -> [LabWarn] -> [LabWarn]
addRef Text
n [] = [Text -> LabWarn
RefNoLabel Text
n]
addRef Text
n l :: [LabWarn]
l@(LabWarn
x:[LabWarn]
xs) = let ys :: [LabWarn]
ys = LabWarn
x forall a. a -> [a] -> [a]
: Text -> [LabWarn] -> [LabWarn]
addRef Text
n [LabWarn]
xs in
case LabWarn
x of
RefNoLabel Text
m -> if Text
n forall a. Eq a => a -> a -> Bool
== Text
m then [LabWarn]
l
else [LabWarn]
ys
LabelNoRef Text
m -> if Text
n forall a. Eq a => a -> a -> Bool
== Text
m then Text -> LabWarn
LabelRef Text
n forall a. a -> [a] -> [a]
: [LabWarn]
xs
else [LabWarn]
ys
LabelRef Text
m -> if Text
n forall a. Eq a => a -> a -> Bool
== Text
m then [LabWarn]
l
else [LabWarn]
ys
forall (m :: * -> *) s. Monad m => s -> StateT s m ()
put forall a b. (a -> b) -> a -> b
$ Text -> [LabWarn] -> [LabWarn]
addRef Text
t [LabWarn]
st