11{-# LANGUAGE CPP #-}
2+ {-# LANGUAGE DerivingStrategies #-}
3+ {-# LANGUAGE GeneralizedNewtypeDeriving #-}
4+ {-# LANGUAGE LambdaCase #-}
25{-# LANGUAGE OverloadedStrings #-}
36{-# LANGUAGE ViewPatterns #-}
47module Text.Markdown.Unlit (
@@ -9,19 +12,22 @@ module Text.Markdown.Unlit (
912, CodeBlock (.. )
1013, parse
1114#ifdef TEST
15+ , parseReorderingKey
1216, parseClasses
1317#endif
1418) where
1519
1620import Prelude ()
1721import Prelude.Compat
18- import Data.Maybe
19- import Data.List.Compat
22+ import Control.Arrow
2023import Data.Char
24+ import Data.List.Compat
25+ import Data.Maybe
2126import Data.String
22- import System.IO
23- import System.Exit
2427import System.Environment
28+ import System.Exit
29+ import System.IO
30+ import Text.Read
2531
2632fenceChars :: [Char ]
2733fenceChars = [' `' , ' ~' ]
@@ -43,7 +49,7 @@ run args =
4349 -- #line 1 "label"
4450 --
4551 case break (== " -h" ) args of
46- (mkSelector -> selector, " -h" : foo ) -> case foo of
52+ (mkSelector -> selector, " -h" : files ) -> case files of
4753 [src, cur, dst] -> do
4854 readFileUtf8 cur >>= writeFileUtf8 dst . unlit src selector
4955 [src] -> do
@@ -70,20 +76,48 @@ run args =
7076 writeUtf8 handle str = hSetEncoding handle utf8 >> hPutStr handle str
7177
7278unlit :: FilePath -> Selector -> String -> String
73- unlit src selector = unlines . concatMap formatCB . filter (toP selector . codeBlockClasses) . parse
79+ unlit src selector = unlines . concatMap formatCodeBlock . sortCodeBlocks . filter (toPredicate selector . codeBlockClasses) . parse
7480 where
75- formatCB :: CodeBlock -> [String ]
76- formatCB cb = (" #line " ++ show (codeBlockStartLine cb) ++ " " ++ show src) : codeBlockContent cb
81+ formatCodeBlock :: CodeBlock -> [String ]
82+ formatCodeBlock cb = (" #line " ++ show (codeBlockStartLine cb) ++ " " ++ show src) : codeBlockContent cb
7783
78- toP :: Selector -> [String ] -> Bool
79- toP = go
84+ sortCodeBlocks :: [CodeBlock ] -> [CodeBlock ]
85+ sortCodeBlocks = map fst . sortOn snd . addSortKey
86+ where
87+ addSortKey :: [CodeBlock ] -> [(CodeBlock , (ReorderingKey , DeclarationOrder ))]
88+ addSortKey = zipWith ((id &&& ) . sortKey) [0 .. ]
89+
90+ sortKey :: a -> CodeBlock -> (ReorderingKey , a )
91+ sortKey n code = (reorderingKey code, n)
92+
93+ toPredicate :: Selector -> [String ] -> Bool
94+ toPredicate = go
8095 where
8196 go s = case s of
8297 Class c -> elem c
8398 Not p -> not . go p
8499 a :&: b -> (&&) <$> go a <*> go b
85100 a :|: b -> (||) <$> go a <*> go b
86101
102+ newtype DeclarationOrder = DeclarationOrder Int
103+ deriving newtype (Eq , Ord , Enum , Num )
104+
105+ newtype ReorderingKey = ReorderingKey Int
106+ deriving newtype (Eq , Show , Read , Ord , Bounded , Num )
107+
108+ reorderingKey :: CodeBlock -> ReorderingKey
109+ reorderingKey = parseReorderingKey . codeBlockClasses
110+
111+ parseReorderingKey :: [String ] -> ReorderingKey
112+ parseReorderingKey = go
113+ where
114+ go :: [String ] -> ReorderingKey
115+ go = \ case
116+ [] -> 0
117+ " top" : _ -> minBound
118+ (' t' : ' o' : ' p' : ' :' : (readMaybe -> Just n)) : _ -> minBound + n
119+ _ : classes -> go classes
120+
87121infixr 3 :&:
88122infixr 2 :|:
89123
0 commit comments