This commit is contained in:
Nate McMaster 2018-09-26 14:25:35 -07:00
Родитель 46aefb86dd c601038484
Коммит 59dd2a05ca
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: A778D9601BD78810
13 изменённых файлов: 250 добавлений и 79 удалений

Просмотреть файл

@ -42,7 +42,7 @@ namespace Microsoft.HttpRepl.Commands
protected abstract bool RequiresBody { get; }
protected override CommandInputSpecification InputSpec
public override CommandInputSpecification InputSpec
{
get
{
@ -469,7 +469,18 @@ namespace Microsoft.HttpRepl.Commands
protected override string GetHelpDetails(IShellState shellState, HttpState programState, DefaultCommandInput<ICoreParseResult> commandInput, ICoreParseResult parseResult)
{
return $"Issues a {Verb.ToUpperInvariant()} request";
var helpText = new StringBuilder();
helpText.Append("Usage: ".Bold());
helpText.AppendLine($"{Verb.ToUpperInvariant()} [Options]");
helpText.AppendLine();
helpText.AppendLine($"Issues a {Verb.ToUpperInvariant()} request.");
if (RequiresBody)
{
helpText.AppendLine("Your default editor will be opened with a sample body if no options are provided.");
}
return helpText.ToString();
}
public override string GetHelpSummary(IShellState shellState, HttpState programState)

Просмотреть файл

@ -4,11 +4,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.HttpRepl.Suggestions;
using Microsoft.Repl;
using Microsoft.Repl.Commanding;
using Microsoft.Repl.ConsoleHandling;
using Microsoft.Repl.Parsing;
namespace Microsoft.HttpRepl.Commands
@ -60,18 +62,19 @@ namespace Microsoft.HttpRepl.Commands
return Task.CompletedTask;
}
protected override CommandInputSpecification InputSpec { get; } = CommandInputSpecification.Create("cd")
public override CommandInputSpecification InputSpec { get; } = CommandInputSpecification.Create("cd")
.MaximumArgCount(1)
.Finish();
protected override string GetHelpDetails(IShellState shellState, HttpState programState, DefaultCommandInput<ICoreParseResult> commandInput, ICoreParseResult parseResult)
{
if (commandInput.Arguments.Count == 1 && !string.IsNullOrEmpty(commandInput.Arguments[0]?.Text))
{
return "Prints the current directory if no argument is specified, otherwise changes to the specified directory";
}
var help = new StringBuilder();
help.Append("Usage:".Bold());
help.AppendLine("cd [directory]");
help.AppendLine();
help.AppendLine("Prints the current directory if no argument is specified, otherwise changes to the specified directory");
return "Changes to the directory " + commandInput.Arguments[0].Text;
return help.ToString();
}
public override string GetHelpSummary(IShellState shellState, HttpState programState)

Просмотреть файл

@ -55,7 +55,7 @@ namespace Microsoft.HttpRepl.Commands
}
}
protected override CommandInputSpecification InputSpec { get; } = CommandInputSpecification.Create("config").Finish();
public override CommandInputSpecification InputSpec { get; } = CommandInputSpecification.Create("config").Finish();
protected override string GetHelpDetails(IShellState shellState, HttpState programState, DefaultCommandInput<ICoreParseResult> commandInput, ICoreParseResult parseResult)
{

Просмотреть файл

@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Repl;
@ -37,11 +38,16 @@ namespace Microsoft.HttpRepl.Commands
return Task.CompletedTask;
}
protected override CommandInputSpecification InputSpec { get; } = CommandInputSpecification.Create("echo").ExactArgCount(1).Finish();
public override CommandInputSpecification InputSpec { get; } = CommandInputSpecification.Create("echo").ExactArgCount(1).Finish();
protected override string GetHelpDetails(IShellState shellState, HttpState programState, DefaultCommandInput<ICoreParseResult> commandInput, ICoreParseResult parseResult)
{
return "Turns request echoing on or off";
var helpText = new StringBuilder();
helpText.Append("Usage: ".Bold());
helpText.AppendLine($"echo [on|off]");
helpText.AppendLine();
helpText.AppendLine($"Turns request echoing on or off. When request echoing is on we will display a text representation of requests made by the CLI.");
return helpText.ToString();
}
public override string GetHelpSummary(IShellState shellState, HttpState programState)

