From e802f66599ff8edef9bd0e2da90b5596dd49e15a Mon Sep 17 00:00:00 2001 From: Mats Rauhala Date: Sat, 2 Jan 2021 08:27:18 +0200 Subject: [PATCH] Refactor the formatter to its own module --- buuka.cabal | 1 + src/Operations/Format.hs | 48 ++++++++++++++++++++++++++++++++++++++++ src/Operations/List.hs | 23 +++---------------- 3 files changed, 52 insertions(+), 20 deletions(-) create mode 100644 src/Operations/Format.hs diff --git a/buuka.cabal b/buuka.cabal index 4e63cbe..1e676b2 100644 --- a/buuka.cabal +++ b/buuka.cabal @@ -38,6 +38,7 @@ library , Control.Monad.Buuka , Operations.Insert , Operations.List + , Operations.Format , Operations , Data.Environment , Data.Buuka diff --git a/src/Operations/Format.hs b/src/Operations/Format.hs new file mode 100644 index 0000000..b155c77 --- /dev/null +++ b/src/Operations/Format.hs @@ -0,0 +1,48 @@ +{-# LANGUAGE LambdaCase #-} +{-| +Module : Operations.Format +Description : Format the list of bookmarks +Copyright : (c) Mats Rauhala, 2020 +License : BSD-3-Clause +Maintainer : mats.rauhala@iki.fi +Stability : experimental +Portability : POSIX + +Format the list of bookmarks. It uses the "hashids" module to create a unique +hash for each entry. Some extra (user) security is given by using the hash of +the full entries as the initial context for hashids. If the state has been +modified between operations, the ids change. +-} +module Operations.Format where + +import Data.Buuka + (Buuka, BuukaEntry(..), URL(..)) +import qualified Data.Buuka as B + +import Data.Semigroup + (Max(..)) + +import Web.Hashids + +import Control.Lens +import Data.Text.Strict.Lens + (unpacked, utf8) + + +-- | Format the entries +formatEntries + :: Buuka -- ^ The full set of entries, for the context + -> [BuukaEntry] -- ^ The list of entries to be formatted + -> [String] +formatEntries buuka xs = + let formatted = zipWith formatEntry [1..] xs + indexWidth = getMax . foldMap (Max . length . fst) $ formatted + in fmap (\(idx,x) -> idx <> replicate (indexWidth - length idx) ' ' <> ". " <> x) formatted + where + ctx = mkContext buuka + mkContext :: Buuka -> HashidsContext + mkContext = hashidsSimple . B.fingerprint + formatEntry :: Int -> BuukaEntry -> (String, String) + formatEntry n = \case + BuukaEntry{title=Just t} -> (encode ctx n ^. utf8 . unpacked, t) + BuukaEntry{url=URL u} -> (encode ctx n ^. utf8 . unpacked, u) diff --git a/src/Operations/List.hs b/src/Operations/List.hs index a51ce50..d786655 100644 --- a/src/Operations/List.hs +++ b/src/Operations/List.hs @@ -8,33 +8,16 @@ import Control.Monad.Reader import Data.Foldable (traverse_) -import Data.Semigroup - (Max(..)) - import Data.Buuka - (Buuka, BuukaEntry(..), URL(..)) + (Buuka) import qualified Data.Buuka as B -import Web.Hashids +import Operations.Format -import Control.Lens -import Data.Text.Strict.Lens - (unpacked, utf8) list :: BuukaM () list = buukaQ (asks go) >>= traverse_ (liftIO . putStrLn) where go :: Buuka -> [String] - go b = - let ctx = hashidsSimple (B.fingerprint b) - in format ctx (B.elements b) - format :: HashidsContext -> [BuukaEntry] -> [String] - format ctx xs = - let formatted = zipWith (formatEntry ctx) [1..] xs - indexWidth = getMax . foldMap (Max . length . fst) $ formatted - in fmap (\(idx,x) -> idx <> replicate (indexWidth - length idx) ' ' <> ". " <> x) formatted - formatEntry :: HashidsContext -> Int -> BuukaEntry -> (String, String) - formatEntry ctx n = \case - BuukaEntry{title=Just t} -> (encode ctx n ^. utf8 . unpacked, t) - BuukaEntry{url=URL u} -> (encode ctx n ^. utf8 . unpacked, u) + go b = formatEntries b (B.elements b)