Formatting Strings in Python - python

I'm printing a title in python and I want it on the center of the screen.
I know I can do it by using
"{:^50}".format("Title")
But the thing with this command is it only utilizes the width I give in (in this case, 50). But it isn't perfect and is sometimes way off. Even if I approximate the width by observing/guessing, it would go out of format if I re-size the terminal. I always want to align it on the middle of the screen, even when the terminal is re-sized(say, in fullscreen mode). Any ways I can achieve this?
EDIT:
I have did this:
Well, I figured out the way to find the window size,
import os
columns = os.popen('stty size', 'r').read().split()[0]
"{:^"+columns+"}".format("Title")
but the last line shows error. I finally have the window size, but I cannot format it correctly. Any help is appreciated!

As zondo pointed out, the title won't reposition when the window is resized.
The correct way to do this: "{:^"+columns+"}".format("Title") is like so:
"{:^{}}".format("Title", width)
#^---------------^ first argument goes with first brace
# ^--------------------^ second argument goes with second brace and sets the width

Related

Label text position in Bokeh

I would like to stick MyText Label to the bottom right part of my figure
for a given text and a given font size (as shown on the picture for 'this is super fun', font size of '20px' and with tiny characters. I found the good position by dichotomy ).
What is the function position I need to pass to x ?
This should depends on len(MyText), text_font_size and figure width ...
from bokeh.models import ColumnDataSource, Label, LabelSet, Range1d
from bokeh.plotting import figure, output_file, show
width,height=400,300
p = figure(plot_width=width, plot_height=height)
MyText='this is super fun'
my_font_size = "20px"
labels = Label(x=width/2+25, y=0,x_units='screen', y_units='screen', text=MyText,text_font_size=my_font_size)
p.add_layout(labels)
show(p)
I don't think there is any 100% robust way to do this, actually.
You can set the text_align to "right" which helps:
p = figure(plot_width=width, plot_height=height)
labels = Label(x=width-50, y=0,
x_units="screen", y_units='screen', text_align="right",
text=MyText,text_font_size=my_font_size)
Note the -50 above is to account (roughly) for the width of the space to the right of the "plot area" (i.e where the toolbar is). However if you add a y-axis on the left side, you'd need to account for that too, and if you allow zooming, then left space can grow and shrink to accommodate bigger or smaller axis labels, which means you can't reliably account for that space with a single constant up front. You could set min_border values to be larger, which might mitigate the problem for some range of zooming/panning.
Also the above assumes the plot sizing mode is not "responsive". If the plot itself can resize then no constant value in screen units will ever work.
If you can fix your x range start/end (or add an "extra" range), then you could right-align to the range end value using "data" units. But if you allow zooming or panning then the label will move to stay fixed at that data position.
The main issue is that the "inner_width" is only computed in the browser. It's not available to the Python code because it doesn't exist outside the browser. What's really needed is some special convention or confguration to designate "inner_width" as a symbolic concept that updates to whatever is necessary, regardless of panning or zooming or resizing. I'd suggest making a GitHub issue to propose this feature.
In the mean time, I think any solution will involve some trial and error with a fixed font size in "px" and also ideally limiting panning/zooming if possible.

How to find the real first line of a shape in pptx presentation

