Skip to content

Commit

Permalink
Support configuring the terminal program
Browse files Browse the repository at this point in the history
The extension preferences has a new entry for the terminal program to
use for running the commands in a terminal.

The default value is "gnome-terminal --" which is the current behaviour.

Here are terminal values that were tested and worked:
"kitty"
"flatpak run com.gexperts.Tilix -e"
"flatpak run app.studiodev.Ptyxis --"

Signed-off-by: Roy Golan <[email protected]>
  • Loading branch information
rgolangh committed Oct 14, 2024
1 parent 4e9df3d commit 49f0fe7
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 32 deletions.
2 changes: 1 addition & 1 deletion src/extension.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ export default class ContainersExtension extends Extension {

async _renderMenu() {
try {
const containers = await Podman.getContainers();
const containers = await Podman.getContainers(this._settings);
console.debug(`found ${containers.length} containers`);

this.menu.removeAll();
Expand Down
42 changes: 23 additions & 19 deletions src/modules/podman.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ let podmanVersion;

/** @returns {Container[]} list of containers as reported by podman */
// eslint-disable-next-line no-unused-vars
export async function getContainers() {
// @param {gio.settigs} settings
export async function getContainers(settings) {
if (podmanVersion === undefined) {
await discoverPodmanVersion();
}
Expand All @@ -35,14 +36,16 @@ export async function getContainers() {

const containers = [];
jsonContainers.forEach(e => {
let c = new Container(e);
let c = new Container(settings, e);
containers.push(c);
});
return containers;
}

class Container {
constructor(jsonContainer) {
// settings: the extension's Gio.settings
constructor(settings, jsonContainer) {
this.terminal = settings.get_string("terminal");
if (podmanVersion.newerOrEqualTo("2.0.3")) {
this.name = jsonContainer.Names[0];
this.id = jsonContainer.Id;
Expand Down Expand Up @@ -94,19 +97,19 @@ class Container {

logs() {
console.debug(`this state ${this.state} and is this === running ${this.state === "running"}`);
runCommandInTerminal("podman logs -f", this.name, "", this.state === "running" ? TERM_CLOSE_ON_EXIT : TERM_KEEP_ON_EXIT);
runCommandInTerminal(this.terminal, "podman logs -f", this.name, "", this.state === "running" ? TERM_CLOSE_ON_EXIT : TERM_KEEP_ON_EXIT);
}

watchTop() {
runCommandInTerminal("watch podman top", this.name, "");
runCommandInTerminal(this.terminal, "watch podman top", this.name, "");
}

shell() {
runCommandInTerminal("podman exec -it", this.name, "/bin/sh");
runCommandInTerminal(this.terminal, "podman exec -it", this.name, "/bin/sh");
}

stats() {
runCommandInTerminal("podman stats", this.name, "");
runCommandInTerminal(this.terminal, "podman stats", this.name, "");
}

async inspect() {
Expand Down Expand Up @@ -209,8 +212,8 @@ class Version {

/**
* spawnCommandline runs a shell command and returns its output
* @param {string} cmdline - the command line to spawn
* @returns {string} - the command output
* @param {string} cmdline the command line to spawn
* @returns {string} the command output
* @throws
*/
export async function spawnCommandline(cmdline) {
Expand All @@ -228,9 +231,9 @@ export async function spawnCommandline(cmdline) {

/**
* runCommand runs a podman container command using the cli
* @param {string} command the command verb
* @param {string} command the command verb
* @param {string} containerName is the contaier name
* @returns {string} command output
* @returns {string} command output
*/
async function runCommand(command, containerName) {
const cmdline = `podman ${command} ${containerName}`;
Expand All @@ -253,19 +256,20 @@ async function runCommand(command, containerName) {
* runCommandInTerminal runs a podman container command using the cli
* and in gnome-terminal(unconfigurable atm) visible to users to present output.
* Useful for logs, top, and stats container-commands.
* @param {string} command {string} the command verb
* @param {string} containerName {string} is the contaier name
* @param {...string} args to pass to the invocation
* @param {string} terminal the terminal program plus extra args if needed to execute in
* @param {string} command the podman verb
* @param {string} containerName is the container name
* @param {string[]} args extra args to pass to the podman invocation
* @param {boolean} keepOpenOnExit true means keep the terminal open when the command terminates
* and/or when the output stream is closed. False means that if the logs can't be followed the terminal
* just exits. For commands that are streaming like 'stats' this doesn't have and effect.
* and/or when the output stream is closed. False means that if the logs can't be followed the terminal
* just exits. For commands that are streaming like 'stats' this doesn't have an effect.
*/
function runCommandInTerminal(command, containerName, args, keepOpenOnExit) {
function runCommandInTerminal(terminal, command, containerName, args, keepOpenOnExit) {
let cmdline;
if (keepOpenOnExit) {
cmdline = `gnome-terminal -- bash -c '${command} ${containerName} ${args};read i'`;
cmdline = `${terminal} bash -c '${command} ${containerName} ${args};read i'`;
} else {
cmdline = `gnome-terminal -- ${command} ${containerName} ${args}`;
cmdline = `${terminal} ${command} ${containerName} ${args}`;
}
console.debug(`running command ${cmdline}`);
try {
Expand Down
31 changes: 20 additions & 11 deletions src/prefs.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,32 +3,41 @@ import Adw from 'gi://Adw';

import {ExtensionPreferences, gettext as _} from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js';


export default class ContainersPreferences extends ExtensionPreferences {
fillPreferencesWindow(window) {
// Create a preferences page, with a single group
window._settings = this.getSettings();

const page = new Adw.PreferencesPage({
title: _('General'),
icon_name: 'dialog-information-symbolic',
});
window.add(page);

const group = new Adw.PreferencesGroup({
const appearanceGroup = new Adw.PreferencesGroup({
title: _('Appearance'),
description: _('Configure the appearance of the extension'),
});
page.add(group);
page.add(appearanceGroup);

// Create a new preferences row
const row = new Adw.SwitchRow({
const extraInfoRow = new Adw.SwitchRow({
title: _('Extra Info'),
subtitle: _('Whether to show extra info of a container in name and the opened menu'),
});
group.add(row);
appearanceGroup.add(extraInfoRow);
window._settings.bind('extra-info', extraInfoRow, 'active', Gio.SettingsBindFlags.DEFAULT);

// Create a settings object and bind the row to the `extra-info` key
window._settings = this.getSettings();
window._settings.bind('extra-info', row, 'active',
Gio.SettingsBindFlags.DEFAULT);
const behaviourGroup = new Adw.PreferencesGroup({
title: _('Behaviour'),
description: _('Configure the behaviour of the extension'),
});
page.add(behaviourGroup);

const terminalRow = new Adw.EntryRow({
title: _('Terminal program with arguments'),
show_apply_button: true, // Allows user to apply the input
});
behaviourGroup.add(terminalRow);
window._settings.bind('terminal', terminalRow, 'text', Gio.SettingsBindFlags.DEFAULT);
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,9 @@
<key name="extra-info" type="b">
<default>true</default>
</key>
</schema>
<key name="terminal" type="s">
<default>"gnome-terminal --"</default>
<description>The terminal program and arguments to use for running commands such as shell, logs, stats, and watch</description>
</key>
</schema>
</schemalist>

0 comments on commit 49f0fe7

Please sign in to comment.