Skip to content

Commit 09c0cfa

Browse files
committed
Add generator of documentation for CLI
1 parent a87ddee commit 09c0cfa

15 files changed

+502
-0
lines changed
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net48</TargetFramework>
5+
<OutputType>Exe</OutputType>
6+
<AssemblyName>Roslynator.CommandLine.DocumentationGenerator</AssemblyName>
7+
<RootNamespace>Roslynator.CommandLine</RootNamespace>
8+
<IsPackable>false</IsPackable>
9+
</PropertyGroup>
10+
11+
<ItemGroup>
12+
<PackageReference Include="DotMarkdown" Version="0.1.1" />
13+
<PackageReference Include="CommandLineParser" Version="2.8.0" />
14+
</ItemGroup>
15+
16+
<ItemGroup>
17+
<ProjectReference Include="..\CommandLine\CommandLine.csproj" />
18+
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="3.10.0" />
19+
<PackageReference Include="Microsoft.CodeAnalysis.VisualBasic.Workspaces" Version="3.10.0" />
20+
</ItemGroup>
21+
22+
</Project>
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Copyright (c) Josef Pihrt. All rights reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
2+
3+
using DotMarkdown;
4+
5+
namespace Roslynator.CommandLine.Documentation
6+
{
7+
internal class DocumentationWriter : MarkdownDocumentationWriter
8+
{
9+
public DocumentationWriter(MarkdownWriter writer) : base(writer)
10+
{
11+
}
12+
13+
public override void WriteOptionDescription(CommandOption option)
14+
{
15+
_writer.WriteString(option.FullDescription);
16+
}
17+
}
18+
}
Lines changed: 245 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,245 @@
1+
// Copyright (c) Josef Pihrt. All rights reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
2+
3+
using System.Collections.Generic;
4+
using System.Linq;
5+
using System.Text;
6+
using DotMarkdown;
7+
8+
namespace Roslynator.CommandLine
9+
{
10+
public class MarkdownDocumentationWriter
11+
{
12+
protected readonly MarkdownWriter _writer;
13+
14+
public MarkdownDocumentationWriter(MarkdownWriter writer)
15+
{
16+
_writer = writer;
17+
}
18+
19+
public void WriteCommandHeading(Command command, CommandLineApplication application)
20+
{
21+
_writer.WriteStartHeading(1);
22+
_writer.WriteInlineCode(application.Name + " " + command.Name);
23+
_writer.WriteEndHeading();
24+
}
25+
26+
public void WriteCommandDescription(Command command)
27+
{
28+
_writer.WriteString(command.Description);
29+
_writer.WriteLine();
30+
_writer.WriteLine();
31+
}
32+
33+
public void WriteCommandSynopsis(Command command, CommandLineApplication application)
34+
{
35+
_writer.WriteHeading2("Synopsis");
36+
37+
var sb = new StringBuilder();
38+
39+
sb.Append(application.Name);
40+
sb.Append(" ");
41+
sb.Append(command.Name);
42+
43+
using (IEnumerator<CommandArgument> en = command.Arguments.OrderBy(f => f.Index).GetEnumerator())
44+
{
45+
if (en.MoveNext())
46+
{
47+
sb.Append(" ");
48+
49+
while (true)
50+
{
51+
CommandArgument argument = en.Current;
52+
53+
if (!argument.IsRequired)
54+
sb.Append("[");
55+
56+
if (!string.IsNullOrEmpty(argument.Name))
57+
{
58+
sb.Append(argument.Name);
59+
}
60+
else
61+
{
62+
sb.Append("<");
63+
sb.Append(argument.Index);
64+
sb.Append(">");
65+
}
66+
67+
if (!argument.IsRequired)
68+
sb.Append("]");
69+
70+
if (en.MoveNext())
71+
{
72+
sb.Append(", ");
73+
}
74+
else
75+
{
76+
break;
77+
}
78+
}
79+
}
80+
}
81+
82+
sb.AppendLine();
83+
84+
bool anyIsOptional = command.Options.Any(f => !f.IsRequired);
85+
bool anyHasShortName = command.Options.Any(f => !string.IsNullOrEmpty(f.ShortName));
86+
87+
var sb2 = new StringBuilder();
88+
var lines = new List<string>();
89+
90+
foreach (CommandOption option in command.Options)
91+
{
92+
if (!option.IsRequired)
93+
{
94+
sb2.Append("[");
95+
}
96+
else if (anyIsOptional)
97+
{
98+
sb2.Append(" ");
99+
}
100+
101+
if (!string.IsNullOrEmpty(option.ShortName))
102+
{
103+
sb2.Append("-");
104+
sb2.Append(option.ShortName);
105+
sb2.Append("|");
106+
}
107+
else if (anyHasShortName)
108+
{
109+
sb2.Append(' ', 3);
110+
}
111+
112+
if (!string.IsNullOrEmpty(option.Name))
113+
{
114+
sb2.Append("--");
115+
sb2.Append(option.Name);
116+
}
117+
118+
if (!option.IsRequired)
119+
sb2.Append("]");
120+
121+
lines.Add(sb2.ToString());
122+
123+
sb2.Clear();
124+
}
125+
126+
int maxWidth = lines.Max(f => f.Length);
127+
128+
for (int i = 0; i < lines.Count; i++)
129+
{
130+
sb.Append(lines[i]);
131+
132+
if (!string.IsNullOrEmpty(command.Options[i].MetaValue))
133+
{
134+
sb.Append(' ', maxWidth - lines[i].Length + 1);
135+
sb.Append(command.Options[i].MetaValue);
136+
}
137+
138+
sb.AppendLine();
139+
}
140+
141+
_writer.WriteFencedCodeBlock(sb.ToString());
142+
}
143+
144+
public void WriteArguments(IEnumerable<CommandArgument> arguments)
145+
{
146+
using (IEnumerator<CommandArgument> en = arguments.GetEnumerator())
147+
{
148+
if (en.MoveNext())
149+
{
150+
_writer.WriteHeading2("Arguments");
151+
152+
do
153+
{
154+
CommandArgument argument = en.Current;
155+
156+
WriteArgument(argument);
157+
158+
} while (en.MoveNext());
159+
}
160+
}
161+
}
162+
163+
public virtual void WriteArgument(CommandArgument argument)
164+
{
165+
_writer.WriteStartBold();
166+
_writer.WriteInlineCode((!string.IsNullOrEmpty(argument.Name)) ? argument.Name : $"<{argument.Index}>");
167+
_writer.WriteEndBold();
168+
_writer.WriteLine();
169+
_writer.WriteLine();
170+
171+
if (!string.IsNullOrEmpty(argument.Description))
172+
{
173+
_writer.WriteString(argument.Description);
174+
_writer.WriteLine();
175+
_writer.WriteLine();
176+
}
177+
}
178+
179+
public void WriteOptions(IEnumerable<CommandOption> options)
180+
{
181+
using (IEnumerator<CommandOption> en = options.GetEnumerator())
182+
{
183+
if (en.MoveNext())
184+
{
185+
_writer.WriteHeading2("Options");
186+
187+
do
188+
{
189+
WriteOption(en.Current);
190+
191+
} while (en.MoveNext());
192+
}
193+
}
194+
}
195+
196+
public virtual void WriteOption(CommandOption option)
197+
{
198+
_writer.WriteStartHeading(5);
199+
200+
var sb = new StringBuilder();
201+
202+
if (!option.IsRequired)
203+
sb.Append("[");
204+
205+
if (!string.IsNullOrEmpty(option.ShortName))
206+
{
207+
sb.Append("-");
208+
sb.Append(option.ShortName);
209+
sb.Append("|");
210+
}
211+
212+
if (!string.IsNullOrEmpty(option.Name))
213+
{
214+
sb.Append("--");
215+
sb.Append(option.Name);
216+
}
217+
218+
if (!option.IsRequired)
219+
sb.Append("]");
220+
221+
if (!string.IsNullOrEmpty(option.MetaValue))
222+
{
223+
sb.Append(" ");
224+
sb.Append(option.MetaValue);
225+
}
226+
227+
_writer.WriteInlineCode(sb.ToString());
228+
_writer.WriteEndHeading();
229+
230+
WriteOptionDescription(option);
231+
}
232+
233+
public virtual void WriteOptionDescription(CommandOption option)
234+
{
235+
string description = option.FullDescription;
236+
237+
if (!string.IsNullOrEmpty(description))
238+
{
239+
_writer.WriteString(description);
240+
_writer.WriteLine();
241+
_writer.WriteLine();
242+
}
243+
}
244+
}
245+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Copyright (c) Josef Pihrt. All rights reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
2+
3+
namespace Roslynator.CommandLine
4+
{
5+
internal static class MarkdownHelpers
6+
{
7+
public static string CreateGitHubHeadingLink(string value)
8+
{
9+
return "#"
10+
+ value
11+
.Replace("<", "")
12+
.Replace(">", "")
13+
.Replace("[", "")
14+
.Replace("]", "")
15+
.Replace("|", "")
16+
.Replace(" ", "-")
17+
.ToLower();
18+
}
19+
}
20+
}

0 commit comments

Comments
 (0)