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

Application Scripting Runtime #393

Open
3 tasks
o-sdn-o opened this issue May 31, 2023 · 21 comments
Open
3 tasks

Application Scripting Runtime #393

o-sdn-o opened this issue May 31, 2023 · 21 comments
Assignees
Labels
enhancement New feature or request GUI UX User Experience XML
Milestone

Comments

@o-sdn-o
Copy link
Collaborator

o-sdn-o commented May 31, 2023

Application Scripting Runtime

  • Configuration access
  • Environment access via REPL (aka Direct mode)
  • Scripting actions

Language support

  • Python
  • Windows PowerShell (powershell.exe)
  • PowerShell Core (pwsh)
  • JavaScript
  • Lua
@o-sdn-o o-sdn-o added enhancement New feature or request GUI UX User Experience XML labels May 31, 2023
@o-sdn-o o-sdn-o added this to the v1.0.0 milestone May 31, 2023
@o-sdn-o o-sdn-o self-assigned this May 31, 2023
@o-sdn-o o-sdn-o pinned this issue May 31, 2023
@o-sdn-o
Copy link
Collaborator Author

o-sdn-o commented Jun 1, 2023

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

  • Scripting languages provide C-API for integration.
  • Possible preservation of high performance due to direct interaction with the runtime object of the scripting environment.
  • Finer control over the lifetime of a script runtime object.

cons

  • Dependence on the source code of the scripting language.
  • Dependence on C-API scripting language.
  • Dependence on the license under which the scripting language is published.
  • Increasing the size of everything.
  • Lack of support for static linking in a number of scripting languages (e.g. Python).
  • Increasing the complexity of building and linking.
  • As a rule, integration is limited to only one scripting language.

Second way

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

pros

  • Independence from C-API scripting language.
  • Independence from the source code of the scripting language.
  • Independence from the license under which the scripting language is published.
  • Ability to static linking.
  • No effect on compilation complexity.
  • Support for any number of scripting languages (even parallel usage).

cons

  • Requires a proxy object to be integrated into each runtime environment of a supported scripting language (inject via input stream).
  • Possible performance loss when marshaling through a proxy object.
  • Control of the lifetime of a script runtime object is possible only at the operating system level.

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
Copy link
Collaborator Author

o-sdn-o commented Jun 1, 2023

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

@o-sdn-o
Copy link
Collaborator Author

o-sdn-o commented Jun 2, 2023

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
Copy link
Collaborator Author

o-sdn-o commented Jun 6, 2023

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:

  • Character-by-character transmission. Forward each key pressed so that the script engine forms command blocks on its side.
  • Block-based transmission. Cook a text command block on our side and send the finished block to the script engine.

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

  • The powershel interpreter is only able to work in non-interactive mode (in our environment), which implies only block input.
  • Our environment is multi-user, respectively, several users can simultaneously enter commands, which will lead to inevitable interference in character-by-character transmission.
  • We intend to support multiple scripting engines with different syntax and formatting, and the only way to unify command line input is to use block-based transmission.

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).

@o-sdn-o o-sdn-o unpinned this issue Jun 17, 2023
@Vosjedev
Copy link

Vosjedev commented Aug 11, 2023

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
Copy link
Collaborator Author

o-sdn-o commented Aug 11, 2023

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
Copy link
Collaborator Author

o-sdn-o commented Aug 11, 2023

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
Copy link

Vosjedev commented Aug 17, 2023

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
Copy link

Vosjedev commented Aug 17, 2023

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

where does the output go?

@o-sdn-o
Copy link
Collaborator Author

o-sdn-o commented Aug 17, 2023

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
Copy link
Collaborator Author

o-sdn-o commented Aug 17, 2023

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

Exactly

@Vosjedev
Copy link

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
Copy link
Collaborator Author

o-sdn-o commented Aug 20, 2023

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

  • By using the script tag in the configuration file (settings.xml or somename.xml). Something like an event subscription.
  • Interactively, via CLI console input in vtm -s or vtm -m session.
  • Programmatically, through a special pipe (sending the body of the script) or a special vt-sequence.
  • Maybe in some other way.

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
Copy link
Collaborator Author

o-sdn-o commented Aug 20, 2023

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
Copy link

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
Copy link
Collaborator Author

o-sdn-o commented Nov 16, 2023

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
Copy link
Collaborator Author

o-sdn-o commented Nov 17, 2023

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:

  • Main window (terminal/console):
    • stdin_1 - user keyboard input to vtm
    • stdout_1 - rendering vtm's UI to console
  • Optional scripting repl console:
    • stdin_2 - user keyboard input to scripting repl
    • stdout_2 - repl console output
  • IPC to communicate between scripting space and vtm space
    • input_3 - pipe to the DOM
    • output_3 - pipe from the DOM

@Vosjedev
Copy link

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
Copy link

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
Copy link
Collaborator Author

o-sdn-o commented Nov 17, 2023

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

  • Main window's pair (terminal/console):
    • It is a pair of standard streams (stdin/stdout in console application).
  • Optional scripting repl console's pair:
    • Available as standard streams when additional console is connected to vtm. You can try it out by running vtm -m and typing some text inside it (vtm server should be active for that). All your input is broadcasted to the vtm environment, but not processed yet - you will see echo (not implemented integration with scripting).
  • IPC to communicate between scripting space and vtm space (not implemented yet):
    • It is will be implemented using UNIX domain sockets on POSIX-like platforms and using Named Pipes on MS Windows.

@o-sdn-o
Copy link
Collaborator Author

o-sdn-o commented Nov 17, 2023

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request GUI UX User Experience XML
Projects
None yet
Development

No branches or pull requests

2 participants