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

Revision 1158, 3.3 kB (checked in by jknaoya, 6 years ago)

lang/haskell/blosxkel/blosxkel.hs:

blosxom の感じにあわせました。path は data とか拡張子とかふくまないように

  • 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
18import Text.Regex
19
20
21-- ref. http://i.loveruby.net/ja/stdhaskell/samples/lazylines/Template.hs.html
22fillFlavour :: String -> String -> [(String, String)] -> IO String
23fillFlavour flavour place params = return . fill =<< (readFile $ place ++ "." ++ flavour)
24    where
25        fill ""   = ""
26        fill tmpl = case break (== '$') tmpl of
27                         (s, ('$':cs)) -> s ++ expand var ++ fill cont
28                                          where (var, cont) = span isAlpha cs
29                         (s, cont)     -> s ++ fill cont
30
31        expand var = fromMaybe ('$':var) (lookup var params)
32
33
34data Entry = Entry {
35    file  :: FilePath,
36    path  :: String,
37    title :: String,
38    time  :: ClockTime,
39    body  :: [String]
40}
41
42
43getFileEntry :: String -> FilePath -> IO Entry
44getFileEntry d f = do
45    {
46    ; mtime <- getModificationTime f
47    ; cs    <- readFile f
48    ; case lines cs of
49        h:tl -> return $ Entry { file  = f
50                               , path  = dropExtension $ drop (length d) f
51                               , title = h
52                               , time  = mtime
53                               , body  = tl
54                               }
55    }
56
57-- http://www.tom.sfc.keio.ac.jp/~sakai/2ch/1162902266.html
58getRecursiveContents :: FilePath -> IO [FilePath]
59getRecursiveContents fp = getDirectoryContents fp >>= mapM (fx fp) >>= return . concat
60    where
61       fx :: FilePath -> FilePath -> IO [FilePath]
62       fx bp "."  = return [bp]
63       fx bp ".." = return []
64       fx bp f    = do let np = bp ++ ('/':f)
65                       b <- doesDirectoryExist np
66                       if b then getRecursiveContents np
67                            else return [np]
68
69
70
71getTextFileEntries :: FilePath -> IO [Entry]
72getTextFileEntries d = do
73    {
74    ; fs <- getRecursiveContents d
75    ; es <- mapM (getFileEntry d) $ filter (isSuffixOf ".txt") fs
76    ; return es
77    }
78
79
80getResult :: [(String, String)] -> IO (String, String)
81getResult cgiparams = do
82    {
83    ; entries <- getTextFileEntries "data"
84    ; ct <- fill "content_type" []
85    ; ch <- fill "head" []
86    ; cs <- mapM
87               (\e -> fill "story"
88               [("title", title e),
89                ("body", concat (body e)),
90                ("time", formatCalendarTime defaultTimeLocale "%Y-%m-%d %H:%M:%S" (toUTCTime (time e))),
91                ("path", path e)])
92               $ take 7 $ reverse $ sortBy (\a b -> compare (time a) (time b)) entries
93    ; cf <- fill "foot" []
94    ; return $ (ct, concat $ [ch, concat cs, cf])
95    } where
96        fill place params = fillFlavour "html" place (params ++ [("title", "Blosxkel.hs"),
97                                                                 ("version", "aaa")] ++ cgiparams)
98
99cgiMain :: CGI CGIResult
100cgiMain =  do
101    {
102    ; home <- scriptName
103    ; pathinfo <- pathInfo
104    ; result <- liftIO $ getResult [("home", home), ("pathinfo", pathinfo)]
105    ; setHeader "Content-Type" $ fst result
106    ; output $ snd result
107    }
108
109main :: IO ()
110main =  runCGI $ handleErrors cgiMain
111
Note: See TracBrowser for help on using the browser.