Add files using upload-large-folder tool
Browse filesThis view is limited to 50 files because it contains too many changes.
See raw diff
- .gitattributes +7 -0
- .venv/lib/python3.11/site-packages/_virtualenv.pth +3 -0
- .venv/lib/python3.11/site-packages/charset_normalizer-3.4.3.dist-info/licenses/LICENSE +21 -0
- .venv/lib/python3.11/site-packages/charset_normalizer/md__mypyc.cpython-311-x86_64-linux-gnu.so +3 -0
- .venv/lib/python3.11/site-packages/fsspec-2025.9.0.dist-info/licenses/LICENSE +29 -0
- .venv/lib/python3.11/site-packages/hf_xet/hf_xet.abi3.so +3 -0
- .venv/lib/python3.11/site-packages/huggingface_hub/__pycache__/hf_api.cpython-311.pyc +3 -0
- .venv/lib/python3.11/site-packages/idna/__pycache__/idnadata.cpython-311.pyc +3 -0
- .venv/lib/python3.11/site-packages/packaging-25.0.dist-info/licenses/LICENSE +3 -0
- .venv/lib/python3.11/site-packages/packaging-25.0.dist-info/licenses/LICENSE.APACHE +177 -0
- .venv/lib/python3.11/site-packages/packaging-25.0.dist-info/licenses/LICENSE.BSD +23 -0
- .venv/lib/python3.11/site-packages/prompt_toolkit-3.0.52.dist-info/licenses/AUTHORS.rst +11 -0
- .venv/lib/python3.11/site-packages/prompt_toolkit-3.0.52.dist-info/licenses/LICENSE +27 -0
- .venv/lib/python3.11/site-packages/prompt_toolkit/__pycache__/__init__.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/prompt_toolkit/__pycache__/auto_suggest.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/prompt_toolkit/__pycache__/buffer.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/prompt_toolkit/__pycache__/cache.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/prompt_toolkit/__pycache__/cursor_shapes.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/prompt_toolkit/__pycache__/data_structures.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/prompt_toolkit/__pycache__/document.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/prompt_toolkit/__pycache__/enums.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/prompt_toolkit/__pycache__/history.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/prompt_toolkit/__pycache__/keys.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/prompt_toolkit/__pycache__/mouse_events.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/prompt_toolkit/__pycache__/renderer.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/prompt_toolkit/__pycache__/search.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/prompt_toolkit/__pycache__/selection.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/prompt_toolkit/__pycache__/utils.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/prompt_toolkit/__pycache__/validation.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/prompt_toolkit/application/__pycache__/__init__.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/prompt_toolkit/application/__pycache__/application.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/prompt_toolkit/application/__pycache__/current.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/prompt_toolkit/application/__pycache__/dummy.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/prompt_toolkit/application/__pycache__/run_in_terminal.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/prompt_toolkit/clipboard/__pycache__/__init__.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/prompt_toolkit/clipboard/__pycache__/base.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/prompt_toolkit/clipboard/__pycache__/in_memory.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/prompt_toolkit/completion/__pycache__/__init__.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/prompt_toolkit/completion/__pycache__/base.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/prompt_toolkit/completion/__pycache__/deduplicate.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/prompt_toolkit/completion/__pycache__/filesystem.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/prompt_toolkit/completion/__pycache__/fuzzy_completer.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/prompt_toolkit/completion/__pycache__/nested.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/prompt_toolkit/completion/__pycache__/word_completer.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/prompt_toolkit/contrib/completers/__init__.py +5 -0
- .venv/lib/python3.11/site-packages/prompt_toolkit/contrib/completers/system.py +64 -0
- .venv/lib/python3.11/site-packages/prompt_toolkit/contrib/regular_languages/__init__.py +80 -0
- .venv/lib/python3.11/site-packages/prompt_toolkit/contrib/regular_languages/compiler.py +579 -0
- .venv/lib/python3.11/site-packages/prompt_toolkit/contrib/regular_languages/completion.py +100 -0
- .venv/lib/python3.11/site-packages/prompt_toolkit/contrib/regular_languages/lexer.py +94 -0
.gitattributes
CHANGED
|
@@ -35,3 +35,10 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
|
| 35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
| 36 |
tokenizer.json filter=lfs diff=lfs merge=lfs -text
|
| 37 |
thumbnail.png filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
| 36 |
tokenizer.json filter=lfs diff=lfs merge=lfs -text
|
| 37 |
thumbnail.png filter=lfs diff=lfs merge=lfs -text
|
| 38 |
+
.venv/lib/python3.11/site-packages/idna/__pycache__/idnadata.cpython-311.pyc filter=lfs diff=lfs merge=lfs -text
|
| 39 |
+
.venv/lib/python3.11/site-packages/huggingface_hub/__pycache__/hf_api.cpython-311.pyc filter=lfs diff=lfs merge=lfs -text
|
| 40 |
+
.venv/lib/python3.11/site-packages/prompt_toolkit/key_binding/bindings/__pycache__/vi.cpython-311.pyc filter=lfs diff=lfs merge=lfs -text
|
| 41 |
+
.venv/lib/python3.11/site-packages/prompt_toolkit/layout/__pycache__/containers.cpython-311.pyc filter=lfs diff=lfs merge=lfs -text
|
| 42 |
+
.venv/lib/python3.11/site-packages/yaml/_yaml.cpython-311-x86_64-linux-gnu.so filter=lfs diff=lfs merge=lfs -text
|
| 43 |
+
.venv/lib/python3.11/site-packages/hf_xet/hf_xet.abi3.so filter=lfs diff=lfs merge=lfs -text
|
| 44 |
+
.venv/lib/python3.11/site-packages/charset_normalizer/md__mypyc.cpython-311-x86_64-linux-gnu.so filter=lfs diff=lfs merge=lfs -text
|
.venv/lib/python3.11/site-packages/_virtualenv.pth
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:69ac3d8f27e679c81b94ab30b3b56e9cd138219b1ba94a1fa3606d5a76a1433d
|
| 3 |
+
size 18
|
.venv/lib/python3.11/site-packages/charset_normalizer-3.4.3.dist-info/licenses/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
MIT License
|
| 2 |
+
|
| 3 |
+
Copyright (c) 2025 TAHRI Ahmed R.
|
| 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.
|
.venv/lib/python3.11/site-packages/charset_normalizer/md__mypyc.cpython-311-x86_64-linux-gnu.so
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:631f96dfb24c0a4d8471724082545706b36c03079c36deca6abaf9a71dd17aa0
|
| 3 |
+
size 281208
|
.venv/lib/python3.11/site-packages/fsspec-2025.9.0.dist-info/licenses/LICENSE
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
BSD 3-Clause License
|
| 2 |
+
|
| 3 |
+
Copyright (c) 2018, Martin Durant
|
| 4 |
+
All rights reserved.
|
| 5 |
+
|
| 6 |
+
Redistribution and use in source and binary forms, with or without
|
| 7 |
+
modification, are permitted provided that the following conditions are met:
|
| 8 |
+
|
| 9 |
+
* Redistributions of source code must retain the above copyright notice, this
|
| 10 |
+
list of conditions and the following disclaimer.
|
| 11 |
+
|
| 12 |
+
* Redistributions in binary form must reproduce the above copyright notice,
|
| 13 |
+
this list of conditions and the following disclaimer in the documentation
|
| 14 |
+
and/or other materials provided with the distribution.
|
| 15 |
+
|
| 16 |
+
* Neither the name of the copyright holder nor the names of its
|
| 17 |
+
contributors may be used to endorse or promote products derived from
|
| 18 |
+
this software without specific prior written permission.
|
| 19 |
+
|
| 20 |
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
| 21 |
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
| 22 |
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
| 23 |
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
| 24 |
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
| 25 |
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
| 26 |
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
| 27 |
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
| 28 |
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
| 29 |
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
.venv/lib/python3.11/site-packages/hf_xet/hf_xet.abi3.so
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:5815fbc856f76eda6c435431e94fcf414dbd5121da2bc55beec4696245bd045b
|
| 3 |
+
size 7942656
|
.venv/lib/python3.11/site-packages/huggingface_hub/__pycache__/hf_api.cpython-311.pyc
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:b32b254634467dd5d688832c7bdf422925ec2ce2729915d40fdf94a4e374a4cb
|
| 3 |
+
size 506593
|
.venv/lib/python3.11/site-packages/idna/__pycache__/idnadata.cpython-311.pyc
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:2564ad128f80bff7f6dd8bbe7e5ab7c001ba11f9cf0d1f38a58ab5267b082d45
|
| 3 |
+
size 101536
|
.venv/lib/python3.11/site-packages/packaging-25.0.dist-info/licenses/LICENSE
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
This software is made available under the terms of *either* of the licenses
|
| 2 |
+
found in LICENSE.APACHE or LICENSE.BSD. Contributions to this software is made
|
| 3 |
+
under the terms of *both* these licenses.
|
.venv/lib/python3.11/site-packages/packaging-25.0.dist-info/licenses/LICENSE.APACHE
ADDED
|
@@ -0,0 +1,177 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
|
| 2 |
+
Apache License
|
| 3 |
+
Version 2.0, January 2004
|
| 4 |
+
http://www.apache.org/licenses/
|
| 5 |
+
|
| 6 |
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
| 7 |
+
|
| 8 |
+
1. Definitions.
|
| 9 |
+
|
| 10 |
+
"License" shall mean the terms and conditions for use, reproduction,
|
| 11 |
+
and distribution as defined by Sections 1 through 9 of this document.
|
| 12 |
+
|
| 13 |
+
"Licensor" shall mean the copyright owner or entity authorized by
|
| 14 |
+
the copyright owner that is granting the License.
|
| 15 |
+
|
| 16 |
+
"Legal Entity" shall mean the union of the acting entity and all
|
| 17 |
+
other entities that control, are controlled by, or are under common
|
| 18 |
+
control with that entity. For the purposes of this definition,
|
| 19 |
+
"control" means (i) the power, direct or indirect, to cause the
|
| 20 |
+
direction or management of such entity, whether by contract or
|
| 21 |
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
| 22 |
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
| 23 |
+
|
| 24 |
+
"You" (or "Your") shall mean an individual or Legal Entity
|
| 25 |
+
exercising permissions granted by this License.
|
| 26 |
+
|
| 27 |
+
"Source" form shall mean the preferred form for making modifications,
|
| 28 |
+
including but not limited to software source code, documentation
|
| 29 |
+
source, and configuration files.
|
| 30 |
+
|
| 31 |
+
"Object" form shall mean any form resulting from mechanical
|
| 32 |
+
transformation or translation of a Source form, including but
|
| 33 |
+
not limited to compiled object code, generated documentation,
|
| 34 |
+
and conversions to other media types.
|
| 35 |
+
|
| 36 |
+
"Work" shall mean the work of authorship, whether in Source or
|
| 37 |
+
Object form, made available under the License, as indicated by a
|
| 38 |
+
copyright notice that is included in or attached to the work
|
| 39 |
+
(an example is provided in the Appendix below).
|
| 40 |
+
|
| 41 |
+
"Derivative Works" shall mean any work, whether in Source or Object
|
| 42 |
+
form, that is based on (or derived from) the Work and for which the
|
| 43 |
+
editorial revisions, annotations, elaborations, or other modifications
|
| 44 |
+
represent, as a whole, an original work of authorship. For the purposes
|
| 45 |
+
of this License, Derivative Works shall not include works that remain
|
| 46 |
+
separable from, or merely link (or bind by name) to the interfaces of,
|
| 47 |
+
the Work and Derivative Works thereof.
|
| 48 |
+
|
| 49 |
+
"Contribution" shall mean any work of authorship, including
|
| 50 |
+
the original version of the Work and any modifications or additions
|
| 51 |
+
to that Work or Derivative Works thereof, that is intentionally
|
| 52 |
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
| 53 |
+
or by an individual or Legal Entity authorized to submit on behalf of
|
| 54 |
+
the copyright owner. For the purposes of this definition, "submitted"
|
| 55 |
+
means any form of electronic, verbal, or written communication sent
|
| 56 |
+
to the Licensor or its representatives, including but not limited to
|
| 57 |
+
communication on electronic mailing lists, source code control systems,
|
| 58 |
+
and issue tracking systems that are managed by, or on behalf of, the
|
| 59 |
+
Licensor for the purpose of discussing and improving the Work, but
|
| 60 |
+
excluding communication that is conspicuously marked or otherwise
|
| 61 |
+
designated in writing by the copyright owner as "Not a Contribution."
|
| 62 |
+
|
| 63 |
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
| 64 |
+
on behalf of whom a Contribution has been received by Licensor and
|
| 65 |
+
subsequently incorporated within the Work.
|
| 66 |
+
|
| 67 |
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
| 68 |
+
this License, each Contributor hereby grants to You a perpetual,
|
| 69 |
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
| 70 |
+
copyright license to reproduce, prepare Derivative Works of,
|
| 71 |
+
publicly display, publicly perform, sublicense, and distribute the
|
| 72 |
+
Work and such Derivative Works in Source or Object form.
|
| 73 |
+
|
| 74 |
+
3. Grant of Patent License. Subject to the terms and conditions of
|
| 75 |
+
this License, each Contributor hereby grants to You a perpetual,
|
| 76 |
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
| 77 |
+
(except as stated in this section) patent license to make, have made,
|
| 78 |
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
| 79 |
+
where such license applies only to those patent claims licensable
|
| 80 |
+
by such Contributor that are necessarily infringed by their
|
| 81 |
+
Contribution(s) alone or by combination of their Contribution(s)
|
| 82 |
+
with the Work to which such Contribution(s) was submitted. If You
|
| 83 |
+
institute patent litigation against any entity (including a
|
| 84 |
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
| 85 |
+
or a Contribution incorporated within the Work constitutes direct
|
| 86 |
+
or contributory patent infringement, then any patent licenses
|
| 87 |
+
granted to You under this License for that Work shall terminate
|
| 88 |
+
as of the date such litigation is filed.
|
| 89 |
+
|
| 90 |
+
4. Redistribution. You may reproduce and distribute copies of the
|
| 91 |
+
Work or Derivative Works thereof in any medium, with or without
|
| 92 |
+
modifications, and in Source or Object form, provided that You
|
| 93 |
+
meet the following conditions:
|
| 94 |
+
|
| 95 |
+
(a) You must give any other recipients of the Work or
|
| 96 |
+
Derivative Works a copy of this License; and
|
| 97 |
+
|
| 98 |
+
(b) You must cause any modified files to carry prominent notices
|
| 99 |
+
stating that You changed the files; and
|
| 100 |
+
|
| 101 |
+
(c) You must retain, in the Source form of any Derivative Works
|
| 102 |
+
that You distribute, all copyright, patent, trademark, and
|
| 103 |
+
attribution notices from the Source form of the Work,
|
| 104 |
+
excluding those notices that do not pertain to any part of
|
| 105 |
+
the Derivative Works; and
|
| 106 |
+
|
| 107 |
+
(d) If the Work includes a "NOTICE" text file as part of its
|
| 108 |
+
distribution, then any Derivative Works that You distribute must
|
| 109 |
+
include a readable copy of the attribution notices contained
|
| 110 |
+
within such NOTICE file, excluding those notices that do not
|
| 111 |
+
pertain to any part of the Derivative Works, in at least one
|
| 112 |
+
of the following places: within a NOTICE text file distributed
|
| 113 |
+
as part of the Derivative Works; within the Source form or
|
| 114 |
+
documentation, if provided along with the Derivative Works; or,
|
| 115 |
+
within a display generated by the Derivative Works, if and
|
| 116 |
+
wherever such third-party notices normally appear. The contents
|
| 117 |
+
of the NOTICE file are for informational purposes only and
|
| 118 |
+
do not modify the License. You may add Your own attribution
|
| 119 |
+
notices within Derivative Works that You distribute, alongside
|
| 120 |
+
or as an addendum to the NOTICE text from the Work, provided
|
| 121 |
+
that such additional attribution notices cannot be construed
|
| 122 |
+
as modifying the License.
|
| 123 |
+
|
| 124 |
+
You may add Your own copyright statement to Your modifications and
|
| 125 |
+
may provide additional or different license terms and conditions
|
| 126 |
+
for use, reproduction, or distribution of Your modifications, or
|
| 127 |
+
for any such Derivative Works as a whole, provided Your use,
|
| 128 |
+
reproduction, and distribution of the Work otherwise complies with
|
| 129 |
+
the conditions stated in this License.
|
| 130 |
+
|
| 131 |
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
| 132 |
+
any Contribution intentionally submitted for inclusion in the Work
|
| 133 |
+
by You to the Licensor shall be under the terms and conditions of
|
| 134 |
+
this License, without any additional terms or conditions.
|
| 135 |
+
Notwithstanding the above, nothing herein shall supersede or modify
|
| 136 |
+
the terms of any separate license agreement you may have executed
|
| 137 |
+
with Licensor regarding such Contributions.
|
| 138 |
+
|
| 139 |
+
6. Trademarks. This License does not grant permission to use the trade
|
| 140 |
+
names, trademarks, service marks, or product names of the Licensor,
|
| 141 |
+
except as required for reasonable and customary use in describing the
|
| 142 |
+
origin of the Work and reproducing the content of the NOTICE file.
|
| 143 |
+
|
| 144 |
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
| 145 |
+
agreed to in writing, Licensor provides the Work (and each
|
| 146 |
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
| 147 |
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
| 148 |
+
implied, including, without limitation, any warranties or conditions
|
| 149 |
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
| 150 |
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
| 151 |
+
appropriateness of using or redistributing the Work and assume any
|
| 152 |
+
risks associated with Your exercise of permissions under this License.
|
| 153 |
+
|
| 154 |
+
8. Limitation of Liability. In no event and under no legal theory,
|
| 155 |
+
whether in tort (including negligence), contract, or otherwise,
|
| 156 |
+
unless required by applicable law (such as deliberate and grossly
|
| 157 |
+
negligent acts) or agreed to in writing, shall any Contributor be
|
| 158 |
+
liable to You for damages, including any direct, indirect, special,
|
| 159 |
+
incidental, or consequential damages of any character arising as a
|
| 160 |
+
result of this License or out of the use or inability to use the
|
| 161 |
+
Work (including but not limited to damages for loss of goodwill,
|
| 162 |
+
work stoppage, computer failure or malfunction, or any and all
|
| 163 |
+
other commercial damages or losses), even if such Contributor
|
| 164 |
+
has been advised of the possibility of such damages.
|
| 165 |
+
|
| 166 |
+
9. Accepting Warranty or Additional Liability. While redistributing
|
| 167 |
+
the Work or Derivative Works thereof, You may choose to offer,
|
| 168 |
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
| 169 |
+
or other liability obligations and/or rights consistent with this
|
| 170 |
+
License. However, in accepting such obligations, You may act only
|
| 171 |
+
on Your own behalf and on Your sole responsibility, not on behalf
|
| 172 |
+
of any other Contributor, and only if You agree to indemnify,
|
| 173 |
+
defend, and hold each Contributor harmless for any liability
|
| 174 |
+
incurred by, or claims asserted against, such Contributor by reason
|
| 175 |
+
of your accepting any such warranty or additional liability.
|
| 176 |
+
|
| 177 |
+
END OF TERMS AND CONDITIONS
|
.venv/lib/python3.11/site-packages/packaging-25.0.dist-info/licenses/LICENSE.BSD
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Copyright (c) Donald Stufft and individual contributors.
|
| 2 |
+
All rights reserved.
|
| 3 |
+
|
| 4 |
+
Redistribution and use in source and binary forms, with or without
|
| 5 |
+
modification, are permitted provided that the following conditions are met:
|
| 6 |
+
|
| 7 |
+
1. Redistributions of source code must retain the above copyright notice,
|
| 8 |
+
this list of conditions and the following disclaimer.
|
| 9 |
+
|
| 10 |
+
2. Redistributions in binary form must reproduce the above copyright
|
| 11 |
+
notice, this list of conditions and the following disclaimer in the
|
| 12 |
+
documentation and/or other materials provided with the distribution.
|
| 13 |
+
|
| 14 |
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
| 15 |
+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
| 16 |
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
| 17 |
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
| 18 |
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
| 19 |
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
| 20 |
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
| 21 |
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
| 22 |
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
| 23 |
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
.venv/lib/python3.11/site-packages/prompt_toolkit-3.0.52.dist-info/licenses/AUTHORS.rst
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Authors
|
| 2 |
+
=======
|
| 3 |
+
|
| 4 |
+
Creator
|
| 5 |
+
-------
|
| 6 |
+
Jonathan Slenders <jonathan AT slenders.be>
|
| 7 |
+
|
| 8 |
+
Contributors
|
| 9 |
+
------------
|
| 10 |
+
|
| 11 |
+
- Amjith Ramanujam <amjith.r AT gmail.com>
|
.venv/lib/python3.11/site-packages/prompt_toolkit-3.0.52.dist-info/licenses/LICENSE
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Copyright (c) 2014, Jonathan Slenders
|
| 2 |
+
All rights reserved.
|
| 3 |
+
|
| 4 |
+
Redistribution and use in source and binary forms, with or without modification,
|
| 5 |
+
are permitted provided that the following conditions are met:
|
| 6 |
+
|
| 7 |
+
* Redistributions of source code must retain the above copyright notice, this
|
| 8 |
+
list of conditions and the following disclaimer.
|
| 9 |
+
|
| 10 |
+
* Redistributions in binary form must reproduce the above copyright notice, this
|
| 11 |
+
list of conditions and the following disclaimer in the documentation and/or
|
| 12 |
+
other materials provided with the distribution.
|
| 13 |
+
|
| 14 |
+
* Neither the name of the {organization} nor the names of its
|
| 15 |
+
contributors may be used to endorse or promote products derived from
|
| 16 |
+
this software without specific prior written permission.
|
| 17 |
+
|
| 18 |
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
| 19 |
+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
| 20 |
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
| 21 |
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
| 22 |
+
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
| 23 |
+
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
| 24 |
+
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
| 25 |
+
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
| 26 |
+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
| 27 |
+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
.venv/lib/python3.11/site-packages/prompt_toolkit/__pycache__/__init__.cpython-311.pyc
ADDED
|
Binary file (1.96 kB). View file
|
|
|
.venv/lib/python3.11/site-packages/prompt_toolkit/__pycache__/auto_suggest.cpython-311.pyc
ADDED
|
Binary file (9.61 kB). View file
|
|
|
.venv/lib/python3.11/site-packages/prompt_toolkit/__pycache__/buffer.cpython-311.pyc
ADDED
|
Binary file (82.6 kB). View file
|
|
|
.venv/lib/python3.11/site-packages/prompt_toolkit/__pycache__/cache.cpython-311.pyc
ADDED
|
Binary file (6.04 kB). View file
|
|
|
.venv/lib/python3.11/site-packages/prompt_toolkit/__pycache__/cursor_shapes.cpython-311.pyc
ADDED
|
Binary file (5.14 kB). View file
|
|
|
.venv/lib/python3.11/site-packages/prompt_toolkit/__pycache__/data_structures.cpython-311.pyc
ADDED
|
Binary file (898 Bytes). View file
|
|
|
.venv/lib/python3.11/site-packages/prompt_toolkit/__pycache__/document.cpython-311.pyc
ADDED
|
Binary file (49.8 kB). View file
|
|
|
.venv/lib/python3.11/site-packages/prompt_toolkit/__pycache__/enums.cpython-311.pyc
ADDED
|
Binary file (662 Bytes). View file
|
|
|
.venv/lib/python3.11/site-packages/prompt_toolkit/__pycache__/history.cpython-311.pyc
ADDED
|
Binary file (15.3 kB). View file
|
|
|
.venv/lib/python3.11/site-packages/prompt_toolkit/__pycache__/keys.cpython-311.pyc
ADDED
|
Binary file (5.54 kB). View file
|
|
|
.venv/lib/python3.11/site-packages/prompt_toolkit/__pycache__/mouse_events.cpython-311.pyc
ADDED
|
Binary file (3.17 kB). View file
|
|
|
.venv/lib/python3.11/site-packages/prompt_toolkit/__pycache__/renderer.cpython-311.pyc
ADDED
|
Binary file (31.2 kB). View file
|
|
|
.venv/lib/python3.11/site-packages/prompt_toolkit/__pycache__/search.cpython-311.pyc
ADDED
|
Binary file (8.15 kB). View file
|
|
|
.venv/lib/python3.11/site-packages/prompt_toolkit/__pycache__/selection.cpython-311.pyc
ADDED
|
Binary file (2.33 kB). View file
|
|
|
.venv/lib/python3.11/site-packages/prompt_toolkit/__pycache__/utils.cpython-311.pyc
ADDED
|
Binary file (12.9 kB). View file
|
|
|
.venv/lib/python3.11/site-packages/prompt_toolkit/__pycache__/validation.cpython-311.pyc
ADDED
|
Binary file (10.2 kB). View file
|
|
|
.venv/lib/python3.11/site-packages/prompt_toolkit/application/__pycache__/__init__.cpython-311.pyc
ADDED
|
Binary file (858 Bytes). View file
|
|
|
.venv/lib/python3.11/site-packages/prompt_toolkit/application/__pycache__/application.cpython-311.pyc
ADDED
|
Binary file (73.8 kB). View file
|
|
|
.venv/lib/python3.11/site-packages/prompt_toolkit/application/__pycache__/current.cpython-311.pyc
ADDED
|
Binary file (7.84 kB). View file
|
|
|
.venv/lib/python3.11/site-packages/prompt_toolkit/application/__pycache__/dummy.cpython-311.pyc
ADDED
|
Binary file (3.05 kB). View file
|
|
|
.venv/lib/python3.11/site-packages/prompt_toolkit/application/__pycache__/run_in_terminal.cpython-311.pyc
ADDED
|
Binary file (5.89 kB). View file
|
|
|
.venv/lib/python3.11/site-packages/prompt_toolkit/clipboard/__pycache__/__init__.cpython-311.pyc
ADDED
|
Binary file (547 Bytes). View file
|
|
|
.venv/lib/python3.11/site-packages/prompt_toolkit/clipboard/__pycache__/base.cpython-311.pyc
ADDED
|
Binary file (5.67 kB). View file
|
|
|
.venv/lib/python3.11/site-packages/prompt_toolkit/clipboard/__pycache__/in_memory.cpython-311.pyc
ADDED
|
Binary file (2.46 kB). View file
|
|
|
.venv/lib/python3.11/site-packages/prompt_toolkit/completion/__pycache__/__init__.cpython-311.pyc
ADDED
|
Binary file (1.16 kB). View file
|
|
|
.venv/lib/python3.11/site-packages/prompt_toolkit/completion/__pycache__/base.cpython-311.pyc
ADDED
|
Binary file (20.6 kB). View file
|
|
|
.venv/lib/python3.11/site-packages/prompt_toolkit/completion/__pycache__/deduplicate.cpython-311.pyc
ADDED
|
Binary file (2.12 kB). View file
|
|
|
.venv/lib/python3.11/site-packages/prompt_toolkit/completion/__pycache__/filesystem.cpython-311.pyc
ADDED
|
Binary file (6.09 kB). View file
|
|
|
.venv/lib/python3.11/site-packages/prompt_toolkit/completion/__pycache__/fuzzy_completer.cpython-311.pyc
ADDED
|
Binary file (10.4 kB). View file
|
|
|
.venv/lib/python3.11/site-packages/prompt_toolkit/completion/__pycache__/nested.cpython-311.pyc
ADDED
|
Binary file (5.31 kB). View file
|
|
|
.venv/lib/python3.11/site-packages/prompt_toolkit/completion/__pycache__/word_completer.cpython-311.pyc
ADDED
|
Binary file (4.51 kB). View file
|
|
|
.venv/lib/python3.11/site-packages/prompt_toolkit/contrib/completers/__init__.py
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from __future__ import annotations
|
| 2 |
+
|
| 3 |
+
from .system import SystemCompleter
|
| 4 |
+
|
| 5 |
+
__all__ = ["SystemCompleter"]
|
.venv/lib/python3.11/site-packages/prompt_toolkit/contrib/completers/system.py
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from __future__ import annotations
|
| 2 |
+
|
| 3 |
+
from prompt_toolkit.completion.filesystem import ExecutableCompleter, PathCompleter
|
| 4 |
+
from prompt_toolkit.contrib.regular_languages.compiler import compile
|
| 5 |
+
from prompt_toolkit.contrib.regular_languages.completion import GrammarCompleter
|
| 6 |
+
|
| 7 |
+
__all__ = [
|
| 8 |
+
"SystemCompleter",
|
| 9 |
+
]
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
class SystemCompleter(GrammarCompleter):
|
| 13 |
+
"""
|
| 14 |
+
Completer for system commands.
|
| 15 |
+
"""
|
| 16 |
+
|
| 17 |
+
def __init__(self) -> None:
|
| 18 |
+
# Compile grammar.
|
| 19 |
+
g = compile(
|
| 20 |
+
r"""
|
| 21 |
+
# First we have an executable.
|
| 22 |
+
(?P<executable>[^\s]+)
|
| 23 |
+
|
| 24 |
+
# Ignore literals in between.
|
| 25 |
+
(
|
| 26 |
+
\s+
|
| 27 |
+
("[^"]*" | '[^']*' | [^'"]+ )
|
| 28 |
+
)*
|
| 29 |
+
|
| 30 |
+
\s+
|
| 31 |
+
|
| 32 |
+
# Filename as parameters.
|
| 33 |
+
(
|
| 34 |
+
(?P<filename>[^\s]+) |
|
| 35 |
+
"(?P<double_quoted_filename>[^\s]+)" |
|
| 36 |
+
'(?P<single_quoted_filename>[^\s]+)'
|
| 37 |
+
)
|
| 38 |
+
""",
|
| 39 |
+
escape_funcs={
|
| 40 |
+
"double_quoted_filename": (lambda string: string.replace('"', '\\"')),
|
| 41 |
+
"single_quoted_filename": (lambda string: string.replace("'", "\\'")),
|
| 42 |
+
},
|
| 43 |
+
unescape_funcs={
|
| 44 |
+
"double_quoted_filename": (
|
| 45 |
+
lambda string: string.replace('\\"', '"')
|
| 46 |
+
), # XXX: not entirely correct.
|
| 47 |
+
"single_quoted_filename": (lambda string: string.replace("\\'", "'")),
|
| 48 |
+
},
|
| 49 |
+
)
|
| 50 |
+
|
| 51 |
+
# Create GrammarCompleter
|
| 52 |
+
super().__init__(
|
| 53 |
+
g,
|
| 54 |
+
{
|
| 55 |
+
"executable": ExecutableCompleter(),
|
| 56 |
+
"filename": PathCompleter(only_directories=False, expanduser=True),
|
| 57 |
+
"double_quoted_filename": PathCompleter(
|
| 58 |
+
only_directories=False, expanduser=True
|
| 59 |
+
),
|
| 60 |
+
"single_quoted_filename": PathCompleter(
|
| 61 |
+
only_directories=False, expanduser=True
|
| 62 |
+
),
|
| 63 |
+
},
|
| 64 |
+
)
|
.venv/lib/python3.11/site-packages/prompt_toolkit/contrib/regular_languages/__init__.py
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
r"""
|
| 2 |
+
Tool for expressing the grammar of an input as a regular language.
|
| 3 |
+
==================================================================
|
| 4 |
+
|
| 5 |
+
The grammar for the input of many simple command line interfaces can be
|
| 6 |
+
expressed by a regular language. Examples are PDB (the Python debugger); a
|
| 7 |
+
simple (bash-like) shell with "pwd", "cd", "cat" and "ls" commands; arguments
|
| 8 |
+
that you can pass to an executable; etc. It is possible to use regular
|
| 9 |
+
expressions for validation and parsing of such a grammar. (More about regular
|
| 10 |
+
languages: http://en.wikipedia.org/wiki/Regular_language)
|
| 11 |
+
|
| 12 |
+
Example
|
| 13 |
+
-------
|
| 14 |
+
|
| 15 |
+
Let's take the pwd/cd/cat/ls example. We want to have a shell that accepts
|
| 16 |
+
these three commands. "cd" is followed by a quoted directory name and "cat" is
|
| 17 |
+
followed by a quoted file name. (We allow quotes inside the filename when
|
| 18 |
+
they're escaped with a backslash.) We could define the grammar using the
|
| 19 |
+
following regular expression::
|
| 20 |
+
|
| 21 |
+
grammar = \s* (
|
| 22 |
+
pwd |
|
| 23 |
+
ls |
|
| 24 |
+
(cd \s+ " ([^"]|\.)+ ") |
|
| 25 |
+
(cat \s+ " ([^"]|\.)+ ")
|
| 26 |
+
) \s*
|
| 27 |
+
|
| 28 |
+
|
| 29 |
+
What can we do with this grammar?
|
| 30 |
+
---------------------------------
|
| 31 |
+
|
| 32 |
+
- Syntax highlighting: We could use this for instance to give file names
|
| 33 |
+
different color.
|
| 34 |
+
- Parse the result: .. We can extract the file names and commands by using a
|
| 35 |
+
regular expression with named groups.
|
| 36 |
+
- Input validation: .. Don't accept anything that does not match this grammar.
|
| 37 |
+
When combined with a parser, we can also recursively do
|
| 38 |
+
filename validation (and accept only existing files.)
|
| 39 |
+
- Autocompletion: .... Each part of the grammar can have its own autocompleter.
|
| 40 |
+
"cat" has to be completed using file names, while "cd"
|
| 41 |
+
has to be completed using directory names.
|
| 42 |
+
|
| 43 |
+
How does it work?
|
| 44 |
+
-----------------
|
| 45 |
+
|
| 46 |
+
As a user of this library, you have to define the grammar of the input as a
|
| 47 |
+
regular expression. The parts of this grammar where autocompletion, validation
|
| 48 |
+
or any other processing is required need to be marked using a regex named
|
| 49 |
+
group. Like ``(?P<varname>...)`` for instance.
|
| 50 |
+
|
| 51 |
+
When the input is processed for validation (for instance), the regex will
|
| 52 |
+
execute, the named group is captured, and the validator associated with this
|
| 53 |
+
named group will test the captured string.
|
| 54 |
+
|
| 55 |
+
There is one tricky bit:
|
| 56 |
+
|
| 57 |
+
Often we operate on incomplete input (this is by definition the case for
|
| 58 |
+
autocompletion) and we have to decide for the cursor position in which
|
| 59 |
+
possible state the grammar it could be and in which way variables could be
|
| 60 |
+
matched up to that point.
|
| 61 |
+
|
| 62 |
+
To solve this problem, the compiler takes the original regular expression and
|
| 63 |
+
translates it into a set of other regular expressions which each match certain
|
| 64 |
+
prefixes of the original regular expression. We generate one prefix regular
|
| 65 |
+
expression for every named variable (with this variable being the end of that
|
| 66 |
+
expression).
|
| 67 |
+
|
| 68 |
+
|
| 69 |
+
TODO: some examples of:
|
| 70 |
+
- How to create a highlighter from this grammar.
|
| 71 |
+
- How to create a validator from this grammar.
|
| 72 |
+
- How to create an autocompleter from this grammar.
|
| 73 |
+
- How to create a parser from this grammar.
|
| 74 |
+
"""
|
| 75 |
+
|
| 76 |
+
from __future__ import annotations
|
| 77 |
+
|
| 78 |
+
from .compiler import compile
|
| 79 |
+
|
| 80 |
+
__all__ = ["compile"]
|
.venv/lib/python3.11/site-packages/prompt_toolkit/contrib/regular_languages/compiler.py
ADDED
|
@@ -0,0 +1,579 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
r"""
|
| 2 |
+
Compiler for a regular grammar.
|
| 3 |
+
|
| 4 |
+
Example usage::
|
| 5 |
+
|
| 6 |
+
# Create and compile grammar.
|
| 7 |
+
p = compile('add \s+ (?P<var1>[^\s]+) \s+ (?P<var2>[^\s]+)')
|
| 8 |
+
|
| 9 |
+
# Match input string.
|
| 10 |
+
m = p.match('add 23 432')
|
| 11 |
+
|
| 12 |
+
# Get variables.
|
| 13 |
+
m.variables().get('var1') # Returns "23"
|
| 14 |
+
m.variables().get('var2') # Returns "432"
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
Partial matches are possible::
|
| 18 |
+
|
| 19 |
+
# Create and compile grammar.
|
| 20 |
+
p = compile('''
|
| 21 |
+
# Operators with two arguments.
|
| 22 |
+
((?P<operator1>[^\s]+) \s+ (?P<var1>[^\s]+) \s+ (?P<var2>[^\s]+)) |
|
| 23 |
+
|
| 24 |
+
# Operators with only one arguments.
|
| 25 |
+
((?P<operator2>[^\s]+) \s+ (?P<var1>[^\s]+))
|
| 26 |
+
''')
|
| 27 |
+
|
| 28 |
+
# Match partial input string.
|
| 29 |
+
m = p.match_prefix('add 23')
|
| 30 |
+
|
| 31 |
+
# Get variables. (Notice that both operator1 and operator2 contain the
|
| 32 |
+
# value "add".) This is because our input is incomplete, and we don't know
|
| 33 |
+
# yet in which rule of the regex we we'll end up. It could also be that
|
| 34 |
+
# `operator1` and `operator2` have a different autocompleter and we want to
|
| 35 |
+
# call all possible autocompleters that would result in valid input.)
|
| 36 |
+
m.variables().get('var1') # Returns "23"
|
| 37 |
+
m.variables().get('operator1') # Returns "add"
|
| 38 |
+
m.variables().get('operator2') # Returns "add"
|
| 39 |
+
|
| 40 |
+
"""
|
| 41 |
+
|
| 42 |
+
from __future__ import annotations
|
| 43 |
+
|
| 44 |
+
import re
|
| 45 |
+
from typing import Callable, Dict, Iterable, Iterator, Pattern, TypeVar, overload
|
| 46 |
+
from typing import Match as RegexMatch
|
| 47 |
+
|
| 48 |
+
from .regex_parser import (
|
| 49 |
+
AnyNode,
|
| 50 |
+
Lookahead,
|
| 51 |
+
Node,
|
| 52 |
+
NodeSequence,
|
| 53 |
+
Regex,
|
| 54 |
+
Repeat,
|
| 55 |
+
Variable,
|
| 56 |
+
parse_regex,
|
| 57 |
+
tokenize_regex,
|
| 58 |
+
)
|
| 59 |
+
|
| 60 |
+
__all__ = ["compile", "Match", "Variables"]
|
| 61 |
+
|
| 62 |
+
|
| 63 |
+
# Name of the named group in the regex, matching trailing input.
|
| 64 |
+
# (Trailing input is when the input contains characters after the end of the
|
| 65 |
+
# expression has been matched.)
|
| 66 |
+
_INVALID_TRAILING_INPUT = "invalid_trailing"
|
| 67 |
+
|
| 68 |
+
EscapeFuncDict = Dict[str, Callable[[str], str]]
|
| 69 |
+
|
| 70 |
+
|
| 71 |
+
class _CompiledGrammar:
|
| 72 |
+
"""
|
| 73 |
+
Compiles a grammar. This will take the parse tree of a regular expression
|
| 74 |
+
and compile the grammar.
|
| 75 |
+
|
| 76 |
+
:param root_node: :class~`.regex_parser.Node` instance.
|
| 77 |
+
:param escape_funcs: `dict` mapping variable names to escape callables.
|
| 78 |
+
:param unescape_funcs: `dict` mapping variable names to unescape callables.
|
| 79 |
+
"""
|
| 80 |
+
|
| 81 |
+
def __init__(
|
| 82 |
+
self,
|
| 83 |
+
root_node: Node,
|
| 84 |
+
escape_funcs: EscapeFuncDict | None = None,
|
| 85 |
+
unescape_funcs: EscapeFuncDict | None = None,
|
| 86 |
+
) -> None:
|
| 87 |
+
self.root_node = root_node
|
| 88 |
+
self.escape_funcs = escape_funcs or {}
|
| 89 |
+
self.unescape_funcs = unescape_funcs or {}
|
| 90 |
+
|
| 91 |
+
#: Dictionary that will map the regex names to Node instances.
|
| 92 |
+
self._group_names_to_nodes: dict[
|
| 93 |
+
str, str
|
| 94 |
+
] = {} # Maps regex group names to varnames.
|
| 95 |
+
counter = [0]
|
| 96 |
+
|
| 97 |
+
def create_group_func(node: Variable) -> str:
|
| 98 |
+
name = f"n{counter[0]}"
|
| 99 |
+
self._group_names_to_nodes[name] = node.varname
|
| 100 |
+
counter[0] += 1
|
| 101 |
+
return name
|
| 102 |
+
|
| 103 |
+
# Compile regex strings.
|
| 104 |
+
self._re_pattern = f"^{self._transform(root_node, create_group_func)}$"
|
| 105 |
+
self._re_prefix_patterns = list(
|
| 106 |
+
self._transform_prefix(root_node, create_group_func)
|
| 107 |
+
)
|
| 108 |
+
|
| 109 |
+
# Compile the regex itself.
|
| 110 |
+
flags = re.DOTALL # Note that we don't need re.MULTILINE! (^ and $
|
| 111 |
+
# still represent the start and end of input text.)
|
| 112 |
+
self._re = re.compile(self._re_pattern, flags)
|
| 113 |
+
self._re_prefix = [re.compile(t, flags) for t in self._re_prefix_patterns]
|
| 114 |
+
|
| 115 |
+
# We compile one more set of regexes, similar to `_re_prefix`, but accept any trailing
|
| 116 |
+
# input. This will ensure that we can still highlight the input correctly, even when the
|
| 117 |
+
# input contains some additional characters at the end that don't match the grammar.)
|
| 118 |
+
self._re_prefix_with_trailing_input = [
|
| 119 |
+
re.compile(
|
| 120 |
+
r"(?:{})(?P<{}>.*?)$".format(t.rstrip("$"), _INVALID_TRAILING_INPUT),
|
| 121 |
+
flags,
|
| 122 |
+
)
|
| 123 |
+
for t in self._re_prefix_patterns
|
| 124 |
+
]
|
| 125 |
+
|
| 126 |
+
def escape(self, varname: str, value: str) -> str:
|
| 127 |
+
"""
|
| 128 |
+
Escape `value` to fit in the place of this variable into the grammar.
|
| 129 |
+
"""
|
| 130 |
+
f = self.escape_funcs.get(varname)
|
| 131 |
+
return f(value) if f else value
|
| 132 |
+
|
| 133 |
+
def unescape(self, varname: str, value: str) -> str:
|
| 134 |
+
"""
|
| 135 |
+
Unescape `value`.
|
| 136 |
+
"""
|
| 137 |
+
f = self.unescape_funcs.get(varname)
|
| 138 |
+
return f(value) if f else value
|
| 139 |
+
|
| 140 |
+
@classmethod
|
| 141 |
+
def _transform(
|
| 142 |
+
cls, root_node: Node, create_group_func: Callable[[Variable], str]
|
| 143 |
+
) -> str:
|
| 144 |
+
"""
|
| 145 |
+
Turn a :class:`Node` object into a regular expression.
|
| 146 |
+
|
| 147 |
+
:param root_node: The :class:`Node` instance for which we generate the grammar.
|
| 148 |
+
:param create_group_func: A callable which takes a `Node` and returns the next
|
| 149 |
+
free name for this node.
|
| 150 |
+
"""
|
| 151 |
+
|
| 152 |
+
def transform(node: Node) -> str:
|
| 153 |
+
# Turn `AnyNode` into an OR.
|
| 154 |
+
if isinstance(node, AnyNode):
|
| 155 |
+
return "(?:{})".format("|".join(transform(c) for c in node.children))
|
| 156 |
+
|
| 157 |
+
# Concatenate a `NodeSequence`
|
| 158 |
+
elif isinstance(node, NodeSequence):
|
| 159 |
+
return "".join(transform(c) for c in node.children)
|
| 160 |
+
|
| 161 |
+
# For Regex and Lookahead nodes, just insert them literally.
|
| 162 |
+
elif isinstance(node, Regex):
|
| 163 |
+
return node.regex
|
| 164 |
+
|
| 165 |
+
elif isinstance(node, Lookahead):
|
| 166 |
+
before = "(?!" if node.negative else "(="
|
| 167 |
+
return before + transform(node.childnode) + ")"
|
| 168 |
+
|
| 169 |
+
# A `Variable` wraps the children into a named group.
|
| 170 |
+
elif isinstance(node, Variable):
|
| 171 |
+
return f"(?P<{create_group_func(node)}>{transform(node.childnode)})"
|
| 172 |
+
|
| 173 |
+
# `Repeat`.
|
| 174 |
+
elif isinstance(node, Repeat):
|
| 175 |
+
if node.max_repeat is None:
|
| 176 |
+
if node.min_repeat == 0:
|
| 177 |
+
repeat_sign = "*"
|
| 178 |
+
elif node.min_repeat == 1:
|
| 179 |
+
repeat_sign = "+"
|
| 180 |
+
else:
|
| 181 |
+
repeat_sign = "{%i,%s}" % (
|
| 182 |
+
node.min_repeat,
|
| 183 |
+
("" if node.max_repeat is None else str(node.max_repeat)),
|
| 184 |
+
)
|
| 185 |
+
|
| 186 |
+
return "(?:{}){}{}".format(
|
| 187 |
+
transform(node.childnode),
|
| 188 |
+
repeat_sign,
|
| 189 |
+
("" if node.greedy else "?"),
|
| 190 |
+
)
|
| 191 |
+
else:
|
| 192 |
+
raise TypeError(f"Got {node!r}")
|
| 193 |
+
|
| 194 |
+
return transform(root_node)
|
| 195 |
+
|
| 196 |
+
@classmethod
|
| 197 |
+
def _transform_prefix(
|
| 198 |
+
cls, root_node: Node, create_group_func: Callable[[Variable], str]
|
| 199 |
+
) -> Iterable[str]:
|
| 200 |
+
"""
|
| 201 |
+
Yield all the regular expressions matching a prefix of the grammar
|
| 202 |
+
defined by the `Node` instance.
|
| 203 |
+
|
| 204 |
+
For each `Variable`, one regex pattern will be generated, with this
|
| 205 |
+
named group at the end. This is required because a regex engine will
|
| 206 |
+
terminate once a match is found. For autocompletion however, we need
|
| 207 |
+
the matches for all possible paths, so that we can provide completions
|
| 208 |
+
for each `Variable`.
|
| 209 |
+
|
| 210 |
+
- So, in the case of an `Any` (`A|B|C)', we generate a pattern for each
|
| 211 |
+
clause. This is one for `A`, one for `B` and one for `C`. Unless some
|
| 212 |
+
groups don't contain a `Variable`, then these can be merged together.
|
| 213 |
+
- In the case of a `NodeSequence` (`ABC`), we generate a pattern for
|
| 214 |
+
each prefix that ends with a variable, and one pattern for the whole
|
| 215 |
+
sequence. So, that's one for `A`, one for `AB` and one for `ABC`.
|
| 216 |
+
|
| 217 |
+
:param root_node: The :class:`Node` instance for which we generate the grammar.
|
| 218 |
+
:param create_group_func: A callable which takes a `Node` and returns the next
|
| 219 |
+
free name for this node.
|
| 220 |
+
"""
|
| 221 |
+
|
| 222 |
+
def contains_variable(node: Node) -> bool:
|
| 223 |
+
if isinstance(node, Regex):
|
| 224 |
+
return False
|
| 225 |
+
elif isinstance(node, Variable):
|
| 226 |
+
return True
|
| 227 |
+
elif isinstance(node, (Lookahead, Repeat)):
|
| 228 |
+
return contains_variable(node.childnode)
|
| 229 |
+
elif isinstance(node, (NodeSequence, AnyNode)):
|
| 230 |
+
return any(contains_variable(child) for child in node.children)
|
| 231 |
+
|
| 232 |
+
return False
|
| 233 |
+
|
| 234 |
+
def transform(node: Node) -> Iterable[str]:
|
| 235 |
+
# Generate separate pattern for all terms that contain variables
|
| 236 |
+
# within this OR. Terms that don't contain a variable can be merged
|
| 237 |
+
# together in one pattern.
|
| 238 |
+
if isinstance(node, AnyNode):
|
| 239 |
+
# If we have a definition like:
|
| 240 |
+
# (?P<name> .*) | (?P<city> .*)
|
| 241 |
+
# Then we want to be able to generate completions for both the
|
| 242 |
+
# name as well as the city. We do this by yielding two
|
| 243 |
+
# different regular expressions, because the engine won't
|
| 244 |
+
# follow multiple paths, if multiple are possible.
|
| 245 |
+
children_with_variable = []
|
| 246 |
+
children_without_variable = []
|
| 247 |
+
for c in node.children:
|
| 248 |
+
if contains_variable(c):
|
| 249 |
+
children_with_variable.append(c)
|
| 250 |
+
else:
|
| 251 |
+
children_without_variable.append(c)
|
| 252 |
+
|
| 253 |
+
for c in children_with_variable:
|
| 254 |
+
yield from transform(c)
|
| 255 |
+
|
| 256 |
+
# Merge options without variable together.
|
| 257 |
+
if children_without_variable:
|
| 258 |
+
yield "|".join(
|
| 259 |
+
r for c in children_without_variable for r in transform(c)
|
| 260 |
+
)
|
| 261 |
+
|
| 262 |
+
# For a sequence, generate a pattern for each prefix that ends with
|
| 263 |
+
# a variable + one pattern of the complete sequence.
|
| 264 |
+
# (This is because, for autocompletion, we match the text before
|
| 265 |
+
# the cursor, and completions are given for the variable that we
|
| 266 |
+
# match right before the cursor.)
|
| 267 |
+
elif isinstance(node, NodeSequence):
|
| 268 |
+
# For all components in the sequence, compute prefix patterns,
|
| 269 |
+
# as well as full patterns.
|
| 270 |
+
complete = [cls._transform(c, create_group_func) for c in node.children]
|
| 271 |
+
prefixes = [list(transform(c)) for c in node.children]
|
| 272 |
+
variable_nodes = [contains_variable(c) for c in node.children]
|
| 273 |
+
|
| 274 |
+
# If any child is contains a variable, we should yield a
|
| 275 |
+
# pattern up to that point, so that we are sure this will be
|
| 276 |
+
# matched.
|
| 277 |
+
for i in range(len(node.children)):
|
| 278 |
+
if variable_nodes[i]:
|
| 279 |
+
for c_str in prefixes[i]:
|
| 280 |
+
yield "".join(complete[:i]) + c_str
|
| 281 |
+
|
| 282 |
+
# If there are non-variable nodes, merge all the prefixes into
|
| 283 |
+
# one pattern. If the input is: "[part1] [part2] [part3]", then
|
| 284 |
+
# this gets compiled into:
|
| 285 |
+
# (complete1 + (complete2 + (complete3 | partial3) | partial2) | partial1 )
|
| 286 |
+
# For nodes that contain a variable, we skip the "|partial"
|
| 287 |
+
# part here, because thees are matched with the previous
|
| 288 |
+
# patterns.
|
| 289 |
+
if not all(variable_nodes):
|
| 290 |
+
result = []
|
| 291 |
+
|
| 292 |
+
# Start with complete patterns.
|
| 293 |
+
for i in range(len(node.children)):
|
| 294 |
+
result.append("(?:")
|
| 295 |
+
result.append(complete[i])
|
| 296 |
+
|
| 297 |
+
# Add prefix patterns.
|
| 298 |
+
for i in range(len(node.children) - 1, -1, -1):
|
| 299 |
+
if variable_nodes[i]:
|
| 300 |
+
# No need to yield a prefix for this one, we did
|
| 301 |
+
# the variable prefixes earlier.
|
| 302 |
+
result.append(")")
|
| 303 |
+
else:
|
| 304 |
+
result.append("|(?:")
|
| 305 |
+
# If this yields multiple, we should yield all combinations.
|
| 306 |
+
assert len(prefixes[i]) == 1
|
| 307 |
+
result.append(prefixes[i][0])
|
| 308 |
+
result.append("))")
|
| 309 |
+
|
| 310 |
+
yield "".join(result)
|
| 311 |
+
|
| 312 |
+
elif isinstance(node, Regex):
|
| 313 |
+
yield f"(?:{node.regex})?"
|
| 314 |
+
|
| 315 |
+
elif isinstance(node, Lookahead):
|
| 316 |
+
if node.negative:
|
| 317 |
+
yield f"(?!{cls._transform(node.childnode, create_group_func)})"
|
| 318 |
+
else:
|
| 319 |
+
# Not sure what the correct semantics are in this case.
|
| 320 |
+
# (Probably it's not worth implementing this.)
|
| 321 |
+
raise Exception("Positive lookahead not yet supported.")
|
| 322 |
+
|
| 323 |
+
elif isinstance(node, Variable):
|
| 324 |
+
# (Note that we should not append a '?' here. the 'transform'
|
| 325 |
+
# method will already recursively do that.)
|
| 326 |
+
for c_str in transform(node.childnode):
|
| 327 |
+
yield f"(?P<{create_group_func(node)}>{c_str})"
|
| 328 |
+
|
| 329 |
+
elif isinstance(node, Repeat):
|
| 330 |
+
# If we have a repetition of 8 times. That would mean that the
|
| 331 |
+
# current input could have for instance 7 times a complete
|
| 332 |
+
# match, followed by a partial match.
|
| 333 |
+
prefix = cls._transform(node.childnode, create_group_func)
|
| 334 |
+
|
| 335 |
+
if node.max_repeat == 1:
|
| 336 |
+
yield from transform(node.childnode)
|
| 337 |
+
else:
|
| 338 |
+
for c_str in transform(node.childnode):
|
| 339 |
+
if node.max_repeat:
|
| 340 |
+
repeat_sign = "{,%i}" % (node.max_repeat - 1)
|
| 341 |
+
else:
|
| 342 |
+
repeat_sign = "*"
|
| 343 |
+
yield "(?:{}){}{}{}".format(
|
| 344 |
+
prefix,
|
| 345 |
+
repeat_sign,
|
| 346 |
+
("" if node.greedy else "?"),
|
| 347 |
+
c_str,
|
| 348 |
+
)
|
| 349 |
+
|
| 350 |
+
else:
|
| 351 |
+
raise TypeError(f"Got {node!r}")
|
| 352 |
+
|
| 353 |
+
for r in transform(root_node):
|
| 354 |
+
yield f"^(?:{r})$"
|
| 355 |
+
|
| 356 |
+
def match(self, string: str) -> Match | None:
|
| 357 |
+
"""
|
| 358 |
+
Match the string with the grammar.
|
| 359 |
+
Returns a :class:`Match` instance or `None` when the input doesn't match the grammar.
|
| 360 |
+
|
| 361 |
+
:param string: The input string.
|
| 362 |
+
"""
|
| 363 |
+
m = self._re.match(string)
|
| 364 |
+
|
| 365 |
+
if m:
|
| 366 |
+
return Match(
|
| 367 |
+
string, [(self._re, m)], self._group_names_to_nodes, self.unescape_funcs
|
| 368 |
+
)
|
| 369 |
+
return None
|
| 370 |
+
|
| 371 |
+
def match_prefix(self, string: str) -> Match | None:
|
| 372 |
+
"""
|
| 373 |
+
Do a partial match of the string with the grammar. The returned
|
| 374 |
+
:class:`Match` instance can contain multiple representations of the
|
| 375 |
+
match. This will never return `None`. If it doesn't match at all, the "trailing input"
|
| 376 |
+
part will capture all of the input.
|
| 377 |
+
|
| 378 |
+
:param string: The input string.
|
| 379 |
+
"""
|
| 380 |
+
# First try to match using `_re_prefix`. If nothing is found, use the patterns that
|
| 381 |
+
# also accept trailing characters.
|
| 382 |
+
for patterns in [self._re_prefix, self._re_prefix_with_trailing_input]:
|
| 383 |
+
matches = [(r, r.match(string)) for r in patterns]
|
| 384 |
+
matches2 = [(r, m) for r, m in matches if m]
|
| 385 |
+
|
| 386 |
+
if matches2 != []:
|
| 387 |
+
return Match(
|
| 388 |
+
string, matches2, self._group_names_to_nodes, self.unescape_funcs
|
| 389 |
+
)
|
| 390 |
+
|
| 391 |
+
return None
|
| 392 |
+
|
| 393 |
+
|
| 394 |
+
class Match:
|
| 395 |
+
"""
|
| 396 |
+
:param string: The input string.
|
| 397 |
+
:param re_matches: List of (compiled_re_pattern, re_match) tuples.
|
| 398 |
+
:param group_names_to_nodes: Dictionary mapping all the re group names to the matching Node instances.
|
| 399 |
+
"""
|
| 400 |
+
|
| 401 |
+
def __init__(
|
| 402 |
+
self,
|
| 403 |
+
string: str,
|
| 404 |
+
re_matches: list[tuple[Pattern[str], RegexMatch[str]]],
|
| 405 |
+
group_names_to_nodes: dict[str, str],
|
| 406 |
+
unescape_funcs: dict[str, Callable[[str], str]],
|
| 407 |
+
):
|
| 408 |
+
self.string = string
|
| 409 |
+
self._re_matches = re_matches
|
| 410 |
+
self._group_names_to_nodes = group_names_to_nodes
|
| 411 |
+
self._unescape_funcs = unescape_funcs
|
| 412 |
+
|
| 413 |
+
def _nodes_to_regs(self) -> list[tuple[str, tuple[int, int]]]:
|
| 414 |
+
"""
|
| 415 |
+
Return a list of (varname, reg) tuples.
|
| 416 |
+
"""
|
| 417 |
+
|
| 418 |
+
def get_tuples() -> Iterable[tuple[str, tuple[int, int]]]:
|
| 419 |
+
for r, re_match in self._re_matches:
|
| 420 |
+
for group_name, group_index in r.groupindex.items():
|
| 421 |
+
if group_name != _INVALID_TRAILING_INPUT:
|
| 422 |
+
regs = re_match.regs
|
| 423 |
+
reg = regs[group_index]
|
| 424 |
+
node = self._group_names_to_nodes[group_name]
|
| 425 |
+
yield (node, reg)
|
| 426 |
+
|
| 427 |
+
return list(get_tuples())
|
| 428 |
+
|
| 429 |
+
def _nodes_to_values(self) -> list[tuple[str, str, tuple[int, int]]]:
|
| 430 |
+
"""
|
| 431 |
+
Returns list of (Node, string_value) tuples.
|
| 432 |
+
"""
|
| 433 |
+
|
| 434 |
+
def is_none(sl: tuple[int, int]) -> bool:
|
| 435 |
+
return sl[0] == -1 and sl[1] == -1
|
| 436 |
+
|
| 437 |
+
def get(sl: tuple[int, int]) -> str:
|
| 438 |
+
return self.string[sl[0] : sl[1]]
|
| 439 |
+
|
| 440 |
+
return [
|
| 441 |
+
(varname, get(slice), slice)
|
| 442 |
+
for varname, slice in self._nodes_to_regs()
|
| 443 |
+
if not is_none(slice)
|
| 444 |
+
]
|
| 445 |
+
|
| 446 |
+
def _unescape(self, varname: str, value: str) -> str:
|
| 447 |
+
unwrapper = self._unescape_funcs.get(varname)
|
| 448 |
+
return unwrapper(value) if unwrapper else value
|
| 449 |
+
|
| 450 |
+
def variables(self) -> Variables:
|
| 451 |
+
"""
|
| 452 |
+
Returns :class:`Variables` instance.
|
| 453 |
+
"""
|
| 454 |
+
return Variables(
|
| 455 |
+
[(k, self._unescape(k, v), sl) for k, v, sl in self._nodes_to_values()]
|
| 456 |
+
)
|
| 457 |
+
|
| 458 |
+
def trailing_input(self) -> MatchVariable | None:
|
| 459 |
+
"""
|
| 460 |
+
Get the `MatchVariable` instance, representing trailing input, if there is any.
|
| 461 |
+
"Trailing input" is input at the end that does not match the grammar anymore, but
|
| 462 |
+
when this is removed from the end of the input, the input would be a valid string.
|
| 463 |
+
"""
|
| 464 |
+
slices: list[tuple[int, int]] = []
|
| 465 |
+
|
| 466 |
+
# Find all regex group for the name _INVALID_TRAILING_INPUT.
|
| 467 |
+
for r, re_match in self._re_matches:
|
| 468 |
+
for group_name, group_index in r.groupindex.items():
|
| 469 |
+
if group_name == _INVALID_TRAILING_INPUT:
|
| 470 |
+
slices.append(re_match.regs[group_index])
|
| 471 |
+
|
| 472 |
+
# Take the smallest part. (Smaller trailing text means that a larger input has
|
| 473 |
+
# been matched, so that is better.)
|
| 474 |
+
if slices:
|
| 475 |
+
slice = (max(i[0] for i in slices), max(i[1] for i in slices))
|
| 476 |
+
value = self.string[slice[0] : slice[1]]
|
| 477 |
+
return MatchVariable("<trailing_input>", value, slice)
|
| 478 |
+
return None
|
| 479 |
+
|
| 480 |
+
def end_nodes(self) -> Iterable[MatchVariable]:
|
| 481 |
+
"""
|
| 482 |
+
Yields `MatchVariable` instances for all the nodes having their end
|
| 483 |
+
position at the end of the input string.
|
| 484 |
+
"""
|
| 485 |
+
for varname, reg in self._nodes_to_regs():
|
| 486 |
+
# If this part goes until the end of the input string.
|
| 487 |
+
if reg[1] == len(self.string):
|
| 488 |
+
value = self._unescape(varname, self.string[reg[0] : reg[1]])
|
| 489 |
+
yield MatchVariable(varname, value, (reg[0], reg[1]))
|
| 490 |
+
|
| 491 |
+
|
| 492 |
+
_T = TypeVar("_T")
|
| 493 |
+
|
| 494 |
+
|
| 495 |
+
class Variables:
|
| 496 |
+
def __init__(self, tuples: list[tuple[str, str, tuple[int, int]]]) -> None:
|
| 497 |
+
#: List of (varname, value, slice) tuples.
|
| 498 |
+
self._tuples = tuples
|
| 499 |
+
|
| 500 |
+
def __repr__(self) -> str:
|
| 501 |
+
return "{}({})".format(
|
| 502 |
+
self.__class__.__name__,
|
| 503 |
+
", ".join(f"{k}={v!r}" for k, v, _ in self._tuples),
|
| 504 |
+
)
|
| 505 |
+
|
| 506 |
+
@overload
|
| 507 |
+
def get(self, key: str) -> str | None: ...
|
| 508 |
+
|
| 509 |
+
@overload
|
| 510 |
+
def get(self, key: str, default: str | _T) -> str | _T: ...
|
| 511 |
+
|
| 512 |
+
def get(self, key: str, default: str | _T | None = None) -> str | _T | None:
|
| 513 |
+
items = self.getall(key)
|
| 514 |
+
return items[0] if items else default
|
| 515 |
+
|
| 516 |
+
def getall(self, key: str) -> list[str]:
|
| 517 |
+
return [v for k, v, _ in self._tuples if k == key]
|
| 518 |
+
|
| 519 |
+
def __getitem__(self, key: str) -> str | None:
|
| 520 |
+
return self.get(key)
|
| 521 |
+
|
| 522 |
+
def __iter__(self) -> Iterator[MatchVariable]:
|
| 523 |
+
"""
|
| 524 |
+
Yield `MatchVariable` instances.
|
| 525 |
+
"""
|
| 526 |
+
for varname, value, slice in self._tuples:
|
| 527 |
+
yield MatchVariable(varname, value, slice)
|
| 528 |
+
|
| 529 |
+
|
| 530 |
+
class MatchVariable:
|
| 531 |
+
"""
|
| 532 |
+
Represents a match of a variable in the grammar.
|
| 533 |
+
|
| 534 |
+
:param varname: (string) Name of the variable.
|
| 535 |
+
:param value: (string) Value of this variable.
|
| 536 |
+
:param slice: (start, stop) tuple, indicating the position of this variable
|
| 537 |
+
in the input string.
|
| 538 |
+
"""
|
| 539 |
+
|
| 540 |
+
def __init__(self, varname: str, value: str, slice: tuple[int, int]) -> None:
|
| 541 |
+
self.varname = varname
|
| 542 |
+
self.value = value
|
| 543 |
+
self.slice = slice
|
| 544 |
+
|
| 545 |
+
self.start = self.slice[0]
|
| 546 |
+
self.stop = self.slice[1]
|
| 547 |
+
|
| 548 |
+
def __repr__(self) -> str:
|
| 549 |
+
return f"{self.__class__.__name__}({self.varname!r}, {self.value!r})"
|
| 550 |
+
|
| 551 |
+
|
| 552 |
+
def compile(
|
| 553 |
+
expression: str,
|
| 554 |
+
escape_funcs: EscapeFuncDict | None = None,
|
| 555 |
+
unescape_funcs: EscapeFuncDict | None = None,
|
| 556 |
+
) -> _CompiledGrammar:
|
| 557 |
+
"""
|
| 558 |
+
Compile grammar (given as regex string), returning a `CompiledGrammar`
|
| 559 |
+
instance.
|
| 560 |
+
"""
|
| 561 |
+
return _compile_from_parse_tree(
|
| 562 |
+
parse_regex(tokenize_regex(expression)),
|
| 563 |
+
escape_funcs=escape_funcs,
|
| 564 |
+
unescape_funcs=unescape_funcs,
|
| 565 |
+
)
|
| 566 |
+
|
| 567 |
+
|
| 568 |
+
def _compile_from_parse_tree(
|
| 569 |
+
root_node: Node,
|
| 570 |
+
escape_funcs: EscapeFuncDict | None = None,
|
| 571 |
+
unescape_funcs: EscapeFuncDict | None = None,
|
| 572 |
+
) -> _CompiledGrammar:
|
| 573 |
+
"""
|
| 574 |
+
Compile grammar (given as parse tree), returning a `CompiledGrammar`
|
| 575 |
+
instance.
|
| 576 |
+
"""
|
| 577 |
+
return _CompiledGrammar(
|
| 578 |
+
root_node, escape_funcs=escape_funcs, unescape_funcs=unescape_funcs
|
| 579 |
+
)
|
.venv/lib/python3.11/site-packages/prompt_toolkit/contrib/regular_languages/completion.py
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Completer for a regular grammar.
|
| 3 |
+
"""
|
| 4 |
+
|
| 5 |
+
from __future__ import annotations
|
| 6 |
+
|
| 7 |
+
from typing import Iterable
|
| 8 |
+
|
| 9 |
+
from prompt_toolkit.completion import CompleteEvent, Completer, Completion
|
| 10 |
+
from prompt_toolkit.document import Document
|
| 11 |
+
|
| 12 |
+
from .compiler import Match, _CompiledGrammar
|
| 13 |
+
|
| 14 |
+
__all__ = [
|
| 15 |
+
"GrammarCompleter",
|
| 16 |
+
]
|
| 17 |
+
|
| 18 |
+
|
| 19 |
+
class GrammarCompleter(Completer):
|
| 20 |
+
"""
|
| 21 |
+
Completer which can be used for autocompletion according to variables in
|
| 22 |
+
the grammar. Each variable can have a different autocompleter.
|
| 23 |
+
|
| 24 |
+
:param compiled_grammar: `GrammarCompleter` instance.
|
| 25 |
+
:param completers: `dict` mapping variable names of the grammar to the
|
| 26 |
+
`Completer` instances to be used for each variable.
|
| 27 |
+
"""
|
| 28 |
+
|
| 29 |
+
def __init__(
|
| 30 |
+
self, compiled_grammar: _CompiledGrammar, completers: dict[str, Completer]
|
| 31 |
+
) -> None:
|
| 32 |
+
self.compiled_grammar = compiled_grammar
|
| 33 |
+
self.completers = completers
|
| 34 |
+
|
| 35 |
+
def get_completions(
|
| 36 |
+
self, document: Document, complete_event: CompleteEvent
|
| 37 |
+
) -> Iterable[Completion]:
|
| 38 |
+
m = self.compiled_grammar.match_prefix(document.text_before_cursor)
|
| 39 |
+
|
| 40 |
+
if m:
|
| 41 |
+
yield from self._remove_duplicates(
|
| 42 |
+
self._get_completions_for_match(m, complete_event)
|
| 43 |
+
)
|
| 44 |
+
|
| 45 |
+
def _get_completions_for_match(
|
| 46 |
+
self, match: Match, complete_event: CompleteEvent
|
| 47 |
+
) -> Iterable[Completion]:
|
| 48 |
+
"""
|
| 49 |
+
Yield all the possible completions for this input string.
|
| 50 |
+
(The completer assumes that the cursor position was at the end of the
|
| 51 |
+
input string.)
|
| 52 |
+
"""
|
| 53 |
+
for match_variable in match.end_nodes():
|
| 54 |
+
varname = match_variable.varname
|
| 55 |
+
start = match_variable.start
|
| 56 |
+
|
| 57 |
+
completer = self.completers.get(varname)
|
| 58 |
+
|
| 59 |
+
if completer:
|
| 60 |
+
text = match_variable.value
|
| 61 |
+
|
| 62 |
+
# Unwrap text.
|
| 63 |
+
unwrapped_text = self.compiled_grammar.unescape(varname, text)
|
| 64 |
+
|
| 65 |
+
# Create a document, for the completions API (text/cursor_position)
|
| 66 |
+
document = Document(unwrapped_text, len(unwrapped_text))
|
| 67 |
+
|
| 68 |
+
# Call completer
|
| 69 |
+
for completion in completer.get_completions(document, complete_event):
|
| 70 |
+
new_text = (
|
| 71 |
+
unwrapped_text[: len(text) + completion.start_position]
|
| 72 |
+
+ completion.text
|
| 73 |
+
)
|
| 74 |
+
|
| 75 |
+
# Wrap again.
|
| 76 |
+
yield Completion(
|
| 77 |
+
text=self.compiled_grammar.escape(varname, new_text),
|
| 78 |
+
start_position=start - len(match.string),
|
| 79 |
+
display=completion.display,
|
| 80 |
+
display_meta=completion.display_meta,
|
| 81 |
+
)
|
| 82 |
+
|
| 83 |
+
def _remove_duplicates(self, items: Iterable[Completion]) -> Iterable[Completion]:
|
| 84 |
+
"""
|
| 85 |
+
Remove duplicates, while keeping the order.
|
| 86 |
+
(Sometimes we have duplicates, because the there several matches of the
|
| 87 |
+
same grammar, each yielding similar completions.)
|
| 88 |
+
"""
|
| 89 |
+
|
| 90 |
+
def hash_completion(completion: Completion) -> tuple[str, int]:
|
| 91 |
+
return completion.text, completion.start_position
|
| 92 |
+
|
| 93 |
+
yielded_so_far: set[tuple[str, int]] = set()
|
| 94 |
+
|
| 95 |
+
for completion in items:
|
| 96 |
+
hash_value = hash_completion(completion)
|
| 97 |
+
|
| 98 |
+
if hash_value not in yielded_so_far:
|
| 99 |
+
yielded_so_far.add(hash_value)
|
| 100 |
+
yield completion
|
.venv/lib/python3.11/site-packages/prompt_toolkit/contrib/regular_languages/lexer.py
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
`GrammarLexer` is compatible with other lexers and can be used to highlight
|
| 3 |
+
the input using a regular grammar with annotations.
|
| 4 |
+
"""
|
| 5 |
+
|
| 6 |
+
from __future__ import annotations
|
| 7 |
+
|
| 8 |
+
from typing import Callable
|
| 9 |
+
|
| 10 |
+
from prompt_toolkit.document import Document
|
| 11 |
+
from prompt_toolkit.formatted_text.base import StyleAndTextTuples
|
| 12 |
+
from prompt_toolkit.formatted_text.utils import split_lines
|
| 13 |
+
from prompt_toolkit.lexers import Lexer
|
| 14 |
+
|
| 15 |
+
from .compiler import _CompiledGrammar
|
| 16 |
+
|
| 17 |
+
__all__ = [
|
| 18 |
+
"GrammarLexer",
|
| 19 |
+
]
|
| 20 |
+
|
| 21 |
+
|
| 22 |
+
class GrammarLexer(Lexer):
|
| 23 |
+
"""
|
| 24 |
+
Lexer which can be used for highlighting of fragments according to variables in the grammar.
|
| 25 |
+
|
| 26 |
+
(It does not actual lexing of the string, but it exposes an API, compatible
|
| 27 |
+
with the Pygments lexer class.)
|
| 28 |
+
|
| 29 |
+
:param compiled_grammar: Grammar as returned by the `compile()` function.
|
| 30 |
+
:param lexers: Dictionary mapping variable names of the regular grammar to
|
| 31 |
+
the lexers that should be used for this part. (This can
|
| 32 |
+
call other lexers recursively.) If you wish a part of the
|
| 33 |
+
grammar to just get one fragment, use a
|
| 34 |
+
`prompt_toolkit.lexers.SimpleLexer`.
|
| 35 |
+
"""
|
| 36 |
+
|
| 37 |
+
def __init__(
|
| 38 |
+
self,
|
| 39 |
+
compiled_grammar: _CompiledGrammar,
|
| 40 |
+
default_style: str = "",
|
| 41 |
+
lexers: dict[str, Lexer] | None = None,
|
| 42 |
+
) -> None:
|
| 43 |
+
self.compiled_grammar = compiled_grammar
|
| 44 |
+
self.default_style = default_style
|
| 45 |
+
self.lexers = lexers or {}
|
| 46 |
+
|
| 47 |
+
def _get_text_fragments(self, text: str) -> StyleAndTextTuples:
|
| 48 |
+
m = self.compiled_grammar.match_prefix(text)
|
| 49 |
+
|
| 50 |
+
if m:
|
| 51 |
+
characters: StyleAndTextTuples = [(self.default_style, c) for c in text]
|
| 52 |
+
|
| 53 |
+
for v in m.variables():
|
| 54 |
+
# If we have a `Lexer` instance for this part of the input.
|
| 55 |
+
# Tokenize recursively and apply tokens.
|
| 56 |
+
lexer = self.lexers.get(v.varname)
|
| 57 |
+
|
| 58 |
+
if lexer:
|
| 59 |
+
document = Document(text[v.start : v.stop])
|
| 60 |
+
lexer_tokens_for_line = lexer.lex_document(document)
|
| 61 |
+
text_fragments: StyleAndTextTuples = []
|
| 62 |
+
for i in range(len(document.lines)):
|
| 63 |
+
text_fragments.extend(lexer_tokens_for_line(i))
|
| 64 |
+
text_fragments.append(("", "\n"))
|
| 65 |
+
if text_fragments:
|
| 66 |
+
text_fragments.pop()
|
| 67 |
+
|
| 68 |
+
i = v.start
|
| 69 |
+
for t, s, *_ in text_fragments:
|
| 70 |
+
for c in s:
|
| 71 |
+
if characters[i][0] == self.default_style:
|
| 72 |
+
characters[i] = (t, characters[i][1])
|
| 73 |
+
i += 1
|
| 74 |
+
|
| 75 |
+
# Highlight trailing input.
|
| 76 |
+
trailing_input = m.trailing_input()
|
| 77 |
+
if trailing_input:
|
| 78 |
+
for i in range(trailing_input.start, trailing_input.stop):
|
| 79 |
+
characters[i] = ("class:trailing-input", characters[i][1])
|
| 80 |
+
|
| 81 |
+
return characters
|
| 82 |
+
else:
|
| 83 |
+
return [("", text)]
|
| 84 |
+
|
| 85 |
+
def lex_document(self, document: Document) -> Callable[[int], StyleAndTextTuples]:
|
| 86 |
+
lines = list(split_lines(self._get_text_fragments(document.text)))
|
| 87 |
+
|
| 88 |
+
def get_line(lineno: int) -> StyleAndTextTuples:
|
| 89 |
+
try:
|
| 90 |
+
return lines[lineno]
|
| 91 |
+
except IndexError:
|
| 92 |
+
return []
|
| 93 |
+
|
| 94 |
+
return get_line
|