From af5d8a824479f8a708447b8467e94b3282a75634 Mon Sep 17 00:00:00 2001 From: Mike Lorbetske Date: Fri, 3 Aug 2018 09:18:39 -0700 Subject: [PATCH] Address most code review comments Pagination hasn't been dealt with yet mac keybindings may be able to be simplified, pending some additional verification Fix 3rd party signing cert Bind a few common bash/zsh mappings Check for output redirection Make package version variable name consistent Add --help option for the command line Remove regions Remove old pointer resolution code Make command not found message more friendly Fix issue where base address was required for requests to absolute URIs Add options to suppress response formatting and streaming Turn off packing for the REPL project --- Directory.Build.props | 3 +- build/dependencies.props | 2 +- .../Commands/BaseHttpCommand.cs | 63 ++++++++-------- .../Commands/HelpCommand.cs | 23 +++--- .../Microsoft.HttpRepl.csproj | 4 +- src/Microsoft.HttpRepl/OpenApi/PointerUtil.cs | 72 ------------------- .../Preferences/WellKnownPreference.cs | 2 - src/Microsoft.HttpRepl/Program.cs | 24 +++++++ .../Commanding/DefaultCommandDispatcher.cs | 1 + src/Microsoft.Repl/Input/IInputManager.cs | 2 + src/Microsoft.Repl/Input/InputManager.cs | 34 +++++++-- src/Microsoft.Repl/Input/KeyHandlers.cs | 6 ++ src/Microsoft.Repl/Microsoft.Repl.csproj | 1 + .../Microsoft.HttpRepl.Tests.csproj | 2 +- 14 files changed, 119 insertions(+), 120 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index 8ca8a8757b..9921cb358e 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,4 +1,4 @@ - + @@ -16,6 +16,7 @@ true MicrosoftNuGet Microsoft + Microsoft3rdPartyAppComponentDual true true diff --git a/build/dependencies.props b/build/dependencies.props index ee0b0b8ccf..bffcc722e2 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -17,7 +17,7 @@ 2.0.3 4.5.1 4.5.0 - 11.0.2 + 11.0.2 9.0.1 2.3.1 2.4.0 diff --git a/src/Microsoft.HttpRepl/Commands/BaseHttpCommand.cs b/src/Microsoft.HttpRepl/Commands/BaseHttpCommand.cs index 374544790b..ee9b4bcf0e 100644 --- a/src/Microsoft.HttpRepl/Commands/BaseHttpCommand.cs +++ b/src/Microsoft.HttpRepl/Commands/BaseHttpCommand.cs @@ -31,6 +31,8 @@ namespace Microsoft.HttpRepl.Commands private const string ResponseFileOption = nameof(ResponseFileOption); private const string BodyFileOption = nameof(BodyFileOption); private const string NoBodyOption = nameof(NoBodyOption); + private const string NoFormattingOption = nameof(NoFormattingOption); + private const string NoStreamingOption = nameof(NoStreamingOption); private const string BodyContentOption = nameof(BodyContentOption); private static readonly char[] HeaderSeparatorChars = new[] { '=', ':' }; @@ -54,7 +56,9 @@ namespace Microsoft.HttpRepl.Commands .WithOption(new CommandOptionSpecification(HeaderOption, requiresValue: true, forms: new[] {"--header", "-h"})) .WithOption(new CommandOptionSpecification(ResponseFileOption, requiresValue: true, maximumOccurrences: 1, forms: new[] { "--response", })) .WithOption(new CommandOptionSpecification(ResponseHeadersFileOption, requiresValue: true, maximumOccurrences: 1, forms: new[] { "--response:headers", })) - .WithOption(new CommandOptionSpecification(ResponseBodyFileOption, requiresValue: true, maximumOccurrences: 1, forms: new[] { "--response:body", })); + .WithOption(new CommandOptionSpecification(ResponseBodyFileOption, requiresValue: true, maximumOccurrences: 1, forms: new[] { "--response:body", })) + .WithOption(new CommandOptionSpecification(NoFormattingOption, maximumOccurrences: 1, forms: new[] { "--no-formatting", "-F" })) + .WithOption(new CommandOptionSpecification(NoStreamingOption, maximumOccurrences: 1, forms: new[] { "--no-streaming", "-S" })); if (RequiresBody) { @@ -70,9 +74,9 @@ namespace Microsoft.HttpRepl.Commands protected override async Task ExecuteAsync(IShellState shellState, HttpState programState, DefaultCommandInput commandInput, ICoreParseResult parseResult, CancellationToken cancellationToken) { - if (programState.BaseAddress == null) + if (programState.BaseAddress == null && (commandInput.Arguments.Count == 0 || !Uri.TryCreate(commandInput.Arguments[0].Text, UriKind.Absolute, out Uri _))) { - shellState.ConsoleManager.Error.WriteLine("'set base {url}' must be called before issuing requests".Bold().Red()); + shellState.ConsoleManager.Error.WriteLine("'set base {url}' must be called before issuing requests to a relative path".Bold().Red()); return; } @@ -203,10 +207,10 @@ namespace Microsoft.HttpRepl.Commands string bodyTarget = commandInput.Options[ResponseBodyFileOption].FirstOrDefault()?.Text ?? commandInput.Options[ResponseFileOption].FirstOrDefault()?.Text; HttpResponseMessage response = await programState.Client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); - await HandleResponseAsync(programState, shellState.ConsoleManager, response, programState.EchoRequest, headersTarget, bodyTarget, cancellationToken).ConfigureAwait(false); + await HandleResponseAsync(programState, commandInput, shellState.ConsoleManager, response, programState.EchoRequest, headersTarget, bodyTarget, cancellationToken).ConfigureAwait(false); } - private static async Task HandleResponseAsync(HttpState programState, IConsoleManager consoleManager, HttpResponseMessage response, bool echoRequest, string headersTargetFile, string bodyTargetFile, CancellationToken cancellationToken) + private static async Task HandleResponseAsync(HttpState programState, DefaultCommandInput commandInput, IConsoleManager consoleManager, HttpResponseMessage response, bool echoRequest, string headersTargetFile, string bodyTargetFile, CancellationToken cancellationToken) { RequestConfig requestConfig = new RequestConfig(programState); ResponseConfig responseConfig = new ResponseConfig(programState); @@ -244,7 +248,7 @@ namespace Microsoft.HttpRepl.Commands { using (StreamWriter writer = new StreamWriter(new MemoryStream())) { - await FormatBodyAsync(programState, consoleManager, response.RequestMessage.Content, writer, cancellationToken).ConfigureAwait(false); + await FormatBodyAsync(commandInput, programState, consoleManager, response.RequestMessage.Content, writer, cancellationToken).ConfigureAwait(false); } } @@ -311,7 +315,7 @@ namespace Microsoft.HttpRepl.Commands if (response.Content != null) { - await FormatBodyAsync(programState, consoleManager, response.Content, bodyFileWriter, cancellationToken).ConfigureAwait(false); + await FormatBodyAsync(commandInput, programState, consoleManager, response.Content, bodyFileWriter, cancellationToken).ConfigureAwait(false); } bodyFileWriter.Flush(); @@ -321,7 +325,7 @@ namespace Microsoft.HttpRepl.Commands consoleManager.WriteLine(); } - private static async Task FormatBodyAsync(HttpState programState, IConsoleManager consoleManager, HttpContent content, StreamWriter bodyFileWriter, CancellationToken cancellationToken) + private static async Task FormatBodyAsync(DefaultCommandInput commandInput, HttpState programState, IConsoleManager consoleManager, HttpContent content, StreamWriter bodyFileWriter, CancellationToken cancellationToken) { string contentType = null; if (content.Headers.TryGetValues("Content-Type", out IEnumerable contentTypeValues)) @@ -331,33 +335,36 @@ namespace Microsoft.HttpRepl.Commands contentType = contentType?.ToUpperInvariant() ?? "text/plain"; - if (contentType.EndsWith("/JSON", StringComparison.OrdinalIgnoreCase) - || contentType.EndsWith("-JSON", StringComparison.OrdinalIgnoreCase) - || contentType.EndsWith("+JSON", StringComparison.OrdinalIgnoreCase) - || contentType.EndsWith("/JAVASCRIPT", StringComparison.OrdinalIgnoreCase) - || contentType.EndsWith("-JAVASCRIPT", StringComparison.OrdinalIgnoreCase) - || contentType.EndsWith("+JAVASCRIPT", StringComparison.OrdinalIgnoreCase)) + if (commandInput.Options[NoFormattingOption].Count == 0) { - if (await FormatJsonAsync(programState, consoleManager, content, bodyFileWriter)) + if (contentType.EndsWith("/JSON", StringComparison.OrdinalIgnoreCase) + || contentType.EndsWith("-JSON", StringComparison.OrdinalIgnoreCase) + || contentType.EndsWith("+JSON", StringComparison.OrdinalIgnoreCase) + || contentType.EndsWith("/JAVASCRIPT", StringComparison.OrdinalIgnoreCase) + || contentType.EndsWith("-JAVASCRIPT", StringComparison.OrdinalIgnoreCase) + || contentType.EndsWith("+JAVASCRIPT", StringComparison.OrdinalIgnoreCase)) { - return; + if (await FormatJsonAsync(programState, consoleManager, content, bodyFileWriter)) + { + return; + } } - } - else if (contentType.EndsWith("/HTML", StringComparison.OrdinalIgnoreCase) - || contentType.EndsWith("-HTML", StringComparison.OrdinalIgnoreCase) - || contentType.EndsWith("+HTML", StringComparison.OrdinalIgnoreCase) - || contentType.EndsWith("/XML", StringComparison.OrdinalIgnoreCase) - || contentType.EndsWith("-XML", StringComparison.OrdinalIgnoreCase) - || contentType.EndsWith("+XML", StringComparison.OrdinalIgnoreCase)) - { - if (await FormatXmlAsync(consoleManager, content, bodyFileWriter)) + else if (contentType.EndsWith("/HTML", StringComparison.OrdinalIgnoreCase) + || contentType.EndsWith("-HTML", StringComparison.OrdinalIgnoreCase) + || contentType.EndsWith("+HTML", StringComparison.OrdinalIgnoreCase) + || contentType.EndsWith("/XML", StringComparison.OrdinalIgnoreCase) + || contentType.EndsWith("-XML", StringComparison.OrdinalIgnoreCase) + || contentType.EndsWith("+XML", StringComparison.OrdinalIgnoreCase)) { - return; + if (await FormatXmlAsync(consoleManager, content, bodyFileWriter)) + { + return; + } } } - //If we don't have content length, assume streaming - if (!content.Headers.TryGetValues("Content-Length", out IEnumerable _)) + //Unless the user has explicitly specified to not stream the response, if we don't have content length, assume streaming + if (commandInput.Options[NoStreamingOption].Count == 0 && !content.Headers.TryGetValues("Content-Length", out IEnumerable _)) { Memory buffer = new Memory(new char[2048]); Stream s = await content.ReadAsStreamAsync().ConfigureAwait(false); diff --git a/src/Microsoft.HttpRepl/Commands/HelpCommand.cs b/src/Microsoft.HttpRepl/Commands/HelpCommand.cs index f205fc1243..646dd4c544 100644 --- a/src/Microsoft.HttpRepl/Commands/HelpCommand.cs +++ b/src/Microsoft.HttpRepl/Commands/HelpCommand.cs @@ -30,15 +30,7 @@ namespace Microsoft.HttpRepl.Commands { if (parseResult.Sections.Count == 1) { - foreach (ICommand command in dispatcher.Commands) - { - string help = command.GetHelpSummary(shellState, programState); - - if (!string.IsNullOrEmpty(help)) - { - shellState.ConsoleManager.WriteLine(help); - } - } + CoreGetHelp(shellState, dispatcher, programState); } else { @@ -171,5 +163,18 @@ namespace Microsoft.HttpRepl.Commands return null; } + + public void CoreGetHelp(IShellState shellState, ICommandDispatcher dispatcher, HttpState programState) + { + foreach (ICommand command in dispatcher.Commands) + { + string help = command.GetHelpSummary(shellState, programState); + + if (!string.IsNullOrEmpty(help)) + { + shellState.ConsoleManager.WriteLine(help); + } + } + } } } diff --git a/src/Microsoft.HttpRepl/Microsoft.HttpRepl.csproj b/src/Microsoft.HttpRepl/Microsoft.HttpRepl.csproj index cf53e4b62e..2dce88c68b 100644 --- a/src/Microsoft.HttpRepl/Microsoft.HttpRepl.csproj +++ b/src/Microsoft.HttpRepl/Microsoft.HttpRepl.csproj @@ -23,8 +23,8 @@ - - + + diff --git a/src/Microsoft.HttpRepl/OpenApi/PointerUtil.cs b/src/Microsoft.HttpRepl/OpenApi/PointerUtil.cs index db36c082bf..c8566095b7 100644 --- a/src/Microsoft.HttpRepl/OpenApi/PointerUtil.cs +++ b/src/Microsoft.HttpRepl/OpenApi/PointerUtil.cs @@ -145,77 +145,5 @@ namespace Microsoft.HttpRepl.OpenApi return toResolve; } - - //public static async Task ResolvePointerAsync(this JToken root, HttpClient client, string pointer) - //{ - // if (!pointer.StartsWith("#/", StringComparison.Ordinal)) - // { - // HttpResponseMessage response = await client.GetAsync(pointer).ConfigureAwait(false); - - // if (!response.IsSuccessStatusCode) - // { - // //TODO: Failed to resolve pointer message - // return new JValue((object)null); - // } - - // string responseString = await response.Content.ReadAsStringAsync().ConfigureAwait(false); - - // try - // { - // root = JToken.Parse(responseString); - // int hashIndex = pointer.IndexOf("#"); - - // if (hashIndex < 0) - // { - // return root; - // } - - // pointer = pointer.Substring(hashIndex); - // } - // catch (Exception ex) - // { - // //TODO: Failed to deserialize pointer message - // return new JValue((object)null); - // } - // } - - // string[] pointerParts = pointer.Split('/'); - - // for (int i = 1; !(root is null) && i < pointerParts.Length; ++i) - // { - // if (root is JArray arr) - // { - // if (!int.TryParse(pointerParts[i], System.Globalization.NumberStyles.Integer, System.Globalization.CultureInfo.InvariantCulture, out int result) || result < 0 || result >= arr.Count) - // { - // //TODO: Failed to resolve pointer part message (non-integer index to array or index out of range) - // return null; - // } - - // root = arr[result]; - // } - // else if (root is JObject obj) - // { - // root = obj[pointerParts[i]]; - - // if (root is null) - // { - // //TODO: Failed to resolve pointer part message (no such path in object) - // } - - // JToken nestedRef = root["$ref"]; - // if (nestedRef is JValue value && value.Type == JTokenType.String) - // { - // root = await ResolvePointerAsync(root, ) - // } - // } - // else - // { - // //TODO: Failed to resolve pointer part message (pathing into literal) - // return null; - // } - // } - - // return root; - //} } } diff --git a/src/Microsoft.HttpRepl/Preferences/WellKnownPreference.cs b/src/Microsoft.HttpRepl/Preferences/WellKnownPreference.cs index 1cd17a04ce..424c0bb9a4 100644 --- a/src/Microsoft.HttpRepl/Preferences/WellKnownPreference.cs +++ b/src/Microsoft.HttpRepl/Preferences/WellKnownPreference.cs @@ -38,7 +38,6 @@ namespace Microsoft.HttpRepl.Preferences } } - #region JSON public static string JsonArrayBraceColor { get; } = "colors.json.arrayBrace"; public static string JsonObjectBraceColor { get; } = "colors.json.objectBrace"; @@ -66,7 +65,6 @@ namespace Microsoft.HttpRepl.Preferences public static string JsonSyntaxColor { get; } = "colors.json.syntax"; public static string JsonBraceColor { get; } = "colors.json.brace"; - #endregion JSON public static string RequestColor { get; } = "colors.request"; diff --git a/src/Microsoft.HttpRepl/Program.cs b/src/Microsoft.HttpRepl/Program.cs index a0e1c9addf..6509e7a38c 100644 --- a/src/Microsoft.HttpRepl/Program.cs +++ b/src/Microsoft.HttpRepl/Program.cs @@ -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; using System.Threading; using System.Threading.Tasks; using Microsoft.Repl; using Microsoft.Repl.Commanding; +using Microsoft.Repl.ConsoleHandling; using Microsoft.Repl.Parsing; using Microsoft.HttpRepl.Commands; @@ -14,6 +16,12 @@ namespace Microsoft.HttpRepl { static async Task Main(string[] args) { + if(Console.IsOutputRedirected) + { + Reporter.Error.WriteLine("Cannot start the REPL when output is being redirected".Bold().Red()); + return; + } + var state = new HttpState(); var dispatcher = DefaultCommandDispatcher.Create(state.GetPrompt, state); @@ -44,6 +52,22 @@ namespace Microsoft.HttpRepl shell.ShellState.ConsoleManager.AddBreakHandler(() => source.Cancel()); if (args.Length > 0) { + if (string.Equals(args[0], "--help", StringComparison.OrdinalIgnoreCase)) + { + shell.ShellState.ConsoleManager.WriteLine("Usage: dotnet httprepl [] [options]"); + shell.ShellState.ConsoleManager.WriteLine(); + shell.ShellState.ConsoleManager.WriteLine("Arguments:"); + shell.ShellState.ConsoleManager.WriteLine(" - The initial base address for the REPL."); + shell.ShellState.ConsoleManager.WriteLine(); + shell.ShellState.ConsoleManager.WriteLine("Options:"); + shell.ShellState.ConsoleManager.WriteLine(" --help - Show help information."); + + shell.ShellState.ConsoleManager.WriteLine(); + shell.ShellState.ConsoleManager.WriteLine("REPL Commands:"); + new HelpCommand().CoreGetHelp(shell.ShellState, (ICommandDispatcher)shell.ShellState.CommandDispatcher, state); + return; + } + shell.ShellState.CommandDispatcher.OnReady(shell.ShellState); shell.ShellState.InputManager.SetInput(shell.ShellState, $"set base \"{args[0]}\""); await shell.ShellState.CommandDispatcher.ExecuteCommandAsync(shell.ShellState, CancellationToken.None).ConfigureAwait(false); diff --git a/src/Microsoft.Repl/Commanding/DefaultCommandDispatcher.cs b/src/Microsoft.Repl/Commanding/DefaultCommandDispatcher.cs index 2b85c2bc57..22be314827 100644 --- a/src/Microsoft.Repl/Commanding/DefaultCommandDispatcher.cs +++ b/src/Microsoft.Repl/Commanding/DefaultCommandDispatcher.cs @@ -156,6 +156,7 @@ namespace Microsoft.Repl.Commanding } shellState.ConsoleManager.Error.WriteLine("No matching command found".Red().Bold()); + shellState.ConsoleManager.Error.WriteLine("Execute 'help' to se available commands".Red().Bold()); } } diff --git a/src/Microsoft.Repl/Input/IInputManager.cs b/src/Microsoft.Repl/Input/IInputManager.cs index b67f3e3936..e8e98b2d54 100644 --- a/src/Microsoft.Repl/Input/IInputManager.cs +++ b/src/Microsoft.Repl/Input/IInputManager.cs @@ -13,6 +13,8 @@ namespace Microsoft.Repl.Input IInputManager RegisterKeyHandler(ConsoleKey key, AsyncKeyPressHandler handler); + IInputManager RegisterKeyHandler(ConsoleKey key, ConsoleModifiers modifiers, AsyncKeyPressHandler handler); + void ResetInput(); Task StartAsync(IShellState state, CancellationToken cancellationToken); diff --git a/src/Microsoft.Repl/Input/InputManager.cs b/src/Microsoft.Repl/Input/InputManager.cs index e1d6055683..cd1157c6ff 100644 --- a/src/Microsoft.Repl/Input/InputManager.cs +++ b/src/Microsoft.Repl/Input/InputManager.cs @@ -12,7 +12,7 @@ namespace Microsoft.Repl.Input { public class InputManager : IInputManager { - private readonly Dictionary _handlers = new Dictionary(); + private readonly Dictionary> _handlers = new Dictionary>(); private readonly List _inputBuffer = new List(); public bool IsOverwriteMode { get; set; } @@ -29,13 +29,37 @@ namespace Microsoft.Repl.Input public IInputManager RegisterKeyHandler(ConsoleKey key, AsyncKeyPressHandler handler) { + if (!_handlers.TryGetValue(key, out Dictionary handlers)) + { + _handlers[key] = handlers = new Dictionary(); + } + if (handler == null) { - _handlers.Remove(key); + handlers.Remove(default(ConsoleModifiers)); } else { - _handlers[key] = handler; + handlers[default(ConsoleModifiers)] = handler; + } + + return this; + } + + public IInputManager RegisterKeyHandler(ConsoleKey key, ConsoleModifiers modifiers, AsyncKeyPressHandler handler) + { + if (!_handlers.TryGetValue(key, out Dictionary handlers)) + { + _handlers[key] = handlers = new Dictionary(); + } + + if (handler == null) + { + handlers.Remove(modifiers); + } + else + { + handlers[modifiers] = handler; } return this; @@ -169,7 +193,7 @@ namespace Microsoft.Repl.Input { ConsoleKeyInfo keyPress = state.ConsoleManager.ReadKey(cancellationToken); - if (_handlers.TryGetValue(keyPress.Key, out AsyncKeyPressHandler handler)) + if (_handlers.TryGetValue(keyPress.Key, out Dictionary handlerLookup) && handlerLookup.TryGetValue(keyPress.Modifiers, out AsyncKeyPressHandler handler)) { using (CancellationTokenSource source = new CancellationTokenSource()) using (state.ConsoleManager.AddBreakHandler(() => source.Cancel())) @@ -189,6 +213,7 @@ namespace Microsoft.Repl.Input FlushInput(state, ref presses); } + //TODO: Verify on a mac whether these are still needed if (keyPress.Key == ConsoleKey.A) { state.ConsoleManager.MoveCaret(-state.ConsoleManager.CaretPosition); @@ -198,6 +223,7 @@ namespace Microsoft.Repl.Input state.ConsoleManager.MoveCaret(_inputBuffer.Count - state.ConsoleManager.CaretPosition); } } + //TODO: Register these like regular commands else if (!string.IsNullOrEmpty(_ttyState) && keyPress.Modifiers == ConsoleModifiers.Alt) { if (presses != null) diff --git a/src/Microsoft.Repl/Input/KeyHandlers.cs b/src/Microsoft.Repl/Input/KeyHandlers.cs index 192c55319c..750db8d2f6 100644 --- a/src/Microsoft.Repl/Input/KeyHandlers.cs +++ b/src/Microsoft.Repl/Input/KeyHandlers.cs @@ -14,9 +14,13 @@ namespace Microsoft.Repl.Input { //Navigation in line inputManager.RegisterKeyHandler(ConsoleKey.LeftArrow, LeftArrow); + inputManager.RegisterKeyHandler(ConsoleKey.LeftArrow, ConsoleModifiers.Control, LeftArrow); inputManager.RegisterKeyHandler(ConsoleKey.RightArrow, RightArrow); + inputManager.RegisterKeyHandler(ConsoleKey.RightArrow, ConsoleModifiers.Control, RightArrow); inputManager.RegisterKeyHandler(ConsoleKey.Home, Home); + inputManager.RegisterKeyHandler(ConsoleKey.A, ConsoleModifiers.Control, Home); inputManager.RegisterKeyHandler(ConsoleKey.End, End); + inputManager.RegisterKeyHandler(ConsoleKey.E, ConsoleModifiers.Control, End); //Command history inputManager.RegisterKeyHandler(ConsoleKey.UpArrow, UpArrow); @@ -24,9 +28,11 @@ namespace Microsoft.Repl.Input //Completion inputManager.RegisterKeyHandler(ConsoleKey.Tab, Tab); + inputManager.RegisterKeyHandler(ConsoleKey.Tab, ConsoleModifiers.Shift, Tab); //Input manipulation inputManager.RegisterKeyHandler(ConsoleKey.Escape, Escape); + inputManager.RegisterKeyHandler(ConsoleKey.U, ConsoleModifiers.Control, Escape); inputManager.RegisterKeyHandler(ConsoleKey.Delete, Delete); inputManager.RegisterKeyHandler(ConsoleKey.Backspace, Backspace); diff --git a/src/Microsoft.Repl/Microsoft.Repl.csproj b/src/Microsoft.Repl/Microsoft.Repl.csproj index 63af949be4..cb7311eeeb 100644 --- a/src/Microsoft.Repl/Microsoft.Repl.csproj +++ b/src/Microsoft.Repl/Microsoft.Repl.csproj @@ -4,6 +4,7 @@ netcoreapp2.2 A framework for creating REPLs in .NET Core. dotnet;repl + false diff --git a/test/Microsoft.HttpRepl.Tests/Microsoft.HttpRepl.Tests.csproj b/test/Microsoft.HttpRepl.Tests/Microsoft.HttpRepl.Tests.csproj index 7a79d0121e..a50dd1df30 100644 --- a/test/Microsoft.HttpRepl.Tests/Microsoft.HttpRepl.Tests.csproj +++ b/test/Microsoft.HttpRepl.Tests/Microsoft.HttpRepl.Tests.csproj @@ -10,7 +10,7 @@ - +