Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
12d898d
Add toggle command to switch between two input sources; update docume…
markdwags Jan 8, 2026
3d2c487
Add Chocolatey installation instructions to README
markdwags Jan 8, 2026
0ff4ae9
Add EDID parsing functionality and update monitor data structure
markdwags Jan 9, 2026
ff1b199
Add EDID information retrieval and display command for monitors
markdwags Jan 9, 2026
06e264f
Add info command to display detailed EDID information with JSON outpu…
markdwags Jan 9, 2026
f7a2556
Refactor manufacture date display to include month name and week number
markdwags Jan 9, 2026
4454b6f
Enhance monitor details display with structured panels and tables for…
markdwags Jan 9, 2026
7886612
Improve error handling and performance in command processing and feat…
markdwags Jan 9, 2026
fe10fa5
Remove outdated examples and improve documentation clarity for EDID d…
markdwags Jan 9, 2026
4efcd89
Update README.md
markdwags Jan 9, 2026
a474f12
Update DDCSwitch/Commands/ToggleCommand.cs
markdwags Jan 9, 2026
9fe5f4b
Update DDCSwitch/NativeMethods.cs
markdwags Jan 9, 2026
0af6a6d
Update DDCSwitch/EdidParser.cs
markdwags Jan 9, 2026
74d1264
Merge remote-tracking branch 'origin/fix/choco-install' into fix/choc…
markdwags Jan 9, 2026
c171cda
Align table columns in ConsoleOutputFormatter and adjust spacing in L…
markdwags Jan 9, 2026
5387633
Add build script and enhance command output styling
markdwags Jan 9, 2026
b7f0168
Enhance monitor name resolution with DDC/CI priority and improve EDID…
markdwags Jan 10, 2026
3a75d18
Restructure project layout
markdwags Jan 10, 2026
f2f2617
Merge branch 'main' into feature/enhancements
markdwags Jan 12, 2026
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
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,6 @@ artifacts/
*.snupkg
**/packages/*

dist/
dist/

.vscode/
18 changes: 18 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,24 @@

All notable changes to ddcswitch will be documented in this file.

## [1.0.4] - 2026-01-09

### Added
- Enhanced visual styling across all commands with improved panels, tables, and progress bars
- Better color hierarchy and readability optimized for Windows Terminal and Command Prompt dark backgrounds
- Improved status indicators with clear symbols (✓/✗/⚠) for monitor and feature status
- Visual progress bars for percentage-based features (brightness, contrast) in `get` command
- Summary statistics in `list` command showing monitor count and DDC/CI status overview
- Better visual separation and formatting in `set`, `toggle`, and scan commands
- Documentation for `NO_COLOR` environment variable support (automatic via Spectre.Console)
- Consistent panel styling with icons for better visual hierarchy (📋⚡🎨📡)

### Improved
- Error messages now include better formatting and actionable hints
- Success panels show more detailed information with clear visual structure
- Table styling enhanced for better readability on dark backgrounds
- Warning messages have improved formatting and context

## [1.0.3] - 2026-01-08

### Added
Expand Down
8 changes: 4 additions & 4 deletions DDCSwitch/Commands/ConsoleOutputFormatter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public static void WriteMonitorDetails(Monitor monitor)
{
// Header with monitor identification
var headerPanel = new Panel(
$"[bold white]{monitor.Name}[/]\n" +
$"[bold white]{monitor.ResolvedName}[/]\n" +
$"[dim]Device:[/] [cyan]{monitor.DeviceName}[/] " +
$"[dim]Primary:[/] {(monitor.IsPrimary ? "[green]Yes[/]" : "[dim]No[/]")}")
{
Expand Down Expand Up @@ -152,9 +152,9 @@ public static void WriteMonitorDetails(Monitor monitor)
var chromaTable = new Table()
.Border(TableBorder.Rounded)
.BorderColor(Color.Grey)
.AddColumn(new TableColumn("[bold]Color[/]").Centered().Width(12))
.AddColumn(new TableColumn("[bold]X[/]").Centered().Width(12))
.AddColumn(new TableColumn("[bold]Y[/]").Centered().Width(12));
.AddColumn(new TableColumn("[bold]Color[/]").LeftAligned().Width(12))
.AddColumn(new TableColumn("[bold]X[/]").LeftAligned().Width(12))
.AddColumn(new TableColumn("[bold]Y[/]").LeftAligned().Width(12));

chromaTable.AddRow(
"[red]● Red[/]",
Expand Down
43 changes: 31 additions & 12 deletions DDCSwitch/Commands/GetCommand.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using Spectre.Console;
using Spectre.Console;
using System.Text.Json;

namespace DDCSwitch.Commands;
Expand Down Expand Up @@ -267,39 +267,58 @@ private static void OutputFeatureValue(Monitor monitor, VcpFeature feature, uint
}
else
{
var panel = new Panel(
$"[bold cyan]Monitor:[/] {monitor.Name}\n" +
// Header panel with monitor info
var headerPanel = new Panel(
$"[bold white]{monitor.Name}[/]\n" +
$"[dim]Device:[/] [dim]{monitor.DeviceName}[/]")
{
Header = new PanelHeader($"[bold green]>> Feature Value[/]", Justify.Left),
Header = new PanelHeader($"[bold cyan]📊 {feature.Name}[/]", Justify.Left),
Border = BoxBorder.Rounded,
BorderStyle = new Style(Color.Cyan)
};
AnsiConsole.Write(panel);
AnsiConsole.Write(headerPanel);
AnsiConsole.WriteLine();

if (feature.Code == InputSource.VcpInputSource)
{
// Display input with name resolution
var inputName = InputSource.GetName(current);
AnsiConsole.MarkupLine($" [bold yellow]{feature.Name}:[/] [cyan]{inputName}[/] [dim](0x{current:X2})[/]");
var valuePanel = new Panel(
$"[bold cyan]{inputName}[/] [dim](0x{current:X2})[/]")
{
Header = new PanelHeader("[bold yellow]Current Input Source[/]", Justify.Left),
Border = BoxBorder.Rounded,
BorderStyle = new Style(Color.Yellow)
};
AnsiConsole.Write(valuePanel);
}
else if (feature.SupportsPercentage)
{
// Display percentage for brightness/contrast
// Display percentage for brightness/contrast with progress bar
uint percentage = FeatureResolver.ConvertRawToPercentage(current, max);

var progressBar = new BarChart()
.Width(40)
.Label($"[bold yellow]{feature.Name}[/]")
.Width(50)
.Label($"[bold yellow]{percentage}%[/]")
.CenterLabel()
.AddItem("", percentage, Color.Green);
.AddItem("", percentage, percentage >= 75 ? Color.Green :
percentage >= 50 ? Color.Yellow :
percentage >= 25 ? Color.Orange1 : Color.Red);

AnsiConsole.Write(progressBar);
AnsiConsole.MarkupLine($" [bold green]{percentage}%[/] [dim](raw: {current}/{max})[/]");
AnsiConsole.MarkupLine($" [dim]Raw value: {current}/{max}[/]");
}
else
{
// Display raw values for unknown VCP codes
AnsiConsole.MarkupLine($" [bold yellow]{feature.Name}:[/] [green]{current}[/] [dim](max: {max})[/]");
var valuePanel = new Panel(
$"[bold green]{current}[/] [dim](maximum: {max})[/]")
{
Header = new PanelHeader("[bold yellow]Current Value[/]", Justify.Left),
Border = BoxBorder.Rounded,
BorderStyle = new Style(Color.Yellow)
};
AnsiConsole.Write(valuePanel);
}
}
}
Expand Down
6 changes: 3 additions & 3 deletions DDCSwitch/Commands/InfoCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ private static int DisplayMonitorInfo(Monitor monitor, bool jsonOutput)
{
var monitorRef = new MonitorReference(
monitor.Index,
monitor.Name,
monitor.ResolvedName,
monitor.DeviceName,
monitor.IsPrimary);

Expand Down Expand Up @@ -166,7 +166,7 @@ private static int DisplayMonitorInfo(Monitor monitor, bool jsonOutput)
{
if (jsonOutput)
{
var monitorRef = new MonitorReference(monitor.Index, monitor.Name, monitor.DeviceName, monitor.IsPrimary);
var monitorRef = new MonitorReference(monitor.Index, monitor.ResolvedName, monitor.DeviceName, monitor.IsPrimary);
var error = new ErrorResponse(false, $"Failed to retrieve monitor information: {ex.Message}", monitorRef);
Console.WriteLine(JsonSerializer.Serialize(error, JsonContext.Default.ErrorResponse));
}
Expand Down Expand Up @@ -204,7 +204,7 @@ private static int HandleMonitorNotFound(List<Monitor> monitors, string identifi
else
{
ConsoleOutputFormatter.WriteError($"Monitor '{identifier}' not found.");
AnsiConsole.MarkupLine($"Available monitors: [cyan]{string.Join(", ", monitors.Select(m => m.Index.ToString()))}[/]");
AnsiConsole.MarkupLine("[dim]Use [/][yellow]ddcswitch list[/][dim] to see available monitors.[/]");
}

foreach (var m in monitors)
Expand Down
45 changes: 37 additions & 8 deletions DDCSwitch/Commands/ListCommand.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using Spectre.Console;
using Spectre.Console;
using System.Text.Json;

namespace DDCSwitch.Commands;
Expand Down Expand Up @@ -118,7 +118,7 @@ private static void OutputJsonList(List<Monitor> monitors, bool verboseOutput)

return new MonitorInfo(
monitor.Index,
monitor.Name,
monitor.ResolvedName,
monitor.DeviceName,
monitor.IsPrimary,
inputName,
Expand All @@ -141,6 +141,35 @@ private static void OutputJsonList(List<Monitor> monitors, bool verboseOutput)

private static void OutputTableList(List<Monitor> monitors, bool verboseOutput)
{
// Summary statistics header
int ddcciCount = 0;
int primaryCount = 0;

foreach (var monitor in monitors)
{
if (monitor.IsPrimary) primaryCount++;
try
{
if (monitor.TryGetInputSource(out _, out _))
{
ddcciCount++;
}
}
catch { }
}

var summaryPanel = new Panel(
$"[bold white]Total Monitors:[/] [cyan]{monitors.Count}[/] " +
$"[bold white]DDC/CI Capable:[/] [green]{ddcciCount}[/] " +
$"[bold white]Primary:[/] [yellow]{primaryCount}[/]")
{
Header = new PanelHeader("[bold cyan]🖥️ Monitor Overview[/]", Justify.Left),
Border = BoxBorder.Rounded,
BorderStyle = new Style(Color.Cyan)
};
AnsiConsole.Write(summaryPanel);
AnsiConsole.WriteLine();

var table = new Table()
.Border(TableBorder.Rounded)
.BorderColor(Color.White)
Expand All @@ -165,7 +194,7 @@ private static void OutputTableList(List<Monitor> monitors, bool verboseOutput)
foreach (var monitor in monitors)
{
string inputInfo = "[dim]N/A[/]";
string status = "[green]+[/] [bold green]OK[/]";
string status = "[green][/] [bold green]OK[/]";
string brightnessInfo = "[dim]N/A[/]";
string contrastInfo = "[dim]N/A[/]";

Expand All @@ -178,11 +207,11 @@ private static void OutputTableList(List<Monitor> monitors, bool verboseOutput)
}
else
{
status = "[yellow]~[/] [bold yellow]No DDC/CI[/]";
status = "[yellow][/] [bold yellow]No DDC/CI[/]";
}

// Get brightness and contrast if verbose mode is enabled and monitor supports DDC/CI
if (verboseOutput && status == "[green]+[/] [bold green]OK[/]")
if (verboseOutput && status == "[green][/] [bold green]OK[/]")
{
// Try to get brightness (VCP 0x10)
if (monitor.TryGetVcpFeature(VcpFeature.Brightness.Code, out uint brightnessCurrent, out uint brightnessMax))
Expand Down Expand Up @@ -214,7 +243,7 @@ private static void OutputTableList(List<Monitor> monitors, bool verboseOutput)
}
catch
{
status = "[red]X[/] [bold red]Error[/]";
status = "[red][/] [bold red]Error[/]";
if (verboseOutput)
{
brightnessInfo = "[dim]N/A[/]";
Expand All @@ -224,8 +253,8 @@ private static void OutputTableList(List<Monitor> monitors, bool verboseOutput)

var row = new List<string>
{
monitor.IsPrimary ? $"[bold cyan]{monitor.Index}[/] [yellow]*[/]" : $"[cyan]{monitor.Index}[/]",
monitor.Name,
monitor.IsPrimary ? $"[bold cyan]{monitor.Index}[/] [yellow][/]" : $"[cyan]{monitor.Index}[/]",
monitor.ResolvedName,
$"[dim]{monitor.DeviceName}[/]",
inputInfo
};
Expand Down
21 changes: 13 additions & 8 deletions DDCSwitch/Commands/SetCommand.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using Spectre.Console;
using Spectre.Console;
using System.Text.Json;

namespace DDCSwitch.Commands;
Expand Down Expand Up @@ -369,28 +369,33 @@ private static void OutputSuccess(Monitor monitor, VcpFeature feature, uint setV
else
{
string displayValue;
string featureIcon;

if (feature.Code == InputSource.VcpInputSource)
{
// Display input with name resolution
displayValue = $"[cyan]{InputSource.GetName(setValue)}[/]";
displayValue = $"[bold cyan]{InputSource.GetName(setValue)}[/] [dim](0x{setValue:X2})[/]";
featureIcon = "📺";
}
else if (percentageValue.HasValue)
{
// Display percentage for brightness/contrast
displayValue = $"[green]{percentageValue}%[/]";
displayValue = $"[bold green]{percentageValue}%[/] [dim](raw: {setValue})[/]";
featureIcon = feature.Code == VcpFeature.Brightness.Code ? "☀️" : "🎨";
}
else
{
// Display raw value for unknown VCP codes
displayValue = $"[green]{setValue}[/]";
displayValue = $"[bold green]{setValue}[/]";
featureIcon = "⚙️";
}

var successPanel = new Panel(
$"[bold cyan]Monitor:[/] {monitor.Name}\n" +
$"[bold yellow]Feature:[/] {feature.Name}\n" +
$"[bold green]New Value:[/] {displayValue}")
$"[bold white]{monitor.Name}[/]\n" +
$"[dim]Device:[/] [dim]{monitor.DeviceName}[/]\n\n" +
$"[bold yellow]{feature.Name}:[/] {displayValue}")
{
Header = new PanelHeader("[bold green]>> Successfully Applied[/]", Justify.Left),
Header = new PanelHeader($"[bold green]✓ {featureIcon} Successfully Applied[/]", Justify.Left),
Border = BoxBorder.Rounded,
BorderStyle = new Style(Color.Green)
};
Expand Down
17 changes: 12 additions & 5 deletions DDCSwitch/Commands/ToggleCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -379,11 +379,11 @@ private static void OutputToggleSuccess(Monitor monitor, uint currentInput, uint
else
{
var successPanel = new Panel(
$"[bold cyan]Monitor:[/] {monitor.Name}\n" +
$"[bold yellow]From:[/] {fromInputName}\n" +
$"[bold green]To:[/] {toInputName}")
$"[bold white]{monitor.Name}[/]\n" +
$"[dim]Device:[/] [dim]{monitor.DeviceName}[/]\n\n" +
$"[cyan]{fromInputName}[/] [dim](0x{currentInput:X2})[/] [bold yellow]→[/] [bold cyan]{toInputName}[/] [dim](0x{targetInput:X2})[/]")
{
Header = new PanelHeader("[bold green]>> Input Toggled Successfully[/]", Justify.Left),
Header = new PanelHeader("[bold green]✓ 🔄 Input Toggled Successfully[/]", Justify.Left),
Border = BoxBorder.Rounded,
BorderStyle = new Style(Color.Green)
};
Expand All @@ -392,7 +392,14 @@ private static void OutputToggleSuccess(Monitor monitor, uint currentInput, uint

if (hasWarning && warningMessage != null)
{
AnsiConsole.MarkupLine($"[yellow]Warning:[/] {warningMessage}");
AnsiConsole.WriteLine();
var warningPanel = new Panel(warningMessage)
{
Header = new PanelHeader("[bold yellow]⚠ Warning[/]", Justify.Left),
Border = BoxBorder.Rounded,
BorderStyle = new Style(Color.Yellow)
};
AnsiConsole.Write(warningPanel);
}
}
}
Expand Down
Loading