{- Copyright (C) 2009 John MacFarlane This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -} {- Utility functions for Gitit. -} module Network.Gitit.Util ( readFileUTF8 , inDir , withTempDir , orIfNull , splitCategories , trim , yesOrNo , parsePageType ) where import System.Directory import Control.Exception (bracket) import System.FilePath ((), (<.>)) import System.IO.Error (isAlreadyExistsError) import Control.Monad.Trans (liftIO) import Data.Char (toLower) import Data.ByteString.Lazy.UTF8 (toString) import qualified Data.ByteString.Lazy as B import Network.Gitit.Types import Control.Monad (liftM) import Codec.Binary.UTF8.String (encodeString) -- | Read file as UTF-8 string. Encode filename as UTF-8. readFileUTF8 :: FilePath -> IO String readFileUTF8 f = liftM toString $ B.readFile $ encodeString f -- | Perform a function a directory and return to working directory. inDir :: FilePath -> IO a -> IO a inDir d action = do w <- getCurrentDirectory setCurrentDirectory d result <- action setCurrentDirectory w return result -- | Perform a function in a temporary directory and clean up. withTempDir :: FilePath -> (FilePath -> IO a) -> IO a withTempDir baseName = bracket (createTempDir 0 baseName) removeDirectoryRecursive -- | Create a temporary directory with a unique name. createTempDir :: Integer -> FilePath -> IO FilePath createTempDir num baseName = do sysTempDir <- getTemporaryDirectory let dirName = sysTempDir baseName <.> show num liftIO $ catch (createDirectory dirName >> return dirName) $ \e -> if isAlreadyExistsError e then createTempDir (num + 1) baseName else ioError e -- | Returns a list, if it is not null, or a backup, if it is. orIfNull :: [a] -> [a] -> [a] orIfNull lst backup = if null lst then backup else lst -- | Split a string containing a list of categories. splitCategories :: String -> [String] splitCategories = words . map puncToSpace . trim where puncToSpace x | x `elem` ".,;:" = ' ' puncToSpace x = x -- | Trim leading and trailing spaces. trim :: String -> String trim = reverse . trimLeft . reverse . trimLeft where trimLeft = dropWhile (`elem` " \t") -- | Show Bool as "yes" or "no". yesOrNo :: Bool -> String yesOrNo True = "yes" yesOrNo False = "no" parsePageType :: String -> (PageType, Bool) parsePageType s = case map toLower s of "markdown" -> (Markdown,False) "markdown+lhs" -> (Markdown,True) "rst" -> (RST,False) "rst+lhs" -> (RST,True) "html" -> (HTML,False) "textile" -> (Textile,False) "latex" -> (LaTeX,False) "latex+lhs" -> (LaTeX,True) x -> error $ "Unknown page type: " ++ x