How can I get console width?
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.
@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
drawn. 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:
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.
@JonB, The current font block of code prints
Nonefor me. The default font one is working and printing
'Menlo-Regular', 12.Which is strange because I not changed my font at all, and it's not 12 but 14.
I totally don't understand this, but apparently one needs to trigger an attribute error against the view in order for outputFont to show up... apparently I had done this accidentally while poking around. Indeed the above code didnt work when i restarted, then suddenly worked up again after poking around a bit more. The code below seems to work in a fresh restart. After triggering the error once, all that is needed is to call ouputFont() subsequently.
from objc_util import * app=ObjCClass('UIApplication').sharedApplication() d=app.delegate() cvc=d.consoleViewController() try: cvc.view().thisattributedoesnotexist() except AttributeError: pass font=cvc.outputFont() print font
@Balur , thanks. I will also use your function. I often want to write a full screen divider when debugging. I get lazy though 😱 I set my font in the startup script to Menlo , 22. I have problems seeing smaller. But I tested your function on my ipad pro, and the 1.5 char adjustment works in both orientations.
@JonB Strange, but it's do the job. One little problem for me is how to access the values one by one, not this UICTFont object thing?
getConsoleWidth()is still not perfect when I run on ipad when pythonista editor and console are side by side. Because of
ui.get_screen_size().widthreturns the full screen size, not just the console size. I have to subtrack the editor panel width from the full screen size. Or something like that. Any suggestion?
@JonB I suspect that this has nothing to do with the
AttributeError, but with the fact that you're accessing the
viewproperty while doing the attribute lookup. This has the side effect of loading the view (and typically other setup code) if it isn't loaded already. To be honest, I can't really think of a situation where the console view wouldn't be loaded already, but I can't think of another explanation for this behavior.
@omz indeed, this works for me:
from objc_util import * app=ObjCClass('UIApplication').sharedApplication() d=app.delegate() cvc=d.consoleViewController() cvc.view() font=cvc.outputFont() print font
font.advancementForGlyph_(68).width gives you the actual width of a character.
font.lineHeight() gives the height of a line
font.pointSize() gives the point size, which you dont need except for setting default.
gives the font name. Menlo-Regular or Menlo respectively
The width of the half console can be found somewhere... will need to poke around later
@JonB Thank you, I extended the functions based on your answer. If you find something about 1/3 screen console, please let me know.
# coding: utf-8 import ui import objc_util def getDefaultConsoleFont(): defaults=objc_util.ObjCClass('NSUserDefaults').standardUserDefaults() return (str(defaults.stringForKey_('OutputFontName')),\ defaults.integerForKey_('OutputFontSize')) def getCurrentConsoleFont(): app=objc_util.ObjCClass('UIApplication').sharedApplication() cv=app.delegate().consoleViewController() cv.view() font=cv.outputFont() font_family=str(font.familyNameForCSSFontFamilyValue()) #font_family2=str(font.familyName()) font_size=font.pointSize() char_width=font.advancementForGlyph_(68).width line_height=font.lineHeight() return (font_family, font_size), char_width, line_height def getConsoleCharWidth(): font,charWidth,lineHeight=getCurrentConsoleFont() screenWidth=ui.get_screen_size().width #charWidth=ui.measure_string('.',font=font).width return int(screenWidth / charWidth-1.5) if __name__ == '__main__': ccwidth=getConsoleCharWidth() currentFont,_,_=getCurrentConsoleFont() defaultFont=getDefaultConsoleFont() print('currentConsoleFont='+str(currentFont)) print('defaultConsoleFont='+str(defaultFont)) print('consoleCharWidth = '+str(ccwidth)) print('='*ccwidth)
Sorry for copy paste, it's a bit long.
The objc_util syntax makes it difficult to keep to PEP8 line lengths so just go straight at
It is still shorter than the line above it.