php-tui / term

low-level terminal manipulation library for PHP
MIT License
30 stars 4 forks source link

Windows Support #14

Open ALameLlama opened 1 month ago

ALameLlama commented 1 month ago

Hey,

In the other repo, you said adding Windows support shouldn't be too bad, so I thought I'd take a look at it.

Having a quick look, I think the main roadblock will be https://github.com/php-tui/term/blob/main/src/Reader/StreamReader.php#L29

I don't think Windows Con will allow reading like this and will require input to continue otherwise it will hang, I've seen other examples on GitHub using PHP FFI and directly using C but I'm not sure if that's the best direction since I think it'll be slow.

Would love to have some input on what you'd suggest looking into :)

Edit: I've been looking over crossterm which is why I was looking down the FFI path and using C

dantleech commented 1 month ago

I don't really have much insight here, Symfony Console supports color output on Windows 10: https://github.com/symfony/symfony/pull/18385 because W10 supports "VT100 color support". But as you suggest we probably need to hook into the C API as crossterm does - and if we did that we could also avoid calling out to stty - I think the problem with FFI was essentially that it's not enabled by default?

ALameLlama commented 1 month ago

I stumbled upon this https://github.com/nahkampf/php-keypress-windows, this is what I was manually implementing but seems a lot more complete.

https://github.com/php-tui/term/commit/faf9b5da6a5c9d391b65b3b376a5ce791dcb148b

I don't believe FFI is enabled by default since I don't think most people want PHP to be able to execute C code which is understandable.

I guess the main benefit here would be if you were to ship your tui apps using static PHP cli since you can enable it and distribute it. https://static-php.dev/en/guide/extensions.html

I think I'll have a play around with some ideas but it seems like windows will need FFI to work anything like does on Unix.

I have it starting and keypresses work, no mouse events and it breaks when pressing tab.

https://github.com/user-attachments/assets/c5e053bf-d86a-4c76-b54a-2918568640d1

dantleech commented 1 month ago

Yes, having an FFI strategy would be good for Unix systems too I think.

ALameLlama commented 2 weeks ago

I'm still slowly looking into this, there's still like a 100-200ms delay between pressing a key and it's getting read. and I haven't got mouse cursor support working correctly yet either.

ALameLlama commented 1 week ago

Ok, it's looking much better, I still want to clean some more of the code up and test is more fully since I don't have a 100% keyboard to test keypad properly.

I'll need to think about how to handle the enable mouse since doing $terminal->execute(Actions::enableMouseCapture()); requires it to be a virtual input but this breaks events like the focus gain/focus loss. but I don't think having the mouse always enabled is the worst thing.

<?php

require_once __DIR__ . '/vendor/autoload.php';

use PhpTui\Term\Actions;
use PhpTui\Term\ClearType;
use PhpTui\Term\Event\CharKeyEvent;
use PhpTui\Term\Terminal;

$terminal = Terminal::new();

$terminal->execute(Actions::cursorHide());
$terminal->execute(Actions::alternateScreenEnable());
// $terminal->execute(Actions::enableMouseCapture());
$terminal->enableRawMode();

echo 'press q to quit' . PHP_EOL;
while (true) {
    while ($event = $terminal->events()->next()) {
        if (empty($event)) {
            continue;
        }

        var_export($event);

        if ($event instanceof CharKeyEvent) {
            if ($event->char == 'q') {
                break 2;
            }
        }
    }
}

$terminal->disableRawMode();
// $terminal->execute(Actions::disableMouseCapture());
$terminal->execute(Actions::alternateScreenDisable());
$terminal->execute(Actions::cursorShow());
$terminal->execute(Actions::clear(ClearType::All));

https://github.com/user-attachments/assets/883bd8c2-60e7-4864-b630-acffc662bdb8

There seems to be still weird input delay and mouse issues using the example demo even though the code is very similar so I'll need to see what is happening on the php-tui side to see if something is causing it.