Navigation Menu

Skip to content

Commit

Permalink
move help, man to UI.Command.Doc
Browse files Browse the repository at this point in the history
  • Loading branch information
kfish committed Aug 2, 2009
1 parent 1e9f2a4 commit 63ca528
Show file tree
Hide file tree
Showing 4 changed files with 169 additions and 167 deletions.
168 changes: 1 addition & 167 deletions UI/Command/Command.hs
@@ -1,24 +1,9 @@
module UI.Command.Command (
Command (..),
SubCommand (..),
help, man
)where

import Control.Monad (when)
) where

import Data.Default
import Data.Char (toUpper)

import System.Environment (getArgs)
import System.Exit

import System.Locale (defaultTimeLocale)
import Data.Time.Format (formatTime)
import Data.Time.Clock (getCurrentTime)

import Text.Printf (printf)

import UI.Command.Render

------------------------------------------------------------
-- Command class
Expand Down Expand Up @@ -72,154 +57,3 @@ instance Default SubCommand where
def = SubCommand "<undocumented subcommand>"
(\_ -> putStrLn "Unimplemented command")
def def def def

------------------------------------------------------------
-- internal subcommands
--

internalSubs = [helpSub, manSub]

------------------------------------------------------------
-- Help
--

helpSub :: SubCommand
helpSub = def {subName = "help", subShortDesc = "Display help for a specific subcommand"}

help :: Command -> [String] -> IO ()
help cmd args = mapM_ putStr $ longHelp cmd args

longHelp :: Command -> [String] -> [String]
-- | "cmd help" with no arguments: Give a list of all subcommands
longHelp cmd [] =
[commandShortDesc cmd ++ "\n"] ++
["Usage: " ++ (commandName cmd) ++ " [--version] [--help] command [args]\n\n"] ++
[indent 2 (commandLongDesc cmd), "\n"] ++
map (categoryHelp cmd) (commandCategories cmd) ++
[internalHelp cmd] ++
["\nPlease report bugs to <" ++ commandBugEmail cmd ++ ">\n"]

-- | "cmd help command": Give command-specific help
longHelp cmd (command:_) = contextHelp cmd command m
where m = filter (\x -> subName x == command) (commandSubs cmd)

-- | Provide synopses for a specific category of commands
categoryHelp :: Command -> String -> String
categoryHelp cmd c = c ++ ":\n" ++ unlines (map itemHelp items) ++ "\n"
where
items = filter (\x -> subCategory x == c) (commandSubs cmd)

-- | Provide synopses for internal commands
internalHelp :: Command -> String
internalHelp cmd = unlines $ "Miscellaneous:" : map itemHelp internalSubs

-- | One-line format for a command
itemHelp i = printf " %-14s%s" (subName i) (subShortDesc i)

-- | Provide detailed help for a specific command
contextHelp :: Command -> [Char] -> [SubCommand] -> [String]
contextHelp cmd command [] = longHelp cmd [] ++ contextError
where contextError = ["\n*** \"" ++ command ++ "\": Unknown command.\n"]
contextHelp cmd command (item:_) = synopsis ++ usage ++ description ++ examples
where usage = ["Usage: " ++ commandName cmd ++ " " ++ command ++ hasOpts command ++ "\n"]
hasOpts "help" = " command"
hasOpts _ = " [options]"
synopsis = [(commandName cmd) ++ " " ++ command ++ ": " ++ subSynopsis item ++ "\n"]
description = case (subShortDesc item) of
"" -> []
_ -> ["\n" ++ indent 2 (subShortDesc item)]
examples = case (subExamples item) of
[] -> []
_ -> ["\nExamples:"] ++
flip map (subExamples item) (\(desc,opts) ->
"\n " ++ desc ++ ":\n " ++ (commandName cmd) ++ " " ++ command ++
" " ++ opts ++ "\n")

------------------------------------------------------------
-- man
--

manSub :: SubCommand
manSub = def {subName = "man", subShortDesc = "Generate Unix man page for specific subcommand"}

