emanote-1.0.2.0: src/Emanote/Model/Calendar.hs
{- | A primitive module to eventually pave way towards first-class "calendar"
(daily notes, etc.) support in Emanote; either built-in or as plugin.
-}
module Emanote.Model.Calendar where
import Data.Time.Calendar (Day, fromGregorianValid)
import Emanote.Model.Note qualified as N
import Emanote.Model.Title (Title)
import Emanote.Model.Type (Model, modelLookupTitle)
import Emanote.Route (LMLRoute)
import Emanote.Route qualified as R
import Relude
import Text.Megaparsec qualified as M
import Text.Megaparsec.Char qualified as M
-- HACK: This is so that calendar backlinks are sorted properly.
backlinkSortKey :: Model -> LMLRoute -> Down Title
backlinkSortKey model =
Down . flip modelLookupTitle model
-- HACK: Until we have a proper search support. This sorts query results for
-- timeline
noteSortKey :: N.Note -> (Down (Maybe Text), LMLRoute)
noteSortKey note =
(Down $ N.lookupMeta @Text (one "date") note, N._noteRoute note)
isDailyNote :: LMLRoute -> Bool
isDailyNote =
isJust . parseRouteDay
parseRouteDay :: LMLRoute -> Maybe Day
parseRouteDay =
M.parseMaybe parse . R.withLmlRoute R.routeBaseName
where
parse :: M.Parsec Void Text Day
parse = do
let asInt = maybe (fail "Not an int") pure . readMaybe
-- Year
year <- asInt =<< replicateM 4 M.digitChar
void $ M.string "-"
-- Month
month <- asInt =<< replicateM 2 M.digitChar
void $ M.string "-"
-- Day
day <- asInt =<< replicateM 2 M.digitChar
-- Optional suffix (ignored)
void $
optional $ do
void $ M.oneOf ['-', '_', ' ']
void M.takeRest
maybe (fail "Not a date") pure $
fromGregorianValid year (fromInteger month) (fromInteger day)