How to send commands to pygobject virtual terminal?
Asked Answered
T

1

0

Right now I can make a terminal but the output is not used as a command. It just prints a string to the virtual terminal.

from gi.repository import Gtk, GObject, Vte

class TheWindow(Gtk.Window):

    def __init__(self):
        Gtk.Window.__init__(self, title="inherited cell renderer")
        self.set_default_size(400, 200)

        box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
        v = Vte.Terminal()
        #v.connect ("child-exited", lambda term: gtk.main_quit())
        length = len("echo \"string\"\n")
        v.feed("echo \"string\"\n", length)
        box.pack_start(v, True, True, 0)

        self.add(box)

I tried to use the docs here http://developer.gnome.org/vte/0.30/ , but I had some trouble figuring all that out. I couldn't find any documentation on vte for python gtk3 at all.

Mainly I'm just trying to figure out how to get the command prompt in the virtual terminal so it will accept commands from inside the python gtk3 interface.

Tribadism answered 3/8, 2012 at 23:13 Comment(1)
Here is some more info about it askubuntu.com/questions/154354/… After following those instructions I was able to write commands in the terminal directly. Now I need to figure out how to do it from gtk.Tribadism
T
4

Here's the answer. :) The important parts are fork_command_full and feed_child.

from gi.repository import Gtk, GObject, Vte
#GObject is not required. I just import it everywhere just in case.
#Gtk, Vte, and GLib are required.
from gi.repository import GLib
import os
#os.environ['HOME'] helps to keep from hard coding the home string.
#os is not required unless you want that functionality.

class TheWindow(Gtk.Window):

    def __init__(self):
        Gtk.Window.__init__(self, title="inherited cell renderer")
        self.set_default_size(600, 300)
        self.terminal     = Vte.Terminal()
        self.terminal.fork_command_full(
                Vte.PtyFlags.DEFAULT, #default is fine
                os.environ['HOME'], #where to start the command?
                ["/bin/sh"], #where is the emulator?
                [], #it's ok to leave this list empty
                GLib.SpawnFlags.DO_NOT_REAP_CHILD,
                None, #at least None is required
                None,
                )
        #Set up a button to click and run a demo command
        self.button = Gtk.Button("Do The Command")
        #To get the command to automatically run
        #a newline(\n) character is used at the end of the
        #command string.
        self.command = "echo \"Sending this command to a virtual terminal.\"\n"
        command = Gtk.Label("The command: "+self.command)
        self.button.connect("clicked", self.InputToTerm)
        #end demo command code

        #set up the interface
        box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
        box.pack_start(self.button, False, True, 0)
        box.pack_start(command, False, True, 1)
        #a scroll window is required for the terminal
        scroller = Gtk.ScrolledWindow()
        scroller.set_hexpand(True)
        scroller.set_vexpand(True)
        scroller.add(self.terminal)
        box.pack_start(scroller, False, True, 2)
        self.add(box)

    def InputToTerm(self, clicker):
        #get the command when the button is clicked
        length = len(self.command)
        #A length is not required but is the easiest mechanism.
        #Otherwise the command must be null terminated.
        #Feed the command to the terminal.
        self.terminal.feed_child(self.command, length)


win = TheWindow()
win.connect("delete-event", Gtk.main_quit)
win.show_all()
Gtk.main()
Tribadism answered 4/8, 2012 at 16:36 Comment(9)
The script works great but do you know if is there any way to avoid printing the commands? ex: echo "Sending this command to a virtual terminal." ?Abney
I'm not sure what you mean. If you want to run commands that aren't printed you don't need a virtual terminal. Popen will do that.Tribadism
( i was asking about how to only print the output of commands in a vte, it is usefull for printing in real time)but i just find it how to do it. in the VTE terminal write tty in other to get /dev/pts/# and then the bash commands from other process can be redirected there by doing echo 'foo' > /dev/pts/#Abney
Ask this as a question. Link to it here in a comment. I will answer it.Tribadism
Ok. Do you not want the python code to do it for you?Tribadism
Is there any better solution than the one of using echo 'foo' > /dev/pts/# ? if not i think that is not worth to ask!Abney
If you are satisfied with that then go with it.Tribadism
the command will not be printed if contains non ascii chars. So, in one line: self.terminal.feed_child(self.command, len(self.command.decode()))Claypoole
The function "fork_command_full" has been renamed to "spawn_sync" and is deprecated.Ormsby

© 2022 - 2024 — McMap. All rights reserved.