{-# 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
(Warning -> Warning -> Bool)
-> (Warning -> Warning -> Bool) -> Eq Warning
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Warning -> Warning -> Bool
== :: Warning -> Warning -> Bool
$c/= :: Warning -> Warning -> Bool
/= :: Warning -> Warning -> Bool
Eq,Int -> Warning -> ShowS
[Warning] -> ShowS
Warning -> String
(Int -> Warning -> ShowS)
-> (Warning -> String) -> ([Warning] -> ShowS) -> Show Warning
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Warning -> ShowS
showsPrec :: Int -> Warning -> ShowS
$cshow :: Warning -> String
show :: Warning -> String
$cshowList :: [Warning] -> ShowS
showList :: [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
TC LaTeX -> [Warning]
tc1 <> :: TeXCheck -> TeXCheck -> TeXCheck
<> TC LaTeX -> [Warning]
tc2 = (LaTeX -> [Warning]) -> TeXCheck
TC ((LaTeX -> [Warning]) -> TeXCheck)
-> (LaTeX -> [Warning]) -> TeXCheck
forall a b. (a -> b) -> a -> b
$ ([Warning] -> [Warning] -> [Warning])
-> ([Warning], [Warning]) -> [Warning]
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry [Warning] -> [Warning] -> [Warning]
forall a. Semigroup a => a -> a -> a
(<>) (([Warning], [Warning]) -> [Warning])
-> (LaTeX -> ([Warning], [Warning])) -> LaTeX -> [Warning]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (LaTeX -> [Warning]
tc1 (LaTeX -> [Warning])
-> (LaTeX -> [Warning]) -> LaTeX -> ([Warning], [Warning])
forall b c c'. (b -> c) -> (b -> c') -> b -> (c, c')
forall (a :: * -> * -> *) b c c'.
Arrow a =>
a b c -> a b c' -> a b (c, c')
&&& LaTeX -> [Warning]
tc2)
instance Monoid TeXCheck where
mempty :: TeXCheck
mempty = (LaTeX -> [Warning]) -> TeXCheck
TC ((LaTeX -> [Warning]) -> TeXCheck)
-> (LaTeX -> [Warning]) -> TeXCheck
forall a b. (a -> b) -> a -> b
$ [Warning] -> LaTeX -> [Warning]
forall a b. a -> b -> a
const []
checkAll :: TeXCheck
checkAll :: TeXCheck
checkAll = [TeXCheck] -> TeXCheck
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 ((LaTeX -> [Warning]) -> TeXCheck)
-> (LaTeX -> [Warning]) -> TeXCheck
forall a b. (a -> b) -> a -> b
$ \LaTeX
l -> if State Bool () -> Bool -> Bool
forall s a. State s a -> s -> s
execState (LaTeX -> State Bool ()
classcheck LaTeX
l) Bool
False then [] else [Warning
NoClassSelected]
classcheck :: LaTeX -> BoolSt ()
classcheck :: LaTeX -> State Bool ()
classcheck (TeXComm String
c [TeXArg]
_) =
case String
c of
String
"documentclass" -> Bool -> State Bool ()
forall (m :: * -> *) s. Monad m => s -> StateT s m ()
put Bool
True
String
_ -> () -> State Bool ()
forall a. a -> StateT Bool Identity a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
classcheck (TeXBraces LaTeX
l) = LaTeX -> State Bool ()
classcheck LaTeX
l
classcheck (TeXSeq LaTeX
l1 LaTeX
l2) = LaTeX -> State Bool ()
classcheck LaTeX
l1 State Bool () -> State Bool () -> State Bool ()
forall a b.
StateT Bool Identity a
-> StateT Bool Identity b -> StateT Bool Identity b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> LaTeX -> State Bool ()
classcheck LaTeX
l2
classcheck LaTeX
_ = () -> State Bool ()
forall a. a -> StateT Bool Identity a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
checkDoc :: TeXCheck
checkDoc :: TeXCheck
checkDoc = (LaTeX -> [Warning]) -> TeXCheck
TC ((LaTeX -> [Warning]) -> TeXCheck)
-> (LaTeX -> [Warning]) -> TeXCheck
forall a b. (a -> b) -> a -> b
$ \LaTeX
l -> if State Bool () -> Bool -> Bool
forall s a. State s a -> s -> s
execState (LaTeX -> State Bool ()
doccheck LaTeX
l) Bool
False then [] else [Warning
NoDocumentInserted]
doccheck :: LaTeX -> BoolSt ()
doccheck :: LaTeX -> State Bool ()
doccheck (TeXEnv String
n [TeXArg]
_ LaTeX
_) =
case String
n of
String
"document" -> Bool -> State Bool ()
forall (m :: * -> *) s. Monad m => s -> StateT s m ()
put Bool
True
String
_ -> () -> State Bool ()
forall a. a -> StateT Bool Identity a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
doccheck (TeXBraces LaTeX
l) = LaTeX -> State Bool ()
doccheck LaTeX
l
doccheck (TeXSeq LaTeX
l1 LaTeX
l2) = LaTeX -> State Bool ()
doccheck LaTeX
l1 State Bool () -> State Bool () -> State Bool ()
forall a b.
StateT Bool Identity a
-> StateT Bool Identity b -> StateT Bool Identity b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> LaTeX -> State Bool ()
doccheck LaTeX
l2
doccheck LaTeX
_ = () -> State Bool ()
forall a. a -> StateT Bool Identity a
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) = Warning -> Maybe Warning
forall a. a -> Maybe a
Just (Warning -> Maybe Warning) -> Warning -> Maybe Warning
forall a b. (a -> b) -> a -> b
$ Text -> Warning
UndefinedLabel Text
n
labWarnToWarning (LabelNoRef Text
n) = Warning -> Maybe Warning
forall a. a -> Maybe a
Just (Warning -> Maybe Warning) -> Warning -> Maybe Warning
forall a b. (a -> b) -> a -> b
$ Text -> Warning
UnusedLabel Text
n
labWarnToWarning LabWarn
_ = Maybe Warning
forall a. Maybe a
Nothing
type LabSt = State [LabWarn]
checkLabels :: TeXCheck
checkLabels :: TeXCheck
checkLabels = (LaTeX -> [Warning]) -> TeXCheck
TC ((LaTeX -> [Warning]) -> TeXCheck)
-> (LaTeX -> [Warning]) -> TeXCheck
forall a b. (a -> b) -> a -> b
$ \LaTeX
l -> [Maybe Warning] -> [Warning]
forall a. [Maybe a] -> [a]
catMaybes ([Maybe Warning] -> [Warning])
-> ([LabWarn] -> [Maybe Warning]) -> [LabWarn] -> [Warning]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (LabWarn -> Maybe Warning) -> [LabWarn] -> [Maybe Warning]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap LabWarn -> Maybe Warning
labWarnToWarning ([LabWarn] -> [Warning]) -> [LabWarn] -> [Warning]
forall a b. (a -> b) -> a -> b
$ State [LabWarn] () -> [LabWarn] -> [LabWarn]
forall s a. State s a -> s -> s
execState (LaTeX -> State [LabWarn] ()
labcheck LaTeX
l) []
labcheck :: LaTeX -> LabSt ()
labcheck :: LaTeX -> State [LabWarn] ()
labcheck (TeXComm String
c [FixArg (TeXRaw Text
n)]) =
case String
c of
String
"label" -> Text -> State [LabWarn] ()
newlab Text
n
String
"ref" -> Text -> State [LabWarn] ()
newref Text
n
String
"pageref" -> Text -> State [LabWarn] ()
newref Text
n
String
_ -> () -> State [LabWarn] ()
forall a. a -> StateT [LabWarn] Identity a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
labcheck (TeXEnv String
_ [TeXArg]
_ LaTeX
l) = LaTeX -> State [LabWarn] ()
labcheck LaTeX
l
labcheck (TeXMath MathType
_ LaTeX
l) = LaTeX -> State [LabWarn] ()
labcheck LaTeX
l
labcheck (TeXBraces LaTeX
l) = LaTeX -> State [LabWarn] ()
labcheck LaTeX
l
labcheck (TeXSeq LaTeX
l1 LaTeX
l2) = LaTeX -> State [LabWarn] ()
labcheck LaTeX
l1 State [LabWarn] () -> State [LabWarn] () -> State [LabWarn] ()
forall a b.
StateT [LabWarn] Identity a
-> StateT [LabWarn] Identity b -> StateT [LabWarn] Identity b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> LaTeX -> State [LabWarn] ()
labcheck LaTeX
l2
labcheck LaTeX
_ = () -> State [LabWarn] ()
forall a. a -> StateT [LabWarn] Identity a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
newlab :: Text -> LabSt ()
newlab :: Text -> State [LabWarn] ()
newlab Text
t = do
[LabWarn]
st <- StateT [LabWarn] Identity [LabWarn]
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 LabWarn -> [LabWarn] -> [LabWarn]
forall a. a -> [a] -> [a]
: Text -> [LabWarn] -> [LabWarn]
addLab Text
n [LabWarn]
xs in
case LabWarn
x of
RefNoLabel Text
m -> if Text
n Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text
m then Text -> LabWarn
LabelRef Text
n LabWarn -> [LabWarn] -> [LabWarn]
forall a. a -> [a] -> [a]
: [LabWarn]
xs
else [LabWarn]
ys
LabelNoRef Text
m -> if Text
n Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text
m then [LabWarn]
l
else [LabWarn]
ys
LabelRef Text
m -> if Text
n Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text
m then [LabWarn]
l
else [LabWarn]
ys
[LabWarn] -> State [LabWarn] ()
forall (m :: * -> *) s. Monad m => s -> StateT s m ()
put ([LabWarn] -> State [LabWarn] ())
-> [LabWarn] -> State [LabWarn] ()
forall a b. (a -> b) -> a -> b
$ Text -> [LabWarn] -> [LabWarn]
addLab Text
t [LabWarn]
st
newref :: Text -> LabSt ()
newref :: Text -> State [LabWarn] ()
newref Text
t = do
[LabWarn]
st <- StateT [LabWarn] Identity [LabWarn]
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 LabWarn -> [LabWarn] -> [LabWarn]
forall a. a -> [a] -> [a]
: Text -> [LabWarn] -> [LabWarn]
addRef Text
n [LabWarn]
xs in
case LabWarn
x of
RefNoLabel Text
m -> if Text
n Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text
m then [LabWarn]
l
else [LabWarn]
ys
LabelNoRef Text
m -> if Text
n Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text
m then Text -> LabWarn
LabelRef Text
n LabWarn -> [LabWarn] -> [LabWarn]
forall a. a -> [a] -> [a]
: [LabWarn]
xs
else [LabWarn]
ys
LabelRef Text
m -> if Text
n Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text
m then [LabWarn]
l
else [LabWarn]
ys
[LabWarn] -> State [LabWarn] ()
forall (m :: * -> *) s. Monad m => s -> StateT s m ()
put ([LabWarn] -> State [LabWarn] ())
-> [LabWarn] -> State [LabWarn] ()
forall a b. (a -> b) -> a -> b
$ Text -> [LabWarn] -> [LabWarn]
addRef Text
t [LabWarn]
st