Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support platform-specific path separator in TextPath #1730

Open
TheTonttu opened this issue Jan 11, 2025 · 0 comments
Open

Support platform-specific path separator in TextPath #1730

TheTonttu opened this issue Jan 11, 2025 · 0 comments

Comments

@TheTonttu
Copy link

Is your feature request related to a problem? Please describe.
TextPath is hard-coded to use POSIX path separator, which could impair UX on a platform with different primary path separator, e.g. Windows.

Describe the solution you'd like
Allow configuring TextPath to alternatively use the platform-specific path separator.

Describe alternatives you've considered
One workaround is to create wrapper class for TextPath that swaps the separator segment on render. Alternative, and probably less clunky, workaround would be to create derived implementation of TextPath which overrides the render method but that is not currently possible because the class is marked sealed.

Simplified example of the workaround wrapper class

using Spectre.Console;
using Spectre.Console.Rendering;

public class SystemTextPath : IRenderable, IHasJustification
{
    private static readonly string SystemDirectorySeparator = Path.DirectorySeparatorChar.ToString();
    private static readonly bool OverrideSeparator = OperatingSystem.IsWindows() || Path.DirectorySeparatorChar != '/';

    private readonly TextPath _textPath;
    private Segment _directorySeparatorSegment;

    // For brevity, duplicated non-interface TextPath style etc. passthrough properties omitted.

    public Justify? Justification
    {
        get => _textPath.Justification;
        set => _textPath.Justification = value;
    }

    public SystemTextPath(string path)
    {
        _textPath = new TextPath(path);
        _directorySeparatorSegment = new Segment(SystemDirectorySeparator, _textPath.SeparatorStyle ?? Style.Plain);
    }

    public Measurement Measure(RenderOptions options, int maxWidth)
    {
        // Measurement should not be affected with '/' -> '\' swap.
        return _textPath.Measure(options, maxWidth);
    }

    public IEnumerable<Segment> Render(RenderOptions options, int maxWidth)
    {
        if (OverrideSeparator)
        {
            return RenderSystemSpecificPath(options, maxWidth);
        }
        // Default POSIX path.
        return _textPath.Render(options, maxWidth);
    }

    private IEnumerable<Segment> RenderSystemSpecificPath(RenderOptions options, int maxWidth)
    {
        var pathSegments = _textPath.Render(options, maxWidth);
        foreach (Segment segment in pathSegments)
        {
            yield return IsPathSeparator(segment)
                ? _directorySeparatorSegment
                : segment;
        }
    }

    private static bool IsPathSeparator(Segment segment)
    {
        return string.Equals("/", segment.Text, StringComparison.Ordinal);
    }
}

Please upvote 👍 this issue if you are interested in it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: Todo 🕑
Development

No branches or pull requests

1 participant