Просмотреть файл

@ -1,10 +1,12 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Repl;
using Microsoft.Repl.Commanding;
using Microsoft.Repl.ConsoleHandling;
using Microsoft.Repl.Parsing;
namespace Microsoft.HttpRepl.Commands
@ -17,11 +19,16 @@ namespace Microsoft.HttpRepl.Commands
return Task.CompletedTask;
}
protected override CommandInputSpecification InputSpec { get; } = CommandInputSpecification.Create("exit").ExactArgCount(0).Finish();
public override CommandInputSpecification InputSpec { get; } = CommandInputSpecification.Create("exit").ExactArgCount(0).Finish();
protected override string GetHelpDetails(IShellState shellState, object programState, DefaultCommandInput<ICoreParseResult> commandInput, ICoreParseResult parseResult)
{
return "Exits the shell";
var helpText = new StringBuilder();
helpText.Append("Usage: ".Bold());
helpText.AppendLine($"exit");
helpText.AppendLine();
helpText.AppendLine($"Exits the shell");
return helpText.ToString();
}
public override string GetHelpSummary(IShellState shellState, object programState)

Просмотреть файл

@ -10,6 +10,7 @@ using Microsoft.HttpRepl.Preferences;
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 @@ namespace Microsoft.HttpRepl.Commands
if (!string.IsNullOrEmpty(help))
{
anyHelp = true;
shellState.ConsoleManager.WriteLine();
shellState.ConsoleManager.WriteLine(help);
var structuredCommand = command as CommandWithStructuredInputBase<HttpState, ICoreParseResult>;
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 @@ namespace Microsoft.HttpRepl.Commands
}
}
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 + "/");
shellState.ConsoleManager.WriteLine("Child directories:");
foreach (string name in structure.DirectoryNames)
{
shellState.ConsoleManager.WriteLine(" " + name + "/");
}
anyHelp = true;
}
anyHelp = true;
}
if (structure.RequestInfo != null)
{
if (structure.RequestInfo.Methods.Count > 0)
if (structure.RequestInfo != null)
{
if (anyHelp)
if (structure.RequestInfo.Methods.Count > 0)
{
shellState.ConsoleManager.WriteLine();
}
anyHelp = true;
shellState.ConsoleManager.WriteLine("Available methods:");
foreach (string method in structure.RequestInfo.Methods)
{
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(" Accepts: " + acceptsString);
shellState.ConsoleManager.WriteLine();
}
anyHelp = true;
shellState.ConsoleManager.WriteLine("Available methods:");
foreach (string method in structure.RequestInfo.Methods)
{
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 @@ namespace Microsoft.HttpRepl.Commands
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();
}
}
}

Просмотреть файл

@ -5,11 +5,13 @@ using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.HttpRepl.Preferences;
using Microsoft.Repl;
using Microsoft.Repl.Commanding;
using Microsoft.Repl.ConsoleHandling;
using Microsoft.Repl.Parsing;
namespace Microsoft.HttpRepl.Commands
@ -118,19 +120,24 @@ namespace Microsoft.HttpRepl.Commands
protected override CommandInputSpecification InputSpec { get; } = CommandInputSpecification.Create("ls").AlternateName("dir")
public override CommandInputSpecification InputSpec { get; } = CommandInputSpecification.Create("ls").AlternateName("dir")
.MaximumArgCount(1)
.WithOption(new CommandOptionSpecification(RecursiveOption, maximumOccurrences: 1, acceptsValue: true, forms: new[] {"-r", "--recursive"}))
.Finish();
protected override string GetHelpDetails(IShellState shellState, HttpState programState, DefaultCommandInput<ICoreParseResult> commandInput, ICoreParseResult parseResult)
{
return "Lists the contents of a directory";
var helpText = new StringBuilder();
helpText.Append("Usage: ".Bold());
helpText.AppendLine($"ls [Options]");
helpText.AppendLine();
helpText.AppendLine($"Displays the known routes at the current location. Requires a Swagger document to be set.");
return helpText.ToString();
}
public override string GetHelpSummary(IShellState shellState, HttpState programState)
{
return "ls - Performs a directory listing";
return "ls - List known routes for the current location";
}
protected override IEnumerable<string> GetArgumentSuggestionsForText(IShellState shellState, HttpState programState, ICoreParseResult parseResult, DefaultCommandInput<ICoreParseResult> commandInput, string normalCompletionString)

