Display % after input(...) prompt? - python

Suppose we are on python3.3 and multi-platform (Linux and WIndow), if I do following:
>>> eval(input("enter a percent from 1-100"))
I get:
enter a percent from 1-100: (Terminal is Waiting for user prompt)
I want it to display:
enter a percent from 1-100: (waiting for user prompt) %
How do I show that % following the parenthesis?

If I understand your question, you want to be able to write a prompt that includes a % sign character, but places the user's cursor to the left of the sign, like this:
Enter a percent from 1-100: %
^ cursor is here
There's not a universal solution to this, since basic text-IO is usually oriented around input and output streams that don't have well defined interactions. There are some approaches that will work in some situations but not others, but I'm not sure of anything that will work everywhere (short of writing a GUI).
One suggestion I have is to include ASCII (and unicode) backspace characters '\b' (or '\x08') in your prompt. On some consoles this will move the cursor to the left one character per backspace. So, the prompt above could be generated by:
input("Enter a percent from 1-100: %\b\b\b\b\b")
This works when I run Python from a windows CMD.exe shell, but not when I run it within IDLE (the '\x08' characters are displayed as a box with a small circle taken out of the middle). It's a bit crude though, as it can't prevent the user from entering more characters than there are spaces before the % (which will be overwritten by the fifth character entered).
Another solution which may be a bit more robust (but not cross-platform, alas) is to use the curses module. I'm not knowledgeable enough about it to suggest code, but it should be possible to make it do what you want (and even control things like preventing the user from entering more than three characters, or moving the % sign to correctly align with values of any length).
One final thing: I strongly suggest that you don't use eval around your input call. If you expect (and require) an integer value, use int(input()). If you might get an integer, but could also get some other kind of value, use multiple lines to test what you got:
def get_val():
str_val = input()
try:
return int(str_val) # handle numbers like 1, 23232, etc.
except ValueError:
pass
try:
return float(str_val) # handles 23.5 and -3e-3 (but beware, also "nan" and "inf")
except ValueError:
pass
try:
return make_some_other_value(str_val) # whatever you want
except ValueError:
pass
return str_val # give up and return the string

Here's an alternative using the getch package. Instead of using input, we'll roll our own.
import string
import sys
try:
from msvcrt import getch
except ImportError:
from getch import getch
def char_valid(char):
"""Do whatever validation you need here."""
return char in string.ascii_letters or char in string.digits
def char_bkspace(char):
"""Matches backspace and delete."""
return char in ['\x08', '\x7f']
message_pre = 'enter a percent from 1-100'
message_post = '%'
user_input = ''
while True:
sys.stdout.write('\r{0} {1} {2}'.format(message_pre, user_input, message_post))
char = getch()
if char_bkspace(char):
user_input = user_input[:-1]
elif char_valid(char):
user_input += char
else:
break
print('\nyour message was', user_input)
This gets user input one character at a time in a while loop using getch. By using sys.stdout.write('\r...') we can avoid newlines and constantly overwrite the previous line.
This has the problem that if you backspace, multiple %'s will be visible because the new line is not entirely overwriting the previous line. This can be fixed by padding the string with spaces.

Related

python 3 input without newline

