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.
[Beta] Tinkering with Pythonista's internals using objc_util
-
This is super! Thanks Ole! Can't wait for the final product.
-
Hi,
How can i access the Pythonista console view using objc_util?Thanks in advance
Filippo -
here is the method i used to explore the wonderful world of pythonista's view heirarchy. we will search for an objective c object that contains some known text or classname. the custom classes tend to start with OM...
from objc_util import * w=ObjCClass('UIApplication').sharedApplication().keyWindow() main_view=w.rootViewController().view() def filter_subviews(view,text=None, objcclasstext=None): matching_svs=[] sv=view.subviews() if sv is None: return matching_svs for v in sv: if objcclasstext and objcclasstext in v._get_objc_classname(): matching_svs.append(v) if text and hasattr(v,'text'): if str(v.text()) and text in str(v.text()): matching_svs.append(v) matching_svs.extend( filter_subviews(v, text=text, objcclasstext=objcclasstext)) return matching_svs # don't find editor window, so concatenate string print 'find'+'me' # in this case, only one entry will be returned. otherwise, may need to look at list to figure out which view is the one you are seeking. console_view=filter_subviews(main_view,'find'+'me')[0]
once you find the thing you are looking for, you can traverse up and down the view heirarchy by using
superview
andsubviews
. for instance, maybe you dont want the actual console textview, but you want the text inputconsole_view.superview().subviews()
gives a clue, although in some cases you may have to traverse up or down a few levels to find what you are looking for. once you find the classname, note it for future use, as you can search dirsctly for the classname instead.
i also found it useful to walk portions of the subviews, printing out a "tree", where classname, and frame are printed. i eventually thought that a TreeView type object brower might be useful, to browse the tree
-
Thanks
-
@JonB Quick tip:
UIView
has a built-inrecursiveDescription
method that produces a tree-like representation of all subviews. -
Oh, that's the most useful thing i've ever seen :O
-
Understanding this is for experimentation only, how would one go about modifying
OMPythonSyntaxHighlighter
or making a custom syntax highlighter class? -
@nfmusician I don't know anything about NSRegularExpression, but, only for testing, a little modif in @omz code → Code Editor Demo.py (Gist)
allows to change rule for Python comment, from #xxxx into &xxxx
editor_view = OMTextEditorView.alloc().initWithFrame_syntaxHighlighterClass_theme_(f, SyntaxHighlighter, theme) # ============= begin # https://forum.omz-software.com/topic/2014/beta-tinkering-with-pythonista-s-internals-using-objc_util/12 rules = editor_view.syntaxHighlighter().syntaxHighlightingRules() for rule in rules: print(rule.scopeName()) if rule.regex(): print(' NSRegularExpression pattern=',rule.regex().pattern()) if str(rule.scopeName()) == 'comment': #print(dir(rule)) comment_pattern = rule.regex().pattern() comment_pattern = ns(str(comment_pattern).replace('#','&')) comment_options = rule.regex().options() regex_new = ObjCClass('NSRegularExpression').alloc().initWithPattern_options_error_(comment_pattern, comment_options, None) rule.setRegex_(regex_new) print(' NSRegularExpression pattern=',rule.regex().pattern()) print(dir(rule)) # ============= end
-
@nfmusician still only for testing: how to modify color of a rule, here the comment
PA2UITheme = ObjCClass('PA2UITheme') theme_dict = PA2UITheme.sharedTheme().themeDict().mutableCopy() theme_dict.autorelease() theme_dict['font-family'] = 'Menlo-Regular' theme_dict['font-size'] = 14 # ============= begin #print(theme_dict) new_theme_dict = {} for x in theme_dict.allKeys(): #print(x._get_objc_classname(),x) if str(x) == 'scopes': new_dict_scopes = {} for y in theme_dict[x].allKeys(): #print(' ',y._get_objc_classname(),y) if str(y) == 'comment': new_dict_comment = {} for z in theme_dict[x][y].allKeys(): #print(' ','-',z._get_objc_classname(),z) if str(z) == 'color': new_dict_comment[z] = "#DC7633" # new color else: new_dict_comment[z] = theme_dict[x][y][z] new_dict_scopes[y] = new_dict_comment else: new_dict_scopes[y] = theme_dict[x][y] new_theme_dict[x] = new_dict_scopes else: new_theme_dict[x] = theme_dict[x] theme_dict = new_theme_dict #print(theme_dict) # ============= end theme = OMSyntaxHighlighterTheme.alloc().initWithDictionary_(theme_dict) theme.autorelease()
-
Is there a way to mark Python syntax errors like
print “Hello World”
in blinkingred
? -
@ccc It is only an editor, thus it does not check anything about Python rules. At least' that's what I think. For instance, it recognizes Python reserved words but that's all
-
@ccc Is that not what Analyze (pyflakes) tool does?
-
It is a difference between active and passive. The Pythonista editor is passive because I have to manually run pyflakes while VSCode is active because it updates the syntax highlighting as I type by running flake8. Given the speed of current iOS CPUs, active syntax highlighting might have acceptable performance.
-
@ccc Ok, I understand but I wanted to say in my answer is that current Pythonista Editor does not allow to intercept at typing, it only checks content with some easy rules.
-
@ccc Upon reflection, I think that it should be possible, via the delegate of the editor's TextView, to intercept the modifications of the source and to execute a code, like flak8, to check the syntax of the script. But it seems to be quite complex
-
It would not need be letter-by-letter, but it would be cool if fixers like "isort ; black ; pyupgrade ----py37-plus" were autorun on the code in the editor. The trick would be for the fixers to fail gracefully if the user is in mid-thought.
-