1
1
{-# LANGUAGE CPP #-}
2
+ {-# LANGUAGE DerivingStrategies #-}
3
+ {-# LANGUAGE GeneralizedNewtypeDeriving #-}
4
+ {-# LANGUAGE LambdaCase #-}
2
5
{-# LANGUAGE OverloadedStrings #-}
3
6
{-# LANGUAGE ViewPatterns #-}
4
7
module Text.Markdown.Unlit (
@@ -9,19 +12,22 @@ module Text.Markdown.Unlit (
9
12
, CodeBlock (.. )
10
13
, parse
11
14
#ifdef TEST
15
+ , parseReorderingKey
12
16
, parseClasses
13
17
#endif
14
18
) where
15
19
16
20
import Prelude ()
17
21
import Prelude.Compat
18
- import Data.Maybe
19
- import Data.List.Compat
22
+ import Control.Arrow
20
23
import Data.Char
24
+ import Data.List.Compat
25
+ import Data.Maybe
21
26
import Data.String
22
- import System.IO
23
- import System.Exit
24
27
import System.Environment
28
+ import System.Exit
29
+ import System.IO
30
+ import Text.Read
25
31
26
32
fenceChars :: [Char ]
27
33
fenceChars = [' `' , ' ~' ]
@@ -43,7 +49,7 @@ run args =
43
49
-- #line 1 "label"
44
50
--
45
51
case break (== " -h" ) args of
46
- (mkSelector -> selector, " -h" : foo ) -> case foo of
52
+ (mkSelector -> selector, " -h" : files ) -> case files of
47
53
[src, cur, dst] -> do
48
54
readFileUtf8 cur >>= writeFileUtf8 dst . unlit src selector
49
55
[src] -> do
@@ -70,20 +76,48 @@ run args =
70
76
writeUtf8 handle str = hSetEncoding handle utf8 >> hPutStr handle str
71
77
72
78
unlit :: 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
74
80
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
77
83
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
80
95
where
81
96
go s = case s of
82
97
Class c -> elem c
83
98
Not p -> not . go p
84
99
a :&: b -> (&&) <$> go a <*> go b
85
100
a :|: b -> (||) <$> go a <*> go b
86
101
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
+
87
121
infixr 3 :&:
88
122
infixr 2 :|:
89
123
0 commit comments