packages feed

smh-0.2.1: src/Mappings.hs

{-# OPTIONS_GHC -Wno-unused-do-bind #-}
{-# LANGUAGE ImpredicativeTypes #-}

module Mappings where

import           Common        (Focus (FList, FText), Focuser (..), Mapping,
                                Range, getIndexes, makeFilteredText, mapText,
                                readMaybeRational, showRational, toTextUnsafe)
import           Control.Lens  ((^..))
import           Data.Char     (toLower, toUpper)
import           Data.Function (on)
import           Data.List     (sortBy)
import           Data.Text     (Text)
import qualified Data.Text     as T
import           Text.Read     (readMaybe)

mappingReverse :: Mapping
mappingReverse (FList lst) = FList (reverse lst)
mappingReverse (FText str) = FText (T.reverse str)

mappingLength :: Mapping
mappingLength (FText str) = FText $ T.pack $ show $ T.length str
mappingLength flist       = flist

mappingMap :: Mapping -> Mapping
mappingMap mapping (FList lst) = FList $ map mapping lst
mappingMap mapping (FText str) = FText $ T.concat $ mapText
    (toTextUnsafe . mapping . FText . T.singleton) str

mappingAppend :: Focuser -> Mapping
mappingAppend (FTrav trav) fstr@(FText str) = case fstr ^.. trav of
    [FText s] -> FText $ T.append str s
    _         -> fstr
mappingAppend _ flist            = flist

mappingPrepend :: Focuser -> Mapping
mappingPrepend (FTrav trav) fstr@(FText str) = case fstr ^.. trav of
    [FText s] -> FText $ T.append s str
    _         -> fstr
mappingPrepend _ flist            = flist

mappingUpper :: Mapping
mappingUpper (FText str) = FText $ T.toUpper str
mappingUpper flist       = flist

mappingLower :: Mapping
mappingLower (FText str) = FText $ T.toLower str
mappingLower flist       = flist

mappingMath :: (Rational -> Rational) -> Mapping
mappingMath f (FText str) = case readMaybeRational str of
    Nothing -> FText str
    Just n  -> FText $ showRational $ f n
mappingMath _ flist         = flist

mappingAdd :: Rational -> Mapping
mappingAdd = mappingMath . (+)

mappingSub :: Rational -> Mapping
mappingSub = mappingMath . flip (-)

mappingMult :: Rational -> Mapping
mappingMult = mappingMath . (*)

mappingDiv :: Rational -> Mapping
mappingDiv = mappingMath . flip (/)

mappingPow :: Int -> Mapping
mappingPow = mappingMath . flip (^^)

mappingAbs :: Mapping
mappingAbs = mappingMath abs

mappingSign :: Mapping
mappingSign = mappingMath signum

mappingSlice :: [Range] -> Mapping
mappingSlice ranges (FText str) = FText filtered_str
  where
    str_length = T.length str
    is = getIndexes ranges str_length
    filtered_str = makeFilteredText str_length is str

mappingSlice _ flist = flist

mappingSortBy :: Focuser -> Mapping
mappingSortBy (FTrav trav) focus = case focus of
    FText str -> FText $ T.pack $ sortBy (cmp `on` (FText . T.singleton)) $ T.unpack str
    FList lst   -> FList $ sortBy cmp lst
  where
    cmp f1 f2 =
        let f1' = f1 ^.. trav
            f2' = f2 ^.. trav
        in case (f1', f2') of
            ([FText s1], [FText s2]) -> case (readMDouble s1, readMDouble s2) of
                (Just n1, Just n2) -> compare n1 n2
                _                  -> EQ
            _ -> EQ

    readMDouble :: Text -> Maybe Double
    readMDouble = readMaybe . T.unpack

mappingSortLexBy :: Focuser -> Mapping
mappingSortLexBy (FTrav trav) focus = case focus of
    FText str -> FText $ T.pack $ sortBy (cmp `on` (FText . T.singleton)) $ T.unpack str
    FList lst   -> FList $ sortBy cmp lst
  where
    cmp f1 f2 =
        let f1' = f1 ^.. trav
            f2' = f2 ^.. trav
        in case (f1', f2') of
            ([FText s1], [FText s2]) -> compare s1 s2
            _                        -> EQ

mappingId :: Mapping
mappingId = id