@@ -106,28 +106,100 @@ def displaymsgnodelay(stdscr,message: list):
106106 mi += 1
107107 stdscr .addstr (int (y // 2 + mi ),int (x // 2 - len (msgl )// 2 ),msgl )
108108 stdscr .refresh ()
109-
109+ def __retr_nbl_lst (input :list )-> list :
110+ return [l for l in input if str (l ) != "" ]
111+ def __shft_lst (input :list )-> list :
112+ xl = [i for i in input if str (i ) != "" ]
113+ return xl + ["" for _ in range (1000 - len (xl ))]
110114
111- def cursesinput (stdscr ,prompt : str ) :
115+ def cursesinput (stdscr ,prompt : str , lines = 1 , maxlen = 0 ) -> str :
112116 """
113- Get a single line input of text from curses. To be used instead of Python standard input()
117+ Get input from the user. Set maxlen to 0 for no maximum
114118 """
115- x ,y = os .get_terminal_size ()
116- stdscr .erase ()
117- stdscr .addstr (0 , 0 , f"{ prompt } (hit Enter to send)" )
118-
119- editwin = curses .newwin (1 ,x - 2 , 2 ,1 )
120- rectangle (stdscr , 1 ,0 , 3 , x - 1 )
121- stdscr .refresh ()
122-
123- box = Textbox (editwin )
124-
125- # Let the user edit until Ctrl-G is struck.
126- box .edit ()
127-
128- # Get resulting contents
129- message = box .gather ()
130- return message [0 :- 1 ]
119+ mx ,my = os .get_terminal_size ()
120+ extoffscr = lines > my - 3
121+ if extoffscr :
122+ lnrectmaxy = my - 2
123+ else :
124+ lnrectmaxy = lines + 2
125+ text : list [list [str ]] = [[] for _ in range (lines )]
126+ ln = 0
127+ col = 0
128+ xoffset = 0
129+ while True :
130+ filline (stdscr ,0 ,set_colour (WHITE ,BLACK ))
131+ stdscr .addstr (0 ,0 ,str (prompt + " (Press ctrl-D to submit)" )[0 :mx - 2 ],set_colour (WHITE ,BLACK ))
132+ rectangle (stdscr ,1 ,0 ,lnrectmaxy ,mx - 1 )
133+ chi = 1
134+ for chln in text :
135+ chi += 1
136+ stdscr .addstr (chi ,1 ,"" .join (chln )[xoffset :xoffset + mx - 3 ])
137+ if xoffset > 0 :
138+ stdscr .addstr (chi ,0 ,"<" ,set_colour (BLUE ,WHITE ))
139+ stdscr .addstr (0 ,mx - 10 ,f"{ ln } ,{ col } " ,set_colour (WHITE ,BLACK ))
140+ stdscr .move (ln + 2 ,col - xoffset + 1 )
141+
142+ stdscr .refresh ()
143+ ch = stdscr .getch ()
144+ chn = curses .keyname (ch )
145+ if ch == 10 or ch == 13 or ch == curses .KEY_ENTER or ch == curses .KEY_DOWN :
146+ if ln == lines - 1 :
147+ curses .beep ()
148+ else :
149+ ln += 1
150+ col = 0
151+ elif ch == curses .KEY_LEFT :
152+ if col > 0 :
153+ col -= 1
154+ if xoffset > 0 :
155+ xoffset -= 1
156+ stdscr .clear ()
157+ else :
158+ curses .beep ()
159+ elif ch == curses .KEY_RIGHT :
160+ if col < len (__retr_nbl_lst (text [ln ])):
161+ col += 1
162+ if col - xoffset > mx - 2 :
163+ xoffset += 1
164+ stdscr .clear ()
165+ else :
166+ curses .beep ()
167+ elif ch == curses .KEY_BACKSPACE :
168+ if col > 0 :
169+ del text [ln ][col - 1 ]
170+ col -= 1
171+ if xoffset > 0 :
172+ xoffset -= 1
173+ stdscr .clear ()#Fix render errors
174+
175+ else :
176+ curses .beep ()
177+ elif ch == curses .KEY_UP :
178+ if ln > 0 :
179+ ln -= 1
180+ col = 0
181+ else :
182+ if len (chn ) > 1 :
183+ #Special char
184+ if chn == b"^D" :
185+ stdscr .erase ()
186+ return "\n " .join (["" .join (t ) for t in text ])
187+ elif chn == b"^K" :
188+ text = [[] for _ in range (lines )]#Delete
189+ ln = 0
190+ col = 0
191+ stdscr .erase ()
192+ else :
193+ curses .beep ()
194+ else :
195+ #append
196+ col += 1
197+ text [ln ].insert (col - 1 ,chn .decode ())
198+
199+ if col > mx - 2 :
200+ xoffset += 1
201+ stdscr .clear ()
202+
131203
132204def displayops (stdscr ,options : list ,title = "Please choose an option" ) -> int :
133205 """Display an options menu provided by options list. ALso displays title. Returns integer value of selected item."""
@@ -172,6 +244,7 @@ def displayops(stdscr,options: list,title="Please choose an option") -> int:
172244 selected += 1
173245 elif _ch == curses .KEY_BACKSPACE or _ch == 98 :
174246 return - 1
247+ stdscr .erase ()
175248
176249def optionmenu (stdscr ,options :list ,title = "Please choose an option and press enter" ) -> int :
177250 """Alias function to displayops()"""
0 commit comments