boomange-0.1.0.0: Main.hs
{-
Copyright 2013,2014 Marcelo Millani
This file is part of boomange.
boomange 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 3 of the License, or
(at your option) any later version.
boomange 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 boomange. If not, see <http://www.gnu.org/licenses/>
-}
import Control.Exception
import Control.Monad
import System.IO
import System.Directory
import System.Environment
import System.FilePath
import Data.List
import Paths_boomange -- automatically generated
import Data.DescriLo
import Data.Builder
import Data.Entities hiding (name)
import Data.Loader
appName = "boomange"
-- header to be used on the sample config file
configHeader =
"# This is the configuration file for " ++ appName ++ "\n" ++
"# For a full description of its syntax, see the haddock documentation of DescriLo\n" ++
"# In the config description:\n" ++
"# output - where should the resulting html file be placed\n" ++
"# header - file to be prepended to output\n" ++
"# footer - file to be appended to output\n" ++
"# there are no other values for config\n\n" ++
"# In the watch description, there may be an unlimited amount of values and the left part is always ignored by the program and may be used for organization.\n" ++
"# The right part indicates which file will be read to create the output. It will behave as if all of the files were concatenated.\n\n"
-- header to be used on the sample bookmarks file
bookmarksHeader =
"# This is a sample bookmarks file for " ++ appName ++ "\n" ++
"# For a full description of its syntax, see the haddock documentation of DescriLo\n" ++
"# Every description has at least two values:\n" ++
"# type - may be either 'folder' or 'url'\n" ++
"# father - creates an hierarchy. May be the name of any folder description or 'root'\n" ++
"# Additionally, descriptions where type=url have the following value:\n" ++
"# url - where it links to\n" ++
"# there are no other possible values\n\n"
generateBookmarks config = do
header <- readFile $ headerFile config
footer <- readFile $ footerFile config
final <- openFile (outputFile config) WriteMode
bookmarks <- loadBookmarks $ watch config
let body = htmlBookmarks bookmarks
hPutStr final header
hPutStr final body
hPutStr final footer
hClose final
-- | gets the directory where configuration files should be placed
--
-- First, checks if XDG_CONFIG_HOME exists, producing $XDG_CONFIG_HOME/appName if it does
-- if it does not, the checks if HOME does, producing $HOME/.config/appName if it does
-- if it still fails, returns getAppUserDataDirectory appName
getConfigDirectory appName =
let failXDG e = do
dir <- getEnv "HOME"
return $ dir ++ [pathSeparator] ++ ".config" ++ [pathSeparator] ++ appName
in
let failHOME e = getAppUserDataDirectory appName in
do
handle
(failHOME::SomeException -> IO FilePath) $
handle (failXDG::SomeException -> IO FilePath) $ do
dir <- getEnv "XDG_CONFIG_HOME"
return $ dir ++ [pathSeparator] ++ appName
-- | installs a basic configuration
installConfig cDir =
let htmlDir = cDir ++ [pathSeparator] ++ "html" in
let bookFile = cDir ++ [pathSeparator] ++ "bookmarks" in
let outFile = cDir ++ [pathSeparator] ++ "bookmarks.html" in
let config =
Description
{
name = "config"
, values = [
("output",outFile)
,("header",htmlDir ++ [pathSeparator] ++ "header.html")
,("footer", htmlDir ++ [pathSeparator] ++ "footer.html")
]
}
in
let watch =
Description
{
name = "watch"
, values = [
("default",bookFile)
]
}
in
let sampleFolder =
Description
{
name = "Sample Folder"
, values = [
("type","folder")
,("father","root")
]
}
in
let sampleUrl =
Description
{
name = "Sample Url"
, values = [
("type","url")
,("father","Sample Folder")
,("url","file://" ++ outFile)
]
}
in
let cFile = cDir ++ [pathSeparator] ++ "config" in
do
-- creates the base config file
hcFile <- openFile cFile WriteMode
hPutStr hcFile configHeader
hPutStr hcFile $ show config
-- hPutStr hcFile $ "\n\n"
hPutStr hcFile $ show watch
hClose hcFile
-- copies the default html files
headerFile <- getDataFileName "html/header.html"
footerFile <- getDataFileName "html/footer.html"
cssFile <- getDataFileName "style.css"
-- creates the html folder
createDirectoryIfMissing True htmlDir
-- copies html files
copyFile headerFile $ htmlDir ++ [pathSeparator] ++ "header.html"
copyFile footerFile $ htmlDir ++ [pathSeparator] ++ "footer.html"
-- copies css file
copyFile cssFile $ cDir ++ [pathSeparator] ++ "style.css"
-- creates a sample bookmarks file
hBookmarks <- openFile bookFile WriteMode
hPutStr hBookmarks bookmarksHeader
hPutStr hBookmarks $ show sampleFolder
hPutStr hBookmarks $ show sampleUrl
hClose hBookmarks
main = do
cDir <- getConfigDirectory appName
-- if the configuration directory does not exists, sets it up
confExists <- doesDirectoryExist cDir
when (not confExists) $ do
createDirectoryIfMissing True cDir
installConfig cDir
let cFile = cDir ++ "/config"
config <- loadConfig cFile
generateBookmarks config