module Language.Lojban.Util (-- * Query a Jbovlaste database lujvoSelrafsis ,lujvosSelrafsi ,lujvosSelrafsis ,lujvosSelrafsis' ,findGismu ,findCmavo ,findSelrafsi ,filterSelma'o ,valsiByGloss -- * External programs ,grammar ,translate ,wordType ,lujvoAndRate ,selma'oInfo ,isValidLojban) where import Utils import Language.Lojban.Jbovlaste import Control.Arrow import Data.Char import Data.List import Text.Regex import Data.Ord -- | Find valsi(s) by gloss, more detailed. valsiByGloss :: JboDB -> String -> [JboValsi] valsiByGloss db s = sortBy (comparing valsiType) $ filterValsi db match where match e = any (isInfixWord s) (valsiGloss e) isInfixWord s = any (==s) . words -- | Return the selrafsis of a lujvo (string). lujvoSelrafsis :: JboDB -> String -> Maybe [JboValsi] lujvoSelrafsis db = list Nothing (Just . valsiSelrafsis . head) . valsi db -- | Returns all lujvos which contain the given selrafsi. lujvosSelrafsi :: JboDB -> String -- ^ selrafsi (either a cmavo or gismu) -> [JboValsi] -- ^ lujvos containing said selrafsi lujvosSelrafsi db w = filterValsi db (any ((==w) . valsiWord) . valsiSelrafsis) -- | Returns all lujvos which contain any of the given selrafsis. lujvosSelrafsis :: JboDB -> [String] -- ^ selrafsis -> [JboValsi] -- ^ lujvos containing any of the selrafsis lujvosSelrafsis db ws = filterValsi db (any (flip elem ws . valsiWord) . valsiSelrafsis) -- | Returns all lujvos which contain all of the given selrafsis (in order). lujvosSelrafsis' :: JboDB -> [String] -- ^ selrafsis -> [JboValsi] -- ^ lujvos containing all of the selrafsis (in order) lujvosSelrafsis' db ws = filterValsi db ((==ws) . map valsiWord . valsiSelrafsis) -- | Find a gismu valsi matching the given word. findGismu :: JboDB -> String -> Maybe JboValsi findGismu db w = findValsi db gismu where gismu v = valsiType v == GismuType && valsiWord v == w -- | Find a cmavo valsi matching the given word. findCmavo :: JboDB -> String -> Maybe JboValsi findCmavo db w = findValsi db cmavo where cmavo v = valsiType v == CmavoType && valsiWord v == w -- | Find a selrafsi matching the given rafsi. findSelrafsi :: JboDB -> String -> Maybe JboValsi findSelrafsi db w = findValsi db selrafsi where selrafsi v = (valsiType v == CmavoType || valsiType v == GismuType) && (any (==w) (valsiRafsis v) || (length w >= 4 && valsiType v == GismuType && w `isPrefixOf` valsiWord v)) -- | Returns all cmavo which belong to the given selma'o. filterSelma'o :: JboDB -> String -> [JboValsi] filterSelma'o db s = filterValsi db selma'o where selma'o v = valsiType v == CmavoType && fmap format (valsiSelma'o v) == Just (format s) where format | any isDigit s = lower | otherwise = filter isLetter . lower -- | Shows the grammar of a lojban utterance using jbofihe. grammar :: String -- ^ The lojban utterance -> IO (Either String (String,String)) -- ^ A pair of error and success strings. grammar = run "jbofihe -ie" -- | Translates a lojban utterance to English using jbofihe. translate :: String -- ^ The lojban utterance -> IO (Either String (String,String)) -- ^ English output translate = run "jbofihe -x" -- | Shows the type of a word using vlatai. wordType :: String -- ^ The lojban word -> IO (Either String String) -- ^ Word type wordType w = do r <- run ("vlatai \"" ++ (lojbanic w) ++ "\"") "" case r of Right ("",v) -> return . Right . unwords . words $ v Right (e,_) -> return $ Left e Left e -> return $ Left e -- | Tries to construct and rate lujvo from selfrasis, using jvocuhadju. lujvoAndRate :: [String] -- ^ selrafsis -> IO (Either String [(Int,String)]) -- ^ Word type lujvoAndRate ws = do let selrafsis = unwords $ map (("\""++) . (++"\"") . lojbanic) ws r <- run ("jvocuhadju " ++ selrafsis ++ "") "" case r of Right ("",g) -> return $ Right $ map (rating . trim) $ dropWhile (not . any isDigit) $ lines $ g Right (e,_) -> return $ Left e Left e -> return $ Left e where rating = (read *** tail) . break isSpace -- | Returns information about a selma'o, using mahotic. selma'oInfo :: String -> IO (Either String String) selma'oInfo s = do r <- run ("mahotci -i \"" ++ upper (lojbanic s) ++ "\"") "" case r of Right ("",good) -> return $ Right (format good) Right (bad,_) -> return $ Left $ "no entry for \"" ++ s ++ "\"" Left _ -> return $ Left "mahotci pipe error" where format = flip (subRegex r1) "\n" . flip (subRegex r) "\\1 \\2" r = mkRegex "([^\n])\n([^\n])" r1 = mkRegex "\n\n" -- | Just checks with jbofihe if some lojban is grammatically valid. isValidLojban :: String -> IO Bool isValidLojban line = do out <- grammar line case out of Right (_,"") -> return $ False _ -> return $ True lojbanic = filter good where good c = isLetter c || c == '\'' || c == ' ' lower = map toLower upper = map toUpper