1.Naming convention 2.Base definitions 3.String output & progress 4.Property definitions 5.Command enabled or disabled 6.Autocomplete 7.Register command 8.Register configuration
Kebab case
public class BaseCommand : TerminalCommandBase
{
public BaseCommand(ITerminal terminal)
: base(terminal)
{
}
[CommandPropertyRequired]
public string RequiedValue { get; set; }
[CommandProperty]
public string OptionValue { get; set; }
[CommandPropertySwitch]
public bool SwitchValue { get; set; }
[CommandPropertyArray]
public string[] Values { get; set; }
protected override void OnExecute()
{
}
}
base value --option-value v --switch-value value1 value2 value3
class BaseAsyncCommand : TerminalCommandAsyncBase
{
public BaseAsyncCommand(ITerminal terminal)
: base(terminal)
{
}
[CommandProperty]
public string Value1 { get; set; }
protected override Task OnExecuteAsync(CancellationToken cancellation)
{
}
}
base-async --value1 v
public class BaseSubCommand : TerminalCommandMethodBase
{
public BaseSubCommand(ITerminal terminal)
: base(terminal})
{
}
[CommandMethod]
public void Method1(string value1, string value2 = "")
{
}
[CommandMethod]
[CommandMethodProperty(nameof(PropertyValue))]
public void Method2(string value1, params string[] args)
{
}
[CommandMethod]
public Task Method3Async(CancellationToken cancellation, string value1)
{
}
[CommandProperty]
public string PropertyValue
{
get; set;
}
base-sub method1 value
base-sub method2 value v1 v2 v3 --property-value p
base-sub method3 value
WriteLineAsync must be used in asynchronous methods.
...
protected override void OnExecute()
{
this.WriteLine("tex");
this.WriteLine("foreground color", TerminalColor.Red);
}
...
...
protected override async Task OnExecuteAsync(CancellationToken cancellation)
{
await this.WriteLineAsync("tex");
await this.WriteLineAsync("foreground and background color", TerminalColor.Red, TerminalColor.White);
}
...
Writing many strings one by one can slow down the speed, so using StringBuilder is a good idea to write them all at once.
...
protected override void OnExecute()
{
var sb = new StringBuilder();
for (var i = 0; i < 1000; i++)
{
sb.AppendLine($"index: {i}");
}
this.Write(sb.ToString());
}
...
You can invoke the method from the main thread using the dispatcher in an asynchronous method.
...
protected override async Task OnExecuteAsync(CancellationToken cancellation)
{
this.Dispatcher.InvokeAsync(() => Debug.Log("log"));
}
...
...
protected override async Task OnExecuteAsync(CancellationToken cancellation)
{
await this.WriteLineAsync("Start Loading.", TerminalColor.Red);
for (var i = 0; i < 100; i++)
{
if (cancellation.IsCancellationRequested == true)
{
throw new Exception("Loading canceled.");
}
await this.SetProgressAsync($"{i}%", (float)i / 100);
}
await this.SetProgressAsync($"{100}%", 1.0f);
await this.CompleteProgressAsync("Completed");
}
...
[CommandProperty]
public string Value { get; set; }
[CommandProperty(DefaultValue = "text")]
public string Value { get; set; }
[CommandProperty(InitValue = "")]
public string Value { get; set; }
[CommandPropertyRequired]
public string Value { get; set; }
[CommandPropertyRequired(DefaultValue = "text")]
public string Value { get; set; }
[CommandPropertyRequired(IsExplicit = true)]
public string Value { get; set; }
[CommandPropertySwitch]
public bool Value { get; set; }
[CommandPropertyArray]
public string[] Values { get; set; }
Override IsEnabled Property
public class BaseCommand : TerminalCommandBase
{
...
public override bool IsEnabled => true;
...
}
Use property in Can + “name” format
public class BaseSubCommand : TerminalCommandMethodBase
{
[CommandMethod]
public void Method1(string value1, string value2 = "")
{
}
public bool CanMethod1 => true;
[CommandMethod]
public Task Method2Async(CancellationToken cancellation, string value1)
{
}
public bool CanMethod2 => true;
}
Override GetCompletions Method
public class BaseCommand : TerminalCommandBase
{
public override string[] GetCompletions(CommandCompletionContext completionContext)
{
var memberDescriptor = completionContext.MemberDescriptor;
if (memberDescriptor != null && memberDescriptor.DescriptorName == nameof(Value))
{
var items = new string[] { "a", "b", "c" };
var query = from item in items
where item.StartsWith(completionContext.Find)
select item;
return query.ToArray();
}
return null;
}
[CommandProperty]
public string Value { get; set; }
}
Override GetCompletions Method
public class BaseSubCommand : TerminalCommandMethodBase
{
public override string[] GetCompletions(CommandMethodDescriptor methodDescriptor, CommandMemberDescriptor memberDescriptor, string find)
{
}
}
or Define method named Complete + “name”
public class BaseSubCommand : TerminalCommandMethodBase
{
[CommandMethod]
public void Method1(string value1, string value2 = "")
{
}
public string[] CompleteMethod1(CommandMemberDescriptor descriptor, string find)
{
...
}
}
Add the CommandSystem component to a terminal object with the CommandContextHost component.
public class CommandSystem : CommandSystemBase
{
protected override IEnumerable<ICommand> OnCommandProvide(ITerminal terminal)
{
yield return new BaseCommand(terminal);
}
}
You can specify values through the config command in the terminal by registering fields and properties.
To register a static field or property
public class CommandSystem : CommandSystemBase
{
protected override void Awake()
{
base.Awake();
AddConfig(new CommandConfiguration<bool>("sound.pause", (o) => AudioListener.pause, (o, v) => AudioListener.pause = v));
AddConfig(new CommandConfiguration<float>("sound.volume", (o) => AudioListener.volume, (o, v) => AudioListener.volume = v));
}
protected override void OnDestroy()
{
base.OnDestroy();
RemoveConfig("sound.pause");
RemoveConfig("sound.volume");
}
}
To register fields or properties for a specific instance
public class TestConfiguration : MonoBehaviour
{
[SerializeField]
private float value = 0;
[SerializeField]
private CommandSystem commandSystem = null;
public bool IsValue { get; set; }
private void Awake()
{
if (this.commandSystem != null)
{
this.commandSystem.AddConfig(new FieldConfiguration("test.value", this, nameof(value)));
this.commandSystem.AddConfig(new PropertyConfiguration("test.IsValue", this, nameof(IsValue)));
}
}
private void OnDestroy()
{
if (this.commandSystem != null)
{
this.commandSystem.RemoveConfig("test.value");
this.commandSystem.RemoveConfig("test.IsValue");
}
}
}
You can use the CommandConfigurationAttribute to register multiple configurations at once.
[CommandConfiguration("test")]
public class TestController : MonoBehaviour
{
public CommandSystem commandSystem = null;
[Range(0, 10)]
[Tooltip("integer value")]
[CommandConfiguration]
public int value = 0;
private TestSettings settings;
private void Awake()
{
this.settings = new TestSettings();
if (this.commandSystem != null)
{
this.commandSystem.AddConfigs(this);
this.commandSystem.AddConfigs(this.settings, "settings");
}
}
private void OnDestroy()
{
if (this.commandSystem != null)
{
this.commandSystem.RemoveConfigs(this);
this.commandSystem.RemoveConfigs(this.settings, "settings");
}
this.settings = null;
}
[CommandConfiguration]
public class TestSettings
{
[CommandConfiguration]
public int value = 0;
}
}
Show list of configurations
config --list
Show value of ‘test.value’ configuration
config test.value
Set value of ‘test.value’ configuration
config test.value 0
Reset value of ‘test.value’ configuration
config test.value --reset