man :: Command -> [String] -> IO ()
man cmd args = do
currentTime <- getCurrentTime
let dateStamp = formatTime defaultTimeLocale "%B %Y" currentTime
mapM_ putStrLn $ longMan cmd dateStamp args

headerMan :: Command -> String -> [String]
headerMan cmd dateStamp = [unwords [".TH", u, "1", quote dateStamp, quote "Flim!", "\n"]]
where
u = map toUpper (commandName cmd)

synopsisMan :: Command -> String -> [SubCommand] -> [String]
synopsisMan cmd _ [] =
[".SH SYNOPSIS\n\n.B ", commandName cmd, "\n.RI SUBCOMMAND\n[\n.I OPTIONS\n]\n.I filename ...\n\n"]
synopsisMan cmd command (item:_) =
[".SH SYNOPSIS\n\n.B ", commandName cmd, "\n.RI ", command, "\n", hasOpts command, "\n"]
where hasOpts "help" = ".I <subcommand>\n"
hasOpts "man" = ".I <subcommand>\n"
hasOpts _ = "[\n.I OPTIONS\n]\n"

authorsMan :: Command -> String -> [String]
authorsMan cmd command = a ++ g ++ e
where
n = commandName cmd
a | commandAuthors cmd == [] = []
| otherwise = [".SH AUTHORS\n\n" ++ n ++ " was written by ", englishList $ commandAuthors cmd, "\n\n"]
g = ["This manual page was autogenerated by\n.B " ++ n ++ " man" ++ space command ++ ".\n\n"]
e | commandBugEmail cmd == "" = []
| otherwise = ["Please report bugs to <" ++ commandBugEmail cmd ++ ">\n"]
space "" = ""
space c = ' ':c

descMan :: String -> [String]
descMan desc = [".SH DESCRIPTION\n", desc, "\n"]

longMan :: Command -> String -> [String] -> [String]
longMan cmd dateStamp [] =
headerMan cmd dateStamp ++
[".SH NAME"] ++
[commandName cmd, " \\- ", commandShortDesc cmd, "\n\n"] ++
synopsisMan cmd "SUBCOMMAND" [] ++
descMan (".B " ++ commandName cmd ++ "\n" ++ commandLongDesc cmd) ++
map (categoryMan cmd) (commandCategories cmd) ++
authorsMan cmd "" ++
seeAlsoMan cmd

longMan cmd dateStamp (command:_) = contextMan cmd dateStamp command m
where
m = filter (\x -> subName x == command) (commandSubs cmd)

-- | Provide a list of related commands
seeAlsoMan :: Command -> [String]
seeAlsoMan cmd
| commandSeeAlso cmd == def = []
| otherwise = [".SH \"SEE ALSO\"\n\n.PP\n"] ++
map (\x -> "\\fB"++x++"\\fR(1)\n") (commandSeeAlso cmd)

-- | Provide synopses for a specific category of commands
categoryMan :: Command -> String -> String
categoryMan cmd c = ".SH " ++ (map toUpper c) ++ "\n" ++ concat (map itemMan items) ++ "\n"
where items = filter (\x -> subCategory x == c) (commandSubs cmd)
itemMan i = printf ".IP %s\n%s\n" (subName i) (subShortDesc i)

contextMan :: Command -> String -> [Char] -> [SubCommand] -> [String]
contextMan cmd dateStamp _ [] = longMan cmd dateStamp []
contextMan cmd dateStamp command i@(item:_) =
headerMan cmd dateStamp ++
synopsisMan cmd command i ++
descMan (subSynopsis item) ++
description ++
examples ++
authorsMan cmd command
where
description | subShortDesc item == "" = []
| otherwise = ["\n" ++ subShortDesc item]
examples | subExamples item == [] = []
| otherwise = ["\n.SH ExAMPLES\n"] ++
flip map (subExamples item) (\(desc, opts) ->
".PP\n" ++ desc ++ ":\n.PP\n.RS\n\\f(CW" ++
commandName cmd ++ " " ++ command ++ " " ++
opts ++ "\\fP\n.RE\n")
166 changes: 166 additions & 0 deletions UI/Command/Doc.hs
@@ -0,0 +1,166 @@
module UI.Command.Doc (
help, man
)where

