1 {-| 2 Module : unphone 3 Description : Convert partial-markdown using special phone-friendly markup to our regular "wiki-style" markdown. See "Phone Shortcuts" in DESIGN-CODE for full details. 4 Copyright : (c) Robin Lee Powell, 2016 5 License : MIT 6 Maintainer : rlpowell@digitalkingdom.org 7 Stability : experimental 8 Portability : POSIX 9 10 See "Phone Shortcuts" in DESIGN-CODE for full details. 11 12 -} 13 -------------------------------------------------------------------------------- 14 {-# LANGUAGE OverloadedStrings #-} 15 {-# LANGUAGE QuasiQuotes #-} 16 {-# LANGUAGE FlexibleContexts #-} 17 module Main where 18 import System.Directory (createDirectoryIfMissing, doesFileExist) 19 import System.FilePath 20 -- import System.Posix.Files 21 import System.Environment 22 import Text.Regex.PCRE.Heavy as PCRE 23 import System.FilePath.Find 24 import HBlog.Lib 25 26 -------------------------------------------------------------------------------- 27 main :: IO () 28 main = do 29 args <- getArgs 30 case args of 31 indir:outdir:[] -> maybeTree indir outdir 32 _ -> putStrLn "Need exactly two arguments, input directory and output directory." 33 34 maybeTree :: String -> String -> IO () 35 maybeTree inthing outthing = do 36 isInFile <- doesFileExist inthing 37 if isInFile then 38 handleFile inthing outthing 39 else 40 walkTree inthing outthing 41 42 walkTree :: String -> String -> IO () 43 walkTree indir outdir = do 44 files <- find always (extension ==? ".md") indir 45 _ <- mapM (handleFileAndDir indir outdir) files 46 return () 47 48 handleFileAndDir :: FilePath -> FilePath -> FilePath -> IO () 49 handleFileAndDir indir outdir fname = do 50 let shortname = makeRelative indir fname 51 _ <- createDirectoryIfMissing True (takeDirectory $ (outdir </> shortname)) 52 handleFile (indir </> shortname) (outdir </> shortname) 53 54 handleFile :: FilePath -> FilePath -> IO () 55 handleFile infile outfile = do 56 body <- readFile $ infile 57 let newBody = unPhone body in do 58 _ <- writeFile outfile newBody 59 return () 60 61 unPhone :: String -> String 62 unPhone oldBody = 63 if newBody == oldBody then 64 newBody 65 else 66 unPhone newBody 67 where 68 -- The list of gsubs starts at the bottom and works its way up 69 newBody = 70 -- Sub: qwl x qw [x](x) 71 PCRE.gsub [caselessre|(\s+)qwl\s+(.*?)\s+qw(\s+|[.,;]|$)|] sub_link_no_desc $ 72 -- Sub: qwl x qwu y qw [x](y) 73 PCRE.gsub [caselessre|(\s+)qwl\s+(.*?)\s+qwu\s+(.*?)\s+qw(\s+|[.,;]|$)|] sub_link_with_desc $ 74 oldBody 75 sub_link_no_desc :: [String] -> String 76 sub_link_no_desc (ls:url:ts:_) = mconcat [ ls, "[", url, "]", "(", url, ")", ts ] :: String 77 sub_link_no_desc _ = error "Called regex function sub_link_no_desc with the wrong stuff in unphone; this is a bug in either Text.Regex.PCRE.Heavy or Text.Regex.PCRE.Light" 78 sub_link_with_desc :: [String] -> String 79 sub_link_with_desc (ls:text:url:ts:_) = mconcat [ ls, "[", text, "]", "(", url, ")", ts ] :: String 80 sub_link_with_desc _ = error "Called regex function sub_link_with_desc with the wrong stuff in unphone; this is a bug in either Text.Regex.PCRE.Heavy or Text.Regex.PCRE.Light"