1{-# OPTIONS_GHC -Wall #-}
2{-# LANGUAGE OverloadedStrings #-}
6 , dummyName, core, browser, virtualDom, html, webgl, linearAlgebra
7 , toString, toText, toUrl, toFilePath
10 , initialVersion, dummyVersion
11 , bumpPatch, bumpMinor, bumpMajor
12 , filterLatest, majorAndMinor
13 , versionToString, versionToText, versionFromText
22import Control.Monad (liftM, liftM2, liftM3)
23import Data.Binary (Binary, get, getWord8, put, putWord8)
24import qualified Data.Char as Char
25import Data.Function (on)
26import qualified Data.List as List
27import Data.Monoid ((<>))
28import qualified Data.Text as Text
29import qualified Data.Text.Read as Text
30import qualified Data.Text.Lazy as B (toStrict)
31import qualified Data.Text.Lazy.Builder as B (singleton, toLazyText)
32import qualified Data.Text.Lazy.Builder.Int as B (decimal)
33import Data.Text (Text)
34import Data.Word (Word16)
35import System.FilePath ((</>))
36import qualified Json.Decode as Decode
37import qualified Json.Encode as Encode
55 , _version :: !Version
67 Name "elm-lang" "core"
72 Name "elm-lang" "browser"
77 Name "elm-lang" "virtual-dom"
82 Name "elm-lang" "html"
87 Name "elm-community" "webgl"
92 Name "elm-community" "linear-algebra"
95toString :: Name -> String
97 Text.unpack (toText name)
100toText :: Name -> Text
101toText (Name user project) =
102 user <> "/" <> project
105toUrl :: Name -> String
106toUrl (Name user project) =
107 Text.unpack user ++ "/" ++ Text.unpack project
110toFilePath :: Name -> FilePath
111toFilePath (Name user project) =
112 Text.unpack user </> Text.unpack project
115fromText :: Text -> Either String Name
117 case Text.splitOn "/" text of
118 [ user, project ] | not (Text.null user || Text.null project) ->
119 Name user <$> validateProjectName project
122 Left "A valid project name looks like `user/project`"
125validateProjectName :: Text -> Either String Text
126validateProjectName text =
127 if Text.isInfixOf "--" text then
128 Left "There is a double dash -- in your package name. It must be a single dash."
130 else if Text.isInfixOf "_" text then
131 Left "Underscores are not allowed in package names."
133 else if Text.isInfixOf "." text then
134 Left "Dots are not allowed in package names."
136 else if Text.any Char.isUpper text then
137 Left "Upper case characters are not allowed in package names."
139 else if not (Char.isLetter (Text.head text)) then
140 Left "Package names must start with a letter."
142 else if Text.isSuffixOf "-" text then
143 Left "Package names cannot end with a dash."
155 { _major :: {-# UNPACK #-} !Word16
156 , _minor :: {-# UNPACK #-} !Word16
157 , _patch :: {-# UNPACK #-} !Word16
162initialVersion :: Version
166dummyVersion :: Version
171bumpPatch :: Version -> Version
172bumpPatch (Version major minor patch) =
173 Version major minor (patch + 1)
176bumpMinor :: Version -> Version
177bumpMinor (Version major minor _patch) =
178 Version major (minor + 1) 0
181bumpMajor :: Version -> Version
182bumpMajor (Version major _minor _patch) =
183 Version (major + 1) 0 0
190filterLatest :: (Ord a) => (Version -> a) -> [Version] -> [Version]
191filterLatest characteristic versions =
192 map last (List.groupBy ((==) `on` characteristic) (List.sort versions))
195majorAndMinor :: Version -> ( Int, Int )
196majorAndMinor (Version major minor _patch) =
197 ( fromIntegral major, fromIntegral minor )
204versionToString :: Version -> String
205versionToString version =
206 Text.unpack (versionToText version)
209versionToText :: Version -> Text
210versionToText (Version major minor patch) =
211 B.toStrict $ B.toLazyText $
219versionFromText :: Text -> Either String Version
220versionFromText text =
221 case Text.splitOn "." text of
222 [major, minor, patch] ->
229 Left "Must have format MAJOR.MINOR.PATCH (e.g. 1.0.2)"
232toNumber :: Text -> Either String Word16
234 case Text.decimal txt of
239 Left "Must have format MAJOR.MINOR.PATCH (e.g. 1.0.2)"
246instance Binary Name where
250 put (Name user project) =
255instance Binary Package where
257 liftM2 Package get get
259 put (Package name version) =
264instance Binary Version where
268 then liftM3 Version get get get
270 do minor <- liftM fromIntegral getWord8
271 patch <- liftM fromIntegral getWord8
272 return (Version (fromIntegral word) minor patch)
274 put (Version major minor patch) =
275 if major < 256 && minor < 256 && patch < 256 then
276 do putWord8 (fromIntegral major)
277 putWord8 (fromIntegral minor)
278 putWord8 (fromIntegral patch)
290decoder :: Decode.Decoder Name
292 do txt <- Decode.text
295 Decode.fail $ "Expecting a PACKAGE name. " ++ msg
301encode :: Name -> Encode.Value
303 Encode.text (toText name)
307versionDecoder :: Decode.Decoder Version
309 do txt <- Decode.text
310 case versionFromText txt of
312 Decode.succeed version
315 Decode.fail $ "Expecting a VERSION. " ++ msg
318encodeVersion :: Version -> Encode.Value
319encodeVersion version =
320 Encode.text (versionToText version)
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