I am new to coding. And I would like to know if there's a way for input function to not print newline character after the value is entered. Something like print function's argument end. Is there any way?
Well, you can't make input() trigger by anything besides 'Enter' hit (other way may be using sys.stdin and retrieving character one-by-one until you receive some stop marker, but it's difficult both for programmer and for user, I suppose). As a workaround I can the suggest the following: if you can know the length of line written before + length of user input, then you can use some system codes to move cursor back to the end of previous line, discarding the printed newline:
print("This is first line.")
prompt = "Enter second: "
ans = input(prompt)
print(f"\033[A\033[{len(prompt)+len(ans)}C And the third.")
\033[A moves cursor one line up and \033[<N>C moves cursor N symbols right. The example code produces the following output:
This is first line.
Enter second: USER INPUT HERE And the third.
Also note that the newline character is not printed by your program, it's entered by user.
name=input('Enter your name : ')
print('hello',name,end='')
I know about the end function which is abov

How can I change the cursor position of the user input in input() function in Python?

While using the input() function I want to take or receive a string from the user to a variable. So is it possible to input inside square brackets instead of plain text? For example;
a = input("-->")
this shows the output like this:
-->
but instead can I have the output like this:
--> [ _ ]
and take the input inside the square bracket. (_ represents the cursor.)
Manipulating the cursor position when you call input() requires a hack with ANSI escape sequences. (See #chepner's answer.) To do what you want more correctly, you need to use a library that can manipulate the terminal, such as curses.
You can, sort of. If your terminal supports ANSI escape sequences, you can save the current cursor position by outputting \033[s and move the cursor back to the last saved position with \033[u. Then your call to input will look like
a = input("--> [\033[s ]\033[u")
However, this is purely visual: nothing stops you from typing "beyond" the square bracket. The main limitation is that input itself knows nothing about the terminal; it just reads from standard input, which is line-buffered. input returns nothing until a complete line is entered; until then, it just waits for the terminal to send something. A library like curses provides much more exact handling; for instance, it can stop responding to key presses if you try to type beyond the ] in your prompt.
The following code snippet, using curses, will handle standard visible ascii characters, deleting characters, and newline (for submit).
from curses import wrapper
def prompt(stdscr, prompt_template="--> [ {} ]"):
user_inp = ""
display_str = prompt_template.format(user_inp)
stdscr.addstr(0, 0, display_str)
while True:
inp_ch = stdscr.getch()
# standard ASCII characters
if 32 <= inp_ch <= 126:
user_inp += chr(inp_ch)
elif inp_ch in (8, 127, 263): # BS, DEL, Key_Backspace
user_inp = user_inp[:-1]
elif inp_ch == 10: # is newline, enter pressed
break
else: # all other characters are ignored
continue
display_str = prompt_template.format(user_inp)
stdscr.erase()
stdscr.addstr(0, 0, display_str)
stdscr.refresh()
return user_inp
print(wrapper(prompt))

How do I show a suffix to user input in Python?

I want a percentage sign to display after the users enters their number. Thanks
percent_tip = float(input(" Please Enter the percent of the tip:")("%"))
For example, before the user types anything they should see:
Please Enter the percent of the tip:
Once they begin typing the number 20 they should see:
Please Enter the percent of the tip: 20
After they hit <Enter> they should see:
Please Enter the percent of the tip: 20%
Please try this if this is what you are asking for:
import sys
import time
percent_tip = ""
while percent_tip in "123456789": # This part checks with the "if" statement, if its not a integer then it returns
percent_tip = input("Please Enter the % of the tip: ")
if percent_tip in "123456789":
print(str(percent_tip) + " %") # Prints the number and the percentage symbol
sys.exit() #stops the shell
else:
time.sleep(.100) #Shell waits then goes back in the while loop (unless its controlled by the "while" and "if")
Please do not try to harden yourself with a code that you don't know how to do it.
If you are on Windows, you will have the msvcrt module available. It provides, among others, the getwche() function, giving you the key pressed. This allows you to act on individual characters, and then print the % at the end (if you play around a bit more, you can probably also get it to appear while typing).
Example:
def get_chars():
chars = []
new = msvcrt.getwche()
while new != '\r': # returns \r on <RETURN> press
# you probably want to do some input validation here
chars.append(new)
new = msvcrt.getwche() # get the next one
print(end='%', flush=True)
return ''.join(chars) # this returns a str, you might want to directly get an int
Also, you will probably want to add input validation inside to make sure the input is only numbers.

Hangman in python: have lines be replaced?

I'm working on writing a simple Hangman game in Python from what I know so far (I'm doing Learn Python the Hard Way) and so far I have this:
from sys import argv
import random
script_name, dict_file = argv
hang_list = open(dict_file).read().splitlines()
hang_list = filter(None, hang_list)
word = random.choice(hang_list)
guesses = ''
def compare_words():
global guesses
new_word = ''
for char in word:
if char in guesses:
new_word += char
else:
new_word += "_"
return new_word
def test_letter():
global guesses
letter = raw_input("Guess a letter: ")
guesses += letter
new_word = compare_words()
print "\nCurrent guesses: %s" % guesses
print "%s\n\n" % new_word
if new_word == word:
print "You won!"
else:
test_letter()
test_letter()
I've yet to implement the scoring system (piece of cake) but I have an issue with the layout. As you can tell, this will print "Current guesses: " and the new word each time; however, what I want is four lines that look like:
Guess a letter:
Guesses: abczy
__c__b_
And have those three lines keep updating. However, I am having trouble figuring out how to make the print replace stdout. I believe I need to use the \r escape character, yet I've tried placing that in various places but can't get it to work. So, how should I modify this to get it to replace? I would prefer not to just clear, as then it still makes things a bit messy; I want to just replace what's there. Thanks!
It would be a bit tricky to make this work for all terminals, but if yours understands ANSI escape codes like mine does, this might work:
...
if new_word == word:
print "You won!"
else:
print '\033[F'*7
print ' '*17 + '\b'*17 + '\033[F'
test_letter()
This relies on the ANSI code F: move the cursor up one line; backspaces (\b) alone have no effect once the beginning of the line is reached.
The first print takes you back up to the input line and the second deletes the character that was previously entered.
You can use the escape characters \033c and this will erase the code in a terminal window and put the cursor at the top left.
For example this code:
import time
print("text 1")
time.sleep(1)
print('\033c')
time.sleep(1)
print("text 2")
This code will print "text 1" wait one second, clear the console, wait one second and then print "text 2".
So you could use the code
def test_letter():
print("\033c")
global guesses
letter = raw_input("Guess a letter: ")
guesses += letter
new_word = compare_words()
print "\nCurrent guesses: %s" % guesses
print "%s\n\n" % new_word
if new_word == word:
print "You won!"
else:
test_letter()
What this code will do is clear the console, ask the person to guess a number, display that four line piece of code that you wanted and then clear the console again.
I hope this helps!
If you want to replace the content of a specific line, from a specific position, you can use ANSI Escape Codes. To do this, make sure that you're using stdout.write() rather than print(). You can access this method by using the following import statement:
from sys import stdout
Then, in order to navigate the "cursor" (where text printed with this method will go), use the escape code \u001b[<L>;<C>H (or \u001b[<L>;<C>F where <L> and <C> represent the respective line number and character index of the desired position. For example, if you wanted to set the cursor to line 3; character 2, you would do the following.
stdout.write(u"\u001b[3;2H")
Note the u proceeding the double-quoted string. This is required in Python 2.x, since it contains special characters, but can be omitted in Python 3 and above.
Once you have set the cursor to be at the desired position, anything you write will replace the characters that currently reside there. This is important, because if the replacement string is shorter than the original, you may end up with trailing legacy characters. The simplest way to deal with this is to pad the printing string in spaces.
After doing this you should probably move the cursor back to the end of stdout, using the same method, and flush the output with stdout.flush().
Example
Let's say I had the following output on the terminal:
Name: Shakespeare
Score: 0
Some text...
I could change the score to 1 by running the following:
stdout.write(u"\u001b[2;8H")
stdout.write("1")
stdout.write(u"\u001b[5;0H")
stdout.flush()
Again, the u is optional in Python 3 and up.
Notes
This line-and-character-number method applies to all output currently being displayed in the terminal. This means that if you have anything left from another program or command, for example
$ python game.py
so it is best to clear the output at the start of your program, with something like print(u"\033c"), or os.system("clear"), otherwise you may end up writing to the wrong line.
Also, if your going to use stdout.write() anywhere else, remember to put \n at the end if you want to go to the next line.
The \r character is a carriage return, which means it will return the cursor to the start of the current line. That's OK if you want to redraw the line the cursor is on, but no good if you want to redraw other lines.
To do what you want, you need to use a terminal library like curses on Linux or the console API on Windows. If you are just working on Linux and want a simpler way to access colours, cursor movement and input without echo, you could do worse than try out blessed (https://pypi.python.org/pypi/blessed/).
If you need a cross platform API to do this sort of thing, there is no pure Python way to handle it all yet, but I am working on one. The Screen class in https://github.com/peterbrittain/asciimatics cover all the features above in a cross-platform manner.

How to not issue a new line in Python 3 when entering text with input()

I'm making a basic utility in Python 3 where the user inputs a command and gets feedback printed out into the console. When entering data using the input() or sys.stdin.readline() functions this is what the command-line session may look like (including \r and \n characters)
1. What is your name:\n
2. <user input>\n
3. Your name is <variable>.\n
But, I would like to display a \r character after the user hits enter instead of the \n character, as shown on line 2. After the user had typed everything in and hit enter it would look like this
1. What is your name:\n
2. Your name is <variable>.\n
(because line 2 would have a \r character after the entered data, returning the cursur back to the far left)
Does anybody know of a way I might accomplish this?
Well, I discovered this method although I am almost cirtain that the msvcrt module is for Windows only.
import msvcrt
import sys
def msgInput(prompt):
print(prompt, end='')
data= b''
while True:
char= msvcrt.getch()
if char != b'\r':
print(char.decode(), end='')
sys.stdout.flush()
data= data+char
else:
print('\r', end='')
break
return data.decode()
If anybody knows of any cross-platform methods, please share.
Update - Unfortunately this method has many limitations, such as the user cannot navigate the entered text with the arrow keys.
Well, I believe I found the solution you wanted:
strng=input("Enter String - ")
Where strng is just a variable to hold the input response. This will return the string in the interpreter Enter String - (without any quote) and allow you to save the response in the variable strng.

Categories

Resources