Haskell Shelly sample code

1.4k Views Asked by At

I'm trying to figure out how to use the Shelly (Shell.Pipe) library. So far i've got:

{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ExtendedDefaultRules #-}
{-# OPTIONS_GHC -fno-warn-type-defaults #-}
import Control.Applicative
import Data.List(sort)

import Shelly.Pipe
import Data.Text.Lazy as LT

default (LT.Text)

findExt ext = findWhen (pure . hasExt ext)
main = shelly $ verbosely $ do
cd bookPath 
findExt "epub" "."

I can find all the epub files but then I have no idea how to operate on each of the epub file ? For example I want to run ebook-convert command on those file names wrapped by Sh Monad.

Btw: The examples are really scarce on the internet... And it is very confusing that there are two similar libries:Shelly and Shelly.Pipe. The functions inside these two share same name with different Types: In Shelly.Pipe:

find :: FilePath -> Sh FilePath
find = sh1s S.find

In Shelly:

find :: FilePath -> ShIO [FilePath]

Really frustrating !

PS: With the help from John Wiegley I finally got the code working. I post the code below for people who might use it. Pay attention to the use of unpack.

{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ExtendedDefaultRules #-}
{-# OPTIONS_GHC -fno-warn-type-defaults #-}

import Control.Applicative
import Data.List(sort)
import Control.Monad
import Shelly
import System.Directory
import Data.Text
import System.FilePath
default (Text)


bookPath = "/dir/to/books"

main = shelly $ verbosely $ do
    fnames <- Shelly.find bookPath  --fnames can not be processed by normal pure String processing functions and need to be "escaped"
    forM_ fnames $ \n-> liftIO $ putStrLn $ ProcessBookFileName $ unpack $ toTextIgnore n --ProcessBookFileName::String->String
1

There are 1 best solutions below

6
On

From what I can gather, you don't want to use the Shelly.Pipe module, just the Shelly module. The ShIO monad implements MonadIO, which allows you to execute arbitrary IO actions while inside ShIO. This would let you do something like

convertEpub :: FilePath -> IO ()
convertEpub fname = undefined

main = shelly $ do
    cd "projects/haskell/testing"
    liftIO $ putStrLn "Hello, world!  I'm in Shelly"
    fnames <- find (pure . hasExt "hs") "."
    liftIO $ forM_ fnames $ \fname -> do
        putStrLn $ "Processing file " ++ show fname
        convertEpub fname