directvt / vtm

Text-based desktop environment
MIT License
1.61k stars 43 forks source link

Application Scripting Runtime #393

Open o-sdn-o opened 1 year ago

o-sdn-o commented 1 year ago

Application Scripting Runtime

Language support

o-sdn-o commented 1 year ago

I see two ways to integrate vtm with high-level scripting languages (a-la embedding a scripting language).

First way

The integration at the source code level by including scripting language libraries to your code and parallel launch of the scripting language runtime object inside our environment.

pros

cons

Second way

Parallel execution of the scripting language runtime in interactive mode and control of its lifetime from the outside.

pros

cons

Summary

In both cases, binary serialization is required.

I chose the second way because the list of pros is too tempting. Maybe I will run into some unsolvable problems in the future, but so far everything looks quite feasible.

Scripting engine runtime configuration https://github.com/netxs-group/vtm/blob/0594a25ee5b18ca61b9c06b95ed2cbfbe76c9fc1/src/vtm.xml#L2-L13

o-sdn-o commented 1 year ago

PowerShell (both Windows PowerShell and PowerShell Core) doesn't fit into this concept. They do not support redirected I/O.

o-sdn-o commented 1 year ago

They do not support redirected I/O.

There is an option to pile up the PSRP protocol implementation to communicate with a running powershell -s server, but I consider this a dead end and overengineering.

So let's give powershell the console they need. No wonder we have our own windows console api server implementation.

o-sdn-o commented 1 year ago

We have implemented scripting engine lifetime control in our environment, we get console output from them and we can send command blocks.

Now we need to somehow forward user input to the script engine. I see two approaches to implement such forwarding:

For us, the only acceptable option is to send commands in blocks for the following reasons:

To implement block input, we need our own ReadLine function, which supports grapheme clusters, inline editing, clipboard, input history (with prediction), and possibly syntax highlighting.

We are already experienced in creating ReadLine-like functions. We did this as part of the cooked read implementation for Win32 API Server (readline for cmd.exe).

Vosjedev commented 1 year ago

any docs on how to use this planned?

We have implemented scripting engine lifetime control in our environment, we get console output from them and we can send command blocks.

what does this mean in simpler languige? (oops, knowledge limit...)

o-sdn-o commented 1 year ago

any docs on how to use this planned?

yes, it will definitely be

We have implemented scripting engine lifetime control in our environment, we get console output from them and we can send command blocks.

what does this mean in simpler language?

vtm can run any scripting shell (python, powershell, pwsh, lua, javascript) in parallel. vtm can send input to it and receive output (a-la stdin/stdout). Now we need to make some kind of proxy object inside the scripting shell to provide access to the vtm environment internals (sort of IPC). I'm thinking of generating this object by stdin injection at startup.

o-sdn-o commented 1 year ago

This approach is to use these scripting interpreters without integrating with third-party libraries at the source code level.

In general, vtm runs the scripting interpreter and provides the user or code with an interface to interact with the scripting engine.

Vosjedev commented 1 year ago

some kind of proxy object inside the scripting shell

Ah. so vtm can start a python3 runtime for example, and all the code executes, but there is currently no way to see the output in vtm?

how would I currently let vtm start a python3 script? This so I can test it by making a file (a persistent change) to make sure it runs...

Vosjedev commented 1 year ago

