+-- | Max command length when formatting command list output.
+maxCmdLen :: Int
+maxCmdLen = 60
+
+-- | Formats usage for a multi-personality program.
+formatCmdUsage :: (StandardOptions a) => String -> PersonalityList a -> String
+formatCmdUsage prog personalities =
+ let mlen = min maxCmdLen . maximum $ map (length . fst) personalities
+ sorted = sortBy (comparing fst) personalities
+ header = [ printf "Usage: %s {command} [options...] [argument...]" prog
+ , printf "%s <command> --help to see details, or man %s"
+ prog prog
+ , ""
+ , "Commands:"
+ ]
+ rows = map (\(cmd, (_, _, _, desc)) ->
+ -- FIXME: not wrapped here
+ printf " %-*s - %s" mlen cmd desc::String) sorted
+ in unlines $ header ++ rows
+
+-- | Displays usage for a program and exits.
+showCmdUsage :: (StandardOptions a) =>
+ String -- ^ Program name
+ -> PersonalityList a -- ^ Personality list
+ -> Bool -- ^ Whether the exit code is success or not
+ -> IO b
+showCmdUsage prog personalities success = do
+ let usage = formatCmdUsage prog personalities
+ putStr usage
+ if success
+ then exitSuccess
+ else exitWith $ ExitFailure C.exitFailure
+
+-- | Generates completion information for a multi-command binary.
+multiCmdCompletion :: (StandardOptions a) => PersonalityList a -> String
+multiCmdCompletion personalities =
+ unlines .
+ map argComplToText $
+ map (\(cmd, _) -> ArgCompletion (OptComplChoices [cmd]) 1 (Just 1))
+ personalities
+
+-- | Displays completion information for a multi-command binary and exits.
+showCmdCompletion :: (StandardOptions a) => PersonalityList a -> IO b
+showCmdCompletion personalities =
+ putStr (multiCmdCompletion personalities) >> exitSuccess
+