-
Notifications
You must be signed in to change notification settings - Fork 2
/
Block.hs
63 lines (54 loc) · 1.63 KB
/
Block.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
-- | A block of code
{-# LANGUAGE OverloadedStrings #-}
module HStyle.Block
( Block
, fromText
, prettyBlock
, toLines
, subBlock
, perLine
, absoluteLineNumber
) where
import Data.Text (Text)
import Data.Vector (Vector)
import qualified Data.Vector as V
import qualified Data.Text as T
data Block = Block
{ blockOffset :: Int
, blockLines :: Vector Text
} deriving (Show)
fromText :: Text -> Block
fromText text = Block
{ blockOffset = 0
, blockLines = V.fromList $ T.lines text
}
prettyBlock :: Block -> Text
prettyBlock block = T.unlines $ map pretty $
zip [offset + 1 ..] $ V.toList lines'
where
offset = blockOffset block
lines' = blockLines block
width = length $ show (offset + V.length lines')
pretty (ln, t) =
let ln' = T.pack (show ln)
lnl = T.length ln'
in T.replicate (width - lnl) " " `T.append`
ln' `T.append` " " `T.append` t
toLines :: Block -> [Text]
toLines = V.toList . blockLines
-- | Subblock from start to end -- including both.
subBlock :: Int -> Int -> Block -> Block
subBlock start end block = Block
{ blockOffset = blockOffset block + start - 1
, blockLines = V.slice (start - 1) (end - start + 1) $ blockLines block
}
-- | Create a new block for every line.
perLine :: Block -> [Block]
perLine (Block offset lines') = map line $
zip [offset + 0 ..] $ V.toList lines'
where
line (i, t) = Block i $ V.singleton t
-- | Convert relative line number (within this block, 1-based) to an absolute
-- line number
absoluteLineNumber :: Int -> Block -> Int
absoluteLineNumber i = (+ i) . blockOffset