{- | Module : Text.Zenhan Description : Converter between Full-width Japanese and Half-width Japanese Copyright : 2017 karky7 Calimakvonia License : BSD3 Maintainer : cantimerny.g@gmail.com Stability : unstable Portability : portable This module ported Python's zenhan library, similar to the "zenhan" library found in pypi: Let's see an example. @ {-# LANGUAGE OverloadedStrings #-} import Text.Zenhan import Data.Text (pack, unpack) main :: IO () main = do let h = h2z [Kana, Digit, Ascii] \"A\" \"ABCd\\\\「」アイウエオ123\" z = z2h [Kana, Digit, Ascii] \"Bエ\" h putStrLn $ toString h putStrLn $ toString z @ This library is still a work-in-progress, and contributions are welcome for missing pieces and to fix bugs. Please see the Github page to contribute with code or bug reports: -} {-# LANGUAGE OverloadedStrings #-} module Text.Zenhan ( z2h , h2z , isAllZenKana , isAllHanKana , isAllZen , toString , Mode(..) ) where import Data.Tuple (swap) import qualified Data.Text as T import qualified Data.Map as M import Text.Table.Chars -- | Type for character type to be converted data Mode = Kana | Digit | Ascii deriving(Eq, Show) -- | Convert from Full-width Japanese character to Half-width Japanese character z2h :: [Mode] -- ^ Type of character to be converted -> T.Text -- ^ Conversion exclusion character -> T.Text -- ^ Characters to be converted -> T.Text -- ^ Result z2h mode ignore text = T.concat $ map (zhTrans mode (convAry ignore)) (convAry text) -- | Convert from Half-width Japanese character to Full-width Japanese character h2z :: [Mode] -- ^ Type of character to be converted -> T.Text -- ^ Conversion exclusion character -> T.Text -- ^ Characters to be converted -> T.Text -- ^ Result h2z mode ignore text = T.concat $ map (hzTrans mode (hconvAry ignore)) (hconvAry text) -- | Check Full-width Japanese character zen kana, return True if all text is Zen Kana isAllZenKana :: T.Text -- ^ The text to be checked -> Bool -- ^ Result isAllZenKana = T.all (flip elem (T.unpack $ T.concat $ z_kana)) -- | Check Full-width Japanese character zen kana, return True if all text is Hen Kana isAllHanKana :: T.Text -- ^ The text to be checked -> Bool -- ^ Result isAllHanKana = T.all (flip elem (T.unpack $ T.concat $ h_kana)) -- | Check Full-width Japanese character zen kana, returns True if the text all Zen Kana isAllZen :: T.Text -- ^ The text to be checked -> Bool -- ^ Result isAllZen = not . T.any (flip elem (T.unpack $ T.concat $ (h_asciidigit ++ h_kana))) -- | Convert to String toString :: T.Text -> String toString = T.unpack zhTrans :: [Mode] -> [T.Text] -> T.Text -> T.Text zhTrans mode ign t = case M.lookup t (z2hMap mode) of Just v -> choice (elem t ign) t v Nothing -> t hzTrans :: [Mode] -> [T.Text] -> T.Text -> T.Text hzTrans mode ign t = case M.lookup t (h2zMap mode) of Just v -> choice (elem t ign) t v Nothing -> t choice :: Bool -> a -> a -> a choice True t _ = t choice False _ v = v z2hMap :: [Mode] -> M.Map T.Text T.Text z2hMap [] = M.empty z2hMap (x:xs) = M.unions ([zhMap x, z2hMap xs]) zhMap :: Mode -> M.Map T.Text T.Text zhMap Kana = zh_kana zhMap Digit = zh_digit zhMap Ascii = zh_ascii h2zMap :: [Mode] -> M.Map T.Text T.Text h2zMap [] = M.empty h2zMap (x:xs) = M.unions ([hzMap x, h2zMap xs]) hzMap :: Mode -> M.Map T.Text T.Text hzMap Kana = hz_kana hzMap Digit = hz_digit hzMap Ascii = hz_ascii convAry :: T.Text -> [T.Text] convAry xs = T.transpose [xs] hconvAry :: T.Text -> [T.Text] hconvAry = mergeWord . convAry mergeWord :: [T.Text] -> [T.Text] mergeWord (x:y:xs) = choice (elem (T.concat [x, y]) (h_kana_d ++ h_kana_p)) (T.concat [x, y] : mergeWord xs) (x : mergeWord (y:xs)) mergeWord (x:xs) = x : mergeWord xs mergeWord [] = [] zh_ascii :: M.Map T.Text T.Text zh_ascii = M.fromList $ zip z_ascii h_ascii hz_ascii :: M.Map T.Text T.Text hz_ascii = transposeMap zh_ascii zh_digit :: M.Map T.Text T.Text zh_digit = M.fromList $ zip z_digit h_digit hz_digit :: M.Map T.Text T.Text hz_digit = transposeMap zh_digit zh_kana :: M.Map T.Text T.Text zh_kana = M.fromList $ zip z_kana h_kana hz_kana :: M.Map T.Text T.Text hz_kana = transposeMap zh_kana transposeMap :: M.Map T.Text T.Text -> M.Map T.Text T.Text transposeMap = M.fromList . map swap . M.toList