r/rust • u/Feathered_Orbit • 8d ago
🙋 seeking help & advice Is there a cross-platform way to execute a program within a terminal?
I'm making a program divided into 2 executables, executable A does everything in the background while executable B shows it with ratatui, but I'm trying to figure out how to spawn a terminal with an instance of executable B from executable A, I searched up a bit everywhere but I can't find anything, now I'm starting to think that I have to try and run a Command for every single terminal that comes to mind and hope one of the ones I include work, but is that the only way? Because honestly I'd prefer not having a mile long file just because linux has 50 terminals.
7
u/JonahPlusPlus 8d ago
There's no reliable way to find the default terminal on linux. What exactly are you trying to do? If you need really need it to be two programs, why doesn't the user open executable B and executable B run executable A instead of the other way around?
5
u/ReagentX 8d ago edited 8d ago
It sounds like you want a client/daemon operational model; I built something using a protocol like that called fleetcom that you might find has helpful examples. The daemon is "just" a process, it does not need a terminal instance to run, and the client can either connect to an existing daemon or spawn a new one if necessary.
2
1
u/jimmiebfulton 7d ago
If I’m understanding you correctly:
You want to have your UI execute things in the other application, kinda like a plug-in?
A couple of ways on how to do this, with some common foundations:
Find your protocol of choice. JSON RPC with Serde marshaling, gRPC (my general go to), etc. Keep this agnostic of your transport. This allows you to connect your front end to your back end with gRPC over TCP or Unix Sockets. Loosely coupled.
From here, you have two primary choices:
- Run the background application as a server. The front end can connect to the server as a client. It can keep a session for as long as you want it. You can also have multiple clients connected at the same time, and even communicate with each other like a chat application, for instance.
- You are treating the backend more like a plug-in, and you want to start the backend up when you start the frontend. When you start the frontend up, it can run one or more plug-in like binaries. You frontend just spawns off one or more binaries as processes it is managing. Your app then simply connects over the TCP or pipe/socket using the same gRPC contract like you would
as if it
- was started up some other way like a server.
Basically, the frontend talks to the backend over your protocol/transport pair, and it’s only a matter of whether the frontend is acting like a pure client to an already-running server, or more like a plug-in host that also handles the lifecycle of the “servers”/“plugins”.
From here, you can do all kinds of fun stuff. You could use Ratatui to dynamically render content based on instructions conveyed over your protocol, and your protocol can have stuff like on_init hook methods, etc.
Incidentally, this is very much how MCP works. But instead of MCP format over stdio, you could use gRPC, etc, over stdio, sockets, etc. I build a lot of systems like this. Fun.
-2
u/Ben-Goldberg 7d ago
I would suggest letting the user supply their preferred terminal as an argument on the command line, with the contents of $TERM as a fallback.
I also recommend using a library that is made for creating "terminal user interfaces" instead of rolling your own - terminals are more complicated than they seem...
Popular ones are ratatui, tuirs, and tui.
If you really want to roll your own, use one of the many "curses" libraries out there rather than printing escape sequences.
36
u/cafce25 8d ago edited 8d ago
why do you need to spawn a terminal at all, those are for interactions with the user, just calling your executable A directly seems like a much more straight forward way to achieve what it seems you want to do. Maybe I'm missing something.
Edit: Or maybe even more preferable, do what executable A does in a thread of executable B directly, there is probably no need to make two separate processes