boomange 0.1.2.1 → 0.1.3.0
raw patch · 5 files changed
+127/−78 lines, 5 filesdep ~basedep ~descrilodep ~filepath
Dependency ranges changed: base, descrilo, filepath, simtreelo
Files
- Data/Builder.hs +21/−21
- Data/Loader.hs +19/−19
- Main.hs +81/−34
- boomange.cabal +3/−3
- style.css +3/−1
Data/Builder.hs view
@@ -23,33 +23,33 @@ import Data.Entities splitSet _ [] = ([],[])-splitSet f (h:r) = - let (true,false) = splitSet f r in- if f h then (h:true,false)- else (true,h:false)+splitSet f (h:r) =+ let (true,false) = splitSet f r in+ if f h then (h:true,false)+ else (true,h:false) makeError msg fname = - let file = Node{rootLabel = "file://" ++ fname, subForest = []} in- let link = Node{rootLabel = fname, subForest = [file]} in- Node{rootLabel = "Error: " ++ msg, subForest = [link] }+ let file = Node{rootLabel = "file://" ++ fname, subForest = []}+ link = Node{rootLabel = fname, subForest = [file]} in+ Node{rootLabel = "Error: " ++ msg, subForest = [link] } -- | builds the bookmark tree buildBookmarks fname Node{rootLabel = rl, subForest = sForest} = - case sForest of- [] -> buildBookmarks fname (makeError ("empty tree (" ++ rl ++ ")") fname)- [Node{rootLabel = l, subForest = []} ] -> Url{name = rl, url = l}- _ -> Folder{name = rl, children = map (buildBookmarks fname ) sForest}+ case sForest of+ [] -> buildBookmarks fname (makeError ("empty tree (" ++ rl ++ ")") fname)+ [Node{rootLabel = l, subForest = []} ] -> Url{name = rl, url = l}+ _ -> Folder{name = rl, children = map (buildBookmarks fname ) sForest} -- | generates html for the given bookmarks htmlBookmarks bookmark = concat $ map (htmlBookmarks' 0) bookmark htmlBookmarks' depth bookmark = - case bookmark of- Folder{name = n, children = c} ->- ident ++ "<div class='folder'>\n" ++- ident ++ "<p class='folder'>" ++ n ++ "</p>\n" ++- (concat $ map (htmlBookmarks' (depth+1)) c ) ++- ident ++ "</div>\n"- Url{name = n, url = u} ->- ident ++ "<a class='url' href='" ++ u ++ "'>" ++ n ++ "</a><br>\n"- where- ident = take depth $ repeat '\t'+ case bookmark of+ Folder{name = n, children = c} ->+ ident ++ "<div class='folder'>\n"+ ++ ident ++ "<p class='folder'>" ++ n ++ "</p>\n"+ ++ (concat $ map (htmlBookmarks' (depth+1)) c )+ ++ ident ++ "</div>\n"+ Url{name = n, url = u} -> + ident ++ "<a class='url' href='" ++ u ++ "'>" ++ n ++ "</a><br>\n"+ where+ ident = take depth $ repeat '\t'
Data/Loader.hs view
@@ -30,27 +30,27 @@ createConfig description = createConfig' (values description) defaultConfig createConfig' [] config = config createConfig' (h:r) config = - case h of- ("output",outp) -> createConfig' r config{outputFile = outp}- ("header",head) -> createConfig' r config{headerFile = head}- ("footer",foot) -> createConfig' r config{footerFile = foot}- _ -> createConfig' r config+ case h of+ ("output",outp) -> createConfig' r config{outputFile = outp}+ ("header",head) -> createConfig' r config{headerFile = head}+ ("footer",foot) -> createConfig' r config{footerFile = foot}+ _ -> createConfig' r config loadConfig cFile = do- description <- loadDescriptionFile cFile "config"- let Just c = find (\x -> (name x) == "config") description- let config = createConfig c- let Just w = find (\x -> (name x) == "watch") description- return $ (createConfig c){watch = map (\(l,r) -> r) (values w)}- + description <- loadDescriptionFile cFile "config"+ let Just c = find (\x -> (name x) == "config") description+ let config = createConfig c+ let Just w = find (\x -> (name x) == "watch") description+ return $ (createConfig c){watch = map (\(l,r) -> r) (values w)}+ -- | builds the bookmark tree loadBookmarks [] = do return [] loadBookmarks (h:r) = do- books <- Simtreelo.loadFile h- let here = case books of- Right forest -> -- forest- if null $ filter (\x -> null $ subForest x) forest then forest- else [makeError "empty tree" h]- Left error -> [makeError error h]- rest <- loadBookmarks r- return $ (map (buildBookmarks h) here) ++ rest+ books <- Simtreelo.loadFile h+ let here = case books of+ Right forest -> -- forest+ if null $ filter (\x -> null $ subForest x) forest then forest+ else [makeError "empty tree" h]+ Left error -> [makeError error h]+ rest <- loadBookmarks r+ return $ (map (buildBookmarks h) here) ++ rest
Main.hs view
@@ -25,17 +25,21 @@ import System.FilePath import Data.List import Text.Printf+import Data.Tree import Paths_boomange -- automatically generated -import Data.DescriLo+import Data.DescriLo as DescriLo+import Data.Simtreelo as Simtreelo import Data.Builder import Data.Entities hiding (name)-import Data.Loader +import Data.Loader ++ appName = "boomange"-appVersion = "0.1.2.1"+appVersion = "0.1.3.0" -- header to be used on the sample config file configHeader = "# This is the configuration file for " ++ appName ++ "\n" ++@@ -47,7 +51,7 @@ "# 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 = "#\n" ++@@ -96,13 +100,13 @@ Description { name = "config"- , values = [+ , values = [ ("output",outFile) , ("header",htmlDir ++ [pathSeparator] ++ "header.html") , ("footer", htmlDir ++ [pathSeparator] ++ "footer.html") ]- }- + }+ watch = Description {@@ -110,7 +114,7 @@ , values = [ ("default",bookFile) ]- } + } sampleBookmarks = "Boomange\n\tDocumentation\n" ++ "\t\tDescriLo\n\t\t\thttp://hackage.haskell.org/package/descrilo-0.1.0.0/docs/Data-DescriLo.html\n" ++@@ -125,7 +129,7 @@ hPutStr hcFile $ show config hPutStr hcFile $ show watch hClose hcFile- + -- copies the default html files headerFile <- getDataFileName "html/header.html" footerFile <- getDataFileName "html/footer.html"@@ -136,7 +140,7 @@ copyFile headerFile $ htmlDir ++ [pathSeparator] ++ "header.html" copyFile footerFile $ htmlDir ++ [pathSeparator] ++ "footer.html" -- copies css file- copyFile cssFile $ cDir ++ [pathSeparator] ++ "style.css" + copyFile cssFile $ cDir ++ [pathSeparator] ++ "style.css" -- creates a sample bookmarks file hBookmarks <- openFile bookFile WriteMode@@ -144,30 +148,71 @@ hPutStr hBookmarks $ sampleBookmarks hClose hBookmarks -data Action = Help | ConfigFile String | Version | Status | Invalid String | Generate deriving Eq-parseArgs args = case args of- "-h":r -> Help : parseArgs r- "--help":r -> Help : parseArgs r- "-c":file:r -> ConfigFile file : parseArgs r- "--config":file:r -> ConfigFile file : parseArgs r- "-v":r -> Version : parseArgs r- "--version":r -> Version : parseArgs r- "-s":r -> Status : parseArgs r- "--status":r -> Status : parseArgs r- [] -> []- other:r -> Invalid other : Help : parseArgs r+data Action = Help | ConfigFile String | Version | Status | Add String String String | Invalid String | Generate deriving Eq -execute [] _ = return ()-execute (h:r) configFiles =+parseArgs args activeConfig = case args of+ "-h":r -> Help : parseArgs r activeConfig+ "--help":r -> Help : parseArgs r activeConfig+ "-c":file:r -> ConfigFile file : parseArgs r file+ "--config":file:r -> ConfigFile file : parseArgs r file+ "-v":r -> Version : parseArgs r activeConfig+ "--version":r -> Version : parseArgs r activeConfig+ "-s":r -> Status : parseArgs r activeConfig+ "--status":r -> Status : parseArgs r activeConfig+ "-a":bookmark:uri:r -> Add bookmark uri activeConfig : parseArgs r activeConfig+ "--add":bookmark:uri:r -> Add bookmark uri activeConfig : parseArgs r activeConfig+ [] -> []+ other:r -> Invalid other : Help : parseArgs r activeConfig++-- | Adds a bookmark to the correct file inside the configuration file given+--+-- | The bookmark is in the form "id/path/of/bookmark", where 'id' is the identifier of the simtreelo file to which the bookmark should be added and each slash indicates a new depth in the tree. The last value should be the URI of the bookmark.+--+-- | Existing depths will be reused (i.e., duplicates will not be generated).+addBookmark bookmark uri configFile = do+ let (id, r) = span (/= '/') bookmark+ config <- DescriLo.loadDescriptionFile configFile ""+ let mwatch = find (\x -> DescriLo.name x == "watch") config+ case mwatch of+ Just watch -> let mid = find (\(x,y) -> x == id) $ DescriLo.values watch in+ case mid of+ Nothing -> printf "No bookmark file with id '%s' found in configuration file '%s'. Bookmark '%s' ignored.\n" id configFile bookmark+ -- adds the bookmark to the respective simtreelo file+ Just (foundId, treeFile) -> addBookmarkTree (tail r) uri treeFile+ Nothing -> putStr "invalid configuration file"+ ++addBookmarkTree bookmark uri treeFile = do+ let bookmarkTree = pathToTree bookmark uri+ oldForest <- Simtreelo.loadFile treeFile+ case oldForest of+ Left error -> printf "Failed loading '%s':\n\t%s" treeFile error+ Right forest -> do+ let newTree = Simtreelo.merge forest bookmarkTree+ Simtreelo.write newTree "" "\t" treeFile+ printf "Added '%s' to '%s'.\n" uri treeFile++pathToTree path uri =+ let (label, r) = span (/= '/') path in+ Node{rootLabel = label, subForest = if r == [] then [Node{rootLabel = uri, subForest = []}] else [ pathToTree (tail r) uri ] }++execute [] _ _ = return ()+execute (h:r) activeConfig configFiles = case h of+ Add bookmark uri configFile -> do+ addBookmark bookmark uri configFile Help -> do printf "usage: %s [OPTION...]\n" appName putStr $ "Options:\n" ++- "\t-h, --help shows this help text\n" ++- "\t-c, --config <file> uses <file> as config instead of the default\n" ++- "\t-v, --version outputs version and exits\n"++- "\t-s, --status outputs configuration file info and exits\n"+ " -h, --help shows this help text\n" +++ " -c, --config <file> uses <file> as config instead of the default\n" +++ " -v, --version outputs version and exits\n"+++ " -s, --status outputs configuration file info and exits\n" +++ " -a, --add <location> <URI> adds a bookmark to file with the given id.\n" +++ " The depths of <location> should be separated\n" +++ " with '/'s.\n" +++ " Example: 'id/section'\n" Version -> do printf "%s %s\n" appName appVersion putStr $ "Copyright (C) 2013,2014 Marcelo Garlet Millani\n" ++@@ -181,7 +226,7 @@ Generate -> do configs <- mapM loadConfig configFiles mapM_ generateBookmarks configs- >> execute r configFiles+ >> execute r activeConfig configFiles showStatus :: String -> IO [String] showStatus configFile = do@@ -193,19 +238,21 @@ "\tBookmarks files:" : (map (\x -> "\t\t" ++ x) $ watch config) +{- separateConfigs [] = ([],[]) separateConfigs (h:r) = let (actions, configs) = separateConfigs r in case h of ConfigFile x -> (actions, x : configs) other -> (other : actions, configs)- +-} main = do args <- getArgs- let (argActions, argConfigs) = separateConfigs $ parseArgs args- -- if help or version were asked, does not generate bookmarks- actions = if elem Help argActions || elem Version argActions || elem Status argActions then argActions else (Generate : argActions)+ let (argConfigs', argActions) = partition (\x -> case x of ConfigFile _ -> True ; _ -> False) $ parseArgs args ""+ argConfigs = map (\(ConfigFile x) -> x) argConfigs'+ -- if help, status or version were asked, does not generate bookmarks+ actions = if elem Help argActions || elem Version argActions || elem Status argActions then argActions else (argActions ++ [Generate]) -- if no configuration file was given, uses the default one configs <- if argConfigs == [] then do cDir <- getConfigDirectory appName@@ -216,7 +263,7 @@ installConfig cDir return $ [cDir ++ "/config"] else (return argConfigs)- execute actions configs+ execute actions "" configs {- cDir <- getConfigDirectory appName
boomange.cabal view
@@ -2,14 +2,14 @@ -- documentation, see http://haskell.org/cabal/users-guide/ name: boomange-version: 0.1.2.1+version: 0.1.3.0 synopsis: A Bookmarks manager with a HTML generator description: In order to allow a unified and customized bookmarks file, boomange generates a HTML file with an user's bookmarks. license: GPL-3 license-file: LICENSE author: Marcelo Garlet Millani maintainer: marcelogmillani@gmail.com-copyright: (c) 2013,2014 Marcelo Garlet Millani+copyright: (c) 2013-2015 Marcelo Garlet Millani category: Web build-type: Simple data-files: html/footer.html , html/header.html, style.css@@ -20,7 +20,7 @@ main-is: Main.hs -- other-modules: -- other-extensions: - build-depends: base >=4.7 && <4.8, directory >=1.2 && <1.3, filepath >=1.3 && <1.4, descrilo >=0.1.0.0 && <0.2, containers >=0.5 && <0.6, simtreelo >=0.1.0.0 && <0.2+ build-depends: base >=4.8 && <4.9, directory >=1.2 && <1.3, filepath >=1.4 && <1.5, descrilo >=0.1 && <0.2, containers >=0.5 && <0.6, simtreelo >=0.1 && <0.2 -- hs-source-dirs: other-modules: Data.Entities, Data.Loader, Data.Builder default-extensions: DoAndIfThenElse
style.css view
@@ -8,6 +8,7 @@ { padding:5px; border:5px solid #58A2DC;+ border-radius:6px; margin:5px; background-color:#aac9F2; }@@ -17,11 +18,12 @@ text-align:justify; font-weight:bold; color:#20207F;+ border-bottom:dotted #50A0D0;+ border-width:2px; } a.url:link,a.url:visited {- font-weight:bold; color:blue; } a.url:hover,a.url:active