{-# LANGUAGE CPP #-}
{-# LANGUAGE ViewPatterns #-}
module Agda.Interaction.Highlighting.LaTeX.Base
( generateLaTeXIO
, prepareCommonAssets
, runLogLaTeXTWith
, logMsgToText
, LogMessage(..)
, MonadLogLaTeX
, LogLaTeXT
, LaTeXOptions(..)
) where
import Prelude hiding (log)
import Data.Bifunctor (second)
import Data.Char
import Data.Maybe
import Data.Function
import Data.Foldable (toList)
#if !(MIN_VERSION_base(4,11,0))
import Data.Semigroup (Semigroup(..))
#endif
import Control.Monad (forM_, mapM_, unless, when)
import Control.Monad.Trans.Reader as R ( ReaderT(runReaderT))
import Control.Monad.RWS.Strict
( RWST(runRWST)
, MonadReader(..), asks
, MonadState(..), gets, modify
, lift, tell
)
import Control.Monad.IO.Class
( MonadIO(..)
)
import System.Directory
import System.Exit
import System.FilePath
import System.Process
import Data.Text (Text)
import qualified Data.Text as T
#ifdef COUNT_CLUSTERS
import qualified Data.Text.ICU as ICU
#endif
import qualified Data.Text.Lazy as L
import qualified Data.Text.Lazy.Encoding as E
import qualified Data.ByteString.Lazy as BS
import Data.HashSet (HashSet)
import qualified Data.HashSet as Set
import qualified Data.IntMap as IntMap
import qualified Data.List as List
import Paths_Agda
import Agda.Syntax.Abstract (toTopLevelModuleName)
import Agda.Syntax.Common
import Agda.Syntax.Concrete (TopLevelModuleName, moduleNameParts)
import Agda.Syntax.Parser.Literate (literateTeX, LayerRole, atomizeLayers)
import qualified Agda.Syntax.Parser.Literate as L
import Agda.Syntax.Position (startPos)
import Agda.Interaction.Highlighting.Precise hiding (toList)
import Agda.TypeChecking.Monad (Interface(..))
import Agda.Utils.FileName (AbsolutePath)
import Agda.Utils.Function (applyWhen)
import Agda.Utils.Functor ((<&>))
import Agda.Utils.List (last1, updateHead, updateLast)
import Agda.Utils.Maybe (whenJust)
import qualified Agda.Utils.List1 as List1
import Agda.Utils.Impossible
class Monad m => MonadLogLaTeX m where
logLaTeX :: LogMessage -> m ()
type LogLaTeXT m = ReaderT (LogMessage -> m ()) m
instance Monad m => MonadLogLaTeX (LogLaTeXT m) where
logLaTeX :: LogMessage -> LogLaTeXT m ()
logLaTeX LogMessage
message = do
LogMessage -> m ()
doLog <- ReaderT (LogMessage -> m ()) m (LogMessage -> m ())
forall r (m :: * -> *). MonadReader r m => m r
ask
m () -> LogLaTeXT m ()
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m () -> LogLaTeXT m ()) -> m () -> LogLaTeXT m ()
forall a b. (a -> b) -> a -> b
$ LogMessage -> m ()
doLog LogMessage
message
runLogLaTeXTWith :: Monad m => (LogMessage -> m ()) -> LogLaTeXT m a -> m a
runLogLaTeXTWith :: (LogMessage -> m ()) -> LogLaTeXT m a -> m a
runLogLaTeXTWith = (LogLaTeXT m a -> (LogMessage -> m ()) -> m a)
-> (LogMessage -> m ()) -> LogLaTeXT m a -> m a
forall a b c. (a -> b -> c) -> b -> a -> c
flip LogLaTeXT m a -> (LogMessage -> m ()) -> m a
forall r (m :: * -> *) a. ReaderT r m a -> r -> m a
runReaderT
type LaTeX a = forall m. MonadLogLaTeX m => RWST Env [Output] State m a
data LogMessage = LogMessage Debug Text [Text] deriving Int -> LogMessage -> ShowS
[LogMessage] -> ShowS
LogMessage -> String
(Int -> LogMessage -> ShowS)
-> (LogMessage -> String)
-> ([LogMessage] -> ShowS)
-> Show LogMessage
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [LogMessage] -> ShowS
$cshowList :: [LogMessage] -> ShowS
show :: LogMessage -> String
$cshow :: LogMessage -> String
showsPrec :: Int -> LogMessage -> ShowS
$cshowsPrec :: Int -> LogMessage -> ShowS
Show
data Output
= Text !Text
| MaybeColumn !AlignmentColumn
deriving Int -> Output -> ShowS
[Output] -> ShowS
Output -> String
(Int -> Output -> ShowS)
-> (Output -> String) -> ([Output] -> ShowS) -> Show Output
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Output] -> ShowS
$cshowList :: [Output] -> ShowS
show :: Output -> String
$cshow :: Output -> String
showsPrec :: Int -> Output -> ShowS
$cshowsPrec :: Int -> Output -> ShowS
Show
data Kind
= Indentation
| Alignment
deriving (Kind -> Kind -> Bool
(Kind -> Kind -> Bool) -> (Kind -> Kind -> Bool) -> Eq Kind
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Kind -> Kind -> Bool
$c/= :: Kind -> Kind -> Bool
== :: Kind -> Kind -> Bool
$c== :: Kind -> Kind -> Bool
Eq, Int -> Kind -> ShowS
[Kind] -> ShowS
Kind -> String
(Int -> Kind -> ShowS)
-> (Kind -> String) -> ([Kind] -> ShowS) -> Show Kind
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Kind] -> ShowS
$cshowList :: [Kind] -> ShowS
show :: Kind -> String
$cshow :: Kind -> String
showsPrec :: Int -> Kind -> ShowS
$cshowsPrec :: Int -> Kind -> ShowS
Show)
type IndentationColumnId = Int
data AlignmentColumn = AlignmentColumn
{ AlignmentColumn -> Int
columnCodeBlock :: !Int
, AlignmentColumn -> Int
columnColumn :: !Int
, AlignmentColumn -> Maybe Int
columnKind :: Maybe IndentationColumnId
} deriving Int -> AlignmentColumn -> ShowS
[AlignmentColumn] -> ShowS
AlignmentColumn -> String
(Int -> AlignmentColumn -> ShowS)
-> (AlignmentColumn -> String)
-> ([AlignmentColumn] -> ShowS)
-> Show AlignmentColumn
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [AlignmentColumn] -> ShowS
$cshowList :: [AlignmentColumn] -> ShowS
show :: AlignmentColumn -> String
$cshow :: AlignmentColumn -> String
showsPrec :: Int -> AlignmentColumn -> ShowS
$cshowsPrec :: Int -> AlignmentColumn -> ShowS
Show
type TextWidthEstimator = Text -> Int
data Env = Env
{ Env -> TextWidthEstimator
estimateTextWidth :: !TextWidthEstimator
, Env -> [Debug]
debugs :: [Debug]
}
data State = State
{ State -> Int
codeBlock :: !Int
, State -> Int
column :: !Int
, State -> [AlignmentColumn]
columns :: [AlignmentColumn]
, State -> [AlignmentColumn]
columnsPrev :: [AlignmentColumn]
, State -> Int
nextId :: !IndentationColumnId
, State -> HashSet Int
usedColumns :: HashSet IndentationColumnId
}
type Tokens = [Token]
data Token = Token
{ Token -> Text
text :: !Text
, Token -> Aspects
info :: Aspects
}
deriving Int -> Token -> ShowS
[Token] -> ShowS
Token -> String
(Int -> Token -> ShowS)
-> (Token -> String) -> ([Token] -> ShowS) -> Show Token
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Token] -> ShowS
$cshowList :: [Token] -> ShowS
show :: Token -> String
$cshow :: Token -> String
showsPrec :: Int -> Token -> ShowS
$cshowsPrec :: Int -> Token -> ShowS
Show
withTokenText :: (Text -> Text) -> Token -> Token
withTokenText :: (Text -> Text) -> Token -> Token
withTokenText Text -> Text
f tok :: Token
tok@Token{text :: Token -> Text
text = Text
t} = Token
tok{text :: Text
text = Text -> Text
f Text
t}
data Debug = MoveColumn | NonCode | Code | Spaces | Output | FileSystem
deriving (Debug -> Debug -> Bool
(Debug -> Debug -> Bool) -> (Debug -> Debug -> Bool) -> Eq Debug
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Debug -> Debug -> Bool
$c/= :: Debug -> Debug -> Bool
== :: Debug -> Debug -> Bool
$c== :: Debug -> Debug -> Bool
Eq, Int -> Debug -> ShowS
[Debug] -> ShowS
Debug -> String
(Int -> Debug -> ShowS)
-> (Debug -> String) -> ([Debug] -> ShowS) -> Show Debug
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Debug] -> ShowS
$cshowList :: [Debug] -> ShowS
show :: Debug -> String
$cshow :: Debug -> String
showsPrec :: Int -> Debug -> ShowS
$cshowsPrec :: Int -> Debug -> ShowS
Show)
runLaTeX :: MonadLogLaTeX m =>
LaTeX a -> Env -> State -> m (a, State, [Output])
runLaTeX :: LaTeX a -> Env -> State -> m (a, State, [Output])
runLaTeX LaTeX a
l = RWST Env [Output] State m a
-> Env -> State -> m (a, State, [Output])
forall r w s (m :: * -> *) a.
RWST r w s m a -> r -> s -> m (a, s, w)
runRWST RWST Env [Output] State m a
LaTeX a
l
emptyState :: State
emptyState :: State
emptyState = State :: Int
-> Int
-> [AlignmentColumn]
-> [AlignmentColumn]
-> Int
-> HashSet Int
-> State
State
{ codeBlock :: Int
codeBlock = Int
0
, column :: Int
column = Int
0
, columns :: [AlignmentColumn]
columns = []
, columnsPrev :: [AlignmentColumn]
columnsPrev = []
, nextId :: Int
nextId = Int
0
, usedColumns :: HashSet Int
usedColumns = HashSet Int
forall a. HashSet a
Set.empty
}
emptyEnv
:: TextWidthEstimator
-> Env
emptyEnv :: TextWidthEstimator -> Env
emptyEnv TextWidthEstimator
twe = TextWidthEstimator -> [Debug] -> Env
Env TextWidthEstimator
twe []
size :: Text -> LaTeX Int
size :: Text -> LaTeX Int
size Text
t = (Env -> TextWidthEstimator)
-> RWST Env [Output] State m TextWidthEstimator
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks Env -> TextWidthEstimator
estimateTextWidth RWST Env [Output] State m TextWidthEstimator
-> (TextWidthEstimator -> Int) -> RWST Env [Output] State m Int
forall (m :: * -> *) a b. Functor m => m a -> (a -> b) -> m b
<&> (TextWidthEstimator -> TextWidthEstimator
forall a b. (a -> b) -> a -> b
$ Text
t)
isSpaces :: Text -> Bool
isSpaces :: Text -> Bool
isSpaces = (Char -> Bool) -> Text -> Bool
T.all Char -> Bool
isSpace
isSpaceNotNewline :: Char -> Bool
isSpaceNotNewline :: Char -> Bool
isSpaceNotNewline Char
c = Char -> Bool
isSpace Char
c Bool -> Bool -> Bool
&& Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/= Char
'\n'
replaceSpaces :: Text -> Text
replaceSpaces :: Text -> Text
replaceSpaces = (Char -> Char) -> Text -> Text
T.map (\Char
c -> if Char -> Bool
isSpaceNotNewline Char
c then Char
' ' else Char
c)
moveColumnForToken :: Token -> LaTeX ()
moveColumnForToken :: Token -> LaTeX ()
moveColumnForToken Token{ text :: Token -> Text
text = Text
t } = do
Bool
-> RWST Env [Output] State m () -> RWST Env [Output] State m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (Text -> Bool
isSpaces Text
t) (RWST Env [Output] State m () -> RWST Env [Output] State m ())
-> RWST Env [Output] State m () -> RWST Env [Output] State m ()
forall a b. (a -> b) -> a -> b
$ do
Debug -> Text -> LaTeX ()
log Debug
MoveColumn Text
t
Int
n <- Text -> LaTeX Int
size Text
t
Int -> LaTeX ()
moveColumn Int
n
resetColumn :: LaTeX ()
resetColumn :: RWST Env [Output] State m ()
resetColumn = (State -> State) -> RWST Env [Output] State m ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify ((State -> State) -> RWST Env [Output] State m ())
-> (State -> State) -> RWST Env [Output] State m ()
forall a b. (a -> b) -> a -> b
$ \State
s ->
State
s { column :: Int
column = Int
0
, columnsPrev :: [AlignmentColumn]
columnsPrev = [AlignmentColumn] -> [AlignmentColumn] -> [AlignmentColumn]
mergeCols (State -> [AlignmentColumn]
columns State
s) (State -> [AlignmentColumn]
columnsPrev State
s)
, columns :: [AlignmentColumn]
columns = []
}
where
mergeCols :: [AlignmentColumn] -> [AlignmentColumn] -> [AlignmentColumn]
mergeCols [] [AlignmentColumn]
old = [AlignmentColumn]
old
mergeCols new :: [AlignmentColumn]
new@(AlignmentColumn
n:[AlignmentColumn]
ns) [AlignmentColumn]
old = [AlignmentColumn]
new [AlignmentColumn] -> [AlignmentColumn] -> [AlignmentColumn]
forall a. [a] -> [a] -> [a]
++ (AlignmentColumn -> Bool) -> [AlignmentColumn] -> [AlignmentColumn]
forall a. (a -> Bool) -> [a] -> [a]
filter ((Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
leastNew) (Int -> Bool)
-> (AlignmentColumn -> Int) -> AlignmentColumn -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. AlignmentColumn -> Int
columnColumn) [AlignmentColumn]
old
where
leastNew :: Int
leastNew = AlignmentColumn -> Int
columnColumn (AlignmentColumn -> [AlignmentColumn] -> AlignmentColumn
forall a. a -> [a] -> a
last1 AlignmentColumn
n [AlignmentColumn]
ns)
moveColumn :: Int -> LaTeX ()
moveColumn :: Int -> LaTeX ()
moveColumn Int
i = (State -> State) -> RWST Env [Output] State m ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify ((State -> State) -> RWST Env [Output] State m ())
-> (State -> State) -> RWST Env [Output] State m ()
forall a b. (a -> b) -> a -> b
$ \State
s -> State
s { column :: Int
column = Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
+ State -> Int
column State
s }
registerColumn :: Kind -> LaTeX AlignmentColumn
registerColumn :: Kind -> LaTeX AlignmentColumn
registerColumn Kind
kind = do
Int
column <- (State -> Int) -> RWST Env [Output] State m Int
forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
gets State -> Int
column
Int
codeBlock <- (State -> Int) -> RWST Env [Output] State m Int
forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
gets State -> Int
codeBlock
Maybe Int
colKind <- case Kind
kind of
Kind
Alignment -> Maybe Int -> RWST Env [Output] State m (Maybe Int)
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe Int
forall a. Maybe a
Nothing
Kind
Indentation -> do
Int
nextId <- (State -> Int) -> RWST Env [Output] State m Int
forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
gets State -> Int
nextId
(State -> State) -> RWST Env [Output] State m ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify ((State -> State) -> RWST Env [Output] State m ())
-> (State -> State) -> RWST Env [Output] State m ()
forall a b. (a -> b) -> a -> b
$ \State
s -> State
s { nextId :: Int
nextId = Int -> Int
forall a. Enum a => a -> a
succ Int
nextId }
Maybe Int -> RWST Env [Output] State m (Maybe Int)
forall (m :: * -> *) a. Monad m => a -> m a
return (Int -> Maybe Int
forall a. a -> Maybe a
Just Int
nextId)
let c :: AlignmentColumn
c = AlignmentColumn :: Int -> Int -> Maybe Int -> AlignmentColumn
AlignmentColumn { columnColumn :: Int
columnColumn = Int
column
, columnCodeBlock :: Int
columnCodeBlock = Int
codeBlock
, columnKind :: Maybe Int
columnKind = Maybe Int
colKind
}
(State -> State) -> RWST Env [Output] State m ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify ((State -> State) -> RWST Env [Output] State m ())
-> (State -> State) -> RWST Env [Output] State m ()
forall a b. (a -> b) -> a -> b
$ \State
s -> State
s { columns :: [AlignmentColumn]
columns = AlignmentColumn
c AlignmentColumn -> [AlignmentColumn] -> [AlignmentColumn]
forall a. a -> [a] -> [a]
: State -> [AlignmentColumn]
columns State
s }
AlignmentColumn -> RWST Env [Output] State m AlignmentColumn
forall (m :: * -> *) a. Monad m => a -> m a
return AlignmentColumn
c
useColumn :: AlignmentColumn -> LaTeX ()
useColumn :: AlignmentColumn -> LaTeX ()
useColumn AlignmentColumn
c = Maybe Int
-> (Int -> RWST Env [Output] State m ())
-> RWST Env [Output] State m ()
forall (m :: * -> *) a. Monad m => Maybe a -> (a -> m ()) -> m ()
whenJust (AlignmentColumn -> Maybe Int
columnKind AlignmentColumn
c) ((Int -> RWST Env [Output] State m ())
-> RWST Env [Output] State m ())
-> (Int -> RWST Env [Output] State m ())
-> RWST Env [Output] State m ()
forall a b. (a -> b) -> a -> b
$ \ Int
i ->
(State -> State) -> RWST Env [Output] State m ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify ((State -> State) -> RWST Env [Output] State m ())
-> (State -> State) -> RWST Env [Output] State m ()
forall a b. (a -> b) -> a -> b
$ \ State
s -> State
s { usedColumns :: HashSet Int
usedColumns = Int -> HashSet Int -> HashSet Int
forall a. (Eq a, Hashable a) => a -> HashSet a -> HashSet a
Set.insert Int
i (State -> HashSet Int
usedColumns State
s) }
columnZero :: LaTeX AlignmentColumn
columnZero :: RWST Env [Output] State m AlignmentColumn
columnZero = do
Int
codeBlock <- (State -> Int) -> RWST Env [Output] State m Int
forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
gets State -> Int
codeBlock
AlignmentColumn -> RWST Env [Output] State m AlignmentColumn
forall (m :: * -> *) a. Monad m => a -> m a
return (AlignmentColumn -> RWST Env [Output] State m AlignmentColumn)
-> AlignmentColumn -> RWST Env [Output] State m AlignmentColumn
forall a b. (a -> b) -> a -> b
$ AlignmentColumn :: Int -> Int -> Maybe Int -> AlignmentColumn
AlignmentColumn { columnColumn :: Int
columnColumn = Int
0
, columnCodeBlock :: Int
columnCodeBlock = Int
codeBlock
, columnKind :: Maybe Int
columnKind = Maybe Int
forall a. Maybe a
Nothing
}
registerColumnZero :: LaTeX ()
registerColumnZero :: RWST Env [Output] State m ()
registerColumnZero = do
AlignmentColumn
c <- RWST Env [Output] State m AlignmentColumn
LaTeX AlignmentColumn
columnZero
(State -> State) -> RWST Env [Output] State m ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify ((State -> State) -> RWST Env [Output] State m ())
-> (State -> State) -> RWST Env [Output] State m ()
forall a b. (a -> b) -> a -> b
$ \State
s -> State
s { columns :: [AlignmentColumn]
columns = [AlignmentColumn
c] }
enterCode :: LaTeX ()
enterCode :: RWST Env [Output] State m ()
enterCode = do
RWST Env [Output] State m ()
LaTeX ()
resetColumn
(State -> State) -> RWST Env [Output] State m ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify ((State -> State) -> RWST Env [Output] State m ())
-> (State -> State) -> RWST Env [Output] State m ()
forall a b. (a -> b) -> a -> b
$ \State
s -> State
s { codeBlock :: Int
codeBlock = State -> Int
codeBlock State
s Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1 }
leaveCode :: LaTeX ()
leaveCode :: RWST Env [Output] State m ()
leaveCode = () -> RWST Env [Output] State m ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
tshow :: Show a => a -> Text
tshow :: a -> Text
tshow = String -> Text
T.pack (String -> Text) -> (a -> String) -> a -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> String
forall a. Show a => a -> String
show
logMsgToText :: LogMessage -> Text
logMsgToText :: LogMessage -> Text
logMsgToText (LogMessage Debug
messageLabel Text
text [Text]
extra) = [Text] -> Text
T.concat ([Text] -> Text) -> [Text] -> Text
forall a b. (a -> b) -> a -> b
$
[ Debug -> Text
forall a. Show a => a -> Text
tshow Debug
messageLabel, Text
": '", Text
text, Text
"' "
] [Text] -> [Text] -> [Text]
forall a. [a] -> [a] -> [a]
++ if [Text] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Text]
extra then [] else [Text
"(", [Text] -> Text
T.unwords [Text]
extra, Text
")"]
logHelper :: Debug -> Text -> [Text] -> LaTeX ()
logHelper :: Debug -> Text -> [Text] -> LaTeX ()
logHelper Debug
debug Text
text [Text]
extra = do
[Debug]
logLevels <- Env -> [Debug]
debugs (Env -> [Debug])
-> RWST Env [Output] State m Env
-> RWST Env [Output] State m [Debug]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> RWST Env [Output] State m Env
forall r (m :: * -> *). MonadReader r m => m r
ask
Bool
-> RWST Env [Output] State m () -> RWST Env [Output] State m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Debug
debug Debug -> [Debug] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Debug]
logLevels) (RWST Env [Output] State m () -> RWST Env [Output] State m ())
-> RWST Env [Output] State m () -> RWST Env [Output] State m ()
forall a b. (a -> b) -> a -> b
$ do
m () -> RWST Env [Output] State m ()
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m () -> RWST Env [Output] State m ())
-> m () -> RWST Env [Output] State m ()
forall a b. (a -> b) -> a -> b
$ LogMessage -> m ()
forall (m :: * -> *). MonadLogLaTeX m => LogMessage -> m ()
logLaTeX (Debug -> Text -> [Text] -> LogMessage
LogMessage Debug
debug Text
text [Text]
extra)
log :: Debug -> Text -> LaTeX ()
log :: Debug -> Text -> LaTeX ()
log Debug
MoveColumn Text
text = do
[AlignmentColumn]
cols <- (State -> [AlignmentColumn])
-> RWST Env [Output] State m [AlignmentColumn]
forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
gets State -> [AlignmentColumn]
columns
Debug -> Text -> [Text] -> LaTeX ()
logHelper Debug
MoveColumn Text
text [Text
"columns=", [AlignmentColumn] -> Text
forall a. Show a => a -> Text
tshow [AlignmentColumn]
cols]
log Debug
Code Text
text = do
[AlignmentColumn]
cols <- (State -> [AlignmentColumn])
-> RWST Env [Output] State m [AlignmentColumn]
forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
gets State -> [AlignmentColumn]
columns
Int
col <- (State -> Int) -> RWST Env [Output] State m Int
forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
gets State -> Int
column
Debug -> Text -> [Text] -> LaTeX ()
logHelper Debug
Code Text
text [Text
"columns=", [AlignmentColumn] -> Text
forall a. Show a => a -> Text
tshow [AlignmentColumn]
cols, Text
"col=", Int -> Text
forall a. Show a => a -> Text
tshow Int
col]
log Debug
debug Text
text = Debug -> Text -> [Text] -> LaTeX ()
logHelper Debug
debug Text
text []
output :: Output -> LaTeX ()
output :: Output -> LaTeX ()
output Output
item = do
Debug -> Text -> LaTeX ()
log Debug
Output (Text -> LaTeX ()) -> Text -> LaTeX ()
forall a b. (a -> b) -> a -> b
$ Output -> Text
forall a. Show a => a -> Text
tshow Output
item
[Output] -> RWST Env [Output] State m ()
forall w (m :: * -> *). MonadWriter w m => w -> m ()
tell [Output
item]
nl :: Text
nl :: Text
nl = Text
"%\n"
agdaSpace :: Text
agdaSpace :: Text
agdaSpace = Text
cmdPrefix Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"Space" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
cmdArg Text
T.empty Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
nl
columnName :: AlignmentColumn -> Text
columnName :: AlignmentColumn -> Text
columnName AlignmentColumn
c = String -> Text
T.pack (String -> Text) -> String -> Text
forall a b. (a -> b) -> a -> b
$ case AlignmentColumn -> Maybe Int
columnKind AlignmentColumn
c of
Maybe Int
Nothing -> Int -> String
forall a. Show a => a -> String
show (AlignmentColumn -> Int
columnColumn AlignmentColumn
c)
Just Int
i -> Int -> String
forall a. Show a => a -> String
show Int
i String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"I"
ptOpen' :: Text -> Text
ptOpen' :: Text -> Text
ptOpen' Text
name = Text
"\\>[" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
name Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"]"
ptOpen :: AlignmentColumn -> Text
ptOpen :: AlignmentColumn -> Text
ptOpen AlignmentColumn
c = Text -> Text
ptOpen' (AlignmentColumn -> Text
columnName AlignmentColumn
c)
ptOpenBeginningOfLine :: Text
ptOpenBeginningOfLine :: Text
ptOpenBeginningOfLine = Text -> Text
ptOpen' Text
"." Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"[@{}l@{}]"
ptOpenIndent
:: AlignmentColumn
-> Int
-> Text
ptOpenIndent :: AlignmentColumn -> Int -> Text
ptOpenIndent AlignmentColumn
c Int
delta =
AlignmentColumn -> Text
ptOpen AlignmentColumn
c Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"[@{}l@{"
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
cmdPrefix
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"Indent"
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
cmdArg (String -> Text
T.pack (String -> Text) -> String -> Text
forall a b. (a -> b) -> a -> b
$ Int -> String
forall a. Show a => a -> String
show Int
delta)
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"}]"
ptClose :: Text
ptClose :: Text
ptClose = Text
"\\<"
ptClose' :: AlignmentColumn -> Text
ptClose' :: AlignmentColumn -> Text
ptClose' AlignmentColumn
c =
Text
ptClose Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"[" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> AlignmentColumn -> Text
columnName AlignmentColumn
c Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"]"
ptNL :: Text
ptNL :: Text
ptNL = Text
nl Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"\\\\\n"
ptEmptyLine :: Text
ptEmptyLine :: Text
ptEmptyLine =
Text
nl Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"\\\\["
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
cmdPrefix
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"EmptyExtraSkip"
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"]%\n"
cmdPrefix :: Text
cmdPrefix :: Text
cmdPrefix = Text
"\\Agda"
cmdArg :: Text -> Text
cmdArg :: Text -> Text
cmdArg Text
x = Text
"{" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
x Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"}"
processLayers :: [(LayerRole, Tokens)] -> LaTeX ()
processLayers :: [(LayerRole, [Token])] -> LaTeX ()
processLayers [(LayerRole, [Token])]
lt = [(LayerRole, [Token])]
-> ((LayerRole, [Token]) -> RWST Env [Output] State m ())
-> RWST Env [Output] State m ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ [(LayerRole, [Token])]
lt (((LayerRole, [Token]) -> RWST Env [Output] State m ())
-> RWST Env [Output] State m ())
-> ((LayerRole, [Token]) -> RWST Env [Output] State m ())
-> RWST Env [Output] State m ()
forall a b. (a -> b) -> a -> b
$ \ (LayerRole
layerRole,[Token]
toks) -> do
case LayerRole
layerRole of
LayerRole
L.Markup -> [Token] -> LaTeX ()
processMarkup [Token]
toks
LayerRole
L.Comment -> [Token] -> LaTeX ()
processComment [Token]
toks
LayerRole
L.Code -> [Token] -> LaTeX ()
processCode [Token]
toks
processMarkup :: Tokens -> LaTeX ()
processMarkup :: [Token] -> LaTeX ()
processMarkup [Token]
ts = [Token]
-> (Token -> RWST Env [Output] State m ())
-> RWST Env [Output] State m ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ [Token]
ts ((Token -> RWST Env [Output] State m ())
-> RWST Env [Output] State m ())
-> (Token -> RWST Env [Output] State m ())
-> RWST Env [Output] State m ()
forall a b. (a -> b) -> a -> b
$ \ Token
t' -> do
Token -> LaTeX ()
moveColumnForToken Token
t'
Output -> LaTeX ()
output (Text -> Output
Text (Token -> Text
text Token
t'))
processComment :: Tokens -> LaTeX ()
[Token]
ts = [Token]
-> (Token -> RWST Env [Output] State m ())
-> RWST Env [Output] State m ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ [Token]
ts ((Token -> RWST Env [Output] State m ())
-> RWST Env [Output] State m ())
-> (Token -> RWST Env [Output] State m ())
-> RWST Env [Output] State m ()
forall a b. (a -> b) -> a -> b
$ \ Token
t' -> do
Bool
-> RWST Env [Output] State m () -> RWST Env [Output] State m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (Text
"%" Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Int -> Text -> Text
T.take Int
1 (Text -> Text
T.stripStart (Token -> Text
text Token
t'))) (RWST Env [Output] State m () -> RWST Env [Output] State m ())
-> RWST Env [Output] State m () -> RWST Env [Output] State m ()
forall a b. (a -> b) -> a -> b
$ do
Token -> LaTeX ()
moveColumnForToken Token
t'
Output -> LaTeX ()
output (Text -> Output
Text (Token -> Text
text Token
t'))
processCode :: Tokens -> LaTeX ()
processCode :: [Token] -> LaTeX ()
processCode [Token]
toks' = do
Output -> LaTeX ()
output (Output -> LaTeX ()) -> Output -> LaTeX ()
forall a b. (a -> b) -> a -> b
$ Text -> Output
Text Text
nl
RWST Env [Output] State m ()
LaTeX ()
enterCode
(Token -> RWST Env [Output] State m ())
-> [Token] -> RWST Env [Output] State m ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ Token -> RWST Env [Output] State m ()
forall (m :: * -> *).
MonadLogLaTeX m =>
Token -> RWST Env [Output] State m ()
go [Token]
toks'
Int -> RWST Env [Output] State m ()
forall (m :: * -> *) a.
(Eq a, Num a, MonadLogLaTeX m) =>
a -> RWST Env [Output] State m ()
ptOpenWhenColumnZero (Int -> RWST Env [Output] State m ())
-> RWST Env [Output] State m Int -> RWST Env [Output] State m ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< (State -> Int) -> RWST Env [Output] State m Int
forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
gets State -> Int
column
Output -> LaTeX ()
output (Output -> LaTeX ()) -> Output -> LaTeX ()
forall a b. (a -> b) -> a -> b
$ Text -> Output
Text (Text -> Output) -> Text -> Output
forall a b. (a -> b) -> a -> b
$ Text
ptClose Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
nl
RWST Env [Output] State m ()
LaTeX ()
leaveCode
where
go :: Token -> RWST Env [Output] State m ()
go tok' :: Token
tok'@Token{ text :: Token -> Text
text = Text
tok } = do
Int
col <- (State -> Int) -> RWST Env [Output] State m Int
forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
gets State -> Int
column
Token -> LaTeX ()
moveColumnForToken Token
tok'
Debug -> Text -> LaTeX ()
log Debug
Code Text
tok
Bool
-> RWST Env [Output] State m () -> RWST Env [Output] State m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (Text -> Bool
T.null Text
tok) (RWST Env [Output] State m () -> RWST Env [Output] State m ())
-> RWST Env [Output] State m () -> RWST Env [Output] State m ()
forall a b. (a -> b) -> a -> b
$
if (Text -> Bool
isSpaces Text
tok) then do
[Text] -> LaTeX ()
spaces ([Text] -> LaTeX ()) -> [Text] -> LaTeX ()
forall a b. (a -> b) -> a -> b
$ Text -> [Text]
T.group (Text -> [Text]) -> Text -> [Text]
forall a b. (a -> b) -> a -> b
$ Text -> Text
replaceSpaces Text
tok
else do
Int -> RWST Env [Output] State m ()
forall (m :: * -> *) a.
(Eq a, Num a, MonadLogLaTeX m) =>
a -> RWST Env [Output] State m ()
ptOpenWhenColumnZero Int
col
Output -> LaTeX ()
output (Output -> LaTeX ()) -> Output -> LaTeX ()
forall a b. (a -> b) -> a -> b
$ Text -> Output
Text (Text -> Output) -> Text -> Output
forall a b. (a -> b) -> a -> b
$
(String -> Text -> Text) -> Text -> [String] -> Text
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (\String
c Text
t -> Text
cmdPrefix Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
T.pack String
c Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
cmdArg Text
t)
(Text -> Text
escape Text
tok)
([String] -> Text) -> [String] -> Text
forall a b. (a -> b) -> a -> b
$ (OtherAspect -> String) -> [OtherAspect] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map OtherAspect -> String
fromOtherAspect (Set OtherAspect -> [OtherAspect]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList (Set OtherAspect -> [OtherAspect])
-> Set OtherAspect -> [OtherAspect]
forall a b. (a -> b) -> a -> b
$ Aspects -> Set OtherAspect
otherAspects (Aspects -> Set OtherAspect) -> Aspects -> Set OtherAspect
forall a b. (a -> b) -> a -> b
$ Token -> Aspects
info Token
tok') [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++
(Aspect -> [String]) -> [Aspect] -> [String]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap Aspect -> [String]
fromAspect (Maybe Aspect -> [Aspect]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList (Maybe Aspect -> [Aspect]) -> Maybe Aspect -> [Aspect]
forall a b. (a -> b) -> a -> b
$ Aspects -> Maybe Aspect
aspect (Aspects -> Maybe Aspect) -> Aspects -> Maybe Aspect
forall a b. (a -> b) -> a -> b
$ Token -> Aspects
info Token
tok')
ptOpenWhenColumnZero :: a -> RWST Env [Output] State m ()
ptOpenWhenColumnZero a
col =
Bool
-> RWST Env [Output] State m () -> RWST Env [Output] State m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (a
col a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
0) (RWST Env [Output] State m () -> RWST Env [Output] State m ())
-> RWST Env [Output] State m () -> RWST Env [Output] State m ()
forall a b. (a -> b) -> a -> b
$ do
RWST Env [Output] State m ()
LaTeX ()
registerColumnZero
(\Output
o -> Output -> LaTeX ()
output Output
o)(Output -> RWST Env [Output] State m ())
-> (AlignmentColumn -> Output)
-> AlignmentColumn
-> RWST Env [Output] State m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Output
Text (Text -> Output)
-> (AlignmentColumn -> Text) -> AlignmentColumn -> Output
forall b c a. (b -> c) -> (a -> b) -> a -> c
. AlignmentColumn -> Text
ptOpen (AlignmentColumn -> RWST Env [Output] State m ())
-> RWST Env [Output] State m AlignmentColumn
-> RWST Env [Output] State m ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< RWST Env [Output] State m AlignmentColumn
LaTeX AlignmentColumn
columnZero
fromOtherAspect :: OtherAspect -> String
fromOtherAspect :: OtherAspect -> String
fromOtherAspect = OtherAspect -> String
forall a. Show a => a -> String
show
fromAspect :: Aspect -> [String]
fromAspect :: Aspect -> [String]
fromAspect Aspect
a = let s :: [String]
s = [Aspect -> String
forall a. Show a => a -> String
show Aspect
a] in case Aspect
a of
Aspect
Comment -> [String]
s
Aspect
Keyword -> [String]
s
Aspect
Hole -> [String]
s
Aspect
String -> [String]
s
Aspect
Number -> [String]
s
Aspect
Symbol -> [String]
s
Aspect
PrimitiveType -> [String]
s
Aspect
Pragma -> [String]
s
Aspect
Background -> [String]
s
Aspect
Markup -> [String]
s
Name Maybe NameKind
Nothing Bool
isOp -> Aspect -> [String]
fromAspect (Maybe NameKind -> Bool -> Aspect
Name (NameKind -> Maybe NameKind
forall a. a -> Maybe a
Just NameKind
Postulate) Bool
isOp)
Name (Just NameKind
kind) Bool
isOp ->
(\String
c -> if Bool
isOp then [String
"Operator", String
c] else [String
c]) (String -> [String]) -> String -> [String]
forall a b. (a -> b) -> a -> b
$
case NameKind
kind of
NameKind
Bound -> String
sk
NameKind
Generalizable -> String
sk
Constructor Induction
Inductive -> String
"InductiveConstructor"
Constructor Induction
CoInductive -> String
"CoinductiveConstructor"
NameKind
Datatype -> String
sk
NameKind
Field -> String
sk
NameKind
Function -> String
sk
NameKind
Module -> String
sk
NameKind
Postulate -> String
sk
NameKind
Primitive -> String
sk
NameKind
Record -> String
sk
NameKind
Argument -> String
sk
NameKind
Macro -> String
sk
where
sk :: String
sk = NameKind -> String
forall a. Show a => a -> String
show NameKind
kind
escape :: Text -> Text
escape :: Text -> Text
escape (Text -> Maybe (Char, Text)
T.uncons -> Maybe (Char, Text)
Nothing) = Text
T.empty
escape (Text -> Maybe (Char, Text)
T.uncons -> Just (Char
c, Text
s)) = String -> Text
T.pack (Char -> String
replace Char
c) Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
escape Text
s
where
replace :: Char -> String
replace :: Char -> String
replace Char
char = case Char
char of
Char
'_' -> String
"\\AgdaUnderscore{}"
Char
'{' -> String
"\\{"
Char
'}' -> String
"\\}"
Char
'#' -> String
"\\#"
Char
'$' -> String
"\\$"
Char
'&' -> String
"\\&"
Char
'%' -> String
"\\%"
Char
'~' -> String
"\\textasciitilde{}"
Char
'^' -> String
"\\textasciicircum{}"
Char
'\\' -> String
"\\textbackslash{}"
Char
' ' -> String
"\\ "
Char
_ -> [ Char
char ]
#if __GLASGOW_HASKELL__ < 810
escape _ = __IMPOSSIBLE__
#endif
spaces :: [Text] -> LaTeX ()
spaces :: [Text] -> LaTeX ()
spaces [] = () -> RWST Env [Output] State m ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
spaces (s :: Text
s@(Text -> Maybe (Char, Text)
T.uncons -> Just (Char
'\n', Text
_)) : [Text]
ss) = do
Int
col <- (State -> Int) -> RWST Env [Output] State m Int
forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
gets State -> Int
column
Bool
-> RWST Env [Output] State m () -> RWST Env [Output] State m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Int
col Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0) (RWST Env [Output] State m () -> RWST Env [Output] State m ())
-> RWST Env [Output] State m () -> RWST Env [Output] State m ()
forall a b. (a -> b) -> a -> b
$
(\Output
o -> Output -> LaTeX ()
output Output
o) (Output -> RWST Env [Output] State m ())
-> (AlignmentColumn -> Output)
-> AlignmentColumn
-> RWST Env [Output] State m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Output
Text (Text -> Output)
-> (AlignmentColumn -> Text) -> AlignmentColumn -> Output
forall b c a. (b -> c) -> (a -> b) -> a -> c
. AlignmentColumn -> Text
ptOpen (AlignmentColumn -> RWST Env [Output] State m ())
-> RWST Env [Output] State m AlignmentColumn
-> RWST Env [Output] State m ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< RWST Env [Output] State m AlignmentColumn
LaTeX AlignmentColumn
columnZero
Output -> LaTeX ()
output (Output -> LaTeX ()) -> Output -> LaTeX ()
forall a b. (a -> b) -> a -> b
$ Text -> Output
Text (Text -> Output) -> Text -> Output
forall a b. (a -> b) -> a -> b
$ Text
ptClose Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
ptNL Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<>
Int -> Text -> Text
T.replicate (TextWidthEstimator
T.length Text
s Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) Text
ptEmptyLine
RWST Env [Output] State m ()
LaTeX ()
resetColumn
[Text] -> LaTeX ()
spaces [Text]
ss
spaces (Text
_ : ss :: [Text]
ss@(Text
_ : [Text]
_)) = [Text] -> LaTeX ()
spaces [Text]
ss
spaces [ Text
s ] = do
Int
col <- (State -> Int) -> RWST Env [Output] State m Int
forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
gets State -> Int
column
let len :: Int
len = TextWidthEstimator
T.length Text
s
kind :: Kind
kind = if Int
col Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
0 Bool -> Bool -> Bool
&& Int
len Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
1
then Kind
Indentation
else Kind
Alignment
Int -> LaTeX ()
moveColumn Int
len
AlignmentColumn
column <- Kind -> LaTeX AlignmentColumn
registerColumn Kind
kind
if Int
col Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
0
then Debug -> Text -> LaTeX ()
log Debug
Spaces Text
"col /= 0"
else do
[AlignmentColumn]
columns <- (State -> [AlignmentColumn])
-> RWST Env [Output] State m [AlignmentColumn]
forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
gets State -> [AlignmentColumn]
columnsPrev
Int
codeBlock <- (State -> Int) -> RWST Env [Output] State m Int
forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
gets State -> Int
codeBlock
Debug -> Text -> LaTeX ()
log Debug
Spaces (Text -> LaTeX ()) -> Text -> LaTeX ()
forall a b. (a -> b) -> a -> b
$
Text
"col == 0: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
T.pack ((Int, [AlignmentColumn]) -> String
forall a. Show a => a -> String
show (Int
len, [AlignmentColumn]
columns))
case (AlignmentColumn -> Bool) -> [AlignmentColumn] -> [AlignmentColumn]
forall a. (a -> Bool) -> [a] -> [a]
filter ((Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
len) (Int -> Bool)
-> (AlignmentColumn -> Int) -> AlignmentColumn -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. AlignmentColumn -> Int
columnColumn) [AlignmentColumn]
columns of
AlignmentColumn
c : [AlignmentColumn]
_ | AlignmentColumn -> Int
columnColumn AlignmentColumn
c Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
len, Maybe Int -> Bool
forall a. Maybe a -> Bool
isJust (AlignmentColumn -> Maybe Int
columnKind AlignmentColumn
c) -> do
AlignmentColumn -> LaTeX ()
useColumn AlignmentColumn
c
Output -> LaTeX ()
output (Output -> LaTeX ()) -> Output -> LaTeX ()
forall a b. (a -> b) -> a -> b
$ Text -> Output
Text (Text -> Output) -> Text -> Output
forall a b. (a -> b) -> a -> b
$ Text
ptOpenBeginningOfLine
Output -> LaTeX ()
output (Output -> LaTeX ()) -> Output -> LaTeX ()
forall a b. (a -> b) -> a -> b
$ Text -> Output
Text (Text -> Output) -> Text -> Output
forall a b. (a -> b) -> a -> b
$ AlignmentColumn -> Text
ptClose' AlignmentColumn
c
AlignmentColumn
c : [AlignmentColumn]
_ | AlignmentColumn -> Int
columnColumn AlignmentColumn
c Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
len -> do
AlignmentColumn -> LaTeX ()
useColumn AlignmentColumn
c
Output -> LaTeX ()
output (Output -> LaTeX ()) -> Output -> LaTeX ()
forall a b. (a -> b) -> a -> b
$ Text -> Output
Text (Text -> Output) -> Text -> Output
forall a b. (a -> b) -> a -> b
$ AlignmentColumn -> Int -> Text
ptOpenIndent AlignmentColumn
c (Int
codeBlock Int -> Int -> Int
forall a. Num a => a -> a -> a
- AlignmentColumn -> Int
columnCodeBlock AlignmentColumn
c)
[AlignmentColumn]
_ -> () -> RWST Env [Output] State m ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
Output -> LaTeX ()
output (Output -> LaTeX ()) -> Output -> LaTeX ()
forall a b. (a -> b) -> a -> b
$ AlignmentColumn -> Output
MaybeColumn AlignmentColumn
column
stringLiteral :: Token -> Tokens
stringLiteral :: Token -> [Token]
stringLiteral Token
t | Aspects -> Maybe Aspect
aspect (Token -> Aspects
info Token
t) Maybe Aspect -> Maybe Aspect -> Bool
forall a. Eq a => a -> a -> Bool
== Aspect -> Maybe Aspect
forall a. a -> Maybe a
Just Aspect
String =
(Text -> Token) -> [Text] -> [Token]
forall a b. (a -> b) -> [a] -> [b]
map (\ Text
x -> Token
t { text :: Text
text = Text
x })
([Text] -> [Token]) -> [Text] -> [Token]
forall a b. (a -> b) -> a -> b
$ (Text -> [Text]) -> [Text] -> [Text]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap Text -> [Text]
leadingSpaces
([Text] -> [Text]) -> [Text] -> [Text]
forall a b. (a -> b) -> a -> b
$ Text -> [Text] -> [Text]
forall a. a -> [a] -> [a]
List.intersperse Text
"\n"
([Text] -> [Text]) -> [Text] -> [Text]
forall a b. (a -> b) -> a -> b
$ Text -> [Text]
T.lines (Token -> Text
text Token
t)
where
leadingSpaces :: Text -> [Text]
leadingSpaces :: Text -> [Text]
leadingSpaces Text
tok = [Text
pre, Text
suf]
where (Text
pre , Text
suf) = (Char -> Bool) -> Text -> (Text, Text)
T.span Char -> Bool
isSpaceNotNewline Text
tok
stringLiteral Token
t = [Token
t]
multiLineComment :: Token -> Tokens
Token{ text :: Token -> Text
text = Text
s, info :: Token -> Aspects
info = Aspects
i } | Aspects -> Maybe Aspect
aspect Aspects
i Maybe Aspect -> Maybe Aspect -> Bool
forall a. Eq a => a -> a -> Bool
== Aspect -> Maybe Aspect
forall a. a -> Maybe a
Just Aspect
Comment =
(Text -> Token) -> [Text] -> [Token]
forall a b. (a -> b) -> [a] -> [b]
map (Text -> Aspects -> Token
`Token` Aspects
i)
([Text] -> [Token]) -> [Text] -> [Token]
forall a b. (a -> b) -> a -> b
$ Text -> [Text] -> [Text]
forall a. a -> [a] -> [a]
List.intersperse Text
"\n"
([Text] -> [Text]) -> [Text] -> [Text]
forall a b. (a -> b) -> a -> b
$ Text -> [Text]
T.lines Text
s
multiLineComment Token
t = [Token
t]
latexDataDir :: FilePath
latexDataDir :: String
latexDataDir = String
"latex"
defaultStyFile :: String
defaultStyFile :: String
defaultStyFile = String
"agda.sty"
data LaTeXOptions = LaTeXOptions
{ LaTeXOptions -> String
latexOptOutDir :: FilePath
, LaTeXOptions -> Maybe AbsolutePath
latexOptSourceFileName :: Maybe AbsolutePath
, LaTeXOptions -> Bool
latexOptCountClusters :: Bool
}
getTextWidthEstimator :: Bool -> TextWidthEstimator
getTextWidthEstimator :: Bool -> TextWidthEstimator
getTextWidthEstimator Bool
_countClusters =
#ifdef COUNT_CLUSTERS
if _countClusters
then length . (ICU.breaks (ICU.breakCharacter ICU.Root))
else T.length
#else
TextWidthEstimator
T.length
#endif
prepareCommonAssets :: (MonadLogLaTeX m, MonadIO m) => FilePath -> m ()
prepareCommonAssets :: String -> m ()
prepareCommonAssets String
dir = do
IO () -> m ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> m ()) -> IO () -> m ()
forall a b. (a -> b) -> a -> b
$ Bool -> String -> IO ()
createDirectoryIfMissing Bool
True String
dir
(ExitCode
code, String
_, String
_) <-
IO (ExitCode, String, String) -> m (ExitCode, String, String)
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (ExitCode, String, String) -> m (ExitCode, String, String))
-> IO (ExitCode, String, String) -> m (ExitCode, String, String)
forall a b. (a -> b) -> a -> b
$
String -> [String] -> String -> IO (ExitCode, String, String)
readProcessWithExitCode
String
"kpsewhich"
[String
"--path=" String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
dir, String
defaultStyFile]
String
""
Bool -> m () -> m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (ExitCode
code ExitCode -> ExitCode -> Bool
forall a. Eq a => a -> a -> Bool
/= ExitCode
ExitSuccess) (m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$ do
LogMessage -> m ()
forall (m :: * -> *). MonadLogLaTeX m => LogMessage -> m ()
logLaTeX (LogMessage -> m ()) -> LogMessage -> m ()
forall a b. (a -> b) -> a -> b
$ Debug -> Text -> [Text] -> LogMessage
LogMessage Debug
FileSystem
(String -> Text
T.pack (String -> Text) -> String -> Text
forall a b. (a -> b) -> a -> b
$ [String] -> String
unwords [String
defaultStyFile, String
"was not found. Copying a default version of", String
defaultStyFile, String
"into", String
dir])
[]
IO () -> m ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> m ()) -> IO () -> m ()
forall a b. (a -> b) -> a -> b
$ do
String
styFile <- String -> IO String
getDataFileName (String -> IO String) -> String -> IO String
forall a b. (a -> b) -> a -> b
$
String
latexDataDir String -> ShowS
</> String
defaultStyFile
String -> String -> IO ()
copyFile String
styFile (String
dir String -> ShowS
</> String
defaultStyFile)
generateLaTeXIO :: (MonadLogLaTeX m, MonadIO m) => LaTeXOptions -> Interface -> m ()
generateLaTeXIO :: LaTeXOptions -> Interface -> m ()
generateLaTeXIO LaTeXOptions
opts Interface
i = do
let textWidthEstimator :: TextWidthEstimator
textWidthEstimator = Bool -> TextWidthEstimator
getTextWidthEstimator (LaTeXOptions -> Bool
latexOptCountClusters LaTeXOptions
opts)
let baseDir :: String
baseDir = LaTeXOptions -> String
latexOptOutDir LaTeXOptions
opts
let outPath :: String
outPath = String
baseDir String -> ShowS
</> (TopLevelModuleName -> String
latexOutRelativeFilePath (TopLevelModuleName -> String) -> TopLevelModuleName -> String
forall a b. (a -> b) -> a -> b
$ ModuleName -> TopLevelModuleName
toTopLevelModuleName (ModuleName -> TopLevelModuleName)
-> ModuleName -> TopLevelModuleName
forall a b. (a -> b) -> a -> b
$ Interface -> ModuleName
iModuleName Interface
i)
ByteString
latex <- Text -> ByteString
E.encodeUtf8 (Text -> ByteString) -> m Text -> m ByteString
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Env -> Maybe AbsolutePath -> Text -> HighlightingInfo -> m Text
forall (m :: * -> *).
MonadLogLaTeX m =>
Env -> Maybe AbsolutePath -> Text -> HighlightingInfo -> m Text
toLaTeX
(TextWidthEstimator -> Env
emptyEnv TextWidthEstimator
textWidthEstimator)
(LaTeXOptions -> Maybe AbsolutePath
latexOptSourceFileName LaTeXOptions
opts)
(Interface -> Text
iSource Interface
i)
(Interface -> HighlightingInfo
iHighlighting Interface
i)
IO () -> m ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> m ()) -> IO () -> m ()
forall a b. (a -> b) -> a -> b
$ do
Bool -> String -> IO ()
createDirectoryIfMissing Bool
True (ShowS
takeDirectory String
outPath)
String -> ByteString -> IO ()
BS.writeFile String
outPath ByteString
latex
latexOutRelativeFilePath :: TopLevelModuleName -> FilePath
latexOutRelativeFilePath :: TopLevelModuleName -> String
latexOutRelativeFilePath TopLevelModuleName
m = String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
List.intercalate [Char
pathSeparator] (NonEmpty String -> [String]
forall a. NonEmpty a -> [a]
List1.toList (NonEmpty String -> [String]) -> NonEmpty String -> [String]
forall a b. (a -> b) -> a -> b
$ TopLevelModuleName -> NonEmpty String
moduleNameParts TopLevelModuleName
m) String -> ShowS
<.> String
"tex"
groupByFst :: forall a b. Eq a => [(a,b)] -> [(a,[b])]
groupByFst :: [(a, b)] -> [(a, [b])]
groupByFst =
([(a, b)] -> (a, [b])) -> [[(a, b)]] -> [(a, [b])]
forall a b. (a -> b) -> [a] -> [b]
map (\[(a, b)]
xs -> case [(a, b)]
xs of
[] -> (a, [b])
forall a. HasCallStack => a
__IMPOSSIBLE__
(a
tag, b
_): [(a, b)]
_ -> (a
tag, ((a, b) -> b) -> [(a, b)] -> [b]
forall a b. (a -> b) -> [a] -> [b]
map (a, b) -> b
forall a b. (a, b) -> b
snd [(a, b)]
xs))
([[(a, b)]] -> [(a, [b])])
-> ([(a, b)] -> [[(a, b)]]) -> [(a, b)] -> [(a, [b])]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((a, b) -> (a, b) -> Bool) -> [(a, b)] -> [[(a, b)]]
forall a. (a -> a -> Bool) -> [a] -> [[a]]
List.groupBy (a -> a -> Bool
forall a. Eq a => a -> a -> Bool
(==) (a -> a -> Bool) -> ((a, b) -> a) -> (a, b) -> (a, b) -> Bool
forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
`on` (a, b) -> a
forall a b. (a, b) -> a
fst)
toLaTeX
:: MonadLogLaTeX m
=> Env
-> Maybe AbsolutePath
-> L.Text
-> HighlightingInfo
-> m L.Text
toLaTeX :: Env -> Maybe AbsolutePath -> Text -> HighlightingInfo -> m Text
toLaTeX Env
env Maybe AbsolutePath
path Text
source HighlightingInfo
hi =
Env -> [(LayerRole, [Token])] -> m Text
forall (m :: * -> *).
MonadLogLaTeX m =>
Env -> [(LayerRole, [Token])] -> m Text
processTokens Env
env
([(LayerRole, [Token])] -> m Text)
-> (String -> [(LayerRole, [Token])]) -> String -> m Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((LayerRole, [(Maybe Aspects, Char)]) -> (LayerRole, [Token]))
-> [(LayerRole, [(Maybe Aspects, Char)])] -> [(LayerRole, [Token])]
forall a b. (a -> b) -> [a] -> [b]
map
( ( \(LayerRole
role, [Token]
tokens) ->
(LayerRole
role,) ([Token] -> (LayerRole, [Token]))
-> [Token] -> (LayerRole, [Token])
forall a b. (a -> b) -> a -> b
$
( Bool -> ([Token] -> [Token]) -> [Token] -> [Token]
forall a. Bool -> (a -> a) -> a -> a
applyWhen (LayerRole -> Bool
L.isCode LayerRole
role) (([Token] -> [Token]) -> [Token] -> [Token])
-> ([Token] -> [Token]) -> [Token] -> [Token]
forall a b. (a -> b) -> a -> b
$
([Token] -> [Token]) -> [Token] -> [Token]
forall a. ([a] -> [a]) -> [a] -> [a]
whenMoreThanOne
( (Token -> Token) -> [Token] -> [Token]
forall a. (a -> a) -> [a] -> [a]
updateLast
((Token -> Token) -> [Token] -> [Token])
-> (Token -> Token) -> [Token] -> [Token]
forall a b. (a -> b) -> a -> b
$ (Text -> Text) -> Token -> Token
withTokenText
((Text -> Text) -> Token -> Token)
-> (Text -> Text) -> Token -> Token
forall a b. (a -> b) -> a -> b
$ \Text
suf ->
Text -> (Text -> Text) -> Maybe Text -> Text
forall b a. b -> (a -> b) -> Maybe a -> b
maybe
Text
suf
((Char -> Bool) -> Text -> Text
T.dropWhileEnd Char -> Bool
isSpaceNotNewline)
(Text -> Text -> Maybe Text
T.stripSuffix Text
"\n" Text
suf)
)
([Token] -> [Token]) -> ([Token] -> [Token]) -> [Token] -> [Token]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Token -> Token) -> [Token] -> [Token]
forall a. (a -> a) -> [a] -> [a]
updateLast ((Text -> Text) -> Token -> Token
withTokenText ((Text -> Text) -> Token -> Token)
-> (Text -> Text) -> Token -> Token
forall a b. (a -> b) -> a -> b
$ (Char -> Bool) -> Text -> Text
T.dropWhileEnd Char -> Bool
isSpaceNotNewline)
([Token] -> [Token]) -> ([Token] -> [Token]) -> [Token] -> [Token]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Token -> Token) -> [Token] -> [Token]
forall a. (a -> a) -> [a] -> [a]
updateHead
( (Text -> Text) -> Token -> Token
withTokenText ((Text -> Text) -> Token -> Token)
-> (Text -> Text) -> Token -> Token
forall a b. (a -> b) -> a -> b
$
\Text
pre ->
Text -> Maybe Text -> Text
forall a. a -> Maybe a -> a
fromMaybe Text
pre (Maybe Text -> Text) -> Maybe Text -> Text
forall a b. (a -> b) -> a -> b
$ Text -> Text -> Maybe Text
T.stripPrefix Text
"\n" (Text -> Maybe Text) -> Text -> Maybe Text
forall a b. (a -> b) -> a -> b
$
(Char -> Bool) -> Text -> Text
T.dropWhile
Char -> Bool
isSpaceNotNewline
Text
pre
)
)
[Token]
tokens
) ((LayerRole, [Token]) -> (LayerRole, [Token]))
-> ((LayerRole, [(Maybe Aspects, Char)]) -> (LayerRole, [Token]))
-> (LayerRole, [(Maybe Aspects, Char)])
-> (LayerRole, [Token])
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ( ([(Maybe Aspects, Char)] -> [Token])
-> (LayerRole, [(Maybe Aspects, Char)]) -> (LayerRole, [Token])
forall (p :: * -> * -> *) b c a.
Bifunctor p =>
(b -> c) -> p a b -> p a c
second
(
(Token -> [Token]) -> [Token] -> [Token]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap Token -> [Token]
stringLiteral
([Token] -> [Token])
-> ([(Maybe Aspects, Char)] -> [Token])
-> [(Maybe Aspects, Char)]
-> [Token]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Token -> [Token]) -> [Token] -> [Token]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap Token -> [Token]
multiLineComment
([Token] -> [Token])
-> ([(Maybe Aspects, Char)] -> [Token])
-> [(Maybe Aspects, Char)]
-> [Token]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((Maybe Aspects, String) -> Token)
-> [(Maybe Aspects, String)] -> [Token]
forall a b. (a -> b) -> [a] -> [b]
map ( \(Maybe Aspects
mi, String
cs) ->
Token :: Text -> Aspects -> Token
Token {text :: Text
text = String -> Text
T.pack String
cs, info :: Aspects
info = Aspects -> Maybe Aspects -> Aspects
forall a. a -> Maybe a -> a
fromMaybe Aspects
forall a. Monoid a => a
mempty Maybe Aspects
mi}
)
([(Maybe Aspects, String)] -> [Token])
-> ([(Maybe Aspects, Char)] -> [(Maybe Aspects, String)])
-> [(Maybe Aspects, Char)]
-> [Token]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [(Maybe Aspects, Char)] -> [(Maybe Aspects, String)]
forall a b. Eq a => [(a, b)] -> [(a, [b])]
groupByFst
)
)
)
([(LayerRole, [(Maybe Aspects, Char)])] -> [(LayerRole, [Token])])
-> (String -> [(LayerRole, [(Maybe Aspects, Char)])])
-> String
-> [(LayerRole, [Token])]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [(LayerRole, (Maybe Aspects, Char))]
-> [(LayerRole, [(Maybe Aspects, Char)])]
forall a b. Eq a => [(a, b)] -> [(a, [b])]
groupByFst
([(LayerRole, (Maybe Aspects, Char))]
-> [(LayerRole, [(Maybe Aspects, Char)])])
-> (String -> [(LayerRole, (Maybe Aspects, Char))])
-> String
-> [(LayerRole, [(Maybe Aspects, Char)])]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int -> (LayerRole, Char) -> (LayerRole, (Maybe Aspects, Char)))
-> [Int]
-> [(LayerRole, Char)]
-> [(LayerRole, (Maybe Aspects, Char))]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith (\Int
pos (LayerRole
role, Char
char) -> (LayerRole
role, (Int -> IntMap Aspects -> Maybe Aspects
forall a. Int -> IntMap a -> Maybe a
IntMap.lookup Int
pos IntMap Aspects
infoMap, Char
char)))
[Int
1..] ([(LayerRole, Char)] -> [(LayerRole, (Maybe Aspects, Char))])
-> (String -> [(LayerRole, Char)])
-> String
-> [(LayerRole, (Maybe Aspects, Char))]
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
Layers -> [(LayerRole, Char)]
atomizeLayers (Layers -> [(LayerRole, Char)])
-> (String -> Layers) -> String -> [(LayerRole, Char)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Position -> String -> Layers
literateTeX (Maybe AbsolutePath -> Position
startPos Maybe AbsolutePath
path)
(String -> m Text) -> String -> m Text
forall a b. (a -> b) -> a -> b
$ Text -> String
L.unpack Text
source
where
infoMap :: IntMap Aspects
infoMap = HighlightingInfo -> IntMap Aspects
forall a m. IsBasicRangeMap a m => m -> IntMap a
toMap HighlightingInfo
hi
whenMoreThanOne :: ([a] -> [a]) -> [a] -> [a]
whenMoreThanOne :: ([a] -> [a]) -> [a] -> [a]
whenMoreThanOne [a] -> [a]
f xs :: [a]
xs@(a
_:a
_:[a]
_) = [a] -> [a]
f [a]
xs
whenMoreThanOne [a] -> [a]
_ [a]
xs = [a]
xs
processTokens
:: MonadLogLaTeX m
=> Env
-> [(LayerRole, Tokens)]
-> m L.Text
processTokens :: Env -> [(LayerRole, [Token])] -> m Text
processTokens Env
env [(LayerRole, [Token])]
ts = do
((), State
s, [Output]
os) <- LaTeX () -> Env -> State -> m ((), State, [Output])
forall (m :: * -> *) a.
MonadLogLaTeX m =>
LaTeX a -> Env -> State -> m (a, State, [Output])
runLaTeX ([(LayerRole, [Token])] -> LaTeX ()
processLayers [(LayerRole, [Token])]
ts) Env
env State
emptyState
Text -> m Text
forall (m :: * -> *) a. Monad m => a -> m a
return (Text -> m Text) -> Text -> m Text
forall a b. (a -> b) -> a -> b
$ [Text] -> Text
L.fromChunks ([Text] -> Text) -> [Text] -> Text
forall a b. (a -> b) -> a -> b
$ (Output -> Text) -> [Output] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map (State -> Output -> Text
render State
s) [Output]
os
where
render :: State -> Output -> Text
render State
_ (Text Text
s) = Text
s
render State
s (MaybeColumn AlignmentColumn
c)
| Just Int
i <- AlignmentColumn -> Maybe Int
columnKind AlignmentColumn
c,
Bool -> Bool
not (Int
i Int -> HashSet Int -> Bool
forall a. (Eq a, Hashable a) => a -> HashSet a -> Bool
`Set.member` State -> HashSet Int
usedColumns State
s) = Text
agdaSpace
| Bool
otherwise = Text
nl Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> AlignmentColumn -> Text
ptOpen AlignmentColumn
c