packages feed

tweet-hs 0.6.0.1 → 0.6.1.2

raw patch · 13 files changed

+287/−197 lines, 13 filesdep −hspec-megaparsecdep ~megaparsecPVP ok

version bump matches the API change (PVP)

Dependencies removed: hspec-megaparsec

Dependency ranges changed: megaparsec

API changes (from Hackage documentation)

+ Web.Tweet: bird :: String
+ Web.Tweet: mute :: String -> FilePath -> IO ()
+ Web.Tweet: muteUserRaw :: String -> FilePath -> IO ByteString
+ Web.Tweet: unmute :: String -> FilePath -> IO ()
+ Web.Tweet: unmuteUserRaw :: String -> FilePath -> IO ByteString
+ Web.Tweet.Exec: Mute :: String -> Command
+ Web.Tweet.Exec: Unmute :: String -> Command
+ Web.Tweet.Parser.FastParser: fromFast :: FastTweet -> TweetEntity

Files

README.md view
@@ -76,13 +76,21 @@ ```  ### Sending tweets++To send a tweet:++```+tweet send "This is my tweet"+```++#### Input from stdin To tweet from stderr, run a command that pipes stderr to stdin, i.e.  ```-YOUR_BUILD_COMMAND 2>&1 >/dev/null | tweet input+stack build &>/dev/null | tweet input ``` -The `tweet` executable reads from stdIn only, but you can view the options (replies, number of tweets to thread, etc.) with+The `tweet` executable reads from stdin only, but you can view the options (replies, number of tweets to thread, etc.) with  ``` tweet --help
bench/Bench.hs view
@@ -1,19 +1,17 @@ module Main where -import Criterion.Main-import Text.Megaparsec-import Web.Tweet.Parser-import Web.Tweet.Parser.FastParser-import qualified Data.ByteString as BS+import           Criterion.Main+import qualified Data.ByteString             as BS+import           Web.Tweet.Parser.FastParser -fun = parse parseTweet "" -fast = fastParse+setupEnv = BS.readFile "test/data" +fast = fmap (fmap fromFast) . fastParse+ main = do-    file <- BS.readFile "test/data"-    defaultMain [ bgroup "parseTweet"-                      [ bench "226" $ whnf fun file ]-                , bgroup "fastParser"+    defaultMain [+                env setupEnv $ \ ~file ->+                bgroup "fastParser"                       [ bench "226" $ whnf fast file ]                 ]
src/Web/Tweet.hs view
@@ -27,11 +27,14 @@     , signRequest     -- * Functions to generate a URL string from a `Tweet`     , urlString+    -- * Helper function to print a bird+    , bird     ) where      import Web.Tweet.Sign import Web.Tweet.API import Web.Tweet.Utils.API+import Web.Tweet.Utils import Web.Tweet.Types import Data.List.Split (chunksOf) import Control.Monad
src/Web/Tweet/API.hs view
@@ -70,6 +70,22 @@ showBest :: String -> Int -> Bool -> FilePath -> IO String showBest screenName n color = fmap (showTweets color . pure . (take n . hits)) . getAll screenName Nothing +-- | Mute a user given their screen name+mute :: String -> FilePath -> IO ()+mute = (fmap void) . muteUserRaw++-- | Unmute a user given their screen name+unmute :: String -> FilePath -> IO ()+unmute = (fmap void) . unmuteUserRaw++-- | Mute a user given their screen name+muteUserRaw :: String -> FilePath -> IO BSL.ByteString+muteUserRaw screenName = postRequest ("https://api.twitter.com/1.1/mutes/users/create.json?screen_name=" ++ screenName)++-- | Unmute a user given their screen name+unmuteUserRaw :: String -> FilePath -> IO BSL.ByteString+unmuteUserRaw screenName = postRequest ("https://api.twitter.com/1.1/mutes/users/destroy.json?screen_name=" ++ screenName)+ -- | Display user timeline showTimeline :: Int -> Bool -> FilePath -> IO String showTimeline count color = (fmap (showTweets color)) . getTimeline count 
src/Web/Tweet/Exec.hs view
@@ -3,14 +3,14 @@                       , Program (..)                       , Command (..)) where -import Web.Tweet-import Options.Applicative import qualified Data.ByteString.Lazy.Char8 as BSL-import Data.Monoid hiding (getAll)-import System.Directory-import Data.Maybe-import Paths_tweet_hs-import Data.Version+import           Data.Maybe+import           Data.Monoid                hiding (getAll)+import           Data.Version+import           Options.Applicative+import           Paths_tweet_hs+import           System.Directory+import           Web.Tweet  -- | Data type for our program: one optional path to a credential file, (optionally) the number of tweetInputs to make, the id of the status you're replying to, and a list of users you wish to mention. data Program = Program { subcommand :: Command , cred :: Maybe FilePath , color :: Bool }@@ -33,6 +33,8 @@     | Unfollow { screenName :: String }     | Block { screenName :: String }     | Unblock { screenName :: String }+    | Mute { screenName :: String }+    | Unmute { screenName :: String }     | Dump { screenName :: String }  -- | query twitter to post stdin with no fancy options@@ -51,7 +53,7 @@  -- | Executes parser exec :: IO ()-exec = execParser opts >>= select+exec = putStrLn bird >> execParser opts >>= select     where         versionInfo = infoOption ("tweet-hs version: " ++ showVersion version) (short 'v' <> long "version" <> help "Show version")         opts        = info (helper <*> versionInfo <*> program)@@ -62,8 +64,8 @@ -- | Executes program given parsed `Program` select :: Program -> IO () select (Program com maybeFile color) = case maybeFile of-    (Just file) -> selectCommand com color file-    _ -> selectCommand com color =<< (++ "/.cred") <$> getHomeDirectory+    (Just file) -> selectCommand com (not color) file+    _ -> selectCommand com (not color) =<< (++ "/.cred") <$> getHomeDirectory  -- | Executes subcommand given subcommand + filepath to configuration file selectCommand :: Command -> Bool -> FilePath -> IO ()@@ -109,6 +111,12 @@ selectCommand (Unblock screenName) color file = do     unblock screenName file     putStrLn ("..." ++ screenName ++ " unblocked successfully")+selectCommand (Mute screenName) color file = do+    mute screenName file+    putStrLn ("..." ++ screenName ++ " muted successfully")+selectCommand (Unmute screenName) color file = do+    unmute screenName file+    putStrLn ("..." ++ screenName ++ " unmuted successfully") selectCommand (Dump screenName) color file = BSL.putStrLn =<< (getProfileRaw screenName 3200 file Nothing)  -- | Parser to return a program datatype@@ -136,11 +144,12 @@         (long "cred"         <> short 'c'         <> metavar "CREDENTIALS"+        <> completer (bashCompleter "file -o plusdirs")         <> help "path to credentials"))     <*> switch         (long "color"         <> short 'l'-        <> help "Display timeline with colorized terminal output.")+        <> help "Turn off colorized terminal output.")  -- | Parser for the view subcommand timeline :: Parser Command@@ -215,7 +224,7 @@         <> short 'n'         <> metavar "NUM"         <> help "Number of tweetInputs to fetch, default 12"))-    <*> optional user +    <*> optional user  -- | Parser for the mention subcommand mentionsParser :: Parser Command
src/Web/Tweet/Parser.hs view
@@ -1,5 +1,4 @@ {-# LANGUAGE OverloadedStrings #-}--- FIXME make this module available under cabal file -- | Module containing parsers for tweet and response data. module Web.Tweet.Parser ( parseTweet                         , getData ) where@@ -12,6 +11,8 @@ import Data.Monoid import qualified Data.Map as M import Data.Maybe+import qualified Data.Text as T+import qualified Data.Text.Encoding as TE import Control.Monad  -- | Parse some number of tweets@@ -74,7 +75,7 @@     string $ "\"" <> str <> "\":"     open <- optional $ char '\"'     let forbidden = if isJust open then ("\\\"" :: String) else ("\\\"," :: String)-    want <- many $ parseHTMLChar <|> noneOf forbidden <|> specialChar '\"' <|> specialChar '/' <|> newlineChar <|> unicodeChar -- TODO modify parsec to make this parallel?+    want <- many $ parseHTMLChar <|> noneOf forbidden <|> specialChar '\"' <|> specialChar '/' <|> newlineChar <|> emojiChar <|> unicodeChar -- TODO modify parsec to make this parallel?     pure want  -- | Parse a newline@@ -90,6 +91,20 @@     num <- fromHex . filterEmoji . BS.pack . map (fromIntegral . fromEnum) <$> count 4 anyChar     pure . toEnum . fromIntegral $ num +emojiChar :: Parser Char+emojiChar = do+    string "\\ud"+    str1 <- count 3 anyChar+    str2 <- string "\\ud" >> count 3 anyChar+    let num = decodeUtf16 $ "d" <> str1 <> "d" <> str2+    pure . head $ num++decodeUtf16 = T.unpack . TE.decodeUtf16BE . BS.concat . go+    where+        go []             = []+        go (a:b:c:d:rest) = let sym = convert16 [a,b] [c,d] in sym : go rest+        convert16 x y = BS.pack [(read . ("0x"<>)) x, (read . ("0x"<>)) y]+ -- | helper function to ignore emoji filterEmoji str = if BS.head str == (fromIntegral . fromEnum $ 'd') then "FFFD" else str @@ -114,3 +129,4 @@ fromHex :: BS.ByteString -> Integer fromHex = fromRight . (parse (L.hexadecimal :: Parser Integer) "")     where fromRight (Right a) = a+          fromRight (Left x) = error (show x)
src/Web/Tweet/Parser/FastParser.hs view
@@ -1,32 +1,38 @@-{-# LANGUAGE DeriveGeneric     #-}+{-# LANGUAGE DeriveGeneric   #-}+{-# LANGUAGE RecordWildCards #-}  module Web.Tweet.Parser.FastParser ( fastParse+                                   , fromFast                                    , FastTweet (..)                                    ) where -import GHC.Generics-import Data.Aeson-import qualified Data.Text as T+import           Data.Aeson+import qualified Data.ByteString      as BS import qualified Data.ByteString.Lazy as BSL-import qualified Data.ByteString as BS---import Data.Vector+import           Data.Text            (unpack)+import qualified Data.Text            as T+import           GHC.Generics+import           Web.Tweet.Types      hiding (name, text)  data FastTweet = FastTweet-    { id :: !Int-    , text :: !T.Text-    , user :: User-    , quoted_status :: Maybe FastTweet-    , retweet_count :: !Int+    { id             :: !Int+    , text           :: !T.Text+    , user           :: User+    , quoted_status  :: Maybe FastTweet+    , retweet_count  :: !Int     , favorite_count :: !Int     } deriving (Generic, Eq, Show)  data User = User { name        :: !T.Text-                 , screen_name :: !T.Text } +                 , screen_name :: !T.Text }                  deriving (Generic, Eq, Show)  instance FromJSON FastTweet  instance FromJSON User -fastParse :: BS.ByteString -> Either String [FastTweet] -- (Vector FastTweet)+fromFast :: FastTweet -> TweetEntity+fromFast FastTweet{..} = TweetEntity (unpack text) (unpack . name $ user) (unpack . screen_name $ user) id (fmap fromFast quoted_status) retweet_count favorite_count++fastParse :: BS.ByteString -> Either String [FastTweet] fastParse = eitherDecode . BSL.fromStrict
src/Web/Tweet/Types.hs view
@@ -1,6 +1,5 @@ {-# LANGUAGE DeriveGeneric   #-} {-# LANGUAGE DeriveAnyClass  #-}-{-# LANGUAGE TemplateHaskell #-}  -- | Exports the `Tweet` type, a datatype for building tweets easily module Web.Tweet.Types where@@ -34,6 +33,42 @@ -- | Contains an 'OAuth' and a 'Credential'; encapsulates everything needed to sign a request. type Config = (OAuth, Credential) -makeLenses ''Tweet+-- | Lens for `Tweet` accessing the `status` field.+status :: Lens' Tweet String+status f tweet@Tweet { _status = str } = fmap (\str' -> tweet { _status = str'}) (f str) -makeLenses ''TweetEntity+-- | Lens for `Tweet` accessing the `handles` field.+handles :: Lens' Tweet [String]+handles f tweet@Tweet { _handles = hs } = fmap (\hs' -> tweet { _handles = hs'}) (f hs)++-- | Lens for `Tweet` accessing the `_replyID` field.+replyID :: Lens' Tweet (Maybe Int)+replyID f tweet@Tweet { _replyID = reply } = fmap (\reply' -> tweet { _replyID = reply'}) (f reply)++-- | Lens for `TweetEntity` accessing the `_text` field.+text :: Lens' TweetEntity String+text f tweet@TweetEntity { _text = txt } = fmap (\txt' -> tweet { _text = txt'}) (f txt)++-- | Lens for `TweetEntity` accessing the `_name` field.+name :: Lens' TweetEntity String+name f tweet@TweetEntity { _name = nam } = fmap (\nam' -> tweet { _name = nam'}) (f nam)++-- | Lens for `TweetEntity` accessing the `_screenName` field.+screenName :: Lens' TweetEntity String+screenName f tweet@TweetEntity { _screenName = scr } = fmap (\scr' -> tweet { _screenName = scr'}) (f scr)++-- | Lens for `TweetEntity` accessing the `_tweetId` field.+tweetId :: Lens' TweetEntity Int +tweetId f tweet@TweetEntity { _tweetId = tw } = fmap (\tw' -> tweet { _tweetId = tw'}) (f tw)++-- | Lens for `TweetEntity` accessing the `_quoted` field.+quoted :: Lens' TweetEntity (Maybe TweetEntity) +quoted f tweet@TweetEntity { _quoted = quot } = fmap (\quot' -> tweet { _quoted = quot'}) (f quot)++-- | Lens for `TweetEntity` accessing the `_retweets` field.+retweets :: Lens' TweetEntity Int +retweets f tweet@TweetEntity { _retweets = rts } = fmap (\rts' -> tweet { _retweets = rts'}) (f rts)++-- | Lens for `TweetEntity` accessing the `_favorites` field.+favorites :: Lens' TweetEntity Int +favorites f tweet@TweetEntity { _favorites = fav } = fmap (\fav' -> tweet { _favorites = fav'}) (f fav)
src/Web/Tweet/Utils.hs view
@@ -1,25 +1,28 @@ -- | Miscellaneous functions that don't fit the project directly module Web.Tweet.Utils (     hits+  , getTweetsFast   , getTweets   , displayTimeline   , displayTimelineColor   , lineByKey+  , bird   , getConfigData ) where -import qualified Data.ByteString.Char8 as BS-import qualified Data.ByteString as BS2-import Data.List-import Web.Tweet.Types-import Control.Lens hiding (noneOf)-import Web.Tweet.Utils.Colors-import Data.List.Extra-import Web.Tweet.Parser+import           Control.Lens                hiding (noneOf)+import qualified Data.ByteString             as BS2+import qualified Data.ByteString.Char8       as BS+import           Data.List+import           Data.List.Extra+import           Web.Tweet.Parser.FastParser hiding (text)+import           Web.Tweet.Parser+import           Web.Tweet.Types+import           Web.Tweet.Utils.Colors import Text.Megaparsec  -- | filter out retweets, and sort by most successful. hits :: Timeline -> Timeline-hits = sortTweets . filterRTs +hits = sortTweets . filterRTs  -- | Filter out retweets filterRTs :: Timeline -> Timeline@@ -33,87 +36,97 @@ getTweets :: BS2.ByteString -> Either (ParseError Char Dec) Timeline getTweets = parse parseTweet ""  +-- | Get a list of tweets from a response, returning author, favorites, retweets, and content.+-- This version uses aeson, which it's far faster, but also has worse error messages.+getTweetsFast :: BS2.ByteString -> Either String Timeline+getTweetsFast = fmap (fmap fromFast) . fastParse+ -- | Display Timeline without color displayTimeline :: Timeline -> String displayTimeline ((TweetEntity content user screenName idTweet Nothing rts fave):rest) = concat [user     , " ("     , screenName     , ")"-    ,":\n    " -    ,fixNewline content -    ,"\n    " -    ,"♥ " -    ,show fave -    ," ♺ " -    ,show rts +    ,":\n    "+    ,fixNewline content+    ,"\n    "+    , "💜"+    -- , "♥ "+    ,show fave+    , " \61561  "+    -- ," ♺ "+    ,show rts     , "  "     , show idTweet-    ,"\n\n" +    ,"\n\n"     ,displayTimeline rest]-displayTimeline ((TweetEntity content user screenName idTweet (Just quoted) rts fave):rest) = concat [user +displayTimeline ((TweetEntity content user screenName idTweet (Just quoted) rts fave):rest) = concat [user     , " ("     , screenName     , ")"-    , ":\n    " -    , fixNewline content -    , "\n    " -    , "♥ " -    , show fave -    , " ♺ " -    , show rts +    , ":\n    "+    , fixNewline content+    , "\n    "+    , "💜"+    , show fave+    , " \61561  "+    , show rts     , "  "     , show idTweet-    , "\n    " -    , _name quoted +    , "\n    "+    , _name quoted     , " ("     , _screenName quoted     , ")"-    , ": " -    , _text quoted -    , "\n\n" +    , ": "+    , _text quoted+    , "\n\n"     , displayTimeline rest] displayTimeline [] = [] +bird :: String+bird = toPlainBlue $ "🐦\n"+ -- | Display Timeline in color displayTimelineColor :: Timeline -> String-displayTimelineColor ((TweetEntity content user screenName idTweet Nothing rts fave):rest) = concat [toYellow user +displayTimelineColor ((TweetEntity content user screenName idTweet Nothing rts fave):rest) = concat [toYellow user     , " ("     , screenName     , ")"-    , ":\n    " +    , ":\n    "     , fixNewline content-    , "\n    " -    , toRed "♥"+    , "\n    "+    , toRed "💜"     , " "-    , show fave -    , toGreen " ♺ " -    , show rts +    , show fave+    , toGreen " \61561  " -- ♺ "+    , show rts     , "  "     , toBlue (show idTweet)-    , "\n\n" +    , "\n\n"     , displayTimelineColor rest]-displayTimelineColor ((TweetEntity content user screenName  idTweet (Just quoted) rts fave):rest) = concat [toYellow user +displayTimelineColor ((TweetEntity content user screenName  idTweet (Just quoted) rts fave):rest) = concat [toYellow user     , " ("     , screenName     , ")"-    , ":\n    " -    , fixNewline content -    , "\n    " -    , toRed "♥"+    , ":\n    "+    , fixNewline content+    , "\n    "+    , toRed "💜"     , " "-    , show fave -    , toGreen " ♺ " -    , show rts +    , show fave+    , toGreen " \61561  "+    , show rts     , "  "     , toBlue (show idTweet)-    , "\n    " -    , toYellow $ _name quoted +    , "\n    "+    , toYellow $ _name quoted     , " ("     , _screenName quoted     , ")"-    , ": " -    , _text quoted -    , "\n\n" +    , ": "+    , _text quoted+    , "\n\n"     , displayTimelineColor rest] displayTimelineColor [] = [] 
src/Web/Tweet/Utils/Colors.hs view
@@ -3,6 +3,8 @@  import Text.PrettyPrint.ANSI.Leijen +--  😎+ -- | Make a string red toRed :: String -> String toRed = show . dullred . text@@ -18,3 +20,7 @@ -- | Make a string blue toBlue :: String -> String toBlue = show . underline . dullblue . text++-- | Make a string blue; no underlining.+toPlainBlue :: String -> String+toPlainBlue = show . dullblue . text
stack.yaml view
@@ -1,66 +1,39 @@-# This file was automatically generated by 'stack init'-#-# Some commonly used options have been documented as comments in this file.-# For advanced use and comprehensive documentation of the format, please see:-# http://docs.haskellstack.org/en/stable/yaml_configuration/--# Resolver to choose a 'specific' stackage snapshot or a compiler version.-# A snapshot resolver dictates the compiler version and the set of packages-# to be used for project dependencies. For example:-#-# resolver: lts-3.5-# resolver: nightly-2015-09-21-# resolver: ghc-7.10.2-# resolver: ghcjs-0.1.0_ghc-7.10.2-# resolver:-#  name: custom-snapshot-#  location: "./custom-snapshot.yaml"-resolver: lts-8.20--# User packages to be built.-# Various formats can be used as shown in the example below.-#-# packages:-# - some-directory-# - https://example.com/foo/bar/baz-0.0.2.tar.gz-# - location:-#    git: https://github.com/commercialhaskell/stack.git-#    commit: e7b331f14bcffb8367cd58fbfc8b40ec7642100a-# - location: https://github.com/commercialhaskell/stack/commit/e7b331f14bcffb8367cd58fbfc8b40ec7642100a-#   extra-dep: true-#  subdirs:-#  - auto-update-#  - wai-#-# A package marked 'extra-dep: true' will only be built if demanded by a-# non-dependency (i.e. a user package), and its test suites and benchmarks-# will not be run. This is useful for tweaking upstream packages.+resolver: lts-8.19 packages:-- '.'-# Dependency packages to be pulled from upstream that are not in the resolver-# (e.g., acme-missiles-0.3)-extra-deps: []--# Override default flag values for local packages and extra-deps-flags: {}--# Extra package databases containing global packages-extra-package-dbs: []--# Control whether we use the GHC we find on the path-# system-ghc: true-#-# Require a specific version of stack, using version ranges-# require-stack-version: -any # Default-# require-stack-version: ">=1.4"-#-# Override the architecture used by stack, especially useful on Windows-# arch: i386-# arch: x86_64-#-# Extra directories used by stack for building-# extra-include-dirs: [/path/to/dir]-# extra-lib-dirs: [/path/to/dir]-#-# Allow a newer minor version of GHC than the snapshot specifies-# compiler-check: newer-minor+ - .+ - extra-dep: true+   location:+       git: https://github.com/haskell/deepseq+       commit: 0b22c9825ef79c1ee41d2f19e7c997f5cdc93494+ - extra-dep: true+   location:+       git: https://github.com/ekmett/semigroupoids.git+       commit: c3297f970658ae874db098190327ec742044a2e6+ - extra-dep: true+   location:+       git: http://github.com/ekmett/lens.git+       commit: 7031e00f62a704a86c3149c75c1e2afc059af022+ - extra-dep: true+   location:+       git: https://github.com/dreixel/syb.git+       commit: f584ecd525179778063df2eb02dc6bbe406d7e75+flags:+    tweet-hs:+        llvm-fast: true+        parallel-gc: false+ghc-options:+    tweet-hs: -fdiagnostics-color=always+allow-newer: true+compiler: ghc-8.2.0.20170507+compiler-check: match-exact+setup-info:+ ghc:+  linux64:+   8.2.0.20170507:+    url: https://downloads.haskell.org/~ghc/8.2.1-rc2/ghc-8.2.0.20170507-x86_64-deb8-linux.tar.xz+  macosx:+   8.2.0.20170507:+    url: https://downloads.haskell.org/~ghc/8.2.1-rc2/ghc-8.2.0.20170507-x86_64-apple-darwin.tar.xz+  windows64:+   8.2.0.20170507:+    url: https://downloads.haskell.org/~ghc/8.2.1-rc2/ghc-8.2.0.20170507-x86_64-unknown-mingw32.tar.xz
test/Spec.hs view
@@ -1,23 +1,12 @@ {-# LANGUAGE OverloadedStrings #-} -import Test.Hspec-import Test.Hspec.Megaparsec-import Text.Megaparsec-import Web.Tweet.Parser-import qualified Data.ByteString as BS----import Web.Tweet.Parser.FastParser+import qualified Data.ByteString             as BS+import           Test.Hspec+import           Web.Tweet.Parser.FastParser --- TODO make sure it's the right number of tweets as well main :: IO () main = hspec $ do-    describe "parseTweet" $ do-        file <- runIO $ BS.readFile "test/data"-        parallel $ it "parses sample tweets" $ do-            parse parseTweet "" `shouldSucceedOn` file-            {--     describe "fastParse" $ do         file <- runIO $ BS.readFile "test/data"         parallel $ it "parses sample tweets wrong" $ do-            fastParse "" `shouldBe` Left "some error idk"-            --}+            fastParse "" `shouldBe` Left "Error in $: not enough input"
tweet-hs.cabal view
@@ -1,5 +1,5 @@ name:                tweet-hs-version:             0.6.0.1+version:             0.6.1.2 synopsis:            Command-line tool for twitter description:         a Command Line Interface Tweeter homepage:            https://github.com/vmchale/command-line-tweeter#readme@@ -24,12 +24,22 @@   Default:     False } +Flag gold {+  Description: Use the gold linker+  Default:     True+}++Flag parallel-gc {+  Description: Use parallel garbage collector+  Default:     False+}+ library   hs-source-dirs:      src   exposed-modules:     Web.Tweet                      , Web.Tweet.Exec-                     , Web.Tweet.Parser                      , Web.Tweet.Parser.FastParser+                     , Web.Tweet.Parser   other-modules:       Web.Tweet.Types                      , Web.Tweet.Utils                      , Web.Tweet.Utils.Colors@@ -42,13 +52,13 @@                      , http-client                      , http-types                      , authenticate-oauth+                     , megaparsec                      , bytestring                      , split                      , optparse-applicative                       , lens                      , data-default                      , text-                     , megaparsec                      , containers                      , ansi-wl-pprint                      , directory@@ -57,8 +67,10 @@                      , aeson   default-language:    Haskell2010   default-extensions:  LambdaCase-  ghc-options:      -fwarn-unused-imports-  -- -fwarn-unused-binds +  if flag(gold) +    ghc-options:       -optl-fuse-ld=gold+    ld-options:        -fuse-ld=gold+  ghc-options:         -fwarn-unused-imports  executable tweet   if flag(library)@@ -68,27 +80,32 @@   hs-source-dirs:      app   main-is:             Main.hs   if flag(llvm-fast)-    ghc-options:       -threaded -rtsopts -with-rtsopts=-N -fllvm -optlo-O3 -O3-  else-    ghc-options:       -threaded -rtsopts -with-rtsopts=-N+    ghc-options:       -fllvm -optlo-O3 -O3+  if flag(gold) +    ghc-options:       -optl-fuse-ld=gold+    ld-options:        -fuse-ld=gold+  if flag(parallel-gc)+    ghc-options:       -rtsopts -with-rtsopts=-N+  ghc-options:         -threaded -O3   build-depends:       base                      , tweet-hs    default-language:    Haskell2010  benchmark tweeths-bench-  type:             exitcode-stdio-1.0-  hs-source-dirs:   bench-  main-is:          Bench.hs-  build-depends:    base-                  , criterion-                  , tweet-hs-                  , megaparsec-                  , bytestring+  type:                exitcode-stdio-1.0+  hs-source-dirs:      bench+  main-is:             Bench.hs+  build-depends:       base+                       , criterion+                       , tweet-hs+                       , bytestring   if flag(llvm-fast)-    ghc-options:       -threaded -rtsopts -with-rtsopts=-N -fllvm -optlo-O3 -O3-  else-    ghc-options:       -threaded -rtsopts -with-rtsopts=-N -O3-  default-language: Haskell2010+    ghc-options:       -fllvm -optlo-O3 -O3+  if flag(gold) +    ghc-options:       -optl-fuse-ld=gold+    ld-options:        -fuse-ld=gold+  ghc-options:         -threaded -rtsopts -with-rtsopts=-N+  default-language:    Haskell2010  test-suite tweeths-test   type:                exitcode-stdio-1.0@@ -97,12 +114,13 @@   build-depends:       base                      , tweet-hs                      , hspec-                     , hspec-megaparsec-                     , megaparsec                      , bytestring+  if flag(gold) +    ghc-options:       -optl-fuse-ld=gold+    ld-options:        -fuse-ld=gold   ghc-options:         -threaded -rtsopts -with-rtsopts=-N    default-language:    Haskell2010  source-repository head   type:     git-  location: https://github.com/vmchale/command-line-tweeter+  location: https://hub.darcs.net/vmchale/tweet-hs