+ -- | A list of characters valid in a Twitter username.
+ --
+ username_chars :: String
+ username_chars = ['a'..'z'] ++ ['A'..'Z'] ++ ['0'..'9'] ++ "_"
+
+ -- | Take a string and drop everything (including the \'@\') up to
+ -- the first character of the first username (if one exists).
+ --
+ start_name :: String -> String
+ start_name w =
+ case dropWhile (/= '@') w of
+ [] -> []
+ (_:xs) -> xs
+
+ parse_userchars :: String -> String
+ parse_userchars = takeWhile (`elem` username_chars)
+
+ -- | Parse a username from the given String by dropping all
+ -- characters that don't belong to it. This function calls
+ -- itself recursively until it gets a username or runs out of
+ -- string.
+ --
+ parse_name :: String -> String
+ parse_name [] = []
+ parse_name rest@(_:xs) =
+ let ucs = (parse_userchars . start_name) rest in
+ case ucs of
+ [] -> parse_name xs
+ _ -> ucs
+
+ parse_result :: String
+ parse_result = parse_name s