Beta expired
Let us pray
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.
Ole is back on Twitter and there is a new version of Editorial
And the new version of Pythonista will come soon.
@engdan77 You're right.
And I am so happy to see a post that is not an advertising for some useless product 😀
@ihf said
This a (low priority) idea for the wish list: I sometimes want to read my outlines on the Mac. What I do now is save them in pdf or some other format that the Mac understands. This works fine but I have to remember to do it after any change so that the outline will be up-to-date. A reader script in python would permit me to view an outline on the Mac or on anything that runs python and has access to the iCloud files.
Written in my todo list, but when you say "view an outline", that will say use an UI...or print it in the console of this Python interpreter.
I have never used Python on a Mac, which free app do I need?
Little (not quick but still dirty) script to be executed once by Pythonista restart (fi in your pythonista_startup.py).
When you tap help in the popup menu of a selected text
After some seconds (function of your iDevice, the number and size of your scripts), you get a list of scripts containing the selected text (case insensitive)
If you select a script, you'll get, like for Pythonista help, a small (webview) window displaying the script as an html with Python syntax highlighting, where occurrences of selected text are also highlighted (in yellow)
If you search has also results in Pythonista help, you'll see both results in the list
The script imports @jonB's swizzle module
You can find this script here
@omz Welcome back and thanks for the future version. I'm sincerely more than happy that you feel better.
@Matteo Please could you try this code as a Pythonista tool.
First, you run the tool,
then you run a script with a console output,
then, in console mode, you type the text fo search and tap the 🔍 icon, and you will watch the miracle 😀
Sure that the code is not bug free, but it is good to start, if interested
The OMTextView does not allow to set text attributes as an UITextView but you can draw on it
from objc_util import *
import clipboard
import ui
@on_main_thread
def test(sender):
import console
import re
import ui
txt = str(sender.console.text())
if txt[-1] == '\n':
txt = txt[:-1]
win = ObjCClass('UIApplication').sharedApplication().keyWindow()
main_view = win.rootViewController().view()
ret = ''
def analyze(v):
for tv in v.subviews():
if 'OMTextView' in str(tv._get_objc_classname()):
su = tv.superview()
if 'OMTextEditorView' in str(su._get_objc_classname()):
continue
for sv in tv.subviews():
if 'SUIButton_PY3' in str(sv._get_objc_classname()):
sv.removeFromSuperview()
if txt == '':
return
t = str(tv.text())
#print('search',txt,'in',t)
for m in re.finditer(txt, t):
st,end=m.span()
p1 = tv.positionFromPosition_offset_(tv.beginningOfDocument(), st)
p2 = tv.positionFromPosition_offset_(tv.beginningOfDocument(), st+len(txt))
rge = tv.textRangeFromPosition_toPosition_(p1,p2)
rect = tv.firstRectForRange_(rge) # CGRect
x,y = rect.origin.x,rect.origin.y
w,h = rect.size.width,rect.size.height
#print(x,y,w,h)
l = ui.Button()
l.frame = (x,y,w,h)
l.background_color = (1,0,0,0.2)
l.corner_radius = 4
l.border_width = 1
tv.addSubview_(l)
ret = analyze(tv)
if ret:
return ret
ret = analyze(main_view)
@on_main_thread
def FindTextInConsole():
global console_tv
win = ObjCClass('UIApplication').sharedApplication().keyWindow()
main_view = win.rootViewController().view()
ret = ''
next_is_console = False
def analyze(v,indent):
global next_is_console
ret = None
for sv in v.subviews():
#print(indent,sv._get_objc_classname())
if 'UILabel' in str(sv._get_objc_classname()):
#print(indent,sv.text())
if str(sv.text()) == '>':
next_is_console = sv
else:
next_is_console = False
elif 'OMTextView' in str(sv._get_objc_classname()):
if next_is_console:
su = next_is_console.superview()
for ssv in su.subviews():
if 'SUIButton_PY3'in str(ssv._get_objc_classname()):
# rerun of this script, remove previous button
ssv.removeFromSuperview()
b = ui.Button(name='clipboard')
b.tint_color ='red'
b.image = ui.Image.named('iob:ios7_search_32')
b.background_color = 'white'
h = su.frame().size.height
b.frame = (2,2,h-4,h-4)
b.action = test
b.console = sv
#print(dir(sv))
retain_global(b)
su.addSubview(ObjCInstance(b))
ret = analyze(sv,indent+' ')
if ret:
return ret
ret = analyze(main_view,'')
return ret
if __name__ == '__main__':
r = FindTextInConsole()
You can also put a line with 3 quotes above and under these lines
'''
these
lines
are
commented
'''
@TableForGlasses In the console. Swipe from right to left to get it.
@osamu Ok, good for you if you only want device type, and no more its user name.
@ccc yes, I've tried with some different pdf but extractText
method returns an empty string, known problem with this module. And without the text, not easy to search word occurrences for splitting.
@TravelCoder not easy to (try to) help without the code it-self
@streetcodernate Perhaps, you could try the workaround described at the bottom of this post in this GitHub Stash issues
@LankyDonkey said
Do we know if Ole is still actively involved in the product?
normally I would say no but the latest update 3.4 arrived so long after the previous one that it is difficult to deduce anything from this delay
As for my health, I have nothing to complain about. Thanks for asking.
@streetcodernate This is a quick and dirty little script to be configured and executed as a Pythonista tool as a workaround when you want to copy paste a control in a custom view.
First you have to select the custom view, then tap "subviews" of the custom view, then select the control you want to copy.
Then, instead of tapping copy and paste in the pop up menu, you run the script as a tool. The copy will be performed automatically in the custom view, not in the main view.
The y of the new control will be a little bit higher and its name will be the name of the original control followed by the word "copy"
import console
import editor
from objc_util import *
import ui
@on_main_thread
def closeTab(fn):
win = UIApplication.sharedApplication().keyWindow()
root_vc = win.rootViewController()
tabs_vc = root_vc.detailViewController()
for tab in tabs_vc.tabViewControllers():
tab_file = str(tab.filePath())
if tab_file == fn:
tabs_vc.closeTab_(tab)
return True
return False
def main():
console.clear()
fn = editor.get_path()
with open(fn, mode='rt') as inp:
v_str = inp.read()
#print(v_str)
# search two selected controls
t_select = '"selected" : '
is1 = v_str.find(t_select + "true")
if is1 < 0:
console.alert('no selected control','','ok',hide_cancel_button=True)
return
is2 = v_str.find('"selected" : true',is1+1)
if is2 < 0:
console.alert('not two selected controls','','ok',hide_cancel_button=True)
return
# search names of both selected controls
def searchNameAndClass(isn):
t = '"name" : '
i = v_str[:isn].rfind(t)
j = v_str.find('",',i)
nm = v_str[i+len(t)+1:j]
t = '"class" : '
i = v_str[:isn].rfind(t)
j = v_str.find('",',i)
cl = v_str[i+len(t)+1:j]
return nm,cl
n1,c1 = searchNameAndClass(is1)
#print(n1,c1)
n2,c2 = searchNameAndClass(is2)
#print(n2,c2)
if c2 != 'View':
console.alert('the 2nd selected control is not a subView','','ok',hide_cancel_button=True)
return
# duplicate copied control (and change its name)
v_str = v_str[:is1] + t_select + "false" + v_str[is1+len(t_select+"true"):]
i = v_str[:is1].rfind('"nodes" : [')
js = v_str[:i].rfind('{')
js = v_str[:js].rfind('\n') + 1
je = v_str.find('}',is1)+1
#print(v_str[js:je])
t_copy = v_str[js:je].replace('"name" : "'+n1+'"','"name" : "'+n1+'copy"')
# "frame" : "{{64, 131}, {80, 32}}",
fr = t_copy.find('"frame" : "{{')
i = t_copy.find(', ',fr)
j = t_copy.find('}',i)
t_copy = t_copy[:i+1] + str(int(t_copy[i+1:j])+20) + t_copy[j:]
#print(t_copy)
v_str = v_str[:je] + ',\n' + t_copy + v_str[je:]
#print(v_str)
closeTab(fn)
with open(fn, mode='wt') as out:
out.write(v_str)
editor.open_file(fn)
if __name__ == '__main__':
main()
@rb the only problems I met came from Pythonista upgrade, not iPadOS
@streetcodernate It shouldn't be too difficult to write a Pythonista script to use as a tool after doing the paste, to move the control into the same view as the original copied control