From abe40c2658db9480874a7a5bc729f14e89a4769d Mon Sep 17 00:00:00 2001 From: Anupal Mishra Date: Fri, 23 Jan 2026 00:53:40 +0000 Subject: [PATCH 1/6] allow icon override for cpu subcommand --- stmx/Commands/CpuCommand.cs | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/stmx/Commands/CpuCommand.cs b/stmx/Commands/CpuCommand.cs index d36ad3c..a4234c4 100644 --- a/stmx/Commands/CpuCommand.cs +++ b/stmx/Commands/CpuCommand.cs @@ -14,21 +14,32 @@ public CpuCommand(ISystemStatsService systemStats, IIconService icons) : base("c _systemStats = systemStats ?? throw new ArgumentNullException(nameof(systemStats)); _icons = icons ?? throw new ArgumentNullException(nameof(icons)); - var showIconOption = new Option("--icon", ["-i"]); - showIconOption.Description = "whether to show icon"; - showIconOption.DefaultValueFactory = _ => _systemStats.Options.DefaultShowMemoryIcon; + var showIconOption = new Option("--icon", ["-i"]); + showIconOption.Description = "whether to show icon (optionally provide custom icon)"; + // this allows users to pass one or more values + showIconOption.Arity = ArgumentArity.ZeroOrOne; Add(showIconOption); SetAction(async (parseResult, cancellationToken) => { - var showIcon = parseResult.GetValue(showIconOption); - await ExecuteAsync(showIcon!); + var iconValue = parseResult.GetValue(showIconOption); + await ExecuteAsync( + parseResult.GetResult(showIconOption) is not null, + iconValue! + ); }); } - public async Task ExecuteAsync(bool showIcon) + public async Task ExecuteAsync(bool showIcon, string iconValue) { - string cpuIcon = showIcon ? $"{_icons.Options.CpuIcon} " : ""; + string cpuIcon = ""; + // if -i was passed + if (showIcon) + { + cpuIcon = string.IsNullOrEmpty(iconValue) + ? $"{_icons.Options.CpuIcon} " + : $"{iconValue} "; // if a custom icon was also passed + } var cpuPercent = await _systemStats.GetCpuUsagePercent(); Console.Write($"{cpuIcon}{cpuPercent:F2}%"); From e0ad984078d93c3c33c5363d239c2f34ab97967a Mon Sep 17 00:00:00 2001 From: Anupal Mishra Date: Fri, 23 Jan 2026 00:53:48 +0000 Subject: [PATCH 2/6] allow icon override for memory subcommand --- stmx/Commands/MemoryCommand.cs | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/stmx/Commands/MemoryCommand.cs b/stmx/Commands/MemoryCommand.cs index 63d62cc..87da9fe 100644 --- a/stmx/Commands/MemoryCommand.cs +++ b/stmx/Commands/MemoryCommand.cs @@ -15,9 +15,10 @@ public MemoryCommand(ISystemStatsService systemStats, IIconService icons) : base _systemStats = systemStats ?? throw new ArgumentNullException(nameof(systemStats)); _icons = icons ?? throw new ArgumentNullException(nameof(icons)); - var showIconOption = new Option("--icon", ["-i"]); - showIconOption.Description = "whether to show icon"; - showIconOption.DefaultValueFactory = _ => _systemStats.Options.DefaultShowMemoryIcon; + var showIconOption = new Option("--icon", ["-i"]); + showIconOption.Description = "whether to show icon (optionally provide custom icon)"; + // this allows users to pass one or more values + showIconOption.Arity = ArgumentArity.ZeroOrOne; Add(showIconOption); var showPercentOption = new Option("--percent", ["-p"]); @@ -32,16 +33,28 @@ public MemoryCommand(ISystemStatsService systemStats, IIconService icons) : base SetAction(async (parseResult, cancellationToken) => { - var showIcon = parseResult.GetValue(showIconOption); + var iconValue = parseResult.GetValue(showIconOption); var showPercent = parseResult.GetValue(showPercentOption); var unit = parseResult.GetValue(unitOption); - await ExecuteAsync(showIcon!, showPercent!, unit!); + await ExecuteAsync( + parseResult.GetResult(showIconOption) is not null, + iconValue!, + showPercent!, + unit! + ); }); } - public async Task ExecuteAsync(bool showIcon, bool showPercent, MemoryUnits unit) + public async Task ExecuteAsync(bool showIcon, string iconValue, bool showPercent, MemoryUnits unit) { - string memoryIcon = showIcon ? $"{_icons.Options.MemoryIcon} " : ""; + string memoryIcon = ""; + // if -i was passed + if (showIcon) + { + memoryIcon = string.IsNullOrEmpty(iconValue) + ? $"{_icons.Options.MemoryIcon} " + : $"{iconValue} "; // if a custom icon was also passed + } if (showPercent) { From 47fd456e2e10b8214a834ec9ada52c0a7ef78951 Mon Sep 17 00:00:00 2001 From: Anupal Mishra Date: Tue, 27 Jan 2026 23:18:39 +0000 Subject: [PATCH 3/6] Use -p for showing '%' and introduce MemoryUnit for percent --- stmx/Commands/MemoryCommand.cs | 34 +++++++++++++--------- stmx/Services/ISystemStatsService.cs | 2 +- stmx/Services/IconServiceOptions.cs | 1 + stmx/Services/LinuxSystemStatsService.cs | 4 +-- stmx/Services/SystemStatsServiceOptions.cs | 3 +- stmx/Utils/Enums.cs | 1 + 6 files changed, 27 insertions(+), 18 deletions(-) diff --git a/stmx/Commands/MemoryCommand.cs b/stmx/Commands/MemoryCommand.cs index 87da9fe..bfc64b6 100644 --- a/stmx/Commands/MemoryCommand.cs +++ b/stmx/Commands/MemoryCommand.cs @@ -15,16 +15,16 @@ public MemoryCommand(ISystemStatsService systemStats, IIconService icons) : base _systemStats = systemStats ?? throw new ArgumentNullException(nameof(systemStats)); _icons = icons ?? throw new ArgumentNullException(nameof(icons)); - var showIconOption = new Option("--icon", ["-i"]); - showIconOption.Description = "whether to show icon (optionally provide custom icon)"; + var showIconOption = new Option("--show-icon", ["-i"]); + showIconOption.Description = "show icon (optionally provide custom icon)"; // this allows users to pass one or more values showIconOption.Arity = ArgumentArity.ZeroOrOne; Add(showIconOption); - var showPercentOption = new Option("--percent", ["-p"]); - showPercentOption.Description = "whether to show as a percentage"; - showPercentOption.DefaultValueFactory = _ => _systemStats.Options.DefaultShowBatteryPercent; - Add(showPercentOption); + var showPercentIconOption = new Option("--show-percent", ["-p"]); + showPercentIconOption.Description = "show percent icon (optionally provide custom icon)"; + showPercentIconOption.Arity = ArgumentArity.ZeroOrOne; + Add(showPercentIconOption); var unitOption = new Option("--unit", "-u"); unitOption.Description = "Select the memory unit for display"; @@ -34,20 +34,22 @@ public MemoryCommand(ISystemStatsService systemStats, IIconService icons) : base SetAction(async (parseResult, cancellationToken) => { var iconValue = parseResult.GetValue(showIconOption); - var showPercent = parseResult.GetValue(showPercentOption); + var percentValue = parseResult.GetValue(showPercentIconOption); var unit = parseResult.GetValue(unitOption); await ExecuteAsync( parseResult.GetResult(showIconOption) is not null, iconValue!, - showPercent!, + parseResult.GetResult(showPercentIconOption) is not null, + percentValue!, unit! ); }); } - public async Task ExecuteAsync(bool showIcon, string iconValue, bool showPercent, MemoryUnits unit) + public async Task ExecuteAsync(bool showIcon, string iconValue, bool showPercentIcon, + string percentIconValue, MemoryUnits unit) { - string memoryIcon = ""; + string memoryIcon = "", percentIcon = ""; // if -i was passed if (showIcon) { @@ -56,10 +58,16 @@ public async Task ExecuteAsync(bool showIcon, string iconValue, bool showPercent : $"{iconValue} "; // if a custom icon was also passed } - if (showPercent) + if (unit == MemoryUnits.Percent) { - var memoryPercent = await _systemStats.GetMemoryUsagePercent(unit); - Console.Write($"{memoryIcon}{memoryPercent:F2}%"); + var memoryPercent = await _systemStats.GetMemoryUsagePercent(); + if (showPercentIcon) + { + percentIcon = string.IsNullOrEmpty(percentIconValue) + ? _icons.Options.PercentIcon + : percentIconValue; + } + Console.Write($"{memoryIcon}{memoryPercent:F2}{percentIcon}"); } else { diff --git a/stmx/Services/ISystemStatsService.cs b/stmx/Services/ISystemStatsService.cs index 1e86f70..a6f39be 100644 --- a/stmx/Services/ISystemStatsService.cs +++ b/stmx/Services/ISystemStatsService.cs @@ -7,7 +7,7 @@ public interface ISystemStatsService Task GetBatteryCapacity(); Task GetBatteryStatus(); Task GetMemoryUsageNumber(MemoryUnits unit); - Task GetMemoryUsagePercent(MemoryUnits unit); + Task GetMemoryUsagePercent(); Task GetCpuUsagePercent(); SystemStatsServiceOptions Options { get; } } diff --git a/stmx/Services/IconServiceOptions.cs b/stmx/Services/IconServiceOptions.cs index d0f491a..d893f61 100644 --- a/stmx/Services/IconServiceOptions.cs +++ b/stmx/Services/IconServiceOptions.cs @@ -12,4 +12,5 @@ public class IconServiceOptions }; public string MemoryIcon { get; set; } = ""; public string CpuIcon { get; set; } = ""; + public string PercentIcon { get; set; } = ""; } diff --git a/stmx/Services/LinuxSystemStatsService.cs b/stmx/Services/LinuxSystemStatsService.cs index b41c220..38ef0ce 100644 --- a/stmx/Services/LinuxSystemStatsService.cs +++ b/stmx/Services/LinuxSystemStatsService.cs @@ -91,11 +91,11 @@ public LinuxSystemStatsService(IFileReader fileReader, IFileSystem fileSystem) } } - public async Task GetMemoryUsagePercent(MemoryUnits unit) + public async Task GetMemoryUsagePercent() { try { - MemoryUsageData data = ReadMemoryUsageFromProcFile().ConvertTo(unit); + MemoryUsageData data = ReadMemoryUsageFromProcFile(); double percent = ((double)data.Used / data.Total) * 100; return Math.Round(percent, 2); } diff --git a/stmx/Services/SystemStatsServiceOptions.cs b/stmx/Services/SystemStatsServiceOptions.cs index 26a79ed..03750cb 100644 --- a/stmx/Services/SystemStatsServiceOptions.cs +++ b/stmx/Services/SystemStatsServiceOptions.cs @@ -8,6 +8,5 @@ public class SystemStatsServiceOptions public bool DefaultShowBatteryChargingIcon { get; set; } = false; public bool DefaultShowBatteryPercent { get; set; } = false; - public bool DefaultShowMemoryIcon { get; set; } = false; - public MemoryUnits DefaultMemoryUnit {get; set; } = MemoryUnits.KiloBytes; + public MemoryUnits DefaultMemoryUnit {get; set; } = MemoryUnits.Percent; } diff --git a/stmx/Utils/Enums.cs b/stmx/Utils/Enums.cs index 6acf7f3..724c40a 100644 --- a/stmx/Utils/Enums.cs +++ b/stmx/Utils/Enums.cs @@ -2,6 +2,7 @@ namespace stmx.Utils; public enum MemoryUnits { + Percent = 0, Bytes = 1, KiloBytes = 2, KibiBytes = 3, From 31926c767d462dc91b6644a28c98821a407cb039 Mon Sep 17 00:00:00 2001 From: Anupal Mishra Date: Tue, 27 Jan 2026 23:19:27 +0000 Subject: [PATCH 4/6] Use -p for showing '%' --- TODO.md | 0 stmx/Commands/CpuCommand.cs | 33 ++++++++++++++++++++++++--------- 2 files changed, 24 insertions(+), 9 deletions(-) create mode 100644 TODO.md diff --git a/TODO.md b/TODO.md new file mode 100644 index 0000000..e69de29 diff --git a/stmx/Commands/CpuCommand.cs b/stmx/Commands/CpuCommand.cs index a4234c4..182a3d2 100644 --- a/stmx/Commands/CpuCommand.cs +++ b/stmx/Commands/CpuCommand.cs @@ -14,34 +14,49 @@ public CpuCommand(ISystemStatsService systemStats, IIconService icons) : base("c _systemStats = systemStats ?? throw new ArgumentNullException(nameof(systemStats)); _icons = icons ?? throw new ArgumentNullException(nameof(icons)); - var showIconOption = new Option("--icon", ["-i"]); - showIconOption.Description = "whether to show icon (optionally provide custom icon)"; + var showIconOption = new Option("--show-icon", ["-i"]); + showIconOption.Description = "show icon (optionally provide custom icon)"; // this allows users to pass one or more values showIconOption.Arity = ArgumentArity.ZeroOrOne; Add(showIconOption); + var showPercentIconOption = new Option("--show-percent", ["-p"]); + showPercentIconOption.Description = "show percent icon (optionally provide custom icon)"; + showPercentIconOption.Arity = ArgumentArity.ZeroOrOne; + Add(showPercentIconOption); + SetAction(async (parseResult, cancellationToken) => { var iconValue = parseResult.GetValue(showIconOption); + var percentIconValue = parseResult.GetValue(showPercentIconOption); await ExecuteAsync( parseResult.GetResult(showIconOption) is not null, - iconValue! + iconValue!, + parseResult.GetResult(showPercentIconOption) is not null, + percentIconValue! ); }); } - public async Task ExecuteAsync(bool showIcon, string iconValue) + public async Task ExecuteAsync(bool showIcon, string iconValue, bool showPercentIcon, string percentIconValue) { - string cpuIcon = ""; + string cpuIcon = "", percentIcon = ""; // if -i was passed if (showIcon) { - cpuIcon = string.IsNullOrEmpty(iconValue) - ? $"{_icons.Options.CpuIcon} " - : $"{iconValue} "; // if a custom icon was also passed + cpuIcon = string.IsNullOrEmpty(iconValue) + ? $"{_icons.Options.CpuIcon} " + : $"{iconValue} "; // if a custom icon was also passed + } + + if (showPercentIcon) + { + percentIcon = string.IsNullOrEmpty(percentIconValue) + ? _icons.Options.PercentIcon + : percentIconValue; } var cpuPercent = await _systemStats.GetCpuUsagePercent(); - Console.Write($"{cpuIcon}{cpuPercent:F2}%"); + Console.Write($"{cpuIcon}{cpuPercent:F2}{percentIcon}"); } } From 8ae75b9991f28600ef7ad8f2ac03727d7b271306 Mon Sep 17 00:00:00 2001 From: Anupal Mishra Date: Tue, 3 Feb 2026 19:39:30 +0000 Subject: [PATCH 5/6] Update tests --- stmx.tests/Commands/CpuCommandTest.cs | 112 ++++++++++-------- stmx.tests/Commands/MemoryCommandTest.cs | 70 ++++++----- .../Services/LinuxSystemStatsServiceTest.cs | 4 +- 3 files changed, 106 insertions(+), 80 deletions(-) diff --git a/stmx.tests/Commands/CpuCommandTest.cs b/stmx.tests/Commands/CpuCommandTest.cs index 8282e8f..17e4ec8 100644 --- a/stmx.tests/Commands/CpuCommandTest.cs +++ b/stmx.tests/Commands/CpuCommandTest.cs @@ -7,27 +7,24 @@ namespace stmx.Tests; public class CpuCommandTests { [Test] - public async Task TestCpuCommand_PrintsIconAndPercent() + public async Task TestCpuCommand_PrintsCustomIconAndPercent() { var mockStats = new Mock(); var mockIcons = new Mock(); mockStats.Setup(s => s.GetCpuUsagePercent()).ReturnsAsync(37.42); - mockStats.SetupGet(s => s.Options).Returns(new SystemStatsServiceOptions - { - DefaultShowMemoryIcon = true - }); - mockIcons.SetupGet(i => i.Options).Returns(new IconServiceOptions - { - CpuIcon = "CPU_ICON" - }); var cmd = new CpuCommand(mockStats.Object, mockIcons.Object); var consoleOut = new StringWriter(); Console.SetOut(consoleOut); - await cmd.ExecuteAsync(showIcon: true); + await cmd.ExecuteAsync( + showIcon: true, + iconValue: "CPU_ICON", + showPercentIcon: true, + percentIconValue: "%" + ); Assert.That(consoleOut.ToString(), Is.EqualTo("CPU_ICON 37.42%")); } @@ -42,7 +39,8 @@ public async Task TestCpuCommand_PrintsPercentWithoutIcon() mockStats.SetupGet(s => s.Options).Returns(new SystemStatsServiceOptions()); mockIcons.SetupGet(i => i.Options).Returns(new IconServiceOptions { - CpuIcon = "CPU_ICON" + CpuIcon = "CPU_ICON", + PercentIcon = "%" }); var cmd = new CpuCommand(mockStats.Object, mockIcons.Object); @@ -50,27 +48,28 @@ public async Task TestCpuCommand_PrintsPercentWithoutIcon() var consoleOut = new StringWriter(); Console.SetOut(consoleOut); - await cmd.ExecuteAsync(showIcon: false); + await cmd.ExecuteAsync( + showIcon: false, + iconValue: "", + showPercentIcon: true, + percentIconValue: "" + ); Assert.That(consoleOut.ToString(), Is.EqualTo("12.35%")); } [Test] - public async Task TestCpuCommand_RespectsDefaultOptions() + public async Task TestCpuCommand_PrintsPercentWithoutPercentIcon() { - var opts = new SystemStatsServiceOptions - { - DefaultShowMemoryIcon = true - }; - var mockStats = new Mock(); - mockStats.SetupGet(s => s.Options).Returns(opts); - mockStats.Setup(s => s.GetCpuUsagePercent()).ReturnsAsync(50.0); - var mockIcons = new Mock(); - mockIcons.SetupGet(s => s.Options).Returns(new IconServiceOptions + + mockStats.Setup(s => s.GetCpuUsagePercent()).ReturnsAsync(12.345); + mockStats.SetupGet(s => s.Options).Returns(new SystemStatsServiceOptions()); + mockIcons.SetupGet(i => i.Options).Returns(new IconServiceOptions { - CpuIcon = "CPU_ICON" + CpuIcon = "CPU_ICON", + PercentIcon = "%" }); var cmd = new CpuCommand(mockStats.Object, mockIcons.Object); @@ -78,22 +77,27 @@ public async Task TestCpuCommand_RespectsDefaultOptions() var consoleOut = new StringWriter(); Console.SetOut(consoleOut); - await cmd.ExecuteAsync(showIcon: opts.DefaultShowMemoryIcon); + await cmd.ExecuteAsync( + showIcon: false, + iconValue: "", + showPercentIcon: false, + percentIconValue: "" + ); - Assert.That(consoleOut.ToString(), Is.EqualTo("CPU_ICON 50.00%")); + Assert.That(consoleOut.ToString(), Is.EqualTo("12.35")); } [Test] - public async Task TestCpuCommand_HandlesNullCpuPercent() + public async Task TestCpuCommand_RespectsDefaultOptions() { var mockStats = new Mock(); var mockIcons = new Mock(); - mockStats.Setup(s => s.GetCpuUsagePercent()).ReturnsAsync((double?)null); - mockStats.SetupGet(s => s.Options).Returns(new SystemStatsServiceOptions()); - mockIcons.SetupGet(s => s.Options).Returns(new IconServiceOptions + mockStats.Setup(s => s.GetCpuUsagePercent()).ReturnsAsync(37.42); + mockIcons.SetupGet(i => i.Options).Returns(new IconServiceOptions { - CpuIcon = "CPU_ICON" + CpuIcon = "CPU_ICON", + PercentIcon = "%" }); var cmd = new CpuCommand(mockStats.Object, mockIcons.Object); @@ -101,48 +105,52 @@ public async Task TestCpuCommand_HandlesNullCpuPercent() var consoleOut = new StringWriter(); Console.SetOut(consoleOut); - await cmd.ExecuteAsync(showIcon: true); + await cmd.ExecuteAsync( + showIcon: true, + iconValue: "", + showPercentIcon: true, + percentIconValue: "" + ); - Assert.That(consoleOut.ToString(), Is.EqualTo("CPU_ICON %")); + Assert.That(consoleOut.ToString(), Is.EqualTo("CPU_ICON 37.42%")); } [Test] - public async Task TestCpuCommand_FormatsToTwoDecimalPlaces() + public async Task TestCpuCommand_HandlesNullCpuPercent() { var mockStats = new Mock(); var mockIcons = new Mock(); - mockStats.Setup(s => s.GetCpuUsagePercent()).ReturnsAsync(33.3333); + mockStats.Setup(s => s.GetCpuUsagePercent()).ReturnsAsync((double?)null); mockStats.SetupGet(s => s.Options).Returns(new SystemStatsServiceOptions()); - mockIcons.SetupGet(s => s.Options).Returns(new IconServiceOptions - { - CpuIcon = "CPU" - }); var cmd = new CpuCommand(mockStats.Object, mockIcons.Object); var consoleOut = new StringWriter(); Console.SetOut(consoleOut); - await cmd.ExecuteAsync(showIcon: false); + await cmd.ExecuteAsync( + showIcon: true, + iconValue: "CPU_ICON", + showPercentIcon: true, + percentIconValue: "%" + ); - Assert.That(consoleOut.ToString(), Is.EqualTo("33.33%")); + + Assert.That(consoleOut.ToString(), Is.EqualTo("CPU_ICON %")); } [Test] - public async Task TestCpuCommand_OptionParsingCallsExecute() + public async Task TestCpuCommand_FormatsToTwoDecimalPlaces() { var mockStats = new Mock(); var mockIcons = new Mock(); - mockStats.Setup(s => s.GetCpuUsagePercent()).ReturnsAsync(10.0); - mockStats.SetupGet(s => s.Options).Returns(new SystemStatsServiceOptions - { - DefaultShowMemoryIcon = false - }); + mockStats.Setup(s => s.GetCpuUsagePercent()).ReturnsAsync(33.3333); + mockStats.SetupGet(s => s.Options).Returns(new SystemStatsServiceOptions()); mockIcons.SetupGet(s => s.Options).Returns(new IconServiceOptions { - CpuIcon = "CPU_ICON" + CpuIcon = "CPU" }); var cmd = new CpuCommand(mockStats.Object, mockIcons.Object); @@ -150,9 +158,13 @@ public async Task TestCpuCommand_OptionParsingCallsExecute() var consoleOut = new StringWriter(); Console.SetOut(consoleOut); - // mimic command execution with icon enabled - await cmd.ExecuteAsync(showIcon: true); + await cmd.ExecuteAsync( + showIcon: false, + iconValue: "", + showPercentIcon: true, + percentIconValue: "%" + ); - Assert.That(consoleOut.ToString(), Is.EqualTo("CPU_ICON 10.00%")); + Assert.That(consoleOut.ToString(), Is.EqualTo("33.33%")); } } diff --git a/stmx.tests/Commands/MemoryCommandTest.cs b/stmx.tests/Commands/MemoryCommandTest.cs index b446632..1dfb540 100644 --- a/stmx.tests/Commands/MemoryCommandTest.cs +++ b/stmx.tests/Commands/MemoryCommandTest.cs @@ -14,22 +14,23 @@ public async Task TestMemoryCommand_PrintsIconAndPercent() var mockStatsService = new Mock(); var mockIconService = new Mock(); - mockStatsService.Setup(s => s.GetMemoryUsagePercent(MemoryUnits.MibiBytes)).ReturnsAsync(75.0); + mockStatsService.Setup(s => s.GetMemoryUsagePercent()).ReturnsAsync(75.0); mockStatsService.SetupGet(s => s.Options).Returns(new SystemStatsServiceOptions { DefaultMemoryUnit = MemoryUnits.MibiBytes }); - mockIconService.SetupGet(s => s.Options).Returns(new IconServiceOptions - { - MemoryIcon = "MEM_ICON" - }); var cmd = new MemoryCommand(mockStatsService.Object, mockIconService.Object); var consoleOut = new StringWriter(); Console.SetOut(consoleOut); - await cmd.ExecuteAsync(showIcon: true, showPercent: true, unit: MemoryUnits.MibiBytes); + await cmd.ExecuteAsync( + showIcon: true, + iconValue: "MEM_ICON", + showPercentIcon: true, + percentIconValue: "%", + unit: MemoryUnits.Percent); Assert.That(consoleOut.ToString(), Is.EqualTo("MEM_ICON 75.00%")); } @@ -56,7 +57,12 @@ public async Task TestMemoryCommand_PrintsNumberWithoutIcon() var consoleOut = new StringWriter(); Console.SetOut(consoleOut); - await cmd.ExecuteAsync(showIcon: false, showPercent: false, unit: MemoryUnits.GibiBytes); + await cmd.ExecuteAsync( + showIcon: false, + iconValue: "", + showPercentIcon: true, + percentIconValue: "", + unit: MemoryUnits.GibiBytes); Assert.That(consoleOut.ToString(), Is.EqualTo("2 / 8")); } @@ -64,36 +70,33 @@ public async Task TestMemoryCommand_PrintsNumberWithoutIcon() [Test] public async Task TestMemoryCommand_RespectsDefaultOptions() { - var opts = new SystemStatsServiceOptions - { - DefaultShowMemoryIcon = true, - DefaultShowBatteryPercent = true, - DefaultMemoryUnit = MemoryUnits.MibiBytes - }; - var mockStatsService = new Mock(); - mockStatsService.SetupGet(s => s.Options).Returns(opts); var mockIconService = new Mock(); + + mockStatsService.Setup(s => s.GetMemoryUsagePercent()).ReturnsAsync(75.0); + mockStatsService.SetupGet(s => s.Options).Returns(new SystemStatsServiceOptions + { + DefaultMemoryUnit = MemoryUnits.MibiBytes + }); mockIconService.SetupGet(s => s.Options).Returns(new IconServiceOptions { - MemoryIcon = "MEM_ICON" + MemoryIcon = "MEM_ICON", + PercentIcon = "%" }); - mockStatsService.Setup(s => s.GetMemoryUsagePercent(MemoryUnits.MibiBytes)).ReturnsAsync(60.0); - var cmd = new MemoryCommand(mockStatsService.Object, mockIconService.Object); var consoleOut = new StringWriter(); Console.SetOut(consoleOut); - // Using defaults await cmd.ExecuteAsync( - showIcon: opts.DefaultShowMemoryIcon, - showPercent: opts.DefaultShowBatteryPercent, - unit: opts.DefaultMemoryUnit - ); + showIcon: true, + iconValue: "", + showPercentIcon: true, + percentIconValue: "", + unit: MemoryUnits.Percent); - Assert.That(consoleOut.ToString(), Is.EqualTo("MEM_ICON 60.00%")); + Assert.That(consoleOut.ToString(), Is.EqualTo("MEM_ICON 75.00%")); } [Test] @@ -102,7 +105,7 @@ public async Task TestMemoryCommand_HandlesNullValues() var mockStatsService = new Mock(); var mockIconService = new Mock(); - mockStatsService.Setup(s => s.GetMemoryUsagePercent(MemoryUnits.MibiBytes)).ReturnsAsync((double?)null); + mockStatsService.Setup(s => s.GetMemoryUsagePercent()).ReturnsAsync((double?)null); mockStatsService.Setup(s => s.GetMemoryUsageNumber(MemoryUnits.MibiBytes)).ReturnsAsync((string?)null); mockStatsService.SetupGet(s => s.Options).Returns(new SystemStatsServiceOptions @@ -111,7 +114,8 @@ public async Task TestMemoryCommand_HandlesNullValues() }); mockIconService.SetupGet(s => s.Options).Returns(new IconServiceOptions { - MemoryIcon = "MEM_ICON" + MemoryIcon = "MEM_ICON", + PercentIcon = "%" }); var cmd = new MemoryCommand(mockStatsService.Object, mockIconService.Object); @@ -120,13 +124,23 @@ public async Task TestMemoryCommand_HandlesNullValues() Console.SetOut(consoleOut); // Percent null - await cmd.ExecuteAsync(showIcon: true, showPercent: true, unit: MemoryUnits.MibiBytes); + await cmd.ExecuteAsync( + showIcon: true, + iconValue: "MEM_ICON", + showPercentIcon: true, + percentIconValue: "%", + unit: MemoryUnits.Percent); Assert.That(consoleOut.ToString(), Is.EqualTo("MEM_ICON %")); consoleOut.GetStringBuilder().Clear(); // Number null - await cmd.ExecuteAsync(showIcon: true, showPercent: false, unit: MemoryUnits.MibiBytes); + await cmd.ExecuteAsync( + showIcon: true, + iconValue: "MEM_ICON", + showPercentIcon: false, + percentIconValue: "", + unit: MemoryUnits.MibiBytes); Assert.That(consoleOut.ToString(), Is.EqualTo("MEM_ICON ")); } } diff --git a/stmx.tests/Services/LinuxSystemStatsServiceTest.cs b/stmx.tests/Services/LinuxSystemStatsServiceTest.cs index 8d313f4..c48069b 100644 --- a/stmx.tests/Services/LinuxSystemStatsServiceTest.cs +++ b/stmx.tests/Services/LinuxSystemStatsServiceTest.cs @@ -173,7 +173,7 @@ public async Task GetMemoryUsagePercent_ReturnsCorrectValue() _fileReaderMock.Setup(f => f.ReadAllText(It.IsAny())).Returns(mockMemInfo); - double? percent = await _service.GetMemoryUsagePercent(MemoryUnits.KiloBytes); + double? percent = await _service.GetMemoryUsagePercent(); Assert.That(percent, Is.EqualTo(75.0)); } @@ -193,7 +193,7 @@ public async Task GetMemoryUsagePercent_ReturnsNull_OnIOException() { _fileReaderMock.Setup(f => f.ReadAllText(It.IsAny())).Throws(new IOException()); - var result = await _service.GetMemoryUsagePercent(MemoryUnits.KiloBytes); + var result = await _service.GetMemoryUsagePercent(); Assert.That(result, Is.Null); } From e8f5b7cbe4911ed684f6b157e46259759a0695f7 Mon Sep 17 00:00:00 2001 From: Anupal Mishra Date: Tue, 3 Feb 2026 21:04:48 +0000 Subject: [PATCH 6/6] Update battery command and tests --- stmx.tests/Commands/BatteryCommandTest.cs | 26 +++++++++---- stmx/Commands/BatteryCommand.cs | 47 +++++++++++++++-------- 2 files changed, 50 insertions(+), 23 deletions(-) diff --git a/stmx.tests/Commands/BatteryCommandTest.cs b/stmx.tests/Commands/BatteryCommandTest.cs index 49fff12..49bd030 100644 --- a/stmx.tests/Commands/BatteryCommandTest.cs +++ b/stmx.tests/Commands/BatteryCommandTest.cs @@ -24,7 +24,12 @@ public async Task TestBatteryCommand_PrintsIconsAndPercent() var consoleOut = new StringWriter(); Console.SetOut(consoleOut); - await cmd.ExecuteAsync(showIcon: true, showStatusIcon: true, showPercent: true); + await cmd.ExecuteAsync( + showIcon: true, + showStatusIcon: true, + showPercentIcon: true, + percentIconValue: "%" + ); Assert.That(consoleOut.ToString(), Is.EqualTo("CAP_ICONSTATUS_ICON 80%")); } @@ -44,7 +49,12 @@ public async Task TestBatteryCommand_NoBatteryData_PrintsEmptyFields() var consoleOut = new StringWriter(); Console.SetOut(consoleOut); - await cmd.ExecuteAsync(showIcon: false, showStatusIcon: false, showPercent: false); + await cmd.ExecuteAsync( + showIcon: false, + showStatusIcon: false, + showPercentIcon: false, + percentIconValue: "" + ); Assert.That(consoleOut.ToString(), Is.EqualTo("")); } @@ -73,12 +83,14 @@ public async Task TestBatteryCommand_RespectsDefaultOptions() var consoleOut = new StringWriter(); Console.SetOut(consoleOut); - // Use defaults - await cmd.ExecuteAsync(showIcon: opts.DefaultShowBatteryIcon, - showStatusIcon: opts.DefaultShowBatteryChargingIcon, - showPercent: opts.DefaultShowBatteryPercent); + await cmd.ExecuteAsync( + showIcon: false, + showStatusIcon: false, + showPercentIcon: false, + percentIconValue: "%" + ); - Assert.That(consoleOut.ToString(), Is.EqualTo("ICON50 50%")); + Assert.That(consoleOut.ToString(), Is.EqualTo("50")); } } diff --git a/stmx/Commands/BatteryCommand.cs b/stmx/Commands/BatteryCommand.cs index eb17884..b80d3c5 100644 --- a/stmx/Commands/BatteryCommand.cs +++ b/stmx/Commands/BatteryCommand.cs @@ -14,38 +14,53 @@ public BatteryCommand(ISystemStatsService systemStats, IIconService icons) : bas _systemStats = systemStats ?? throw new ArgumentNullException(nameof(systemStats)); _icons = icons ?? throw new ArgumentNullException(nameof(icons)); - var showIconOption = new Option("--icon", ["-i"]); - showIconOption.Description = "whether to show icon"; + var showIconOption = new Option("--show-icon", ["-i"]); + showIconOption.Description = "show battery capacity icon"; showIconOption.DefaultValueFactory = _ => _systemStats.Options.DefaultShowBatteryIcon; Add(showIconOption); - var showChargingIconOption = new Option("--charging-icon", ["-c"]); - showChargingIconOption.Description = "whether to show charging icon"; - showChargingIconOption.DefaultValueFactory = _ => _systemStats.Options.DefaultShowBatteryChargingIcon; - Add(showChargingIconOption); + var showStatusIconOption = new Option("--show-status-icon", ["-s"]); + showStatusIconOption.Description = "show battery status icon"; + showStatusIconOption.DefaultValueFactory = _ => _systemStats.Options.DefaultShowBatteryChargingIcon; + Add(showStatusIconOption); - var showPercentOption = new Option("--percent", ["-p"]); - showPercentOption.Description = "whether to percent symbol"; - showPercentOption.DefaultValueFactory = _ => _systemStats.Options.DefaultShowBatteryPercent; - Add(showPercentOption); + var showPercentIconOption = new Option("--show-percent", ["-p"]); + showPercentIconOption.Description = "show percent icon (optionally provide a custom icon)"; + showPercentIconOption.Arity = ArgumentArity.ZeroOrOne; + Add(showPercentIconOption); SetAction(async (parseResult, cancellationToken) => { var showIcon = parseResult.GetValue(showIconOption); - var showChargingIcon = parseResult.GetValue(showChargingIconOption); - var showPercent = parseResult.GetValue(showPercentOption); - await ExecuteAsync(showIcon!, showChargingIcon!, showPercent!); + var showStatusIcon = parseResult.GetValue(showStatusIconOption); + var percentIconValue = parseResult.GetValue(showPercentIconOption); + await ExecuteAsync( + showIcon!, + showStatusIcon!, + parseResult.GetResult(showPercentIconOption) is not null, + percentIconValue! + ); }); } - public async Task ExecuteAsync(bool showIcon, bool showStatusIcon, bool showPercent) + public async Task ExecuteAsync( + bool showIcon, + bool showStatusIcon, + bool showPercentIcon, + string percentIconValue) { string batteryCapacityIcon = "", batteryStatusIcon = "", percentIcon = ""; var batteryCapacity = await _systemStats.GetBatteryCapacity(); - if (batteryCapacity.HasValue) { + if (batteryCapacity.HasValue) + { batteryCapacityIcon = showIcon ? await _icons.GetBatteryCapacityIcon(batteryCapacity.Value) : ""; - percentIcon = showPercent ? "%" : ""; + if (showPercentIcon) + { + percentIcon = string.IsNullOrEmpty(percentIconValue) + ? _icons.Options.PercentIcon + : percentIconValue; + } } var batteryStatus = await _systemStats.GetBatteryStatus();