twin/app/Main.hs

104 lines
3.7 KiB
Haskell
Raw Normal View History

2024-03-10 14:23:22 +01:00
{-# LANGUAGE GADTs #-}
2023-07-30 22:54:04 +02:00
module Main where
import System.Directory
import Options.Applicative
import Data.List
2024-03-09 02:52:59 +01:00
import Control.Exception
2024-03-10 14:23:22 +01:00
import Data.Ord
2023-07-30 22:54:04 +02:00
2023-07-31 16:09:45 +02:00
data CgiState = CgiSuccess
instance Show CgiState where
show CgiSuccess = "20 text/gemini; lang=en; charset=utf-8\r"
2023-07-31 00:29:26 +02:00
2024-03-10 14:23:22 +01:00
data Args where
2024-03-10 17:26:06 +01:00
Args :: { title :: String
, directory :: FilePath
, fileHead :: FilePath
, names :: Bool
, cgi :: Bool
, back :: String
, reverseSort :: Bool
, filename :: Bool
} -> Args
2023-07-30 22:54:04 +02:00
args :: Parser Args
args = Args
2023-07-31 16:09:45 +02:00
<$> strOption ( long "title" <> short 't' <> value "Title Left Blank" <> help "Document title" )
<*> strOption ( long "directory" <> short 'd' <> value "./" <> help "Directory to parse" )
<*> strOption ( long "header" <> short 'H' <> value "" <> help "Header text" )
2023-08-06 16:55:27 +02:00
-- <*> switch ( long "verbose" <> short 'v' <> help "Verbose mode")
2023-07-31 16:09:45 +02:00
<*> switch ( long "names" <> short 'n' <> help "Generate link names based on first of each document" )
<*> switch ( long "cgi" <> help "Output gemini file header")
2024-03-10 14:23:22 +01:00
<*> strOption ( long "back" <> short 'b' <> value "" <> help "Print 'return to dir' url")
<*> switch ( long "reverse" <> short 'r' <> help "Reverse sort order")
<*> switch ( long "filename" <> help "Prepend filename")
2023-07-30 22:54:04 +02:00
main :: IO ()
main = parseArgs =<< execParser opts
where
opts = info ( args <**> helper)
( fullDesc
2023-07-31 00:29:26 +02:00
<> progDesc "Generate gemini page index"
<> header "Generate a gemini page index")
2023-07-30 22:54:04 +02:00
parseArgs :: Args -> IO()
2023-08-06 16:55:27 +02:00
--parseArgs (Args t dir h v n c b) = do
2024-03-10 14:23:22 +01:00
parseArgs (Args t dir h genNames c backValue revOrder prependFile) = do
2023-08-05 01:23:06 +02:00
if c
then do print CgiSuccess
2023-07-31 14:32:56 +02:00
putStrLn $ "# " ++ t
2023-08-05 01:23:06 +02:00
else putStrLn $ "# " ++ t
2023-07-31 14:32:56 +02:00
if not (null h)
2023-08-05 01:23:06 +02:00
then putStr $ "\n" ++ h ++ "\n\n"
else putStr "\n"
2024-03-10 14:23:22 +01:00
if not (null backValue)
then do
generateList genNames prependFile dir revOrder
putStr "\n"
putStrLn $ "=> " ++ backValue ++ " Back"
else generateList genNames prependFile dir revOrder
2023-07-31 14:32:56 +02:00
2024-03-10 14:23:22 +01:00
generateList :: Bool -> Bool -> FilePath -> Bool -> IO ()
generateList genNames prependFile dir revOrder = do
dirContents <- (if revOrder then sortBy (comparing Down) else sort) . filter (isSuffixOf "gmi") <$> getDirectoryContents dir
mapM_ putStrLn =<< mapM (mkIndex genNames prependFile dir) dirContents
2023-07-31 16:09:45 +02:00
2024-03-10 14:23:22 +01:00
mkIndex :: Bool -> Bool -> FilePath -> FilePath -> IO String
2023-07-30 22:54:04 +02:00
2024-03-10 14:23:22 +01:00
mkIndex False _ dir file =
return $
"=> " ++ case dir of
"./" -> file
_ -> dir ++ "/" ++ file
-- a sane person should look over this fucking thing...
mkIndex True prependFile dir file =
let path = dir ++ "/" ++ file
basename = if prependFile
2024-03-10 17:26:06 +01:00
-- I wish I had BQNs Under modifier/combinator here...
2024-03-10 14:23:22 +01:00
then (" " ++) . reverse . drop 4 . reverse $ file
else ""
trim string
| length string >= 8 = appendDots . unwords . take 8 . cleanString $ string
| otherwise = unwords . cleanString $ string
where
-- remove all '#' signs and any potential resulting empty lists
cleanString = filter (/= "") . map (dropWhile (== '#'))
-- in case the last character is a dot, remove it
appendDots name
2024-03-10 14:23:22 +01:00
| last name == '.' = (++ "...") . reverse . dropWhile (== '.') . reverse $ name
| otherwise = name
in do
line <- trim . words . head . lines <$> readFile path
2024-03-10 14:23:22 +01:00
return $
"=> " ++ path ++ basename ++ " " ++ line
2024-03-09 02:52:59 +01:00
getFirstLine :: FilePath -> IO (Maybe String)
getFirstLine f = (Just <$> readFile f) `catch` handler
where
handler :: IOException -> IO (Maybe String)
handler _ = return Nothing