packages feed

zwirn-0.2.3.1: app/zwirnmill/Docs/Util.hs

module Docs.Util where

import Data.Bifunctor (second)
import Data.List (elemIndex, mapAccumL, (!?))
import Data.Maybe (fromMaybe)
import qualified Data.Text as T
import UI.Core (Doc (..), DocBlock (..), DocFocus (..), DocInline (..))

getCodeAt :: Doc -> Int -> Maybe T.Text
getCodeAt (Doc []) _ = Nothing
getCodeAt (Doc ((CodeBlock t) : _)) 0 = Just t
getCodeAt (Doc ((CodeBlock _) : ds)) n = getCodeAt (Doc ds) (n - 1)
getCodeAt (Doc (_ : ds)) n = getCodeAt (Doc ds) n

getLinkAt :: Doc -> Int -> Maybe T.Text
getLinkAt (Doc []) _ = Nothing
getLinkAt (Doc ((Paragraph ps) : ds)) n = case getLinkAtPar ps n of
  Left i -> getLinkAt (Doc ds) i
  Right x -> Just x
getLinkAt (Doc ((CodeBlock _) : ds)) n = getLinkAt (Doc ds) n

getLinkAtPar :: [DocInline] -> Int -> Either Int T.Text
getLinkAtPar [] i = Left i
getLinkAtPar ((Link _ d) : _) 0 = Right d
getLinkAtPar ((Link _ _) : ds) n = getLinkAtPar ds (n - 1)
getLinkAtPar (_ : ds) n = getLinkAtPar ds n

currentLink :: DocFocus -> Int -> Bool
currentLink (LinkFocus t) k = t == k
currentLink _ _ = False

currentCodeBlock :: DocFocus -> Int -> Bool
currentCodeBlock (CodeFocus i) j = i == j
currentCodeBlock _ _ = False

docFoci :: Doc -> [DocFocus]
docFoci (Doc ds) = concat $ snd $ mapAccumL getFociBlock (0, 0) ds

getFociBlock :: (Int, Int) -> DocBlock -> ((Int, Int), [DocFocus])
getFociBlock (i, j) (CodeBlock _) = ((i + 1, j), [CodeFocus i])
getFociBlock (i, j) (Paragraph ls) = second concat $ mapAccumL getFociInline (i, j) ls

getFociInline :: (Int, Int) -> DocInline -> ((Int, Int), [DocFocus])
getFociInline (i, j) (Link _ _) = ((i, j + 1), [LinkFocus j])
getFociInline (i, j) _ = ((i, j), [])

moveNext :: Doc -> DocFocus -> DocFocus
moveNext d NoFocus = fromMaybe NoFocus $ docFoci d !? 0
moveNext d cur = next
  where
    fs = docFoci d
    i = fromMaybe 0 $ elemIndex cur fs
    next = case fs !? (i + 1) of
      Just n -> n
      Nothing -> fromMaybe cur (fs !? 0)