/// <summary> /// Writes a list of all the shell commands in the specified assembly to the specified <see cref="TextWriter"/> using the specified formatting options. /// </summary> /// <param name="writer">The <see cref="TextWriter"/> to write the commands to.</param> /// <param name="assembly">The assembly that contains the shell commands.</param> /// <param name="commandFormat">The format string used to format a command's name and description, for example "{0,13} : {1}".</param> /// <exception cref="ArgumentNullException"> /// <paramref name="writer"/>, <paramref name="assembly"/> or <paramref name="commandFormat"/> is <see langword="null"/>. /// </exception> /// <remarks> /// <para> /// The <paramref name="commandFormat"/> should have two placeholders, which are used for the command name and description respectively. /// </para> /// <para> /// This method writes a list of all shell command names and their descriptions to <paramref name="writer"/>. /// </para> /// <para> /// A command's name is retrieved from its <see cref="ShellCommandAttribute"/> attribute, and the description is retrieved /// from its <see cref="DescriptionAttribute"/> attribute. /// </para> /// <para> /// If <paramref name="writer"/> is a <see cref="LineWrappingTextWriter"/>, the writer's indent will be reset before every /// command. It is recommended to set the <see cref="LineWrappingTextWriter.Indent"/> property to a value appropriate for /// your <paramref name="commandFormat"/>. /// </para> /// </remarks> public static void WriteAssemblyCommandList(TextWriter writer, Assembly assembly, string commandFormat) { if (writer == null) { throw new ArgumentNullException("writer"); } if (assembly == null) { throw new ArgumentNullException("assembly"); } if (commandFormat == null) { throw new ArgumentNullException("commandFormat"); } LineWrappingTextWriter lineWriter = writer as LineWrappingTextWriter; Type[] commandTypes = GetShellCommands(assembly); foreach (Type commandType in commandTypes) { string name = GetShellCommandName(commandType); string description = GetShellCommandDescription(commandType); if (lineWriter != null) { lineWriter.ResetIndent(); } writer.WriteLine(commandFormat, name, description ?? string.Empty); } }
/// <summary> /// Writes a list of all the shell commands in the specified assembly to the standard output stream. /// </summary> /// <param name="assembly">The assembly that contains the shell commands.</param> /// <exception cref="ArgumentNullException"> /// <paramref name="assembly"/> is <see langword="null"/>. /// </exception> /// <remarks> /// <para> /// This method writes a list of all shell command names and their descriptions to the standard output stream, wrapping /// the lines to fit on the console automatically. /// </para> /// <para> /// A command's name is retrieved from its <see cref="ShellCommandAttribute"/> attribute, and the description is retrieved /// from its <see cref="DescriptionAttribute"/> attribute. /// </para> /// <para> /// Line wrapping at word boundaries is applied to the output, wrapping at the console's window width. When the console output is /// redirected to a file, Microsoft .Net will still report the console's actual window width, but on Mono the value of /// the <see cref="Console.WindowWidth"/> property will be 0. In that case, the usage information will not be wrapped. /// </para> /// <para> /// This method indents additional lines for the command descriptions, unless the <see cref="Console.WindowWidth"/> property is less than 31. /// </para> /// </remarks> public static void WriteAssemblyCommandListToConsole(Assembly assembly) { using (LineWrappingTextWriter writer = LineWrappingTextWriter.ForConsoleOut()) { WriteAssemblyCommandList(writer, assembly); } }
/// <summary> /// Writes a list of all the shell commands in the specified assembly to the specified <see cref="TextWriter"/>. /// </summary> /// <param name="writer">The <see cref="TextWriter"/> to write the commands to.</param> /// <param name="assembly">The assembly that contains the shell commands.</param> /// <exception cref="ArgumentNullException"> /// <paramref name="writer"/> or <paramref name="assembly"/> is <see langword="null"/>. /// </exception> /// <remarks> /// <para> /// This method writes a list of all shell command names and their descriptions to <paramref name="writer"/>. /// </para> /// <para> /// A command's name is retrieved from its <see cref="ShellCommandAttribute"/> attribute, and the description is retrieved /// from its <see cref="DescriptionAttribute"/> attribute. /// </para> /// <para> /// If <paramref name="writer"/> is an instance of the <see cref="LineWrappingTextWriter"/> class, the <see cref="LineWrappingTextWriter.Indent"/> /// property will be set to a value appropriate for the formatting of the command list, and indenting will be reset before each command. Indenting /// will not be used if the <see cref="LineWrappingTextWriter.MaximumLineLength"/> is less than 30. /// </para> /// </remarks> public static void WriteAssemblyCommandList(TextWriter writer, Assembly assembly) { LineWrappingTextWriter lineWriter = writer as LineWrappingTextWriter; if (lineWriter != null) { lineWriter.Indent = lineWriter.MaximumLineLength < CommandLineParser.MaximumLineWidthForIndent ? 0 : 16; } WriteAssemblyCommandList(writer, assembly, Properties.Resources.DefaultCommandFormat); }
private static void WriteShellCommandListUsage(TextWriter output, Assembly assembly, CreateShellCommandOptions options) { output.WriteLine(options.CommandUsageFormat, options.UsageOptions.UsagePrefix); output.WriteLine(); output.WriteLine(options.AvailableCommandsHeader); output.WriteLine(); LineWrappingTextWriter lineWriter = output as LineWrappingTextWriter; if (lineWriter != null) { lineWriter.Indent = lineWriter.MaximumLineLength < CommandLineParser.MaximumLineWidthForIndent ? 0 : options.CommandDescriptionIndent; } WriteAssemblyCommandList(output, assembly, options.CommandDescriptionFormat); }
/// <summary> /// Finds and instantiates the shell command with the specified name, or if that fails, writes error and usage information to the specified writers. /// </summary> /// <param name="assembly">The assembly to search for the shell command.</param> /// <param name="commandName">The name of the command.</param> /// <param name="args">The arguments to the shell command.</param> /// <param name="index">The index in <paramref name="args"/> at which to start parsing the arguments.</param> /// <param name="options">The options to use.</param> /// <returns>An instance a class deriving from <see cref="ShellCommand"/>, or <see langword="null"/> if the command was not found or an error occurred parsing the arguments.</returns> /// <exception cref="ArgumentNullException"> /// <paramref name="assembly"/>, <paramref name="args"/>, or <paramref name="options"/> is <see langword="null"/> /// </exception> /// <exception cref="ArgumentOutOfRangeException"><paramref name="index"/> does not fall inside the bounds of <paramref name="args"/>.</exception> /// <remarks> /// <para> /// If the command could not be found, a list of possible commands is written to <see cref="CreateShellCommandOptions.Out"/>. If an error occurs parsing the command's arguments, the error /// message is written to <see cref="CreateShellCommandOptions.Error"/>, and the shell command's usage information is written to <see cref="CreateShellCommandOptions.Out"/>. /// </para> /// <para> /// If the <see cref="CreateShellCommandOptions.Out"/> property or <see cref="CreateShellCommandOptions.Error"/> property is <see langword="null"/>, output /// is written to the standard output and error streams respectively, with line wrapping at word boundaries applied to the output, wrapping at the console's window width. When the console output is /// redirected to a file, Microsoft .Net will still report the console's actual window width, but on Mono the value of /// the <see cref="Console.WindowWidth"/> property will be 0. In that case, the usage information will not be wrapped. /// </para> /// <para> /// If the <see cref="CreateShellCommandOptions.Out"/> property or <see cref="CreateShellCommandOptions.Error"/> property are instance of the /// <see cref="LineWrappingTextWriter"/> class, this method indents additional lines for the usage syntax and argument descriptions according /// to the values specified by the <see cref="CreateShellCommandOptions"/>, unless the <see cref="LineWrappingTextWriter.MaximumLineLength"/> property is less than 30. /// </para> /// </remarks> public static ShellCommand CreateShellCommand(Assembly assembly, string commandName, string[] args, int index, CreateShellCommandOptions options) { if (assembly == null) { throw new ArgumentNullException("assembly"); } if (args == null) { throw new ArgumentNullException("args"); } if (index < 0 || index > args.Length) { throw new ArgumentOutOfRangeException("index"); } if (options == null) { throw new ArgumentNullException("options"); } bool disposeOut = false; bool disposeError = false; TextWriter output = options.Out; TextWriter error = options.Error; try { if (output == null) { disposeOut = true; output = LineWrappingTextWriter.ForConsoleOut(); options.Out = output; } if (error == null) { disposeError = true; error = LineWrappingTextWriter.ForConsoleError(); options.Error = error; } Type commandType = commandName == null ? null : GetShellCommand(assembly, commandName, options.CommandNameComparer); if (commandType == null) { WriteShellCommandListUsage(output, assembly, options); } else if (CommandUsesCustomArgumentParsing(commandType)) { return((ShellCommand)Activator.CreateInstance(commandType, args, index, options)); } else { CommandLineParser parser = new CommandLineParser(commandType, options.ArgumentNamePrefixes, options.ArgumentNameComparer) { AllowDuplicateArguments = options.AllowDuplicateArguments, AllowWhiteSpaceValueSeparator = options.AllowWhiteSpaceValueSeparator, }; ShellCommand command = null; try { command = (ShellCommand)parser.Parse(args, index); } catch (CommandLineArgumentException ex) { error.WriteLine(ex.Message); error.WriteLine(); } if (command == null) { string originalPrefix = options.UsageOptions.UsagePrefix; options.UsageOptions.UsagePrefix += " " + GetShellCommandName(commandType); // If we're writing this to the console, output should already by a LineWrappingTextWriter, so the max line length argument here is ignored. parser.WriteUsage(output, 0, options.UsageOptions); options.UsageOptions.UsagePrefix = originalPrefix; } else { return(command); } } return(null); } finally { if (disposeOut && output != null) { output.Dispose(); } if (disposeError && error != null) { error.Dispose(); } } }