Skip to content

Commit

Permalink
Update CLI commands
Browse files Browse the repository at this point in the history
  • Loading branch information
BartoszCichecki committed Jun 23, 2024
1 parent 8a962c7 commit 635a54e
Show file tree
Hide file tree
Showing 4 changed files with 185 additions and 70 deletions.
8 changes: 5 additions & 3 deletions LenovoLegionToolkit.CLI.Lib/IpcRequest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@ public class IpcRequest
{
public enum OperationType
{
QuickAction,
Unknown,
ListFeatures,
ListFeatureValues,
SetFeature,
GetFeature,
ListQuickActions,
GetFeatureValue,
SetFeatureValue,
QuickAction,
}

public OperationType? Operation { get; init; }
Expand Down
24 changes: 18 additions & 6 deletions LenovoLegionToolkit.CLI/IpcClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public static class IpcClient
{
private static bool PipeExists => Directory.GetFiles(@"\\.\pipe\", Constants.PIPE_NAME).Length > 0;

public static async Task<string> ListFeatures()
public static async Task<string> ListFeaturesAsync()
{
var req = new IpcRequest
{
Expand All @@ -22,7 +22,8 @@ public static async Task<string> ListFeatures()
return await SendRequestAsync(req).ConfigureAwait(false)
?? throw new IpcException("Missing return message.");
}
public static async Task<string> ListFeatureValues(string name)

public static async Task<string> ListFeatureValuesAsync(string name)
{
var req = new IpcRequest
{
Expand All @@ -34,30 +35,41 @@ public static async Task<string> ListFeatureValues(string name)
?? throw new IpcException("Missing return message.");
}

public static Task SetFeature(string name, string value)
public static Task SetFeatureValueAsync(string name, string value)
{
var req = new IpcRequest
{
Operation = IpcRequest.OperationType.SetFeature,
Operation = IpcRequest.OperationType.SetFeatureValue,
Name = name,
Value = value
};

return SendRequestAsync(req);
}

public static async Task<string> GetFeature(string name)
public static async Task<string> GetFeatureValueAsync(string name)
{
var req = new IpcRequest
{
Operation = IpcRequest.OperationType.GetFeature,
Operation = IpcRequest.OperationType.GetFeatureValue,
Name = name
};

return await SendRequestAsync(req).ConfigureAwait(false)
?? throw new IpcException("Missing return message.");
}

public static async Task<string> ListQuickActionsAsync()
{
var req = new IpcRequest
{
Operation = IpcRequest.OperationType.ListQuickActions
};

return await SendRequestAsync(req).ConfigureAwait(false)
?? throw new IpcException("Missing return message.");
}

public static Task RunQuickActionAsync(string name)
{
var req = new IpcRequest
Expand Down
165 changes: 126 additions & 39 deletions LenovoLegionToolkit.CLI/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,61 +11,148 @@ namespace LenovoLegionToolkit.CLI;

public class Program
{
public static async Task<int> Main(string[] args)
public static Task<int> Main(string[] args) => BuildCommandLine().InvokeAsync(args);

private static Parser BuildCommandLine()
{
var root = new RootCommand("Control LLT");

var builder = new CommandLineBuilder(root)
.UseDefaults()
.UseExceptionHandler(OnException);

var quickActionNameArgument = new Argument<string>("name", "Name of the QuickAction") { Arity = ArgumentArity.ExactlyOne };
var featureArgument = new Argument<string>("feature", "Name of the feature") { Arity = ArgumentArity.ExactlyOne };
var valueArgument = new Argument<string>("value", "Value of the feature") { Arity = ArgumentArity.ExactlyOne };
root.AddCommand(BuildFeatureCommand());
root.AddCommand(BuildQuickActionsCommand());

return builder.Build();
}

private static Command BuildFeatureCommand()
{
var getCmd = BuildGetFeatureCommand();
var setCmd = BuildSetFeatureCommand();

var runQuickActionCommand = new Command("quick-action", "Run Quick Action with specified name");
runQuickActionCommand.AddAlias("qa");
runQuickActionCommand.AddArgument(quickActionNameArgument);
runQuickActionCommand.SetHandler(IpcClient.RunQuickActionAsync, quickActionNameArgument);
root.AddCommand(runQuickActionCommand);
var listOption = new Option<bool?>("--list", "List available features") { Arity = ArgumentArity.ZeroOrOne };
listOption.AddAlias("-l");

var listFeaturesCommand = new Command("feature-list", "List supported features");
listFeaturesCommand.AddAlias("fl");
listFeaturesCommand.SetHandler(async _ =>
var cmd = new Command("feature", "Control features");
cmd.AddAlias("f");
cmd.AddCommand(getCmd);
cmd.AddCommand(setCmd);
cmd.AddOption(listOption);
cmd.SetHandler(async list =>
{
var value = await IpcClient.ListFeatures();
if (!list.HasValue || !list.Value)
return;
var value = await IpcClient.ListFeaturesAsync();
Console.WriteLine(value);
}, listOption);
cmd.AddValidator(result =>
{
if (result.FindResultFor(getCmd) is not null)
return;
if (result.FindResultFor(setCmd) is not null)
return;
if (result.FindResultFor(listOption) is not null)
return;
result.ErrorMessage = $"{getCmd.Name}, {setCmd.Name} or --{listOption.Name} should be specified";
});
root.AddCommand(listFeaturesCommand);

var listFeatureValuesCommand = new Command("feature-list-values", "List values supported by a feature");
listFeatureValuesCommand.AddAlias("flv");
listFeatureValuesCommand.SetHandler(async name =>
return cmd;
}

private static Command BuildGetFeatureCommand()
{
var nameArgument = new Argument<string>("name", "Name of the feature") { Arity = ArgumentArity.ExactlyOne };

var cmd = new Command("get", "Get value of a feature");
cmd.AddAlias("g");
cmd.AddArgument(nameArgument);
cmd.SetHandler(async name =>
{
var value = await IpcClient.ListFeatureValues(name);
Console.WriteLine(value);
}, featureArgument);
listFeatureValuesCommand.AddArgument(featureArgument);
root.AddCommand(listFeatureValuesCommand);

var setFeatureCommand = new Command("feature-set-value", "Set feature with value");
setFeatureCommand.AddAlias("fsv");
setFeatureCommand.AddArgument(featureArgument);
setFeatureCommand.AddArgument(valueArgument);
setFeatureCommand.SetHandler(IpcClient.SetFeature, featureArgument, valueArgument);
root.AddCommand(setFeatureCommand);

var getFeatureCommand = new Command("feature-get-value", "Get feature value");
getFeatureCommand.AddAlias("fgv");
getFeatureCommand.AddArgument(featureArgument);
getFeatureCommand.SetHandler(async name =>
var result = await IpcClient.GetFeatureValueAsync(name);
Console.WriteLine(result);
}, nameArgument);

return cmd;
}

private static Command BuildSetFeatureCommand()
{
var nameArgument = new Argument<string>("name", "Name of the feature") { Arity = ArgumentArity.ExactlyOne };
var valueArgument = new Argument<string>("value", "Value of the feature") { Arity = ArgumentArity.ZeroOrOne };

var listOption = new Option<bool>("--list", "List available feature values") { Arity = ArgumentArity.ZeroOrOne };
listOption.AddAlias("-l");

var cmd = new Command("set", "Set value of a feature");
cmd.AddAlias("s");
cmd.AddArgument(nameArgument);
cmd.AddArgument(valueArgument);
cmd.AddOption(listOption);
cmd.SetHandler(async (name, value, list) =>
{
var value = await IpcClient.GetFeature(name);
Console.WriteLine(value);
}, featureArgument);
root.AddCommand(getFeatureCommand);
if (list)
{
var result = await IpcClient.ListFeatureValuesAsync(name);
Console.WriteLine(result);
return;
}
await IpcClient.SetFeatureValueAsync(name, value);
}, nameArgument, valueArgument, listOption);
cmd.AddValidator(result =>
{
if (result.FindResultFor(nameArgument) is not null)
return;
if (result.FindResultFor(listOption) is not null)
return;
result.ErrorMessage = $"{nameArgument.Name} or --{listOption.Name} should be specified";
});

return cmd;
}

private static Command BuildQuickActionsCommand()
{
var nameArgument = new Argument<string>("name", "Name of the Quick Action") { Arity = ArgumentArity.ZeroOrOne };

var listOption = new Option<bool>("--list", "List available Quick Actions") { Arity = ArgumentArity.ZeroOrOne };
listOption.AddAlias("-l");

var cmd = new Command("quickAction", "Run Quick Action");
cmd.AddAlias("qa");
cmd.AddArgument(nameArgument);
cmd.AddOption(listOption);
cmd.SetHandler(async (name, list) =>
{
if (list)
{
var result = await IpcClient.ListQuickActionsAsync();
Console.WriteLine(result);
return;
}
await IpcClient.RunQuickActionAsync(name);
}, nameArgument, listOption);
cmd.AddValidator(result =>
{
if (result.FindResultFor(nameArgument) is not null)
return;
if (result.FindResultFor(listOption) is not null)
return;
result.ErrorMessage = $"{nameArgument.Name} or --{listOption.Name} should be specified";
});

return await builder.Build().InvokeAsync(args);
return cmd;
}

private static void OnException(Exception ex, InvocationContext context)
Expand Down
58 changes: 36 additions & 22 deletions LenovoLegionToolkit.WPF/CLI/IpcServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -107,37 +107,29 @@ private async Task<IpcResponse> HandleRequest(IpcRequest req)

switch (req.Operation)
{
case IpcRequest.OperationType.QuickAction when req is { Name: not null }:
await RunQuickActionAsync(req.Name).ConfigureAwait(false);
return new IpcResponse { Success = true };
case IpcRequest.OperationType.ListFeatures:
message = await ListFeaturesAsync();
return new IpcResponse { Success = true, Message = message };
case IpcRequest.OperationType.ListFeatureValues when req is { Name: not null }:
message = await ListFeatureValuesAsync(req.Name);
return new IpcResponse { Success = true, Message = message };
case IpcRequest.OperationType.SetFeature when req is { Name: not null, Value: not null }:
await SetFeatureAsync(req.Name, req.Value).ConfigureAwait(false);
case IpcRequest.OperationType.GetFeatureValue when req is { Name: not null }:
message = await GetFeatureValueAsync(req.Name);
return new IpcResponse { Success = true, Message = message };
case IpcRequest.OperationType.SetFeatureValue when req is { Name: not null, Value: not null }:
await SetFeatureValueAsync(req.Name, req.Value).ConfigureAwait(false);
return new IpcResponse { Success = true };
case IpcRequest.OperationType.GetFeature when req is { Name: not null }:
message = await GetFeatureAsync(req.Name);
case IpcRequest.OperationType.ListQuickActions:
message = await ListQuickActionsAsync().ConfigureAwait(false);
return new IpcResponse { Success = true, Message = message };
case IpcRequest.OperationType.QuickAction when req is { Name: not null }:
await RunQuickActionAsync(req.Name).ConfigureAwait(false);
return new IpcResponse { Success = true };
default:
throw new IpcException("Invalid request");
}
}

private async Task RunQuickActionAsync(string name)
{
var pipelines = await automationProcessor.GetPipelinesAsync().ConfigureAwait(false);
var quickAction = pipelines
.Where(p => p.Trigger is null)
.FirstOrDefault(p => p.Name == name)
?? throw new InvalidOperationException($"Quick Action \"{name}\" not found.");

await automationProcessor.RunNowAsync(quickAction.Id);
}

private static async Task<string?> ListFeaturesAsync()
{
var features = new List<string>();
Expand All @@ -150,6 +142,7 @@ private async Task RunQuickActionAsync(string name)

return string.Join('\n', features);
}

private static async Task<string?> ListFeatureValuesAsync(string name)
{
var feature = FeatureRegistry.All.FirstOrDefault(f => f.Name == name)
Expand All @@ -158,17 +151,38 @@ private async Task RunQuickActionAsync(string name)
return string.Join('\n', values);
}

private static async Task SetFeatureAsync(string name, string value)
private static async Task<string> GetFeatureValueAsync(string name)
{
var feature = FeatureRegistry.All.FirstOrDefault(f => f.Name == name)
?? throw new IpcException("Invalid feature.");
await feature.SetValueAsync(value).ConfigureAwait(false);
return await feature.GetValueAsync().ConfigureAwait(false);
}

private static async Task<string> GetFeatureAsync(string name)
private static async Task SetFeatureValueAsync(string name, string value)
{
var feature = FeatureRegistry.All.FirstOrDefault(f => f.Name == name)
?? throw new IpcException("Invalid feature.");
return await feature.GetValueAsync().ConfigureAwait(false);
await feature.SetValueAsync(value).ConfigureAwait(false);
}

private async Task<string> ListQuickActionsAsync()
{
var pipelines = await automationProcessor.GetPipelinesAsync().ConfigureAwait(false);
var quickActions = pipelines
.Where(p => p.Trigger is null)
.Select(p => p.Name);

return string.Join('\n', quickActions);
}

private async Task RunQuickActionAsync(string name)
{
var pipelines = await automationProcessor.GetPipelinesAsync().ConfigureAwait(false);
var quickAction = pipelines
.Where(p => p.Trigger is null)
.FirstOrDefault(p => p.Name == name)
?? throw new InvalidOperationException($"Quick Action \"{name}\" not found.");

await automationProcessor.RunNowAsync(quickAction.Id);
}
}

0 comments on commit 635a54e

Please sign in to comment.