I’m making an addin to run current file based on it’s extension. I need a terminal to communicate with launched program. I create Ide.TerminalPage at construction time and, after project is loaded, add TerminalPage to bottom area. I need terminal widget to not show anything before user launches the program. But TerminalPage starts with host interactive shell.
To run program RunCommand and TerminalLauncher are created. Calling spawn_async somewhat works, but program output “layers” on top of interactive shell.
Could you provide some basic steps on how to create TerminalPage and run program in it? I tried looking at Builder’s source, but it’s a bit overwhelming.
Here is my typescript code:
import GObject from 'gi://GObject';
import Gtk from 'gi://Gtk?version=4.0';
import GLib from 'gi://GLib';
import Gio from 'gi://Gio';
import Ide from 'gi://Ide';
import Panel from 'gi://Panel';
var c_files = ['c', 'cpp'];
export var CodeRunAddin = GObject.registerClass({
Implements: [Ide.WorkspaceAddin],
}, class CodeRunAddin extends GObject.Object {
workspace?: Ide.Workspace = undefined;
run_button: Gtk.Button;
context: Ide.Context|null = null;
podman_runtime?: Ide.Runtime = undefined;
source: Gio.File|null = null;
term: Ide.TerminalPage;
constructor() {
super();
this.term = new Ide.TerminalPage({
pty: Ide.pty_new_sync(),
respawnOnExit: false,
manageSpawn: true,
});
this.run_button = new Gtk.Button({
visible: false,
iconName: "media-seek-forward-symbolic",
});
this.run_button.connect("clicked", this.compile.bind(this));
}
compile () {
// Ide.Run
var builder = new Ide.RunContext();
var runner = new Ide.RunContext();
if (this.podman_runtime !== undefined && this.source?.get_path() !== null) {
var cwd = this.source?.get_parent()!;
var source_rel = cwd.get_relative_path(this.source!)!;
this.podman_runtime.prepare_to_build(null, builder);
builder.set_cwd(cwd.get_path()!);
print(`Compiler cwd: \"${builder.get_cwd()}\"`);
// runner.append_argv("lsb-release");
// runner.append_argv("-i");
builder.append_argv("g++");
builder.append_argv(source_rel);
builder.append_argv("-o");
builder.append_argv("main");
try {
var process = builder.spawn();
process.wait(null);
} catch (e: any) {
print(e.message);
}
this.podman_runtime.prepare_to_run(null, runner);
runner.set_cwd(cwd.get_path()!);
print(`Runner cwd: \"${runner.get_cwd()}\"`);
// runner.append_argv("lsb-release");
// runner.append_argv("-i");
runner.append_argv("./main");
try {
var command = new Ide.RunCommand();
var launcher = Ide.TerminalLauncher.new(this.context!, command);
command.prepare_to_run(runner, this.context!);
command.set_cwd(cwd.get_path()!);
command.append_argv("./main");
print("term pty:", this.term.get_pty());
launcher.spawn_async(this.term.get_pty(), null, null);
} catch (e: any) {
print(e.message);
}
}
}
vfunc_load(_workspace: Ide.Workspace) {
this.workspace = _workspace;
if (this.workspace.context?.has_project() == false) {
this.vfunc_unload(_workspace);
return;
} else {
print("Project seems to be loaded");
}
var pane = new Ide.Pane();
pane.set_child(this.term);
var pos = new Panel.Position();
pos.set_area(Panel.Area.BOTTOM);
_workspace.add_pane(pane, pos);
var titlebar = this.workspace?.get_header_bar();
titlebar?.add(Ide.HeaderBarPosition.RIGHT_OF_CENTER, 1, this.run_button);
this.context = _workspace.get_context();
var runtime_manager = Ide.RuntimeManager.from_context(this.context!);
var fd = runtime_manager.connect("items-changed", this.on_runtimes_changed.bind(this));
print("fd = ", fd);
// for (var i: number = 0; i < runtime_manager.get_n_items(); i += 1) {
// var item: Ide.Runtime = runtime_manager.get_item(i)!;
// print(item.name);
// }
print("Workspace addin loaded");
}
on_runtimes_changed(self: Gio.ListModel, position: number, removed: number, added: number) {
for (var i = position; i < position + added; i+=1) {
var item: Ide.Runtime = self.get_item(i)!;
if (item.id?.startsWith("podman:")) {
print (`New runtime appears: \"${item.name}\"`);
if (item.name == "dbx-arch") {
print("Found desired runtime");
this.podman_runtime = item;
}
}
}
}
vfunc_unload(workspace: Ide.Workspace) {
print("Workspace addin unloaded");
}
vfunc_page_changed(some_page: Ide.Page) {
if (some_page.constructor.$gtype === Ide.EditorPage.$gtype) {
print("Editor page");
var editor_page: Ide.EditorPage = some_page as Ide.EditorPage;
var source_file: Gio.File = editor_page.get_file();
var extension = source_file.get_path()?.split('.').pop();
print("Current extension:", extension);
if (extension !== undefined && c_files.includes(extension)) {
this.run_button.set_visible(true);
this.source = source_file;
} else {
print("Unsupported extension");
this.run_button.set_visible(false);
}
} else {
this.run_button.set_visible(false);
}
}
});