Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

renaming status context to environment and adding environment vars #21

Merged
merged 1 commit into from
May 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -348,3 +348,4 @@ MigrationBackup/

# Ionide (cross platform F# VS Code tools) working folder
.ionide/
/src.bak
21 changes: 15 additions & 6 deletions src/Xcaciv.Command.FileLoader/Crawler.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using System.Collections.Concurrent;
using System.Diagnostics;
using System.IO.Abstractions;
using Xcaciv.Command.Interface;
using Xcaciv.Command.Interface.Attributes;
using Xcaciv.Command.Interface.Exceptions;
using Xcaciv.Loader;

Expand Down Expand Up @@ -62,13 +64,20 @@ public IDictionary<string, PackageDescription> LoadPackageDescriptions(string ba
{
if (commandType == null) continue; // not sure why it could be null, but the compiler says so

var command = context.CreateInstance<ICommandDelegate>(commandType);
commands[command.BaseCommand] = new CommandDescription()
// required to have BaseCommandAttribute,
if (Attribute.GetCustomAttribute(commandType, typeof(BaseCommandAttribute)) is BaseCommandAttribute attributes)
{
BaseCommand = command.BaseCommand,
FullTypeName = command.GetType().FullName ?? String.Empty,
PackageDescription = packagDesc
};
commands[attributes.Command] = new CommandDescription()
{
BaseCommand = attributes.Command,
FullTypeName = commandType.FullName ?? String.Empty,
PackageDescription = packagDesc
};
}
else
{
Debug.WriteLine($"{commandType.FullName} implements ICommandDelegate but does not have BaseCommandAttribute. Unable to automatically register.");
}
}

packagDesc.Commands = commands;
Expand Down
43 changes: 43 additions & 0 deletions src/Xcaciv.Command.Interface/Attributes/BaseCommandAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Xcaciv.Command.Interface.Attributes
{
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
public class BaseCommandAttribute : Attribute
{
private string _command;
/// <summary>
/// define how this command is to be called
/// </summary>
/// <param name="command"></param>
/// <param name="description"></param>
public BaseCommandAttribute(string command = "", string description = "")
{
this._command = command.ToUpper();
this.Description = description;
}
/// <summary>
/// the base command string
/// </summary>
/// <example>DIR</example>
public string Command {
get
{ return this._command; }
set
{ this._command = value.ToUpper(); }
}
/// <summary>
/// What does this command do
/// </summary>
public string Description { get; set; } = "TODO";
/// <summary>
/// Prototype/example of how to call the command with parameters parameters
/// </summary>
/// <example>CMD [-A | -U] [-Q] [-D] [-E ON | OFF]</example>
public string Prototype { get; set; } = "TODO";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Xcaciv.Command.Interface.Attributes
{
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = false)]
public class CommandHelpRemarksAttribute : Attribute
{
/// <summary>
/// add remarks to help output
/// </summary>
/// <param name="remarks"></param>
public CommandHelpRemarksAttribute(string remarks)
{
this.Remarks = remarks;
}
/// <summary>
/// further explination to be displayed in help
/// </summary>
public string Remarks { get; set; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Xcaciv.Command.Interface.Attributes
{
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = false)]
public class CommandParameterAttribute : Attribute
{
private string _valueName = "TODO";

public CommandParameterAttribute(string name, string description = "")
{
this.ValueName = name;
}

public CommandParameterAttribute(string flagname, string name, string description = "")
{
this.FlagName = flagname;
this.ValueName = name;
}

public CommandParameterAttribute(string abbrFlag, string flagname, string name, string description = "")
{
this.AbbrFlagName = abbrFlag;
this.FlagName = flagname;
this.ValueName = name;
}

public string AbbrFlagName { get; } = "";
public string FlagName { get; set; } = "";

public string ValueName
{
get { return _valueName; }
set { _valueName = String.Format(@"<{0}>", value.Trim('>').Trim(']')); }
}

public string ValueDescription { get; set; } = "";

public override string ToString()
{
return $"{AbbrFlagName} {FlagName} \t {_valueName} \t {ValueDescription}".Trim();
}
}
}
4 changes: 4 additions & 0 deletions src/Xcaciv.Command.Interface/CommandDescription.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,8 @@ public class CommandDescription
/// full path to containing assembly
/// </summary>
public PackageDescription PackageDescription { get; set; } = new PackageDescription();
/// <summary>
/// explicitly indicates if a command modifes the environment
/// </summary>
public bool ModifiesEnvironment { get; set; }
}
8 changes: 0 additions & 8 deletions src/Xcaciv.Command.Interface/ICommandDelegate.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,6 @@ namespace Xcaciv.Command.Interface
/// </summary>
public interface ICommandDelegate : IAsyncDisposable
{
/// <summary>
/// unique typed command - alphanumeric with dash or underscore
/// </summary>
string BaseCommand { get; }
/// <summary>
/// Display name - may contain special characters
/// </summary>
string FriendlyName { get; }
/// <summary>
/// primary command execution method
/// </summary>
Expand Down
14 changes: 14 additions & 0 deletions src/Xcaciv.Command.Interface/IEnvironment.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,5 +51,19 @@ public interface IEnvironment
/// <param name="key"></param>
/// <returns>String.Empty if not found</returns>
string GetValue(string key);
/// <summary>
/// captures the environment values and returns them
/// </summary>
/// <returns></returns>
Dictionary<string, string> GetEnvinronment();
/// <summary>
/// indicates that the environment variables has changed
/// </summary>
bool ValuesChanged { get; }
/// <summary>
/// sync values in envronment
/// </summary>
/// <param name="dictionary"></param>
void UpdateEnvironment(Dictionary<string, string> dictionary);
}
}
2 changes: 1 addition & 1 deletion src/Xcaciv.Command.Interface/ITextIoContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,5 @@ public interface ITextIoContext : IEnvironment, IInputContext, IOutputContext, I
/// <param name="childArguments">arguments to pass to child context</param>
/// <param name="pipeline">specify we are dealing with a pipeline</param>
/// <returns></returns>
Task<ITextIoContext> GetChild(string[]? childArguments = null);
Task<ITextIoContext> GetChild(string[]? childArguments = null);
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<Version>1.0.6</Version>
<Version>1.1.11</Version>
<IsPublishable>True</IsPublishable>
<AssemblyName>Xcaciv.Command.Interface</AssemblyName>
<RootNamespace>Xcaciv.Command.Interface</RootNamespace>
Expand Down
34 changes: 34 additions & 0 deletions src/Xcaciv.Command.Tests/Commands/SayCommandTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System.Threading.Tasks;
using Xcaciv.Command.FileLoader;
using Xcaciv.Command.Commands;
using Xcaciv.Command.Interface.Attributes;

