root/lang/haskell/blosxkel/blosxkel.hs @ 1160

Revision 1160, 5.1 kB (checked in by jknaoya, 6 years ago)

lang/haskell/blosxkel/story.html,
lang/haskell/blosxkel/head.html,
lang/haskell/blosxkel/foot.html,
lang/haskell/blosxkel/blosxkel.hs:

正規表現つかったら負けかな、と思ってる (笑)
blosxom 互換のテンプレート変数を追加しました

  • Property svn:executable set to *
Line 
1#!/usr/local/bin/runghc
2-- id:nobsun さんありがとうございます
3
4module Main where
5
6import System.FilePath
7import System.Directory
8import System.Time
9import System.Locale (defaultTimeLocale)
10
11import Data.List
12import Data.Maybe
13import Data.Char
14import Data.Eq
15
16import Network.CGI
17
18-- ref. http://i.loveruby.net/ja/stdhaskell/samples/lazylines/Template.hs.html
19fillFlavour :: String -> String -> [(String, String)] -> IO String
20fillFlavour flavour place params = return . fill =<< (readFile $ place ++ "." ++ flavour)
21    where
22        fill ""   = ""
23        fill tmpl = case break (== '$') tmpl of
24                         (s, ('$':cs)) -> s ++ expand var ++ fill cont
25                                          where (var, cont) = span isAlpha cs
26                         (s, cont)     -> s ++ fill cont
27
28        expand var = fromMaybe ('$':var) (lookup var params)
29
30loadConfig :: String -> IO [(String, String)]
31loadConfig config = do
32    {
33    ; c <- readFile config
34    ; return $ concatMap parseLine $ lines c
35    } where
36        parseLine :: String -> [(String, String)]
37        parseLine l
38                  | all isSpace l = []
39                  | otherwise     = let (k, (':':v)) = (break (== ':') l)
40                                    in [(strip k, strip v)]
41        strip     = rstrip . lstrip
42        rstrip    = reverse . lstrip . reverse
43        lstrip    = dropWhile isSpace
44
45getConfig :: [(String, String)] -> String -> String
46getConfig config key = fromJust $ lookup key config
47
48data Entry = Entry {
49    file  :: FilePath,
50    path  :: String,
51    title :: String,
52    time  :: ClockTime,
53    body  :: [String]
54}
55
56
57getFileEntry :: String -> FilePath -> IO Entry
58getFileEntry d f = do
59    {
60    ; mtime <- getModificationTime f
61    ; cs    <- readFile f
62    ; case lines cs of
63        h:tl -> return $ Entry { file  = f
64                               , path  = dropExtension $ drop (length d) f
65                               , title = h
66                               , time  = mtime
67                               , body  = tl
68                               }
69    }
70
71-- http://www.tom.sfc.keio.ac.jp/~sakai/2ch/1162902266.html
72getRecursiveContents :: FilePath -> IO [FilePath]
73getRecursiveContents fp = getDirectoryContents fp >>= mapM (fx fp) >>= return . concat
74    where
75       fx :: FilePath -> FilePath -> IO [FilePath]
76       fx bp "."  = return [bp]
77       fx bp ".." = return []
78       fx bp f    = do let np = bp ++ ('/':f)
79                       b <- doesDirectoryExist np
80                       if b then getRecursiveContents np
81                            else return [np]
82
83
84
85getTextFileEntries :: FilePath -> IO [Entry]
86getTextFileEntries d = do
87    {
88    ; fs <- getRecursiveContents d
89    ; es <- mapM (getFileEntry d) $ filter (isSuffixOf ".txt") fs
90    ; return es
91    }
92
93
94getResult :: [(String, String)] -> [(String, String)] -> IO (String, String)
95getResult cgiparams config = do
96    {
97    ; entries <- getTextFileEntries $ getConfig config "data-dir"
98    ; ct <- fill "content_type" []
99    ; ch <- fill "head" []
100    ; cs <- mapM
101               (\e -> fill "story"
102               [("title"  , title e),
103                ("body"   , concat (body e)),
104                ("time"   , formatCalendarTime defaultTimeLocale "%Y-%m-%d %H:%M:%S" (toUTCTime (time e))),
105                ("yr"     , formatCalendarTime defaultTimeLocale "%Y" (toUTCTime (time e))),
106                ("mo"     , formatCalendarTime defaultTimeLocale "%b" (toUTCTime (time e))),
107                ("mo_num" , formatCalendarTime defaultTimeLocale "%m" (toUTCTime (time e))),
108                ("da"     , formatCalendarTime defaultTimeLocale "%d" (toUTCTime (time e))),
109                ("dw"     , formatCalendarTime defaultTimeLocale "%a" (toUTCTime (time e))),
110                ("hr"     , formatCalendarTime defaultTimeLocale "%H" (toUTCTime (time e))),
111                ("min"    , formatCalendarTime defaultTimeLocale "%M" (toUTCTime (time e))),
112                ("hr12"   , formatCalendarTime defaultTimeLocale "%I" (toUTCTime (time e))),
113                ("ampm"   , formatCalendarTime defaultTimeLocale "%p" (toUTCTime (time e))),
114                ("ti"     , formatCalendarTime defaultTimeLocale "%X" (toUTCTime (time e))),
115                ("fn"     , path e),
116                ("path"   , path e)])
117               $ take 7 $ reverse $ sortBy (\a b -> compare (time a) (time b)) entries
118    ; cf <- fill "foot" []
119    ; return $ (ct, concat $ [ch, concat cs, cf])
120    } where
121        fill place params = fillFlavour "html" place (params ++ [("title"  , getConfig config "title"),
122                                                                 ("author" , getConfig config "author"),
123                                                                 ("version", "How I can get this version of GHC in program?")] ++ cgiparams)
124
125cgiMain :: CGI CGIResult
126cgiMain =  do
127    {
128    ; config  <- liftIO $ loadConfig "config"
129    ; home <- scriptName
130    ; pathinfo <- pathInfo
131    ; (ct, cb)  <- liftIO $ getResult [("home", home), ("pathinfo", pathinfo)] config
132    ; setHeader "Content-Type" $ ct
133    ; output $ cb
134    }
135
136main :: IO ()
137main =  runCGI $ handleErrors cgiMain
138
Note: See TracBrowser for help on using the browser.