ttyscan 0.0.2__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.
@@ -0,0 +1,218 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[codz]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ share/python-wheels/
24
+ *.egg-info/
25
+ .installed.cfg
26
+ *.egg
27
+ MANIFEST
28
+
29
+ # PyInstaller
30
+ # Usually these files are written by a python script from a template
31
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
32
+ *.manifest
33
+ *.spec
34
+
35
+ # Installer logs
36
+ pip-log.txt
37
+ pip-delete-this-directory.txt
38
+
39
+ # Unit test / coverage reports
40
+ htmlcov/
41
+ .tox/
42
+ .nox/
43
+ .coverage
44
+ .coverage.*
45
+ .cache
46
+ nosetests.xml
47
+ coverage.xml
48
+ *.cover
49
+ *.py.cover
50
+ .hypothesis/
51
+ .pytest_cache/
52
+ cover/
53
+
54
+ # Translations
55
+ *.mo
56
+ *.pot
57
+
58
+ # Django stuff:
59
+ *.log
60
+ local_settings.py
61
+ db.sqlite3
62
+ db.sqlite3-journal
63
+
64
+ # Flask stuff:
65
+ instance/
66
+ .webassets-cache
67
+
68
+ # Scrapy stuff:
69
+ .scrapy
70
+
71
+ # Sphinx documentation
72
+ docs/_build/
73
+
74
+ # PyBuilder
75
+ .pybuilder/
76
+ target/
77
+
78
+ # Jupyter Notebook
79
+ .ipynb_checkpoints
80
+
81
+ # IPython
82
+ profile_default/
83
+ ipython_config.py
84
+
85
+ # pyenv
86
+ # For a library or package, you might want to ignore these files since the code is
87
+ # intended to run in multiple environments; otherwise, check them in:
88
+ # .python-version
89
+
90
+ # pipenv
91
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
92
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
93
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
94
+ # install all needed dependencies.
95
+ # Pipfile.lock
96
+
97
+ # UV
98
+ # Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
99
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
100
+ # commonly ignored for libraries.
101
+ # uv.lock
102
+
103
+ # poetry
104
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
105
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
106
+ # commonly ignored for libraries.
107
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
108
+ # poetry.lock
109
+ # poetry.toml
110
+
111
+ # pdm
112
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
113
+ # pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python.
114
+ # https://pdm-project.org/en/latest/usage/project/#working-with-version-control
115
+ # pdm.lock
116
+ # pdm.toml
117
+ .pdm-python
118
+ .pdm-build/
119
+
120
+ # pixi
121
+ # Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control.
122
+ # pixi.lock
123
+ # Pixi creates a virtual environment in the .pixi directory, just like venv module creates one
124
+ # in the .venv directory. It is recommended not to include this directory in version control.
125
+ .pixi
126
+
127
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
128
+ __pypackages__/
129
+
130
+ # Celery stuff
131
+ celerybeat-schedule
132
+ celerybeat.pid
133
+
134
+ # Redis
135
+ *.rdb
136
+ *.aof
137
+ *.pid
138
+
139
+ # RabbitMQ
140
+ mnesia/
141
+ rabbitmq/
142
+ rabbitmq-data/
143
+
144
+ # ActiveMQ
145
+ activemq-data/
146
+
147
+ # SageMath parsed files
148
+ *.sage.py
149
+
150
+ # Environments
151
+ .env
152
+ .envrc
153
+ .venv
154
+ env/
155
+ venv/
156
+ ENV/
157
+ env.bak/
158
+ venv.bak/
159
+
160
+ # Spyder project settings
161
+ .spyderproject
162
+ .spyproject
163
+
164
+ # Rope project settings
165
+ .ropeproject
166
+
167
+ # mkdocs documentation
168
+ /site
169
+
170
+ # mypy
171
+ .mypy_cache/
172
+ .dmypy.json
173
+ dmypy.json
174
+
175
+ # Pyre type checker
176
+ .pyre/
177
+
178
+ # pytype static type analyzer
179
+ .pytype/
180
+
181
+ # Cython debug symbols
182
+ cython_debug/
183
+
184
+ # PyCharm
185
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
186
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
187
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
188
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
189
+ # .idea/
190
+
191
+ # Abstra
192
+ # Abstra is an AI-powered process automation framework.
193
+ # Ignore directories containing user credentials, local state, and settings.
194
+ # Learn more at https://abstra.io/docs
195
+ .abstra/
196
+
197
+ # Visual Studio Code
198
+ # Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore
199
+ # that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
200
+ # and can be added to the global gitignore or merged into this file. However, if you prefer,
201
+ # you could uncomment the following to ignore the entire vscode folder
202
+ # .vscode/
203
+ # Temporary file for partial code execution
204
+ tempCodeRunnerFile.py
205
+
206
+ # Ruff stuff:
207
+ .ruff_cache/
208
+
209
+ # PyPI configuration file
210
+ .pypirc
211
+
212
+ # Marimo
213
+ marimo/_static/
214
+ marimo/_lsp/
215
+ __marimo__/
216
+
217
+ # Streamlit
218
+ .streamlit/secrets.toml
ttyscan-0.0.2/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Jeff Quast
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
ttyscan-0.0.2/PKG-INFO ADDED
@@ -0,0 +1,263 @@
1
+ Metadata-Version: 2.4
2
+ Name: ttyscan
3
+ Version: 0.0.2
4
+ Summary: Queries a terminal emulator for its type, size and capabilities
5
+ Project-URL: Homepage, https://github.com/jquast/ttyscan
6
+ Author-email: Jeff Quast <contact@jeffquast.com>
7
+ License-Expression: MIT
8
+ License-File: LICENSE
9
+ Keywords: capability,colorterm,console,curses,query,serial,setupterm,ssh,telnet,terminal,terminfo,tty,xtgettcap
10
+ Classifier: Development Status :: 5 - Production/Stable
11
+ Classifier: Environment :: Console
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Natural Language :: English
14
+ Classifier: Operating System :: POSIX
15
+ Classifier: Programming Language :: Python :: 3 :: Only
16
+ Classifier: Programming Language :: Python :: 3.8
17
+ Classifier: Programming Language :: Python :: 3.9
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Programming Language :: Python :: 3.13
22
+ Classifier: Programming Language :: Python :: 3.14
23
+ Classifier: Topic :: Software Development :: Libraries
24
+ Classifier: Topic :: Terminals
25
+ Requires-Python: >=3.8
26
+ Description-Content-Type: text/x-rst
27
+
28
+ | |pypi_downloads| |codecov| |windows| |linux| |mac| |bsd|
29
+
30
+ ttyscan
31
+ =======
32
+
33
+ *ttyscan* queries a terminal emulator for its type, size and capabilities, creating a
34
+ curses-compatible `terminfo(5)`_ file entry if necessary, and exports any corrected values of
35
+ ``TERM``, ``COLORTERM``, ``LINES``, ``COLUMNS``, and optionally ``TERMCAP`` environment variables.
36
+
37
+ Problem
38
+ -------
39
+
40
+ ncurses_ does not support XTGETTCAP, and so `terminfo(5)`_ files for some terminals must be
41
+ deployed to remote systems by system operators in some circumstances.
42
+
43
+ Curses programs fail to start until those files are deployed or an alternate ``TERM`` is exported.
44
+ All kinds of errors and warnings may be raised until this is done, some examples::
45
+
46
+ $ tmux attach
47
+ missing or unsuitable terminal: xterm-kitty
48
+
49
+ $ irssi
50
+ setupterm() failed for TERM=xterm-kitty: 0
51
+ Can't initialize screen handling.
52
+
53
+ $ htop
54
+ Error opening terminal: xterm-kitty.
55
+
56
+ $ python -c 'import curses;curses.setupterm()'
57
+ Traceback (most recent call last):
58
+ File "<string>", line 1, in <module>
59
+ _curses.error: setupterm: could not find terminal
60
+
61
+ $ git log -p
62
+ WARNING: terminal is not fully functional
63
+ Press RETURN to continue
64
+
65
+ Solution
66
+ --------
67
+
68
+ *ttyscan* creates the missing `terminfo(5)` file using the ``XTGETTCAP`` (``DCS +q``) terminal query
69
+ protocol when supported, and suggests a new ``TERMINFO`` environment value for export, allowing
70
+ legacy calls to curses of `setupterm(3)`_ to succeed::
71
+
72
+ $ ttyscan -vft
73
+ ttyscan: probing terminal via XTGETTCAP ...
74
+ ttyscan: size via dual CPR: 28x100
75
+ ttyscan: XTGETTCAP supported, terminal: rio; received 204 caps (10 bool, 5 num, 185 str) in 1523ms
76
+ ttyscan: writing /home/jq/.config/ttyscan/terminfo/r/rio
77
+ export COLORTERM=truecolor
78
+ export TERM=rio
79
+ export LINES=28
80
+ export COLUMNS=100
81
+ export TERMINFO=/home/jq/.config/ttyscan/terminfo
82
+ export TERMCAP='rio|XTGETTCAP-discovered terminal::am::ut::hs::km::5i::mi::ms::NP::xn::Co#256::co#80::it#8::li#24::pa#32767::ac=``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~::bl=^G::mb=\E[5m::md=\E[1m::vi=\E[?25l::cl=\E[H\E[2J::ve=\E[?12l\E[?25h::cr=\r::cs=\E[%i%p1%d;%p2%dr::le=\b::DO=\E[%p1%dB::do=\n::nd=\E[C::cm=\E[%i%p1%d;%p2%dH::up=\E[A::vs=\E[?12;25h::dC=\E[P::mh=\E[2m::dl=\E[M::ds=\E]2;^G::ec=\E[%p1%dX::cd=\E[J::ce=\E[K::cb=\E[1K::vb=\E[?5h$<100/>\E[?5l::fs=^G::ho=\E[H::ch=\E[%i%p1%dG::ta=\t::st=\EH::al=\E[L::sf=\n::mk=\E[8m::is=\E[!p\E[?3;4l\E[4l\E>::K2=\EOE::kb=^?::kB=\E[Z::kl=\EOD::kd=\EOB::kr=\EOC::ku=\EOA::kD=\E[3~::@7=\EOF::@8=\EOM::k1=\EOP::k0=\E[21~::F1=\E[23~::F2=\E[24~::k2=\EOQ::k3=\EOR::k4=\EOS::k5=\E[15~::k6=\E[17~::k7=\E[18~::k8=\E[19~::k9=\E[20~::kh=\EOH::kI=\E[2~::kH=\E[1;2B::kN=\E[6~::kP=\E[5~::op=\E[39;49m::rp=%p1%c\E[%p2%{1}%-%db::mr=\E[7m::sr=\EM::ZR=\E[23m::ae=\E(B::te=\E[?1049l\E[23;0;0t::ei=\E[4l::ke=\E[?1l\E>::se=\E[27m::ue=\E[24m::r1=\Ec\E]104^G::r2=\E[!p\E[?3;4l\E[4l\E>::sa=%?%p9%t\E(0%e\E(B%;\E[0%?%p6%t;1%;%?%p5%t;2%;%?%p2%t;4%;%?%p1%p3%|%t;7%;%?%p4%t;5%;%?%p7%t;8%;m::me=\E(B\E[m::ZH=\E[3m::as=\E(0::ti=\E[?1049h\E[22;0;0t::im=\E[4h::ks=\E[?1h\E=::so=\E[7m::us=\E[4m::ct=\E[3g::ts=\E]2;::cv=\E[%i%p1%dd:'
83
+
84
+ $ eval `ttyscan`
85
+
86
+ $ echo $TERM, $TERMINFO
87
+ rio, /home/jquast/.config/ttyscan/terminfo
88
+
89
+ $ file -b /home/jquast/.config/ttyscan/terminfo/r/rio
90
+ Compiled terminfo entry "rio"
91
+
92
+ $ python -c 'import curses;curses.setupterm()'; echo $?
93
+ 0
94
+
95
+ CLI Arguments
96
+ -------------
97
+
98
+ ::
99
+
100
+ usage: ttyscan [-h] [-v] [-f] [-t]
101
+
102
+ Export terminal capabilities discovered via XTGETTCAP
103
+
104
+ options:
105
+ -h, --help show this help message and exit
106
+ -v, --verbose Print diagnostic information to stderr
107
+ -f, --force Force export of all values even if unchanged
108
+ -t, --termcap Also export TERMCAP value
109
+
110
+ *ttyscan* saves a `terminfo(5)`_ file to $XDG_CONFIG_HOME/ttyscan/terminfo or
111
+ ~/.config/ttyscan/terminfo, and does not re-query or re-create it when it already exists from
112
+ previous executions, unless ``--force`` argument is used.
113
+
114
+ Typical total execution time is 200ms. The default timeout query can be changed by environment
115
+ value TTYSCAN_QUERY_TIMEOUT=1.0 (float), in seconds. If timeout is reached, terminal response may
116
+ "bleed" into subsequent programs, (like a shell prompt).
117
+
118
+ Installation
119
+ ------------
120
+
121
+ .. code-block:: shell
122
+
123
+ pip install ttyscan
124
+
125
+ *ttyscan* requires Python3.8+.
126
+
127
+ ttyscan.py_ is a stand-alone python file, it does not require pip to install, you can copy this
128
+ single file directly from source and execute it from source, eg. ``python ~/bin/ttyscan.py``
129
+
130
+ Motive
131
+ ------
132
+
133
+ Naturally, transferring your ``$HOME/.terminfo`` folder to a remote machine is the best solution.
134
+
135
+ However, enterprise systems, bastion hosts, cloud systems, web consoles, hypervisors, radio, and
136
+ serial ports can be challenging places or protocol layers through which to deploy terminfo files.
137
+
138
+ Some workarounds include exporting a generally-compatible ``TERM=xterm-256color`` or ``xterm`` with
139
+ sometimes minor corruption of screen output, missed interpretation of keyboard input such as
140
+ backspace or delete, or a small reduction of features such as italic or underlined text or number of
141
+ colors.
142
+
143
+ **And so this tool is not often needed** except for the **very serious** terminal connoisseur.
144
+
145
+ It serves as a demonstration: that a full terminal capability database *can* be transferred using
146
+ XTGETTCAP_ for many modern terminals, supporting modern `terminfo(5)`_ and legacy `termcap(5)`_. It
147
+
148
+ My hope is that `setupterm(3)`_ may negotiate with full XTGETTCAP_ support at some point in the
149
+ future, and that this utility is not commonly used or required!
150
+
151
+ Scope
152
+ -----
153
+
154
+ At time of this writing (May 2026), the ucs-detect_ dataset of 42 terminals shows three categories
155
+ of support for ``XTGETTCAP``:
156
+
157
+ - **Full** ``XTGETTCAP`` capability support: contour_, foot_, ghostty_, kitty_, rio, and wezterm
158
+ transmit their complete terminfo boolean, numeric, and string capabilities via XTGETTCAP_.
159
+
160
+ *ttyscan* produces terminfo files for only these terminals. *ttyscan* may also discover a
161
+ preferred ``TERM`` from ``TN``, and ``COLORTERM=truecolor`` from ``RGB``.
162
+
163
+ - **Partial** ``XTGETTCAP`` capability support: XTerm_, iterm2, mlterm, AbsoluteTelnet/SSH, GNOME
164
+ Terminal, LXTerminal, terminator, termit, and xfce4-terminal report only ``TN``, ``Co``, and
165
+ ``RGB``.
166
+
167
+ *ttyscan* may only discover preferred ``TERM`` from ``TN``, and ``COLORTERM=truecolor`` from
168
+ ``RGB``.
169
+
170
+ XTerm_ supports only keyboard sequences in addition to ``TN``, ``Co``, and ``RGB``. It does not
171
+ report *all* capabilities, and so a `terminfo(5)`_ entry cannot be built. However,
172
+ ``TERM=xterm-256color`` and ``TERM=xterm`` are the most ubiquitous terminal name, you should be
173
+ just fine.
174
+
175
+ - **None**: alacritty (refuses: `alacritty/vte#98`_), bobcat, cmd.exe, ConEmu, cool-retro-term,
176
+ Extraterm, Hyper, Konsole (requested: `KDE#507017`_), linux fbdev, mintty, PuTTY, QTerminal,
177
+ rxvt-unicode, screen, securecrt, st, Tabby, Apple Terminal, Terminal.exe (planned:
178
+ `microsoft/terminal#17735`_), terminology, tmux (passthrough: `tmux/tmux#3755`_), libvterm, VS
179
+ Code (xterm.js, proposal: `xtermjs/xterm.js#4107`_), weston-terminal, and zutty.
180
+
181
+ Architecture
182
+ ------------
183
+
184
+ *ttyscan* uses the following,
185
+
186
+ - ``XTGETTCAP`` field ``TN`` is used to correct ``TERM`` when unmatched.
187
+ - ``XTGETTCAP`` field ``RGB`` is used to correct ``COLORTERM`` when unmatched.
188
+ - all capability strings, keyboard and screen, when provided by ``XTGETTCAP``.
189
+ - DEC Private Mode 2048 (In-Band Resize) to determine the window size
190
+ - Or failing that, using Cursor Position Report sequence like done in XTerm's `resize.c
191
+ <https://github.com/joejulian/xterm/blob/master/resize.c>`_
192
+
193
+ Details
194
+ -------
195
+
196
+ The difference of *Full* and *Partial* ``XTGETTCAP`` support is best described by foot_:
197
+
198
+ ``XTGETTCAP`` is an escape sequence initially introduced by XTerm_, and also implemented (and extended,
199
+ to some degree) by Kitty.
200
+
201
+ Applications using this feature do not need to use the classic, file-based, terminfo definition.
202
+
203
+ XTerm's implementation (as of XTerm-370) only supports querying key (as in keyboard keys)
204
+ capabilities, and three custom capabilities:
205
+
206
+ ``TN`` - terminal name
207
+ ``Co`` - number of colors (alias for the colors capability)
208
+ ``RGB`` - number of bits per color channel (different semantics from the RGB capability in file-based
209
+ terminfo definitions!).
210
+
211
+ Kitty has extended this, and also supports querying all integer and string capabilities.
212
+
213
+ Foot supports this, and extends it even further, to also include boolean capabilities.
214
+ This means foot's entire terminfo can be queried via ``XTGETTCAP``.
215
+
216
+ Further, all of ``TERM``, ``COLORTERM``, ``LINES``, or ``COLUMNS`` may not be transmitted by all
217
+ software or protocols, some examples:
218
+
219
+ - ssh does not forward ``COLORTERM`` unless configured using ``SendEnv`` in `ssh_config(5)`_ and
220
+ ``AcceptEnv`` in `sshd_config(5)`_.
221
+ - serial does not forward any; ``TERM`` is defined by host `agetty(8)`_ configuration, for example.
222
+ - rlogin can forward all but ``COLORTERM``.
223
+ - telnet can forward all, but IAC NAWS and NEW-ENVIRON capability varies by software.
224
+ - websocket cannot forward any without customization, often used in-browser.
225
+
226
+ *ttyscan* detects when these variables are unset or do not match values and re-exports the corrected
227
+ values when they differ.
228
+
229
+ .. _`agetty(8)`: https://linux.die.net/man/8/agetty
230
+ .. _`alacritty/vte#98`: https://github.com/alacritty/vte/issues/98
231
+ .. _contour: https://github.com/contour-terminal/contour
232
+ .. _foot: https://codeberg.org/dnkl/foot#xtgettcap
233
+ .. _ghostty: https://mitchellh.com/writing/ghostty-devlog-004
234
+ .. _`KDE#507017`: https://bugs.kde.org/show_bug.cgi?id=507017
235
+ .. _kitty: https://sw.kovidgoyal.net/kitty/kittens/query_terminal/
236
+ .. _`microsoft/terminal#17735`: https://github.com/microsoft/terminal/issues/17735
237
+ .. _ncurses: https://invisible-island.net/ncurses/
238
+ .. _`setupterm(3)`: https://linux.die.net/man/3/setupterm
239
+ .. _`ssh_config(5)`: https://linux.die.net/man/5/ssh_config
240
+ .. _`sshd_config(5)`: https://linux.die.net/man/5/sshd_config
241
+ .. _`termcap(5)`: https://linux.die.net/man/5/termcap
242
+ .. _`terminfo(5)`: https://linux.die.net/man/5/terminfo
243
+ .. _`tmux/tmux#3755`: https://github.com/tmux/tmux/issues/3755
244
+ .. _`ttyscan.py`: https://github.com/jquast/ttyscan/blob/master/ttyscan.py
245
+ .. _ucs-detect: https://ucs-detect.readthedocs.io/results.html#terminal-capabilities
246
+ .. _XTerm: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h4-Device-Control-functions:DCS-plus-q-Pt-ST.F95
247
+ .. _`xtermjs/xterm.js#4107`: https://github.com/xtermjs/xterm.js/issues/4107
248
+ .. _XTGETTCAP: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h4-Device-Control-functions:DCS-plus-q-Pt-ST.F95
249
+
250
+ .. |pypi_downloads| image:: https://img.shields.io/pypi/dm/ttyscan.svg?logo=pypi
251
+ :alt: Downloads
252
+ :target: https://pypi.org/project/ttyscan/
253
+ .. |codecov| image:: https://codecov.io/gh/jquast/ttyscan/branch/master/graph/badge.svg
254
+ :alt: codecov.io Code Coverage
255
+ :target: https://codecov.io/gh/jquast/ttyscan/
256
+ .. |linux| image:: https://img.shields.io/badge/Linux-yes-success?logo=linux
257
+ :alt: Linux supported
258
+ .. |windows| image:: https://img.shields.io/badge/Windows-yes-success?logo=windows
259
+ :alt: Windows supported
260
+ .. |mac| image:: https://img.shields.io/badge/MacOS-yes-success?logo=apple
261
+ :alt: MacOS supported
262
+ .. |bsd| image:: https://img.shields.io/badge/BSD-yes-success?logo=freebsd
263
+ :alt: BSD supported