import Data.Default
import Data.Char (toUpper)

import System.Locale (defaultTimeLocale)
import Data.Time.Format (formatTime)
import Data.Time.Clock (getCurrentTime)

import Text.Printf (printf)

import UI.Command.Command
import UI.Command.Render

------------------------------------------------------------
-- internal subcommands
--

internalSubs = [helpSub, manSub]

------------------------------------------------------------
-- Help
--

helpSub :: SubCommand
helpSub = def {subName = "help", subShortDesc = "Display help for a specific subcommand"}

help :: Command -> [String] -> IO ()
help cmd args = mapM_ putStr $ longHelp cmd args

longHelp :: Command -> [String] -> [String]
-- | "cmd help" with no arguments: Give a list of all subcommands
longHelp cmd [] =
[commandShortDesc cmd ++ "\n"] ++
["Usage: " ++ (commandName cmd) ++ " [--version] [--help] command [args]\n\n"] ++
[indent 2 (commandLongDesc cmd), "\n"] ++
map (categoryHelp cmd) (commandCategories cmd) ++
[internalHelp cmd] ++
["\nPlease report bugs to <" ++ commandBugEmail cmd ++ ">\n"]

-- | "cmd help command": Give command-specific help
longHelp cmd (command:_) = contextHelp cmd command m
where m = filter (\x -> subName x == command) (commandSubs cmd)

-- | Provide synopses for a specific category of commands
categoryHelp :: Command -> String -> String
categoryHelp cmd c = c ++ ":\n" ++ unlines (map itemHelp items) ++ "\n"
where
items = filter (\x -> subCategory x == c) (commandSubs cmd)

-- | Provide synopses for internal commands
internalHelp :: Command -> String
internalHelp cmd = unlines $ "Miscellaneous:" : map itemHelp internalSubs

-- | One-line format for a command
itemHelp i = printf " %-14s%s" (subName i) (subShortDesc i)

-- | Provide detailed help for a specific command
contextHelp :: Command -> [Char] -> [SubCommand] -> [String]
contextHelp cmd command [] = longHelp cmd [] ++ contextError
where contextError = ["\n*** \"" ++ command ++ "\": Unknown command.\n"]
contextHelp cmd command (item:_) = synopsis ++ usage ++ description ++ examples
where usage = ["Usage: " ++ commandName cmd ++ " " ++ command ++ hasOpts command ++ "\n"]
hasOpts "help" = " command"
hasOpts _ = " [options]"
synopsis = [(commandName cmd) ++ " " ++ command ++ ": " ++ subSynopsis item ++ "\n"]
description = case (subShortDesc item) of
"" -> []
_ -> ["\n" ++ indent 2 (subShortDesc item)]
examples = case (subExamples item) of
[] -> []
_ -> ["\nExamples:"] ++
flip map (subExamples item) (\(desc,opts) ->
"\n " ++ desc ++ ":\n " ++ (commandName cmd) ++ " " ++ command ++
" " ++ opts ++ "\n")

------------------------------------------------------------
-- man
--

manSub :: SubCommand
manSub = def {subName = "man", subShortDesc = "Generate Unix man page for specific subcommand"}

man :: Command -> [String] -> IO ()
man cmd args = do
currentTime <- getCurrentTime
let dateStamp = formatTime defaultTimeLocale "%B %Y" currentTime
mapM_ putStrLn $ longMan cmd dateStamp args

headerMan :: Command -> String -> [String]
headerMan cmd dateStamp = [unwords [".TH", u, "1", quote dateStamp, quote "Flim!", "\n"]]
where
u = map toUpper (commandName cmd)