vtm can send input to it and receive output (a-la stdin/stdout

where does the output go?

o-sdn-o commented 1 year ago

where does the output go?

All output is made through the logging subsystem and goes to the server console vtm -s as well as any attached monitor vtm -m.

I am now making keyboard input possible in the server console, as well as in monitors (vtm -m), and then forwarding this input to the scripting runtime.

o-sdn-o commented 1 year ago

so vtm can start a python3 runtime for example, and all the code executes

Exactly

Vosjedev commented 1 year ago

Sorry for asking again, but how do I tell vtm to start a script? Though a new type of app in the app bar? or using a command line option?

I am now making keyboard input possible in the server console, as well as in monitors (vtm -m), and then forwarding this input to the scripting runtime.

So for now apps will only be able to get input via the server, not via the client?

o-sdn-o commented 1 year ago

It is assumed that the launch of scripts will be possible in the following ways:

At the moment, this has not yet been implemented and these are only plans to do so. I will describe how to use it in more detail when I finish it and it will be possible to use it. The approach that I decided to implement is not used by anyone, and there may be some inconsistencies that require rethinking of such an architecture.

So for now apps will only be able to get input via the server, not via the client?

Applications now have a TUI subsystem through which they receive keyboard and mouse input and output their interface. When the scripting runtime is done, each application will have additional CLI input interface, like the vtm server has. As a result, applications will have their own textual CLI console, which will be accessible from outside.

o-sdn-o commented 1 year ago

Feel free to ask if you have any questions. I will try to make it clearer. Of course, this will all be clearer when it is implemented and it will be possible to play with it live.

Vosjedev commented 10 months ago

I was recently thinking about this... So if I understand correctly, the idea is vtm will run a script, and read stdout. The script will give instructions via stdout, and it will get input via stdin. I thought maybe apps could work like this:

The app prints a layout in an xml/html-like format (or maybe something else). Every element of which the content could be updated or needs to be accesable in another waygets an id in the element tag. The app can then print just that one element, including id (but other tags not), with the new content.

For example: (I wrote the examples in html as I am more familiar with it. A new ml (dvtml?) is possible.) The app starts, and prints the following layout:

<root>
    <!-- The window title -->
    <title>Test Window</title>
    <!-- window size (in terminal blocks?) -->
    <height>80</height>
    <width>80</width> <!-- this windows width is twice it's height, maybe the size shouldn't be in terminal blocks... -->

    <!-- UI -->
    <text>This is a window.</text>
    <text id="textfield">This text changes</text>
</root>

And then it could update the textfield with id textfield by printing this:

<text id="textfield">Changed text</text>

So then the layout looks like this:

<root>
    <!-- The window title -->
    <title>Test Window</title>
    <!-- window size (in terminal blocks?) -->
    <height>80</height>
    <width>80</width> <!-- this windows width is twice it's height, maybe the size shouldn't be in terminal blocks... -->

    <!-- UI -->
    <text>This is a window.</text>
    <text id="textfield">Changed text</text>
</root>

So far my though-out ideas, here are just some random ones:

Input fields? Layout:

<root>
    <!-- The window title -->
    <title>Test Window</title>

    <!-- UI -->
    <text>Type text below</text>
    <input id="inputfield" placeholder="Type here..."></button>
</root>

placeholder would be text that disappeared as the flield gets focus, like on many input fields thoughout oses and toolkits. The app could request the content with printing this:

<input id="inputfield" action='getData'>

and then read stdin for the data. With multiline input fields it could read until a specific character ('\x04'/C-d/EOF?) was printed on a seperate line.

End of random ideas

The recieving of data by the app itself is a bit of a problem in my concept.

This is just a concept, and is probably very flawed... but I though I would just thow it out anyway.

Also: github did not like me typing such long messages in its message box, so I wrote in vscode and copied it :D

o-sdn-o commented 10 months ago

Interesting idea, I'll have to think about it.

vtm will run a script, and read stdout. The script will give instructions via stdout, and it will get input via stdin.

I have the following concept in my head. The script will communicate with the vtm environment through some global object (proxy object) located in the address space of the scripting language runtime. This global object will provide an API interface (methods) for interacting with vtm environment objects. This global object will be loaded (injected) into the scripting language's address space via stdin (or somehow) when vtm server is started.

All stdout data is text information for the user displayed on the console in interactive mode.

o-sdn-o commented 10 months ago

Yes, indeed, there are two areas - building and modifying the DOM (object model) of the vtm environment, and rendering the UI to the console.

After any IPC mechanism for communicating with DOM from the scripting language runtime is implemented, it will be necessary to come up with a protocol/approach for modifying DOM objects. The approach you suggested is very suitable for this.

By the way, the DirectVT protocol is a story about console rendering.

In the end there will be six pipes:

Vosjedev commented 10 months ago

Ah, more than one I/O pair solves the problems indeed. But do you have any plans on how to implement multiple I/O pairs without writing native libraries? I think binary calls are being avoided in most languages other than shellscript... The only way I know to make pipes cross-language is unix sockets which (as the name suggests) aren't cross-platform, and tcp/udp which is made for internet stuff, not ipc, and last, reading/writing stdin/out/err which only gives 1 I and 2 O's, and the plan is 3 I's and 3 O's.

Vosjedev commented 10 months ago

Just though of another option which is plain text files, but that gives read/write cycles to the ssd and is slow, so unwanted on most systems.

o-sdn-o commented 10 months ago

do you have any plans on how to implement multiple I/O pairs

o-sdn-o commented 10 months ago

To see the input text broadcast, you can run multiple instances of vtm -m.

Just be careful and don't accidentally run vtm -m inside the vtm environment with Log switch enabled. If Log is enabled, then recursion occurs and everything freezes. vtm -m should be run without the "Log" switch enabled.

Log switch is enabled in debug builds by default.

Also, you can play around with broadcasting when you run vtm server in interactive mode vtm -s.