Просмотреть файл

@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.HttpRepl.Preferences;
@ -42,19 +43,86 @@ namespace Microsoft.HttpRepl.Commands
protected override string GetHelpDetails(IShellState shellState, HttpState programState, DefaultCommandInput<ICoreParseResult> commandInput, ICoreParseResult parseResult)
{
var helpText = new StringBuilder();
helpText.Append("Usage: ".Bold());
if (commandInput.Arguments.Count == 0 || !_allowedSubcommands.Contains(commandInput.Arguments[0]?.Text))
{
return "pref [get/set] {setting} [{value}] - Get or sets a preference to a particular value";
helpText.AppendLine("pref [get/set] {setting} [{value}] - Get or sets a preference to a particular value");
}
if (string.Equals(commandInput.Arguments[0].Text, "get", StringComparison.OrdinalIgnoreCase))
else if (string.Equals(commandInput.Arguments[0].Text, "get", StringComparison.OrdinalIgnoreCase))
{
return "pref get [{setting}] - Gets the value of the specified preference or lists all preferences if no preference is specified";
helpText.AppendLine("pref get [{setting}] - Gets the value of the specified preference or lists all preferences if no preference is specified");
}
else
{
return "pref set {setting} [{value}] - Sets (or clears if value is not specified) the value of the specified preference";
helpText.AppendLine("pref set {setting} [{value}] - Sets (or clears if value is not specified) the value of the specified preference");
}
helpText.AppendLine();
helpText.AppendLine("Current Default Preferences:");
foreach (var pref in programState.DefaultPreferences)
{
var val = pref.Value;
if (pref.Key.Contains("colors"))
{
val = GetColor(val);
}
helpText.AppendLine($"{pref.Key,-50}{val}");
}
helpText.AppendLine();
helpText.AppendLine("Current Preferences:");
foreach (var pref in programState.Preferences)
{
var val = pref.Value;
if (pref.Key.Contains("colors"))
{
val = GetColor(val);
}
helpText.AppendLine($"{pref.Key,-50}{val}");
}
return helpText.ToString();
}
private static string GetColor(string value)
{
if (value.Contains("Bold"))
{
value = value.Bold();
}
if (value.Contains("Yellow"))
{
value = value.Yellow();
}
if (value.Contains("Cyan"))
{
value = value.Cyan();
}
if (value.Contains("Magenta"))
{
value = value.Magenta();
}
if (value.Contains("Green"))
{
value = value.Green();
}
if (value.Contains("White"))
{
value = value.White();
}
if (value.Contains("Black"))
{
value = value.Black();
}
return value;
}
protected override Task ExecuteAsync(IShellState shellState, HttpState programState, DefaultCommandInput<ICoreParseResult> commandInput, ICoreParseResult parseResult, CancellationToken cancellationToken)
@ -123,7 +191,7 @@ namespace Microsoft.HttpRepl.Commands
return Task.CompletedTask;
}
protected override CommandInputSpecification InputSpec { get; } = CommandInputSpecification.Create("pref")
public override CommandInputSpecification InputSpec { get; } = CommandInputSpecification.Create("pref")
.MinimumArgCount(1)
.MaximumArgCount(3)
.Finish();

Просмотреть файл