At the moment I need to get the actual width of the text, the best solution that I tried was to find the first line of text, and get its width.
The presentations given to me were made by different people, and I cannot directly influence them. And it turns out that the shape frame itself in the presentation is often much wider than the text, which is a problem, because I need to get visible text shape collisions, which possible only when i have real frame of text(tried to show it in the screenshot1, screenshot2)
My best try to get real first line is:
# i have already compiled PIL font, with font typeface and size named "font"
# width of shape and text of shape
# and also class TextWrapper that wraps given string with given width and outputs a list
# get first line from wrapped text, and from tuple select width
width_first = font.getsize(TextWrapper(shape.text, font, width).text_lines[0])[0]
# get lines that wrapped at width first string
wrapped_lines = TextWrapper(shape.text, font, width_first).text_lines
# ... some calculations here
Problem that a wrap symbol like '\n' not always be in text, but in presentation i see that wrap.
I tried to explain how I could, did anyone come across this at all?
EDIT:
I found some way how to do thig that i need.
If u need something equals, see code.
import win32com.client
Application = win32com.client.Dispatch("PowerPoint.Application")
# WithWindow=False forces PowerPoint to do not open the PowerPoint Window
Presentation = Application.Presentations.Open("ABCPATH/to/presentation.pptx",
WithWindow=False)
for Slide in Presentation.Slides:
for Shape in Slide.Shapes:
if Shape.HasTextFrame: # checks if shape has text, becouse we avoiding imgs
# that what we need
first_line = Shape.TextFrame.TextRange.Lines(1, 1)
You must have installed PowerPoint Application to do that, and installed pywin32
And it works only on Windows, so thats not so good choose, but for me it works perfect
Maybe someone found this usable

Width as formular but if value smaller than x be a fix value inline?

I draw texts with wxPython on my DC. The position of the text is depending on the width of my frame, in this case the variable "w".
It is calculated in my code like this:
dc.DrawText("Overview", w/2-wt/2, 10)
But now, if the forumlar "w/2-wt/2" is smaller than a certain value I want to set it to a fix value.
I know how to do it with an if than else, but my personal favorit would be to do it inline, to keep my code short an simple.
Is there a way to do this?

Output colored, right aligned text into the terminal

I want to output colored text completly aligned to the right in the terminal (like in this screenshot of pacman (packet manager of the arch linux distribution)(not colored))
Currently I'm using format:
import shutil
left = "foo"
right = "bar"
width = shutil.get_terminal_size().columns
template = "{left:30}{right:{width}}".format(left=left, right=right, width=width-30)
click.echo(template)
# click.echo works just like print with some additional features
This works great until I add colors via ANSI escape codes:
left = click.style("foo", fg="red")
right = click.style("bar", fg="green")
# click.style just adds ANSI codes for colors and bold etc.
Which looks like this:
I.e. the right side is not completly right aligned. Which is "right", because right is actually \\x1b[32mbar\\x1b[0m which of course has a higher lenght than bar and thus needs less spaces to be right aligned. Until the terminal gets the text and only displays bar (with color).
Am I missing anything in the python std lib or click? Or is there a simple library that deals with terminal colors and alignment that could help me? Or is there a simple solution to this problem?
click's documentation does not mention alignment (which is why you are using python's built-in string class). You could stay within the current set of interfaces by telling your script to remember the lengths of the strings before calling click.style, and adding the difference to the width used for the format call. (This would not work as well if you were centering text).
There are perhaps other libraries, but you could use the curses interface with the filter function to draw single-line displays.
First, I want to figure out that click provide a way to get the terminal size: click.get_terminal_size, the documentation is here
>>> import click
>>> click.get_terminal_size()
>>> (66, 24) # (width, height)
And my solution, should works even you resize the terminal:
width = click.get_terminal_size()[0]
left = click.style("foo", fg="red")
right = click.style("bar", fg="green")
print "{0:}{1:>{2}}".format(left, right, width+6)
Since right actually is \x1b[32mbar\x1b[0m, we increase the width by hand to avoid the problem.
Edit: PyFormat is useful for me when do string format in python. It helps me understand string formating. Hope it will help you.

problems with the curses.newwin() command

when using the curses.newwin() command
e.g.
curses.newwin(10, 10, 0, 0)
if i try to edit the integers to create a larger window the program terminates when I try to run it.
As the comments have mentioned, you can't make a larger window than your parent terminal. If you're looking for a way to resize the terminal itself, consider something like this:
os.system("mode con cols=80 lines=60")
os.environ['COLS'] = "80"
os.environ['LINES'] = "60"
This will change the console size. You can change the size to whatever you like, just change cols and lines as needed. The first line sets the upper limit on the bottom two--you'll throw an error if one of the lower numbers is larger.

Categories