packages feed

rewrite (empty) → 0.2

raw patch · 4 files changed

+181/−0 lines, 4 filesdep +basedep +directorydep +multiargsetup-changed

Dependencies added: base, directory, multiarg, process, temporary

Files

+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c) 2013, Omari Norman++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++    * Redistributions of source code must retain the above copyright+      notice, this list of conditions and the following disclaimer.++    * Redistributions in binary form must reproduce the above+      copyright notice, this list of conditions and the following+      disclaimer in the documentation and/or other materials provided+      with the distribution.++    * Neither the name of Omari Norman nor the names of other+      contributors may be used to endorse or promote products derived+      from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ rewrite.cabal view
@@ -0,0 +1,37 @@+-- Initial rewrite.cabal generated by cabal init.  For further +-- documentation, see http://haskell.org/cabal/users-guide/++name:                rewrite+version:             0.2+synopsis:            open file and rewrite it with new contents+description:+  In the Unix shell there is no easy way to use a filter program+  to change the contents of a file in-place. For example, if you+  want to sort a file in place, this will not work:+  .+  sort < myfile > myfile+  .+  All that will get you is an empty myfile. This package+  gives you the rewrite program, so this will work:+  .+  rewrite myfile sort++homepage:            http://www.github.com/massysett/rewrite+license:             BSD3+license-file:        LICENSE+author:              Omari Norman+maintainer:          omari@smileystation.com+copyright:           2013 Omari Norman+category:            System+build-type:          Simple+cabal-version:       >=1.8++executable rewrite+  main-is: rewrite.hs+  build-depends:+      base ==4.6.*+    , multiarg ==0.16.*+    , temporary ==1.1.*+    , process ==1.1.*+    , directory ==1.2.*+  ghc-options: -Wall
+ rewrite.hs view
@@ -0,0 +1,112 @@+module Main (main) where++import Data.Either (partitionEithers)+import qualified System.Console.MultiArg as MA+import qualified System.IO as IO+import System.IO.Temp (withSystemTempDirectory)+import qualified System.Exit as Exit+import qualified System.Directory as D+import qualified System.Process as P++help :: String -> String+help pn = unlines+  [ "usage: " ++ pn ++ "[options] FILE PROGRAM [program options]"+  , "opens given FILE and feeds it to standard input of PROGRAM"+  , "and writes PROGRAM output back to FILE."+  , ""+  , "Aborts if PROGRAM exits with non-zero exit status."+  , ""+  , "Options:"+  , "  -h, --help          Show help and exit"+  , "  -b, --backup SUFFIX Back up FILE to file with given SUFFIX"+  , "                      before writing new file"+  ]++type Backup = String+type ProgramOpt = String+type ProgName = String+type InputFile = String++errExit :: String -> IO a+errExit msg = do+  pn <- MA.getProgName+  IO.hPutStrLn IO.stderr $ pn ++ ": error: " ++ msg+  Exit.exitFailure++-- | Parses command line arguments; returns whether to do backup and+-- positional arguments+parseArgs :: IO (Maybe Backup, InputFile, ProgName, [ProgramOpt])+parseArgs = do+  let opts = [ MA.OptSpec ["backup"] "b" (MA.OneArg Left) ]+  as <- MA.simpleWithHelp help MA.StopOptions opts (return . Right)+  let (baks, os) = partitionEithers as+  bak <- case baks of+    [] -> return Nothing+    x:[] -> if null x+            then errExit "empty backup suffix given"+            else return $ Just x+    _ -> errExit "multiple backup suffixes given"+  (input, name, progOpts) <- case os of+    [] -> errExit "no input file or program name given"+    _:[] -> errExit "no program name given"+    x:y:xs -> return (x, y, xs)+  return (bak, input, name, progOpts)+++doBackup :: InputFile -> Backup -> IO ()+doBackup inf bak = D.copyFile inf (inf ++ "." ++ bak)+++runProgram+  :: Maybe Backup++  -> InputFile+  -- ^ Name of input file++  -> ProgName++  -> [ProgramOpt]++  -> FilePath+  -- ^ Temporary directory++  -> IO ()+runProgram mayBak inFile pn opts tempPath =+  let outPath = tempPath ++ "/output"+  in IO.withFile outPath IO.WriteMode $ \outHandle ->+     IO.withFile inFile IO.ReadMode $ \inHandle -> do+      writeReadme tempPath+      let cp = P.CreateProcess+            { P.cmdspec = P.RawCommand pn opts+            , P.cwd = Nothing+            , P.env = Nothing+            , P.std_in = P.UseHandle inHandle+            , P.std_out = P.UseHandle outHandle+            , P.std_err = P.Inherit+            , P.close_fds = False+            , P.create_group = False }+      (_, _, _, procHndle) <- P.createProcess cp+      code <- P.waitForProcess procHndle+      _ <- case code of+        Exit.ExitSuccess -> return ()+        Exit.ExitFailure bad ->+          errExit $ "program " ++ pn ++ " exited with code "+                    ++ show bad+      _ <- case mayBak of+        Nothing -> return ()+        Just bak -> doBackup inFile bak+      D.copyFile outPath inFile+++writeReadme+  :: FilePath+  -- ^ Temporary directory+  -> IO ()++writeReadme fp = writeFile (fp ++ "/README")+  "This directory created by the rewrite program."++main :: IO ()+main = do+  (mayBak, inf, pn, opts) <- parseArgs+  withSystemTempDirectory "rewrite" $ runProgram mayBak inf pn opts