From 4d344c8cc337ec54047dc52aac3854d2c090d917 Mon Sep 17 00:00:00 2001 From: Josef Pihrt Date: Wed, 23 Aug 2023 22:31:13 +0200 Subject: [PATCH 1/2] Open help in web browser --- src/CommandLine/Commands/HelpCommand.cs | 163 ++++++++---------- src/CommandLine/OptionShortNames.cs | 1 - .../Options/HelpCommandLineOptions.cs | 8 +- src/CommandLine/Program.cs | 17 +- 4 files changed, 72 insertions(+), 117 deletions(-) diff --git a/src/CommandLine/Commands/HelpCommand.cs b/src/CommandLine/Commands/HelpCommand.cs index 4c3639e124..51e9c306c1 100644 --- a/src/CommandLine/Commands/HelpCommand.cs +++ b/src/CommandLine/Commands/HelpCommand.cs @@ -3,8 +3,10 @@ using System; using System.Collections.Generic; using System.Collections.Immutable; +using System.Diagnostics; using System.Linq; using System.Reflection; +using System.Runtime.InteropServices; using Roslynator.CommandLine.Help; using static Roslynator.Logger; @@ -12,26 +14,34 @@ namespace Roslynator.CommandLine; internal class HelpCommand { - public HelpCommand(HelpCommandLineOptions options, Filter filter) + public HelpCommand(HelpCommandLineOptions options) { Options = options; - Filter = filter; } public HelpCommandLineOptions Options { get; } - public Filter Filter { get; } - public CommandStatus Execute() { try { - WriteHelp( - commandName: Options.Command, - online: false, - manual: Options.Manual, - includeValues: ConsoleOut.Verbosity > Verbosity.Normal, - filter: Filter); + if (Options.Manual) + { + WriteManual(); + } + else if (Options.Command is not null) + { + Command command = CommandLoader.LoadCommand(typeof(HelpCommand).Assembly, Options.Command); + + if (command is null) + throw new InvalidOperationException($"Command '{Options.Command}' does not exist."); + + OpenHelpInBrowser(Options.Command); + } + else + { + WriteCommandsHelp(); + } return CommandStatus.Success; } @@ -42,136 +52,103 @@ public CommandStatus Execute() } } - private static void WriteHelp( - string commandName, - bool online, - bool manual, - bool includeValues, - Filter filter = null) + private static void OpenHelpInBrowser(string commandName) { - if (online) - { - OpenHelpInBrowser(commandName); - } - else if (commandName is not null) - { - Command command = CommandLoader.LoadCommand(typeof(HelpCommand).Assembly, commandName); + var url = "https://josefpihrt.github.io/docs/roslynator/cli"; - if (command is null) - throw new InvalidOperationException($"Command '{commandName}' does not exist."); + if (commandName is not null) + url += $"/commands/{commandName}"; - WriteCommandHelp(command, includeValues: includeValues, filter: filter); - } - else if (manual) + try { - WriteManual(includeValues: includeValues, filter: filter); + Process.Start(url); } - else + catch { - WriteCommandsHelp(includeValues: includeValues, filter: filter); - } - } + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + var psi = new ProcessStartInfo() + { + FileName = url, + UseShellExecute = true + }; - [System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE0060:Remove unused parameter")] - private static void OpenHelpInBrowser(string commandName) - { - throw new NotSupportedException(); + Process.Start(psi); + } + else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { + Process.Start("xdg-open", url); + } + else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + { + Process.Start("open", url); + } + else + { + throw; + } + } } - public static void WriteCommandHelp(Command command, bool includeValues = false, Filter filter = null) + public static void WriteCommandHelp(Command command) { - var writer = new ConsoleHelpWriter(new HelpWriterOptions(filter: filter)); + var writer = new ConsoleHelpWriter(); command = command.WithOptions(command.Options.Sort(CommandOptionComparer.Name)); - CommandHelp commandHelp = CommandHelp.Create(command, providers: null, filter: filter); + CommandHelp commandHelp = CommandHelp.Create(command); writer.WriteCommand(commandHelp); - - if (includeValues) - writer.WriteValues(commandHelp.Values); } - public static void WriteCommandsHelp(bool includeValues = false, Filter filter = null) + public static void WriteCommandsHelp() { IEnumerable commands = LoadCommands().Where(f => f.Name != "help"); - CommandsHelp commandsHelp = CommandsHelp.Create(commands, providers: null, filter: filter); + CommandsHelp commandsHelp = CommandsHelp.Create(commands); - var writer = new ConsoleHelpWriter(new HelpWriterOptions(filter: filter)); + var writer = new ConsoleHelpWriter(new HelpWriterOptions()); writer.WriteCommands(commandsHelp); - if (includeValues) - writer.WriteValues(commandsHelp.Values); - WriteLine(); WriteLine(GetFooterText()); } - private static void WriteManual(bool includeValues = false, Filter filter = null) + private static void WriteManual() { IEnumerable commands = LoadCommands(); - var writer = new ConsoleHelpWriter(new HelpWriterOptions(filter: filter)); + var writer = new ConsoleHelpWriter(); - IEnumerable commandHelps = commands.Select(f => CommandHelp.Create(f, filter: filter)) + IEnumerable commandHelps = commands.Select(f => CommandHelp.Create(f)) .Where(f => f.Arguments.Any() || f.Options.Any()) .ToImmutableArray(); ImmutableArray commandItems = HelpProvider.GetCommandItems(commandHelps.Select(f => f.Command)); - ImmutableArray values = ImmutableArray.Empty; + var commandsHelp = new CommandsHelp(commandItems, ImmutableArray.Empty); - if (commandItems.Any()) - { - values = HelpProvider.GetOptionValues( - commandHelps.SelectMany(f => f.Command.Options), - providers: ImmutableArray.Empty, - filter); + writer.WriteCommands(commandsHelp); - var commandsHelp = new CommandsHelp(commandItems, values); + foreach (CommandHelp commandHelp in commandHelps) + { + WriteSeparator(); + WriteLine(); + WriteLine($"Command: {commandHelp.Name}"); + WriteLine(); - writer.WriteCommands(commandsHelp); + string description = commandHelp.Description; - foreach (CommandHelp commandHelp in commandHelps) + if (!string.IsNullOrEmpty(description)) { - WriteSeparator(); + WriteLine(description); WriteLine(); - WriteLine($"Command: {commandHelp.Name}"); - WriteLine(); - - string description = commandHelp.Description; - - if (!string.IsNullOrEmpty(description)) - { - WriteLine(description); - WriteLine(); - } - - writer.WriteCommand(commandHelp); } - if (includeValues) - WriteSeparator(); - } - else - { - WriteLine(); - WriteLine("No command found"); - - if (includeValues) - { - values = HelpProvider.GetOptionValues( - commands.Select(f => CommandHelp.Create(f)).SelectMany(f => f.Command.Options), - providers: ImmutableArray.Empty, - filter); - } + writer.WriteCommand(commandHelp); } - if (includeValues) - writer.WriteValues(values); - static void WriteSeparator() { WriteLine(); diff --git a/src/CommandLine/OptionShortNames.cs b/src/CommandLine/OptionShortNames.cs index 613350579e..1ffee59130 100644 --- a/src/CommandLine/OptionShortNames.cs +++ b/src/CommandLine/OptionShortNames.cs @@ -6,7 +6,6 @@ internal static class OptionShortNames { public const char AnalyzerAssemblies = 'a'; public const char DryRun = 'd'; - public const char Filter = 'f'; public const char IncludeGeneratedCode = 'g'; public const char Help = 'h'; public const char Manual = 'm'; diff --git a/src/CommandLine/Options/HelpCommandLineOptions.cs b/src/CommandLine/Options/HelpCommandLineOptions.cs index 842c47b139..b0826b9e55 100644 --- a/src/CommandLine/Options/HelpCommandLineOptions.cs +++ b/src/CommandLine/Options/HelpCommandLineOptions.cs @@ -12,13 +12,7 @@ internal sealed class HelpCommandLineOptions : AbstractCommandLineOptions HelpText = "Command name.", MetaName = "")] public string Command { get; set; } = null!; -#if DEBUG - [Option( - shortName: OptionShortNames.Filter, - longName: "filter", - HelpText = "Search phrase to filter the results.")] - public string Filter { get; set; } -#endif + [Option( shortName: OptionShortNames.Manual, longName: "manual", diff --git a/src/CommandLine/Program.cs b/src/CommandLine/Program.cs index 85d3855d5d..160b4adc29 100644 --- a/src/CommandLine/Program.cs +++ b/src/CommandLine/Program.cs @@ -492,22 +492,7 @@ private static async Task RenameSymbolAsync(RenameSymbolCommandLineOptions private static int Help(HelpCommandLineOptions options) { - Filter filter = null; -#if DEBUG - if (!string.IsNullOrEmpty(options.Filter)) - { - try - { - filter = new Filter(new Regex(options.Filter, RegexOptions.IgnoreCase)); - } - catch (ArgumentException ex) - { - WriteLine($"Filter is invalid: {ex.Message}", Verbosity.Quiet); - return ExitCodes.Error; - } - } -#endif - var command = new HelpCommand(options: options, filter); + var command = new HelpCommand(options: options); CommandStatus status = command.Execute(); From 5f4afd055dc2999285afa8b18eaa68a72d5ea357 Mon Sep 17 00:00:00 2001 From: Josef Pihrt Date: Wed, 23 Aug 2023 22:33:26 +0200 Subject: [PATCH 2/2] update --- ChangeLog.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ChangeLog.md b/ChangeLog.md index 1c4f0aa3eb..788cb50076 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -27,6 +27,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Remove empty region directive ([RCS1091](https://josefpihrt.github.io/docs/roslynator/analyzers/RCS1091)) - Remove empty destructor ([RCS1106](https://josefpihrt.github.io/docs/roslynator/analyzers/RCS1106)) +### Changed + +- [CLI] Open help in web browser when running command `roslynator help ` ([#1179](https://github.com/josefpihrt/roslynator/pull/1179)) + ### Fixed - Fix [RCS1187](https://josefpihrt.github.io/docs/roslynator/analyzers/RCS1187) ([#1150](https://github.com/JosefPihrt/Roslynator/pull/1150)).