@ -4,10 +4,12 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Repl;
using Microsoft.Repl.Commanding;
using Microsoft.Repl.ConsoleHandling;
using Microsoft.Repl.Parsing;
using Microsoft.Repl.Scripting;
using Microsoft.Repl.Suggestions;
@ -48,12 +50,13 @@ namespace Microsoft.HttpRepl.Commands
{
if (parseResult.Sections.Count > 0 && string.Equals(parseResult.Sections[0], Name, StringComparison.OrdinalIgnoreCase))
{
if (parseResult.Sections.Count == 1)
{
return "Runs the specified script";
}
return "Runs the script " + parseResult.Sections[1];
var helpText = new StringBuilder();
helpText.Append("Usage: ".Bold());
helpText.AppendLine("run {path to script}");
helpText.AppendLine();
helpText.AppendLine("Runs the specified script.");
helpText.AppendLine("A script is a text file containing one CLI command per line. Each line will be run as if it was typed into the CLI.");
return helpText.ToString();
}
return null;

Просмотреть файл

@ -5,6 +5,7 @@ using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Repl;
@ -80,7 +81,12 @@ namespace Microsoft.HttpRepl.Commands
{
if (parseResult.Sections.Count > 1 && string.Equals(parseResult.Sections[0], Name, StringComparison.OrdinalIgnoreCase) && string.Equals(parseResult.Sections[1], SubCommand, StringComparison.OrdinalIgnoreCase))
{
return Description;
var helpText = new StringBuilder();
helpText.Append("Usage: ".Bold());
helpText.AppendLine($"set base [uri]");
helpText.AppendLine();
helpText.AppendLine(Description);
return helpText.ToString();
}
return null;

Просмотреть файл

@ -4,11 +4,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.HttpRepl.Suggestions;
using Microsoft.Repl;
using Microsoft.Repl.Commanding;
using Microsoft.Repl.ConsoleHandling;
using Microsoft.Repl.Parsing;
namespace Microsoft.HttpRepl.Commands
@ -18,7 +20,7 @@ namespace Microsoft.HttpRepl.Commands
private static readonly string Name = "set";
private static readonly string SubCommand = "header";
public string Description => "set header {name} [{{value}}] - Sets or clears a header";
public string Description => "set header {name} [value] - Sets or clears a header";
public bool? CanHandle(IShellState shellState, HttpState programState, ICoreParseResult parseResult)
{
@ -43,12 +45,12 @@ namespace Microsoft.HttpRepl.Commands
public string GetHelpDetails(IShellState shellState, HttpState programState, ICoreParseResult parseResult)
{
if (parseResult.Sections.Count > 1 && string.Equals(parseResult.Sections[0], Name, StringComparison.OrdinalIgnoreCase) && string.Equals(parseResult.Sections[1], SubCommand, StringComparison.OrdinalIgnoreCase))
{
return Description;
}
return null;
var helpText = new StringBuilder();
helpText.Append("Usage: ".Bold());
helpText.AppendLine("set header {name} [value]");
helpText.AppendLine();
helpText.AppendLine("Sets or clears a header. When [value] is empty the header is cleared.");
return Description;
}
public string GetHelpSummary(IShellState shellState, HttpState programState)

Просмотреть файл

@ -208,6 +208,6 @@ namespace Microsoft.Repl.Commanding
protected abstract Task ExecuteAsync(IShellState shellState, TProgramState programState, DefaultCommandInput<TParseResult> commandInput, TParseResult parseResult, CancellationToken cancellationToken);
protected abstract CommandInputSpecification InputSpec { get; }
public abstract CommandInputSpecification InputSpec { get; }
}
}

Просмотреть файл

@ -2,16 +2,8 @@
<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="$(MicrosoftNETTestSdkPackageVersion)" />
<PackageReference Include="xunit" Version="$(XunitPackageVersion)" />
<PackageReference Include="xunit.runner.visualstudio" Version="$(XunitRunnerVisualStudioPackageVersion)" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Microsoft.Repl\Microsoft.Repl.csproj" />
</ItemGroup>