9 Stimmen

wxPython: Wie erstellt man ein Bash-Shell-Fenster?

Ich möchte ein Popup-Fenster mit wxPython erstellen, das wie eine Bash-Shell funktioniert. Ich will nicht ein Terminal-Emulator, ich brauche nicht Job-Steuerung, ich will nur eine REPL (Read, Eval, Print Loop) basierend auf einem Bash-Prozess.

Gibt es eine einfache Möglichkeit, dies mit wxPython zu tun? Ich kenne das Grundkonzept aus meiner Zeit als tcl/tk-Programmierer, aber mein wxPython fu ist schwach und ich möchte nicht das Rad neu erfinden, wenn ich nicht muss. Ich habe ein wenig über py.shell gelesen. Shell gelesen, aber das sieht so aus, als würde es eine Python-Shell erzeugen, und ich möchte stattdessen eine, die Bash-Befehle ausführt.

2voto

Bryan Oakley Punkte 337213

Ich habe die Lösung für mein Problem gefunden. Es ist komisch, dass es vorher nie in der Google-Suche auftauchte. Es ist nicht produktionsreifen Code, aber letztlich war ich auf der Suche nach einer Möglichkeit, eine Bash-Shell in einem wxPython-Fenster ausführen.

http://sivachandran.blogspot.com/2008/04/termemulator-10-released.html im Webarchiv https://sourceforge.net/projects/termemulator/files/TermEmulator/1.0/

0voto

Anurag Uniyal Punkte 81337

Ich habe gesucht, aber es scheint keine spannende Bash-Shell für wxPython zu geben obwohl das wx.py-Modul ein Shell-Modul hat, das für den Python-Interpreter ist Das Gute ist, dass man seinen eigenen Interpreter übergeben kann, also habe ich einen sehr einfachen Bash-Interpreter entwickelt. Das Beispiel liest derzeit nur eine Zeile von Bash stdout, sonst bleibt es stecken, in echtem Code muss man die Ausgabe im Thread lesen oder select verwenden

import wx
import wx.py
from subprocess import Popen, PIPE

class MyInterpretor(object):
    def __init__(self, locals, rawin, stdin, stdout, stderr):
        self.introText = "Welcome to stackoverflow bash shell"
        self.locals = locals
        self.revision = 1.0
        self.rawin = rawin
        self.stdin = stdin
        self.stdout = stdout
        self.stderr = stderr

        #
        self.more = False

        # bash process
        self.bp = Popen('bash', shell=False, stdout=PIPE, stdin=PIPE, stderr=PIPE)

    def getAutoCompleteKeys(self):
        return [ord('\t')]

    def getAutoCompleteList(self, *args, **kwargs):
        return []

    def getCallTip(self, command):
        return ""

    def push(self, command):
        command = command.strip()
        if not command: return

        self.bp.stdin.write(command+"\n")
        self.stdout.write(self.bp.stdout.readline())

app = wx.PySimpleApp()
frame = wx.py.shell.ShellFrame(InterpClass=MyInterpretor)
frame.Show()
app.SetTopWindow(frame)
app.MainLoop()

0voto

sqram Punkte 6791

Ich werde mal sehen, was ich mir einfallen lassen kann.

Aber falls Sie Ihre Meinung ändern und stattdessen pygtk verwenden wollen, hier ist es:

genießen!!

EDITAR

Ich habe angefangen, eine schlechte Version eines Terminals mit dem Textkontroll-Widget zu erstellen. Ich habe aufgehört, weil es Fehler gibt, die nicht behoben werden können, z. B. wenn Sie den Befehl sudo verwenden.

import wx
import subprocess

class MyFrame(wx.Frame):
    def __init__(self, *args, **kwds):
        # begin wxGlade: MyFrame.__init__
        kwds["style"] = wx.DEFAULT_FRAME_STYLE
        wx.Frame.__init__(self, *args, **kwds)

        self.prompt = "user@stackOvervlow:~ "
        self.textctrl = wx.TextCtrl(self, -1, '', style=wx.TE_PROCESS_ENTER|wx.TE_MULTILINE)
        self.default_txt = self.textctrl.GetDefaultStyle()
        self.textctrl.AppendText(self.prompt)

        self.__set_properties()
        self.__do_layout()
        self.__bind_events()

    def __bind_events(self):
        self.Bind(wx.EVT_TEXT_ENTER, self.__enter)

    def __enter(self, e):
        self.value = (self.textctrl.GetValue())
        self.eval_last_line()
        e.Skip()

    def __set_properties(self):
        self.SetTitle("Poor Man's Terminal")
        self.SetSize((800, 600))
        self.textctrl.SetFocus()

    def __do_layout(self):
        sizer_1 = wx.BoxSizer(wx.VERTICAL)
        sizer_1.Add(self.textctrl, 1, wx.EXPAND, 0)
        self.SetSizer(sizer_1)
        self.Layout()

    def eval_last_line(self):
        nl = self.textctrl.GetNumberOfLines()
        ln =  self.textctrl.GetLineText(nl-1)
        ln = ln[len(self.prompt):]
        args = ln.split(" ")

        proc = subprocess.Popen(args, stdout=subprocess.PIPE)
        retvalue = proc.communicate()[0]

        c = wx.Colour(239, 177, 177)
        tc = wx.TextAttr(c)
        self.textctrl.SetDefaultStyle(tc)
        self.textctrl.AppendText(retvalue)
        self.textctrl.SetDefaultStyle(self.default_txt)
        self.textctrl.AppendText(self.prompt)
        self.textctrl.SetInsertionPoint(GetLastPosition() - 1)

if __name__ == "__main__":
    app = wx.PySimpleApp(0)
    wx.InitAllImageHandlers()
    frame_1 = MyFrame(None, -1, "")
    app.SetTopWindow(frame_1)
    frame_1.Show()
    app.MainLoop()

Wenn man es wirklich will, kann man das auch machen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X