Skip to content

Commit

Permalink
Made more command descriptions Strings.* and refactored a few more me…
Browse files Browse the repository at this point in the history
…thods.
  • Loading branch information
CartBlanche committed May 22, 2024
1 parent 557d4fc commit 4627573
Show file tree
Hide file tree
Showing 3 changed files with 121 additions and 92 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

namespace Meadow.CLI.Commands.Current.Project
{
[Command("project install", Description = "Installs the latest project templates")]
[Command("project install", Description = Strings.ProjectTemplates.InstallCommandDescription)]
public class ProjectInstallCommand : BaseCommand<ProjectInstallCommand>
{
public ProjectInstallCommand(ILoggerFactory loggerFactory)
Expand All @@ -21,35 +21,36 @@ protected override async ValueTask ExecuteCommand()
{
AnsiConsole.MarkupLine(Strings.ProjectTemplates.InstallTitle);

// Install the templates (if they already exist it will update to the newest ones)
_ = await AppTools.RunDotNetCommand("dotnet", $"new install WildernessLabs.Meadow.Template", CancellationToken);
var templateList = await ProjectNewCommand.GetInstalledTemplates(LoggerFactory, Console, CancellationToken);

// Get the list of Meadow project templates
var templateTable = await AppTools.RunDotNetCommand("dotnet", "new list Meadow", CancellationToken);

// Extract template names from the output
var templateList = templateTable
.Skip(4) // Skip the header information
.Where(line => !string.IsNullOrWhiteSpace(line)) // Avoid empty lines
.Select(line => line.Trim()) // Clean whitespace
.ToList();
if (templateList != null)
{
DisplayInstalledTemplates(templateList);
}
else
{
Logger?.LogError(Strings.ProjectTemplates.ErrorInstallingTemplates);
}
}

private void DisplayInstalledTemplates(List<string> templateList)
{
// Use regex to split each line into segments using two or more spaces as the separator
var regex = new Regex(@"\s{2,}");

var table = new Table();
// Add some columns
table.AddColumn("Template Name");
table.AddColumn("Languages");
table.AddColumn(Strings.ProjectTemplates.ColumnTemplateName);
table.AddColumn(Strings.ProjectTemplates.ColumnLanguages);
foreach (var templatesLine in templateList)
{
// Isolate the long and short names
// Isolate the long and shortnames, as well as languages
var segments = regex.Split(templatesLine.Trim());
if (segments.Length >= 2)
{
// Add Key Value of Long Name and Short Name
var longName = segments[0].Trim();
var languages = segments[2].Replace("[",string.Empty).Replace("]",string.Empty).Trim();
var languages = segments[2].Replace("[", string.Empty).Replace("]", string.Empty).Trim();
table.AddRow(longName, languages);
}
}
Expand Down
169 changes: 95 additions & 74 deletions Source/v2/Meadow.CLI/Commands/Current/Project/ProjectNewCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@

namespace Meadow.CLI.Commands.Current.Project
{
[Command("project new", Description = "Shows a list of project templates to choose from.")]
[Command("project new", Description = Strings.ProjectTemplates.NewCommandDescription)]
public class ProjectNewCommand : BaseCommand<ProjectNewCommand>
{
[CommandOption('o', Description = Strings.ProjectTemplates.OutputPath, IsRequired = false)]
public string? OutputPath { get; private set; }
[CommandOption('o', Description = Strings.ProjectTemplates.CommandOptionOutputPathDescription, IsRequired = false)]
public string? OutputPath { get; private set; } = null;

[CommandOption('l', Description = "Generate the projects using the language specific. Valid values are C# or F# or VB", IsRequired = false)]
[CommandOption('l', Description = Strings.ProjectTemplates.CommandOptionSupportedLanguagesDescription, IsRequired = false)]
public string Language { get; private set; } = "C#";

private const string StartKit = "startkit";
Expand All @@ -29,36 +29,45 @@ public ProjectNewCommand(ILoggerFactory loggerFactory)
protected override async ValueTask ExecuteCommand()
{
AnsiConsole.MarkupLine(Strings.ProjectTemplates.WizardTitle);
List<string> templateTable = await GetInstalledTempaltes();

// Ask some pertinent questions
var projectName = AnsiConsole.Ask<string>(Strings.ProjectTemplates.ProjectName);
var templateList = await GetInstalledTemplates(LoggerFactory, Console, CancellationToken);

string outputPathArgument;
if (!string.IsNullOrWhiteSpace(OutputPath))
if (templateList != null)
{
outputPathArgument = $"--output {OutputPath}";
// Ask some pertinent questions
var projectName = AnsiConsole.Ask<string>(Strings.ProjectTemplates.ProjectName);

if (string.IsNullOrWhiteSpace(OutputPath))
{
OutputPath = projectName;
}

var outputPathArgument = $"--output {OutputPath}";

List<MeadowTemplate> selectedTemplates = GatherTemplateInformationFromUsers(templateList);

if (selectedTemplates.Count > 0)
{
await GenerateProjectsAndSolutionsFromSelectedTemplates(projectName, outputPathArgument, selectedTemplates);
}
else
{
AnsiConsole.MarkupLine($"[yellow]{Strings.ProjectTemplates.NoTemplateSelected}[/]");
}
}
else
{
outputPathArgument = $"--output {projectName}";
OutputPath = projectName;
Logger?.LogError(Strings.ProjectTemplates.ErrorInstallingTemplates);
}
}

var generateSln = AnsiConsole.Confirm(Strings.ProjectTemplates.GenerateSln);

// Extract template names from the output
var templateList = templateTable
.Skip(4) // Skip the header information
.Where(line => !string.IsNullOrWhiteSpace(line)) // Avoid empty lines
.Select(line => line.Trim()) // Clean whitespace
.ToList();

private List<MeadowTemplate> GatherTemplateInformationFromUsers(List<string> templateList)
{
var templateNames = new List<MeadowTemplate>();
MeadowTemplate? startKitGroup = null;
List<MeadowTemplate> startKitTemplates = new List<MeadowTemplate>();

startKitGroup = PopulateTemplateList(templateList, templateNames, startKitGroup, startKitTemplates);
startKitGroup = PopulateTemplateNameList(templateList, templateNames, startKitGroup, startKitTemplates);

var multiSelectionPrompt = new MultiSelectionPrompt<MeadowTemplate>()
.Title(Strings.ProjectTemplates.InstalledTemplates)
Expand All @@ -77,20 +86,15 @@ protected override async ValueTask ExecuteCommand()
multiSelectionPrompt.AddChoices(templateNames);

var selectedTemplates = AnsiConsole.Prompt(multiSelectionPrompt);

if (selectedTemplates.Count > 0)
{
await GenerateProjectsFromSelectedTemplates(projectName, outputPathArgument, generateSln, selectedTemplates);
}
else
{
AnsiConsole.MarkupLine($"[yellow]{Strings.ProjectTemplates.NoTemplateSelected}[/]");
}
return selectedTemplates;
}

private async Task GenerateProjectsFromSelectedTemplates(string projectName, string outputPathArgument, bool generateSln, List<MeadowTemplate> selectedTemplates)
private async Task GenerateProjectsAndSolutionsFromSelectedTemplates(string projectName, string outputPathArgument, List<MeadowTemplate> selectedTemplates)
{
string generatedProjectName = projectName;

var generateSln = AnsiConsole.Confirm(Strings.ProjectTemplates.GenerateSln);

// Create the selected templates
foreach (var selectedTemplate in selectedTemplates)
{
Expand All @@ -105,14 +109,14 @@ private async Task GenerateProjectsFromSelectedTemplates(string projectName, str
var match = regexBracketText.Match(selectedTemplate.Name);
if (match.Success)
{
outputPath = Path.Combine(OutputPath, $"{OutputPath}.{match.Groups[1].Value}");
outputPath = Path.Combine(OutputPath!, $"{OutputPath}.{match.Groups[1].Value}");
outputPathArgument = "--output " + outputPath;
}
}
}
else
{
outputPath = Path.Combine(OutputPath, $"{OutputPath}.{selectedTemplate.ShortName}");
outputPath = Path.Combine(OutputPath!, $"{OutputPath}.{selectedTemplate.ShortName}");
outputPathArgument = "--output " + outputPath;
generatedProjectName = $"{projectName}.{selectedTemplate.ShortName}";
}
Expand All @@ -122,45 +126,50 @@ private async Task GenerateProjectsFromSelectedTemplates(string projectName, str

if (generateSln)
{
AnsiConsole.MarkupLine($"[green]{Strings.ProjectTemplates.CreatingSln}[/]");
await GenerateSolution(projectName);
}

// Create the sln
_ = await AppTools.RunDotNetCommand("dotnet", $"new sln -n {projectName} -o {OutputPath} --force", CancellationToken);
AnsiConsole.MarkupLine(Strings.ProjectTemplates.GenerationComplete, $"[green]{projectName}[/]");
}

//Now add to the new sln
var slnFilePath = Path.Combine(OutputPath, projectName + ".sln");
private async Task GenerateSolution(string projectName)
{
AnsiConsole.MarkupLine($"[green]{Strings.ProjectTemplates.CreatingSln}[/]");

var searchWildCard = string.Empty;
switch (Language)
{
case "C#":
searchWildCard = "*.csproj";
break;
case "F#":
searchWildCard = "*.fsproj";
break;
case "VB":
searchWildCard = "*.vbproj";
break;
default:
searchWildCard = "*.csproj";
break;
}
// Create the sln
_ = await AppTools.RunDotNetCommand("dotnet", $"new sln -n {projectName} -o {OutputPath} --force", CancellationToken);

// get all the project files and add them to the sln
var projectFiles = Directory.EnumerateFiles(OutputPath, searchWildCard, SearchOption.AllDirectories);
foreach (var projectFile in projectFiles)
{
_ = await AppTools.RunDotNetCommand("dotnet", $"sln {slnFilePath} add {projectFile}", CancellationToken);
}
//Now add to the new sln
var slnFilePath = Path.Combine(OutputPath!, projectName + ".sln");

OpenSolution(slnFilePath);
string? searchWildCard;
switch (Language)
{
case "C#":
searchWildCard = "*.csproj";
break;
case "F#":
searchWildCard = "*.fsproj";
break;
case "VB":
searchWildCard = "*.vbproj";
break;
default:
searchWildCard = "*.csproj";
break;
}

AnsiConsole.MarkupLine(Strings.ProjectTemplates.GenerationComplete, $"[green]{projectName}[/]");
// get all the project files and add them to the sln
var projectFiles = Directory.EnumerateFiles(OutputPath!, searchWildCard, SearchOption.AllDirectories);
foreach (var projectFile in projectFiles)
{
_ = await AppTools.RunDotNetCommand("dotnet", $"sln {slnFilePath} add {projectFile}", CancellationToken);
}

OpenSolution(slnFilePath);
}

private static MeadowTemplate? PopulateTemplateList(List<string> templateList, List<MeadowTemplate> templateNames, MeadowTemplate? startKitGroup, List<MeadowTemplate> startKitTemplates)
private MeadowTemplate? PopulateTemplateNameList(List<string> templateList, List<MeadowTemplate> templateNameList, MeadowTemplate? startKitGroup, List<MeadowTemplate> startKitTemplates)
{
// Use regex to split each line into segments using two or more spaces as the separator
var regexTemplateLines = new Regex(@"\s{2,}");
Expand Down Expand Up @@ -188,31 +197,43 @@ private async Task GenerateProjectsFromSelectedTemplates(string projectName, str
}
else
{
templateNames.Add(new MeadowTemplate($"{longName} ({languages})", shortName));
templateNameList.Add(new MeadowTemplate($"{longName} ({languages})", shortName));
}
}
}

return startKitGroup;
}

private async Task<List<string>> GetInstalledTempaltes()
internal static async Task<List<string>?> GetInstalledTemplates(ILoggerFactory loggerFactory, CliFx.Infrastructure.IConsole console, CancellationToken cancellationToken)
{
// Get the list of Meadow project templates
var templateTable = await AppTools.RunDotNetCommand("dotnet", "new list Meadow", CancellationToken);
var templateTable = await AppTools.RunDotNetCommand("dotnet", "new list Meadow", cancellationToken);

// If not templates exists, then for now we automagically install them before proceeding
if (templateTable.Count == 0)
// If no templates exists, then for now we automagically install them before proceeding
if (templateTable != null)
{
AnsiConsole.MarkupLine($"[yellow]{Strings.ProjectTemplates.NoTemplatesFound}[/]");
var projectInstallCommand = new ProjectInstallCommand(LoggerFactory);
if (templateTable.Count == 0)
{
AnsiConsole.MarkupLine($"[yellow]{Strings.ProjectTemplates.NoTemplatesFound}[/]");
var projectInstallCommand = new ProjectInstallCommand(loggerFactory);

await projectInstallCommand.ExecuteAsync(console);

templateTable = await AppTools.RunDotNetCommand("dotnet", "new list Meadow", cancellationToken);
}

await projectInstallCommand.ExecuteAsync(Console);
// Extract template names from the output
var templateNameList = templateTable
.Skip(4) // Skip the header information
.Where(line => !string.IsNullOrWhiteSpace(line)) // Avoid empty lines
.Select(line => line.Trim()) // Clean whitespace
.ToList();

templateTable = await AppTools.RunDotNetCommand("dotnet", "new list Meadow", CancellationToken);
return templateNameList;
}

return templateTable;
return null;
}

private void OpenSolution(string solutionPath)
Expand Down
11 changes: 9 additions & 2 deletions Source/v2/Meadow.Cli/Strings.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Meadow.Telemetry;
using Spectre.Console;

namespace Meadow.CLI;

Expand Down Expand Up @@ -90,18 +91,24 @@ public static class ProjectTemplates
public const string InstallTitle = "Installing and updating the Meadow Project Templates";
public const string Installed = "The following Meadow Project Templates are now installed.";

public const string OutputPath = "The path where you would like the projects created.";
public const string WizardTitle = "Meadow Project Wizard...";
public const string ProjectName = "What is your project's name?";
public const string GenerationComplete = "All of {0}'s projects have now been created!";
public const string GenerateSln = "Create an sln that contains all the new projects?";
public const string NoTemplatesFound = "No Meadow project templates found.\n";
public const string NoTemplatesFound = "No Meadow project templates found.";
public const string InstalledTemplates = "--- Installed Templates ---";
public const string MoreChoicesInstructions = "(Move up and down to reveal more templates)";
public const string Instructions = "Press {0} to toggle a template or {1} to accept and generate the selected templates)";
public const string CreatingProject = "Creating {0} project";
public const string CreatingSln = "Creating sln for selected projects....";
public const string NoTemplateSelected = "No templates selected.";
public const string NewCommandDescription = "Shows a list of project templates to choose from.";
public const string CommandOptionOutputPathDescription = "The path where you would like the projects created.";
public const string CommandOptionSupportedLanguagesDescription = "Generate the projects using the specified language. Valid values are C# or F# or VB.NET";
public const string InstallCommandDescription = "Install or updates to the latest project templates";
public const string ErrorInstallingTemplates = "An error occured install the templates. Check that your internet connection is working.";
public const string ColumnTemplateName = "Template Name";
public const string ColumnLanguages = "Languages";
}

public const string UnsupportedOperatingSystem = "Unsupported Operating System";
Expand Down

0 comments on commit 4627573

Please sign in to comment.