Skip to content

Commit

Permalink
compatibility checks for kitty, experimental windowsizing stuff.
Browse files Browse the repository at this point in the history
  • Loading branch information
trackd committed Nov 21, 2024
1 parent 0f09c67 commit 38abd36
Show file tree
Hide file tree
Showing 7 changed files with 120 additions and 10 deletions.
5 changes: 4 additions & 1 deletion docs/en-US/ConvertTo-Sixel.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,10 @@ Accept wildcard characters: False
### -Protocol
Select the image protocol to output, supports Sixel & InlineImageProtocol (1337 xterm).
Select the image protocol to output.
Supports Sixel, InlineImageProtocol, KittyGraphicsProtocol
It will attempt to autoselect the supported image protocol for your terminal.
```yaml
Type: ImageProtocol
Expand Down
2 changes: 1 addition & 1 deletion src/Sixel/Sixel.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.5" />
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.6" />
<PackageReference Include="System.Management.Automation" Version="7.4.6" PrivateAssets="all" />
<ProjectReference Include="../Sixel.Shared/Sixel.Shared.csproj" />
</ItemGroup>
Expand Down
81 changes: 74 additions & 7 deletions src/Sixel/Terminal/Compatibility.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Sixel.Terminal.Models;
using System.Diagnostics;

namespace Sixel.Terminal;

Expand All @@ -9,6 +10,11 @@ public static class Compatibility
/// </summary>
private static bool? _terminalSupportsSixel;

/// <summary>
/// Check if the terminal supports kitty graphics
/// </summary>
private static bool? _terminalSupportsKitty;

/// <summary>
/// Memory-caches the result of the terminal cell size.
/// </summary>
Expand All @@ -17,8 +23,12 @@ public static class Compatibility
/// <summary>
/// get the terminal info
/// </summary>

private static TerminalInfo? _terminalInfo;

private static WindowSizePixels? _windowSizePixels;

private static WindowSizeCharacters? _windowSizeCharacters;

/// <summary>
/// Get the cell size of the terminal in pixel-sixel size.
/// The response to the command will look like [6;20;10t where the 20 is height and 10 is width.
Expand Down Expand Up @@ -52,9 +62,55 @@ public static CellSize GetCellSize()
PixelHeight = 20
};
}

return _cellSize;
}
public static WindowSizePixels GetWindowSizePixels()
{
// this class should be able to re-run, people can resize the terminal
// so should not cache the result.. hopefully this is not too slow
var response14 = GetControlSequenceResponse("[14t");
try
{
var parts14 = response14.Split(';', 't');
_windowSizePixels = new WindowSizePixels
{
PixelWidth = int.Parse(parts14[2]),
PixelHeight = int.Parse(parts14[1]),
};
}
catch
{
_windowSizePixels = new WindowSizePixels
{
PixelWidth = 0,
PixelHeight = 0
};
}
return _windowSizePixels;
}
public static WindowSizeCharacters GetWindowSizeCharacters()
{
// this class should be able to re-run, people can resize the terminal
// so should not cache the result.. hopefully this is not too slow
var response18 = GetControlSequenceResponse("[18t");
try
{
var parts18 = response18.Split(';', 't');
_windowSizeCharacters = new WindowSizeCharacters
{
CharacterWidth = int.Parse(parts18[2]),
CharacterHeight = int.Parse(parts18[1]),
};
}
catch {
_windowSizeCharacters = new WindowSizeCharacters
{
CharacterWidth = 0,
CharacterHeight = 0
};
}
return _windowSizeCharacters;
}

/// <summary>
/// Check if the terminal supports sixel graphics.
Expand All @@ -69,17 +125,28 @@ public static bool TerminalSupportsSixel()
{
return _terminalSupportsSixel.Value;
}

_terminalSupportsSixel = GetControlSequenceResponse("[c").Contains(";4;");

return _terminalSupportsSixel.Value;
}

/// <summary>
/// Send a control sequence to the terminal and read back the response from STDIN.
/// Check if the terminal supports kitty graphics.
/// https://sw.kovidgoyal.net/kitty/graphics-protocol/
// response: ␛_Gi=31;OK␛\␛[?62;c
/// </summary>
/// <param name="controlSequence"></param>
/// <returns>The response from the terminal.</returns>
/// <returns>True if the terminal supports sixel graphics, false otherwise.</returns>
public static bool TerminalSupportsKitty()
{
if (_terminalSupportsKitty.HasValue)
{
return _terminalSupportsKitty.Value;
}
// string kittyTest = $"_Gi=31,s=1,v=1,a=q,t=d,f=24;AAAA{Constants.ESC}\\{Constants.ESC}[c";
string kittyTest = $"_Gi=31,s=1,v=1,a=q,t=d,f=24;AAAA{Constants.ESC}\\";
_terminalSupportsKitty = GetControlSequenceResponse(kittyTest).Contains(";OK");
return _terminalSupportsKitty.Value;
}

private static string GetControlSequenceResponse(string controlSequence)
{
char? c;
Expand Down
4 changes: 4 additions & 0 deletions src/Sixel/Terminal/Load.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ public static class Load
}
if (imageProtocol == ImageProtocol.KittyGraphicsProtocol)
{
if (Compatibility.TerminalSupportsKitty() == false && Force == false)
{
throw new InvalidOperationException("Terminal does not support Kitty, override with -Force");
}
if (width > 0)
{
// we need to resize the image to the target width
Expand Down
17 changes: 17 additions & 0 deletions src/Sixel/Terminal/Models/WindowSizeCharacters.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
namespace Sixel.Terminal.Models;

/// <summary>
/// Represents the size of the terminal window in characters.
/// </summary>
public class WindowSizeCharacters
{
/// <summary>
/// Gets the width of the terminal in characters.
/// </summary>
public int CharacterWidth { get; set; }

/// <summary>
/// Gets the height of the terminal in characters.
/// </summary>
public int CharacterHeight { get; set; }
}
19 changes: 19 additions & 0 deletions src/Sixel/Terminal/Models/WindowSizePixels.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
namespace Sixel.Terminal.Models;

/// <summary>
/// Represents the size of the terminal window in pixels
/// not supported in all terminals.
/// like WezTerm, Alacritty
/// </summary>
public class WindowSizePixels
{
/// <summary>
/// Gets the width of the terminal in pixels.
/// </summary>
public int PixelWidth { get; set; }

/// <summary>
/// Gets the height of the terminal in pixels.
/// </summary>
public int PixelHeight { get; set; }
}
2 changes: 1 addition & 1 deletion src/Sixel/Terminal/Validate.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ protected override void Validate(object arguments, EngineIntrinsics engineIntrin
{
var requestedWidth = (int)arguments;
var hostWidth = engineIntrinsics.Host.UI.RawUI.WindowSize.Width;
if (requestedWidth > hostWidth)
if (requestedWidth > hostWidth)
{
throw new ValidationMetadataException($"{requestedWidth} width is greater than terminal width ({hostWidth}).");
}
Expand Down

0 comments on commit 38abd36

Please sign in to comment.