Welcome!
This is the community forum for my apps Pythonista and Editorial.
For individual support questions, you can also send an email. If you have a very short question or just want to say hello — I'm @olemoritz on Twitter.
Find console view and retrieve text in Pythonista3.4
-
I had code from python2/pythonista3.3 which was able to find the console view in the view hierarchy, and then pull the text out of it:
def findConsoleView(): app = objc_util.UIApplication.sharedApplication() if not app: return "" mainwindow = app.keyWindow() if not mainwindow: return "" mainview = mainwindow.rootViewController().view() if not mainview: return "" visit = list(mainview.subviews()) while visit: v = visit.pop() if bytes(v._get_objc_classname()) == b"OMTextView": if v.superview() and \ bytes(v.superview()._get_objc_classname()) != \ b"OMTextEditorView": return str(v.text()) visit += list(v.subviews()) return ""
Sadly, this no longer works, as I think the console view no longer fits the criteria I was using to find it.
Anyone have a working version of this idea?
I'm going to plug away at searching the view hierarchy and see if I can find where the console is hiding now.( @omz for possible future updates: it would be nice if there was a
console.text()
function in theconsole
module) -
Hrm...upon further investigation, I take it back: the above code appears to work in Pythonista3.4.
I still don't love it. It feels very fragile just "guessing" which OMTextView happens to be right like this. I really wish there was a better way...but I don't see a good way to more directly determine which view is the console view.
Anyway, the right solution is for there to be a
console.text()
function. So I will repeat my plea to @omz to please consider adding that to the features in theconsole
module. -
@shinyformica said
...... fragile .....
You could add this security check that in the subviews of the superview of the OMTextView, you find a label with
>
which is just before the console input linefrom objc_util import * def findConsoleView(): app = UIApplication.sharedApplication() if not app: return "" mainwindow = app.keyWindow() if not mainwindow: return "" mainview = mainwindow.rootViewController().view() if not mainview: return "" visit = list(mainview.subviews()) while visit: v = visit.pop() if bytes(v._get_objc_classname()) == b"OMTextView": if v.superview() and \ bytes(v.superview()._get_objc_classname()) != \ b"OMTextEditorView": # check this the right view su = v.superview() ok = False for ssu in su.subviews(): for ssu in ssu.subviews(): if 'UILabel' in str(ssu._get_objc_classname()): if str(ssu.text()) == '>': print('>'*50) ok = True break if ok: break if ok: return str(v.text()) visit += list(v.subviews()) return "" print('test') print(findConsoleView())
Anyway, as you said, your code works even in Pythonista 3.4 and we don't receive a lot of updates per year (sorry @omz 😉) thus not a big risk, even if you have to test it each time.
Edit: and you could always create a findConsoleView.py and use it so
import console from findConsoleView import * console.text = findConsoleView print('hello') t = console.text() print(t)
-
@cvp searching for the prompt label is a good extra check, I like it...well, I like it a little bit more.
Monkey-patching the console module isn't really necessary...being able to call
console.text
isn't the part that bothered me, it's just my hope for what @omz might eventually add to theconsole
api.Anyway, thanks @cvp, as always!