Free cookie consent management tool by TermsFeed Policy Generator

source: branches/2924_DotNetCoreMigration/HeuristicLab.CommandLineInterface/CLIConsole.cs @ 17039

Last change on this file since 17039 was 16998, checked in by dpiringe, 5 years ago

#2924:

  • in project HeuristicLab.CommandLineInterface changed output for options -> hidden options are not shown in the help box anymore
  • in project HeuristicLab.DynamicAssemblyTestApp:
    • added ApplicationAttributes
    • added full cancel/pause/resume support for class AppTest to test the same behaviour between main and child process
  • in project HeuristicLab:
    • changed auto generated Dockerfile -> only copies necessary projects -> speeds up the build process
    • in file HeuristicLab-3.3.csproj:
      • changed DockerDefaultTargetOS to Linux
      • removed reference HeuristicLab.DefinitionLanguage
      • added icon and manifest
    • deleted folder Properties with file launchSettings.json
    • changed the direct access to ApplicationTypes for OptimizeCommand and InspectCommand to new method IApplicationManager.GetInstances<T>(params object[] args)
  • added build script for docker image dockerImageBuild.ps1
File size: 8.5 KB
Line 
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Text;
5using HeuristicLab.CommandLineInterface.Data;
6using HeuristicLab.Common;
7
8namespace HeuristicLab.CommandLineInterface {
9  /// <summary>
10  /// Static class with output methods.
11  /// </summary>
12  public static class CLIConsole {
13
14    #region Constants
15    private const int Padding = 2;
16    private const int ShortcutWidth = 4;
17    private const int LRowWidth = 20;
18    private const int MRowWidth = 20;
19    private const int RRowWidth = 60;
20    #endregion
21
22    /// <summary>
23    /// Prints the help to the console based on the data saved in CommandData.
24    /// </summary>
25    /// <param name="cmdData"></param>
26    /// <param name="errors"></param>
27    internal static void PrintHelp(CommandData cmdData, Exception exception = null) {
28      WriteHeader(cmdData);
29
30      if (exception != null) WriteErrors(exception);
31
32      WriteSyntax(cmdData);
33
34      if (cmdData.Options.Count > 0) {
35        WriteOptionBox(cmdData);
36        Console.WriteLine();
37      }
38
39      if (cmdData.Commands.Count > 0) WriteCommandBox(cmdData);
40
41      //Exit the application after every help call.
42      Environment.Exit((exception != null) ? 1 : 0);
43    }
44
45    #region PrintHelp steps
46    /// <summary>
47    /// Writes the header of the help.
48    /// </summary>
49    /// <param name="cmdData"></param>
50    private static void WriteHeader(CommandData cmdData) {
51      Console.WriteLine($"{CLIApplication.AppName} {CLIApplication.AppVersion}");
52      if (cmdData.Description != null)
53        Console.WriteLine($"{cmdData.Description}");
54      Console.WriteLine();
55    }
56
57    /// <summary>
58    /// Writes an list of errors.
59    /// </summary>
60    /// <param name="errors"></param>
61    private static void WriteErrors(Exception exception) {
62      Console.WriteLine($"ERROR(S):");
63      AggregateException ae = exception as AggregateException;
64      if (ae != null) {
65        foreach (var e in ae.InnerExceptions) {
66          Console.WriteLine($"  -> {e} ");
67        }
68      } else {
69        Console.WriteLine($"  -> {exception}");
70      }
71      Console.WriteLine();
72    }
73
74    /// <summary>
75    /// Writes the syntax of a specific command.
76    /// </summary>
77    /// <param name="cmdData"></param>
78    private static void WriteSyntax(CommandData cmdData) {
79      Console.Write($"Syntax: {BuildParentCommandString(cmdData).ToLower()}{cmdData.Identifier.ToLower()}");
80      if (cmdData.Options.Count > 0) Console.Write(" [OPTION]");
81      if (cmdData.Commands.Count > 0) Console.Write(" COMMAND");
82      string valueSyntax = BuildValueSyntaxString(cmdData);
83      Console.WriteLine(" " + valueSyntax);
84      Console.WriteLine();
85    }
86
87    /// <summary>
88    /// Writes the help box for the options of a specific command.
89    /// </summary>
90    /// <param name="cmdData"></param>
91    private static void WriteOptionBox(CommandData cmdData) {
92      WriteBoxSeparatorLine();
93      WriteBoxLine("Option", "Parameter", "Description");
94      WriteBoxSeparatorLine();
95      foreach (OptionData opt in cmdData.Options)
96        if (!opt.Hidden)
97          WriteBoxLine(
98            ((opt.Shortcut != null) ?
99              $"{(OptionData.ShortcutPrefix + opt.Shortcut).ToLower() + ",",-ShortcutWidth}" :
100              $""
101            ) +
102            $"{(OptionData.LongformPrefix + opt.Identifier).ToLower()}",
103            opt.Property?.PropertyType.GetPrettyName(),
104            opt.Description
105          );
106      WriteBoxSeparatorLine();
107    }
108
109    /// <summary>
110    /// Writes the help box for the commands of a specific command.
111    /// </summary>
112    /// <param name="cmdData"></param>
113    private static void WriteCommandBox(CommandData cmdData) {
114      WriteBoxSeparatorLine();
115      WriteBoxLine("Commands", "Parameter", "Description");
116      WriteBoxSeparatorLine();
117      foreach (CommandData c in cmdData.Commands)
118        WriteBoxLine(c.Identifier.ToLower(), BuildValueSyntaxString(c), c.Description);
119      WriteBoxSeparatorLine();
120      Console.WriteLine();
121      Console.WriteLine($"Enter \"{BuildParentCommandString(cmdData).ToLower()}" +
122        $"{cmdData.Identifier.ToLower()} COMMAND --help\" to show more information for a command.");
123    }
124
125    /// <summary>
126    /// Writes a horizontal seperator line. Used to print a help box.
127    /// </summary>
128    /// <param name="edge"></param>
129    /// <param name="fill"></param>
130    private static void WriteBoxSeparatorLine(char edge = '+', char fill = '-') {
131      Console.Write($"{edge}");
132      WriteChar(4 * Padding + LRowWidth + MRowWidth + RRowWidth, fill);
133      Console.Write($"{edge}\n");
134    }
135
136    /// <summary>
137    /// Writes a single line for the help box.
138    /// </summary>
139    /// <param name="lrow"></param>
140    /// <param name="mrow"></param>
141    /// <param name="rrow"></param>
142    private static void WriteBoxLine(string lrow, string mrow, string rrow) {
143      IList<string> lf = FitBoxString(lrow ?? "", LRowWidth);
144      IList<string> mf = FitBoxString(mrow ?? "", MRowWidth);
145      IList<string> rf = FitBoxString(rrow ?? "", RRowWidth);
146
147      // to correctly print lines.
148      for (int i = 0; i < lf.Count || i < mf.Count || i < rf.Count; ++i) {
149        Console.Write($"|{"",Padding}");
150        if (i < lf.Count) Console.Write($"{lf[i],-LRowWidth}");
151        else Console.Write($"{"",-LRowWidth}");
152        Console.Write($"{"",Padding}");
153        if (i < mf.Count) Console.Write($"{mf[i],-MRowWidth}");
154        else Console.Write($"{"",-MRowWidth}");
155        Console.Write($"{"",Padding}");
156        if (i < rf.Count) Console.Write($"{rf[i],-RRowWidth}");
157        else Console.Write($"{"",-RRowWidth}");
158        Console.Write($"{"",-Padding}|\n");
159      }
160    }
161    #endregion
162
163    #region Helper
164    /// <summary>
165    /// Iterates through command values and creates a string with their type name.
166    /// </summary>
167    /// <param name="cmdData"></param>
168    /// <returns>A string with the type names of the command's values.</returns>
169    private static string BuildValueSyntaxString(CommandData cmdData) {
170      StringBuilder additionalSyntax = new StringBuilder();
171      int i = 0;
172      foreach (var x in cmdData.Values) {
173        additionalSyntax.Append(x.Property.PropertyType.GetPrettyName());
174        if ((i + 1) < cmdData.Values.Count) additionalSyntax.Append(" ");
175      }
176      return additionalSyntax.ToString();
177    }
178
179    /// <summary>
180    /// Iterates through parent commends of specified commends to create a valid parent command string.
181    /// For example: MyRootCommand Command1 ChildOfCommand1 ...
182    /// </summary>
183    /// <param name="cmdData"></param>
184    /// <returns>A string with parent commends.</returns>
185    private static string BuildParentCommandString(CommandData cmdData) {
186      StringBuilder builder = new StringBuilder();
187
188      CommandData p = cmdData.Parent;
189      IList<CommandData> cmds = new List<CommandData>();
190      while (p != null) {
191        cmds.Add(p);
192        p = p.Parent;
193      }
194      cmds.Reverse();
195
196      foreach (CommandData parent in cmds) builder.Append($"{parent.Identifier} ");
197      return builder.ToString();
198    }
199
200    /// <summary>
201    /// Fits a string to specified width.
202    /// </summary>
203    /// <param name="str"></param>
204    /// <param name="width"></param>
205    /// <returns>Array of string, which stands for lines.</returns>
206    private static IList<string> FitBoxString(string str, int width) {
207      string[] splits = str.Split(' ');
208      IList<string> list = new List<string>();
209      string line = "";
210      foreach (string split in splits) {
211        string tmp = split;
212        if (tmp.Length > width) // if a word is longer then the specified width, it gets "cutted" into multiple lines.
213          while (tmp.Length > width - line.Length) {
214            list.Add(line + tmp.Substring(0, width - line.Length));
215            tmp = tmp.Substring(width - line.Length);
216            line = "";
217          }
218        if (line.Length + tmp.Length <= width - 1) line += tmp + " ";
219        else {
220          list.Add(line);
221          line = tmp;
222        }
223      }
224      if (!string.IsNullOrEmpty(line)) list.Add(line);
225      return list;
226    }
227
228    /// <summary>
229    /// Writes a specific char multiple times.
230    /// </summary>
231    /// <param name="iterations"></param>
232    /// <param name="ch"></param>
233    private static void WriteChar(int iterations = 1, char ch = '-') {
234      for (int i = 0; i < iterations; ++i) Console.Write(ch);
235    }
236    #endregion
237  }
238}
Note: See TracBrowser for help on using the repository browser.