wizlib 3.3.3__tar.gz → 3.3.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of wizlib might be problematic. Click here for more details.

@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: wizlib
3
- Version: 3.3.3
3
+ Version: 3.3.4
4
4
  Summary: Framework for flexible and powerful command-line applications
5
5
  License: MIT
6
6
  Author: Steampunk Wizard
@@ -1,10 +1,10 @@
1
1
  [tool.poetry]
2
2
  name = "wizlib"
3
- version = "3.3.3"
3
+ version = "3.3.4"
4
4
  description = "Framework for flexible and powerful command-line applications"
5
5
  authors = ["Steampunk Wizard <wizlib@steampunkwizard.ca>"]
6
6
  license = "MIT"
7
- readme = "README.md"
7
+ readme = "PACKAGE.md"
8
8
 
9
9
  [tool.poetry.dependencies]
10
10
  python = ">=3.11,<3.12"
@@ -6,6 +6,7 @@ import sys
6
6
  import readchar
7
7
 
8
8
  from wizlib.parser import WizArgumentError
9
+ from wizlib.ui.shell import ESC
9
10
 
10
11
 
11
12
  ISATTY = all(s.isatty() for s in (sys.stdin, sys.stdout, sys.stderr))
@@ -19,9 +20,13 @@ def stream():
19
20
  return '' if ISATTY else sys.stdin.read()
20
21
 
21
22
 
22
- def ttyin():
23
+ def ttyin(): # pragma: nocover
23
24
  if ISATTY:
24
- return readchar.readkey()
25
+ key = readchar.readkey()
26
+ # Handle specialized escape sequences
27
+ if key == ESC + '[1;':
28
+ key = key + readchar.readkey() + readchar.readkey()
29
+ return key
25
30
  else:
26
31
  raise WizArgumentError(
27
32
  'Command designed for interactive use')
@@ -38,3 +38,9 @@ class S(StrEnum):
38
38
  MAGENTA = ESC + '[35m'
39
39
  CYAN = ESC + '[36m'
40
40
  CLEAR = ESC + '[2J'
41
+
42
+ # Alternative keys that can be configured in a terminal emulator
43
+ CUSTOM_END = ESC + '[1;5C'
44
+ CUSTOM_BEGINNING = ESC + '[1;5D'
45
+ CUSTOM_RIGHTWORD = ESC + '[1;9C'
46
+ CUSTOM_LEFTWORD = ESC + '[1;9D'
@@ -92,10 +92,7 @@ class ShellLineEditor: # pragma: nocover
92
92
  if key == S.RETURN:
93
93
  break
94
94
  if key.isprintable():
95
- write(S.BOLD + key + self.buf[self.pos:] +
96
- ('\b' * (len(self.buf) - self.pos)) + S.RESET)
97
- self.buf = self.buf[:self.pos] + key + self.buf[self.pos:]
98
- self.pos += 1
95
+ self.write_key(key)
99
96
  self.fillstate = FillState.USER
100
97
  elif (key in [S.BACKSPACE, S.KILL]) and self.has_fill:
101
98
  # Backspace clears the fill
@@ -113,13 +110,13 @@ class ShellLineEditor: # pragma: nocover
113
110
  elif key == S.RIGHT and self.pos < len(self.buf):
114
111
  self.move_right()
115
112
  self.fillstate = FillState.USER
116
- elif key == S.BEGINNING and self.pos > 0:
113
+ elif (key in [S.BEGINNING, S.CUSTOM_BEGINNING]) and self.pos > 0:
117
114
  self.move_beginning()
118
115
  self.fillstate = FillState.USER
119
- elif key == S.END and self.has_fill:
116
+ elif (key in [S.END, S.CUSTOM_END]) and self.has_fill:
120
117
  self.accept_fill()
121
118
  self.fillstate = FillState.USER
122
- elif key == S.END and self.pos < len(self.buf):
119
+ elif (key in [S.END, S.CUSTOM_END]) and self.pos < len(self.buf):
123
120
  self.move_end_buf()
124
121
  self.fillstate = FillState.USER
125
122
  elif key == S.TAB and (choices := self.valid_choices):
@@ -128,13 +125,25 @@ class ShellLineEditor: # pragma: nocover
128
125
  elif key == S.SHIFT_TAB and self.index > -1:
129
126
  self.index = (self.index - 1) % len(self.valid_choices)
130
127
  self.fillstate = FillState.TAB
131
- elif key == S.LEFT_WORD and self.pos > 0:
128
+ elif (key in [S.LEFT_WORD, S.CUSTOM_LEFTWORD]) and self.pos > 0:
132
129
  while (self.pos > 0) and self.is_sep(self.pos - 1):
133
130
  self.move_left()
134
131
  while (self.pos > 0) and not self.is_sep(self.pos - 1):
135
132
  self.move_left()
136
133
  self.fillstate = FillState.USER
137
- elif key == S.RIGHT_WORD and self.pos < len(self.buf):
134
+ elif (key in [S.RIGHT_WORD, S.CUSTOM_RIGHTWORD]) and self.has_fill:
135
+ fill = self.fill
136
+ self.fillstate = FillState.USER
137
+ while fill:
138
+ char = fill[0]
139
+ self.write_key(char)
140
+ fill = fill[1:]
141
+ if char in S.SEPARATORS:
142
+ self.fillstate = FillState.TAB
143
+ self.index = self.valid_choices.index(self.buf + fill)
144
+ break
145
+ elif (key in [S.RIGHT_WORD, S.CUSTOM_RIGHTWORD]) and \
146
+ self.pos < len(self.buf):
138
147
  while (self.pos < len(self.buf)) and self.is_sep(self.pos):
139
148
  self.move_right()
140
149
  while (self.pos < len(self.buf)) and not self.is_sep(self.pos):
@@ -151,6 +160,12 @@ class ShellLineEditor: # pragma: nocover
151
160
  write(S.RETURN)
152
161
  return self.buf
153
162
 
163
+ def write_key(self, key):
164
+ write(S.BOLD + key + self.buf[self.pos:] +
165
+ ('\b' * (len(self.buf) - self.pos)) + S.RESET)
166
+ self.buf = self.buf[:self.pos] + key + self.buf[self.pos:]
167
+ self.pos += 1
168
+
154
169
  def is_sep(self, pos):
155
170
  return (self.buf[pos] in S.SEPARATORS)
156
171
 
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes