Python code to cause a backspace keystroke? - python

I keep finding ways to map the backspace key differently, but that's not what I'm after.
I'm in a program writing a python code, and basically I want to write a line of code that causes the program to think someone just hit the Backspace key in the GUI (as the backspace key deletes something)
How I would code in a backspace key stroke?

The character for backspace is '\b' but it sounds like you want to affect the GUI.
if your program changes the GUI, then simply delete the last character from the active input field.

and i got it !
print('\b ', end="", flush=True)
sys.stdout.write('\010')
it backspace !

foo = "abc"
foo = foo + "\b" + "xyz"
print foo
>> abxyz
print len(foo)
>> 7
if key == '\b': delete_selected_points()

As other answers have said, use '\b' to backspace. The trick in your case is to use sys.stdout.write instead of print to not get a newline appended. Then wait and print the appropriate number of backspace characters.
import time
import sys
print("Good morning!")
while True:
time_fmt = "It's %I:%M:%S %p on %A, %b %d, %Y"
time_str = time.strftime(time_fmt)
sys.stdout.write(time_str)
sys.stdout.flush()
time.sleep(1)
sys.stdout.write("\b"*len(time_str))

Updating since this still pops up in search.
In Python3 print() can and does work if you use the \<end\> parameter. Meaning sys.stdout.write() and .flush() aren't needed.
eg.
print("\b"*len(time_str),end='')

Related

What does this mean in Python '\x1b[2K'?

