1
0
forked from GitHub/gf-core
Files
gf-core/src/compiler/GF/Command/Help.hs
hallgren ab3cc77656 GF shell: fix a parsing problem with the cc command
This patch fixes a problem introduced last year when the GF shell was
refactored to allow more commands to be treated uniformly and be part
of pipes. The cc command was one of those commands, but unfortunately this
introduced a parsing problem, e.g.

	> cc "last"
	constant not found: last

	> cc "last"++"year"
	command not parsed: cc "last"++"year"

This happened because the generic command line parser in
GF.Command.{Abstract,Parse} assumes that all commands have an argument of
type PGF.Expr. Commands that expect other types of arguments have to
use PGF.showExpr combined with other conversion to the argument type they
expect. The cc command excpets a GF.Grammar.Term, and unfortunately not 
all terms survice the roundtrip through PGF.Expr, in part because of
an additional hack to allow strings to be roundtripped through PGF.Expr
without adding superfluous double quotes.

To solve the problem, this patch

 + makes room for arguments of type Term in the Argument type in
   GF.Command.Abstract.
   
 + makes a special case for the cc command in GF.Command.Parse, by
   calling the partial parser 'runPartial pTerm' recently added in
   GF.Grammar.Lexer and GF.Grammar.Parser. Care was taken so that
   that "|" and ";" can be used both inside terms and as separators between
   commands in the shell, e.g. things like the following now work:

       > cc ("a"|"b") | ps -lexcode
       variants { "a" ; "b" }

 + introduces a type CommandArgument that replaces [Expr] as the
   type of values passed between commands in pipes. It has room for
   values of type [Expr], [String] and Term, thus eliminating the need
   to roundtrip through the Expr type all the time.
   The hack to avoid adding superfluous quotes when strings are
   roundtripped through Expr has been left in place for now,
   but can probably be removed.
2016-04-07 13:40:05 +00:00

92 lines
3.1 KiB
Haskell

module GF.Command.Help where
import GF.Command.Messages
import GF.Command.Abstract(isOpt,getCommandOp)
import GF.Command.CommandInfo
import GF.Data.Operations((++++))
import qualified Data.Map as Map
commandHelpAll' allCommands opts = unlines $
commandHelp' opts (isOpt "full" opts) `map` Map.toList allCommands
commandHelp' opts = if isOpt "t2t" opts then commandHelpTags else commandHelp
--commandHelp :: Bool -> (String,CommandInfo env) -> String
commandHelp full (co,info) = unlines . compact $ [
co ++ optionally (", " ++) (longname info),
synopsis info] ++ if full then [
"",
optionally (("syntax:" ++++).(" "++).(++"\n")) (syntax info),
explanation info,
section "options:" [" -" ++ o ++ "\t" ++ e | (o,e) <- options info],
section "flags:" [" -" ++ o ++ "\t" ++ e | (o,e) <- flags info],
section "examples:" [" " ++ o ++ "\t--" ++ e | (o,e) <- examples info]
] else []
-- for printing with txt2tags formatting
--commandHelpTags :: Bool -> (String,CommandInfo env) -> String
commandHelpTags full (co,info) = unlines . compact $ [
"#VSPACE","",
"===="++hdrname++"====",
"#NOINDENT",
name ++ ": " ++
"//" ++ synopsis info ++ ".//"] ++ if full then [
"","#TINY","",
explanation info,
optionally ("- Syntax: "++) (lit (syntax info)),
section "- Options:\n" [" | ``-" ++ o ++ "`` | " ++ e | (o,e) <- options info],
section "- Flags:\n" [" | ``-" ++ o ++ "`` | " ++ e | (o,e) <- flags info],
section "- Examples:\n" [" | ``" ++ o ++ "`` | " ++ e | (o,e) <- examples info],
"", "#NORMAL", ""
] else []
where
hdrname = co ++ equal (longname info)
name = lit co ++ equal (lit (longname info))
lit = optionally (wrap "``")
equal = optionally (" = "++)
-- verbatim = optionally (wrap ["```"])
wrap d s = d++s++d
section hdr = optionally ((hdr++++).unlines)
optionally f [] = []
optionally f s = f s
compact [] = []
compact ([]:xs@([]:_)) = compact xs
compact (x:xs) = x:compact xs
helpCommand allCommands =
("h", emptyCommandInfo {
longname = "help",
syntax = "h (-full)? COMMAND?",
synopsis = "get description of a command, or a the full list of commands",
explanation = unlines [
"Displays information concerning the COMMAND.",
"Without argument, shows the synopsis of all commands."
],
options = [
("changes","give a summary of changes from GF 2.9"),
("coding","give advice on character encoding"),
("full","give full information of the commands"),
("license","show copyright and license information"),
("t2t","output help in txt2tags format")
],
exec = \opts args ->
let
msg = case toStrings args of
_ | isOpt "changes" opts -> changesMsg
_ | isOpt "coding" opts -> codingMsg
_ | isOpt "license" opts -> licenseMsg
[s] -> let co = getCommandOp s in
case Map.lookup co allCommands of
Just info -> commandHelp' opts True (co,info)
_ -> "command not found"
_ -> commandHelpAll' allCommands opts
in return (fromString msg),
needsTypeCheck = False
})