cs-tty 20260912__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.
- cs_tty-20260912/PKG-INFO +288 -0
- cs_tty-20260912/pyproject.toml +313 -0
- cs_tty-20260912/src/cs/tty.py +339 -0
cs_tty-20260912/PKG-INFO
ADDED
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: cs-tty
|
|
3
|
+
Version: 20260912
|
|
4
|
+
Summary: Functions related to terminals.
|
|
5
|
+
Keywords: python2,python3
|
|
6
|
+
Author-email: Cameron Simpson <cs@cskk.id.au>
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
Classifier: Environment :: Console
|
|
9
|
+
Classifier: Operating System :: POSIX
|
|
10
|
+
Classifier: Programming Language :: Python
|
|
11
|
+
Classifier: Programming Language :: Python :: 2
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Topic :: Terminals
|
|
14
|
+
Classifier: Development Status :: 4 - Beta
|
|
15
|
+
Classifier: Intended Audience :: Developers
|
|
16
|
+
Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
|
|
17
|
+
Requires-Dist: cs.gimmicks>=20260311
|
|
18
|
+
Project-URL: MonoRepo Commits, https://bitbucket.org/cameron_simpson/css/commits/branch/main
|
|
19
|
+
Project-URL: Monorepo Git Mirror, https://github.com/cameron-simpson/css
|
|
20
|
+
Project-URL: Monorepo Hg/Mercurial Mirror, https://hg.sr.ht/~cameron-simpson/css
|
|
21
|
+
Project-URL: Source, https://github.com/cameron-simpson/css/blob/main/lib/python/cs/tty.py
|
|
22
|
+
|
|
23
|
+
Functions related to terminals.
|
|
24
|
+
|
|
25
|
+
*Latest release 20260912*:
|
|
26
|
+
New ttysizepx(fd) function returning the tty size in characters and pixels.
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
Short summary:
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
* `modify_termios`: Apply mode changes to a tty. Return the previous tty modes as from `termios.tcgetattr` or `None` if the changes could not be applied. If `strict`, raise an exception instead of returning `None`.
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
* `setupterm`: Run curses.setupterm, needed to be able to use the status line. Uses a global flag to avoid doing this twice.
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
* `stack_termios`: Context manager to apply and restore changes to a tty. Yield the previous tty modes as from `termios.tcgetattr` or `None` if the changes could not be applied. If `strict`, raise an exception instead of yielding `None`.
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
* `status`: Write a message to the terminal's status line.
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
* `statusline`: Update the status line.
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
* `statusline_bs`: Return a byte string to update the status line.
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
* `ttysize`: Return a (rows, columns) tuple for the specified file descriptor.
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
* `ttysizepx`: Return a `(rows,columns,widthpx,heightpx)` tuple for the specified file descriptor being the terminal character rows and columns and pixel width and height respectively.
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
* `WinSize`: WinSize(rows, columns).
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
* `WinSizePX`: WinSizePX(rows, columns, widthpx, heightpx).
|
|
61
|
+
|
|
62
|
+
# Functions
|
|
63
|
+
|
|
64
|
+
## modify_termios(fd=0, set_modes=None, clear_modes=None, strict=False)
|
|
65
|
+
|
|
66
|
+
Apply mode changes to a tty.
|
|
67
|
+
Return the previous tty modes as from `termios.tcgetattr`
|
|
68
|
+
or `None` if the changes could not be applied.
|
|
69
|
+
If `strict`, raise an exception instead of returning `None`.
|
|
70
|
+
|
|
71
|
+
Parameters:
|
|
72
|
+
* `fd`: optional tty file descriptor, default `0`.
|
|
73
|
+
* `set_modes`: an optional mapping of attribute name to new value
|
|
74
|
+
for values to set
|
|
75
|
+
* `clear_modes`: an optional mapping of attribute name to new value
|
|
76
|
+
for values to clear
|
|
77
|
+
* `strict`: optional flag, default `False`;
|
|
78
|
+
if true, raise exceptions from failed `tcgetattr` and `tcsetattr` calls
|
|
79
|
+
otherwise issue a warning if the errno is not `ENOTTY` and proceed.
|
|
80
|
+
This aims to provide ease of use in batch mode by default
|
|
81
|
+
while providing a mode to fail overtly if required.
|
|
82
|
+
|
|
83
|
+
The attribute names are from
|
|
84
|
+
`iflag`, `oflag`, `cflag`, `lflag`, `ispeed`, `ospeed`, `cc`,
|
|
85
|
+
corresponding to the list entries defined by the `termios.tcgetattr`
|
|
86
|
+
call.
|
|
87
|
+
|
|
88
|
+
For `set_modes`, the attributes `ispeed`, `ospeed` and `cc`
|
|
89
|
+
are applied directly;
|
|
90
|
+
the other attributes are binary ORed into the existing modes.
|
|
91
|
+
|
|
92
|
+
For `clear_modes`, the attributes `ispeed`, `ospeed` and `cc`
|
|
93
|
+
cannot be cleared;
|
|
94
|
+
the other attributes are binary removed from the existing modes.
|
|
95
|
+
|
|
96
|
+
For example, to turn off the terminal echo during some operation:
|
|
97
|
+
|
|
98
|
+
old_modes = apply_termios(clear_modes={'lflag': termios.ECHO}):
|
|
99
|
+
... do something with tty echo disabled ...
|
|
100
|
+
if old_modes:
|
|
101
|
+
termios.tcsetattr(fd, termios.TCSANOW, old_modes)
|
|
102
|
+
|
|
103
|
+
## setupterm(*args)
|
|
104
|
+
|
|
105
|
+
Run curses.setupterm, needed to be able to use the status line.
|
|
106
|
+
Uses a global flag to avoid doing this twice.
|
|
107
|
+
|
|
108
|
+
## stack_termios(fd=0, set_modes=None, clear_modes=None, strict=False)
|
|
109
|
+
|
|
110
|
+
Context manager to apply and restore changes to a tty.
|
|
111
|
+
Yield the previous tty modes as from `termios.tcgetattr`
|
|
112
|
+
or `None` if the changes could not be applied.
|
|
113
|
+
If `strict`, raise an exception instead of yielding `None`.
|
|
114
|
+
|
|
115
|
+
Parameters:
|
|
116
|
+
* `fd`: optional tty file descriptor, default `0`.
|
|
117
|
+
* `set_modes`: an optional mapping of attribute name to new value
|
|
118
|
+
for values to set
|
|
119
|
+
* `clear_modes`: an optional mapping of attribute name to new value
|
|
120
|
+
for values to clear
|
|
121
|
+
* `strict`: optional flag, default `False`;
|
|
122
|
+
if true, raise exceptions from failed `tcgetattr` and `tcsetattr` calls
|
|
123
|
+
otherwise issue a warning if the errno is not `ENOTTY` and proceed.
|
|
124
|
+
This aims to provide ease of use in batch mode by default
|
|
125
|
+
while providing a mode to fail overtly if required.
|
|
126
|
+
|
|
127
|
+
The attribute names are from
|
|
128
|
+
`iflag`, `oflag`, `cflag`, `lflag`, `ispeed`, `ospeed`, `cc`,
|
|
129
|
+
corresponding to the list entries defined by the `termios.tcgetattr`
|
|
130
|
+
call.
|
|
131
|
+
|
|
132
|
+
For `set_modes`, the attributes `ispeed`, `ospeed` and `cc`
|
|
133
|
+
are applied directly;
|
|
134
|
+
the other attributes are binary ORed into the existing modes.
|
|
135
|
+
|
|
136
|
+
For `clear_modes`, the attributes `ispeed`, `ospeed` and `cc`
|
|
137
|
+
cannot be cleared;
|
|
138
|
+
the other attributes are binary removed from the existing modes.
|
|
139
|
+
|
|
140
|
+
For example, to turn off the terminal echo during some operation:
|
|
141
|
+
|
|
142
|
+
with stack_termios(clear_modes={'lflag': termios.ECHO}):
|
|
143
|
+
... do something with tty echo disabled ...
|
|
144
|
+
|
|
145
|
+
## status(msg, *args, **kwargs)
|
|
146
|
+
|
|
147
|
+
Write a message to the terminal's status line.
|
|
148
|
+
|
|
149
|
+
Parameters:
|
|
150
|
+
* `msg`: message string
|
|
151
|
+
* `args`: if not empty, the message is %-formatted with `args`
|
|
152
|
+
* `file`: optional keyword argument specifying the output file.
|
|
153
|
+
Default: `sys.stderr`.
|
|
154
|
+
|
|
155
|
+
Hack: if there is no status line use the xterm title bar sequence :-(
|
|
156
|
+
|
|
157
|
+
## statusline(text, fd=None, reverse=False, xpos=None, ypos=None)
|
|
158
|
+
|
|
159
|
+
Update the status line.
|
|
160
|
+
|
|
161
|
+
## statusline_bs(text, reverse=False, xpos=None, ypos=None)
|
|
162
|
+
|
|
163
|
+
Return a byte string to update the status line.
|
|
164
|
+
|
|
165
|
+
## ttysize(fd)
|
|
166
|
+
|
|
167
|
+
Return a (rows, columns) tuple for the specified file descriptor.
|
|
168
|
+
|
|
169
|
+
If the window size cannot be determined, None will be returned
|
|
170
|
+
for either or both of rows and columns.
|
|
171
|
+
|
|
172
|
+
This function relies on the UNIX `stty` command.
|
|
173
|
+
|
|
174
|
+
## ttysizepx(fd)
|
|
175
|
+
|
|
176
|
+
Return a `(rows,columns,widthpx,heightpx)` tuple for the
|
|
177
|
+
specified file descriptor being the terminal character rows
|
|
178
|
+
and columns and pixel width and height respectively.
|
|
179
|
+
|
|
180
|
+
This function relies on the `fcntl.ioctl` using `termios.TIOCGWINSZ`.
|
|
181
|
+
|
|
182
|
+
# Classes
|
|
183
|
+
|
|
184
|
+
## class WinSize(builtins.tuple)
|
|
185
|
+
|
|
186
|
+
WinSize(rows, columns)
|
|
187
|
+
|
|
188
|
+
### `WinSize.__match_args__`
|
|
189
|
+
|
|
190
|
+
Built-in immutable sequence.
|
|
191
|
+
|
|
192
|
+
If no argument is given, the constructor returns an empty tuple.
|
|
193
|
+
If iterable is specified the tuple is initialized from iterable's items.
|
|
194
|
+
|
|
195
|
+
If the argument is a tuple, the return value is the same object.
|
|
196
|
+
|
|
197
|
+
### `WinSize.__replace__(self, /, **kwds)`
|
|
198
|
+
|
|
199
|
+
Return a new WinSize object replacing specified fields with new values
|
|
200
|
+
|
|
201
|
+
### `WinSize.__slots__`
|
|
202
|
+
|
|
203
|
+
Built-in immutable sequence.
|
|
204
|
+
|
|
205
|
+
If no argument is given, the constructor returns an empty tuple.
|
|
206
|
+
If iterable is specified the tuple is initialized from iterable's items.
|
|
207
|
+
|
|
208
|
+
If the argument is a tuple, the return value is the same object.
|
|
209
|
+
|
|
210
|
+
### `WinSize.columns`
|
|
211
|
+
|
|
212
|
+
Alias for field number 1
|
|
213
|
+
|
|
214
|
+
### `WinSize.rows`
|
|
215
|
+
|
|
216
|
+
Alias for field number 0
|
|
217
|
+
|
|
218
|
+
## class WinSizePX(builtins.tuple)
|
|
219
|
+
|
|
220
|
+
WinSizePX(rows, columns, widthpx, heightpx)
|
|
221
|
+
|
|
222
|
+
### `WinSizePX.__match_args__`
|
|
223
|
+
|
|
224
|
+
Built-in immutable sequence.
|
|
225
|
+
|
|
226
|
+
If no argument is given, the constructor returns an empty tuple.
|
|
227
|
+
If iterable is specified the tuple is initialized from iterable's items.
|
|
228
|
+
|
|
229
|
+
If the argument is a tuple, the return value is the same object.
|
|
230
|
+
|
|
231
|
+
### `WinSizePX.__replace__(self, /, **kwds)`
|
|
232
|
+
|
|
233
|
+
Return a new WinSizePX object replacing specified fields with new values
|
|
234
|
+
|
|
235
|
+
### `WinSizePX.__slots__`
|
|
236
|
+
|
|
237
|
+
Built-in immutable sequence.
|
|
238
|
+
|
|
239
|
+
If no argument is given, the constructor returns an empty tuple.
|
|
240
|
+
If iterable is specified the tuple is initialized from iterable's items.
|
|
241
|
+
|
|
242
|
+
If the argument is a tuple, the return value is the same object.
|
|
243
|
+
|
|
244
|
+
### `WinSizePX.columns`
|
|
245
|
+
|
|
246
|
+
Alias for field number 1
|
|
247
|
+
|
|
248
|
+
### `WinSizePX.heightpx`
|
|
249
|
+
|
|
250
|
+
Alias for field number 3
|
|
251
|
+
|
|
252
|
+
### `WinSizePX.rows`
|
|
253
|
+
|
|
254
|
+
Alias for field number 0
|
|
255
|
+
|
|
256
|
+
### `WinSizePX.widthpx`
|
|
257
|
+
|
|
258
|
+
Alias for field number 2
|
|
259
|
+
|
|
260
|
+
# Release Log
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
*Release 20260912*:
|
|
265
|
+
New ttysizepx(fd) function returning the tty size in characters and pixels.
|
|
266
|
+
|
|
267
|
+
*Release 20210316*:
|
|
268
|
+
* ttysize: discard the Popen object earlier.
|
|
269
|
+
* ttysize: close Popen.stdout after use. seems to leak.
|
|
270
|
+
|
|
271
|
+
*Release 20201102*:
|
|
272
|
+
New modify_termios and stack_termios to apply (and restore) termios modes.
|
|
273
|
+
|
|
274
|
+
*Release 20200521*:
|
|
275
|
+
* New status() function dragged in from cs.logutils, which uses cs.upd for status() -- needs some refactoring to match with the other functions in cs.tty -- text vs bytes, stdout vs stderr, etc.
|
|
276
|
+
* Get warning() from cs.gimmicks.
|
|
277
|
+
|
|
278
|
+
*Release 20190101*:
|
|
279
|
+
Small bugfix for setupterm.
|
|
280
|
+
|
|
281
|
+
*Release 20170903*:
|
|
282
|
+
add statusline and statusline_s functions; ttysize: support BSD stty output format
|
|
283
|
+
|
|
284
|
+
*Release 20160828*:
|
|
285
|
+
Use "install_requires" instead of "requires" in DISTINFO, add PyPI category.
|
|
286
|
+
|
|
287
|
+
*Release 20150116*:
|
|
288
|
+
Initial PyPI release.
|
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "cs-tty"
|
|
3
|
+
description = "Functions related to terminals."
|
|
4
|
+
authors = [
|
|
5
|
+
{ name = "Cameron Simpson", email = "cs@cskk.id.au" },
|
|
6
|
+
]
|
|
7
|
+
keywords = [
|
|
8
|
+
"python2",
|
|
9
|
+
"python3",
|
|
10
|
+
]
|
|
11
|
+
dependencies = [
|
|
12
|
+
"cs.gimmicks>=20260311",
|
|
13
|
+
]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Environment :: Console",
|
|
16
|
+
"Operating System :: POSIX",
|
|
17
|
+
"Programming Language :: Python",
|
|
18
|
+
"Programming Language :: Python :: 2",
|
|
19
|
+
"Programming Language :: Python :: 3",
|
|
20
|
+
"Topic :: Terminals",
|
|
21
|
+
"Development Status :: 4 - Beta",
|
|
22
|
+
"Intended Audience :: Developers",
|
|
23
|
+
"License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)",
|
|
24
|
+
]
|
|
25
|
+
version = "20260912"
|
|
26
|
+
|
|
27
|
+
[project.license]
|
|
28
|
+
text = "GNU General Public License v3 or later (GPLv3+)"
|
|
29
|
+
|
|
30
|
+
[project.urls]
|
|
31
|
+
"Monorepo Hg/Mercurial Mirror" = "https://hg.sr.ht/~cameron-simpson/css"
|
|
32
|
+
"Monorepo Git Mirror" = "https://github.com/cameron-simpson/css"
|
|
33
|
+
"MonoRepo Commits" = "https://bitbucket.org/cameron_simpson/css/commits/branch/main"
|
|
34
|
+
Source = "https://github.com/cameron-simpson/css/blob/main/lib/python/cs/tty.py"
|
|
35
|
+
|
|
36
|
+
[project.readme]
|
|
37
|
+
text = """
|
|
38
|
+
Functions related to terminals.
|
|
39
|
+
|
|
40
|
+
*Latest release 20260912*:
|
|
41
|
+
New ttysizepx(fd) function returning the tty size in characters and pixels.
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
Short summary:
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
* `modify_termios`: Apply mode changes to a tty. Return the previous tty modes as from `termios.tcgetattr` or `None` if the changes could not be applied. If `strict`, raise an exception instead of returning `None`.
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
* `setupterm`: Run curses.setupterm, needed to be able to use the status line. Uses a global flag to avoid doing this twice.
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
* `stack_termios`: Context manager to apply and restore changes to a tty. Yield the previous tty modes as from `termios.tcgetattr` or `None` if the changes could not be applied. If `strict`, raise an exception instead of yielding `None`.
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
* `status`: Write a message to the terminal's status line.
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
* `statusline`: Update the status line.
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
* `statusline_bs`: Return a byte string to update the status line.
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
* `ttysize`: Return a (rows, columns) tuple for the specified file descriptor.
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
* `ttysizepx`: Return a `(rows,columns,widthpx,heightpx)` tuple for the specified file descriptor being the terminal character rows and columns and pixel width and height respectively.
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
* `WinSize`: WinSize(rows, columns).
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
* `WinSizePX`: WinSizePX(rows, columns, widthpx, heightpx).
|
|
76
|
+
|
|
77
|
+
# Functions
|
|
78
|
+
|
|
79
|
+
## modify_termios(fd=0, set_modes=None, clear_modes=None, strict=False)
|
|
80
|
+
|
|
81
|
+
Apply mode changes to a tty.
|
|
82
|
+
Return the previous tty modes as from `termios.tcgetattr`
|
|
83
|
+
or `None` if the changes could not be applied.
|
|
84
|
+
If `strict`, raise an exception instead of returning `None`.
|
|
85
|
+
|
|
86
|
+
Parameters:
|
|
87
|
+
* `fd`: optional tty file descriptor, default `0`.
|
|
88
|
+
* `set_modes`: an optional mapping of attribute name to new value
|
|
89
|
+
for values to set
|
|
90
|
+
* `clear_modes`: an optional mapping of attribute name to new value
|
|
91
|
+
for values to clear
|
|
92
|
+
* `strict`: optional flag, default `False`;
|
|
93
|
+
if true, raise exceptions from failed `tcgetattr` and `tcsetattr` calls
|
|
94
|
+
otherwise issue a warning if the errno is not `ENOTTY` and proceed.
|
|
95
|
+
This aims to provide ease of use in batch mode by default
|
|
96
|
+
while providing a mode to fail overtly if required.
|
|
97
|
+
|
|
98
|
+
The attribute names are from
|
|
99
|
+
`iflag`, `oflag`, `cflag`, `lflag`, `ispeed`, `ospeed`, `cc`,
|
|
100
|
+
corresponding to the list entries defined by the `termios.tcgetattr`
|
|
101
|
+
call.
|
|
102
|
+
|
|
103
|
+
For `set_modes`, the attributes `ispeed`, `ospeed` and `cc`
|
|
104
|
+
are applied directly;
|
|
105
|
+
the other attributes are binary ORed into the existing modes.
|
|
106
|
+
|
|
107
|
+
For `clear_modes`, the attributes `ispeed`, `ospeed` and `cc`
|
|
108
|
+
cannot be cleared;
|
|
109
|
+
the other attributes are binary removed from the existing modes.
|
|
110
|
+
|
|
111
|
+
For example, to turn off the terminal echo during some operation:
|
|
112
|
+
|
|
113
|
+
old_modes = apply_termios(clear_modes={'lflag': termios.ECHO}):
|
|
114
|
+
... do something with tty echo disabled ...
|
|
115
|
+
if old_modes:
|
|
116
|
+
termios.tcsetattr(fd, termios.TCSANOW, old_modes)
|
|
117
|
+
|
|
118
|
+
## setupterm(*args)
|
|
119
|
+
|
|
120
|
+
Run curses.setupterm, needed to be able to use the status line.
|
|
121
|
+
Uses a global flag to avoid doing this twice.
|
|
122
|
+
|
|
123
|
+
## stack_termios(fd=0, set_modes=None, clear_modes=None, strict=False)
|
|
124
|
+
|
|
125
|
+
Context manager to apply and restore changes to a tty.
|
|
126
|
+
Yield the previous tty modes as from `termios.tcgetattr`
|
|
127
|
+
or `None` if the changes could not be applied.
|
|
128
|
+
If `strict`, raise an exception instead of yielding `None`.
|
|
129
|
+
|
|
130
|
+
Parameters:
|
|
131
|
+
* `fd`: optional tty file descriptor, default `0`.
|
|
132
|
+
* `set_modes`: an optional mapping of attribute name to new value
|
|
133
|
+
for values to set
|
|
134
|
+
* `clear_modes`: an optional mapping of attribute name to new value
|
|
135
|
+
for values to clear
|
|
136
|
+
* `strict`: optional flag, default `False`;
|
|
137
|
+
if true, raise exceptions from failed `tcgetattr` and `tcsetattr` calls
|
|
138
|
+
otherwise issue a warning if the errno is not `ENOTTY` and proceed.
|
|
139
|
+
This aims to provide ease of use in batch mode by default
|
|
140
|
+
while providing a mode to fail overtly if required.
|
|
141
|
+
|
|
142
|
+
The attribute names are from
|
|
143
|
+
`iflag`, `oflag`, `cflag`, `lflag`, `ispeed`, `ospeed`, `cc`,
|
|
144
|
+
corresponding to the list entries defined by the `termios.tcgetattr`
|
|
145
|
+
call.
|
|
146
|
+
|
|
147
|
+
For `set_modes`, the attributes `ispeed`, `ospeed` and `cc`
|
|
148
|
+
are applied directly;
|
|
149
|
+
the other attributes are binary ORed into the existing modes.
|
|
150
|
+
|
|
151
|
+
For `clear_modes`, the attributes `ispeed`, `ospeed` and `cc`
|
|
152
|
+
cannot be cleared;
|
|
153
|
+
the other attributes are binary removed from the existing modes.
|
|
154
|
+
|
|
155
|
+
For example, to turn off the terminal echo during some operation:
|
|
156
|
+
|
|
157
|
+
with stack_termios(clear_modes={'lflag': termios.ECHO}):
|
|
158
|
+
... do something with tty echo disabled ...
|
|
159
|
+
|
|
160
|
+
## status(msg, *args, **kwargs)
|
|
161
|
+
|
|
162
|
+
Write a message to the terminal's status line.
|
|
163
|
+
|
|
164
|
+
Parameters:
|
|
165
|
+
* `msg`: message string
|
|
166
|
+
* `args`: if not empty, the message is %-formatted with `args`
|
|
167
|
+
* `file`: optional keyword argument specifying the output file.
|
|
168
|
+
Default: `sys.stderr`.
|
|
169
|
+
|
|
170
|
+
Hack: if there is no status line use the xterm title bar sequence :-(
|
|
171
|
+
|
|
172
|
+
## statusline(text, fd=None, reverse=False, xpos=None, ypos=None)
|
|
173
|
+
|
|
174
|
+
Update the status line.
|
|
175
|
+
|
|
176
|
+
## statusline_bs(text, reverse=False, xpos=None, ypos=None)
|
|
177
|
+
|
|
178
|
+
Return a byte string to update the status line.
|
|
179
|
+
|
|
180
|
+
## ttysize(fd)
|
|
181
|
+
|
|
182
|
+
Return a (rows, columns) tuple for the specified file descriptor.
|
|
183
|
+
|
|
184
|
+
If the window size cannot be determined, None will be returned
|
|
185
|
+
for either or both of rows and columns.
|
|
186
|
+
|
|
187
|
+
This function relies on the UNIX `stty` command.
|
|
188
|
+
|
|
189
|
+
## ttysizepx(fd)
|
|
190
|
+
|
|
191
|
+
Return a `(rows,columns,widthpx,heightpx)` tuple for the
|
|
192
|
+
specified file descriptor being the terminal character rows
|
|
193
|
+
and columns and pixel width and height respectively.
|
|
194
|
+
|
|
195
|
+
This function relies on the `fcntl.ioctl` using `termios.TIOCGWINSZ`.
|
|
196
|
+
|
|
197
|
+
# Classes
|
|
198
|
+
|
|
199
|
+
## class WinSize(builtins.tuple)
|
|
200
|
+
|
|
201
|
+
WinSize(rows, columns)
|
|
202
|
+
|
|
203
|
+
### `WinSize.__match_args__`
|
|
204
|
+
|
|
205
|
+
Built-in immutable sequence.
|
|
206
|
+
|
|
207
|
+
If no argument is given, the constructor returns an empty tuple.
|
|
208
|
+
If iterable is specified the tuple is initialized from iterable's items.
|
|
209
|
+
|
|
210
|
+
If the argument is a tuple, the return value is the same object.
|
|
211
|
+
|
|
212
|
+
### `WinSize.__replace__(self, /, **kwds)`
|
|
213
|
+
|
|
214
|
+
Return a new WinSize object replacing specified fields with new values
|
|
215
|
+
|
|
216
|
+
### `WinSize.__slots__`
|
|
217
|
+
|
|
218
|
+
Built-in immutable sequence.
|
|
219
|
+
|
|
220
|
+
If no argument is given, the constructor returns an empty tuple.
|
|
221
|
+
If iterable is specified the tuple is initialized from iterable's items.
|
|
222
|
+
|
|
223
|
+
If the argument is a tuple, the return value is the same object.
|
|
224
|
+
|
|
225
|
+
### `WinSize.columns`
|
|
226
|
+
|
|
227
|
+
Alias for field number 1
|
|
228
|
+
|
|
229
|
+
### `WinSize.rows`
|
|
230
|
+
|
|
231
|
+
Alias for field number 0
|
|
232
|
+
|
|
233
|
+
## class WinSizePX(builtins.tuple)
|
|
234
|
+
|
|
235
|
+
WinSizePX(rows, columns, widthpx, heightpx)
|
|
236
|
+
|
|
237
|
+
### `WinSizePX.__match_args__`
|
|
238
|
+
|
|
239
|
+
Built-in immutable sequence.
|
|
240
|
+
|
|
241
|
+
If no argument is given, the constructor returns an empty tuple.
|
|
242
|
+
If iterable is specified the tuple is initialized from iterable's items.
|
|
243
|
+
|
|
244
|
+
If the argument is a tuple, the return value is the same object.
|
|
245
|
+
|
|
246
|
+
### `WinSizePX.__replace__(self, /, **kwds)`
|
|
247
|
+
|
|
248
|
+
Return a new WinSizePX object replacing specified fields with new values
|
|
249
|
+
|
|
250
|
+
### `WinSizePX.__slots__`
|
|
251
|
+
|
|
252
|
+
Built-in immutable sequence.
|
|
253
|
+
|
|
254
|
+
If no argument is given, the constructor returns an empty tuple.
|
|
255
|
+
If iterable is specified the tuple is initialized from iterable's items.
|
|
256
|
+
|
|
257
|
+
If the argument is a tuple, the return value is the same object.
|
|
258
|
+
|
|
259
|
+
### `WinSizePX.columns`
|
|
260
|
+
|
|
261
|
+
Alias for field number 1
|
|
262
|
+
|
|
263
|
+
### `WinSizePX.heightpx`
|
|
264
|
+
|
|
265
|
+
Alias for field number 3
|
|
266
|
+
|
|
267
|
+
### `WinSizePX.rows`
|
|
268
|
+
|
|
269
|
+
Alias for field number 0
|
|
270
|
+
|
|
271
|
+
### `WinSizePX.widthpx`
|
|
272
|
+
|
|
273
|
+
Alias for field number 2
|
|
274
|
+
|
|
275
|
+
# Release Log
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
|
|
279
|
+
*Release 20260912*:
|
|
280
|
+
New ttysizepx(fd) function returning the tty size in characters and pixels.
|
|
281
|
+
|
|
282
|
+
*Release 20210316*:
|
|
283
|
+
* ttysize: discard the Popen object earlier.
|
|
284
|
+
* ttysize: close Popen.stdout after use. seems to leak.
|
|
285
|
+
|
|
286
|
+
*Release 20201102*:
|
|
287
|
+
New modify_termios and stack_termios to apply (and restore) termios modes.
|
|
288
|
+
|
|
289
|
+
*Release 20200521*:
|
|
290
|
+
* New status() function dragged in from cs.logutils, which uses cs.upd for status() -- needs some refactoring to match with the other functions in cs.tty -- text vs bytes, stdout vs stderr, etc.
|
|
291
|
+
* Get warning() from cs.gimmicks.
|
|
292
|
+
|
|
293
|
+
*Release 20190101*:
|
|
294
|
+
Small bugfix for setupterm.
|
|
295
|
+
|
|
296
|
+
*Release 20170903*:
|
|
297
|
+
add statusline and statusline_s functions; ttysize: support BSD stty output format
|
|
298
|
+
|
|
299
|
+
*Release 20160828*:
|
|
300
|
+
Use \"install_requires\" instead of \"requires\" in DISTINFO, add PyPI category.
|
|
301
|
+
|
|
302
|
+
*Release 20150116*:
|
|
303
|
+
Initial PyPI release."""
|
|
304
|
+
content-type = "text/markdown"
|
|
305
|
+
|
|
306
|
+
[build-system]
|
|
307
|
+
build-backend = "flit_core.buildapi"
|
|
308
|
+
requires = [
|
|
309
|
+
"flit_core >=3.2,<4",
|
|
310
|
+
]
|
|
311
|
+
|
|
312
|
+
[tool.flit.module]
|
|
313
|
+
name = "cs.tty"
|
|
@@ -0,0 +1,339 @@
|
|
|
1
|
+
#!/usr/bin/python
|
|
2
|
+
#
|
|
3
|
+
# Facilities for terminals.
|
|
4
|
+
# - Cameron Simpson <cs@cskk.id.au>
|
|
5
|
+
#
|
|
6
|
+
|
|
7
|
+
''' Functions related to terminals.
|
|
8
|
+
'''
|
|
9
|
+
|
|
10
|
+
from __future__ import print_function
|
|
11
|
+
import array
|
|
12
|
+
from collections import namedtuple
|
|
13
|
+
from contextlib import contextmanager
|
|
14
|
+
import errno
|
|
15
|
+
import fcntl
|
|
16
|
+
import os
|
|
17
|
+
import re
|
|
18
|
+
from subprocess import Popen, PIPE
|
|
19
|
+
import sys
|
|
20
|
+
from termios import tcsetattr, tcgetattr, TCSANOW, TIOCGWINSZ
|
|
21
|
+
from cs.gimmicks import warning
|
|
22
|
+
|
|
23
|
+
__version__ = '20260912'
|
|
24
|
+
|
|
25
|
+
DISTINFO = {
|
|
26
|
+
'keywords': ["python2", "python3"],
|
|
27
|
+
'classifiers': [
|
|
28
|
+
"Environment :: Console",
|
|
29
|
+
"Operating System :: POSIX",
|
|
30
|
+
"Programming Language :: Python",
|
|
31
|
+
"Programming Language :: Python :: 2",
|
|
32
|
+
"Programming Language :: Python :: 3",
|
|
33
|
+
"Topic :: Terminals",
|
|
34
|
+
],
|
|
35
|
+
'install_requires': ['cs.gimmicks'],
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
WinSize = namedtuple('WinSize', 'rows columns')
|
|
39
|
+
|
|
40
|
+
def ttysize(fd):
|
|
41
|
+
''' Return a (rows, columns) tuple for the specified file descriptor.
|
|
42
|
+
|
|
43
|
+
If the window size cannot be determined, None will be returned
|
|
44
|
+
for either or both of rows and columns.
|
|
45
|
+
|
|
46
|
+
This function relies on the UNIX `stty` command.
|
|
47
|
+
'''
|
|
48
|
+
if not isinstance(fd, int):
|
|
49
|
+
fd = fd.fileno()
|
|
50
|
+
P = Popen(['stty', '-a'], stdin=fd, stdout=PIPE, universal_newlines=True)
|
|
51
|
+
stty = P.stdout.read()
|
|
52
|
+
P.stdout.close()
|
|
53
|
+
xit = P.wait()
|
|
54
|
+
del P
|
|
55
|
+
if xit != 0:
|
|
56
|
+
return None
|
|
57
|
+
m = re.compile(r' rows (\d+); columns (\d+)').search(stty)
|
|
58
|
+
if m:
|
|
59
|
+
rows, columns = int(m.group(1)), int(m.group(2))
|
|
60
|
+
else:
|
|
61
|
+
m = re.compile(r' (\d+) rows; (\d+) columns').search(stty)
|
|
62
|
+
if m:
|
|
63
|
+
rows, columns = int(m.group(1)), int(m.group(2))
|
|
64
|
+
else:
|
|
65
|
+
rows, columns = None, None
|
|
66
|
+
return WinSize(rows, columns)
|
|
67
|
+
|
|
68
|
+
WinSizePX = namedtuple('WinSizePX', 'rows columns widthpx heightpx')
|
|
69
|
+
|
|
70
|
+
def ttysizepx(fd):
|
|
71
|
+
''' Return a `(rows,columns,widthpx,heightpx)` tuple for the
|
|
72
|
+
specified file descriptor being the terminal character rows
|
|
73
|
+
and columns and pixel width and height respectively.
|
|
74
|
+
|
|
75
|
+
This function relies on the `fcntl.ioctl` using `termios.TIOCGWINSZ`.
|
|
76
|
+
'''
|
|
77
|
+
if not isinstance(fd, int):
|
|
78
|
+
fd = fd.fileno()
|
|
79
|
+
buf = array.array('H', [0, 0, 0, 0])
|
|
80
|
+
fcntl.ioctl(fd, TIOCGWINSZ, buf)
|
|
81
|
+
return WinSizePX(*buf)
|
|
82
|
+
|
|
83
|
+
_ti_setup = False
|
|
84
|
+
|
|
85
|
+
def setupterm(*args):
|
|
86
|
+
''' Run curses.setupterm, needed to be able to use the status line.
|
|
87
|
+
Uses a global flag to avoid doing this twice.
|
|
88
|
+
'''
|
|
89
|
+
global _ti_setup # pylint: disable=global-statement
|
|
90
|
+
if _ti_setup:
|
|
91
|
+
return True
|
|
92
|
+
termstr = None
|
|
93
|
+
fd = None
|
|
94
|
+
if args:
|
|
95
|
+
args = list(args)
|
|
96
|
+
termstr = args.pop(0)
|
|
97
|
+
if args:
|
|
98
|
+
fd = args.pop(0)
|
|
99
|
+
if args:
|
|
100
|
+
raise ValueError("extra arguments after termstr and fd: %r" % (args,))
|
|
101
|
+
if termstr is None:
|
|
102
|
+
termstr = os.environ['TERM']
|
|
103
|
+
if fd is None:
|
|
104
|
+
fd = sys.stdout.fileno()
|
|
105
|
+
import curses # pylint: disable=import-outside-toplevel
|
|
106
|
+
curses.setupterm(termstr, fd)
|
|
107
|
+
_ti_setup = True
|
|
108
|
+
return True
|
|
109
|
+
|
|
110
|
+
def statusline_bs(text, reverse=False, xpos=None, ypos=None):
|
|
111
|
+
''' Return a byte string to update the status line.
|
|
112
|
+
'''
|
|
113
|
+
from curses import tigetstr, tparm, tigetflag # pylint: disable=import-outside-toplevel
|
|
114
|
+
setupterm()
|
|
115
|
+
if tigetflag('hs'):
|
|
116
|
+
seq = (
|
|
117
|
+
tigetstr('tsl'),
|
|
118
|
+
tigetstr('dsl'),
|
|
119
|
+
tigetstr('rev') if reverse else b'',
|
|
120
|
+
text.encode(),
|
|
121
|
+
tigetstr('fsl'),
|
|
122
|
+
)
|
|
123
|
+
else:
|
|
124
|
+
# save cursor position, position, reverse, restore position
|
|
125
|
+
if xpos is None:
|
|
126
|
+
xpos = 0
|
|
127
|
+
if ypos is None:
|
|
128
|
+
ypos = 0
|
|
129
|
+
seq = (
|
|
130
|
+
tigetstr('sc'), # save cursor position
|
|
131
|
+
tparm(tigetstr("cup"), xpos, ypos),
|
|
132
|
+
tigetstr('rev') if reverse else b'',
|
|
133
|
+
text.encode(),
|
|
134
|
+
tigetstr('el'),
|
|
135
|
+
tigetstr('rc')
|
|
136
|
+
)
|
|
137
|
+
return b''.join(seq)
|
|
138
|
+
|
|
139
|
+
def statusline(text, fd=None, reverse=False, xpos=None, ypos=None):
|
|
140
|
+
''' Update the status line.
|
|
141
|
+
'''
|
|
142
|
+
if fd is None:
|
|
143
|
+
fd = sys.stdout.fileno()
|
|
144
|
+
os.write(fd, statusline_bs(text, reverse=reverse, xpos=xpos, ypos=ypos))
|
|
145
|
+
|
|
146
|
+
def status(msg, *args, **kwargs):
|
|
147
|
+
''' Write a message to the terminal's status line.
|
|
148
|
+
|
|
149
|
+
Parameters:
|
|
150
|
+
* `msg`: message string
|
|
151
|
+
* `args`: if not empty, the message is %-formatted with `args`
|
|
152
|
+
* `file`: optional keyword argument specifying the output file.
|
|
153
|
+
Default: `sys.stderr`.
|
|
154
|
+
|
|
155
|
+
Hack: if there is no status line use the xterm title bar sequence :-(
|
|
156
|
+
'''
|
|
157
|
+
if args:
|
|
158
|
+
msg = msg % args
|
|
159
|
+
f = kwargs.pop('file', None)
|
|
160
|
+
if kwargs:
|
|
161
|
+
raise ValueError("unexpected keyword arguments: %r" % (kwargs,))
|
|
162
|
+
if f is None:
|
|
163
|
+
f = sys.stderr
|
|
164
|
+
try:
|
|
165
|
+
has_ansi_status = f.has_ansi_status
|
|
166
|
+
except AttributeError:
|
|
167
|
+
try:
|
|
168
|
+
import curses # pylint: disable=import-outside-toplevel
|
|
169
|
+
except ImportError:
|
|
170
|
+
has_ansi_status = None
|
|
171
|
+
else:
|
|
172
|
+
curses.setupterm()
|
|
173
|
+
has_status = curses.tigetflag('hs')
|
|
174
|
+
if has_status == -1:
|
|
175
|
+
warning(
|
|
176
|
+
'status: curses.tigetflag(hs): not a Boolean capability, presuming false'
|
|
177
|
+
)
|
|
178
|
+
has_ansi_status = None
|
|
179
|
+
elif has_status > 0:
|
|
180
|
+
has_ansi_status = (
|
|
181
|
+
curses.tigetstr('to_status_line'),
|
|
182
|
+
curses.tigetstr('from_status_line')
|
|
183
|
+
)
|
|
184
|
+
else:
|
|
185
|
+
warning('status: hs=%s, presuming false', has_status)
|
|
186
|
+
has_ansi_status = None
|
|
187
|
+
f.has_ansi_status = has_ansi_status
|
|
188
|
+
if has_ansi_status:
|
|
189
|
+
msg = has_ansi_status[0] + msg + has_ansi_status[1]
|
|
190
|
+
else:
|
|
191
|
+
msg = '\033]0;' + msg + '\007'
|
|
192
|
+
f.write(msg)
|
|
193
|
+
f.flush()
|
|
194
|
+
|
|
195
|
+
_termios_modes_names = {
|
|
196
|
+
name: index
|
|
197
|
+
for index, name in
|
|
198
|
+
enumerate(('iflag', 'oflag', 'cflag', 'lflag', 'ispeed', 'ospeed', 'cc'))
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
# pylint: disable=too-many-branches
|
|
202
|
+
def modify_termios(fd=0, set_modes=None, clear_modes=None, strict=False):
|
|
203
|
+
''' Apply mode changes to a tty.
|
|
204
|
+
Return the previous tty modes as from `termios.tcgetattr`
|
|
205
|
+
or `None` if the changes could not be applied.
|
|
206
|
+
If `strict`, raise an exception instead of returning `None`.
|
|
207
|
+
|
|
208
|
+
Parameters:
|
|
209
|
+
* `fd`: optional tty file descriptor, default `0`.
|
|
210
|
+
* `set_modes`: an optional mapping of attribute name to new value
|
|
211
|
+
for values to set
|
|
212
|
+
* `clear_modes`: an optional mapping of attribute name to new value
|
|
213
|
+
for values to clear
|
|
214
|
+
* `strict`: optional flag, default `False`;
|
|
215
|
+
if true, raise exceptions from failed `tcgetattr` and `tcsetattr` calls
|
|
216
|
+
otherwise issue a warning if the errno is not `ENOTTY` and proceed.
|
|
217
|
+
This aims to provide ease of use in batch mode by default
|
|
218
|
+
while providing a mode to fail overtly if required.
|
|
219
|
+
|
|
220
|
+
The attribute names are from
|
|
221
|
+
`iflag`, `oflag`, `cflag`, `lflag`, `ispeed`, `ospeed`, `cc`,
|
|
222
|
+
corresponding to the list entries defined by the `termios.tcgetattr`
|
|
223
|
+
call.
|
|
224
|
+
|
|
225
|
+
For `set_modes`, the attributes `ispeed`, `ospeed` and `cc`
|
|
226
|
+
are applied directly;
|
|
227
|
+
the other attributes are binary ORed into the existing modes.
|
|
228
|
+
|
|
229
|
+
For `clear_modes`, the attributes `ispeed`, `ospeed` and `cc`
|
|
230
|
+
cannot be cleared;
|
|
231
|
+
the other attributes are binary removed from the existing modes.
|
|
232
|
+
|
|
233
|
+
For example, to turn off the terminal echo during some operation:
|
|
234
|
+
|
|
235
|
+
old_modes = apply_termios(clear_modes={'lflag': termios.ECHO}):
|
|
236
|
+
... do something with tty echo disabled ...
|
|
237
|
+
if old_modes:
|
|
238
|
+
termios.tcsetattr(fd, termios.TCSANOW, old_modes)
|
|
239
|
+
'''
|
|
240
|
+
if set_modes:
|
|
241
|
+
if not all(map(lambda k: k in _termios_modes_names, set_modes.keys())):
|
|
242
|
+
raise ValueError(
|
|
243
|
+
"set_modes: invalid mode keys: known=%r, supplied=%r" %
|
|
244
|
+
(sorted(_termios_modes_names.keys()), set_modes)
|
|
245
|
+
)
|
|
246
|
+
if clear_modes:
|
|
247
|
+
if not all(map(lambda k: k in _termios_modes_names, clear_modes.keys())):
|
|
248
|
+
raise ValueError(
|
|
249
|
+
"clear_modes: invalid mode keys: known=%r, supplied=%r" %
|
|
250
|
+
(sorted(_termios_modes_names.keys()), clear_modes)
|
|
251
|
+
)
|
|
252
|
+
for k in 'ispeed', 'ospeed', 'cc':
|
|
253
|
+
if k in clear_modes:
|
|
254
|
+
raise ValueError("clear_modes: cannot clear %r" % (k,))
|
|
255
|
+
try:
|
|
256
|
+
original_modes = tcgetattr(fd)
|
|
257
|
+
except OSError as e:
|
|
258
|
+
if strict:
|
|
259
|
+
raise
|
|
260
|
+
if e.errno != errno.ENOTTY:
|
|
261
|
+
warning("tcgetattr(%d): %s", fd, e)
|
|
262
|
+
original_modes = None
|
|
263
|
+
restore_modes = None
|
|
264
|
+
if original_modes:
|
|
265
|
+
new_modes = list(original_modes)
|
|
266
|
+
if set_modes:
|
|
267
|
+
for k, v in set_modes.items():
|
|
268
|
+
i = _termios_modes_names[k]
|
|
269
|
+
if k in ('ispeed', 'ospeed', 'cc'):
|
|
270
|
+
new_modes[i] = v
|
|
271
|
+
else:
|
|
272
|
+
new_modes[i] |= v
|
|
273
|
+
if clear_modes:
|
|
274
|
+
for k, v in clear_modes.items():
|
|
275
|
+
i = _termios_modes_names[k]
|
|
276
|
+
new_modes[i] &= ~v
|
|
277
|
+
if new_modes == original_modes:
|
|
278
|
+
restore_modes = None
|
|
279
|
+
else:
|
|
280
|
+
try:
|
|
281
|
+
tcsetattr(fd, TCSANOW, new_modes)
|
|
282
|
+
except OSError as e:
|
|
283
|
+
if strict:
|
|
284
|
+
raise
|
|
285
|
+
warning("tcsetattr(%d,TCSANOW,%r): %e", fd, new_modes, e)
|
|
286
|
+
else:
|
|
287
|
+
restore_modes = original_modes
|
|
288
|
+
return restore_modes
|
|
289
|
+
|
|
290
|
+
@contextmanager
|
|
291
|
+
def stack_termios(fd=0, set_modes=None, clear_modes=None, strict=False):
|
|
292
|
+
''' Context manager to apply and restore changes to a tty.
|
|
293
|
+
Yield the previous tty modes as from `termios.tcgetattr`
|
|
294
|
+
or `None` if the changes could not be applied.
|
|
295
|
+
If `strict`, raise an exception instead of yielding `None`.
|
|
296
|
+
|
|
297
|
+
Parameters:
|
|
298
|
+
* `fd`: optional tty file descriptor, default `0`.
|
|
299
|
+
* `set_modes`: an optional mapping of attribute name to new value
|
|
300
|
+
for values to set
|
|
301
|
+
* `clear_modes`: an optional mapping of attribute name to new value
|
|
302
|
+
for values to clear
|
|
303
|
+
* `strict`: optional flag, default `False`;
|
|
304
|
+
if true, raise exceptions from failed `tcgetattr` and `tcsetattr` calls
|
|
305
|
+
otherwise issue a warning if the errno is not `ENOTTY` and proceed.
|
|
306
|
+
This aims to provide ease of use in batch mode by default
|
|
307
|
+
while providing a mode to fail overtly if required.
|
|
308
|
+
|
|
309
|
+
The attribute names are from
|
|
310
|
+
`iflag`, `oflag`, `cflag`, `lflag`, `ispeed`, `ospeed`, `cc`,
|
|
311
|
+
corresponding to the list entries defined by the `termios.tcgetattr`
|
|
312
|
+
call.
|
|
313
|
+
|
|
314
|
+
For `set_modes`, the attributes `ispeed`, `ospeed` and `cc`
|
|
315
|
+
are applied directly;
|
|
316
|
+
the other attributes are binary ORed into the existing modes.
|
|
317
|
+
|
|
318
|
+
For `clear_modes`, the attributes `ispeed`, `ospeed` and `cc`
|
|
319
|
+
cannot be cleared;
|
|
320
|
+
the other attributes are binary removed from the existing modes.
|
|
321
|
+
|
|
322
|
+
For example, to turn off the terminal echo during some operation:
|
|
323
|
+
|
|
324
|
+
with stack_termios(clear_modes={'lflag': termios.ECHO}):
|
|
325
|
+
... do something with tty echo disabled ...
|
|
326
|
+
'''
|
|
327
|
+
try:
|
|
328
|
+
restore_modes = modify_termios(
|
|
329
|
+
fd, set_modes=set_modes, clear_modes=clear_modes, strict=strict
|
|
330
|
+
)
|
|
331
|
+
yield restore_modes
|
|
332
|
+
finally:
|
|
333
|
+
if restore_modes:
|
|
334
|
+
try:
|
|
335
|
+
tcsetattr(fd, TCSANOW, restore_modes)
|
|
336
|
+
except OSError as e:
|
|
337
|
+
if strict:
|
|
338
|
+
raise
|
|
339
|
+
warning("tcsetattr(%d,TCSANOW,%r): %e", fd, restore_modes, e)
|