synopsisMan :: Command -> String -> [SubCommand] -> [String]
synopsisMan cmd _ [] =
[".SH SYNOPSIS\n\n.B ", commandName cmd, "\n.RI SUBCOMMAND\n[\n.I OPTIONS\n]\n.I filename ...\n\n"]
synopsisMan cmd command (item:_) =
[".SH SYNOPSIS\n\n.B ", commandName cmd, "\n.RI ", command, "\n", hasOpts command, "\n"]
where hasOpts "help" = ".I <subcommand>\n"
hasOpts "man" = ".I <subcommand>\n"
hasOpts _ = "[\n.I OPTIONS\n]\n"

authorsMan :: Command -> String -> [String]
authorsMan cmd command = a ++ g ++ e
where
n = commandName cmd
a | commandAuthors cmd == [] = []
| otherwise = [".SH AUTHORS\n\n" ++ n ++ " was written by ", englishList $ commandAuthors cmd, "\n\n"]
g = ["This manual page was autogenerated by\n.B " ++ n ++ " man" ++ space command ++ ".\n\n"]
e | commandBugEmail cmd == "" = []
| otherwise = ["Please report bugs to <" ++ commandBugEmail cmd ++ ">\n"]
space "" = ""
space c = ' ':c

descMan :: String -> [String]
descMan desc = [".SH DESCRIPTION\n", desc, "\n"]

longMan :: Command -> String -> [String] -> [String]
longMan cmd dateStamp [] =
headerMan cmd dateStamp ++
[".SH NAME"] ++
[commandName cmd, " \\- ", commandShortDesc cmd, "\n\n"] ++
synopsisMan cmd "SUBCOMMAND" [] ++
descMan (".B " ++ commandName cmd ++ "\n" ++ commandLongDesc cmd) ++
map (categoryMan cmd) (commandCategories cmd) ++
authorsMan cmd "" ++
seeAlsoMan cmd

longMan cmd dateStamp (command:_) = contextMan cmd dateStamp command m
where
m = filter (\x -> subName x == command) (commandSubs cmd)

-- | Provide a list of related commands
seeAlsoMan :: Command -> [String]
seeAlsoMan cmd
| commandSeeAlso cmd == def = []
| otherwise = [".SH \"SEE ALSO\"\n\n.PP\n"] ++
map (\x -> "\\fB"++x++"\\fR(1)\n") (commandSeeAlso cmd)

-- | Provide synopses for a specific category of commands
categoryMan :: Command -> String -> String
categoryMan cmd c = ".SH " ++ (map toUpper c) ++ "\n" ++ concat (map itemMan items) ++ "\n"
where items = filter (\x -> subCategory x == c) (commandSubs cmd)
itemMan i = printf ".IP %s\n%s\n" (subName i) (subShortDesc i)

contextMan :: Command -> String -> [Char] -> [SubCommand] -> [String]
contextMan cmd dateStamp _ [] = longMan cmd dateStamp []
contextMan cmd dateStamp command i@(item:_) =
headerMan cmd dateStamp ++
synopsisMan cmd command i ++
descMan (subSynopsis item) ++
description ++
examples ++
authorsMan cmd command
where
description | subShortDesc item == "" = []
| otherwise = ["\n" ++ subShortDesc item]
examples | subExamples item == [] = []
| otherwise = ["\n.SH ExAMPLES\n"] ++
flip map (subExamples item) (\(desc, opts) ->
".PP\n" ++ desc ++ ":\n.PP\n.RS\n\\f(CW" ++
commandName cmd ++ " " ++ command ++ " " ++
opts ++ "\\fP\n.RE\n")
1 change: 1 addition & 0 deletions UI/Command/Main.hs
Expand Up @@ -8,6 +8,7 @@ import System.Environment (getArgs)
import System.Exit

import UI.Command.Command
import UI.Command.Doc

------------------------------------------------------------
-- subMain
Expand Down
1 change: 1 addition & 0 deletions ui-command.cabal
Expand Up @@ -11,6 +11,7 @@ library
Build-Depends: base, time, old-locale, data-default
Exposed-modules: UI.Command
Other-modules: UI.Command.Command
UI.Command.Doc
UI.Command.Main
UI.Command.Render

Expand Down

0 comments on commit 63ca528

Please sign in to comment.