namespace Xcaciv.Command.Tests.Commands
{
Expand Down Expand Up @@ -53,5 +54,38 @@ public async Task HandleExecutionWithEnvTest()
// by looking at the output of the second output line
Assert.Equal("what is up!", textio.Children.First().Output.First());
}

[Fact()]
public void BaseAttributeTest()
{

//var actual = SayCommand.ProcessEnvValues("what is %direction%!", textio);

var attributes = Attribute.GetCustomAttribute(typeof(SayCommand), typeof(BaseCommandAttribute)) as BaseCommandAttribute;

Assert.NotNull(attributes);
Assert.Equal("Like echo but more valley.", attributes.Description);
}

[Fact()]
public void ParameterAttributeTest()
{

var attributes = Attribute.GetCustomAttribute(typeof(SayCommand), typeof(CommandParameterAttribute)) as CommandParameterAttribute;

Assert.NotNull(attributes);
Assert.Equal("<thing to output>", attributes.ValueName);
}

[Fact()]
public void MultipleParameterAttributeTest()
{

var attributes = Attribute.GetCustomAttributes(typeof(SayCommand), typeof(CommandHelpRemarksAttribute)) as CommandHelpRemarksAttribute[];

Assert.NotNull(attributes);
Assert.NotEmpty(attributes);
Assert.Equal(2, attributes.Length);
}
}
}
10 changes: 8 additions & 2 deletions src/Xcaciv.Command.Tests/TestImpementations/TestTextIo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,18 @@ public TestTextIo(string[]? arguments = null, Dictionary<string, string>? envVar

public override Task<ITextIoContext> GetChild(string[]? childArguments = null)
{
var envVarsCopy = this.EnvironmentVariables.ToDictionary() ;
var child = new TestTextIo(childArguments, envVarsCopy)
var envCopy = this.GetEnvinronment();
var child = new TestTextIo(childArguments, envCopy)
{
Parent = Id
};

Children.Add(child);

if (this.HasPipedInput && this.inputPipe != null) child.SetInputPipe(this.inputPipe);

if (this.outputPipe != null) child.SetOutputPipe(this.outputPipe);

return Task.FromResult<ITextIoContext>(child);
}

Expand Down
21 changes: 19 additions & 2 deletions src/Xcaciv.Command/AbstractTextIo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -143,13 +143,15 @@ public virtual Task AddTraceMessage(string message)
/// MUST be set when creating a child!
/// </summary>
protected ConcurrentDictionary<string, string> EnvironmentVariables { get; set; } = new ConcurrentDictionary<string, string>();
public bool ValuesChanged { get; private set; }

/// <summary>
/// <see cref="Xcaciv.Command.Interface.IEnvironment"/>
/// </summary>
/// <param name="key"></param>
/// <param name="addValue"></param>
/// <returns></returns>
public void SetValue(string key, string addValue)
public virtual void SetValue(string key, string addValue)
{
// make case insensitive var names
key = key.ToUpper();
Expand All @@ -158,13 +160,15 @@ public void SetValue(string key, string addValue)
AddTraceMessage($"Environment value {key} changed from {value} to {addValue}.").Wait();
return addValue;
});

this.ValuesChanged = true;
}
/// <summary>
/// <see cref="Xcaciv.Command.Interface.IEnvironment"/>
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public string GetValue(string key)
public virtual string GetValue(string key)
{
// make case insensitive var names
key = key.ToUpper();
Expand All @@ -173,5 +177,18 @@ public string GetValue(string key)
EnvironmentVariables.TryGetValue(key, out returnValue);
return returnValue ?? String.Empty;
}

public Dictionary<string, string> GetEnvinronment()
{
return EnvironmentVariables.ToDictionary();
}

public void UpdateEnvironment(Dictionary<string, string> dictionary)
{
foreach (var pair in dictionary)
{
SetValue(pair.Key, pair.Value);
}
}
}
}
Loading