packages feed

neuron-0.4.0.0: src/app/Neuron/Zettelkasten/Query/Eval.hs

{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE TupleSections #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE NoImplicitPrelude #-}

module Neuron.Zettelkasten.Query.Eval
  ( evalZettelLinks,
  )
where

import Control.Monad.Except
import Data.Dependent.Sum
import qualified Data.Map.Strict as Map
import Data.Some
import Data.Traversable (for)
import Lucid
import Neuron.Zettelkasten.Connection
import Neuron.Zettelkasten.Query
import Neuron.Zettelkasten.Query.Error
import Neuron.Zettelkasten.Query.Parser (queryFromMarkdownLink)
import Neuron.Zettelkasten.Query.View (renderQueryLink)
import Neuron.Zettelkasten.Zettel
import Relude
import Text.MMark.MarkdownLink

type EvalResult = ([(Connection, Zettel)], Html ())

-- | Evaluate all queries in a zettel
--
-- Return the queries with results as a map from the original markdown link.
evalZettelLinks ::
  MonadError QueryError m =>
  [Zettel] ->
  Zettel ->
  m (Map MarkdownLink EvalResult)
evalZettelLinks zettels Zettel {..} =
  fmap (Map.fromList . catMaybes) $ for (extractLinks zettelContent) $ \ml ->
    fmap (ml,) <$> evalMarkdownLink zettels ml

-- | Fully evaluate the query in a markdown link.
evalMarkdownLink ::
  MonadError QueryError m =>
  [Zettel] ->
  MarkdownLink ->
  m (Maybe EvalResult)
evalMarkdownLink zettels ml =
  liftEither $ runExcept $ do
    mq <- withExcept Left $ queryFromMarkdownLink ml
    case mq of
      Nothing -> pure Nothing
      Just someQ -> Just <$> do
        let qres = withSome someQ $ \q ->
              q :=> Identity (runQuery zettels q)
            conns = getConnections qres
        view <-
          withExcept Right $
            renderQueryLink qres
        pure (conns, view)
  where
    getConnections :: DSum Query Identity -> [(Connection, Zettel)]
    getConnections = \case
      Query_ZettelByID _ mconn :=> Identity mres ->
        maybe [] pure $ (fromMaybe Folgezettel mconn,) <$> mres
      Query_ZettelsByTag _ mconn _mview :=> Identity res ->
        (fromMaybe Folgezettel mconn,) <$> res
      _ ->
        []