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.
How can I get console width?
-
Hi Guys,
I'm new here and new to Python language also.
Is there any working way to get console width in Pythonista? I mean in character count in one row, like 40 or 36. -
You could use scene or ui to get the screen width. then, to get the font size, you could use
objc_util
to find the textview that represents the console window and then check the font size. Then do division. -
Okay, I got the screen size:
import ui width, height = ui.get_screen_size()
But how can I get the main console object?
-
@Balur , as the console can be any font and size, I think you need to use ui.measure_string. If, you for example use console.set_font(mono spaced font) then use ui.measure_string on a character, with the screen width you could calc the number of chars
-
@Balur , I just can't get the right algorithm. My math is crap. Either you can get it or another can chime in.
# coding: utf-8 import console, ui, math fnt_name = 'Source Sans Pro' fnt_size = 12 fnt = (fnt_name, fnt_size) w = ui.get_screen_size()[0] char_width = ui.measure_string('M', font = fnt)[0] print char_width num_chars = math.floor((w / char_width)) print num_chars console.set_font(fnt_name, fnt_size) print 'M' * int(num_chars)
-
Use objc_util. @JonB created a script that will locate the console object.
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]
The found object is
<OMTextView: <OMTextView: 0x16942e00; baseClass = UIScrollView; frame = (0 0; 320 460); text = 'findme >>> console_view '; clipsToBounds = YES; autoresize = W+H; gestureRecognizers = <NSArray: 0x16683d30>; layer = <CALayer: 0x166838a0>; contentOffset: {0, 0}; contentSize: {304, 71}>>
I think you should be able to find font size from this?
-
@Webmaster4o , I think he is asking for something else. Maybe I am wrong, but what I read he just wants something like console.char_width, but of course unless you have a mono spaced font, it's not possible.
The code I put above is very close, but there are some rounding issues with it. I mean to get the screen width in chars given a mono space font -
I think this is why @omz went with the
measure_string()
approach because if you are not using a monospaced font then the number of characters that fits on a line will vary if the string is 'iii' vs. 'www'. -
@ccc , sure with any proportional font you have to use a measure string func to calculate the width. You can not even get close without it. Then you have kerning , kerning pairs Etc. kerning, the space between characters, but it gets more complicated by certain character pairs(AE , MY) have a different kerning, but font dependent. Then there is leading on the height. I did a lot with typography in the old days.
-
@Phuket2 No, my approach is to do this without changing the font size. I'm trying to discover the font size that is currently active in the console, in order to not have to set it first. I'm trying to create a method that can discover the current console width in characters, without changing the font size.
-
@Webmaster4o , I think he wants how many chars per line. So you need to calculate one char, but only works for mono space (fixed width) font. I think he is talking terminal speak, like when you knew consoles/terminals would be something like 80x25 or diff depending on resolution. He also says he is new to Python. Anyway, time for him to chime in and say what he really wants. Still good conversation anyway 💋👍
-
@Webmaster4o , ok you did an edit before I seen it. I just don't think it's practical. If the font is not a fixed width, you have now way to know how many chars will be on any given line.
-
Why would the console not be a fixed width font? I mean, it is possible of course, but generally console/terminals are fixed width, otherwise it makes things really hard do do anything. We are not talking a generalized textview.
I have not been able to figure out where the text styling info is stored in the OMTextView, I think it is
draw
n. It is possible to get the font() size of the console input, which is of type PA2PromptTextField. -
@JonB , I am not sure why it would not be a fixed width. But as you mention it's possible to set it to anything. Why can you print bitmap graphics to the console? That was not possible before, but now it is.
-
Yes, I am also trying to calculate the console width. You are calculating this based on a static font size. It would be more useful and versatile to calculate this based on the current font size, without having to set it first. That is why I am trying to discover what the font size is set at.
-
Webmaster, I believe the console text input has the same font size as the default console size (ie in settings) though set_font can change what is printed on screen. In that sense, there is no single console width, only the width of a given character(setwidth can change over the line i think). So it would allow you to get the default font, then you would have to manage manual set_font calls. There ts a textStylingAtPosition_InDirection which seems promising, but I have not figured out how not to crash calling it. Also, the textStorage() method of the OMTextView seems promising, but it is not obvious how to get attributes, inly set them.
-
@Phuket2, You are right. Actually, I just want how many chars per line. Maybe a silly approach, but I want my scripts' welcome text underlined with a full line of chars.
consoleWidth = getConsoleWidth() # <= 50 print('DownloadFromWeb') print('Give me an URL, and I will download it for you.') print('='*consoleWidth)
It looks like this in console:
DownloadFromWeb
Give me an URL, and I will download it for you.@Phuket2, I don't want to change console font. Default is good for now. What is the default console font?
measure_string()
seems a good approach. -
@JonB Yes, I noticed
textStylingAtPosition_InDirection
, but also could not get it to work. It appears that OMTextView is a class unique to pythonista that @omz created, I can't find any online resource about it. It seems like a combination of a TextField and a ScrollView. However, it does not have the font() method that a TextField does. Maybe @omz could provide some explanation, another thing that could be tried is comparing all attributes of all views within the console before and after changing the font size. -
I think I got the missing piece. After a little testing it seems the default console font is Menlo, 14.
import ui def getConsoleWidth(font=('Menlo',14)): screenWidth = ui.get_screen_size().width charWidth = ui.measure_string('.',font=font).width return int(screenWidth / charWidth-1.5)
I'm not sure why subtract by 1.5 exactly, but I think console margin have something to do with it. Tested on my iphone and ipad mini, both orientations.
-
To check current font:
app=ObjCClass('UIApplication').sharedApplication() d=app.delegate() cv=d.consoleViewController() font=d.consoleViewController().outputFont() print font
Someone else asked about getting the default font, for resetting.
This can be found in defaults.defaults = ObjCClass('NSUserDefaults').standardUserDefaults() print str(defaults.stringForKey_('OutputFontName')) print defaults.integerForKey_('OutputFontSize')
See defaults.dictionaryRepresentation() for other defaults.