PyCtrl
An easy beautiful command line interface add-on for python
main.py
1 """@file main.py
2 Documentation for this module.
3 
4 More details.
5 """
6 import sys, tty, termios
7 
8 
9 def cursorUp(val):
10  """
11  PURPOSE
12 
13  Moves console cursor up by defined value
14 
15  INPUT
16 
17  val -one integer greater than zero
18 
19  RETURNS
20 
21  0 for success and -1 for error
22  """
23  if isinstance(val, int) and val > 0:
24  print_cursor_value(val, "A")
25  return 0
26  return -1
27 
28 
29 def cursorDown(val):
30  """
31  PURPOSE
32 
33  Moves console cursor down by defined value
34 
35  INPUT
36 
37  val -one integer greater than zero
38 
39  RETURNS
40 
41  0 for success and -1 for error
42  """
43  if isinstance(val, int) and val > 0:
44  print_cursor_value(val, "B")
45  return 0
46  return -1
47 
48 
49 def cursorRight(val):
50  """
51  PURPOSE
52 
53  Moves console cursor right by defined value
54 
55  INPUT
56 
57  val -one integer greater than zero
58 
59  RETURNS
60 
61  0 for success and -1 for error
62  """
63  if isinstance(val, int) and val > 0:
64  print_cursor_value(val, "C")
65  return 0
66  return -1
67 
68 
69 def cursorLeft(val):
70  """
71  PURPOSE
72 
73  Moves console cursor left by defined value
74 
75  INPUT
76 
77  val -one integer greater than zero
78 
79  RETURNS
80 
81  0 for success and -1 for error
82  """
83  if isinstance(val, int) and val > 0:
84  print_cursor_value(val, "D")
85  return 0
86  return -1
87 
88 
89 def print_cursor_value(val, letter):
90  """
91  PURPOSE
92 
93  Function designed for printing special @ref ANSI Escape Codes "https://en.wikipedia.org/wiki/ANSI_escape_code#Terminal_input_sequences". The value and letter are concatenated to the escape character before being printed to the console.
94 
95  INPUT
96 
97  val - no verification and validation
98  letter - no verification and validation
99 
100  RETURNS
101 
102  None
103  """
104  unicode_prefix = u"\u001b["
105  print(f'{unicode_prefix}{val}{letter}', end='')
106 
107 
108 def setColor(val):
109  """
110  PURPOSE
111 
112  Defines the console cursor color
113 
114  INPUT
115 
116  val - one string from list (Black, Red, Green, Yellow, Blue, Magenta, Cyan, White, Reset)
117 
118  RETURNS
119 
120  0 for success and -1 for error
121  """
122  if isinstance(val, str):
123  val = val.upper()
124  colors = {"BLACK": "\u001b[30m",
125  "RED": "\u001b[31m",
126  "GREEN": "\u001b[32m",
127  "YELLOW": "\u001b[33m",
128  "BLUE": "\u001b[34m",
129  "MAGENTA": "\u001b[35m",
130  "CYAN": "\u001b[36m",
131  "WHITE": "\u001b[37m",
132  "RESET": "\u001b[0m"}
133  if val in colors.keys():
134  print(colors[val], end="")
135  return 0
136  return -1
137 
138 
139 def printList(arr):
140  """
141  PURPOSE
142 
143  Prints array passed with one element on each line before returning.
144 
145  INPUT
146 
147  arr - array of strings to be printed
148 
149  RETURNS
150 
151  None
152  """
153  for word in arr:
154  print(f" {word}", end="\n\r")
155 
156 
158  """
159  PURPOSE
160 
161  Hide the console cursor.
162 
163  INPUT
164 
165  None
166 
167  RETURNS
168 
169  None
170  """
171  print("\u001b[?25l", end='')
172 
173 
175  """
176  PURPOSE
177 
178  Resets the console cursor to on.
179 
180  INPUT
181 
182  None
183 
184  RETURNS
185 
186  None
187  """
188  print("\u001b[?0l", end='')
189 
190 
191 
192 def onCharUp(cursorColor, position):
193  """
194  PURPOSE
195 
196  @warning {This function is designed to be private, it may be used elswhere if useful hence the lack of attempt to hide}
197 
198  This function sets the curson color as defined on input as well as moving the cursor up as long as the passed position is not currently greater than zero.
199 
200  INPUT
201 
202  cursorColor - Colors defined in setColor
203  position - current cursor position
204 
205  RETURNS
206 
207  position - new position after movement
208  """
209  if position > 0:
210  print(" ", end="")
211  cursorLeft(1)
212  cursorUp(1)
213  setColor(cursorColor)
214  print(">", end="")
215  setColor("Reset")
216  cursorLeft(1)
217  position -= 1
218  return position
219 
220 
221 
222 def onDownChar(arrL, cursorColor, position):
223  """
224  PURPOSE
225 
226  \warning {This function is designed to be private, it may be used elswhere if useful hence the lack of attempt to hide}
227 
228  This function sets the curson color as defined on input as well as moving the cursor down as long as the passed position is not currently at the length of the passed array length.
229 
230  INPUT
231 
232  arrL - Length of array printed
233  cursorColor - Colors defined in setColor
234  position - current cursor position
235 
236  RETURNS
237 
238  position - new position after movement
239  """
240  if position < arrL:
241  print(" ", end="")
242  cursorLeft(1)
243  cursorDown(1)
244  setColor(cursorColor)
245  print(">", end="")
246  setColor("Reset")
247  cursorLeft(1)
248  position += 1
249  return position
250 
251 
253  """
254  PURPOSE
255 
256  Gets single key input from the user
257 
258  INPUT
259 
260  None
261 
262  RETURNS
263 
264  key buffer after press
265  """
266  return ord(sys.stdin.read(1))
267 
268 
269 def singleChoice(arr, cursorColor="Blue", textOrVal="Val"):
270  # save terminal settings
271  fd = sys.stdin.fileno()
272  old_settings = termios.tcgetattr(fd)
273  # set terminal to raw mode
274  tty.setraw(sys.stdin)
275  # read output
276  charIn = 0
277  printList(arr)
278  cursorUp(len(arr))
279 
280  hideCursor()
281  position = 0
282  setColor(cursorColor)
283  print(">", end="")
284  setColor("Reset")
285  cursorLeft(1)
286  enter_not_pressed = charIn != 13
287  while enter_not_pressed:
288  sys.stdout.flush()
289  charIn = get_input_char() # Get input
290  if charIn == 27: # ESC pressed
291  charIn = get_input_char()
292  if charIn == 91: # [ pressed
293  charIn = get_input_char() # Get input
294  if charIn == 65: # Up
295  position = onCharUp(cursorColor, position)
296  elif charIn == 66: # Down
297  position = onDownChar(len(arr)-1, cursorColor, position)
298  enter_not_pressed = charIn != 13
299  cursorDown(len(arr) - position)
300  # Set terminal style back to normal
301  termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
302  resetCursor()
303  if textOrVal.upper() == "TEXT":
304  return arr[position]
305  else:
306  return position
307 
308 
309 def multiChoice(arr, cursorColor="Blue", textOrVal="Val", tickOrCross="T", otherColor="Green"):
310  if (len(tickOrCross) > 1):
311  print("Error: character " + tickOrCross + " Too long")
312  return -1
313  # save terminal settings
314  fd = sys.stdin.fileno()
315  old_settings = termios.tcgetattr(fd)
316  # set terminal to raw mode
317  tty.setraw(sys.stdin)
318  # read output
319  charIn = 0
320  printList(arr)
321  print(" Done", end="\n\r")
322  hideCursor()
323  cursorUp(len(arr) + 1)
324  position = 0
325  setColor(cursorColor)
326  print(">", end="")
327  setColor("Reset")
328  cursorLeft(1)
329  positionList = []
330  ended = False
331  while ended != True: # whilst enter not pressed
332  # draw arrows at selected positions
333  currpos = position
334  cursorUp(position)
335  for i in range(0, len(arr)):
336  if i in positionList:
337  cursorRight(1)
338  if tickOrCross == 'X':
339  setColor("Red")
340  print("✗", end="\r\n")
341  elif tickOrCross == 'T':
342  setColor("Green")
343  print("✓", end="\r\n")
344  else:
345  setColor(otherColor)
346  print(tickOrCross, end="\r\n")
347  setColor("Reset")
348  else:
349  cursorRight(1)
350  print(" ", end="\r\n")
351  cursorUp(len(arr) - currpos)
352 
353  sys.stdout.flush()
354  charIn = ord(sys.stdin.read(1)) # Get input
355 
356  if charIn == 13:#Enter
357  if position == len(arr):
358  ended = True
359  break
360  if position not in positionList:
361  positionList.append(position)
362  else:
363  positionList.remove(position)
364 
365  elif charIn == 27: # ESC pressed
366  charIn = ord(sys.stdin.read(1))
367  if charIn == 91: # [ pressed
368  charIn = ord(sys.stdin.read(1)) # Get input
369  if charIn == 65: # Up
370  position = onCharUp(cursorColor, position)
371  elif charIn == 66: # Down
372  position = onDownChar(len(arr), cursorColor, position)
373  cursorDown(len(arr) - position)
374  print("", end='\n\r')
375  # Set terminal style back to normal
376  termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
377  if textOrVal.upper() == "TEXT":
378  posListText = []
379  for i in positionList:
380  posListText.append(arr[i])
381  return posListText
382  else:
383  return positionList
384 
385 
386 # valArray=["Choice1","Choice2","Choice3"]
387 # print(*multiChoice(valArray,"Red","Text","f","Magenta"), sep='\n')
388 # valArray=["Choice1","Choice2","Choice3"]
389 # print(singleChoice(valArray,"Magenta","Text"),)
def get_input_char()
Definition: main.py:252
def cursorLeft(val)
Definition: main.py:69
def printList(arr)
Definition: main.py:139
def hideCursor()
Definition: main.py:157
def cursorUp(val)
Definition: main.py:9
def cursorDown(val)
Definition: main.py:29
def onDownChar(arrL, cursorColor, position)
Definition: main.py:222
def resetCursor()
Definition: main.py:174
def setColor(val)
Definition: main.py:108
def print_cursor_value(val, letter)
Definition: main.py:89
def onCharUp(cursorColor, position)
Definition: main.py:192
def cursorRight(val)
Definition: main.py:49