I've just learnt that to clear a line that you printed in Python, do this:
sys.stdout.write('\x1b[2K')
Why is it so complicated? what does that weird code mean? and is there any alternative in print command?
Print does offer "end" option that allows to go back and forth in lines, but no way to clear what you printed. Overwriting via \r doesn't always work especially if the new line is shorter than the old one. You will get traces from the old line, so I need clearing first.
Thanks.
\x1b[2K is what's known as an ANSI terminal control sequence. They are a legacy of the 1970s and still used today (but vastly extended) to control terminal emulators.
\x1b is the ASCII for ESCAPE (literally the ESC key on your keyboard). [2K is the command "erase the current line".
There are many libraries in Python for working with the terminal, such as Urwid. These libraries will hide the inner workings of the terminal from you and give you higher-level constructs to create TUIs.
However, there is a much more efficient way of doing this:
You can use the print() command as usual, and delete the screen using
os.system("cls") # For Windows
or
os.system("clear") # For Linux
Alternative to print on a single line
I have a script that prints the x, y coordinates of the mouse as such:
import pyautogui
import time
while True:
x, y = pyautogui.position()
position_string = "X: {} Y: {}".format(str(x).rjust(4), str(y).rjust(4))
print(position_string, end='')
print('\b' * len(position_string), end='', flush=True)
time.sleep(1)
Where I will point out that you can print the backspace character ('\b') the amount of times that there are characters on the screen (len(position_string)), and when used with the end='' and flush=True options this will constantly print on a single line within your console. I should also note that this does not work in IDLE, but only on an actual command line! In IDLE the backspace characters are actually printed as some weird square shape...
This is called ANSI escape code . 2K is the name for Erase in Line. Quote from the link:
Erases part of the line. If n is 0 (or missing), clear from cursor to the end of the line. If n is 1, clear from cursor to beginning of the line. If n is 2, clear entire line. Cursor position does not change.
You can also try echo -e '\x1b[2k' in the terminal for better understanding.

Python if statement not executing

# TEST
import sys
a=sys.stdin.readline() # here the user inputs the string "HELLO"
print a
if a == "HELLO":
sys.stdout.write("GOOD_BYE")
print "AAAAAAAAAAA"
raw_input('\npress any key to continue')
Hi there. I am new to Python.
I am using Python 2.7.11.
I do not understand why control is not entering the if statement.
The output for the given code comes out as
HELLO
HELLO
AAAAAAAAAAA
press any key to continue
NOTE: The first "HELLO" above is user input
I've tried sys.stdout.flush() for the sys.stdout.write() statement. But it doesn't seem to help.
If I write the same code with a=raw_input() instead of the second line, it works perfectly fine.
Can anyone explain the reason for this.
readline comes with a newline character at the end. So what you are actually doing is comparing
HELLO\n == HELLO
which is actually false.
Do a.rstrip() to remove newline.
readline() function read newline character from standard input console. Please use rstrip("\n") to remove the same.
import sys
a=sys.stdin.readline().rstrip('\n')
print (a)
if a == "HELLO":
sys.stdout.write("GOOD_BYE")
print ("AAAAAAAAAAA")
raw_input('\npress any key to continue')
Try using 'in' instead of '==' in your if condition, sometimes the lines might have some hidden characters.
if "HELLO" in a:
You are pressing 'ENTER' after input string to send input. So your input is 'HELLO\n' while your if statement 'if' condition is 'a == "HELLO"'.
Use strip() method. The method strip() returns a copy of the string in which all chars have been stripped from the beginning and the end of the string (default whitespace characters).
So new working code :
import sys
a=sys.stdin.readline().rstrip('\n')
a=a.strip() # This will remove \n from input
print (a)
if a == "HELLO":
sys.stdout.write("GOOD_BYE")
print ("AAAAAAAAAAA")
raw_input('\npress any key to continue')

How can I use \r to make Python print on the same line?

Can someone please thoroughly explain how a '\r' works in Python?
Why isn't the following code printing out anything on the screen?
#!/usr/bin/python
from time import sleep
for x in range(10000):
print "%d\r" % x,
sleep(1)
Your output is being buffered, so it doesn't show up immediately. By the time it does, it's being clobbered by the shell or interpreter prompt.
Solve this by flushing each time you print:
#!/usr/bin/python
from time import sleep
import sys
for x in range(10000):
print "%d\r" % x,
sys.stdout.flush()
sleep(1)
'\r' is just a another ASCII code character. By definition it is a CR or carriage return. It's the terminal or console being used that will determine how to interpret it. Windows and DOS systems usually expect every line to end in CR/LF ('\r\n') while Linux systems are usually just LF ('\n'), classic Mac was just CR ('\r'); but even on these individual systems you can usually tell your terminal emulator how to interpret CR and LF characters.
Historically (as a typewriter worked), LF bumped the cursor to the next line and CR brought it back to the first column.
To answer the question about why nothing is printing: remove the comma at the end of your print line.
Do this instead:
print "\r%d" % x,
This has nothing to do with \r. The problem is the trailing , in your print statement. It's trying to print the last value on the line, and the , is creating a tuple where the last value is empty. Lose the , and it'll work as intended.
Edit:
I'm not sure it's actually correct to say that it's creating a tuple, but either way that's the source of your problem.

How to print voltages side by side?

I'm using a program that prints out voltages one right below the other, like:
2.333
2.334
2.336
2.445
But I want it like:
2.333 2.334 2.336 2.445
Ok, here is what works for me:
while True:
voltsdiff = adc.readADCDifferential01(4096, 8)
import sys
print '{:.4f}'.format(voltsdiff),
sys.stdout.flush()
Just print them with a comma
print "%.4f" % (voltsdiff),
Moreover, you might want to use format method. You can read all about formatting here
print "{:.4f}".format(voltsdiff),
Lets say, you are printing these values by iterating a list, you can do something like this
data = [2.333, 2.334, 2.336, 2.445]
print " ".join(data)
As others have answered, to print output without a newline in Python 2, put a comma at the end of your print statement:
print "%.4f" % voltsdiff,
However, this will not flush the output, as standard output is line buffered by default (it will only be flushed when a newline is added to the output). There are a few ways you can fix that.
First, you could, at some point, append a newline with just a basic print statement, e.g.:
for i, voltsdiffs in enumerate(many_voltages):
print "%.4f" % voltsdiffs,
if i % 10 == 9:
print # puts a newline after every 10 values
Next, you could explicitly flush standard output, using sys.stdout.flush():
print "%.4f" % voltsdiffs,
sys.stdout.flush()
Finally, you can use the Python 3 style print function, which has a flush parameter (which does the flushing for you, if it is True):
# before any other code
from __future__ import print_function
# later
print(format(voltsdiffs, ".4f"), end=" ", flush=True)
I'd generally recommend the last version, as it's what you'll need to use in the future if you port your code to Python 3. It's also quite explicit, with each special characteristic of the printing (no newline at the end, flushing automatically) called for by a separate keyword argument.
If you print to terminal, you may use stdout with \r or \b escape
sys.stdout.write("\r%.4f\t%.4f\t%.4f\t%.4f" % (v1, v2, v3, v4))
The "\r" escape move the cursor at begining of line (like cr on same line) and "\b" is untab: move 4 position back.
P.S.:stdout do some cache, you should call sys.stdout.flush() to be sure that the result is on terminal at request, before the buffer is full

Python : correct use of set_completion_display_matches_hook

I'm trying to write a function to display a custom view when users press the tab button. Apparently "set_completion_display_matches_hook" function is what I need, I can display a custom view, but the problem is that I have to press Enter to get a prompt again.
The solution in Python2 seems to be that (solution here):
def match_display_hook(self, substitution, matches, longest_match_length):
print ''
for match in matches:
print match
print self.prompt.rstrip(),
print readline.get_line_buffer(),
readline.redisplay()
But it doesn't work with Python3. I made these syntax changes :
def match_display_hook(self, substitution, matches, longest_match_length):
print('\n----------------------------------------------\n')
for match in matches:
print(match)
print(self.prompt.rstrip() + readline.get_line_buffer())
readline.redisplay()
Any ideas please ?
First, the Python 2 code uses commas to leave the line unfinished. In Python 3, it's done using end keyword:
print(self.prompt.rstrip(), readline.get_line_buffer(), sep='', end='')
Then, a flush is required to actually display the unfinished line (due to line buffering):
sys.stdout.flush()
The redisplay() call does not seem to be needed.
The final code:
def match_display_hook(self, substitution, matches, longest_match_length):
print()
for match in matches:
print(match)
print(self.prompt.rstrip(), readline.get_line_buffer(), sep='', end='')
sys.stdout.flush()
The redisplay() function
voidrl_redisplay (void)
Change what's displayed on the screen to reflect the current contents of rl_line_buffer.
In your example you have written to stdout, but not changed that buffer.
Print and flush as described by in other answer should work.
One issue you will have, however, is cursor position. Say you have this scenario:
$ cmd some_file
^
+---- User has back-tracked here and want to insert an option.
<TAB> completion with print and flush will put cursor
at end of `some_file' and the line will get an extra 15
spaces after that ...
To remedy this one way is to first get cursor position, then use ANSI sequences to re-position the cursor.
buf = readline.get_line_buffer()
x = readline.get_endidx()
print(self.prompt + buf, end = '')
if x < len(buf):
""" Set cursor at old column position """
print("\r\033[%dC" % (x + len(self.prompt)), end = '')
sys.stdout.flush()
Now, of course, you get another issue if prompt has ANSI sequences in-iteself. Typically color or the like. Then you can not use len(prompt) but have to find printed / visible length.
One has to use open and close bytes elsewhere, typically \0x01 and \0x02 respectively.
So one typically get:
prompt = '\001\033[31;1m\002VISIBLE_TEXT\001\033[0m\002 '
instead of:
prompt = '\033[31;1mVISIBLE_TEXT\033[0m '
With those guards it should be easy enough to strip out the visible text.
Typically something like:
clean_prompt = re.sub(r'\001[^\002]*\002', '', prompt))
Cache the length of that and use when printing the readline manually. Note that you also have to remove the guards when using it manually - as in the hook function. (But it is needed in input(prompt)
this one worked for me for redisplaying substitution and the end of matches display for python3:
def match_display_hook(self, substitution, matches, longest_match_length):
print("")
for match in matches:
print(match)
print("")
sys.stdout.write(substitution)
sys.stdout.flush()
return None
while previous ones using print prompt didn't. (didn't get to the bottom of the problem)

Categories