PE Haskell after part 3

posted on 2014-08-28

Program Evolution of the Haskell program after, part 3.

In the past two posts we created the skeleton, added parallel polling threads, set up tests and cleaned up the code using hlint.

Adding --version support

After installation you want the user to be able to see get the version of the program for when bugs are reported. This version is set in the .cabal file, but you want it compiled in with the program.

For this cabal generates a module you can use:

import Paths_after (version)
import Data.Version (showVersion)

main :: IO ()
main = putStrLn ("after " ++ showVersion version)

All that was left was to add an option to make sure the code is included at the right moment.

Add --pid support

In an earlier commit, we changed the default behavior of after to selecting the pid of any process with the command line in the beginning:

pidHasPartialCommand :: String -> String -> IO Bool
pidHasPartialCommand needle pid = do
    cmd <- psCmdLine pid
    return $ isInfixOf needle cmd

pidsWithPartialCommand :: String -> IO [String]
pidsWithPartialCommand cmdLine = do
    listing <- psListing
    filterM (pidHasPartialCommand cmdLine) listing

Which means that you can run sleep 3m in one console and after "sleep 3m" in another to have after exit after the sleep command exits.

If you still want to use a PID to wait for, we now add support for --pid=1235,31235 to wait for both 1235 and 31235.

To accept multiple arguments with options, we add an optionType_list using defineOptions:

data MainOptions = MainOptions
    { optVersion :: Bool,
      optPid :: [Int]
    }

instance Options MainOptions where
    defineOptions = pure MainOptions
        <*> simpleOption "version" False
            "Show the program version"
        <*> defineOption (optionType_list ',' optionType_int) (\o -> o
            {
                optionLongFlags = ["pid"],
                optionShortFlags = ['p']
            })

In the above code the optionType_int and type of optPid are linked, s the first defines the type of the list element and optPid has to be defined as a list of that same type.

That is it, we are now at commit 6153a009bf3500998fdf89e8d06b4fad809ab59e.

Next post I'll have to look at adding more tests and splitting the package up into a library and executable for testability.