packages feed

pandoc-filter-indent-0.3.3.0: src/Util.hs

{-# LANGUAGE AllowAmbiguousTypes   #-}
{-# LANGUAGE OverloadedStrings     #-}
{-# LANGUAGE PartialTypeSignatures #-}
{-# LANGUAGE FlexibleInstances     #-}
{-# LANGUAGE FlexibleContexts      #-}
-- | Shared utilities that may be moved to upstream libraries.
module Util where

import           Data.Function(on)
import           Data.List(groupBy, sortBy)
import           Data.Maybe(fromMaybe)
import qualified Data.Text as T
import           Optics.Core ( Lens, lens )
import           Prelude hiding(getLine)

import           Token(MyTok(..))

-- | Lens with default value.
maybeLens :: a -> Lens (Maybe a) (Maybe a1) a a1
maybeLens dflt = lens (fromMaybe dflt) (\_ a -> Just a)

-- | Sort and group inputs by a given `Ordering`.
grouping    :: Ord k
            => (   a -> k)
            ->    [a]
            ->   [[a]]
grouping key = groupBy ((==)    `on` key)
             . sortBy  (compare `on` key)

-- | Sort and remove duplicates in a list.
--   Duplicates are detected as equals by default `Ord`ering.
nubSorted :: Ord a => [a] -> [a]
nubSorted  = nubSortedBy compare

-- | Given an `Ord`ering, sort and remove duplicates.
nubSortedBy :: (a -> a -> Ordering) -> [a] -> [a]
nubSortedBy comparison = fmap    head
                       . groupBy equality
                       . sortBy  comparison
  where
    equality a b = a `comparison` b == EQ

-- | Safe tail function that returns empty list for empty input.
safeTail []     = []
safeTail (_:ls) = ls

-- | Take text in braces, and return its inner part.
--   Fail if the given text does not start with opening brace,
--   and end in closing brace.
unbrace txt | T.head txt == '(' && T.last txt == ')' && T.length txt > 2 = Just $ T.tail $ T.init txt
unbrace _ = Nothing

brace txt = mconcat ["(", txt, ")"]

-- | Preprocess tokens before formatting
--   in order to detect tokens like functions converted to operator syntax.
--   These are merged into a single token.
preformatTokens []                                                     = []
preformatTokens ((TOperator,"`"):(TVar, "elem"):(TOperator, "`"):rest) = (TOperator, "elem"):preformatTokens rest
preformatTokens (a                                              :rest) =  a                 :preformatTokens rest