1{-# LANGUAGE OverloadedStrings #-}
3module Links (links) where
5import Control.Applicative
6import Control.DeepSeq (NFData(..))
7import Criterion.Main (Benchmark, bench, nf)
8import Data.Attoparsec.ByteString as A
9import Data.Attoparsec.ByteString.Char8 as A8
10import Data.ByteString.Char8 as B8
14 , linkParams :: [(ByteString, ByteString)]
17instance NFData Link where
18 rnf l = rnf (linkURL l) `seq` rnf (linkParams l)
21link = Link <$> url <*> many (char8 ';' *> skipSpace *> param)
22 where url = char8 '<' *> A8.takeTill (=='>') <* char8 '>' <* skipSpace
24param :: Parser (ByteString, ByteString)
27 skipSpace *> "=" *> skipSpace
29 let isTokenChar = A.inClass "!#$%&'()*+./0-9:<=>?@a-zA-Z[]^_`{|}~-"
32 _ -> A.takeWhile isTokenChar
36data Quot = Literal | Backslash
38quotedString :: Parser ByteString
39quotedString = char '"' *> (fixup <$> body) <* char '"'
40 where body = A8.scan Literal $ \s c ->
42 (Literal, '\\') -> backslash
43 (Literal, '"') -> Nothing
45 literal = Just Literal
46 backslash = Just Backslash
47 fixup = B8.pack . go . B8.unpack
48 where go ('\\' : x@'\\' : xs) = x : go xs
49 go ('\\' : x@'"' : xs) = x : go xs
50 go (x : xs) = x : go xs
53paramName :: Parser ByteString
55 name <- A.takeWhile1 $ A.inClass "a-zA-Z0-9!#$&+-.^_`|~"
58 Just '*' -> B8.snoc name '*'
62links = bench "links" $ nf (A.parseOnly link) lnk
63 where lnk = "<https://api.github.com/search/code?q=addClass+user%3Amozilla&page=2>; rel=\"next\", <https://api.github.com/search/code?q=addClass+user%3Amozilla&page=34>; rel=\"last\""
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