-
Notifications
You must be signed in to change notification settings - Fork 75
[REPL] Help improvements for repl #478
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,6 +10,7 @@ | |
using Microsoft.HttpRepl.Suggestions; | ||
using Microsoft.Repl; | ||
using Microsoft.Repl.Commanding; | ||
using Microsoft.Repl.ConsoleHandling; | ||
using Microsoft.Repl.Parsing; | ||
|
||
namespace Microsoft.HttpRepl.Commands | ||
|
@@ -46,7 +47,30 @@ public async Task ExecuteAsync(IShellState shellState, HttpState programState, I | |
if (!string.IsNullOrEmpty(help)) | ||
{ | ||
anyHelp = true; | ||
shellState.ConsoleManager.WriteLine(); | ||
shellState.ConsoleManager.WriteLine(help); | ||
|
||
var structuredCommand = command as CommandWithStructuredInputBase<HttpState, ICoreParseResult>; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is an attempt to provide a consistent options help section for everything that needs it. Though I don't know that it's the best approach. Looking for ideas from you @mlorbetske. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a reasonable way of going about this. I'm not a huge fan of this only working for things that derive from CommandWithStructuredInputBase<HttpState, ICoreParseResult>, but I don't see us adding additional commands that don't derive from that - making InputSpec public doesn't feel the best either, but I don't think it hurts anything. We could add a method to get the options help to ICommand<,> and implement it in CommandWithStructuredInputBase<,> with the logic below - this would allow InputSpec to become protected again and lift the base type restriction, but it probably doesn't matter too much. |
||
if (structuredCommand != null && structuredCommand.InputSpec.Options.Any()) | ||
{ | ||
shellState.ConsoleManager.WriteLine(); | ||
shellState.ConsoleManager.WriteLine("Options:".Bold()); | ||
foreach (var option in structuredCommand.InputSpec.Options) | ||
{ | ||
var optionText = string.Empty; | ||
foreach (var form in option.Forms) | ||
{ | ||
if (!string.IsNullOrEmpty(optionText)) | ||
{ | ||
optionText += "|"; | ||
} | ||
optionText += form; | ||
} | ||
shellState.ConsoleManager.WriteLine($" {optionText}"); | ||
} | ||
} | ||
|
||
break; | ||
} | ||
} | ||
} | ||
|
@@ -67,39 +91,42 @@ public async Task ExecuteAsync(IShellState shellState, HttpState programState, I | |
} | ||
} | ||
|
||
IDirectoryStructure structure = programState.Structure.TraverseTo(parseResult.Sections[1]); | ||
if (structure.DirectoryNames.Any()) | ||
//Structure is null because, for example, SwaggerEndpoint exists but is not reachable. | ||
if (programState.Structure != null) | ||
{ | ||
shellState.ConsoleManager.WriteLine("Child directories:"); | ||
|
||
foreach (string name in structure.DirectoryNames) | ||
IDirectoryStructure structure = programState.Structure.TraverseTo(parseResult.Sections[1]); | ||
if (structure.DirectoryNames.Any()) | ||
{ | ||
shellState.ConsoleManager.WriteLine(" " + name + "/"); | ||
} | ||
|
||
anyHelp = true; | ||
} | ||
shellState.ConsoleManager.WriteLine("Child directories:"); | ||
|
||
if (structure.RequestInfo != null) | ||
{ | ||
if (structure.RequestInfo.Methods.Count > 0) | ||
{ | ||
if (anyHelp) | ||
foreach (string name in structure.DirectoryNames) | ||
{ | ||
shellState.ConsoleManager.WriteLine(); | ||
shellState.ConsoleManager.WriteLine(" " + name + "/"); | ||
} | ||
|
||
anyHelp = true; | ||
shellState.ConsoleManager.WriteLine("Available methods:"); | ||
} | ||
|
||
foreach (string method in structure.RequestInfo.Methods) | ||
if (structure.RequestInfo != null) | ||
{ | ||
if (structure.RequestInfo.Methods.Count > 0) | ||
{ | ||
shellState.ConsoleManager.WriteLine(" " + method.ToUpperInvariant()); | ||
IReadOnlyList<string> accepts = structure.RequestInfo.ContentTypesByMethod[method]; | ||
string acceptsString = string.Join(", ", accepts.Where(x => !string.IsNullOrEmpty(x))); | ||
if (!string.IsNullOrEmpty(acceptsString)) | ||
if (anyHelp) | ||
{ | ||
shellState.ConsoleManager.WriteLine(); | ||
} | ||
|
||
anyHelp = true; | ||
shellState.ConsoleManager.WriteLine("Available methods:"); | ||
|
||
foreach (string method in structure.RequestInfo.Methods) | ||
{ | ||
shellState.ConsoleManager.WriteLine(" Accepts: " + acceptsString); | ||
shellState.ConsoleManager.WriteLine(" " + method.ToUpperInvariant()); | ||
IReadOnlyList<string> accepts = structure.RequestInfo.ContentTypesByMethod[method]; | ||
string acceptsString = string.Join(", ", accepts.Where(x => !string.IsNullOrEmpty(x))); | ||
if (!string.IsNullOrEmpty(acceptsString)) | ||
{ | ||
shellState.ConsoleManager.WriteLine(" Accepts: " + acceptsString); | ||
} | ||
} | ||
} | ||
} | ||
|
@@ -176,15 +203,54 @@ public IEnumerable<string> Suggest(IShellState shellState, HttpState programStat | |
|
||
public void CoreGetHelp(IShellState shellState, ICommandDispatcher<HttpState, ICoreParseResult> dispatcher, HttpState programState) | ||
{ | ||
foreach (ICommand<HttpState, ICoreParseResult> command in dispatcher.Commands) | ||
{ | ||
string help = command.GetHelpSummary(shellState, programState); | ||
shellState.ConsoleManager.WriteLine(); | ||
shellState.ConsoleManager.WriteLine("HTTP Commands:".Bold().Cyan()); | ||
shellState.ConsoleManager.WriteLine("Use these commands to execute requests against your application."); | ||
shellState.ConsoleManager.WriteLine(); | ||
|
||
if (!string.IsNullOrEmpty(help)) | ||
{ | ||
shellState.ConsoleManager.WriteLine(help); | ||
} | ||
} | ||
const int navCommandColumn = -15; | ||
|
||
shellState.ConsoleManager.WriteLine($"{"GET",navCommandColumn}{"Issues a GET request."}"); | ||
shellState.ConsoleManager.WriteLine($"{"POST",navCommandColumn}{"Issues a POST request."}"); | ||
shellState.ConsoleManager.WriteLine($"{"PUT",navCommandColumn}{"Issues a PUT request."}"); | ||
shellState.ConsoleManager.WriteLine($"{"DELETE",navCommandColumn}{"Issues a DELETE request."}"); | ||
shellState.ConsoleManager.WriteLine($"{"PATCH",navCommandColumn}{"Issues a PATCH request."}"); | ||
shellState.ConsoleManager.WriteLine($"{"HEAD",navCommandColumn}{"Issues a HEAD request."}"); | ||
shellState.ConsoleManager.WriteLine($"{"OPTIONS",navCommandColumn}{"Issues an OPTIONS request."}"); | ||
shellState.ConsoleManager.WriteLine(); | ||
shellState.ConsoleManager.WriteLine($"{"set header",navCommandColumn}{"Sets or clears a header for all requests. e.g. `set header content-type:application/json`"}"); | ||
shellState.ConsoleManager.WriteLine(); | ||
|
||
shellState.ConsoleManager.WriteLine(); | ||
shellState.ConsoleManager.WriteLine("Navigation Commands:".Bold().Cyan()); | ||
shellState.ConsoleManager.WriteLine("The REPL allows you to navigate your URL space and focus on specific APIS that you are working on."); | ||
shellState.ConsoleManager.WriteLine(); | ||
|
||
shellState.ConsoleManager.WriteLine($"{"set base",navCommandColumn}{"Set the base URI. e.g. `set base http://locahost:5000`"}"); | ||
shellState.ConsoleManager.WriteLine($"{"set swagger",navCommandColumn}{"Set the URI, relative to your base if set, of the Swagger document for this API. e.g. `set swagger /swagger/v1/swagger.json`"}"); | ||
shellState.ConsoleManager.WriteLine($"{"ls",navCommandColumn}{"Show all endpoints for the current path."}"); | ||
shellState.ConsoleManager.WriteLine($"{"cd",navCommandColumn}{"Append the given directory to the currently selected path, or move up a path when using `cd ..`."}"); | ||
|
||
shellState.ConsoleManager.WriteLine(); | ||
shellState.ConsoleManager.WriteLine("Shell Commands:".Bold().Cyan()); | ||
shellState.ConsoleManager.WriteLine("Use these commands to interact with the REPL shell."); | ||
shellState.ConsoleManager.WriteLine(); | ||
|
||
shellState.ConsoleManager.WriteLine($"{"clear",navCommandColumn}{"Removes all text from the shell."}"); | ||
shellState.ConsoleManager.WriteLine($"{"echo [on/off]",navCommandColumn}{"Turns request echoing on or off, show the request that was mode when using request commands."}"); | ||
shellState.ConsoleManager.WriteLine($"{"exit",navCommandColumn}{"Exit the shell."}"); | ||
|
||
shellState.ConsoleManager.WriteLine(); | ||
shellState.ConsoleManager.WriteLine("REPL Customization Commands:".Bold().Cyan()); | ||
shellState.ConsoleManager.WriteLine("Use these commands to customize the REPL behavior.."); | ||
shellState.ConsoleManager.WriteLine(); | ||
|
||
shellState.ConsoleManager.WriteLine($"{"pref [get/set]",navCommandColumn}{"Allows viewing or changing preferences, e.g. 'pref set editor.command.default 'C:\\Program Files\\Microsoft VS Code\\Code.exe'`"}"); | ||
shellState.ConsoleManager.WriteLine($"{"run",navCommandColumn}{"Runs the script at the given path. A script is a set of commands that can be typed with one command per line."}"); | ||
shellState.ConsoleManager.WriteLine($"{"ui",navCommandColumn}{"Displays the swagger UI page, if available, in the default browser."}"); | ||
shellState.ConsoleManager.WriteLine(); | ||
shellState.ConsoleManager.WriteLine("Use help <COMMAND> to learn more details about individual commands. e.g. `help get`".Bold().Cyan()); | ||
shellState.ConsoleManager.WriteLine(); | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we want to set these to a particular color from preferences?