@@ -51,7 +51,7 @@ import qualified Json.Encode as Encode
52data Name =
52data Name =
54− { _user :: !Text
54+ { _author :: !Text
55 , _project :: !Text
55 , _project :: !Text
57 deriving (Eq, Ord)
57 deriving (Eq, Ord)
@@ -70,8 +70,8 @@ data Package =
72isKernel :: Name -> Bool
72isKernel :: Name -> Bool
73−isKernel (Name user _) =
73+isKernel (Name author _) =
74− user == "elm-lang" || user == "elm-explorations"
74+ author == "elm-lang" || author == "elm-explorations"
77toString :: Name -> String
77toString :: Name -> String
@@ -80,54 +80,92 @@ toString name =
82toText :: Name -> Text
82toText :: Name -> Text
83−toText (Name user project) =
83+toText (Name author project) =
84− user <> "/" <> project
84+ author <> "/" <> project
87toUrl :: Name -> String
87toUrl :: Name -> String
88−toUrl (Name user project) =
88+toUrl (Name author project) =
89− Text.unpack user ++ "/" ++ Text.unpack project
89+ Text.unpack author ++ "/" ++ Text.unpack project
92toFilePath :: Name -> FilePath
92toFilePath :: Name -> FilePath
93−toFilePath (Name user project) =
93+toFilePath (Name author project) =
94− Text.unpack user </> Text.unpack project
94+ Text.unpack author </> Text.unpack project
97−fromText :: Text -> Either String Name
97+fromText :: Text -> Either (String, [String]) Name
98fromText text =
98fromText text =
99 case Text.splitOn "/" text of
99 case Text.splitOn "/" text of
100− [ user, project ] | not (Text.null user || Text.null project) ->
100+ [ author, project ] | not (Text.null author || Text.null project) ->
101− Name user <$> validateProjectName project
101+ Name author <$> validateProjectName project
104− Left "A valid project name looks like `user/project`"
105+ ( "A valid package name looks like \"author/project\" requiring the author and project name together."
107−validateProjectName :: Text -> Either String Text
110+validateProjectName :: Text -> Either (String, [String]) Text
108validateProjectName text =
111validateProjectName text =
109 if Text.isInfixOf "--" text then
112 if Text.isInfixOf "--" text then
110− Left "There is a double dash -- in your package name. It must be a single dash."
113+ Left $ thisCannot "have two dashes in a row" text (Text.replace "--" "-" text)
112 else if Text.isInfixOf "_" text then
115 else if Text.isInfixOf "_" text then
113− Left "Underscores are not allowed in package names."
116+ Left $ thisCannot "have underscores" text (Text.replace "_" "-" text)
115 else if Text.isInfixOf "." text then
118 else if Text.isInfixOf "." text then
116− Left "Dots are not allowed in package names."
119+ Left $ thisCannot "have dots" text (Text.replace "." "-" text)
118 else if Text.any Char.isUpper text then
121 else if Text.any Char.isUpper text then
119− Left "Upper case characters are not allowed in package names."
122+ Left $ thisCannot "have upper case letters" text (decap text)
121 else if not (Char.isLetter (Text.head text)) then
124 else if not (Char.isLetter (Text.head text)) then
122− Left "Package names must start with a letter."
125+ Left
126+ ( "The project name \"" ++ Text.unpack text ++ "\" must start with a letter. Is there another name that captures what your package is for?"
124 else if Text.isSuffixOf "-" text then
130 else if Text.isSuffixOf "-" text then
125− Left "Package names cannot end with a dash."
131+ Left $ thisCannot "end with a dash" text (Text.dropEnd 1 text)
128 Right text
134 Right text
137+thisCannot :: String -> Text -> Text -> (String, [String])
138+thisCannot beLikeThis problemName suggestedName =
139+ let name = Text.unpack suggestedName in
141+ "The project name \"" ++ Text.unpack problemName ++ "\" cannot "
142+ ++ beLikeThis ++ ". Try something like \"" ++ name ++ "\" instead?"
148+decap :: Text -> Text
152+ uncurry (:) (Text.foldr gatherCaps ([],[]) text)
155+ if any (\c -> length c == 1) chunks then
158+ List.intercalate "-" chunks
161+gatherCaps :: Char -> (String, [String]) -> (String, [String])
162+gatherCaps char (buffer, chunks) =
163+ if Char.isUpper char then
164+ ( [], (Char.toLower char : buffer) : chunks )
166+ (char:buffer, chunks)
132-- COMMON PACKAGE NAMES
170-- COMMON PACKAGE NAMES
@@ -135,7 +173,7 @@ validateProjectName text =
135{-# NOINLINE dummyName #-}
173{-# NOINLINE dummyName #-}
136dummyName :: Name
174dummyName :: Name
137dummyName =
175dummyName =
138− Name "user" "project"
176+ Name "author" "project"
141{-# NOINLINE kernel #-}
179{-# NOINLINE kernel #-}
@@ -316,8 +354,8 @@ instance Binary Name where
317 liftM2 Name get get
355 liftM2 Name get get
319− put (Name user project) =
357+ put (Name author project) =
320− do put user
358+ do put author
321 put project
359 put project
@@ -363,7 +401,7 @@ decoder =
363 Right name ->
401 Right name ->
364 Decode.succeed name
402 Decode.succeed name
366− Left msg ->
404+ Left (msg, _) ->
367 Decode.fail msg
405 Decode.fail msg