fquery-0.2.2: Adelie/UseDesc.hs
-- UseDesc.hs
--
-- Module for parsing portageProfile/use.desc and use.local.desc files.
module Adelie.UseDesc (
UseDescriptions,
readUseDesc,
readUseDescPackage,
readUseExpDesc
) where
import Data.Char (isSpace)
import qualified Data.HashTable.IO as HT
import Control.Monad (when)
import Adelie.ListEx
import Adelie.FileEx
import Adelie.Portage
import System.Directory
import System.FilePath.Posix (takeBaseName, splitExtension)
type UseDescriptions = HT.BasicHashTable String String
----------------------------------------------------------------
readUseDesc :: IO UseDescriptions
readUseDesc = do
table <- HT.new
ls <- readFile useDesc
mapM_ (useParser table) (lines ls)
return table
useParser :: UseDescriptions -> String -> IO ()
useParser _ ('#':_) = return ()
useParser table line = HT.insert table use desc
where (use, desc) = myBreak line
myBreak :: String -> (String, String)
myBreak [] = ("", "")
myBreak (' ':'-':' ':xs) = ("", xs)
myBreak (x:xs) = (x:ys, zs)
where (ys, zs) = myBreak xs
----------------------------------------------------------------
readUseDescPackage :: String -> String -> IO UseDescriptions
readUseDescPackage start end = do
table <- HT.new
ls <- readFile useDescPackage
mapMUntil_ (useParser2 table start end) (lines ls)
return table
mapMUntil_ :: Monad m => (a -> m Bool) -> [a] -> m ()
mapMUntil_ _ [] = return ()
mapMUntil_ f (x:xs) = do
r <- f x
when r (mapMUntil_ f xs)
useParser2 :: UseDescriptions -> String -> String -> String -> IO Bool
useParser2 _ _ _ [] = return True
useParser2 _ _ _ ('#':_) = return True
useParser2 table start end str =
case mid start catname end of
LT -> return True
EQ -> HT.insert table use desc >> return True
GT -> return False
where str' = reverse $ dropWhile isSpace $ reverse str
(catname, rest) = break2 (':' ==) str'
(use, desc) = myBreak rest
----------------------------------------------------------------
readUseExpDesc :: IO UseDescriptions
readUseExpDesc = do
table <- HT.new
files <- noDirs
. addPathPrefix useExpDescDir
. getDirectoryContents
$ useExpDescDir
fileContents <- mapM (\fp -> fmap
(unexpandUse fp . rmBlank . rmComments)
(readFile fp))
files
mapM_ (useParser table) (lines . concat $ fileContents)
return table
-- |Use expand descriptions don't contain the first part of the USE
-- flag in the files, so 'libreoffice_extensions_nlpsolver - desc'
-- is actually 'nlpsolver - desc'.
-- We have to fix that.
unexpandUse :: FilePath -- ^ the file the Use desc is part of
-> String -- ^ the file contents, with comments etc removed
-> String -- ^ the fixed file contents
unexpandUse fp fc =
unlines
. addPrefix (flip (++) "_" . noExt . takeBaseName $ fp)
. lines
$ fc
where
noExt = fst . splitExtension
----------------------------------------------------------------
-- In Haskell, vim-core > vim
-- In sort, vim-core < vim
-- Work around it.
myCompare :: String -> String -> Ordering
myCompare [] [] = EQ
myCompare _ [] = LT
myCompare [] _ = GT
myCompare (a:as) (b:bs) =
if r == EQ
then myCompare as bs
else r
where r = compare a b
mid :: String -> String -> String -> Ordering
mid l m r
| myCompare l m == GT = LT
| myCompare m r == GT = GT
| otherwise = EQ