Skip to content

Commit

Permalink
Generate pattern tree as comment
Browse files Browse the repository at this point in the history
For example:

    // Required:
    //   Either:
    //     Required:
    //       Command(ship, False) -> CommandNode ship Bool
    //       Command(new, False) -> CommandNode new Bool
    //       OneOrMore:
    //         Argument(<name>, []) -> ArgumentNode <name> List
    //     Required:
    //       Command(ship, False) -> CommandNode ship Bool
    //       Argument(<name>, []) -> ArgumentNode <name> List
    //       Command(move, False) -> CommandNode move Bool
    //       Argument(<x>, ) -> ArgumentNode <x> String
    //       Argument(<y>, ) -> ArgumentNode <y> String
    //       Optional:
    //         Option(,--speed,1,10) -> OptionNode speed String
    //     Required:
    //       Command(ship, False) -> CommandNode ship Bool
    //       Command(shoot, False) -> CommandNode shoot Bool
    //       Argument(<x>, ) -> ArgumentNode <x> String
    //       Argument(<y>, ) -> ArgumentNode <y> String
    //     Required:
    //       Command(mine, False) -> CommandNode mine Bool
    //       Required:
    //         Either:
    //           Command(set, False) -> CommandNode set Bool
    //           Command(remove, False) -> CommandNode remove Bool
    //       Argument(<x>, ) -> ArgumentNode <x> String
    //       Argument(<y>, ) -> ArgumentNode <y> String
    //       Optional:
    //         Either:
    //           Option(,--moored,0,False) -> OptionNode moored Bool
    //           Option(,--drifting,0,False) -> OptionNode drifting Bool
    //     Required:
    //       Required:
    //         Option(-h,--help,0,False) -> OptionNode help Bool
    //     Required:
    //       Option(,--version,0,False) -> OptionNode version Bool
  • Loading branch information
atifaziz committed Apr 5, 2021
1 parent 490e650 commit 41bf0c0
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 2 deletions.
6 changes: 6 additions & 0 deletions src/DocoptNet.CodeGeneration/IndentingStringBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,12 @@ public IndentingStringBuilder Append(char value)
return this;
}

public IndentingStringBuilder Append(char value, int repeatCount)
{
OnAppending().Append(value, repeatCount);
return this;
}

public IndentingStringBuilder Append(string value)
{
OnAppending().Append(value);
Expand Down
20 changes: 18 additions & 2 deletions src/DocoptNet.CodeGeneration/SourceGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,24 @@ public static SourceText Generate(string? ns, string name, SourceText text, Enco
.Append(quote).Append(usage.Replace(quote, quote + quote)).Append(quote).Append(";")
.AppendLine();

foreach (var node in new Docopt().GetNodes(usage))
sb.Append("// ").Append(node.ToString()).AppendLine();
void AppendTree(Pattern pattern, int level = 0)
{
sb.Append("// ").Append(' ', level * 2);
switch (pattern)
{
case BranchPattern { Children: var children } branch:
sb.Append(branch.GetType().Name).Append(":").AppendLine();
foreach (var child in children)
AppendTree(child, level + 1);
break;
case LeafPattern leaf:
sb.Append(leaf.ToString()).Append(" -> ").Append(leaf.ToNode().ToString()).AppendLine();
break;
}
}

AppendTree(new Docopt().ParsePattern(usage));
sb.AppendLine();

using (var reader = new StringReader(new Docopt().GenerateCode(usage)))
{
Expand Down
21 changes: 21 additions & 0 deletions src/DocoptNet/Docopt.cs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,27 @@ protected IDictionary<string, ValueObject> Apply(string doc, Tokens tokens,
}
}

// TODO consider consolidating duplication with portions of Apply above
internal Pattern ParsePattern(string doc)
{
var usageSections = ParseSection("usage:", doc);
if (usageSections.Length == 0)
throw new DocoptLanguageErrorException("\"usage:\" (case-insensitive) not found.");
if (usageSections.Length > 1)
throw new DocoptLanguageErrorException("More that one \"usage:\" (case-insensitive).");
var exitUsage = usageSections[0];
var options = ParseDefaults(doc);
var pattern = ParsePattern(FormalUsage(exitUsage), options);
var patternOptions = pattern.Flat<Option>().Distinct().ToList();
// [default] syntax for argument is disabled
foreach (OptionsShortcut optionsShortcut in pattern.Flat(typeof (OptionsShortcut)))
{
var docOptions = ParseDefaults(doc);
optionsShortcut.Children = docOptions.Distinct().Except(patternOptions).ToList();
}
return pattern.Fix();
}

private void SetDefaultPrintExitHandlerIfNecessary(bool exit)
{
if (exit && PrintExit == null)
Expand Down

0 comments on commit 41bf0c0

Please sign in to comment.