Commits

Sergey Astanin  committed a215a94

Pass-through (filter) mode of bitly utility

  • Participants
  • Parent commits 4e7a922
  • Tags 0.0.2

Comments (0)

Files changed (2)

 Name:          Bitly
-Version:       0.0.1
+Version:       0.0.2
 Cabal-version: >= 1.2
 Build-type:    Simple
 
   .
   API key is required. Please find yours at <http://bit.ly/account/>.
   .
-  An optional command line utility is provided (use `-f buildCLI` to build it).
+  Configuration file (`~/.bitly`) format:
+  .
+  > login = your_bit.ly_login
+  > apikey = your_API_key
+  .
+  Examples (command line utility):
+  .
+  > $ echo "Text with an URL: http://example.com/" | bitly
+  > Text with an URL: http://bit.ly/2eSq1z
+  > $ bitly shorten http://example.com
+  > http://bit.ly/2eSq1z
+  > $ bitly expand http://bit.ly/2eSq1z
+  > http://example.com/
 
 Homepage:      http://bitbucket.org/jetxee/hs-bitly/
 Bug-reports:   http://bitbucket.org/jetxee/hs-bitly/issues/
 Tested-with:   GHC == 6.10
 
-Flag buildCLI
-  Description: Build a command line tool to access bit.ly service.
-  Default:     False
-
 Library
   Build-depends:
                  base >= 3 && < 5
 
 Executable bitly
   Main-is:     bitly.hs
-  if !flag(buildCLI)
-    Buildable: False
   Build-depends:
                  filepath
                , directory
+               , regexpr
 
 
 import Control.Applicative ((<$>))
 import Data.Char (isSpace)
-import Data.Maybe (fromJust, isJust, isNothing)
+import Data.Maybe (fromJust, fromMaybe, isJust, isNothing)
 import System.Directory (getHomeDirectory)
 import System.Environment (getArgs)
 import System.Exit (exitFailure, exitSuccess)
 import System.FilePath (makeValid, combine)
 import System.IO (hPutStrLn, stderr)
+import Text.RegexPR
 
 confFileName :: IO String
 confFileName = makeValid <$> flip combine ".bitly" <$> getHomeDirectory
 
 errorExit s = hPutStrLn stderr s >> exitFailure
 
-printModifiedUrl :: (String -> IO Result) -> String -> IO ()
-printModifiedUrl op url = do
+modifyUrl :: (String -> IO Result) -> String -> IO String
+modifyUrl op url = do
   r <- op url
   case r of
-    Left err -> errorExit err
-    Right url' -> putStrLn url'
+    -- don't replace URL on error
+    Left _ -> return url
+    Right url' -> return url'
 
-usage = "Usage: bitly ( help | [shorten] [url ...] | expand [url ...] )\n\n\
-\Configuration file format:\n\
+urlRE = "(http|ftp|https)://\\w+(\\.\\w+)(:[0-9]+)?(/\\S+)?/?"
+
+passThrough :: (String -> IO Result) -> String -> IO String
+passThrough op txt =
+  let m = matchRegexPR urlRE txt
+  in case m of
+    Nothing -> return txt
+    Just ((url,(b,a)),_) -> do
+      url' <- modifyUrl op url
+      return . ((b ++ url') ++) =<< passThrough op a
+
+-- process all given urls or read stdin and pass it through
+runOp :: (String -> IO Result) -> [String] -> IO ()
+runOp op [] = putStr =<< passThrough op =<< getContents
+runOp op urls = mapM_ putStrLn =<< mapM (modifyUrl op) urls
+
+usage = "Usage: bitly [ help | [shorten] [url ...] | expand [url ...] ]\n\n\
+\If no url is given, bitly acts as a filter and replaces all found URLs.\n\
+\Bitly shortens URLs by default.\n\n\
+\Configuration file format (~/.bitly):\n\
 \  login = your_bit.ly_login\n\
 \  apikey = your_API_key"
 
       errorExit $ "Configuration file is incomplete or not found (" ++ f ++ ")"
     Just acc ->
       case args of
-        ("expand":urls) -> printModifiedUrl (expand acc) `mapM_` urls
-        ("shorten":urls) -> printModifiedUrl (shorten acc) `mapM_` urls
-        _  -> printModifiedUrl (shorten acc) `mapM_` args -- shorten by default
+        ("expand":urls) -> runOp (expand acc) urls
+        ("shorten":urls) -> runOp (shorten acc) urls
+        _  -> runOp (shorten acc) args -- shorten by default