INPUT FORMAT COMPLIANCE: a date prompt with 3 mutable input fields separated by 2 static forward slashes, with set ranges for each feild
Question:
I am trying to create a prompt that is either separated by hard slashes or slashes appear after specified input range, all on a single line.
i want:
Enter your age (M/D/Y): int
/ int
/ int
#where the slashes are fixed and part of the prompt
not: M:
D:
Y:
example:
Enter the date M/D/Y: '12'**/**'12'**/**'1234'
0,1,/ 0,1,/
Ideal: the slashes are static but the input fields between are mutable, and cursor skips slashes.
**or:**the slash appears after populating the specified range…and the integer input field ranges would be set at 0:1,0:1,0:3
(mm) if users enters two integers, backslash appears
(dd) if users enters two integers, backslash appears
(yyyy) user completes the range (or not)
User is unable to enter subsequent integers out of range.
nothing seemed to be what I’m after. the closest info i could find was using datetime but that just sorts out the input, i want actual hard slashes to appear, separating the input fields, or appear after input and stay.
printing it like that isn’t an issue, and the integer input field ranges would be set at 0:1,0:1,0:3
being a noob i’m not certain if py is even capable of such a demand.
Answers:
#A solution was provided elsewhere, posting with Author's permission.
"""PINPUT, AN INPUT FORMAT COMPLIANCE MODULE FOR DATE/TIME ENTRY"""
" AUTHOR: INDRAJIT MAJUMDAR "
import sys
try:
#for windows platform.
from msvcrt import getwch as getch
except ImportError:
#for linux, darwin (osx), and other unix distros.
def getch():
"""
Gets a single character from STDIO.
"""
import sys
import tty
import termios
fd = sys.stdin.fileno()
old = termios.tcgetattr(fd)
try:
tty.setraw(fd)
return sys.stdin.read(1)
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, old)
def flsp_input(prmt, ptrn, otyp="t"): #otyp=[s=string, t=tuple, p=ptrn]
"""
--flsp_input:
--Fixed Length Slotted Pattern Input [int, str]--
Licence: opensource
Version: 1.1
Author : [email protected]
"""
def fout(ts, ptrn, otyp):
fs, tpl = 0, []
for i, p in enumerate(ptrn):
if p[2] == "":
csd = ts[fs:]
else:
fi = ts[fs:].find(p[2])
if fi == -1:
csd = ts[fs:]
else:
csd = ts[fs:fs+fi]
fs += p[1]+len(p[2])
if otyp == "s": out = ts
if otyp == "t": tpl.append(csd)
if otyp == "p": ptrn[i].append(csd)
if otyp == "s": out = fout
if otyp == "t": out = tuple(tpl)
if otyp == "p": out = ptrn
return out
i, ts, plts, = 0, "", 0
ptxt = "".join([f"{'_'*e[1]}{e[2]}" for e in ptrn])
print(f"{prmt}{ptxt}r{prmt}", end="")
sys.stdout.flush()
while i < len(ptrn):
ptype, plen, psep = ptrn[i]
while True:
cc = getch()
if ord(cc) == 127: #bksp
frm = 0 if i == 0 else ts.rfind(ptrn[i-1][2])+1
cplf = ts[frm:]
bkstp = 2 if cplf == "" and i != 0 else 1
ts = ts[:len(ts)-bkstp]
if bkstp == 2: i -= 1
ptype, plen, psep = ptrn[i]
plts = sum((ptrn[j][1]+len(ptrn[j][2]) for j in range(i)))
print(f"r{prmt}{ptxt}r{prmt}{ts}", end="")
continue
if ord(cc) == 13: #enter
print()
return fout(ts, ptrn, otyp)
try:
cc = int(cc)
except ValueError:
cc = cc
if type(cc) is ptype:
cc = str(cc)
ts += cc
print(cc, end="")
sys.stdout.flush()
if len(ts) - plts == plen:
print(psep, end="")
ts += psep
plts = len(ts)
sys.stdout.flush()
break
i += 1
print()
return fout(ts, ptrn, otyp)
if __name__ == "__main__":
prmt = "Input Date and Time: "
ptrn = [[int, 2, "/"], [int, 2, "/"], [int, 4, " "],
[int, 2, ":"], [int, 2, ":"], [int, 2, "."],
[int, 3, " "], [str, 2, ""]]
#ptrn = [[str, 2, ":"], [int, 2, " "], [str, 1, " "],
# [int, 4, ""]]
ts = pinput(prmt, ptrn)
print(f"{ts=}")
I am trying to create a prompt that is either separated by hard slashes or slashes appear after specified input range, all on a single line.
i want:
Enter your age (M/D/Y): int
/ int
/ int
#where the slashes are fixed and part of the prompt
not: M:
D:
Y:
example:
Enter the date M/D/Y: '12'**/**'12'**/**'1234'
0,1,/ 0,1,/
Ideal: the slashes are static but the input fields between are mutable, and cursor skips slashes.
**or:**the slash appears after populating the specified range…and the integer input field ranges would be set at 0:1,0:1,0:3
(mm) if users enters two integers, backslash appears
(dd) if users enters two integers, backslash appears
(yyyy) user completes the range (or not)
User is unable to enter subsequent integers out of range.
nothing seemed to be what I’m after. the closest info i could find was using datetime but that just sorts out the input, i want actual hard slashes to appear, separating the input fields, or appear after input and stay.
printing it like that isn’t an issue, and the integer input field ranges would be set at 0:1,0:1,0:3
being a noob i’m not certain if py is even capable of such a demand.
#A solution was provided elsewhere, posting with Author's permission.
"""PINPUT, AN INPUT FORMAT COMPLIANCE MODULE FOR DATE/TIME ENTRY"""
" AUTHOR: INDRAJIT MAJUMDAR "
import sys
try:
#for windows platform.
from msvcrt import getwch as getch
except ImportError:
#for linux, darwin (osx), and other unix distros.
def getch():
"""
Gets a single character from STDIO.
"""
import sys
import tty
import termios
fd = sys.stdin.fileno()
old = termios.tcgetattr(fd)
try:
tty.setraw(fd)
return sys.stdin.read(1)
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, old)
def flsp_input(prmt, ptrn, otyp="t"): #otyp=[s=string, t=tuple, p=ptrn]
"""
--flsp_input:
--Fixed Length Slotted Pattern Input [int, str]--
Licence: opensource
Version: 1.1
Author : [email protected]
"""
def fout(ts, ptrn, otyp):
fs, tpl = 0, []
for i, p in enumerate(ptrn):
if p[2] == "":
csd = ts[fs:]
else:
fi = ts[fs:].find(p[2])
if fi == -1:
csd = ts[fs:]
else:
csd = ts[fs:fs+fi]
fs += p[1]+len(p[2])
if otyp == "s": out = ts
if otyp == "t": tpl.append(csd)
if otyp == "p": ptrn[i].append(csd)
if otyp == "s": out = fout
if otyp == "t": out = tuple(tpl)
if otyp == "p": out = ptrn
return out
i, ts, plts, = 0, "", 0
ptxt = "".join([f"{'_'*e[1]}{e[2]}" for e in ptrn])
print(f"{prmt}{ptxt}r{prmt}", end="")
sys.stdout.flush()
while i < len(ptrn):
ptype, plen, psep = ptrn[i]
while True:
cc = getch()
if ord(cc) == 127: #bksp
frm = 0 if i == 0 else ts.rfind(ptrn[i-1][2])+1
cplf = ts[frm:]
bkstp = 2 if cplf == "" and i != 0 else 1
ts = ts[:len(ts)-bkstp]
if bkstp == 2: i -= 1
ptype, plen, psep = ptrn[i]
plts = sum((ptrn[j][1]+len(ptrn[j][2]) for j in range(i)))
print(f"r{prmt}{ptxt}r{prmt}{ts}", end="")
continue
if ord(cc) == 13: #enter
print()
return fout(ts, ptrn, otyp)
try:
cc = int(cc)
except ValueError:
cc = cc
if type(cc) is ptype:
cc = str(cc)
ts += cc
print(cc, end="")
sys.stdout.flush()
if len(ts) - plts == plen:
print(psep, end="")
ts += psep
plts = len(ts)
sys.stdout.flush()
break
i += 1
print()
return fout(ts, ptrn, otyp)
if __name__ == "__main__":
prmt = "Input Date and Time: "
ptrn = [[int, 2, "/"], [int, 2, "/"], [int, 4, " "],
[int, 2, ":"], [int, 2, ":"], [int, 2, "."],
[int, 3, " "], [str, 2, ""]]
#ptrn = [[str, 2, ":"], [int, 2, " "], [str, 1, " "],
# [int, 4, ""]]
ts = pinput(prmt, ptrn)
print(f"{ts=}")