Reputation: 217
I am making an application in PySide and I want to add a Console/Terminal like screen, where you have a prompt and you can type commands. How would I be able to accomplish this. I am guessing some combination of QPlainTextEdit/QTextEdit for the output and QLineEdit for the actual prompt. Is there a better way to do this?
Upvotes: 4
Views: 5063
Reputation: 6320
I did this with a custom QPlainTextEdit and custom QLineEdit. I also had an indicator label that would display ">>>" on the terminal to show user input. It needs more work. The best way would be to create your own custom widget based off of a QTextEdit and your own io handler. Below is an example of my execute method with self.input being the QLineEdit and self.view being the QTextEdit. It should get you the general idea.
import io, subprocess, shlex, code, rlcompleter, platform
def execute(self, currentText=None):
"""Execute runs the command given based on the console type.
If the console type is "both" then execute will run python commands
unless the user give the input ::os::command or ("::(platform.syste())::command").
Otherwise the console type will determine the what the input will execute with.
Args:
currentText(str): Text to execute. None will run the text from the QLineEdit self.input.
"""
# Check for given text
if currentText is None:
currentText = self.input.text()
self.input.clear()
self.view.display(currentText, "input")
else:
cmd = re.search("^>>>", currentText) # search for start only
if cmd is None:
currentText = ">>>" + currentText
else:
self.view.display(currentText, "input")
# end
# Variables
self.completer.clear()
cmdString = re.sub("^>>>", "", currentText)
result = None
displayType = "output"
run, cmdString = self.getRunType(cmdString)
try:
# Check where the output is going
sys.stdout = self.out = io.StringIO()
sys.stderr = sys.stdout
if run == "python": # Run python command
result = self._runInterpreter(cmdString)
displayType = "python"
elif run == "os": # Run os command
result = self._runSubprocess(cmdString)
displayType = "os"
except Exception as err:
result = str(err)
displayType = "Error"
notFoundPython = "NameError:" in result and "is not defined" in result
notFoundWindows = "returned non-zero exit status" in result
if notFoundPython or notFoundWindows:
result = "Command not found"
finally:
sys.stdout = self.old_stdout
sys.stderr = self.old_stdout
self.display(result, displayType)
# end execute
def getRunType(self, cmdString):
run = self._consoleType
# Check the run type
if self._consoleType == "both":
if re.search("^::python::", cmdString) is not None:
cmdString = re.sub("^::[a-z]*::", "", cmdString)
run = "python"
elif re.search("^(::os::|::"+platform.system()+"::)", cmdString) is not None:
cmdString = re.sub("^::[a-z]*::", "", cmdString)
run = "os"
else:
run = "python"
# end
return run, cmdString
# end getRunType
def _runInterpreter(self, cmdString, outIO=None, run=None):
# Check for a proper console type
if(self._consoleType != "both" and self._consoleType != "python"):
return
# Get the IO
if outIO is None:
outIO = sys.stdout
# Run python command
self.interpreter.push(cmdString)
# Check outIO
result = "Unreadable buffer: Check python's sys.stdout"
if isinstance(outIO, io.StringIO):
result = outIO.getvalue()
else:
if outIO.readable():
result = str(outIO.readlines())
# Check for error
if re.search("^Traceback", result) or re.search("[a-zA-z]*Error:", result):
raise ValueError(result)
return result
# end _runInterpreter
def _runSubprocess(self, cmdString, run=None):
# Check for a proper console type
if(self._consoleType != "both" and self._consoleType != "os"):
return
# Run OS command
cmd = shlex.split(cmdString)
result = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT).decode("utf-8")
# Check for error
if re.search("^Traceback", result) or re.search("[a-zA-z]*Error:", result):
raise ValueError(result)
return result
# end _runSubprocess
Upvotes: 2
Reputation: 2635
You could check out Spyder. They use PyQt (which is similar) and have a terminal. I think you can import their terminal widget, but I haven't played with it.
https://code.google.com/p/spyderlib/
Also, it is my favorite python editor by far!
I've spent a fair deal of time trying to find something like this, but to no avail. Good luck!
Upvotes: 2