1{-# OPTIONS_GHC -Wall -fno-warn-name-shadowing #-}
2{-# LANGUAGE BangPatterns, EmptyDataDecls #-}
18import Prelude hiding (String)
19import qualified Data.ByteString.Builder as B
20import qualified Data.Coerce as Coerce
21import qualified Data.Name as Name
22import qualified Data.Utf8 as Utf8
23import Data.Utf8 (MBA, newByteArray, copyFromPtr, freeze, writeWord8)
24import Data.Word (Word8)
25import Foreign.Ptr (Ptr, plusPtr, minusPtr)
26import Foreign.ForeignPtr (withForeignPtr)
27import GHC.Exts (RealWorld)
28import GHC.IO (stToIO, unsafeDupablePerformIO, unsafePerformIO)
31import qualified Parse.Primitives as P
38-- INVARIANT: any Json.String is appropriately escaped already
39-- TODO: is this the right representation for Json.String? Maybe ByteString instead?
52fromPtr :: Ptr Word8 -> Ptr Word8 -> String
57fromChars :: [Char] -> String
62fromSnippet :: P.Snippet -> String
67fromName :: Name.Name -> String
76toChars :: String -> [Char]
81{-# INLINE toBuilder #-}
82toBuilder :: String -> B.Builder
91fromComment :: P.Snippet -> String
92fromComment (P.Snippet fptr off len _ _) =
93 unsafePerformIO $ withForeignPtr fptr $ \ptr ->
95 !pos = plusPtr ptr off
96 !end = plusPtr pos len
97 !str = fromChunks (chompChunks pos end pos [])
102chompChunks :: Ptr Word8 -> Ptr Word8 -> Ptr Word8 -> [Chunk] -> [Chunk]
103chompChunks pos end start revChunks =
105 reverse (addSlice start end revChunks)
108 !word = P.unsafeIndex pos
111 0x0A {-\n-} -> chompEscape 0x6E {-n-} pos end start revChunks
112 0x22 {-"-} -> chompEscape 0x22 {-"-} pos end start revChunks
113 0x27 {-'-} -> chompEscape 0x27 {-'-} pos end start revChunks
114 0x5C {-\-} -> chompEscape 0x5C {-\-} pos end start revChunks
117 !newPos = plusPtr pos 1
119 chompChunks newPos end newPos (addSlice start pos revChunks)
123 !width = P.getCharWidth pos end word
124 !newPos = plusPtr pos width
126 chompChunks newPos end start revChunks
129chompEscape :: Word8 -> Ptr Word8 -> Ptr Word8 -> Ptr Word8 -> [Chunk] -> [Chunk]
130chompEscape escape pos end start revChunks =
132 !pos1 = plusPtr pos 1
134 chompChunks pos1 end pos1 (Escape escape : addSlice start pos revChunks)
137addSlice :: Ptr Word8 -> Ptr Word8 -> [Chunk] -> [Chunk]
138addSlice start end revChunks =
141 else Slice start (minusPtr end start) : revChunks
149 = Slice (Ptr Word8) Int
153fromChunks :: [Chunk] -> String
155 unsafeDupablePerformIO (stToIO (
156 do let !len = sum (map chunkToWidth chunks)
157 mba <- newByteArray len
158 writeChunks mba 0 chunks
163chunkToWidth :: Chunk -> Int
170writeChunks :: MBA RealWorld -> Int -> [Chunk] -> ST RealWorld ()
171writeChunks mba offset chunks =
179 do copyFromPtr ptr mba offset len
180 let !newOffset = offset + len
181 writeChunks mba newOffset chunks
184 do writeWord8 mba offset 0x5C {- \ -}
185 writeWord8 mba (offset + 1) word
186 let !newOffset = offset + 2
187 writeChunks mba newOffset chunks
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list