2022-10-26 09:57:55 +00:00
|
|
|
module Main where
|
|
|
|
|
2022-10-27 10:20:36 +00:00
|
|
|
import Control.Applicative hiding (some)
|
|
|
|
import Control.Monad
|
|
|
|
import Data.Functor
|
|
|
|
import Data.Void
|
|
|
|
import System.Environment
|
|
|
|
import System.Exit
|
2022-10-28 11:29:21 +00:00
|
|
|
import Text.Megaparsec
|
2022-10-27 10:20:36 +00:00
|
|
|
import Text.Megaparsec.Char
|
2022-10-26 10:37:48 +00:00
|
|
|
|
2022-10-26 22:15:32 +00:00
|
|
|
type Parser = Parsec Void String
|
2022-10-26 11:59:46 +00:00
|
|
|
|
2022-10-30 18:14:23 +00:00
|
|
|
data URL = Img String | Vid String | Website String
|
|
|
|
deriving (Show)
|
2022-10-28 10:55:46 +00:00
|
|
|
|
|
|
|
data Info =
|
|
|
|
Bread String |
|
|
|
|
List [Info] |
|
|
|
|
Header String |
|
|
|
|
Subheader String |
|
|
|
|
Subsubheader String |
|
|
|
|
Image URL |
|
|
|
|
Video URL |
|
|
|
|
Link URL Info |
|
2022-10-29 09:32:41 +00:00
|
|
|
Spoiler [Info]
|
2022-10-28 10:55:46 +00:00
|
|
|
|
|
|
|
instance Show Info where
|
|
|
|
show :: Info -> String
|
|
|
|
show info = case info of
|
2022-10-29 09:57:43 +00:00
|
|
|
Bread text -> text ++ "\n"
|
|
|
|
List texts -> "[LIST]" ++ concatMap ((++) "[*] " . show) texts ++ "[/LIST]\n"
|
|
|
|
Header text -> "[TITLE]" ++ text ++ "[/TITLE]\n"
|
|
|
|
Subheader text -> "[SIZE=4]" ++ text ++ "[/SIZE]\n"
|
|
|
|
Subsubheader text -> "[SIZE=2]" ++ text ++ "[/SIZE]\n"
|
2022-10-30 18:14:23 +00:00
|
|
|
Image (Img url) -> "[IMG]" ++ url ++ "[/IMG]\n"
|
|
|
|
Video (Vid url) -> "[VIDEO]" ++ url ++ "[/VIDEO]\n"
|
|
|
|
Link (Website url) inf -> "[URL=\"" ++ url ++ "\"]" ++ show inf ++ "[/URL]\n"
|
2022-10-29 09:57:43 +00:00
|
|
|
Spoiler inf -> "[SPOILER]" ++ concatMap show inf ++ "[/SPOILER]\n"
|
2022-10-30 18:14:23 +00:00
|
|
|
_ -> error "Something went wrong with showing the parsed information"
|
2022-10-28 10:55:46 +00:00
|
|
|
|
|
|
|
newtype Post = Post [Info]
|
|
|
|
|
2022-10-28 11:29:21 +00:00
|
|
|
instance Show Post where
|
|
|
|
show :: Post -> String
|
|
|
|
show (Post a) = concatMap show a
|
|
|
|
|
2022-10-29 09:32:41 +00:00
|
|
|
reduce :: [Info] -> [Info]
|
|
|
|
reduce [] = []
|
|
|
|
reduce ((List x) : (List y) : xs) = reduce $ List (x++y) : xs
|
|
|
|
reduce ((Spoiler x) : (Spoiler y) : xs) = Spoiler (x++y) : reduce xs
|
|
|
|
reduce ((Spoiler x) : y : xs) = reduce $ Spoiler (reduce $ x ++ [y]) : xs
|
|
|
|
reduce (x:xs) = x: reduce xs
|
|
|
|
|
2022-10-28 11:29:21 +00:00
|
|
|
parseHelper :: Parser a -> String -> a
|
2022-10-26 22:26:14 +00:00
|
|
|
parseHelper parser x = case parse parser "" x of
|
|
|
|
Left bundle -> error $ errorBundlePretty bundle
|
2022-10-27 10:20:36 +00:00
|
|
|
Right text -> text
|
2022-10-26 22:26:14 +00:00
|
|
|
|
2022-10-28 11:29:21 +00:00
|
|
|
parseFile :: String -> Post
|
2022-10-29 09:44:52 +00:00
|
|
|
parseFile = Post . reduce . map (parseHelper fileParser) . dropWhile (/= "") . lines
|
2022-10-26 22:15:32 +00:00
|
|
|
|
2022-10-28 11:29:21 +00:00
|
|
|
fileParser :: Parser Info
|
2022-10-29 09:32:41 +00:00
|
|
|
fileParser =
|
|
|
|
try $
|
|
|
|
choice [
|
|
|
|
Header <$> (string' "* " >> takeRest),
|
|
|
|
Subheader <$> (string' "** " >> takeRest),
|
|
|
|
Subsubheader <$> (string' "*** " >> takeRest),
|
|
|
|
List . (: []) . Bread <$> (string' "- " >> takeRest),
|
|
|
|
-- Image and video needs to know if it is a image or video
|
2022-10-30 18:14:23 +00:00
|
|
|
Image <$> between (string' "[[") (string' "]]") parseLink,
|
|
|
|
Video <$> between (string' "[[") (string' "]]") parseLink,
|
|
|
|
-- (takeWhileP Nothing (/= ']')),
|
2022-10-29 09:44:52 +00:00
|
|
|
Spoiler . (: []) . Bread <$> (string' "#+BEGIN" >> return ""),
|
|
|
|
Spoiler . (: []) . Bread <$> (string' "#+END" >> return ""),
|
2022-10-29 09:32:41 +00:00
|
|
|
Bread <$> takeRest
|
|
|
|
]
|
|
|
|
|
2022-10-30 18:14:23 +00:00
|
|
|
parseLink :: Parser URL
|
|
|
|
parseLink = try $ choice [
|
|
|
|
do
|
|
|
|
scheme <- string' "https://"
|
|
|
|
auth <- takeWhileP Nothing (/= '/')
|
|
|
|
path <- takeWhileP Nothing (/= '.')
|
|
|
|
typ <- try $ string' ".jpg" <|> string ".jpeg" <|> string' ".png" <|> string ".gif"
|
|
|
|
return $ Img $ scheme ++ auth ++ path ++ typ,
|
|
|
|
do
|
|
|
|
scheme <- string' "https://"
|
|
|
|
auth <- try $ string' "youtu.be" <|> string' "youtube.com"
|
|
|
|
path <- takeRest
|
|
|
|
return $ Vid $ scheme ++ auth ++ path,
|
|
|
|
Website <$> takeRest
|
|
|
|
]
|
2022-10-26 10:03:45 +00:00
|
|
|
|
2022-10-28 11:29:21 +00:00
|
|
|
parseCli :: [String] -> IO Post
|
|
|
|
parseCli [] = return $ Post [usage]
|
2022-10-27 10:20:36 +00:00
|
|
|
parseCli [x] =
|
2022-10-26 13:29:48 +00:00
|
|
|
if head x /= '-'
|
|
|
|
then parseFile <$> readFile x
|
2022-10-26 22:26:14 +00:00
|
|
|
else return $ useArgs $ parseHelper argParse x
|
|
|
|
parseCli [x, _] = return $ useArgs $ parseHelper argParse x
|
2022-10-27 10:20:36 +00:00
|
|
|
parseCli _ = fail "Too many arugemnts"
|
2022-10-26 10:37:48 +00:00
|
|
|
|
2022-10-26 22:15:32 +00:00
|
|
|
argParse :: Parser String
|
2022-10-27 10:20:36 +00:00
|
|
|
argParse = string "-" >> some alphaNumChar
|
2022-10-26 10:37:48 +00:00
|
|
|
|
2022-10-28 11:29:21 +00:00
|
|
|
useArgs :: String -> Post
|
|
|
|
useArgs [] = Post [Bread ""]
|
|
|
|
useArgs ('h' : _) = Post [usage]
|
|
|
|
useArgs ('v' : _) = Post [version]
|
2022-10-27 10:20:36 +00:00
|
|
|
useArgs (_ : xs) = useArgs xs
|
2022-10-26 10:37:48 +00:00
|
|
|
|
2022-10-28 11:29:21 +00:00
|
|
|
usage :: Info
|
|
|
|
usage = Bread "Usage: otm [-hv] [file]"
|
2022-10-26 13:29:48 +00:00
|
|
|
|
2022-10-28 11:29:21 +00:00
|
|
|
version :: Info
|
|
|
|
version = Bread "otm 0.1"
|
2022-10-26 22:26:14 +00:00
|
|
|
|
|
|
|
main :: IO ()
|
2022-10-28 11:29:21 +00:00
|
|
|
main = putStr . show =<< parseCli =<< getArgs
|