Compare commits
59
Commits
master
..
62731ae766
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
62731ae766 | ||
|
|
b5cec0d049 | ||
|
|
c821f30880 | ||
|
|
13908d7ba7 | ||
|
|
ec69d4db73 | ||
|
|
511138316a | ||
|
|
d6e0823e21 | ||
|
|
54e7b58c24 | ||
|
|
77a3b71d31 | ||
|
|
21dd86ad3d | ||
|
|
fea303c898 | ||
|
|
e8653cd116 | ||
|
|
5e28fb1e5c | ||
|
|
609eaa8246 | ||
|
|
71bab687d7 | ||
|
|
060f68237b | ||
|
|
ee5f66fbbb | ||
|
|
7ee484f0c0 | ||
|
|
99dc917de3 | ||
|
|
a52d5243ab | ||
|
|
72fcccc8a9 | ||
|
|
0627ca5fd5 | ||
|
|
6225915fda | ||
|
|
e9c0565c04 | ||
|
|
bc3fe1eee1 | ||
|
|
b7a1cb9049 | ||
|
|
91df1df63a | ||
|
|
1a195f75b9 | ||
|
|
6946dde0ad | ||
|
|
608699c431 | ||
|
|
c233fdbac3 | ||
|
|
bd91eea411 | ||
|
|
13f2750a7e | ||
|
|
88a6451fa8 | ||
|
|
3ab71d6441 | ||
|
|
aaadba3812 | ||
|
|
3e920291a0 | ||
|
|
61b8bbc5fa | ||
|
|
2819598ae2 | ||
|
|
73d9ae0517 | ||
|
|
f5c506e210 | ||
|
|
bcd87801e6 | ||
|
|
80a4620724 | ||
|
|
5df23abb10 | ||
|
|
b54e0589d2 | ||
|
|
7a369886de | ||
|
|
dac0fa3fb1 | ||
|
|
d55dd4e5da | ||
|
|
813706265a | ||
|
|
228837bdb5 | ||
|
|
63454aef9d | ||
|
|
b6c4b94bbe | ||
|
|
a4be7a2117 | ||
|
|
1ae33eeeba | ||
|
|
0e3f3513e6 | ||
|
|
424bb34e06 | ||
|
|
7196dc5ec8 | ||
|
|
6c9136bdb2 | ||
|
|
b79220c1ae |
+131
@@ -0,0 +1,131 @@
|
|||||||
|
database.db
|
||||||
|
|
||||||
|
# Byte-compiled / optimized / DLL files
|
||||||
|
__pycache__/
|
||||||
|
*.py[cod]
|
||||||
|
*$py.class
|
||||||
|
|
||||||
|
# C extensions
|
||||||
|
*.so
|
||||||
|
|
||||||
|
# Distribution / packaging
|
||||||
|
.Python
|
||||||
|
build/
|
||||||
|
develop-eggs/
|
||||||
|
dist/
|
||||||
|
downloads/
|
||||||
|
eggs/
|
||||||
|
.eggs/
|
||||||
|
lib/
|
||||||
|
lib64/
|
||||||
|
parts/
|
||||||
|
sdist/
|
||||||
|
var/
|
||||||
|
wheels/
|
||||||
|
pip-wheel-metadata/
|
||||||
|
share/python-wheels/
|
||||||
|
*.egg-info/
|
||||||
|
.installed.cfg
|
||||||
|
*.egg
|
||||||
|
MANIFEST
|
||||||
|
|
||||||
|
# PyInstaller
|
||||||
|
# Usually these files are written by a python script from a template
|
||||||
|
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||||
|
*.manifest
|
||||||
|
*.spec
|
||||||
|
|
||||||
|
# Installer logs
|
||||||
|
pip-log.txt
|
||||||
|
pip-delete-this-directory.txt
|
||||||
|
|
||||||
|
# Unit test / coverage reports
|
||||||
|
htmlcov/
|
||||||
|
.tox/
|
||||||
|
.nox/
|
||||||
|
.coverage
|
||||||
|
.coverage.*
|
||||||
|
.cache
|
||||||
|
nosetests.xml
|
||||||
|
coverage.xml
|
||||||
|
*.cover
|
||||||
|
*.py,cover
|
||||||
|
.hypothesis/
|
||||||
|
.pytest_cache/
|
||||||
|
|
||||||
|
# Translations
|
||||||
|
*.mo
|
||||||
|
*.pot
|
||||||
|
|
||||||
|
# Django stuff:
|
||||||
|
*.log
|
||||||
|
local_settings.py
|
||||||
|
db.sqlite3
|
||||||
|
db.sqlite3-journal
|
||||||
|
|
||||||
|
# Flask stuff:
|
||||||
|
instance/
|
||||||
|
.webassets-cache
|
||||||
|
|
||||||
|
# Scrapy stuff:
|
||||||
|
.scrapy
|
||||||
|
|
||||||
|
# Sphinx documentation
|
||||||
|
docs/_build/
|
||||||
|
|
||||||
|
# PyBuilder
|
||||||
|
target/
|
||||||
|
|
||||||
|
# Jupyter Notebook
|
||||||
|
.ipynb_checkpoints
|
||||||
|
|
||||||
|
# IPython
|
||||||
|
profile_default/
|
||||||
|
ipython_config.py
|
||||||
|
|
||||||
|
# pyenv
|
||||||
|
.python-version
|
||||||
|
|
||||||
|
# pipenv
|
||||||
|
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
||||||
|
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
||||||
|
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
||||||
|
# install all needed dependencies.
|
||||||
|
#Pipfile.lock
|
||||||
|
|
||||||
|
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
|
||||||
|
__pypackages__/
|
||||||
|
|
||||||
|
# Celery stuff
|
||||||
|
celerybeat-schedule
|
||||||
|
celerybeat.pid
|
||||||
|
|
||||||
|
# SageMath parsed files
|
||||||
|
*.sage.py
|
||||||
|
|
||||||
|
# Environments
|
||||||
|
.env
|
||||||
|
.venv
|
||||||
|
env/
|
||||||
|
venv/
|
||||||
|
ENV/
|
||||||
|
env.bak/
|
||||||
|
venv.bak/
|
||||||
|
|
||||||
|
# Spyder project settings
|
||||||
|
.spyderproject
|
||||||
|
.spyproject
|
||||||
|
|
||||||
|
# Rope project settings
|
||||||
|
.ropeproject
|
||||||
|
|
||||||
|
# mkdocs documentation
|
||||||
|
/site
|
||||||
|
|
||||||
|
# mypy
|
||||||
|
.mypy_cache/
|
||||||
|
.dmypy.json
|
||||||
|
dmypy.json
|
||||||
|
|
||||||
|
# Pyre type checker
|
||||||
|
.pyre/
|
||||||
@@ -0,0 +1,339 @@
|
|||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
Version 2, June 1991
|
||||||
|
|
||||||
|
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The licenses for most software are designed to take away your
|
||||||
|
freedom to share and change it. By contrast, the GNU General Public
|
||||||
|
License is intended to guarantee your freedom to share and change free
|
||||||
|
software--to make sure the software is free for all its users. This
|
||||||
|
General Public License applies to most of the Free Software
|
||||||
|
Foundation's software and to any other program whose authors commit to
|
||||||
|
using it. (Some other Free Software Foundation software is covered by
|
||||||
|
the GNU Lesser General Public License instead.) You can apply it to
|
||||||
|
your programs, too.
|
||||||
|
|
||||||
|
When we speak of free software, we are referring to freedom, not
|
||||||
|
price. Our General Public Licenses are designed to make sure that you
|
||||||
|
have the freedom to distribute copies of free software (and charge for
|
||||||
|
this service if you wish), that you receive source code or can get it
|
||||||
|
if you want it, that you can change the software or use pieces of it
|
||||||
|
in new free programs; and that you know you can do these things.
|
||||||
|
|
||||||
|
To protect your rights, we need to make restrictions that forbid
|
||||||
|
anyone to deny you these rights or to ask you to surrender the rights.
|
||||||
|
These restrictions translate to certain responsibilities for you if you
|
||||||
|
distribute copies of the software, or if you modify it.
|
||||||
|
|
||||||
|
For example, if you distribute copies of such a program, whether
|
||||||
|
gratis or for a fee, you must give the recipients all the rights that
|
||||||
|
you have. You must make sure that they, too, receive or can get the
|
||||||
|
source code. And you must show them these terms so they know their
|
||||||
|
rights.
|
||||||
|
|
||||||
|
We protect your rights with two steps: (1) copyright the software, and
|
||||||
|
(2) offer you this license which gives you legal permission to copy,
|
||||||
|
distribute and/or modify the software.
|
||||||
|
|
||||||
|
Also, for each author's protection and ours, we want to make certain
|
||||||
|
that everyone understands that there is no warranty for this free
|
||||||
|
software. If the software is modified by someone else and passed on, we
|
||||||
|
want its recipients to know that what they have is not the original, so
|
||||||
|
that any problems introduced by others will not reflect on the original
|
||||||
|
authors' reputations.
|
||||||
|
|
||||||
|
Finally, any free program is threatened constantly by software
|
||||||
|
patents. We wish to avoid the danger that redistributors of a free
|
||||||
|
program will individually obtain patent licenses, in effect making the
|
||||||
|
program proprietary. To prevent this, we have made it clear that any
|
||||||
|
patent must be licensed for everyone's free use or not licensed at all.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow.
|
||||||
|
|
||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||||
|
|
||||||
|
0. This License applies to any program or other work which contains
|
||||||
|
a notice placed by the copyright holder saying it may be distributed
|
||||||
|
under the terms of this General Public License. The "Program", below,
|
||||||
|
refers to any such program or work, and a "work based on the Program"
|
||||||
|
means either the Program or any derivative work under copyright law:
|
||||||
|
that is to say, a work containing the Program or a portion of it,
|
||||||
|
either verbatim or with modifications and/or translated into another
|
||||||
|
language. (Hereinafter, translation is included without limitation in
|
||||||
|
the term "modification".) Each licensee is addressed as "you".
|
||||||
|
|
||||||
|
Activities other than copying, distribution and modification are not
|
||||||
|
covered by this License; they are outside its scope. The act of
|
||||||
|
running the Program is not restricted, and the output from the Program
|
||||||
|
is covered only if its contents constitute a work based on the
|
||||||
|
Program (independent of having been made by running the Program).
|
||||||
|
Whether that is true depends on what the Program does.
|
||||||
|
|
||||||
|
1. You may copy and distribute verbatim copies of the Program's
|
||||||
|
source code as you receive it, in any medium, provided that you
|
||||||
|
conspicuously and appropriately publish on each copy an appropriate
|
||||||
|
copyright notice and disclaimer of warranty; keep intact all the
|
||||||
|
notices that refer to this License and to the absence of any warranty;
|
||||||
|
and give any other recipients of the Program a copy of this License
|
||||||
|
along with the Program.
|
||||||
|
|
||||||
|
You may charge a fee for the physical act of transferring a copy, and
|
||||||
|
you may at your option offer warranty protection in exchange for a fee.
|
||||||
|
|
||||||
|
2. You may modify your copy or copies of the Program or any portion
|
||||||
|
of it, thus forming a work based on the Program, and copy and
|
||||||
|
distribute such modifications or work under the terms of Section 1
|
||||||
|
above, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) You must cause the modified files to carry prominent notices
|
||||||
|
stating that you changed the files and the date of any change.
|
||||||
|
|
||||||
|
b) You must cause any work that you distribute or publish, that in
|
||||||
|
whole or in part contains or is derived from the Program or any
|
||||||
|
part thereof, to be licensed as a whole at no charge to all third
|
||||||
|
parties under the terms of this License.
|
||||||
|
|
||||||
|
c) If the modified program normally reads commands interactively
|
||||||
|
when run, you must cause it, when started running for such
|
||||||
|
interactive use in the most ordinary way, to print or display an
|
||||||
|
announcement including an appropriate copyright notice and a
|
||||||
|
notice that there is no warranty (or else, saying that you provide
|
||||||
|
a warranty) and that users may redistribute the program under
|
||||||
|
these conditions, and telling the user how to view a copy of this
|
||||||
|
License. (Exception: if the Program itself is interactive but
|
||||||
|
does not normally print such an announcement, your work based on
|
||||||
|
the Program is not required to print an announcement.)
|
||||||
|
|
||||||
|
These requirements apply to the modified work as a whole. If
|
||||||
|
identifiable sections of that work are not derived from the Program,
|
||||||
|
and can be reasonably considered independent and separate works in
|
||||||
|
themselves, then this License, and its terms, do not apply to those
|
||||||
|
sections when you distribute them as separate works. But when you
|
||||||
|
distribute the same sections as part of a whole which is a work based
|
||||||
|
on the Program, the distribution of the whole must be on the terms of
|
||||||
|
this License, whose permissions for other licensees extend to the
|
||||||
|
entire whole, and thus to each and every part regardless of who wrote it.
|
||||||
|
|
||||||
|
Thus, it is not the intent of this section to claim rights or contest
|
||||||
|
your rights to work written entirely by you; rather, the intent is to
|
||||||
|
exercise the right to control the distribution of derivative or
|
||||||
|
collective works based on the Program.
|
||||||
|
|
||||||
|
In addition, mere aggregation of another work not based on the Program
|
||||||
|
with the Program (or with a work based on the Program) on a volume of
|
||||||
|
a storage or distribution medium does not bring the other work under
|
||||||
|
the scope of this License.
|
||||||
|
|
||||||
|
3. You may copy and distribute the Program (or a work based on it,
|
||||||
|
under Section 2) in object code or executable form under the terms of
|
||||||
|
Sections 1 and 2 above provided that you also do one of the following:
|
||||||
|
|
||||||
|
a) Accompany it with the complete corresponding machine-readable
|
||||||
|
source code, which must be distributed under the terms of Sections
|
||||||
|
1 and 2 above on a medium customarily used for software interchange; or,
|
||||||
|
|
||||||
|
b) Accompany it with a written offer, valid for at least three
|
||||||
|
years, to give any third party, for a charge no more than your
|
||||||
|
cost of physically performing source distribution, a complete
|
||||||
|
machine-readable copy of the corresponding source code, to be
|
||||||
|
distributed under the terms of Sections 1 and 2 above on a medium
|
||||||
|
customarily used for software interchange; or,
|
||||||
|
|
||||||
|
c) Accompany it with the information you received as to the offer
|
||||||
|
to distribute corresponding source code. (This alternative is
|
||||||
|
allowed only for noncommercial distribution and only if you
|
||||||
|
received the program in object code or executable form with such
|
||||||
|
an offer, in accord with Subsection b above.)
|
||||||
|
|
||||||
|
The source code for a work means the preferred form of the work for
|
||||||
|
making modifications to it. For an executable work, complete source
|
||||||
|
code means all the source code for all modules it contains, plus any
|
||||||
|
associated interface definition files, plus the scripts used to
|
||||||
|
control compilation and installation of the executable. However, as a
|
||||||
|
special exception, the source code distributed need not include
|
||||||
|
anything that is normally distributed (in either source or binary
|
||||||
|
form) with the major components (compiler, kernel, and so on) of the
|
||||||
|
operating system on which the executable runs, unless that component
|
||||||
|
itself accompanies the executable.
|
||||||
|
|
||||||
|
If distribution of executable or object code is made by offering
|
||||||
|
access to copy from a designated place, then offering equivalent
|
||||||
|
access to copy the source code from the same place counts as
|
||||||
|
distribution of the source code, even though third parties are not
|
||||||
|
compelled to copy the source along with the object code.
|
||||||
|
|
||||||
|
4. You may not copy, modify, sublicense, or distribute the Program
|
||||||
|
except as expressly provided under this License. Any attempt
|
||||||
|
otherwise to copy, modify, sublicense or distribute the Program is
|
||||||
|
void, and will automatically terminate your rights under this License.
|
||||||
|
However, parties who have received copies, or rights, from you under
|
||||||
|
this License will not have their licenses terminated so long as such
|
||||||
|
parties remain in full compliance.
|
||||||
|
|
||||||
|
5. You are not required to accept this License, since you have not
|
||||||
|
signed it. However, nothing else grants you permission to modify or
|
||||||
|
distribute the Program or its derivative works. These actions are
|
||||||
|
prohibited by law if you do not accept this License. Therefore, by
|
||||||
|
modifying or distributing the Program (or any work based on the
|
||||||
|
Program), you indicate your acceptance of this License to do so, and
|
||||||
|
all its terms and conditions for copying, distributing or modifying
|
||||||
|
the Program or works based on it.
|
||||||
|
|
||||||
|
6. Each time you redistribute the Program (or any work based on the
|
||||||
|
Program), the recipient automatically receives a license from the
|
||||||
|
original licensor to copy, distribute or modify the Program subject to
|
||||||
|
these terms and conditions. You may not impose any further
|
||||||
|
restrictions on the recipients' exercise of the rights granted herein.
|
||||||
|
You are not responsible for enforcing compliance by third parties to
|
||||||
|
this License.
|
||||||
|
|
||||||
|
7. If, as a consequence of a court judgment or allegation of patent
|
||||||
|
infringement or for any other reason (not limited to patent issues),
|
||||||
|
conditions are imposed on you (whether by court order, agreement or
|
||||||
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
|
excuse you from the conditions of this License. If you cannot
|
||||||
|
distribute so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you
|
||||||
|
may not distribute the Program at all. For example, if a patent
|
||||||
|
license would not permit royalty-free redistribution of the Program by
|
||||||
|
all those who receive copies directly or indirectly through you, then
|
||||||
|
the only way you could satisfy both it and this License would be to
|
||||||
|
refrain entirely from distribution of the Program.
|
||||||
|
|
||||||
|
If any portion of this section is held invalid or unenforceable under
|
||||||
|
any particular circumstance, the balance of the section is intended to
|
||||||
|
apply and the section as a whole is intended to apply in other
|
||||||
|
circumstances.
|
||||||
|
|
||||||
|
It is not the purpose of this section to induce you to infringe any
|
||||||
|
patents or other property right claims or to contest validity of any
|
||||||
|
such claims; this section has the sole purpose of protecting the
|
||||||
|
integrity of the free software distribution system, which is
|
||||||
|
implemented by public license practices. Many people have made
|
||||||
|
generous contributions to the wide range of software distributed
|
||||||
|
through that system in reliance on consistent application of that
|
||||||
|
system; it is up to the author/donor to decide if he or she is willing
|
||||||
|
to distribute software through any other system and a licensee cannot
|
||||||
|
impose that choice.
|
||||||
|
|
||||||
|
This section is intended to make thoroughly clear what is believed to
|
||||||
|
be a consequence of the rest of this License.
|
||||||
|
|
||||||
|
8. If the distribution and/or use of the Program is restricted in
|
||||||
|
certain countries either by patents or by copyrighted interfaces, the
|
||||||
|
original copyright holder who places the Program under this License
|
||||||
|
may add an explicit geographical distribution limitation excluding
|
||||||
|
those countries, so that distribution is permitted only in or among
|
||||||
|
countries not thus excluded. In such case, this License incorporates
|
||||||
|
the limitation as if written in the body of this License.
|
||||||
|
|
||||||
|
9. The Free Software Foundation may publish revised and/or new versions
|
||||||
|
of the General Public License from time to time. Such new versions will
|
||||||
|
be similar in spirit to the present version, but may differ in detail to
|
||||||
|
address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the Program
|
||||||
|
specifies a version number of this License which applies to it and "any
|
||||||
|
later version", you have the option of following the terms and conditions
|
||||||
|
either of that version or of any later version published by the Free
|
||||||
|
Software Foundation. If the Program does not specify a version number of
|
||||||
|
this License, you may choose any version ever published by the Free Software
|
||||||
|
Foundation.
|
||||||
|
|
||||||
|
10. If you wish to incorporate parts of the Program into other free
|
||||||
|
programs whose distribution conditions are different, write to the author
|
||||||
|
to ask for permission. For software which is copyrighted by the Free
|
||||||
|
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||||
|
make exceptions for this. Our decision will be guided by the two goals
|
||||||
|
of preserving the free status of all derivatives of our free software and
|
||||||
|
of promoting the sharing and reuse of software generally.
|
||||||
|
|
||||||
|
NO WARRANTY
|
||||||
|
|
||||||
|
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||||
|
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||||
|
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||||
|
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||||
|
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||||
|
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||||
|
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||||
|
REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||||
|
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||||
|
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||||
|
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||||
|
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||||
|
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||||
|
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||||
|
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGES.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
How to Apply These Terms to Your New Programs
|
||||||
|
|
||||||
|
If you develop a new program, and you want it to be of the greatest
|
||||||
|
possible use to the public, the best way to achieve this is to make it
|
||||||
|
free software which everyone can redistribute and change under these terms.
|
||||||
|
|
||||||
|
To do so, attach the following notices to the program. It is safest
|
||||||
|
to attach them to the start of each source file to most effectively
|
||||||
|
convey the exclusion of warranty; and each file should have at least
|
||||||
|
the "copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
|
<one line to give the program's name and a brief idea of what it does.>
|
||||||
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along
|
||||||
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
If the program is interactive, make it output a short notice like this
|
||||||
|
when it starts in an interactive mode:
|
||||||
|
|
||||||
|
Gnomovision version 69, Copyright (C) year name of author
|
||||||
|
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||||
|
This is free software, and you are welcome to redistribute it
|
||||||
|
under certain conditions; type `show c' for details.
|
||||||
|
|
||||||
|
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||||
|
parts of the General Public License. Of course, the commands you use may
|
||||||
|
be called something other than `show w' and `show c'; they could even be
|
||||||
|
mouse-clicks or menu items--whatever suits your program.
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or your
|
||||||
|
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||||
|
necessary. Here is a sample; alter the names:
|
||||||
|
|
||||||
|
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||||
|
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||||
|
|
||||||
|
<signature of Ty Coon>, 1 April 1989
|
||||||
|
Ty Coon, President of Vice
|
||||||
|
|
||||||
|
This General Public License does not permit incorporating your program into
|
||||||
|
proprietary programs. If your program is a subroutine library, you may
|
||||||
|
consider it more useful to permit linking proprietary applications with the
|
||||||
|
library. If this is what you want to do, use the GNU Lesser General
|
||||||
|
Public License instead of this License.
|
||||||
@@ -1,12 +1,13 @@
|
|||||||
# Newton Editor
|
# Newton
|
||||||
|
A Python + Gtk 3 based quasi-IDE.
|
||||||
|
|
||||||
### Note
|
### Note
|
||||||
This repository is comprised of two branches with the first using gtk and GtkSource.View widgets to handle text editing.
|
[TODO](TODO.md)
|
||||||
The second bramch uses Angular + Electron with Ace Editor component to handle text editing.
|
|
||||||
Both branches have similar design patterns to Vim with 'buffers' loading to views than the traditionally understood one view per one one tab pattern.
|
|
||||||
|
|
||||||
* [release/newton_gtk](https://code.itdominator.com/itdominator/Newton-Editor/src/branch/release/newton_gtk/)
|
### Images
|
||||||
* [release/newton_electron](https://code.itdominator.com/itdominator/Newton-Editor/src/branch/release/newton_electron/)
|

|
||||||
|

|
||||||
# LSP
|

|
||||||
* [Newton-LSP](https://code.itdominator.com/itdominator/Newton-LSP)
|

|
||||||
|

|
||||||
|

|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
___
|
||||||
|
### Add
|
||||||
|
1. Add Godot LSP Client
|
||||||
|
1. Add TreeSitter
|
||||||
|
1. Add Collapsable code blocks
|
||||||
|
1. Add Terminal plugin
|
||||||
|
1. Add Plugin to <Shift\><Ctrl\>| and <Ctrl\>| to split views up, down, left, right
|
||||||
|
1. Add <Ctrl\>i to **lsp_manager** to list who implements xyz
|
||||||
|
|
||||||
|
___
|
||||||
|
### Change
|
||||||
|
1. Make **telescope** plugin a generic base to allow query mode additions through plugins
|
||||||
|
1. Make **lsp_manager** hard coded values configurable, plus add respective fields to UI
|
||||||
|
|
||||||
|
___
|
||||||
|
### Fix
|
||||||
|
- Fix on lsp client unload to close files lsp side and unload server endpoint
|
||||||
|
|
||||||
|
___
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 1.0 MiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.3 MiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.1 MiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.1 MiB |
Binary file not shown.
|
After Width: | Height: | Size: 951 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 901 KiB |
@@ -0,0 +1,3 @@
|
|||||||
|
"""
|
||||||
|
Plugin Module
|
||||||
|
"""
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
"""
|
||||||
|
Plugin Package
|
||||||
|
"""
|
||||||
@@ -0,0 +1,97 @@
|
|||||||
|
# Python imports
|
||||||
|
|
||||||
|
# Lib imports
|
||||||
|
|
||||||
|
# Application imports
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class Autopairs:
|
||||||
|
def __init__(self):
|
||||||
|
...
|
||||||
|
|
||||||
|
def handle_word_wrap(self, buffer, char_str: str):
|
||||||
|
wrap_block = self.get_wrap_block(char_str)
|
||||||
|
if not wrap_block: return
|
||||||
|
|
||||||
|
selection = buffer.get_selection_bounds()
|
||||||
|
if not selection:
|
||||||
|
self.insert_pair(buffer, char_str, wrap_block)
|
||||||
|
return True
|
||||||
|
|
||||||
|
self.wrap_selection(buffer, char_str, wrap_block, selection)
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def insert_pair(
|
||||||
|
self, buffer, char_str: str, wrap_block: tuple
|
||||||
|
):
|
||||||
|
buffer.begin_user_action()
|
||||||
|
|
||||||
|
left_block, right_block = wrap_block
|
||||||
|
insert_mark = buffer.get_insert()
|
||||||
|
|
||||||
|
insert_itr = buffer.get_iter_at_mark(insert_mark)
|
||||||
|
buffer.insert(insert_itr, f"{left_block}{right_block}")
|
||||||
|
insert_itr = buffer.get_iter_at_mark( insert_mark )
|
||||||
|
insert_itr.backward_char()
|
||||||
|
|
||||||
|
buffer.place_cursor(insert_itr)
|
||||||
|
|
||||||
|
buffer.end_user_action()
|
||||||
|
|
||||||
|
def wrap_selection(
|
||||||
|
self, buffer, char_str: str, wrap_block: tuple, selection
|
||||||
|
):
|
||||||
|
left_block, \
|
||||||
|
right_block = wrap_block
|
||||||
|
start_itr, \
|
||||||
|
end_itr = selection
|
||||||
|
data = buffer.get_text(
|
||||||
|
start_itr, end_itr, include_hidden_chars = False
|
||||||
|
)
|
||||||
|
start_mark = buffer.create_mark("startclose", start_itr, False)
|
||||||
|
end_mark = buffer.create_mark("endclose", end_itr, True)
|
||||||
|
|
||||||
|
buffer.begin_user_action()
|
||||||
|
|
||||||
|
buffer.insert(start_itr, left_block)
|
||||||
|
end_itr = buffer.get_iter_at_mark(end_mark)
|
||||||
|
buffer.insert(end_itr, right_block)
|
||||||
|
|
||||||
|
start = buffer.get_iter_at_mark(start_mark)
|
||||||
|
end = buffer.get_iter_at_mark(end_mark)
|
||||||
|
|
||||||
|
buffer.select_range(start, end)
|
||||||
|
buffer.delete_mark_by_name("startclose")
|
||||||
|
buffer.delete_mark_by_name("endclose")
|
||||||
|
|
||||||
|
buffer.end_user_action()
|
||||||
|
|
||||||
|
def get_wrap_block(self, char_str) -> tuple:
|
||||||
|
left_block = ""
|
||||||
|
right_block = ""
|
||||||
|
|
||||||
|
match char_str:
|
||||||
|
case "(" | ")":
|
||||||
|
left_block = "("
|
||||||
|
right_block = ")"
|
||||||
|
case "[" | "]":
|
||||||
|
left_block = "["
|
||||||
|
right_block = "]"
|
||||||
|
case "{" | "}":
|
||||||
|
left_block = "{"
|
||||||
|
right_block = "}"
|
||||||
|
case '"':
|
||||||
|
left_block = '"'
|
||||||
|
right_block = '"'
|
||||||
|
case "'":
|
||||||
|
left_block = "'"
|
||||||
|
right_block = "'"
|
||||||
|
case "`":
|
||||||
|
left_block = "`"
|
||||||
|
right_block = "`"
|
||||||
|
case _:
|
||||||
|
return ()
|
||||||
|
|
||||||
|
return left_block, right_block
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"name": "Autopairs",
|
||||||
|
"author": "ITDominator",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"support": "",
|
||||||
|
"requests": {}
|
||||||
|
}
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
# Python imports
|
||||||
|
|
||||||
|
# Lib imports
|
||||||
|
|
||||||
|
# Application imports
|
||||||
|
from libs.event_factory import Event_Factory, Code_Event_Types
|
||||||
|
|
||||||
|
from plugins.plugin_types import PluginCode
|
||||||
|
|
||||||
|
from .autopairs import Autopairs
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
autopairs = Autopairs()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class Plugin(PluginCode):
|
||||||
|
def __init__(self):
|
||||||
|
super(Plugin, self).__init__()
|
||||||
|
|
||||||
|
def _controller_message(self, event: Code_Event_Types.CodeEvent):
|
||||||
|
...
|
||||||
|
|
||||||
|
def load(self):
|
||||||
|
event = Event_Factory.create_event("register_command",
|
||||||
|
command_name = "autopairs",
|
||||||
|
command = Handler,
|
||||||
|
binding_mode = "held",
|
||||||
|
binding = [
|
||||||
|
"'", "`", "[", "]",
|
||||||
|
'<Shift>"',
|
||||||
|
'<Shift>(',
|
||||||
|
'<Shift>)',
|
||||||
|
'<Shift>{',
|
||||||
|
'<Shift>}'
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
self.emit_to("source_views", event)
|
||||||
|
|
||||||
|
def unload(self):
|
||||||
|
event = Event_Factory.create_event("unregister_command",
|
||||||
|
command_name = "autopairs",
|
||||||
|
command = Handler,
|
||||||
|
binding_mode = "held",
|
||||||
|
binding = [
|
||||||
|
"'", "`", "[", "]",
|
||||||
|
'<Shift>"',
|
||||||
|
'<Shift>(',
|
||||||
|
'<Shift>)',
|
||||||
|
'<Shift>{',
|
||||||
|
'<Shift>}'
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
self.emit_to("source_views", event)
|
||||||
|
autopairs = None
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
class Handler:
|
||||||
|
@staticmethod
|
||||||
|
def execute(
|
||||||
|
view: any,
|
||||||
|
char_str: str,
|
||||||
|
*args,
|
||||||
|
**kwargs
|
||||||
|
):
|
||||||
|
logger.debug("Command: Autopairs")
|
||||||
|
autopairs.handle_word_wrap(view.get_buffer(), char_str)
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
"""
|
||||||
|
Pligin Module
|
||||||
|
"""
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
"""
|
||||||
|
Pligin Package
|
||||||
|
"""
|
||||||
@@ -0,0 +1,111 @@
|
|||||||
|
# Python imports
|
||||||
|
import colorsys
|
||||||
|
|
||||||
|
# Lib imports
|
||||||
|
|
||||||
|
# Application imports
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class ColorConverterMixinException(Exception):
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class ColorConverterMixin:
|
||||||
|
# NOTE: HSV HSL, and Hex Alpha parsing are available in Gtk 4.0- not lower.
|
||||||
|
# So, for compatability we're gunna convert to rgba string ourselves...
|
||||||
|
def get_color_text(self, buffer, start_itr, end_itr):
|
||||||
|
text = buffer.get_text(start_itr, end_itr, include_hidden_chars = False)
|
||||||
|
|
||||||
|
try:
|
||||||
|
if "hsl" in text:
|
||||||
|
text = self.hsl_to_rgb(text)
|
||||||
|
|
||||||
|
if "hsv" in text:
|
||||||
|
text = self.hsv_to_rgb(text)
|
||||||
|
|
||||||
|
if "#" == text[0]:
|
||||||
|
hex = text[1:]
|
||||||
|
size = len(hex)
|
||||||
|
if size in [4, 8, 16]:
|
||||||
|
rgba = self.hex_to_rgba(hex, size)
|
||||||
|
logger.debug(f"Colorize Plugin: RGBA = {rgba}")
|
||||||
|
|
||||||
|
except ColorConverterMixinException as e:
|
||||||
|
...
|
||||||
|
|
||||||
|
return text
|
||||||
|
|
||||||
|
def hex_to_rgba(self, hex: str, size: int) -> str:
|
||||||
|
rgba = []
|
||||||
|
slots = None
|
||||||
|
step = 2
|
||||||
|
bytes = 16
|
||||||
|
|
||||||
|
if size == 4: # NOTE: RGBA
|
||||||
|
step = 1
|
||||||
|
slots = (0, 1, 2, 3)
|
||||||
|
|
||||||
|
if size == 6: # NOTE: RR GG BB
|
||||||
|
slots = (0, 2, 4)
|
||||||
|
|
||||||
|
if size == 8: # NOTE: RR GG BB AA
|
||||||
|
step = 2
|
||||||
|
slots = (0, 2, 4, 6)
|
||||||
|
|
||||||
|
if size == 16: # NOTE: RRRR GGGG BBBB AAAA
|
||||||
|
step = 4
|
||||||
|
slots = (0, 4, 8, 12)
|
||||||
|
|
||||||
|
for i in slots:
|
||||||
|
v = int(hex[i : i + step], bytes)
|
||||||
|
rgba.append(v)
|
||||||
|
|
||||||
|
|
||||||
|
rgb_sub = ','.join(map(str, tuple(rgba)))
|
||||||
|
|
||||||
|
return f"rgba({rgb_sub})"
|
||||||
|
# return tuple(rgba)
|
||||||
|
|
||||||
|
|
||||||
|
def hsl_to_rgb(self, text: str) -> str:
|
||||||
|
_h, _s , _l = text.replace("hsl", "") \
|
||||||
|
.replace("deg", "") \
|
||||||
|
.replace("(", "") \
|
||||||
|
.replace(")", "") \
|
||||||
|
.replace("%", "") \
|
||||||
|
.replace(" ", "") \
|
||||||
|
.split(",")
|
||||||
|
|
||||||
|
h = None
|
||||||
|
s = None
|
||||||
|
l = None
|
||||||
|
|
||||||
|
h, s , l = int(_h) / 360, float(_s) / 100, float(_l) / 100
|
||||||
|
|
||||||
|
rgb = tuple(round(i * 255) for i in colorsys.hls_to_rgb(h, l, s))
|
||||||
|
rgb_sub = ','.join(map(str, rgb))
|
||||||
|
|
||||||
|
return f"rgb({rgb_sub})"
|
||||||
|
|
||||||
|
|
||||||
|
def hsv_to_rgb(self, text: str) -> str:
|
||||||
|
_h, _s , _v = text.replace("hsv", "") \
|
||||||
|
.replace("deg", "") \
|
||||||
|
.replace("(", "") \
|
||||||
|
.replace(")", "") \
|
||||||
|
.replace("%", "") \
|
||||||
|
.replace(" ", "") \
|
||||||
|
.split(",")
|
||||||
|
|
||||||
|
h = None
|
||||||
|
s = None
|
||||||
|
v = None
|
||||||
|
|
||||||
|
h, s , v = int(_h) / 360, float(_s) / 100, float(_v) / 100
|
||||||
|
|
||||||
|
rgb = tuple(round(i * 255) for i in colorsys.hsv_to_rgb(h,s,v))
|
||||||
|
rgb_sub = ','.join(map(str, rgb))
|
||||||
|
|
||||||
|
return f"rgb({rgb_sub})"
|
||||||
@@ -0,0 +1,240 @@
|
|||||||
|
# Python imports
|
||||||
|
|
||||||
|
# Lib imports
|
||||||
|
import gi
|
||||||
|
gi.require_version('Gtk', '3.0')
|
||||||
|
gi.require_version('Gdk', '3.0')
|
||||||
|
from gi.repository import Gtk
|
||||||
|
from gi.repository import Gdk
|
||||||
|
|
||||||
|
# Application imports
|
||||||
|
from .color_converter_mixin import ColorConverterMixin
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class Colorize(ColorConverterMixin):
|
||||||
|
def __init__(self):
|
||||||
|
super(Colorize, self).__init__()
|
||||||
|
|
||||||
|
self.tag_stub_name: str = "colorize-tag"
|
||||||
|
self.is_colorize_paused: bool = True
|
||||||
|
|
||||||
|
|
||||||
|
def handle_colorize(self, buffer):
|
||||||
|
if self.is_colorize_paused: return
|
||||||
|
|
||||||
|
tag_table = buffer.get_tag_table()
|
||||||
|
start_itr = None
|
||||||
|
end_itr = buffer.get_iter_at_mark( buffer.get_insert() )
|
||||||
|
|
||||||
|
i = 0
|
||||||
|
walker_iter = end_itr.copy()
|
||||||
|
working_tag = self.find_working_tag(walker_iter, i)
|
||||||
|
if working_tag:
|
||||||
|
start_itr = self.find_start_range(walker_iter, working_tag)
|
||||||
|
|
||||||
|
self.find_end_range(end_itr, working_tag)
|
||||||
|
buffer.remove_tag(working_tag, start_itr, end_itr)
|
||||||
|
else:
|
||||||
|
start_itr = self.traverse_backward_25_or_less(walker_iter)
|
||||||
|
self.traverse_forward_25_or_less(end_itr)
|
||||||
|
|
||||||
|
self.do_colorize(buffer, start_itr, end_itr)
|
||||||
|
|
||||||
|
def do_colorize(self, buffer = None, start_itr = None, end_itr = None):
|
||||||
|
if not start_itr or not end_itr:
|
||||||
|
start_itr = buffer.get_start_iter()
|
||||||
|
end_itr = buffer.get_end_iter()
|
||||||
|
|
||||||
|
# rgb(a), hsl, hsv
|
||||||
|
results = self.finalize_non_hex_matches(
|
||||||
|
self.collect_preliminary_results(
|
||||||
|
buffer, start_itr, end_itr
|
||||||
|
)
|
||||||
|
)
|
||||||
|
self.process_results(buffer, results)
|
||||||
|
|
||||||
|
# hex color search
|
||||||
|
results = self.finalize_hex_matches(
|
||||||
|
self.collect_preliminary_hex_results(
|
||||||
|
buffer, start_itr, end_itr
|
||||||
|
)
|
||||||
|
)
|
||||||
|
self.process_results(buffer, results)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def collect_preliminary_results(self, buffer = None, start_itr = None, end_itr = None):
|
||||||
|
if not buffer: return []
|
||||||
|
|
||||||
|
if not start_itr:
|
||||||
|
start_itr = buffer.get_start_iter()
|
||||||
|
|
||||||
|
results1 = self.search(start_itr, end_itr, "rgb")
|
||||||
|
results2 = self.search(start_itr, end_itr, "hsl")
|
||||||
|
results3 = self.search(start_itr, end_itr, "hsv")
|
||||||
|
|
||||||
|
return results1 + results2 + results3
|
||||||
|
|
||||||
|
def find_working_tag(self, walker_iter, i):
|
||||||
|
tags = walker_iter.get_tags()
|
||||||
|
for tag in tags:
|
||||||
|
if not tag.props.name or not self.tag_stub_name in tag.props.name: continue
|
||||||
|
return tag
|
||||||
|
|
||||||
|
result = walker_iter.backward_char()
|
||||||
|
|
||||||
|
if not result: return
|
||||||
|
if i > 25: return
|
||||||
|
return self.find_working_tag(walker_iter, i + 1)
|
||||||
|
|
||||||
|
def find_start_range(self, walker_iter, working_tag):
|
||||||
|
tags = walker_iter.get_tags()
|
||||||
|
for tag in tags:
|
||||||
|
if not tag.props.name or not working_tag.props.name in tag.props.name: continue
|
||||||
|
if not walker_iter.backward_char(): continue
|
||||||
|
|
||||||
|
self.find_start_range(walker_iter, working_tag)
|
||||||
|
|
||||||
|
return walker_iter
|
||||||
|
|
||||||
|
def find_end_range(self, end_itr, working_tag):
|
||||||
|
tags = end_itr.get_tags()
|
||||||
|
for tag in tags:
|
||||||
|
if not tag.props.name or not working_tag.props.name in tag.props.name: continue
|
||||||
|
if not end_itr.forward_char(): continue
|
||||||
|
|
||||||
|
self.find_end_range(end_itr, working_tag)
|
||||||
|
|
||||||
|
def traverse_backward_25_or_less(self, walker_itr):
|
||||||
|
i = 1
|
||||||
|
while i <= 25:
|
||||||
|
res = walker_itr.backward_char()
|
||||||
|
if not res: break
|
||||||
|
i += 1
|
||||||
|
|
||||||
|
def traverse_forward_25_or_less(self, end_itr):
|
||||||
|
i = 1
|
||||||
|
while i <= 25:
|
||||||
|
res = end_itr.forward_char()
|
||||||
|
if not res: break
|
||||||
|
i += 1
|
||||||
|
|
||||||
|
def collect_preliminary_hex_results(
|
||||||
|
self,
|
||||||
|
buffer = None,
|
||||||
|
start_itr = None,
|
||||||
|
end_itr = None
|
||||||
|
) -> list:
|
||||||
|
if not buffer: return []
|
||||||
|
|
||||||
|
if not start_itr:
|
||||||
|
start_itr = buffer.get_start_iter()
|
||||||
|
|
||||||
|
return self.search(start_itr, end_itr, "#")
|
||||||
|
|
||||||
|
def search(self, start_itr = None, end_itr = None, query: str = None) -> list:
|
||||||
|
if not start_itr or not query: return []
|
||||||
|
|
||||||
|
results: list = []
|
||||||
|
flags = Gtk.TextSearchFlags.VISIBLE_ONLY | Gtk.TextSearchFlags.TEXT_ONLY
|
||||||
|
while True:
|
||||||
|
result = start_itr.forward_search(query, flags, end_itr)
|
||||||
|
if not result: break
|
||||||
|
|
||||||
|
results.append(result)
|
||||||
|
start_itr = result[1]
|
||||||
|
|
||||||
|
return results
|
||||||
|
|
||||||
|
def finalize_non_hex_matches(self, result_hits: list = []) -> list:
|
||||||
|
results: list = []
|
||||||
|
|
||||||
|
for start_itr, end_itr in result_hits:
|
||||||
|
# If one of end chars of rgb/rgba/hsv/hsl
|
||||||
|
if end_itr.get_char() in ["a", "b", "l", "v"]:
|
||||||
|
end_itr.forward_char()
|
||||||
|
|
||||||
|
# If afterwards no paren
|
||||||
|
if end_itr.get_char() != "(":
|
||||||
|
continue
|
||||||
|
|
||||||
|
end_itr.forward_chars(21) # Check if best case (255, 255, 255, 0.64)
|
||||||
|
if end_itr.get_char() == ")":
|
||||||
|
end_itr.forward_char()
|
||||||
|
results.append([start_itr, end_itr])
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Break loop if we get back to rgb/rgba/hsl/hsv -> (
|
||||||
|
while end_itr.get_char() != "(":
|
||||||
|
if end_itr.get_char() == ")":
|
||||||
|
end_itr.forward_char()
|
||||||
|
results.append([start_itr, end_itr])
|
||||||
|
break
|
||||||
|
|
||||||
|
if not end_itr.backward_char(): break
|
||||||
|
|
||||||
|
return results
|
||||||
|
|
||||||
|
def finalize_hex_matches(self, result_hits: list = []) -> list:
|
||||||
|
results: list = []
|
||||||
|
|
||||||
|
for start_itr, end_itr in result_hits:
|
||||||
|
i = 0
|
||||||
|
_ch = end_itr.get_char()
|
||||||
|
ch = ord(end_itr.get_char()) if _ch else -1
|
||||||
|
|
||||||
|
while (
|
||||||
|
(ch >= 48 and ch <= 57) or \
|
||||||
|
(ch >= 65 and ch <= 70) or \
|
||||||
|
(ch >= 97 and ch <= 102)
|
||||||
|
):
|
||||||
|
if i > 16: break
|
||||||
|
|
||||||
|
i += 1
|
||||||
|
end_itr.forward_char()
|
||||||
|
_ch = end_itr.get_char()
|
||||||
|
ch = ord(end_itr.get_char()) if _ch else -1
|
||||||
|
|
||||||
|
if i in [3, 4, 6, 8, 9, 12, 16]:
|
||||||
|
results.append([start_itr, end_itr])
|
||||||
|
|
||||||
|
return results
|
||||||
|
|
||||||
|
def process_results(self, buffer, results):
|
||||||
|
for start_itr, end_itr in results:
|
||||||
|
text = self.get_color_text(buffer, start_itr, end_itr)
|
||||||
|
color = Gdk.RGBA()
|
||||||
|
|
||||||
|
if not color.parse(text): continue
|
||||||
|
|
||||||
|
tag = self.get_colorized_tag(buffer, text, color)
|
||||||
|
buffer.apply_tag(tag, start_itr, end_itr)
|
||||||
|
|
||||||
|
def get_colorized_tag(self, buffer, tag, color: Gdk.RGBA):
|
||||||
|
tag_table = buffer.get_tag_table()
|
||||||
|
colorize_tag = f"{self.tag_stub_name}_{tag}"
|
||||||
|
search_tag = tag_table.lookup(colorize_tag)
|
||||||
|
|
||||||
|
if not search_tag:
|
||||||
|
search_tag = buffer.create_tag(
|
||||||
|
colorize_tag, background_rgba = color
|
||||||
|
)
|
||||||
|
|
||||||
|
return search_tag
|
||||||
|
|
||||||
|
def clear_color_tags(self, buffer):
|
||||||
|
tag_table = buffer.get_tag_table()
|
||||||
|
|
||||||
|
def traverse_tags(tag, user_data):
|
||||||
|
name = tag.get_property("name")
|
||||||
|
|
||||||
|
if not name: return
|
||||||
|
if name.startswith(self.tag_stub_name):
|
||||||
|
user_data.append(tag)
|
||||||
|
|
||||||
|
tags = []
|
||||||
|
tag_table.foreach(traverse_tags, tags)
|
||||||
|
for tag in tags:
|
||||||
|
tag_table.remove(tag)
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"name": "Colorize",
|
||||||
|
"author": "ITDominator",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"support": "",
|
||||||
|
"requests": {}
|
||||||
|
}
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
# Python imports
|
||||||
|
|
||||||
|
# Lib imports
|
||||||
|
|
||||||
|
# Application imports
|
||||||
|
from libs.event_factory import Event_Factory, Code_Event_Types
|
||||||
|
|
||||||
|
from plugins.plugin_types import PluginCode
|
||||||
|
|
||||||
|
from .colorize import Colorize
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
colorize = Colorize()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class Plugin(PluginCode):
|
||||||
|
def __init__(self):
|
||||||
|
super(Plugin, self).__init__()
|
||||||
|
|
||||||
|
|
||||||
|
def _controller_message(self, event: Code_Event_Types.CodeEvent):
|
||||||
|
if isinstance(event, Code_Event_Types.AddedNewFileEvent):
|
||||||
|
colorize.handle_colorize(event.file.buffer)
|
||||||
|
elif isinstance(event, Code_Event_Types.TextChangedEvent):
|
||||||
|
colorize.handle_colorize(event.buffer)
|
||||||
|
|
||||||
|
def load(self):
|
||||||
|
self._manage_signals("register_command")
|
||||||
|
|
||||||
|
def unload(self):
|
||||||
|
self._manage_signals("unregister_command")
|
||||||
|
event = Event_Factory.create_event("get_source_views")
|
||||||
|
|
||||||
|
self.emit_to("source_views", event)
|
||||||
|
for view in event.response:
|
||||||
|
buffer = view.get_buffer()
|
||||||
|
colorize.clear_color_tags(buffer)
|
||||||
|
|
||||||
|
def _manage_signals(self, action: str):
|
||||||
|
event = Event_Factory.create_event(action,
|
||||||
|
command_name = "tggle_colorize",
|
||||||
|
command = Handler,
|
||||||
|
binding_mode = "released",
|
||||||
|
binding = "<Shift><Control>c"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.emit_to("source_views", event)
|
||||||
|
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
class Handler:
|
||||||
|
@staticmethod
|
||||||
|
def execute(
|
||||||
|
view: any,
|
||||||
|
*args,
|
||||||
|
**kwargs
|
||||||
|
):
|
||||||
|
logger.debug("Command: Toggle Colorize")
|
||||||
|
|
||||||
|
colorize.is_colorize_paused = not colorize.is_colorize_paused
|
||||||
|
if colorize.is_colorize_paused:
|
||||||
|
colorize.clear_color_tags( view.get_buffer() )
|
||||||
|
return
|
||||||
|
|
||||||
|
colorize.handle_colorize( view.get_buffer() )
|
||||||
|
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
"""
|
||||||
|
Pligin Module
|
||||||
|
"""
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
"""
|
||||||
|
Pligin Package
|
||||||
|
"""
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
# Python imports
|
||||||
|
|
||||||
|
# Lib imports
|
||||||
|
|
||||||
|
# Application imports
|
||||||
|
from .mixins.code_comment_tags_mixin import CodeCommentTagsMixin
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class Commenter(CodeCommentTagsMixin):
|
||||||
|
def __init__(self):
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
def keyboard_tggl_comment(self, buffer):
|
||||||
|
language = buffer.get_language()
|
||||||
|
if language is None: return
|
||||||
|
|
||||||
|
start_tag, end_tag = self.get_comment_tags(language)
|
||||||
|
# Note: Only handling line comment tag- no block comment option
|
||||||
|
if not start_tag and not end_tag: return
|
||||||
|
|
||||||
|
bounds = buffer.get_selection_bounds()
|
||||||
|
if bounds:
|
||||||
|
self._bounds_comment(
|
||||||
|
start_tag, end_tag, bounds, buffer
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
self._line_comment(start_tag, end_tag, buffer)
|
||||||
|
|
||||||
|
|
||||||
|
def _line_comment(self, start_tag, end_tag, buffer):
|
||||||
|
start_itr = buffer.get_iter_at_mark( buffer.get_insert() ).copy()
|
||||||
|
end_itr = start_itr.copy()
|
||||||
|
if not start_itr.starts_line():
|
||||||
|
start_itr.set_line_offset(0)
|
||||||
|
if not end_itr.ends_line():
|
||||||
|
end_itr.forward_to_line_end()
|
||||||
|
|
||||||
|
text = buffer.get_text(start_itr, end_itr, True)
|
||||||
|
text = text.replace(start_tag, "") if text.startswith(start_tag) else start_tag + text
|
||||||
|
|
||||||
|
buffer.begin_user_action()
|
||||||
|
buffer.delete(start_itr, end_itr)
|
||||||
|
buffer.insert(start_itr, text)
|
||||||
|
buffer.end_user_action()
|
||||||
|
|
||||||
|
|
||||||
|
def _bounds_comment(self, start_tag, end_tag, bounds, buffer):
|
||||||
|
start_itr, end_itr = bounds
|
||||||
|
if not start_itr.starts_line():
|
||||||
|
start_itr.set_line_offset(0)
|
||||||
|
if not end_itr.ends_line():
|
||||||
|
end_itr.forward_to_line_end()
|
||||||
|
|
||||||
|
text = buffer.get_text(start_itr, end_itr, True)
|
||||||
|
text = "\n".join(
|
||||||
|
line.replace(start_tag, "") if line.startswith(start_tag) else start_tag + line
|
||||||
|
for line in text.splitlines()
|
||||||
|
)
|
||||||
|
|
||||||
|
buffer.begin_user_action()
|
||||||
|
buffer.delete(start_itr, end_itr)
|
||||||
|
buffer.insert(start_itr, text)
|
||||||
|
buffer.end_user_action()
|
||||||
|
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"name": "Commentzar",
|
||||||
|
"author": "ITDominator",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"support": "",
|
||||||
|
"requests": {}
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
"""
|
||||||
|
Pligin Module Mixin
|
||||||
|
"""
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
# Python imports
|
||||||
|
|
||||||
|
# Lib imports
|
||||||
|
|
||||||
|
# Application imports
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class CodeCommentTagsMixin:
|
||||||
|
def get_comment_tags(self, language):
|
||||||
|
start_tag, end_tag = self.get_line_comment_tags(language)
|
||||||
|
if (start_tag, end_tag) == (None, None):
|
||||||
|
start_tag, end_tag = self.get_block_comment_tags(language)
|
||||||
|
|
||||||
|
return start_tag, end_tag
|
||||||
|
|
||||||
|
def get_block_comment_tags(self, language):
|
||||||
|
start_tag = language.get_metadata('block-comment-start')
|
||||||
|
end_tag = language.get_metadata('block-comment-end')
|
||||||
|
|
||||||
|
if start_tag and end_tag: return (start_tag, end_tag)
|
||||||
|
|
||||||
|
return (None, None)
|
||||||
|
|
||||||
|
def get_line_comment_tags(self, language):
|
||||||
|
start_tag = language.get_metadata('line-comment-start')
|
||||||
|
|
||||||
|
if start_tag: return (start_tag, None)
|
||||||
|
|
||||||
|
return (None, None)
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
# Python imports
|
||||||
|
|
||||||
|
# Lib imports
|
||||||
|
import gi
|
||||||
|
gi.require_version('Gtk', '3.0')
|
||||||
|
from gi.repository import Gtk
|
||||||
|
|
||||||
|
# Application imports
|
||||||
|
from libs.event_factory import Event_Factory, Code_Event_Types
|
||||||
|
|
||||||
|
from plugins.plugin_types import PluginCode
|
||||||
|
|
||||||
|
from .commenter import Commenter
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
commenter = Commenter()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class Plugin(PluginCode):
|
||||||
|
def __init__(self):
|
||||||
|
super(Plugin, self).__init__()
|
||||||
|
|
||||||
|
|
||||||
|
def _controller_message(self, event: Code_Event_Types.CodeEvent):
|
||||||
|
...
|
||||||
|
|
||||||
|
def load(self):
|
||||||
|
event = Event_Factory.create_event("register_command",
|
||||||
|
command_name = "keyboard_tggl_comment",
|
||||||
|
command = Handler,
|
||||||
|
binding_mode = "released",
|
||||||
|
binding = "<Control>slash"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.emit_to("source_views", event)
|
||||||
|
|
||||||
|
def unload(self):
|
||||||
|
event = Event_Factory.create_event("unregister_command",
|
||||||
|
command_name = "keyboard_tggl_comment",
|
||||||
|
command = Handler,
|
||||||
|
binding_mode = "released",
|
||||||
|
binding = "<Control>slash"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.emit_to("source_views", event)
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
class Handler:
|
||||||
|
@staticmethod
|
||||||
|
def execute(
|
||||||
|
view: any,
|
||||||
|
*args,
|
||||||
|
**kwargs
|
||||||
|
):
|
||||||
|
logger.debug("Command: Toggle Comment")
|
||||||
|
commenter.keyboard_tggl_comment( view.get_buffer() )
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
"""
|
||||||
|
Plugin Module
|
||||||
|
"""
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
"""
|
||||||
|
Plugin Package
|
||||||
|
"""
|
||||||
@@ -0,0 +1,97 @@
|
|||||||
|
# Python imports
|
||||||
|
|
||||||
|
# Lib imports
|
||||||
|
|
||||||
|
# Application imports
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class Autopairs:
|
||||||
|
def __init__(self):
|
||||||
|
...
|
||||||
|
|
||||||
|
def handle_word_wrap(self, buffer, char_str: str):
|
||||||
|
wrap_block = self.get_wrap_block(char_str)
|
||||||
|
if not wrap_block: return
|
||||||
|
|
||||||
|
selection = buffer.get_selection_bounds()
|
||||||
|
if not selection:
|
||||||
|
self.insert_pair(buffer, char_str, wrap_block)
|
||||||
|
return True
|
||||||
|
|
||||||
|
self.wrap_selection(buffer, char_str, wrap_block, selection)
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def insert_pair(
|
||||||
|
self, buffer, char_str: str, wrap_block: tuple
|
||||||
|
):
|
||||||
|
buffer.begin_user_action()
|
||||||
|
|
||||||
|
left_block, right_block = wrap_block
|
||||||
|
insert_mark = buffer.get_insert()
|
||||||
|
|
||||||
|
insert_itr = buffer.get_iter_at_mark(insert_mark)
|
||||||
|
buffer.insert(insert_itr, f"{left_block}{right_block}")
|
||||||
|
insert_itr = buffer.get_iter_at_mark( insert_mark )
|
||||||
|
insert_itr.backward_char()
|
||||||
|
|
||||||
|
buffer.place_cursor(insert_itr)
|
||||||
|
|
||||||
|
buffer.end_user_action()
|
||||||
|
|
||||||
|
def wrap_selection(
|
||||||
|
self, buffer, char_str: str, wrap_block: tuple, selection
|
||||||
|
):
|
||||||
|
left_block, \
|
||||||
|
right_block = wrap_block
|
||||||
|
start_itr, \
|
||||||
|
end_itr = selection
|
||||||
|
data = buffer.get_text(
|
||||||
|
start_itr, end_itr, include_hidden_chars = False
|
||||||
|
)
|
||||||
|
start_mark = buffer.create_mark("startclose", start_itr, False)
|
||||||
|
end_mark = buffer.create_mark("endclose", end_itr, True)
|
||||||
|
|
||||||
|
buffer.begin_user_action()
|
||||||
|
|
||||||
|
buffer.insert(start_itr, left_block)
|
||||||
|
end_itr = buffer.get_iter_at_mark(end_mark)
|
||||||
|
buffer.insert(end_itr, right_block)
|
||||||
|
|
||||||
|
start = buffer.get_iter_at_mark(start_mark)
|
||||||
|
end = buffer.get_iter_at_mark(end_mark)
|
||||||
|
|
||||||
|
buffer.select_range(start, end)
|
||||||
|
buffer.delete_mark_by_name("startclose")
|
||||||
|
buffer.delete_mark_by_name("endclose")
|
||||||
|
|
||||||
|
buffer.end_user_action()
|
||||||
|
|
||||||
|
def get_wrap_block(self, char_str) -> tuple:
|
||||||
|
left_block = ""
|
||||||
|
right_block = ""
|
||||||
|
|
||||||
|
match char_str:
|
||||||
|
case "(" | ")":
|
||||||
|
left_block = "("
|
||||||
|
right_block = ")"
|
||||||
|
case "[" | "]":
|
||||||
|
left_block = "["
|
||||||
|
right_block = "]"
|
||||||
|
case "{" | "}":
|
||||||
|
left_block = "{"
|
||||||
|
right_block = "}"
|
||||||
|
case '"':
|
||||||
|
left_block = '"'
|
||||||
|
right_block = '"'
|
||||||
|
case "'":
|
||||||
|
left_block = "'"
|
||||||
|
right_block = "'"
|
||||||
|
case "`":
|
||||||
|
left_block = "`"
|
||||||
|
right_block = "`"
|
||||||
|
case _:
|
||||||
|
return ()
|
||||||
|
|
||||||
|
return left_block, right_block
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"name": "File History",
|
||||||
|
"author": "ITDominator",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"support": "",
|
||||||
|
"requests": {}
|
||||||
|
}
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
# Python imports
|
||||||
|
|
||||||
|
# Lib imports
|
||||||
|
|
||||||
|
# Application imports
|
||||||
|
from libs.event_factory import Event_Factory, Code_Event_Types
|
||||||
|
|
||||||
|
from plugins.plugin_types import PluginCode
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
history: list = []
|
||||||
|
history_size: int = 30
|
||||||
|
|
||||||
|
|
||||||
|
class Plugin(PluginCode):
|
||||||
|
def __init__(self):
|
||||||
|
super(Plugin, self).__init__()
|
||||||
|
|
||||||
|
|
||||||
|
def _controller_message(self, event: Code_Event_Types.CodeEvent):
|
||||||
|
if isinstance(event, Code_Event_Types.RemovedFileEvent):
|
||||||
|
if event.file.ftype == "buffer": return
|
||||||
|
|
||||||
|
if len(history) == history_size:
|
||||||
|
history.pop(0)
|
||||||
|
|
||||||
|
history.append(event.file)
|
||||||
|
|
||||||
|
def load(self):
|
||||||
|
self._manage_signals("register_command")
|
||||||
|
|
||||||
|
def unload(self):
|
||||||
|
self._manage_signals("unregister_command")
|
||||||
|
|
||||||
|
def _manage_signals(self, action: str):
|
||||||
|
event = Event_Factory.create_event(action,
|
||||||
|
command_name = "file_history_pop",
|
||||||
|
command = Handler,
|
||||||
|
binding_mode = "released",
|
||||||
|
binding = "<Shift><Control>t"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.emit_to("source_views", event)
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
class Handler:
|
||||||
|
@staticmethod
|
||||||
|
def execute(
|
||||||
|
view: any,
|
||||||
|
char_str: str,
|
||||||
|
*args,
|
||||||
|
**kwargs
|
||||||
|
):
|
||||||
|
logger.debug("Command: File History")
|
||||||
|
if len(history) == 0: return
|
||||||
|
|
||||||
|
view._on_uri_data_received(
|
||||||
|
[
|
||||||
|
history.pop().replace("file://", "")
|
||||||
|
]
|
||||||
|
)
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
"""
|
||||||
|
Pligin Module
|
||||||
|
"""
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
"""
|
||||||
|
Pligin Package
|
||||||
|
"""
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
# Python imports
|
||||||
|
|
||||||
|
# Lib imports
|
||||||
|
import gi
|
||||||
|
|
||||||
|
gi.require_version('GtkSource', '4')
|
||||||
|
|
||||||
|
from gi.repository import GtkSource
|
||||||
|
|
||||||
|
# Application imports
|
||||||
|
from .helpers import clear_temp_cut_buffer_delayed, set_temp_cut_buffer_delayed
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class Handler:
|
||||||
|
@staticmethod
|
||||||
|
def execute(
|
||||||
|
view: GtkSource.View,
|
||||||
|
*args,
|
||||||
|
**kwargs
|
||||||
|
):
|
||||||
|
logger.debug("Command: Cut to Temp Buffer")
|
||||||
|
|
||||||
|
clear_temp_cut_buffer_delayed(view)
|
||||||
|
|
||||||
|
buffer = view.get_buffer()
|
||||||
|
itr = buffer.get_iter_at_mark(buffer.get_insert())
|
||||||
|
|
||||||
|
start_itr = itr.copy()
|
||||||
|
start_itr.set_line_offset(0)
|
||||||
|
|
||||||
|
end_itr = start_itr.copy()
|
||||||
|
if not end_itr.forward_line():
|
||||||
|
end_itr = buffer.get_end_iter()
|
||||||
|
|
||||||
|
if not hasattr(view, "_cut_buffer"):
|
||||||
|
view._cut_buffer = ""
|
||||||
|
|
||||||
|
line_str = buffer.get_text(start_itr, end_itr, True)
|
||||||
|
view._cut_buffer += line_str
|
||||||
|
|
||||||
|
buffer.delete(start_itr, end_itr)
|
||||||
|
|
||||||
|
set_temp_cut_buffer_delayed(view)
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
# Python imports
|
||||||
|
|
||||||
|
# Lib imports
|
||||||
|
import gi
|
||||||
|
|
||||||
|
from gi.repository import GLib
|
||||||
|
|
||||||
|
# Application imports
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def clear_temp_cut_buffer_delayed(view: any):
|
||||||
|
if not hasattr(view, "_cut_temp_timeout_id"): return
|
||||||
|
if not view._cut_temp_timeout_id: return
|
||||||
|
|
||||||
|
GLib.source_remove(view._cut_temp_timeout_id)
|
||||||
|
|
||||||
|
def set_temp_cut_buffer_delayed(view: any):
|
||||||
|
def clear_temp_buffer(view: any):
|
||||||
|
view._cut_buffer = ""
|
||||||
|
view._cut_temp_timeout_id = None
|
||||||
|
return False
|
||||||
|
|
||||||
|
view._cut_temp_timeout_id = GLib.timeout_add(15000, clear_temp_buffer, view)
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"name": "Nanoesq Temp Buffer",
|
||||||
|
"author": "ITDominator",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"support": "",
|
||||||
|
"requests": {}
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
# Python imports
|
||||||
|
|
||||||
|
# Lib imports
|
||||||
|
import gi
|
||||||
|
|
||||||
|
gi.require_version('GtkSource', '4')
|
||||||
|
|
||||||
|
from gi.repository import GLib
|
||||||
|
from gi.repository import GtkSource
|
||||||
|
|
||||||
|
# Application imports
|
||||||
|
from .helpers import clear_temp_cut_buffer_delayed, set_temp_cut_buffer_delayed
|
||||||
|
|
||||||
|
|
||||||
|
class Handler2:
|
||||||
|
@staticmethod
|
||||||
|
def execute(
|
||||||
|
view: GtkSource.View,
|
||||||
|
*args,
|
||||||
|
**kwargs
|
||||||
|
):
|
||||||
|
logger.debug("Command: Paste Temp Buffer")
|
||||||
|
if not hasattr(view, "_cut_temp_timeout_id"): return
|
||||||
|
if not hasattr(view, "_cut_buffer"): return
|
||||||
|
if not view._cut_buffer: return
|
||||||
|
|
||||||
|
clear_temp_cut_buffer_delayed(view)
|
||||||
|
|
||||||
|
buffer = view.get_buffer()
|
||||||
|
itr = buffer.get_iter_at_mark( buffer.get_insert() )
|
||||||
|
insert_itr = itr.copy()
|
||||||
|
|
||||||
|
buffer.insert(insert_itr, view._cut_buffer, -1)
|
||||||
|
|
||||||
|
set_temp_cut_buffer_delayed(view)
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
# Python imports
|
||||||
|
|
||||||
|
# Lib imports
|
||||||
|
|
||||||
|
# Application imports
|
||||||
|
from libs.event_factory import Event_Factory, Code_Event_Types
|
||||||
|
|
||||||
|
from plugins.plugin_types import PluginCode
|
||||||
|
|
||||||
|
from .cut_to_temp_buffer import Handler
|
||||||
|
from .paste_temp_buffer import Handler2
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class Plugin(PluginCode):
|
||||||
|
def __init__(self):
|
||||||
|
super(Plugin, self).__init__()
|
||||||
|
|
||||||
|
|
||||||
|
def _controller_message(self, event: Code_Event_Types.CodeEvent):
|
||||||
|
...
|
||||||
|
|
||||||
|
def load(self):
|
||||||
|
self._manage_signals("register_command")
|
||||||
|
|
||||||
|
def load(self):
|
||||||
|
self._manage_signals("unregister_command")
|
||||||
|
|
||||||
|
def _manage_signals(self, action: str):
|
||||||
|
event = Event_Factory.create_event(action,
|
||||||
|
command_name = "cut_to_temp_buffer",
|
||||||
|
command = Handler,
|
||||||
|
binding_mode = "held",
|
||||||
|
binding = "<Control>k"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.emit_to("source_views", event)
|
||||||
|
|
||||||
|
event = Event_Factory.create_event(action,
|
||||||
|
command_name = "paste_temp_buffer",
|
||||||
|
command = Handler2,
|
||||||
|
binding_mode = "held",
|
||||||
|
binding = "<Control>u"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.emit_to("source_views", event)
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
...
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
"""
|
||||||
|
Plugin Module
|
||||||
|
"""
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
"""
|
||||||
|
Plugin Package
|
||||||
|
"""
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"name": "Toggle Source View",
|
||||||
|
"author": "ITDominator",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"support": "",
|
||||||
|
"requests": {}
|
||||||
|
}
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
# Python imports
|
||||||
|
|
||||||
|
# Lib imports
|
||||||
|
|
||||||
|
# Application imports
|
||||||
|
from libs.event_factory import Event_Factory, Code_Event_Types
|
||||||
|
|
||||||
|
from plugins.plugin_types import PluginCode
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class Plugin(PluginCode):
|
||||||
|
def __init__(self):
|
||||||
|
super(Plugin, self).__init__()
|
||||||
|
|
||||||
|
def _controller_message(self, event: Code_Event_Types.CodeEvent):
|
||||||
|
...
|
||||||
|
|
||||||
|
def load(self):
|
||||||
|
event = Event_Factory.create_event("register_command",
|
||||||
|
command_name = "toggle_source_view",
|
||||||
|
command = Handler,
|
||||||
|
binding_mode = "released",
|
||||||
|
binding = "<Shift><Control>h"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.emit_to("source_views", event)
|
||||||
|
|
||||||
|
def unload(self):
|
||||||
|
event = Event_Factory.create_event("unregister_command",
|
||||||
|
command_name = "toggle_source_view",
|
||||||
|
command = Handler,
|
||||||
|
binding_mode = "released",
|
||||||
|
binding = "<Shift><Control>h"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.emit_to("source_views", event)
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
class Handler:
|
||||||
|
@staticmethod
|
||||||
|
def execute(
|
||||||
|
view: any,
|
||||||
|
char_str: str,
|
||||||
|
*args,
|
||||||
|
**kwargs
|
||||||
|
):
|
||||||
|
logger.debug("Command: Toggle Source View")
|
||||||
|
target = view.get_parent()
|
||||||
|
target.hide() if target.is_visible() else target.show()
|
||||||
|
|
||||||
|
if view.sibling_left:
|
||||||
|
target = view.sibling_left.get_parent()
|
||||||
|
target.show()
|
||||||
|
view.sibling_left.grab_focus()
|
||||||
|
|
||||||
|
if view.sibling_right:
|
||||||
|
target = view.sibling_right.get_parent()
|
||||||
|
target.show()
|
||||||
|
view.sibling_right.grab_focus()
|
||||||
|
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
"""
|
||||||
|
Pligin Module
|
||||||
|
"""
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
"""
|
||||||
|
Pligin Package
|
||||||
|
"""
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"name": "Example Completer",
|
||||||
|
"author": "John Doe",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"support": "",
|
||||||
|
"requests": {}
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
# Python imports
|
||||||
|
|
||||||
|
# Lib imports
|
||||||
|
import gi
|
||||||
|
gi.require_version('Gtk', '3.0')
|
||||||
|
from gi.repository import Gtk
|
||||||
|
|
||||||
|
# Application imports
|
||||||
|
from libs.event_factory import Event_Factory, Code_Event_Types
|
||||||
|
|
||||||
|
from plugins.plugin_types import PluginCode
|
||||||
|
|
||||||
|
from .provider import Provider
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class Plugin(PluginCode):
|
||||||
|
def __init__(self):
|
||||||
|
super(Plugin, self).__init__()
|
||||||
|
|
||||||
|
self.provider: Provider = None
|
||||||
|
|
||||||
|
|
||||||
|
def _controller_message(self, event: Code_Event_Types.CodeEvent):
|
||||||
|
...
|
||||||
|
|
||||||
|
def load(self):
|
||||||
|
self.provider = Provider()
|
||||||
|
|
||||||
|
event = Event_Factory.create_event(
|
||||||
|
"register_provider",
|
||||||
|
provider_name = "Example Completer",
|
||||||
|
provider = self.provider,
|
||||||
|
language_ids = []
|
||||||
|
)
|
||||||
|
self.emit_to("completion", event)
|
||||||
|
|
||||||
|
def unload(self):
|
||||||
|
event = Event_Factory.create_event(
|
||||||
|
"unregister_provider",
|
||||||
|
provider_name = "Example Completer"
|
||||||
|
)
|
||||||
|
self.emit_to("completion", event)
|
||||||
|
|
||||||
|
self.provider = None
|
||||||
|
del self.provider
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
...
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
# Python imports
|
||||||
|
|
||||||
|
# Lib imports
|
||||||
|
import gi
|
||||||
|
gi.require_version('GtkSource', '4')
|
||||||
|
|
||||||
|
from gi.repository import GObject
|
||||||
|
from gi.repository import GtkSource
|
||||||
|
|
||||||
|
# Application imports
|
||||||
|
from .provider_response_cache import ProviderResponseCache
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class Provider(GObject.GObject, GtkSource.CompletionProvider):
|
||||||
|
"""
|
||||||
|
This is a custom Completion Example Provider.
|
||||||
|
# NOTE: used information from here --> https://warroom.rsmus.com/do-that-auto-complete/
|
||||||
|
"""
|
||||||
|
__gtype_name__ = 'ExampleCompletionProvider'
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
super(Provider, self).__init__()
|
||||||
|
|
||||||
|
self.response_cache: ProviderResponseCache = ProviderResponseCache()
|
||||||
|
|
||||||
|
|
||||||
|
def do_get_name(self):
|
||||||
|
""" Returns: a new string containing the name of the provider. """
|
||||||
|
return 'Example Code Completion'
|
||||||
|
|
||||||
|
def do_match(self, context):
|
||||||
|
# Note: If provider is in interactive activation then need to check
|
||||||
|
# view focus as otherwise non focus views start trying to grab it.
|
||||||
|
completion = context.get_property("completion")
|
||||||
|
if not completion.get_view().has_focus(): return
|
||||||
|
|
||||||
|
word = self.response_cache.get_word(context)
|
||||||
|
if not word or len(word) < 2: return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
def do_get_priority(self):
|
||||||
|
""" Determin position in result list along other providor results. """
|
||||||
|
return 5
|
||||||
|
|
||||||
|
def do_activate_proposal(self, proposal, iter_):
|
||||||
|
""" Manually handle actual completion insert or set flags and handle normally. """
|
||||||
|
|
||||||
|
buffer = iter_.get_buffer()
|
||||||
|
# Note: Flag mostly intended for SourceViewsMultiInsertState
|
||||||
|
# to insure marker processes inserted text correctly.
|
||||||
|
buffer.is_processing_completion = True
|
||||||
|
return False
|
||||||
|
|
||||||
|
def do_get_activation(self):
|
||||||
|
""" The context for when a provider will show results """
|
||||||
|
# return GtkSource.CompletionActivation.NONE
|
||||||
|
# return GtkSource.CompletionActivation.USER_REQUESTED
|
||||||
|
# return GtkSource.CompletionActivation.USER_REQUESTED | GtkSource.CompletionActivation.INTERACTIVE
|
||||||
|
return GtkSource.CompletionActivation.INTERACTIVE
|
||||||
|
|
||||||
|
def do_populate(self, context):
|
||||||
|
results = self.response_cache.filter_with_context(context)
|
||||||
|
proposals = []
|
||||||
|
|
||||||
|
for entry in results:
|
||||||
|
proposals.append(
|
||||||
|
self.response_cache.create_completion_item(
|
||||||
|
entry["label"],
|
||||||
|
entry["text"],
|
||||||
|
entry["info"]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
context.add_proposals(self, proposals, True)
|
||||||
|
|
||||||
@@ -0,0 +1,113 @@
|
|||||||
|
# Python imports
|
||||||
|
from concurrent.futures import ThreadPoolExecutor
|
||||||
|
import re
|
||||||
|
|
||||||
|
# Lib imports
|
||||||
|
import gi
|
||||||
|
gi.require_version('Gtk', '3.0')
|
||||||
|
gi.require_version('GtkSource', '4')
|
||||||
|
|
||||||
|
from gi.repository import Gtk
|
||||||
|
from gi.repository import GLib
|
||||||
|
from gi.repository import GtkSource
|
||||||
|
|
||||||
|
# Application imports
|
||||||
|
from libs.event_factory import Code_Event_Types
|
||||||
|
|
||||||
|
from core.widgets.code.completion_providers.provider_response_cache_base import ProviderResponseCacheBase
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class ProviderResponseCache(ProviderResponseCacheBase):
|
||||||
|
def __init__(self):
|
||||||
|
super(ProviderResponseCache, self).__init__()
|
||||||
|
|
||||||
|
# Note: Using asyncio.run causes a keyboard trap that prevents app
|
||||||
|
# closure from terminal. ThreadPoolExecutor seems to not have such issues...
|
||||||
|
self.executor = ThreadPoolExecutor(max_workers = 1)
|
||||||
|
self.matchers: dict = {
|
||||||
|
"hello": {
|
||||||
|
"label": "Hello, World!",
|
||||||
|
"text": "Hello, World!",
|
||||||
|
"info": GLib.markup_escape_text( "<b>Says the first ever program developers write...</b>" )
|
||||||
|
},
|
||||||
|
"foo": {
|
||||||
|
"label": "foo",
|
||||||
|
"text": "foo }}"
|
||||||
|
},
|
||||||
|
"bar": {
|
||||||
|
"label": "bar",
|
||||||
|
"text": "bar }}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def process_file_load(self, event: Code_Event_Types.AddedNewFileEvent):
|
||||||
|
...
|
||||||
|
|
||||||
|
def process_file_close(self, event: Code_Event_Types.RemovedFileEvent):
|
||||||
|
...
|
||||||
|
|
||||||
|
def process_file_save(self, event: Code_Event_Types.SavedFileEvent):
|
||||||
|
...
|
||||||
|
|
||||||
|
def process_file_change(self, event: Code_Event_Types.TextChangedEvent):
|
||||||
|
...
|
||||||
|
|
||||||
|
def filter(self, word: str) -> list[dict]:
|
||||||
|
...
|
||||||
|
|
||||||
|
def filter_with_context(self, context) -> list[dict]:
|
||||||
|
"""
|
||||||
|
In this instance, it will do 2 things:
|
||||||
|
1) always provide Hello World! (Not ideal but an option so its in the example)
|
||||||
|
2) Utilizes the Gtk.TextIter from the TextBuffer to determine if there is a jinja
|
||||||
|
example of '{{ custom.' if so it will provide you with the options of foo and bar.
|
||||||
|
If selected it will insert foo }} or bar }}, completing your syntax...
|
||||||
|
|
||||||
|
PLEASE NOTE the GtkTextIter Logic and regex are really rough and should be adjusted and tuned
|
||||||
|
"""
|
||||||
|
|
||||||
|
proposals: list[dict] = [
|
||||||
|
{
|
||||||
|
"label": self.matchers[ "hello" ]["label"],
|
||||||
|
"text": self.matchers[ "hello" ]["text"],
|
||||||
|
"info": self.matchers[ "hello" ]["info"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
# Gtk Versions differ on get_iter responses...
|
||||||
|
end_iter = context.get_iter()
|
||||||
|
if not isinstance(end_iter, Gtk.TextIter):
|
||||||
|
_, end_iter = context.get_iter()
|
||||||
|
|
||||||
|
if not end_iter: return
|
||||||
|
|
||||||
|
buf = end_iter.get_buffer()
|
||||||
|
mov_iter = end_iter.copy()
|
||||||
|
if mov_iter.backward_search('{{', Gtk.TextSearchFlags.VISIBLE_ONLY):
|
||||||
|
mov_iter, _ = mov_iter.backward_search('{{', Gtk.TextSearchFlags.VISIBLE_ONLY)
|
||||||
|
left_text = buf.get_text(mov_iter, end_iter, True)
|
||||||
|
else:
|
||||||
|
left_text = ''
|
||||||
|
|
||||||
|
if re.match(r'.*\{\{\s*custom\.$', left_text):
|
||||||
|
# optionally proposed based on left search via regex
|
||||||
|
proposals.append(
|
||||||
|
{
|
||||||
|
"label": self.matchers[ "foo" ]["label"],
|
||||||
|
"text": self.matchers[ "foo" ]["text"],
|
||||||
|
"info": ""
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
# optionally proposed based on left search via regex
|
||||||
|
proposals.append(
|
||||||
|
{
|
||||||
|
"label": self.matchers[ "bar" ]["label"],
|
||||||
|
"text": self.matchers[ "bar" ]["text"],
|
||||||
|
"info": ""
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
return proposals
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
"""
|
||||||
|
Pligin Module
|
||||||
|
"""
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
"""
|
||||||
|
Pligin Package
|
||||||
|
"""
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"name": "Python Completer",
|
||||||
|
"author": "ITDominator",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"support": "",
|
||||||
|
"requests": {}
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
# Python imports
|
||||||
|
|
||||||
|
# Lib imports
|
||||||
|
import gi
|
||||||
|
gi.require_version('Gtk', '3.0')
|
||||||
|
from gi.repository import Gtk
|
||||||
|
|
||||||
|
# Application imports
|
||||||
|
from libs.event_factory import Event_Factory, Code_Event_Types
|
||||||
|
|
||||||
|
from plugins.plugin_types import PluginCode
|
||||||
|
|
||||||
|
from .provider import Provider
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class Plugin(PluginCode):
|
||||||
|
def __init__(self):
|
||||||
|
super(Plugin, self).__init__()
|
||||||
|
|
||||||
|
self.provider: Provider = None
|
||||||
|
|
||||||
|
|
||||||
|
def _controller_message(self, event: Code_Event_Types.CodeEvent):
|
||||||
|
...
|
||||||
|
|
||||||
|
def load(self):
|
||||||
|
self.provider = Provider()
|
||||||
|
|
||||||
|
event = Event_Factory.create_event(
|
||||||
|
"register_provider",
|
||||||
|
provider_name = "Python Completer",
|
||||||
|
provider = self.provider,
|
||||||
|
language_ids = []
|
||||||
|
)
|
||||||
|
self.emit_to("completion", event)
|
||||||
|
|
||||||
|
def unload(self):
|
||||||
|
event = Event_Factory.create_event(
|
||||||
|
"register_provider",
|
||||||
|
provider_name = "Python Completer"
|
||||||
|
)
|
||||||
|
self.emit_to("completion", event)
|
||||||
|
|
||||||
|
self.provider = None
|
||||||
|
del self.provider
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
...
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
# Python imports
|
||||||
|
|
||||||
|
# Lib imports
|
||||||
|
import gi
|
||||||
|
gi.require_version('GtkSource', '4')
|
||||||
|
|
||||||
|
from gi.repository import GObject
|
||||||
|
from gi.repository import GtkSource
|
||||||
|
|
||||||
|
# Application imports
|
||||||
|
from .provider_response_cache import ProviderResponseCache
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class Provider(GObject.GObject, GtkSource.CompletionProvider):
|
||||||
|
"""
|
||||||
|
This code is A python code completion plugin for Newton.
|
||||||
|
# NOTE: Some code pulled/referenced from here --> https://github.com/isamert/gedi
|
||||||
|
"""
|
||||||
|
__gtype_name__ = 'PythonCompletionProvider'
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
super(Provider, self).__init__()
|
||||||
|
|
||||||
|
self.response_cache: ProviderResponseCache = ProviderResponseCache()
|
||||||
|
|
||||||
|
|
||||||
|
def do_get_name(self):
|
||||||
|
return "Python Code Completion"
|
||||||
|
|
||||||
|
def do_match(self, context):
|
||||||
|
word = self.response_cache.get_word(context)
|
||||||
|
if not word or len(word) < 2: return False
|
||||||
|
|
||||||
|
iter = self.response_cache.get_iter_correctly(context)
|
||||||
|
iter.backward_char()
|
||||||
|
|
||||||
|
ch = iter.get_char()
|
||||||
|
# NOTE: Look to re-add or apply supporting logic to use spaces
|
||||||
|
# As is it slows down the editor in certain contexts...
|
||||||
|
# if not (ch in ('_', '.', ' ') or ch.isalnum()):
|
||||||
|
if not (ch in ('_', '.') or ch.isalnum()):
|
||||||
|
return False
|
||||||
|
|
||||||
|
buffer = iter.get_buffer()
|
||||||
|
if buffer.get_context_classes_at_iter(iter) != ['no-spell-check']:
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def do_get_priority(self):
|
||||||
|
return 5
|
||||||
|
|
||||||
|
def do_activate_proposal(self, proposal, iter_):
|
||||||
|
buffer = iter_.get_buffer()
|
||||||
|
# Note: Flag mostly intended for SourceViewsMultiInsertState
|
||||||
|
# to insure marker processes inserted text correctly.
|
||||||
|
buffer.is_processing_completion = True
|
||||||
|
return False
|
||||||
|
|
||||||
|
def do_get_activation(self):
|
||||||
|
""" The context for when a provider will show results """
|
||||||
|
return GtkSource.CompletionActivation.INTERACTIVE
|
||||||
|
|
||||||
|
def do_populate(self, context):
|
||||||
|
results = self.response_cache.filter_with_context(context)
|
||||||
|
|
||||||
|
proposals = []
|
||||||
|
for entry in results:
|
||||||
|
proposals.append(
|
||||||
|
self.response_cache.create_completion_item(
|
||||||
|
entry["label"],
|
||||||
|
entry["text"],
|
||||||
|
entry["info"]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
context.add_proposals(self, proposals, True)
|
||||||
@@ -0,0 +1,106 @@
|
|||||||
|
# Python imports
|
||||||
|
|
||||||
|
# Lib imports
|
||||||
|
import gi
|
||||||
|
gi.require_version('GtkSource', '4')
|
||||||
|
|
||||||
|
from gi.repository import GObject
|
||||||
|
from gi.repository import GtkSource
|
||||||
|
|
||||||
|
import jedi
|
||||||
|
from jedi.api import Script
|
||||||
|
|
||||||
|
# Application imports
|
||||||
|
from libs.event_factory import Code_Event_Types
|
||||||
|
|
||||||
|
from core.widgets.code.completion_providers.provider_response_cache_base import ProviderResponseCacheBase
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# FIXME: Find real icon names...
|
||||||
|
icon_names = {
|
||||||
|
'import': '',
|
||||||
|
'module': '',
|
||||||
|
'class': '',
|
||||||
|
'function': '',
|
||||||
|
'statement': '',
|
||||||
|
'param': ''
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class Jedi:
|
||||||
|
def get_script(file, doc_text):
|
||||||
|
return Script(code = doc_text, path = file)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class ProviderResponseCache(ProviderResponseCacheBase):
|
||||||
|
def __init__(self):
|
||||||
|
super(ProviderResponseCache, self).__init__()
|
||||||
|
|
||||||
|
self._file = None
|
||||||
|
|
||||||
|
|
||||||
|
def process_file_load(self, event: Code_Event_Types.AddedNewFileEvent):
|
||||||
|
...
|
||||||
|
|
||||||
|
def process_file_close(self, event: Code_Event_Types.RemovedFileEvent):
|
||||||
|
...
|
||||||
|
|
||||||
|
def process_file_save(self, event: Code_Event_Types.SavedFileEvent):
|
||||||
|
...
|
||||||
|
|
||||||
|
def process_file_change(self, event: Code_Event_Types.TextChangedEvent):
|
||||||
|
...
|
||||||
|
|
||||||
|
def filter(self, word: str) -> list[dict]:
|
||||||
|
response: list[dict] = []
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
def filter_with_context(self, context: GtkSource.CompletionContext) -> list[dict]:
|
||||||
|
response: list[dict] = []
|
||||||
|
|
||||||
|
if not self._file: return response
|
||||||
|
|
||||||
|
itr = self.get_iter_correctly(context)
|
||||||
|
buffer = itr.get_buffer()
|
||||||
|
|
||||||
|
doc_text = buffer.get_text(
|
||||||
|
buffer.get_start_iter(),
|
||||||
|
buffer.get_end_iter(),
|
||||||
|
False
|
||||||
|
)
|
||||||
|
iter_cursor = buffer.get_iter_at_mark( buffer.get_insert() )
|
||||||
|
linenum = iter_cursor.get_line() + 1
|
||||||
|
charnum = iter_cursor.get_line_index()
|
||||||
|
|
||||||
|
def create_generator():
|
||||||
|
if not self._file: return []
|
||||||
|
|
||||||
|
for completion in Jedi.get_script(self._file, doc_text).complete(
|
||||||
|
line = linenum,
|
||||||
|
column = None,
|
||||||
|
fuzzy = False
|
||||||
|
):
|
||||||
|
{
|
||||||
|
"label": completion.name,
|
||||||
|
"text": completion.name,
|
||||||
|
"info": completion.docstring()
|
||||||
|
"icon" self.get_icon_for_type(completion.type)
|
||||||
|
}
|
||||||
|
|
||||||
|
yield comp_item
|
||||||
|
|
||||||
|
for item in create_generator():
|
||||||
|
response.append(item)
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
def get_icon_for_type(self, _type):
|
||||||
|
try:
|
||||||
|
return self._theme.load_icon(icon_names[_type.lower()], 16, 0)
|
||||||
|
except (KeyError, AttributeError, GObject.GError) as e:
|
||||||
|
return self._theme.load_icon(Gtk.STOCK_ADD, 16, 0)
|
||||||
|
except (GObject.GError, AttributeError) as e:
|
||||||
|
return None
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
"""
|
||||||
|
Pligin Module
|
||||||
|
"""
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
"""
|
||||||
|
Pligin Package
|
||||||
|
"""
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
from .parser import load, loads
|
||||||
|
from .writer import dump, dumps
|
||||||
|
from .speg import ParseError
|
||||||
@@ -0,0 +1,295 @@
|
|||||||
|
from .speg import peg
|
||||||
|
import re, sys
|
||||||
|
|
||||||
|
if sys.version_info[0] == 2:
|
||||||
|
_chr = unichr
|
||||||
|
else:
|
||||||
|
_chr = chr
|
||||||
|
|
||||||
|
def load(fin):
|
||||||
|
return loads(fin.read())
|
||||||
|
|
||||||
|
def loads(s):
|
||||||
|
if isinstance(s, bytes):
|
||||||
|
s = s.decode('utf-8')
|
||||||
|
if s.startswith(u'\ufeff'):
|
||||||
|
s = s[1:]
|
||||||
|
return peg(s.replace('\r\n', '\n'), _p_root)
|
||||||
|
|
||||||
|
def _p_ws(p):
|
||||||
|
p('[ \t]*')
|
||||||
|
|
||||||
|
def _p_nl(p):
|
||||||
|
p(r'([ \t]*(?:#[^\n]*)?\r?\n)+')
|
||||||
|
|
||||||
|
def _p_ews(p):
|
||||||
|
with p:
|
||||||
|
p(_p_nl)
|
||||||
|
p(_p_ws)
|
||||||
|
|
||||||
|
def _p_id(p):
|
||||||
|
return p(r'[$a-zA-Z_][$0-9a-zA-Z_]*')
|
||||||
|
|
||||||
|
_escape_table = {
|
||||||
|
'r': '\r',
|
||||||
|
'n': '\n',
|
||||||
|
't': '\t',
|
||||||
|
'f': '\f',
|
||||||
|
'b': '\b',
|
||||||
|
}
|
||||||
|
def _p_unescape(p):
|
||||||
|
esc = p('\\\\(?:u[0-9a-fA-F]{4}|[^\n])')
|
||||||
|
if esc[1] == 'u':
|
||||||
|
return _chr(int(esc[2:], 16))
|
||||||
|
return _escape_table.get(esc[1:], esc[1:])
|
||||||
|
|
||||||
|
_re_indent = re.compile(r'[ \t]*')
|
||||||
|
def _p_block_str(p, c):
|
||||||
|
p(r'{c}{c}{c}'.format(c=c))
|
||||||
|
lines = [['']]
|
||||||
|
with p:
|
||||||
|
while True:
|
||||||
|
s = p(r'(?:{c}(?!{c}{c})|[^{c}\\])*'.format(c=c))
|
||||||
|
l = s.split('\n')
|
||||||
|
lines[-1].append(l[0])
|
||||||
|
lines.extend([x] for x in l[1:])
|
||||||
|
if p(r'(?:\\\n[ \t]*)*'):
|
||||||
|
continue
|
||||||
|
p.commit()
|
||||||
|
lines[-1].append(p(_p_unescape))
|
||||||
|
p(r'{c}{c}{c}'.format(c=c))
|
||||||
|
|
||||||
|
lines = [''.join(l) for l in lines]
|
||||||
|
strip_ws = len(lines) > 1
|
||||||
|
if strip_ws and all(c in ' \t' for c in lines[-1]):
|
||||||
|
lines.pop()
|
||||||
|
|
||||||
|
indent = None
|
||||||
|
for line in lines[1:]:
|
||||||
|
if not line:
|
||||||
|
continue
|
||||||
|
if indent is None:
|
||||||
|
indent = _re_indent.match(line).group(0)
|
||||||
|
continue
|
||||||
|
for i, (c1, c2) in enumerate(zip(indent, line)):
|
||||||
|
if c1 != c2:
|
||||||
|
indent = indent[:i]
|
||||||
|
break
|
||||||
|
|
||||||
|
ind_len = len(indent or '')
|
||||||
|
if strip_ws and all(c in ' \t' for c in lines[0]):
|
||||||
|
lines = [line[ind_len:] for line in lines[1:]]
|
||||||
|
else:
|
||||||
|
lines[1:] = [line[ind_len:] for line in lines[1:]]
|
||||||
|
|
||||||
|
return '\n'.join(lines)
|
||||||
|
|
||||||
|
_re_mstr_nl = re.compile(r'(?:[ \t]*\n)+[ \t]*')
|
||||||
|
_re_mstr_trailing_nl = re.compile(_re_mstr_nl.pattern + r'\Z')
|
||||||
|
def _p_multiline_str(p, c):
|
||||||
|
p('{c}(?!{c}{c})(?:[ \t]*\n[ \t]*)?'.format(c=c))
|
||||||
|
string_parts = []
|
||||||
|
with p:
|
||||||
|
while True:
|
||||||
|
string_parts.append(p(r'[^{c}\\]*'.format(c=c)))
|
||||||
|
if p(r'(?:\\\n[ \t]*)*'):
|
||||||
|
string_parts.append('')
|
||||||
|
continue
|
||||||
|
p.commit()
|
||||||
|
string_parts.append(p(_p_unescape))
|
||||||
|
p(c)
|
||||||
|
string_parts[-1] = _re_mstr_trailing_nl.sub('', string_parts[-1])
|
||||||
|
string_parts[::2] = [_re_mstr_nl.sub(' ', part) for part in string_parts[::2]]
|
||||||
|
return ''.join(string_parts)
|
||||||
|
|
||||||
|
def _p_string(p):
|
||||||
|
with p:
|
||||||
|
return p(_p_block_str, '"')
|
||||||
|
with p:
|
||||||
|
return p(_p_block_str, "'")
|
||||||
|
with p:
|
||||||
|
return p(_p_multiline_str, '"')
|
||||||
|
return p(_p_multiline_str, "'")
|
||||||
|
|
||||||
|
def _p_array_value(p):
|
||||||
|
with p:
|
||||||
|
p(_p_nl)
|
||||||
|
return p(_p_object)
|
||||||
|
with p:
|
||||||
|
p(_p_ws)
|
||||||
|
return p(_p_line_object)
|
||||||
|
p(_p_ews)
|
||||||
|
return p(_p_simple_value)
|
||||||
|
|
||||||
|
def _p_key(p):
|
||||||
|
with p:
|
||||||
|
return p(_p_id)
|
||||||
|
return p(_p_string)
|
||||||
|
|
||||||
|
def _p_flow_kv(p):
|
||||||
|
k = p(_p_key)
|
||||||
|
p(_p_ews)
|
||||||
|
p(':')
|
||||||
|
with p:
|
||||||
|
p(_p_nl)
|
||||||
|
return k, p(_p_object)
|
||||||
|
with p:
|
||||||
|
p(_p_ws)
|
||||||
|
return k, p(_p_line_object)
|
||||||
|
p(_p_ews)
|
||||||
|
return k, p(_p_simple_value)
|
||||||
|
|
||||||
|
def _p_flow_obj_sep(p):
|
||||||
|
with p:
|
||||||
|
p(_p_ews)
|
||||||
|
p(',')
|
||||||
|
p(_p_ews)
|
||||||
|
return
|
||||||
|
|
||||||
|
p(_p_nl)
|
||||||
|
p(_p_ws)
|
||||||
|
|
||||||
|
def _p_simple_value(p):
|
||||||
|
with p:
|
||||||
|
p('null')
|
||||||
|
return None
|
||||||
|
|
||||||
|
with p:
|
||||||
|
p('false')
|
||||||
|
return False
|
||||||
|
with p:
|
||||||
|
p('true')
|
||||||
|
return True
|
||||||
|
|
||||||
|
with p:
|
||||||
|
return int(p('0b[01]+')[2:], 2)
|
||||||
|
with p:
|
||||||
|
return int(p('0o[0-7]+')[2:], 8)
|
||||||
|
with p:
|
||||||
|
return int(p('0x[0-9a-fA-F]+')[2:], 16)
|
||||||
|
with p:
|
||||||
|
return float(p(r'-?(?:[1-9][0-9]*|0)?\.[0-9]+(?:[Ee][\+-]?[0-9]+)?|(?:[1-9][0-9]*|0)(?:\.[0-9]+)?[Ee][\+-]?[0-9]+'))
|
||||||
|
with p:
|
||||||
|
return int(p('-?[1-9][0-9]*|0'), 10)
|
||||||
|
|
||||||
|
with p:
|
||||||
|
return p(_p_string)
|
||||||
|
|
||||||
|
with p:
|
||||||
|
p(r'\[')
|
||||||
|
r = []
|
||||||
|
with p:
|
||||||
|
p.set('I', '')
|
||||||
|
r.append(p(_p_array_value))
|
||||||
|
with p:
|
||||||
|
while True:
|
||||||
|
with p:
|
||||||
|
p(_p_ews)
|
||||||
|
p(',')
|
||||||
|
rr = p(_p_array_value)
|
||||||
|
if not p:
|
||||||
|
p(_p_nl)
|
||||||
|
with p:
|
||||||
|
rr = p(_p_object)
|
||||||
|
if not p:
|
||||||
|
p(_p_ews)
|
||||||
|
rr = p(_p_simple_value)
|
||||||
|
r.append(rr)
|
||||||
|
p.commit()
|
||||||
|
with p:
|
||||||
|
p(_p_ews)
|
||||||
|
p(',')
|
||||||
|
p(_p_ews)
|
||||||
|
p(r'\]')
|
||||||
|
return r
|
||||||
|
|
||||||
|
p(r'\{')
|
||||||
|
|
||||||
|
r = {}
|
||||||
|
p(_p_ews)
|
||||||
|
with p:
|
||||||
|
p.set('I', '')
|
||||||
|
k, v = p(_p_flow_kv)
|
||||||
|
r[k] = v
|
||||||
|
with p:
|
||||||
|
while True:
|
||||||
|
p(_p_flow_obj_sep)
|
||||||
|
k, v = p(_p_flow_kv)
|
||||||
|
r[k] = v
|
||||||
|
p.commit()
|
||||||
|
p(_p_ews)
|
||||||
|
with p:
|
||||||
|
p(',')
|
||||||
|
p(_p_ews)
|
||||||
|
p(r'\}')
|
||||||
|
return r
|
||||||
|
|
||||||
|
def _p_line_kv(p):
|
||||||
|
k = p(_p_key)
|
||||||
|
p(_p_ws)
|
||||||
|
p(':')
|
||||||
|
p(_p_ws)
|
||||||
|
with p:
|
||||||
|
p(_p_nl)
|
||||||
|
p(p.get('I'))
|
||||||
|
return k, p(_p_indented_object)
|
||||||
|
with p:
|
||||||
|
return k, p(_p_line_object)
|
||||||
|
with p:
|
||||||
|
return k, p(_p_simple_value)
|
||||||
|
p(_p_nl)
|
||||||
|
p(p.get('I'))
|
||||||
|
p('[ \t]')
|
||||||
|
p(_p_ws)
|
||||||
|
return k, p(_p_simple_value)
|
||||||
|
|
||||||
|
def _p_line_object(p):
|
||||||
|
k, v = p(_p_line_kv)
|
||||||
|
r = { k: v }
|
||||||
|
with p:
|
||||||
|
while True:
|
||||||
|
p(_p_ws)
|
||||||
|
p(',')
|
||||||
|
p(_p_ws)
|
||||||
|
k, v = p(_p_line_kv)
|
||||||
|
r[k] = v # uniqueness
|
||||||
|
p.commit()
|
||||||
|
return r
|
||||||
|
|
||||||
|
def _p_object(p):
|
||||||
|
p.set('I', p.get('I') + p('[ \t]*'))
|
||||||
|
r = p(_p_line_object)
|
||||||
|
with p:
|
||||||
|
while True:
|
||||||
|
p(_p_ws)
|
||||||
|
with p:
|
||||||
|
p(',')
|
||||||
|
p(_p_nl)
|
||||||
|
p(p.get('I'))
|
||||||
|
rr = p(_p_line_object)
|
||||||
|
r.update(rr) # unqueness
|
||||||
|
p.commit()
|
||||||
|
return r
|
||||||
|
|
||||||
|
def _p_indented_object(p):
|
||||||
|
p.set('I', p.get('I') + p('[ \t]'))
|
||||||
|
return p(_p_object)
|
||||||
|
|
||||||
|
def _p_root(p):
|
||||||
|
with p:
|
||||||
|
p(_p_nl)
|
||||||
|
|
||||||
|
with p:
|
||||||
|
p.set('I', '')
|
||||||
|
r = p(_p_object)
|
||||||
|
p(_p_ws)
|
||||||
|
with p:
|
||||||
|
p(',')
|
||||||
|
|
||||||
|
if not p:
|
||||||
|
p(_p_ws)
|
||||||
|
r = p(_p_simple_value)
|
||||||
|
|
||||||
|
p(_p_ews)
|
||||||
|
p(p.eof)
|
||||||
|
return r
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
from .peg import peg, ParseError
|
||||||
@@ -0,0 +1,147 @@
|
|||||||
|
import sys, re
|
||||||
|
|
||||||
|
class ParseError(Exception):
|
||||||
|
def __init__(self, msg, text, offset, line, col):
|
||||||
|
self.msg = msg
|
||||||
|
self.text = text
|
||||||
|
self.offset = offset
|
||||||
|
self.line = line
|
||||||
|
self.col = col
|
||||||
|
super(ParseError, self).__init__(msg, offset, line, col)
|
||||||
|
|
||||||
|
if sys.version_info[0] == 2:
|
||||||
|
_basestr = basestring
|
||||||
|
else:
|
||||||
|
_basestr = str
|
||||||
|
|
||||||
|
def peg(s, r):
|
||||||
|
p = _Peg(s)
|
||||||
|
try:
|
||||||
|
return p(r)
|
||||||
|
except _UnexpectedError as e:
|
||||||
|
offset = max(p._errors)
|
||||||
|
err = p._errors[offset]
|
||||||
|
raise ParseError(err.msg, s, offset, err.line, err.col)
|
||||||
|
|
||||||
|
class _UnexpectedError(RuntimeError):
|
||||||
|
def __init__(self, state, expr):
|
||||||
|
self.state = state
|
||||||
|
self.expr = expr
|
||||||
|
|
||||||
|
class _PegState:
|
||||||
|
def __init__(self, pos, line, col):
|
||||||
|
self.pos = pos
|
||||||
|
self.line = line
|
||||||
|
self.col = col
|
||||||
|
self.vars = {}
|
||||||
|
self.commited = False
|
||||||
|
|
||||||
|
class _PegError:
|
||||||
|
def __init__(self, msg, line, col):
|
||||||
|
self.msg = msg
|
||||||
|
self.line = line
|
||||||
|
self.col = col
|
||||||
|
|
||||||
|
class _Peg:
|
||||||
|
def __init__(self, s):
|
||||||
|
self._s = s
|
||||||
|
self._states = [_PegState(0, 1, 1)]
|
||||||
|
self._errors = {}
|
||||||
|
self._re_cache = {}
|
||||||
|
|
||||||
|
def __call__(self, r, *args, **kw):
|
||||||
|
if isinstance(r, _basestr):
|
||||||
|
compiled = self._re_cache.get(r)
|
||||||
|
if not compiled:
|
||||||
|
compiled = re.compile(r)
|
||||||
|
self._re_cache[r] = compiled
|
||||||
|
st = self._states[-1]
|
||||||
|
m = compiled.match(self._s[st.pos:])
|
||||||
|
if not m:
|
||||||
|
self.error(expr=r, err=kw.get('err'))
|
||||||
|
|
||||||
|
ms = m.group(0)
|
||||||
|
st.pos += len(ms)
|
||||||
|
nl_pos = ms.rfind('\n')
|
||||||
|
if nl_pos < 0:
|
||||||
|
st.col += len(ms)
|
||||||
|
else:
|
||||||
|
st.col = len(ms) - nl_pos
|
||||||
|
st.line += ms[:nl_pos].count('\n') + 1
|
||||||
|
return ms
|
||||||
|
else:
|
||||||
|
kw.pop('err', None)
|
||||||
|
return r(self, *args, **kw)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
pos = self._states[-1].pos
|
||||||
|
vars = {}
|
||||||
|
for st in self._states:
|
||||||
|
vars.update(st.vars)
|
||||||
|
return '_Peg(%r, %r)' % (self._s[:pos] + '*' + self._s[pos:], vars)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def eof(p):
|
||||||
|
if p._states[-1].pos != len(p._s):
|
||||||
|
p.error()
|
||||||
|
|
||||||
|
def error(self, err=None, expr=None):
|
||||||
|
st = self._states[-1]
|
||||||
|
if err is None:
|
||||||
|
err = 'expected {!r}, found {!r}'.format(expr, self._s[st.pos:st.pos+4])
|
||||||
|
self._errors[st.pos] = _PegError(err, st.line, st.col)
|
||||||
|
raise _UnexpectedError(st, expr)
|
||||||
|
|
||||||
|
def get(self, key, default=None):
|
||||||
|
for state in self._states[::-1]:
|
||||||
|
if key in state.vars:
|
||||||
|
return state.vars[key][0]
|
||||||
|
return default
|
||||||
|
|
||||||
|
def set(self, key, value):
|
||||||
|
self._states[-1].vars[key] = value, False
|
||||||
|
|
||||||
|
def set_global(self, key, value):
|
||||||
|
self._states[-1].vars[key] = value, True
|
||||||
|
|
||||||
|
def opt(self, *args, **kw):
|
||||||
|
with self:
|
||||||
|
return self(*args, **kw)
|
||||||
|
|
||||||
|
def not_(self, s, *args, **kw):
|
||||||
|
with self:
|
||||||
|
self(s)
|
||||||
|
self.error()
|
||||||
|
|
||||||
|
def __enter__(self):
|
||||||
|
self._states[-1].committed = False
|
||||||
|
self._states.append(_PegState(self._states[-1].pos, self._states[-1].line, self._states[-1].col))
|
||||||
|
|
||||||
|
def __exit__(self, type, value, traceback):
|
||||||
|
if type is None:
|
||||||
|
self.commit()
|
||||||
|
self._states.pop()
|
||||||
|
return type == _UnexpectedError
|
||||||
|
|
||||||
|
def commit(self):
|
||||||
|
cur = self._states[-1]
|
||||||
|
prev = self._states[-2]
|
||||||
|
|
||||||
|
for key in cur.vars:
|
||||||
|
val, g = cur.vars[key]
|
||||||
|
if not g:
|
||||||
|
continue
|
||||||
|
if key in prev.vars:
|
||||||
|
prev.vars[key] = val, prev.vars[key][1]
|
||||||
|
else:
|
||||||
|
prev.vars[key] = val, True
|
||||||
|
|
||||||
|
prev.pos = cur.pos
|
||||||
|
prev.line = cur.line
|
||||||
|
prev.col = cur.col
|
||||||
|
prev.committed = True
|
||||||
|
|
||||||
|
def __nonzero__(self):
|
||||||
|
return self._states[-1].committed
|
||||||
|
|
||||||
|
__bool__ = __nonzero__
|
||||||
@@ -0,0 +1,191 @@
|
|||||||
|
import re, json, sys
|
||||||
|
|
||||||
|
if sys.version_info[0] == 2:
|
||||||
|
def _is_num(o):
|
||||||
|
return isinstance(o, int) or isinstance(o, long) or isinstance(o, float)
|
||||||
|
def _stringify(o):
|
||||||
|
if isinstance(o, str):
|
||||||
|
return unicode(o)
|
||||||
|
if isinstance(o, unicode):
|
||||||
|
return o
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
def _is_num(o):
|
||||||
|
return isinstance(o, int) or isinstance(o, float)
|
||||||
|
def _stringify(o):
|
||||||
|
if isinstance(o, bytes):
|
||||||
|
return o.decode()
|
||||||
|
if isinstance(o, str):
|
||||||
|
return o
|
||||||
|
return None
|
||||||
|
|
||||||
|
_id_re = re.compile(r'[$a-zA-Z_][$0-9a-zA-Z_]*\Z')
|
||||||
|
|
||||||
|
class CSONEncoder:
|
||||||
|
def __init__(self, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, sort_keys=False,
|
||||||
|
indent=None, default=None):
|
||||||
|
self._skipkeys = skipkeys
|
||||||
|
self._ensure_ascii = ensure_ascii
|
||||||
|
self._allow_nan = allow_nan
|
||||||
|
self._sort_keys = sort_keys
|
||||||
|
self._indent = ' ' * (indent or 4)
|
||||||
|
self._default = default
|
||||||
|
if check_circular:
|
||||||
|
self._obj_stack = set()
|
||||||
|
else:
|
||||||
|
self._obj_stack = None
|
||||||
|
|
||||||
|
def _format_simple_val(self, o):
|
||||||
|
if o is None:
|
||||||
|
return 'null'
|
||||||
|
if isinstance(o, bool):
|
||||||
|
return 'true' if o else 'false'
|
||||||
|
if _is_num(o):
|
||||||
|
return str(o)
|
||||||
|
s = _stringify(o)
|
||||||
|
if s is not None:
|
||||||
|
return self._escape_string(s)
|
||||||
|
return None
|
||||||
|
|
||||||
|
def _escape_string(self, s):
|
||||||
|
r = json.dumps(s, ensure_ascii=self._ensure_ascii)
|
||||||
|
return u"'{}'".format(r[1:-1].replace("'", r"\'"))
|
||||||
|
|
||||||
|
def _escape_key(self, s):
|
||||||
|
if s is None or isinstance(s, bool) or _is_num(s):
|
||||||
|
s = str(s)
|
||||||
|
s = _stringify(s)
|
||||||
|
if s is None:
|
||||||
|
if self._skipkeys:
|
||||||
|
return None
|
||||||
|
raise TypeError('keys must be a string')
|
||||||
|
if not _id_re.match(s):
|
||||||
|
return self._escape_string(s)
|
||||||
|
return s
|
||||||
|
|
||||||
|
def _push_obj(self, o):
|
||||||
|
if self._obj_stack is not None:
|
||||||
|
if id(o) in self._obj_stack:
|
||||||
|
raise ValueError('Circular reference detected')
|
||||||
|
self._obj_stack.add(id(o))
|
||||||
|
|
||||||
|
def _pop_obj(self, o):
|
||||||
|
if self._obj_stack is not None:
|
||||||
|
self._obj_stack.remove(id(o))
|
||||||
|
|
||||||
|
def _encode(self, o, obj_val=False, indent='', force_flow=False):
|
||||||
|
if isinstance(o, list):
|
||||||
|
if not o:
|
||||||
|
if obj_val:
|
||||||
|
yield ' []\n'
|
||||||
|
else:
|
||||||
|
yield indent
|
||||||
|
yield '[]\n'
|
||||||
|
else:
|
||||||
|
if obj_val:
|
||||||
|
yield ' [\n'
|
||||||
|
else:
|
||||||
|
yield indent
|
||||||
|
yield '[\n'
|
||||||
|
indent = indent + self._indent
|
||||||
|
self._push_obj(o)
|
||||||
|
for v in o:
|
||||||
|
for chunk in self._encode(v, obj_val=False, indent=indent, force_flow=True):
|
||||||
|
yield chunk
|
||||||
|
self._pop_obj(o)
|
||||||
|
yield indent[:-len(self._indent)]
|
||||||
|
yield ']\n'
|
||||||
|
elif isinstance(o, dict):
|
||||||
|
items = [(self._escape_key(k), v) for k, v in o.items()]
|
||||||
|
if self._skipkeys:
|
||||||
|
items = [(k, v) for k, v in items if k is not None]
|
||||||
|
if self._sort_keys:
|
||||||
|
items.sort()
|
||||||
|
if force_flow or not items:
|
||||||
|
if not items:
|
||||||
|
if obj_val:
|
||||||
|
yield ' {}\n'
|
||||||
|
else:
|
||||||
|
yield indent
|
||||||
|
yield '{}\n'
|
||||||
|
else:
|
||||||
|
if obj_val:
|
||||||
|
yield ' {\n'
|
||||||
|
else:
|
||||||
|
yield indent
|
||||||
|
yield '{\n'
|
||||||
|
indent = indent + self._indent
|
||||||
|
self._push_obj(o)
|
||||||
|
for k, v in items:
|
||||||
|
yield indent
|
||||||
|
yield k
|
||||||
|
yield ':'
|
||||||
|
for chunk in self._encode(v, obj_val=True, indent=indent + self._indent, force_flow=False):
|
||||||
|
yield chunk
|
||||||
|
self._pop_obj(o)
|
||||||
|
yield indent[:-len(self._indent)]
|
||||||
|
yield '}\n'
|
||||||
|
else:
|
||||||
|
if obj_val:
|
||||||
|
yield '\n'
|
||||||
|
self._push_obj(o)
|
||||||
|
for k, v in items:
|
||||||
|
yield indent
|
||||||
|
yield k
|
||||||
|
yield ':'
|
||||||
|
for chunk in self._encode(v, obj_val=True, indent=indent + self._indent, force_flow=False):
|
||||||
|
yield chunk
|
||||||
|
self._pop_obj(o)
|
||||||
|
else:
|
||||||
|
v = self._format_simple_val(o)
|
||||||
|
if v is None:
|
||||||
|
self._push_obj(o)
|
||||||
|
v = self.default(o)
|
||||||
|
for chunk in self._encode(v, obj_val=obj_val, indent=indent, force_flow=force_flow):
|
||||||
|
yield chunk
|
||||||
|
self._pop_obj(o)
|
||||||
|
else:
|
||||||
|
if obj_val:
|
||||||
|
yield ' '
|
||||||
|
else:
|
||||||
|
yield indent
|
||||||
|
yield v
|
||||||
|
yield '\n'
|
||||||
|
|
||||||
|
def iterencode(self, o):
|
||||||
|
return self._encode(o)
|
||||||
|
|
||||||
|
def encode(self, o):
|
||||||
|
return ''.join(self.iterencode(o))
|
||||||
|
|
||||||
|
def default(self, o):
|
||||||
|
if self._default is None:
|
||||||
|
raise TypeError('Cannot serialize an object of type {}'.format(type(o).__name__))
|
||||||
|
return self._default(o)
|
||||||
|
|
||||||
|
def dump(obj, fp, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None,
|
||||||
|
indent=None, default=None, sort_keys=False, **kw):
|
||||||
|
if indent is None and cls is None:
|
||||||
|
return json.dump(obj, fp, skipkeys=skipkeys, ensure_ascii=ensure_ascii, check_circular=check_circular,
|
||||||
|
allow_nan=allow_nan, default=default, sort_keys=sort_keys, separators=(',', ':'))
|
||||||
|
|
||||||
|
if cls is None:
|
||||||
|
cls = CSONEncoder
|
||||||
|
encoder = cls(skipkeys=skipkeys, ensure_ascii=ensure_ascii, check_circular=check_circular,
|
||||||
|
allow_nan=allow_nan, sort_keys=sort_keys, indent=indent, default=default, **kw)
|
||||||
|
|
||||||
|
for chunk in encoder.iterencode(obj):
|
||||||
|
fp.write(chunk)
|
||||||
|
|
||||||
|
def dumps(obj, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None,
|
||||||
|
default=None, sort_keys=False, **kw):
|
||||||
|
if indent is None and cls is None:
|
||||||
|
return json.dumps(obj, skipkeys=skipkeys, ensure_ascii=ensure_ascii, check_circular=check_circular,
|
||||||
|
allow_nan=allow_nan, default=default, sort_keys=sort_keys, separators=(',', ':'))
|
||||||
|
|
||||||
|
if cls is None:
|
||||||
|
cls = CSONEncoder
|
||||||
|
encoder = cls(skipkeys=skipkeys, ensure_ascii=ensure_ascii, check_circular=check_circular,
|
||||||
|
allow_nan=allow_nan, sort_keys=sort_keys, indent=indent, default=default, **kw)
|
||||||
|
|
||||||
|
return encoder.encode(obj)
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"name": "Snippets Completer",
|
||||||
|
"author": "ITDominator",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"support": "",
|
||||||
|
"requests": {}
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
# Python imports
|
||||||
|
|
||||||
|
# Lib imports
|
||||||
|
import gi
|
||||||
|
gi.require_version('Gtk', '3.0')
|
||||||
|
from gi.repository import Gtk
|
||||||
|
|
||||||
|
# Application imports
|
||||||
|
from libs.event_factory import Event_Factory, Code_Event_Types
|
||||||
|
|
||||||
|
from plugins.plugin_types import PluginCode
|
||||||
|
|
||||||
|
from .provider import Provider
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class Plugin(PluginCode):
|
||||||
|
def __init__(self):
|
||||||
|
super(Plugin, self).__init__()
|
||||||
|
|
||||||
|
self.provider: Provider = None
|
||||||
|
|
||||||
|
|
||||||
|
def _controller_message(self, event: Code_Event_Types.CodeEvent):
|
||||||
|
...
|
||||||
|
|
||||||
|
def load(self):
|
||||||
|
self.provider = Provider()
|
||||||
|
|
||||||
|
event = Event_Factory.create_event(
|
||||||
|
"register_provider",
|
||||||
|
provider_name = "Snippets Completer",
|
||||||
|
provider = self.provider,
|
||||||
|
language_ids = []
|
||||||
|
)
|
||||||
|
self.emit_to("completion", event)
|
||||||
|
|
||||||
|
def unload(self):
|
||||||
|
event = Event_Factory.create_event(
|
||||||
|
"unregister_provider",
|
||||||
|
provider_name = "Snippets Completer"
|
||||||
|
)
|
||||||
|
self.emit_to("completion", event)
|
||||||
|
|
||||||
|
self.provider = None
|
||||||
|
del self.provider
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
...
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
# Python imports
|
||||||
|
import re
|
||||||
|
|
||||||
|
# Lib imports
|
||||||
|
import gi
|
||||||
|
gi.require_version('GtkSource', '4')
|
||||||
|
|
||||||
|
from gi.repository import GObject
|
||||||
|
from gi.repository import GtkSource
|
||||||
|
|
||||||
|
# Application imports
|
||||||
|
from .provider_response_cache import ProviderResponseCache
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class Provider(GObject.GObject, GtkSource.CompletionProvider):
|
||||||
|
"""
|
||||||
|
This is a Snippits Completion Provider.
|
||||||
|
# NOTE: used information from here --> https://warroom.rsmus.com/do-that-auto-complete/
|
||||||
|
"""
|
||||||
|
__gtype_name__ = 'SnippetsCompletionProvider'
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
super(Provider, self).__init__()
|
||||||
|
|
||||||
|
self.response_cache: ProviderResponseCache = ProviderResponseCache()
|
||||||
|
|
||||||
|
|
||||||
|
def do_get_name(self):
|
||||||
|
return 'Snippits Completion'
|
||||||
|
|
||||||
|
def do_match(self, context):
|
||||||
|
word = self.response_cache.get_word(context)
|
||||||
|
if not word or len(word) < 2: return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def do_get_priority(self):
|
||||||
|
return 2
|
||||||
|
|
||||||
|
def do_activate_proposal(self, proposal, iter_):
|
||||||
|
buffer = iter_.get_buffer()
|
||||||
|
# Note: Flag mostly intended for SourceViewsMultiInsertState
|
||||||
|
# to insure marker processes inserted text correctly.
|
||||||
|
buffer.is_processing_completion = True
|
||||||
|
return False
|
||||||
|
|
||||||
|
def do_get_activation(self):
|
||||||
|
""" The context for when a provider will show results """
|
||||||
|
# return GtkSource.CompletionActivation.NONE
|
||||||
|
return GtkSource.CompletionActivation.USER_REQUESTED
|
||||||
|
# return GtkSource.CompletionActivation.INTERACTIVE
|
||||||
|
|
||||||
|
def do_populate(self, context):
|
||||||
|
word = self.response_cache.get_word(context)
|
||||||
|
results = self.response_cache.filter(word)
|
||||||
|
proposals = []
|
||||||
|
|
||||||
|
for entry in results:
|
||||||
|
proposals.append(
|
||||||
|
self.response_cache.create_completion_item(
|
||||||
|
entry["label"],
|
||||||
|
entry["text"],
|
||||||
|
entry["info"]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
context.add_proposals(self, proposals, True)
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
# Python imports
|
||||||
|
from os import path
|
||||||
|
|
||||||
|
# Lib imports
|
||||||
|
import gi
|
||||||
|
gi.require_version('GtkSource', '4')
|
||||||
|
|
||||||
|
from gi.repository import GLib
|
||||||
|
from gi.repository import GtkSource
|
||||||
|
|
||||||
|
# Application imports
|
||||||
|
from libs.event_factory import Code_Event_Types
|
||||||
|
|
||||||
|
from core.widgets.code.completion_providers.provider_response_cache_base import ProviderResponseCacheBase
|
||||||
|
|
||||||
|
from . import cson
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class ProviderResponseCache(ProviderResponseCacheBase):
|
||||||
|
def __init__(self):
|
||||||
|
super(ProviderResponseCache, self).__init__()
|
||||||
|
|
||||||
|
self.matchers: dict = {}
|
||||||
|
|
||||||
|
self.load_snippets()
|
||||||
|
|
||||||
|
|
||||||
|
def load_snippets(self):
|
||||||
|
fpath = path.join(path.dirname(path.realpath(__file__)), "snippets.cson")
|
||||||
|
with open(fpath, 'rb') as f:
|
||||||
|
self.snippets = cson.load(f)
|
||||||
|
for group in self.snippets:
|
||||||
|
self.snippets[group]
|
||||||
|
for entry in self.snippets[group]:
|
||||||
|
data = self.snippets[group][entry]
|
||||||
|
self.matchers[ data["prefix"] ] = {
|
||||||
|
"label": entry,
|
||||||
|
"text": data["body"],
|
||||||
|
"info": GLib.markup_escape_text( data["body"] )
|
||||||
|
}
|
||||||
|
|
||||||
|
def process_file_load(self, event: Code_Event_Types.AddedNewFileEvent):
|
||||||
|
...
|
||||||
|
|
||||||
|
def process_file_close(self, event: Code_Event_Types.RemovedFileEvent):
|
||||||
|
...
|
||||||
|
|
||||||
|
def process_file_save(self, event: Code_Event_Types.SavedFileEvent):
|
||||||
|
...
|
||||||
|
|
||||||
|
def process_file_change(self, event: Code_Event_Types.TextChangedEvent):
|
||||||
|
...
|
||||||
|
|
||||||
|
def filter(self, word: str) -> list[dict]:
|
||||||
|
response: list[dict] = []
|
||||||
|
|
||||||
|
for entry in self.matchers:
|
||||||
|
if not word in entry: continue
|
||||||
|
data = self.matchers[entry]
|
||||||
|
response.append(data)
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
def filter_with_context(self, context: GtkSource.CompletionContext) -> list[dict]:
|
||||||
|
response: list[dict] = []
|
||||||
|
|
||||||
|
return response
|
||||||
@@ -0,0 +1,614 @@
|
|||||||
|
# Your snippets
|
||||||
|
#
|
||||||
|
# Atom snippets allow you to enter a simple prefix in the editor and hit tab to
|
||||||
|
# expand the prefix into a larger code block with templated values.
|
||||||
|
#
|
||||||
|
# You can create a new snippet in this file by typing "snip" and then hitting
|
||||||
|
# tab.
|
||||||
|
#
|
||||||
|
# An example CoffeeScript snippet to expand log to console.log:
|
||||||
|
#
|
||||||
|
# '.source.coffee':
|
||||||
|
# 'Console log':
|
||||||
|
# 'prefix': 'log'
|
||||||
|
# 'body': 'console.log $1'
|
||||||
|
#
|
||||||
|
# Each scope (e.g. '.source.coffee' above) can only be declared once.
|
||||||
|
#
|
||||||
|
# This file uses CoffeeScript Object Notation (CSON).
|
||||||
|
# If you are unfamiliar with CSON, you can read more about it in the
|
||||||
|
# Atom Flight Manual:
|
||||||
|
# http://flight-manual.atom.io/using-atom/sections/basic-customization/#_cson
|
||||||
|
|
||||||
|
|
||||||
|
### HTML SNIPPETS ###
|
||||||
|
'.text.html.basic':
|
||||||
|
|
||||||
|
'HTML Template':
|
||||||
|
'prefix': 'html'
|
||||||
|
'body': """<!DOCTYPE html>
|
||||||
|
<html lang="en" dir="ltr">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title></title>
|
||||||
|
<link rel="shortcut icon" href="fave_icon.png">
|
||||||
|
<link rel="stylesheet" href="resources/css/base.css">
|
||||||
|
<link rel="stylesheet" href="resources/css/main.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<script src="resources/js/.js" charset="utf-8"></script>
|
||||||
|
<script src="resources/js/.js" charset="utf-8"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
"""
|
||||||
|
|
||||||
|
'Canvas Tag':
|
||||||
|
'prefix': 'canvas'
|
||||||
|
'body': """<canvas id="canvas" width="800" height="600" style="border:1px solid #c3c3c3;"></canvas>"""
|
||||||
|
|
||||||
|
'Img Tag':
|
||||||
|
'prefix': 'img'
|
||||||
|
'body': """<img class="" src="" alt="" />"""
|
||||||
|
|
||||||
|
'Br Tag':
|
||||||
|
'prefix': 'br'
|
||||||
|
'body': """<br/>"""
|
||||||
|
|
||||||
|
'Hr Tag':
|
||||||
|
'prefix': 'hr'
|
||||||
|
'body': """<hr/>"""
|
||||||
|
|
||||||
|
'Server Side Events':
|
||||||
|
'prefix': 'sse'
|
||||||
|
'body': """// SSE events if supported
|
||||||
|
if(typeof(EventSource) !== "undefined") {
|
||||||
|
let source = new EventSource("resources/php/sse.php");
|
||||||
|
source.onmessage = (event) => {
|
||||||
|
if (event.data === "<yourDataStringToLookFor>") {
|
||||||
|
// code here
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
console.log("SSE Not Supported In Browser...");
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
'AJAX Template Function':
|
||||||
|
'prefix': 'ajax template'
|
||||||
|
'body': """const doAjax = async (actionPath, data) => {
|
||||||
|
let xhttp = new XMLHttpRequest();
|
||||||
|
|
||||||
|
xhttp.onreadystatechange = function() {
|
||||||
|
if (this.readyState === 4 && this.status === 200) {
|
||||||
|
if (this.responseText != null) { // this.responseXML if getting XML fata
|
||||||
|
handleReturnData(JSON.parse(this.responseText));
|
||||||
|
} else {
|
||||||
|
console.log("No content returned. Check the file path.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
xhttp.open("POST", actionPath, true);
|
||||||
|
xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
|
||||||
|
// Force return to be JSON NOTE: Use application/xml to force XML
|
||||||
|
xhttp.overrideMimeType('application/json');
|
||||||
|
xhttp.send(data);
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
'CSS Message Colors':
|
||||||
|
'prefix': 'css colors'
|
||||||
|
'body': """.error { color: rgb(255, 0, 0); }
|
||||||
|
.warning { color: rgb(255, 168, 0); }
|
||||||
|
.success { color: rgb(136, 204, 39); }
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
### JS SNIPPETS ###
|
||||||
|
'.source.js':
|
||||||
|
|
||||||
|
'Server Side Events':
|
||||||
|
'prefix': 'sse'
|
||||||
|
'body': """// SSE events if supported
|
||||||
|
if(typeof(EventSource) !== "undefined") {
|
||||||
|
let source = new EventSource("resources/php/sse.php");
|
||||||
|
source.onmessage = (event) => {
|
||||||
|
if (event.data === "<yourDataStringToLookFor>") {
|
||||||
|
// code here
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
console.log("SSE Not Supported In Browser...");
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
'AJAX Template Function':
|
||||||
|
'prefix': 'ajax template'
|
||||||
|
'body': """const doAjax = async (actionPath, data) => {
|
||||||
|
let xhttp = new XMLHttpRequest();
|
||||||
|
|
||||||
|
xhttp.onreadystatechange = function() {
|
||||||
|
if (this.readyState === 4 && this.status === 200) {
|
||||||
|
if (this.responseText != null) { // this.responseXML if getting XML fata
|
||||||
|
handleReturnData(JSON.parse(this.responseText));
|
||||||
|
} else {
|
||||||
|
console.log("No content returned. Check the file path.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
xhttp.open("POST", actionPath, true);
|
||||||
|
xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
|
||||||
|
// Force return to be JSON NOTE: Use application/xml to force XML
|
||||||
|
xhttp.overrideMimeType('application/json');
|
||||||
|
xhttp.send(data);
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
'SE6 Function':
|
||||||
|
'prefix': 'function se6'
|
||||||
|
'body': """const funcName = (arg = "") => {
|
||||||
|
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
### CSS SNIPPETS ###
|
||||||
|
'.source.css':
|
||||||
|
|
||||||
|
'CSS Message Colors':
|
||||||
|
'prefix': 'css colors'
|
||||||
|
'body': """.error { color: rgb(255, 0, 0); }
|
||||||
|
.warning { color: rgb(255, 168, 0); }
|
||||||
|
.success { color: rgb(136, 204, 39); }
|
||||||
|
"""
|
||||||
|
|
||||||
|
### PHP SNIPPETS ###
|
||||||
|
'.text.html.php':
|
||||||
|
|
||||||
|
'SSE PHP':
|
||||||
|
'prefix': 'sse php'
|
||||||
|
'body': """<?php
|
||||||
|
// Start the session
|
||||||
|
session_start();
|
||||||
|
|
||||||
|
header('Content-Type: text/event-stream');
|
||||||
|
header('Cache-Control: no-cache');
|
||||||
|
|
||||||
|
echo "data:dataToReturn\\\\n\\\\n";
|
||||||
|
|
||||||
|
flush();
|
||||||
|
?>
|
||||||
|
"""
|
||||||
|
|
||||||
|
'PHP Template':
|
||||||
|
'prefix': 'php'
|
||||||
|
'body': """<?php
|
||||||
|
// Start the session
|
||||||
|
session_start();
|
||||||
|
|
||||||
|
|
||||||
|
// Determin action
|
||||||
|
chdir("../../"); // Note: If in resources/php/
|
||||||
|
if (isset($_POST['yourPostID'])) {
|
||||||
|
// code here
|
||||||
|
} else {
|
||||||
|
$message = "Server: [Error] --> Illegal Access Method!";
|
||||||
|
serverMessage("error", $message);
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
"""
|
||||||
|
'HTML Template':
|
||||||
|
'prefix': 'html'
|
||||||
|
'body': """<!DOCTYPE html>
|
||||||
|
<html lang="en" dir="ltr">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title></title>
|
||||||
|
<link rel="shortcut icon" href="fave_icon.png">
|
||||||
|
<link rel="stylesheet" href="resources/css/base.css">
|
||||||
|
<link rel="stylesheet" href="resources/css/main.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<script src="resources/js/.js" charset="utf-8"></script>
|
||||||
|
<script src="resources/js/.js" charset="utf-8"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
### BASH SNIPPETS ###
|
||||||
|
'.source.shell':
|
||||||
|
|
||||||
|
'Bash or Shell Template':
|
||||||
|
'prefix': 'bash template'
|
||||||
|
'body': """#!/bin/bash
|
||||||
|
|
||||||
|
# . CONFIG.sh
|
||||||
|
|
||||||
|
# set -o xtrace ## To debug scripts
|
||||||
|
# set -o errexit ## To exit on error
|
||||||
|
# set -o errunset ## To exit if a variable is referenced but not set
|
||||||
|
|
||||||
|
|
||||||
|
function main() {
|
||||||
|
cd "$(dirname "$0")"
|
||||||
|
echo "Working Dir: " $(pwd)
|
||||||
|
|
||||||
|
file="$1"
|
||||||
|
if [ -z "${file}" ]; then
|
||||||
|
echo "ERROR: No file argument supplied..."
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -f "${file}" ]]; then
|
||||||
|
echo "SUCCESS: The path and file exists!"
|
||||||
|
else
|
||||||
|
echo "ERROR: The path or file '${file}' does NOT exist..."
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
main "$@";
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
'Bash or Shell Config':
|
||||||
|
'prefix': 'bash config'
|
||||||
|
'body': """#!/bin/bash
|
||||||
|
|
||||||
|
shopt -s expand_aliases
|
||||||
|
|
||||||
|
alias echo="echo -e"
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
### PYTHON SNIPPETS ###
|
||||||
|
'.source.python':
|
||||||
|
|
||||||
|
'Glade __main__ Class Template':
|
||||||
|
'prefix': 'glade __main__ class'
|
||||||
|
'body': """#!/usr/bin/python3
|
||||||
|
|
||||||
|
|
||||||
|
# Python imports
|
||||||
|
import argparse
|
||||||
|
import faulthandler
|
||||||
|
import traceback
|
||||||
|
import signal
|
||||||
|
from setproctitle import setproctitle
|
||||||
|
|
||||||
|
# Lib imports
|
||||||
|
import gi
|
||||||
|
gi.require_version('Gtk', '3.0')
|
||||||
|
from gi.repository import Gtk
|
||||||
|
from gi.repository import GLib
|
||||||
|
|
||||||
|
# Application imports
|
||||||
|
from app import Application
|
||||||
|
|
||||||
|
|
||||||
|
def run():
|
||||||
|
try:
|
||||||
|
setproctitle('<replace this>')
|
||||||
|
faulthandler.enable() # For better debug info
|
||||||
|
|
||||||
|
GLib.unix_signal_add(GLib.PRIORITY_DEFAULT, signal.SIGINT, Gtk.main_quit)
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
# Add long and short arguments
|
||||||
|
parser.add_argument("--debug", "-d", default="false", help="Do extra console messaging.")
|
||||||
|
parser.add_argument("--trace-debug", "-td", default="false", help="Disable saves, ignore IPC lock, do extra console messaging.")
|
||||||
|
parser.add_argument("--no-plugins", "-np", default="false", help="Do not load plugins.")
|
||||||
|
|
||||||
|
parser.add_argument("--new-tab", "-t", default="", help="Open a file into new tab.")
|
||||||
|
parser.add_argument("--new-window", "-w", default="", help="Open a file into a new window.")
|
||||||
|
|
||||||
|
# Read arguments (If any...)
|
||||||
|
args, unknownargs = parser.parse_known_args()
|
||||||
|
|
||||||
|
main = Application(args, unknownargs)
|
||||||
|
Gtk.main()
|
||||||
|
except Exception as e:
|
||||||
|
traceback.print_exc()
|
||||||
|
quit()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
''' Set process title, get arguments, and create GTK main thread. '''
|
||||||
|
run()
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
'Glade __main__ Testing Template':
|
||||||
|
'prefix': 'glade testing class'
|
||||||
|
'body': """#!/usr/bin/python3
|
||||||
|
|
||||||
|
|
||||||
|
# Python imports
|
||||||
|
import traceback
|
||||||
|
import faulthandler
|
||||||
|
import signal
|
||||||
|
|
||||||
|
# Lib imports
|
||||||
|
import gi
|
||||||
|
gi.require_version('Gtk', '3.0')
|
||||||
|
from gi.repository import Gtk
|
||||||
|
from gi.repository import GLib
|
||||||
|
|
||||||
|
# Application imports
|
||||||
|
|
||||||
|
|
||||||
|
app_name = "Gtk Quick Test"
|
||||||
|
|
||||||
|
|
||||||
|
class Application(Gtk.ApplicationWindow):
|
||||||
|
def __init__(self):
|
||||||
|
super(Application, self).__init__()
|
||||||
|
self._setup_styling()
|
||||||
|
self._setup_signals()
|
||||||
|
self._load_widgets()
|
||||||
|
|
||||||
|
self.add(Gtk.Box())
|
||||||
|
|
||||||
|
self.show_all()
|
||||||
|
|
||||||
|
|
||||||
|
def _setup_styling(self):
|
||||||
|
self.set_default_size(1670, 830)
|
||||||
|
self.set_title(f"{app_name}")
|
||||||
|
# self.set_icon_from_file( settings.get_window_icon() )
|
||||||
|
self.set_gravity(5) # 5 = CENTER
|
||||||
|
self.set_position(1) # 1 = CENTER, 4 = CENTER_ALWAYS
|
||||||
|
|
||||||
|
def _setup_signals(self):
|
||||||
|
self.connect("delete-event", Gtk.main_quit)
|
||||||
|
|
||||||
|
|
||||||
|
def _load_widgets(self):
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def run():
|
||||||
|
try:
|
||||||
|
faulthandler.enable() # For better debug info
|
||||||
|
GLib.unix_signal_add(GLib.PRIORITY_DEFAULT, signal.SIGINT, Gtk.main_quit)
|
||||||
|
|
||||||
|
main = Application()
|
||||||
|
Gtk.main()
|
||||||
|
except Exception as e:
|
||||||
|
traceback.print_exc()
|
||||||
|
quit()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
''' Set process title, get arguments, and create GTK main thread. '''
|
||||||
|
run()
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
'Glade _init_ Class Template':
|
||||||
|
'prefix': 'glade __init__ class'
|
||||||
|
'body': """# Python imports
|
||||||
|
import inspect
|
||||||
|
|
||||||
|
|
||||||
|
# Lib imports
|
||||||
|
|
||||||
|
|
||||||
|
# Application imports
|
||||||
|
from utils import Settings
|
||||||
|
from signal_classes import CrossClassSignals
|
||||||
|
|
||||||
|
|
||||||
|
class Main:
|
||||||
|
def __init__(self, args):
|
||||||
|
settings = Settings()
|
||||||
|
builder = settings.returnBuilder()
|
||||||
|
|
||||||
|
# Gets the methods from the classes and sets to handler.
|
||||||
|
# Then, builder connects to any signals it needs.
|
||||||
|
classes = [CrossClassSignals(settings)]
|
||||||
|
|
||||||
|
handlers = {}
|
||||||
|
for c in classes:
|
||||||
|
methods = inspect.getmembers(c, predicate=inspect.ismethod)
|
||||||
|
handlers.update(methods)
|
||||||
|
|
||||||
|
builder.connect_signals(handlers)
|
||||||
|
window = settings.createWindow()
|
||||||
|
window.show()
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
'Class Method':
|
||||||
|
'prefix': 'def1'
|
||||||
|
'body': """
|
||||||
|
def fname(self):
|
||||||
|
...
|
||||||
|
"""
|
||||||
|
|
||||||
|
'Gtk Class Method':
|
||||||
|
'prefix': 'def2'
|
||||||
|
'body': """
|
||||||
|
def fname(self, widget, eve):
|
||||||
|
...
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
'Python Glade Settings Template':
|
||||||
|
'prefix': 'glade settings class'
|
||||||
|
'body': """# Python imports
|
||||||
|
import os
|
||||||
|
|
||||||
|
# Lib imports
|
||||||
|
import gi, cairo
|
||||||
|
gi.require_version('Gtk', '3.0')
|
||||||
|
gi.require_version('Gdk', '3.0')
|
||||||
|
|
||||||
|
from gi.repository import Gtk
|
||||||
|
from gi.repository import Gdk
|
||||||
|
|
||||||
|
|
||||||
|
# Application imports
|
||||||
|
|
||||||
|
|
||||||
|
class Settings:
|
||||||
|
def __init__(self):
|
||||||
|
self.SCRIPT_PTH = os.path.dirname(os.path.realpath(__file__)) + "/"
|
||||||
|
self.builder = Gtk.Builder()
|
||||||
|
self.builder.add_from_file(self.SCRIPT_PTH + "../resources/Main_Window.glade")
|
||||||
|
|
||||||
|
# 'Filters'
|
||||||
|
self.office = ('.doc', '.docx', '.xls', '.xlsx', '.xlt', '.xltx', '.xlm',
|
||||||
|
'.ppt', 'pptx', '.pps', '.ppsx', '.odt', '.rtf')
|
||||||
|
self.vids = ('.mkv', '.avi', '.flv', '.mov', '.m4v', '.mpg', '.wmv',
|
||||||
|
'.mpeg', '.mp4', '.webm')
|
||||||
|
self.txt = ('.txt', '.text', '.sh', '.cfg', '.conf')
|
||||||
|
self.music = ('.psf', '.mp3', '.ogg' , '.flac')
|
||||||
|
self.images = ('.png', '.jpg', '.jpeg', '.gif')
|
||||||
|
self.pdf = ('.pdf')
|
||||||
|
|
||||||
|
|
||||||
|
def createWindow(self):
|
||||||
|
# Get window and connect signals
|
||||||
|
window = self.builder.get_object("Main_Window")
|
||||||
|
window.connect("delete-event", gtk.main_quit)
|
||||||
|
self.setWindowData(window, False)
|
||||||
|
return window
|
||||||
|
|
||||||
|
def setWindowData(self, window, paintable):
|
||||||
|
screen = window.get_screen()
|
||||||
|
visual = screen.get_rgba_visual()
|
||||||
|
|
||||||
|
if visual != None and screen.is_composited():
|
||||||
|
window.set_visual(visual)
|
||||||
|
|
||||||
|
# bind css file
|
||||||
|
cssProvider = gtk.CssProvider()
|
||||||
|
cssProvider.load_from_path(self.SCRIPT_PTH + '../resources/stylesheet.css')
|
||||||
|
screen = Gdk.Screen.get_default()
|
||||||
|
styleContext = Gtk.StyleContext()
|
||||||
|
styleContext.add_provider_for_screen(screen, cssProvider, gtk.STYLE_PROVIDER_PRIORITY_USER)
|
||||||
|
|
||||||
|
window.set_app_paintable(paintable)
|
||||||
|
if paintable:
|
||||||
|
window.connect("draw", self.area_draw)
|
||||||
|
|
||||||
|
def getMonitorData(self):
|
||||||
|
screen = self.builder.get_object("Main_Window").get_screen()
|
||||||
|
monitors = []
|
||||||
|
for m in range(screen.get_n_monitors()):
|
||||||
|
monitors.append(screen.get_monitor_geometry(m))
|
||||||
|
|
||||||
|
for monitor in monitors:
|
||||||
|
print(str(monitor.width) + "x" + str(monitor.height) + "+" + str(monitor.x) + "+" + str(monitor.y))
|
||||||
|
|
||||||
|
return monitors
|
||||||
|
|
||||||
|
def area_draw(self, widget, cr):
|
||||||
|
cr.set_source_rgba(0, 0, 0, 0.54)
|
||||||
|
cr.set_operator(cairo.OPERATOR_SOURCE)
|
||||||
|
cr.paint()
|
||||||
|
cr.set_operator(cairo.OPERATOR_OVER)
|
||||||
|
|
||||||
|
|
||||||
|
def returnBuilder(self): return self.builder
|
||||||
|
|
||||||
|
# Filter returns
|
||||||
|
def returnOfficeFilter(self): return self.office
|
||||||
|
def returnVidsFilter(self): return self.vids
|
||||||
|
def returnTextFilter(self): return self.txt
|
||||||
|
def returnMusicFilter(self): return self.music
|
||||||
|
def returnImagesFilter(self): return self.images
|
||||||
|
def returnPdfFilter(self): return self.pdf
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
'Python Glade CrossClassSignals Template':
|
||||||
|
'prefix': 'glade crossClassSignals class'
|
||||||
|
'body': """# Python imports
|
||||||
|
import threading
|
||||||
|
import subprocess
|
||||||
|
import os
|
||||||
|
|
||||||
|
# Lib imports
|
||||||
|
|
||||||
|
# Application imports
|
||||||
|
|
||||||
|
|
||||||
|
def threaded(fn):
|
||||||
|
def wrapper(*args, **kwargs):
|
||||||
|
threading.Thread(target=fn, args=args, kwargs=kwargs).start()
|
||||||
|
|
||||||
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
|
class CrossClassSignals:
|
||||||
|
def __init__(self, settings):
|
||||||
|
self.settings = settings
|
||||||
|
self.builder = self.settings.returnBuilder()
|
||||||
|
|
||||||
|
|
||||||
|
def getClipboardData(self):
|
||||||
|
proc = subprocess.Popen(['xclip','-selection', 'clipboard', '-o'], stdout=subprocess.PIPE)
|
||||||
|
retcode = proc.wait()
|
||||||
|
data = proc.stdout.read()
|
||||||
|
return data.decode("utf-8").strip()
|
||||||
|
|
||||||
|
def setClipboardData(self, data):
|
||||||
|
proc = subprocess.Popen(['xclip','-selection','clipboard'], stdin=subprocess.PIPE)
|
||||||
|
proc.stdin.write(data)
|
||||||
|
proc.stdin.close()
|
||||||
|
retcode = proc.wait()
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
'Python Glade Generic Template':
|
||||||
|
'prefix': 'glade generic class'
|
||||||
|
'body': """# Python imports
|
||||||
|
|
||||||
|
# Lib imports
|
||||||
|
|
||||||
|
# Application imports
|
||||||
|
|
||||||
|
|
||||||
|
class GenericClass:
|
||||||
|
def __init__(self):
|
||||||
|
super(GenericClass, self).__init__()
|
||||||
|
|
||||||
|
self._setup_styling()
|
||||||
|
self._setup_signals()
|
||||||
|
self._subscribe_to_events()
|
||||||
|
self._load_widgets()
|
||||||
|
|
||||||
|
|
||||||
|
def _setup_styling(self):
|
||||||
|
...
|
||||||
|
|
||||||
|
def _setup_signals(self):
|
||||||
|
...
|
||||||
|
|
||||||
|
def _subscribe_to_events(self):
|
||||||
|
event_system.subscribe("handle_file_from_ipc", self.handle_file_from_ipc)
|
||||||
|
|
||||||
|
def _load_widgets(self):
|
||||||
|
...
|
||||||
|
|
||||||
|
"""
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
"""
|
||||||
|
Pligin Module
|
||||||
|
"""
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
"""
|
||||||
|
Pligin Package
|
||||||
|
"""
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
# Python imports
|
||||||
|
import re
|
||||||
|
|
||||||
|
# Lib imports
|
||||||
|
import gi
|
||||||
|
gi.require_version('Gtk', '3.0')
|
||||||
|
gi.require_version('GtkSource', '4')
|
||||||
|
|
||||||
|
from gi.repository import GObject
|
||||||
|
from gi.repository import Gtk
|
||||||
|
from gi.repository import GtkSource
|
||||||
|
|
||||||
|
# Application imports
|
||||||
|
from .provider_response_cache import ProviderResponseCache
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class Provider(GtkSource.CompletionWords):
|
||||||
|
"""
|
||||||
|
This is a Words Completion Provider.
|
||||||
|
# NOTE: used information from here --> https://warroom.rsmus.com/do-that-auto-complete/
|
||||||
|
"""
|
||||||
|
__gtype_name__ = 'WordsCompletionProvider'
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
super(Provider, self).__init__()
|
||||||
|
|
||||||
|
self.response_cache: ProviderResponseCache = ProviderResponseCache()
|
||||||
|
|
||||||
|
|
||||||
|
def do_get_name(self):
|
||||||
|
return 'Words Completion'
|
||||||
|
|
||||||
|
def do_match(self, context):
|
||||||
|
# Note: If provider is in interactive activation then need to check
|
||||||
|
# view focus as otherwise non focus views start trying to grab it.
|
||||||
|
completion = context.get_property("completion")
|
||||||
|
if not completion.get_view().has_focus(): return
|
||||||
|
|
||||||
|
word = self.response_cache.get_word(context)
|
||||||
|
if not word or len(word) < 2: return False
|
||||||
|
|
||||||
|
iter = self.response_cache.get_iter_correctly(context)
|
||||||
|
iter.backward_char()
|
||||||
|
ch = iter.get_char()
|
||||||
|
# NOTE: Look to re-add or apply supprting logic to use spaces
|
||||||
|
# As is it slows down the editor in certain contexts...
|
||||||
|
# if not (ch in ('_', '.', ' ') or ch.isalnum()):
|
||||||
|
if not (ch in ('_', '.') or ch.isalnum()):
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def do_get_priority(self):
|
||||||
|
return 0
|
||||||
|
|
||||||
|
def do_activate_proposal(self, proposal, iter_):
|
||||||
|
buffer = iter_.get_buffer()
|
||||||
|
# Note: Flag mostly intended for SourceViewsMultiInsertState
|
||||||
|
# to insure marker processes inserted text correctly.
|
||||||
|
buffer.is_processing_completion = True
|
||||||
|
return False
|
||||||
|
|
||||||
|
def do_get_activation(self):
|
||||||
|
""" The context for when a provider will show results """
|
||||||
|
# return GtkSource.CompletionActivation.NONE
|
||||||
|
# return GtkSource.CompletionActivation.USER_REQUESTED
|
||||||
|
return GtkSource.CompletionActivation.INTERACTIVE
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
# Python imports
|
||||||
|
|
||||||
|
# Lib imports
|
||||||
|
|
||||||
|
# Application imports
|
||||||
|
from libs.event_factory import Code_Event_Types
|
||||||
|
|
||||||
|
from core.widgets.code.completion_providers.provider_response_cache_base import ProviderResponseCacheBase
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class ProviderResponseCache(ProviderResponseCacheBase):
|
||||||
|
def __init__(self):
|
||||||
|
super(ProviderResponseCache, self).__init__()
|
||||||
|
|
||||||
|
self.matchers: dict = {}
|
||||||
|
|
||||||
|
|
||||||
|
def process_file_load(self, event: Code_Event_Types.AddedNewFileEvent):
|
||||||
|
...
|
||||||
|
|
||||||
|
def process_file_close(self, event: Code_Event_Types.RemovedFileEvent):
|
||||||
|
...
|
||||||
|
|
||||||
|
def process_file_save(self, event: Code_Event_Types.SavedFileEvent):
|
||||||
|
...
|
||||||
|
|
||||||
|
def process_file_change(self, event: Code_Event_Types.TextChangedEvent):
|
||||||
|
...
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"name": "Words Completer",
|
||||||
|
"author": "ITDominator",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"support": "",
|
||||||
|
"requests": {}
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
# Python imports
|
||||||
|
|
||||||
|
# Lib imports
|
||||||
|
import gi
|
||||||
|
gi.require_version('Gtk', '3.0')
|
||||||
|
from gi.repository import Gtk
|
||||||
|
|
||||||
|
# Application imports
|
||||||
|
from libs.event_factory import Event_Factory, Code_Event_Types
|
||||||
|
|
||||||
|
from plugins.plugin_types import PluginCode
|
||||||
|
|
||||||
|
from .provider import Provider
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class Plugin(PluginCode):
|
||||||
|
def __init__(self):
|
||||||
|
super(Plugin, self).__init__()
|
||||||
|
|
||||||
|
self.provider: Provider = None
|
||||||
|
|
||||||
|
|
||||||
|
def _controller_message(self, event: Code_Event_Types.CodeEvent):
|
||||||
|
...
|
||||||
|
|
||||||
|
def load(self):
|
||||||
|
self.provider = Provider()
|
||||||
|
|
||||||
|
event = Event_Factory.create_event(
|
||||||
|
"register_provider",
|
||||||
|
provider_name = "Words Completer",
|
||||||
|
provider = self.provider,
|
||||||
|
language_ids = []
|
||||||
|
)
|
||||||
|
self.emit_to("completion", event)
|
||||||
|
|
||||||
|
def unload(self):
|
||||||
|
event = Event_Factory.create_event(
|
||||||
|
"unregister_provider",
|
||||||
|
provider_name = "Words Completer"
|
||||||
|
)
|
||||||
|
self.emit_to("completion", event)
|
||||||
|
|
||||||
|
self.provider = None
|
||||||
|
del self.provider
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
...
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
# Python imports
|
||||||
|
import re
|
||||||
|
|
||||||
|
# Lib imports
|
||||||
|
import gi
|
||||||
|
gi.require_version('GtkSource', '4')
|
||||||
|
|
||||||
|
from gi.repository import GObject
|
||||||
|
from gi.repository import GtkSource
|
||||||
|
|
||||||
|
# Application imports
|
||||||
|
from .provider_response_cache import ProviderResponseCache
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class Provider(GObject.GObject, GtkSource.CompletionProvider):
|
||||||
|
"""
|
||||||
|
This is a Words Completion Provider.
|
||||||
|
# NOTE: used information from here --> https://warroom.rsmus.com/do-that-auto-complete/
|
||||||
|
"""
|
||||||
|
__gtype_name__ = 'WordsCompletionProvider'
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
super(Provider, self).__init__()
|
||||||
|
|
||||||
|
self.response_cache: ProviderResponseCache = ProviderResponseCache()
|
||||||
|
|
||||||
|
|
||||||
|
def do_get_name(self):
|
||||||
|
return 'Words Completion'
|
||||||
|
|
||||||
|
def do_match(self, context):
|
||||||
|
# Note: If provider is in interactive activation then need to check
|
||||||
|
# view focus as otherwise non focus views start trying to grab it.
|
||||||
|
completion = context.get_property("completion")
|
||||||
|
if not completion.get_view().has_focus(): return
|
||||||
|
|
||||||
|
word = self.response_cache.get_word(context)
|
||||||
|
if not word or len(word) < 2: return False
|
||||||
|
|
||||||
|
iter = self.response_cache.get_iter_correctly(context)
|
||||||
|
iter.backward_char()
|
||||||
|
ch = iter.get_char()
|
||||||
|
# NOTE: Look to re-add or apply supprting logic to use spaces
|
||||||
|
# As is it slows down the editor in certain contexts...
|
||||||
|
# if not (ch in ('_', '.', ' ') or ch.isalnum()):
|
||||||
|
if not (ch in ('_', '.') or ch.isalnum()):
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def do_get_priority(self):
|
||||||
|
return 0
|
||||||
|
|
||||||
|
def do_activate_proposal(self, proposal, iter_):
|
||||||
|
buffer = iter_.get_buffer()
|
||||||
|
# Note: Flag mostly intended for SourceViewsMultiInsertState
|
||||||
|
# to insure marker processes inserted text correctly.
|
||||||
|
buffer.is_processing_completion = True
|
||||||
|
return False
|
||||||
|
|
||||||
|
def do_get_activation(self):
|
||||||
|
""" The context for when a provider will show results """
|
||||||
|
# return GtkSource.CompletionActivation.NONE
|
||||||
|
# return GtkSource.CompletionActivation.USER_REQUESTED
|
||||||
|
return GtkSource.CompletionActivation.INTERACTIVE
|
||||||
|
|
||||||
|
def do_populate(self, context):
|
||||||
|
word = self.response_cache.get_word(context)
|
||||||
|
results = self.response_cache.filter_with_context(context)
|
||||||
|
# results = self.response_cache.filter(word)
|
||||||
|
|
||||||
|
# if not results:
|
||||||
|
# results = self.response_cache.filter_with_context(context)
|
||||||
|
|
||||||
|
proposals = []
|
||||||
|
for entry in results:
|
||||||
|
proposals.append(
|
||||||
|
self.response_cache.create_completion_item(
|
||||||
|
entry["label"],
|
||||||
|
entry["text"],
|
||||||
|
entry["info"]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
context.add_proposals(self, proposals, True)
|
||||||
@@ -0,0 +1,136 @@
|
|||||||
|
# Python imports
|
||||||
|
from concurrent.futures import ThreadPoolExecutor
|
||||||
|
|
||||||
|
# Lib imports
|
||||||
|
import gi
|
||||||
|
gi.require_version('GtkSource', '4')
|
||||||
|
|
||||||
|
from gi.repository import GLib
|
||||||
|
from gi.repository import GtkSource
|
||||||
|
|
||||||
|
# Application imports
|
||||||
|
from libs.event_factory import Code_Event_Types
|
||||||
|
|
||||||
|
from core.widgets.code.completion_providers.provider_response_cache_base import ProviderResponseCacheBase
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class ProviderResponseCache(ProviderResponseCacheBase):
|
||||||
|
def __init__(self):
|
||||||
|
super(ProviderResponseCache, self).__init__()
|
||||||
|
|
||||||
|
self.matchers: dict = {}
|
||||||
|
self._temp_timeout_id: int = None
|
||||||
|
|
||||||
|
|
||||||
|
def process_file_load(self, event: Code_Event_Types.AddedNewFileEvent):
|
||||||
|
buffer = event.file.buffer
|
||||||
|
with ThreadPoolExecutor(max_workers = 1) as executor:
|
||||||
|
executor.submit(self._handle_change, buffer)
|
||||||
|
|
||||||
|
def process_file_close(self, event: Code_Event_Types.RemovedFileEvent):
|
||||||
|
self.matchers[event.file.buffer] = set()
|
||||||
|
del self.matchers[event.file.buffer]
|
||||||
|
|
||||||
|
def process_file_save(self, event: Code_Event_Types.SavedFileEvent):
|
||||||
|
...
|
||||||
|
|
||||||
|
def process_file_change(self, event: Code_Event_Types.TextChangedEvent):
|
||||||
|
buffer = event.file.buffer
|
||||||
|
self._clear_temp_delay()
|
||||||
|
self._set_temp_delay(buffer)
|
||||||
|
|
||||||
|
def _clear_temp_delay(self):
|
||||||
|
if self._temp_timeout_id:
|
||||||
|
GLib.source_remove(self._temp_timeout_id)
|
||||||
|
|
||||||
|
def _set_temp_delay(self, buffer):
|
||||||
|
def run_refresh_update(buffer):
|
||||||
|
with ThreadPoolExecutor(max_workers = 1) as executor:
|
||||||
|
executor.submit(self._handle_change, buffer)
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
self._temp_timeout_id = GLib.timeout_add(1500, run_refresh_update, buffer)
|
||||||
|
|
||||||
|
def _handle_change(self, buffer):
|
||||||
|
start_itr = buffer.get_start_iter()
|
||||||
|
end_itr = buffer.get_end_iter()
|
||||||
|
data = buffer.get_text(start_itr, end_itr, False)
|
||||||
|
|
||||||
|
if not data:
|
||||||
|
GLib.idle_add(self.load_empty_set, buffer)
|
||||||
|
return
|
||||||
|
|
||||||
|
if not buffer in self.matchers:
|
||||||
|
GLib.idle_add(self.load_as_new_set, buffer, data)
|
||||||
|
return
|
||||||
|
|
||||||
|
new_words = self.get_all_words(data)
|
||||||
|
GLib.idle_add(self.load_into_set, buffer, new_words)
|
||||||
|
|
||||||
|
def filter(self, word: str) -> list[dict]:
|
||||||
|
response: list[dict] = []
|
||||||
|
|
||||||
|
for entry in self.matchers:
|
||||||
|
if not word in entry: continue
|
||||||
|
data = self.matchers[entry]
|
||||||
|
response.append(data)
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
def filter_with_context(self, context: GtkSource.CompletionContext) -> list[dict]:
|
||||||
|
buffer = self.get_iter_correctly(context).get_buffer()
|
||||||
|
word = self.get_word(context).rstrip()
|
||||||
|
|
||||||
|
if not buffer in self.matchers:
|
||||||
|
self.matchers[buffer] = set()
|
||||||
|
|
||||||
|
response: list[dict] = []
|
||||||
|
for entry in self.matchers[buffer]:
|
||||||
|
if not entry.rstrip().startswith(word): continue
|
||||||
|
|
||||||
|
data = {
|
||||||
|
"label": entry,
|
||||||
|
"text": entry,
|
||||||
|
"info": ""
|
||||||
|
}
|
||||||
|
|
||||||
|
response.append(data)
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
def load_empty_set(self, buffer):
|
||||||
|
self.matchers[buffer] = set()
|
||||||
|
|
||||||
|
def load_into_set(self, buffer, new_words):
|
||||||
|
# self.matchers[buffer].update(new_words)
|
||||||
|
self.matchers[buffer] = new_words
|
||||||
|
|
||||||
|
def load_as_new_set(self, buffer, data):
|
||||||
|
self.matchers[buffer] = self.get_all_words(data)
|
||||||
|
|
||||||
|
def get_all_words(self, data: str):
|
||||||
|
words = set()
|
||||||
|
|
||||||
|
def is_word_char(c):
|
||||||
|
return c.isalnum() or c == '_'
|
||||||
|
|
||||||
|
size = len(data)
|
||||||
|
i = 0
|
||||||
|
|
||||||
|
while i < size:
|
||||||
|
# Skip non-word characters
|
||||||
|
while i < size and not is_word_char(data[i]):
|
||||||
|
i += 1
|
||||||
|
|
||||||
|
start = i
|
||||||
|
# Consume word characters
|
||||||
|
while i < size and is_word_char(data[i]):
|
||||||
|
i += 1
|
||||||
|
|
||||||
|
word = data[start:i]
|
||||||
|
if not word: continue
|
||||||
|
words.add(word)
|
||||||
|
|
||||||
|
return words
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
"""
|
||||||
|
Plugin Module
|
||||||
|
"""
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
"""
|
||||||
|
Plugin Package
|
||||||
|
"""
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"name": "Extend Source View Menu",
|
||||||
|
"author": "ITDominator",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"support": "",
|
||||||
|
"requests": {}
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
# Python imports
|
||||||
|
|
||||||
|
# Lib imports
|
||||||
|
|
||||||
|
# Application imports
|
||||||
|
from libs.event_factory import Event_Factory, Code_Event_Types
|
||||||
|
|
||||||
|
from plugins.plugin_types import PluginCode
|
||||||
|
|
||||||
|
from .source_view_menu import extend_source_view_menu
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class Plugin(PluginCode):
|
||||||
|
def __init__(self):
|
||||||
|
super(Plugin, self).__init__()
|
||||||
|
|
||||||
|
def _controller_message(self, event: Code_Event_Types.CodeEvent):
|
||||||
|
if isinstance(event, Code_Event_Types.PopulateSourceViewPopupEvent):
|
||||||
|
extend_source_view_menu(event.buffer, event.menu)
|
||||||
|
|
||||||
|
def load(self):
|
||||||
|
...
|
||||||
|
|
||||||
|
def unload(self):
|
||||||
|
...
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
...
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
# Python imports
|
||||||
|
import json
|
||||||
|
|
||||||
|
# Lib imports
|
||||||
|
import gi
|
||||||
|
|
||||||
|
gi.require_version('Gtk', '3.0')
|
||||||
|
|
||||||
|
from gi.repository import Gtk
|
||||||
|
|
||||||
|
# Application imports
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def on_case_handle(menuitem, buffer, action):
|
||||||
|
start_itr, \
|
||||||
|
end_itr = buffer.get_selection_bounds()
|
||||||
|
data = buffer.get_text(start_itr, end_itr, False)
|
||||||
|
text = data
|
||||||
|
|
||||||
|
if action == "on_all_upper":
|
||||||
|
text = data.upper()
|
||||||
|
elif action == "on_all_lower":
|
||||||
|
text = data.lower()
|
||||||
|
elif action == "on_invert":
|
||||||
|
text = data.swapcase()
|
||||||
|
elif action == "on_title":
|
||||||
|
text = data.title()
|
||||||
|
elif action == "on_title_strip":
|
||||||
|
text = data.title().replace("-", "").replace("_", "").replace(" ", "")
|
||||||
|
|
||||||
|
buffer.begin_user_action()
|
||||||
|
buffer.delete(start_itr, end_itr)
|
||||||
|
buffer.insert(start_itr, text)
|
||||||
|
buffer.end_user_action()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def extend_source_view_menu(buffer, menu):
|
||||||
|
if not buffer.get_selection_bounds(): return
|
||||||
|
|
||||||
|
for child in menu.get_children():
|
||||||
|
if not child.get_label() == "C_hange Case": continue
|
||||||
|
menu.remove(child)
|
||||||
|
|
||||||
|
change_case_item = Gtk.MenuItem(label = "Change Case")
|
||||||
|
|
||||||
|
case_menu = Gtk.Menu()
|
||||||
|
au_case_item = Gtk.MenuItem(label = "All Upper Case")
|
||||||
|
al_case_item = Gtk.MenuItem(label = "All Lower Case")
|
||||||
|
inver_case_item = Gtk.MenuItem(label = "Invert Case")
|
||||||
|
title_case_item = Gtk.MenuItem(label = "Title Case")
|
||||||
|
title_strip_case_item = Gtk.MenuItem(label = "Title Strip Case")
|
||||||
|
|
||||||
|
au_case_item.connect("activate", on_case_handle, buffer, "on_all_upper")
|
||||||
|
al_case_item.connect("activate", on_case_handle, buffer, "on_all_lower")
|
||||||
|
inver_case_item.connect("activate", on_case_handle, buffer, "on_invert")
|
||||||
|
title_case_item.connect("activate", on_case_handle, buffer, "on_title")
|
||||||
|
title_strip_case_item.connect("activate", on_case_handle, buffer, "on_title_strip")
|
||||||
|
|
||||||
|
case_menu.append(au_case_item)
|
||||||
|
case_menu.append(al_case_item)
|
||||||
|
case_menu.append(inver_case_item)
|
||||||
|
case_menu.append(title_case_item)
|
||||||
|
case_menu.append(title_strip_case_item)
|
||||||
|
change_case_item.set_submenu(case_menu)
|
||||||
|
|
||||||
|
menu.append(change_case_item)
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
"""
|
||||||
|
Pligin Module
|
||||||
|
"""
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
"""
|
||||||
|
Pligin Package
|
||||||
|
"""
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"name": "File State Watcher",
|
||||||
|
"author": "ITDominator",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"support": "",
|
||||||
|
"requests": {}
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
# Python imports
|
||||||
|
|
||||||
|
# Lib imports
|
||||||
|
|
||||||
|
# Application imports
|
||||||
|
from libs.event_factory import Event_Factory, Code_Event_Types
|
||||||
|
|
||||||
|
from plugins.plugin_types import PluginCode
|
||||||
|
|
||||||
|
from .watcher_checks import *
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class Plugin(PluginCode):
|
||||||
|
def __init__(self):
|
||||||
|
super(Plugin, self).__init__()
|
||||||
|
|
||||||
|
|
||||||
|
def _controller_message(self, event: Code_Event_Types.CodeEvent):
|
||||||
|
if isinstance(event, Code_Event_Types.TextChangedEvent):
|
||||||
|
event.file.check_file_on_disk()
|
||||||
|
|
||||||
|
if event.file.is_deleted():
|
||||||
|
file_is_deleted(event, self.emit)
|
||||||
|
elif event.file.is_externally_modified():
|
||||||
|
file_is_externally_modified(event, self.emit)
|
||||||
|
|
||||||
|
def load(self):
|
||||||
|
...
|
||||||
|
|
||||||
|
def unload(self):
|
||||||
|
...
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
...
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
# Python imports
|
||||||
|
|
||||||
|
# Lib imports
|
||||||
|
import gi
|
||||||
|
gi.require_version('Gtk', '3.0')
|
||||||
|
from gi.repository import Gtk
|
||||||
|
|
||||||
|
# Application imports
|
||||||
|
from libs.event_factory import Event_Factory, Code_Event_Types
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def file_is_deleted(event, emit):
|
||||||
|
event.file.was_deleted = True
|
||||||
|
event = Event_Factory.create_event(
|
||||||
|
"file_externally_deleted",
|
||||||
|
file = event.file,
|
||||||
|
buffer = event.buffer
|
||||||
|
)
|
||||||
|
emit(event)
|
||||||
|
|
||||||
|
|
||||||
|
def file_is_externally_modified(event, emit):
|
||||||
|
# event = Event_Factory.create_event(
|
||||||
|
# "file_externally_modified",
|
||||||
|
# file = event.file,
|
||||||
|
# buffer = event.buffer
|
||||||
|
# )
|
||||||
|
# emit(event)
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
"""
|
||||||
|
Pligin Module
|
||||||
|
"""
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
"""
|
||||||
|
Pligin Package
|
||||||
|
"""
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"name": "Prettify JSON",
|
||||||
|
"author": "ITDominator",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"support": "",
|
||||||
|
"requests": {}
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
# Python imports
|
||||||
|
|
||||||
|
# Lib imports
|
||||||
|
import gi
|
||||||
|
|
||||||
|
gi.require_version('Gtk', '3.0')
|
||||||
|
|
||||||
|
from gi.repository import Gtk
|
||||||
|
|
||||||
|
# Application imports
|
||||||
|
from libs.event_factory import Event_Factory, Code_Event_Types
|
||||||
|
|
||||||
|
from plugins.plugin_types import PluginCode
|
||||||
|
|
||||||
|
from .prettify_json import add_prettify_json
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class Plugin(PluginCode):
|
||||||
|
def __init__(self):
|
||||||
|
super(Plugin, self).__init__()
|
||||||
|
|
||||||
|
|
||||||
|
def _controller_message(self, event: Code_Event_Types.CodeEvent):
|
||||||
|
if isinstance(event, Code_Event_Types.PopulateSourceViewPopupEvent):
|
||||||
|
language = event.buffer.get_language()
|
||||||
|
if not language: return
|
||||||
|
|
||||||
|
if "json" == language.get_id():
|
||||||
|
add_prettify_json(event.buffer, event.menu)
|
||||||
|
|
||||||
|
def load(self):
|
||||||
|
...
|
||||||
|
|
||||||
|
def unload(self):
|
||||||
|
...
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
...
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
# Python imports
|
||||||
|
import json
|
||||||
|
|
||||||
|
# Lib imports
|
||||||
|
import gi
|
||||||
|
|
||||||
|
gi.require_version('Gtk', '3.0')
|
||||||
|
|
||||||
|
from gi.repository import Gtk
|
||||||
|
|
||||||
|
# Application imports
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def add_prettify_json(buffer, menu):
|
||||||
|
def on_prettify_json(menuitem, buffer):
|
||||||
|
start_itr, \
|
||||||
|
end_itr = buffer.get_start_iter(), buffer.get_end_iter()
|
||||||
|
data = buffer.get_text(start_itr, end_itr, False)
|
||||||
|
text = json.dumps(json.loads(data), separators = (',', ':'), indent = 4)
|
||||||
|
|
||||||
|
buffer.begin_user_action()
|
||||||
|
buffer.delete(start_itr, end_itr)
|
||||||
|
buffer.insert(start_itr, text)
|
||||||
|
buffer.end_user_action()
|
||||||
|
|
||||||
|
item = Gtk.MenuItem(label = "Prettify JSON")
|
||||||
|
item.connect("activate", on_prettify_json, buffer)
|
||||||
|
menu.append(item)
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
"""
|
||||||
|
Pligin Module
|
||||||
|
"""
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
"""
|
||||||
|
Pligin Package
|
||||||
|
"""
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
from .libs.tree_sitter_language_pack import \
|
||||||
|
init, download, get_language, get_parser, available_languages, process, ProcessConfig
|
||||||
|
|
||||||
|
# Optional: Pre-download specific languages for offline use
|
||||||
|
#init(["python", "javascript", "rust"])
|
||||||
|
|
||||||
|
# Get a language (auto-downloads if not cached)
|
||||||
|
language = get_language("python")
|
||||||
|
|
||||||
|
# Get a pre-configured parser (auto-downloads if needed)
|
||||||
|
parser = get_parser("python")
|
||||||
|
tree = parser.parse(b"def hello(): pass")
|
||||||
|
print(tree.root_node)
|
||||||
|
|
||||||
|
# List all available languages
|
||||||
|
for lang in available_languages():
|
||||||
|
print(lang)
|
||||||
|
|
||||||
|
|
||||||
|
# Extract file intelligence (auto-downloads language if needed)
|
||||||
|
result = process(
|
||||||
|
"def hello(): pass",
|
||||||
|
ProcessConfig( language = "python")
|
||||||
|
)
|
||||||
|
print(f"Functions: {len(result['structure'])}")
|
||||||
|
|
||||||
|
# Pre-download languages for offline use
|
||||||
|
download(["python", "javascript"])
|
||||||
|
|
||||||
|
# With chunking
|
||||||
|
result = process(
|
||||||
|
source,
|
||||||
|
ProcessConfig(
|
||||||
|
language = "python",
|
||||||
|
chunk_max_size = 1000,
|
||||||
|
comments = True
|
||||||
|
)
|
||||||
|
)
|
||||||
|
print(f"Chunks: {len(result['chunks'])}")
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
"""
|
||||||
|
Libs Module
|
||||||
|
"""
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
"""Python bindings to the Tree-sitter parsing library."""
|
||||||
|
|
||||||
|
from typing import Protocol as _Protocol
|
||||||
|
|
||||||
|
from ._binding import (
|
||||||
|
Language,
|
||||||
|
LogType,
|
||||||
|
LookaheadIterator,
|
||||||
|
Node,
|
||||||
|
Parser,
|
||||||
|
Point,
|
||||||
|
Query,
|
||||||
|
QueryCursor,
|
||||||
|
QueryError,
|
||||||
|
Range,
|
||||||
|
Tree,
|
||||||
|
TreeCursor,
|
||||||
|
LANGUAGE_VERSION,
|
||||||
|
MIN_COMPATIBLE_LANGUAGE_VERSION,
|
||||||
|
)
|
||||||
|
|
||||||
|
LogType.__doc__ = "The type of a log message."
|
||||||
|
|
||||||
|
Point.__doc__ = "A position in a multi-line text document, in terms of rows and columns."
|
||||||
|
Point.row.__doc__ = "The zero-based row of the document."
|
||||||
|
Point.column.__doc__ = "The zero-based column of the document."
|
||||||
|
|
||||||
|
|
||||||
|
class QueryPredicate(_Protocol):
|
||||||
|
"""A custom query predicate that runs on a pattern."""
|
||||||
|
def __call__(self, predicate, args, pattern_index, captures):
|
||||||
|
"""
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
|
||||||
|
predicate : str
|
||||||
|
The name of the predicate.
|
||||||
|
args : list[tuple[str, typing.Literal['capture', 'string']]]
|
||||||
|
The arguments to the predicate.
|
||||||
|
pattern_index : int
|
||||||
|
The index of the pattern within the query.
|
||||||
|
captures : dict[str, list[Node]]
|
||||||
|
The captures contained in the pattern.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
``True`` if the predicate matches, ``False`` otherwise.
|
||||||
|
|
||||||
|
Tip
|
||||||
|
---
|
||||||
|
You don't need to create an actual class, just a function with this signature.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
__all__ = [
|
||||||
|
"Language",
|
||||||
|
"LogType",
|
||||||
|
"LookaheadIterator",
|
||||||
|
"Node",
|
||||||
|
"Parser",
|
||||||
|
"Point",
|
||||||
|
"Query",
|
||||||
|
"QueryCursor",
|
||||||
|
"QueryError",
|
||||||
|
"QueryPredicate",
|
||||||
|
"Range",
|
||||||
|
"Tree",
|
||||||
|
"TreeCursor",
|
||||||
|
"LANGUAGE_VERSION",
|
||||||
|
"MIN_COMPATIBLE_LANGUAGE_VERSION",
|
||||||
|
]
|
||||||
@@ -0,0 +1,416 @@
|
|||||||
|
from enum import IntEnum
|
||||||
|
from collections.abc import ByteString, Callable, Iterator, Sequence
|
||||||
|
from typing import Annotated, Any, Final, Literal, NamedTuple, Protocol, Self, final, overload
|
||||||
|
from typing_extensions import deprecated
|
||||||
|
|
||||||
|
class _SupportsFileno(Protocol):
|
||||||
|
def fileno(self) -> int: ...
|
||||||
|
|
||||||
|
class Point(NamedTuple):
|
||||||
|
row: int
|
||||||
|
column: int
|
||||||
|
|
||||||
|
class LogType(IntEnum):
|
||||||
|
PARSE: int
|
||||||
|
LEX: int
|
||||||
|
|
||||||
|
@final
|
||||||
|
class Language:
|
||||||
|
@overload
|
||||||
|
@deprecated("int argument support is deprecated")
|
||||||
|
def __init__(self, ptr: Annotated[int, "TSLanguage *"], /) -> None: ...
|
||||||
|
@overload
|
||||||
|
def __init__(self, ptr: Annotated[object, "TSLanguage *"], /) -> None: ...
|
||||||
|
@property
|
||||||
|
def name(self) -> str | None: ...
|
||||||
|
@property
|
||||||
|
def abi_version(self) -> int: ...
|
||||||
|
@property
|
||||||
|
def semantic_version(self) -> tuple[int, int, int] | None: ...
|
||||||
|
@deprecated("Use abi_version instead")
|
||||||
|
@property
|
||||||
|
def version(self) -> int: ...
|
||||||
|
@property
|
||||||
|
def node_kind_count(self) -> int: ...
|
||||||
|
@property
|
||||||
|
def parse_state_count(self) -> int: ...
|
||||||
|
@property
|
||||||
|
def field_count(self) -> int: ...
|
||||||
|
@property
|
||||||
|
def supertypes(self) -> tuple[int, ...]: ...
|
||||||
|
def subtypes(self, supertype: int, /) -> tuple[int, ...]: ...
|
||||||
|
def node_kind_for_id(self, id: int, /) -> str | None: ...
|
||||||
|
def id_for_node_kind(self, kind: str, named: bool, /) -> int | None: ...
|
||||||
|
def node_kind_is_named(self, id: int, /) -> bool: ...
|
||||||
|
def node_kind_is_visible(self, id: int, /) -> bool: ...
|
||||||
|
def node_kind_is_supertype(self, id: int, /) -> bool: ...
|
||||||
|
def field_name_for_id(self, field_id: int, /) -> str | None: ...
|
||||||
|
def field_id_for_name(self, name: str, /) -> int | None: ...
|
||||||
|
def next_state(self, state: int, id: int, /) -> int: ...
|
||||||
|
def lookahead_iterator(self, state: int, /) -> LookaheadIterator | None: ...
|
||||||
|
@deprecated("Use the Query() constructor instead")
|
||||||
|
def query(self, source: str, /) -> Query: ...
|
||||||
|
def copy(self) -> Language: ...
|
||||||
|
def __repr__(self) -> str: ...
|
||||||
|
def __eq__(self, other: Any, /) -> bool: ...
|
||||||
|
def __ne__(self, other: Any, /) -> bool: ...
|
||||||
|
def __hash__(self) -> int: ...
|
||||||
|
def __copy__(self) -> Language: ...
|
||||||
|
|
||||||
|
@final
|
||||||
|
class Node:
|
||||||
|
@property
|
||||||
|
def id(self) -> int: ...
|
||||||
|
@property
|
||||||
|
def kind_id(self) -> int: ...
|
||||||
|
@property
|
||||||
|
def grammar_id(self) -> int: ...
|
||||||
|
@property
|
||||||
|
def grammar_name(self) -> str: ...
|
||||||
|
@property
|
||||||
|
def type(self) -> str: ...
|
||||||
|
@property
|
||||||
|
def is_named(self) -> bool: ...
|
||||||
|
@property
|
||||||
|
def is_extra(self) -> bool: ...
|
||||||
|
@property
|
||||||
|
def has_changes(self) -> bool: ...
|
||||||
|
@property
|
||||||
|
def has_error(self) -> bool: ...
|
||||||
|
@property
|
||||||
|
def is_error(self) -> bool: ...
|
||||||
|
@property
|
||||||
|
def parse_state(self) -> int: ...
|
||||||
|
@property
|
||||||
|
def next_parse_state(self) -> int: ...
|
||||||
|
@property
|
||||||
|
def is_missing(self) -> bool: ...
|
||||||
|
@property
|
||||||
|
def start_byte(self) -> int: ...
|
||||||
|
@property
|
||||||
|
def end_byte(self) -> int: ...
|
||||||
|
@property
|
||||||
|
def byte_range(self) -> tuple[int, int]: ...
|
||||||
|
@property
|
||||||
|
def range(self) -> Range: ...
|
||||||
|
@property
|
||||||
|
def start_point(self) -> Point: ...
|
||||||
|
@property
|
||||||
|
def end_point(self) -> Point: ...
|
||||||
|
@property
|
||||||
|
def children(self) -> list[Node]: ...
|
||||||
|
@property
|
||||||
|
def child_count(self) -> int: ...
|
||||||
|
@property
|
||||||
|
def named_children(self) -> list[Node]: ...
|
||||||
|
@property
|
||||||
|
def named_child_count(self) -> int: ...
|
||||||
|
@property
|
||||||
|
def parent(self) -> Node | None: ...
|
||||||
|
@property
|
||||||
|
def next_sibling(self) -> Node | None: ...
|
||||||
|
@property
|
||||||
|
def prev_sibling(self) -> Node | None: ...
|
||||||
|
@property
|
||||||
|
def next_named_sibling(self) -> Node | None: ...
|
||||||
|
@property
|
||||||
|
def prev_named_sibling(self) -> Node | None: ...
|
||||||
|
@property
|
||||||
|
def descendant_count(self) -> int: ...
|
||||||
|
@property
|
||||||
|
def text(self) -> bytes | None: ...
|
||||||
|
def walk(self) -> TreeCursor: ...
|
||||||
|
def edit(
|
||||||
|
self,
|
||||||
|
start_byte: int,
|
||||||
|
old_end_byte: int,
|
||||||
|
new_end_byte: int,
|
||||||
|
start_point: Point | tuple[int, int],
|
||||||
|
old_end_point: Point | tuple[int, int],
|
||||||
|
new_end_point: Point | tuple[int, int],
|
||||||
|
) -> None: ...
|
||||||
|
def child(self, index: int, /) -> Node | None: ...
|
||||||
|
def named_child(self, index: int, /) -> Node | None: ...
|
||||||
|
def first_child_for_byte(self, byte: int, /) -> Node | None: ...
|
||||||
|
def first_named_child_for_byte(self, byte: int, /) -> Node | None: ...
|
||||||
|
def child_by_field_id(self, id: int, /) -> Node | None: ...
|
||||||
|
def child_by_field_name(self, name: str, /) -> Node | None: ...
|
||||||
|
def child_with_descendant(self, descendant: Node, /) -> Node | None: ...
|
||||||
|
def children_by_field_id(self, id: int, /) -> list[Node]: ...
|
||||||
|
def children_by_field_name(self, name: str, /) -> list[Node]: ...
|
||||||
|
def field_name_for_child(self, child_index: int, /) -> str | None: ...
|
||||||
|
def field_name_for_named_child(self, child_index: int, /) -> str | None: ...
|
||||||
|
def descendant_for_byte_range(
|
||||||
|
self,
|
||||||
|
start_byte: int,
|
||||||
|
end_byte: int,
|
||||||
|
/,
|
||||||
|
) -> Node | None: ...
|
||||||
|
def named_descendant_for_byte_range(
|
||||||
|
self,
|
||||||
|
start_byte: int,
|
||||||
|
end_byte: int,
|
||||||
|
/,
|
||||||
|
) -> Node | None: ...
|
||||||
|
def descendant_for_point_range(
|
||||||
|
self,
|
||||||
|
start_point: Point | tuple[int, int],
|
||||||
|
end_point: Point | tuple[int, int],
|
||||||
|
/,
|
||||||
|
) -> Node | None: ...
|
||||||
|
def named_descendant_for_point_range(
|
||||||
|
self,
|
||||||
|
start_point: Point | tuple[int, int],
|
||||||
|
end_point: Point | tuple[int, int],
|
||||||
|
/,
|
||||||
|
) -> Node | None: ...
|
||||||
|
def __repr__(self) -> str: ...
|
||||||
|
def __str__(self) -> str: ...
|
||||||
|
def __eq__(self, other: Any, /) -> bool: ...
|
||||||
|
def __ne__(self, other: Any, /) -> bool: ...
|
||||||
|
def __hash__(self) -> int: ...
|
||||||
|
|
||||||
|
@final
|
||||||
|
class Tree:
|
||||||
|
@property
|
||||||
|
def root_node(self) -> Node: ...
|
||||||
|
@property
|
||||||
|
def included_ranges(self) -> list[Range]: ...
|
||||||
|
@property
|
||||||
|
def language(self) -> Language: ...
|
||||||
|
def root_node_with_offset(
|
||||||
|
self,
|
||||||
|
offset_bytes: int,
|
||||||
|
offset_extent: Point | tuple[int, int],
|
||||||
|
/,
|
||||||
|
) -> Node | None: ...
|
||||||
|
def copy(self) -> Tree: ...
|
||||||
|
def edit(
|
||||||
|
self,
|
||||||
|
start_byte: int,
|
||||||
|
old_end_byte: int,
|
||||||
|
new_end_byte: int,
|
||||||
|
start_point: Point | tuple[int, int],
|
||||||
|
old_end_point: Point | tuple[int, int],
|
||||||
|
new_end_point: Point | tuple[int, int],
|
||||||
|
) -> None: ...
|
||||||
|
def walk(self) -> TreeCursor: ...
|
||||||
|
def changed_ranges(self, new_tree: Tree, /) -> list[Range]: ...
|
||||||
|
def print_dot_graph(self, file: _SupportsFileno, /) -> None: ...
|
||||||
|
def __copy__(self) -> Tree: ...
|
||||||
|
|
||||||
|
@final
|
||||||
|
class TreeCursor:
|
||||||
|
@property
|
||||||
|
def node(self) -> Node | None: ...
|
||||||
|
@property
|
||||||
|
def field_id(self) -> int | None: ...
|
||||||
|
@property
|
||||||
|
def field_name(self) -> str | None: ...
|
||||||
|
@property
|
||||||
|
def depth(self) -> int: ...
|
||||||
|
@property
|
||||||
|
def descendant_index(self) -> int: ...
|
||||||
|
def copy(self) -> TreeCursor: ...
|
||||||
|
def reset(self, node: Node, /) -> None: ...
|
||||||
|
def reset_to(self, cursor: TreeCursor, /) -> None: ...
|
||||||
|
def goto_first_child(self) -> bool: ...
|
||||||
|
def goto_last_child(self) -> bool: ...
|
||||||
|
def goto_parent(self) -> bool: ...
|
||||||
|
def goto_next_sibling(self) -> bool: ...
|
||||||
|
def goto_previous_sibling(self) -> bool: ...
|
||||||
|
def goto_descendant(self, index: int, /) -> None: ...
|
||||||
|
def goto_first_child_for_byte(self, byte: int, /) -> int | None: ...
|
||||||
|
def goto_first_child_for_point(self, point: Point | tuple[int, int], /) -> int | None: ...
|
||||||
|
def __copy__(self) -> TreeCursor: ...
|
||||||
|
|
||||||
|
@final
|
||||||
|
class Parser:
|
||||||
|
@overload
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
language: Language | None = None,
|
||||||
|
*,
|
||||||
|
included_ranges: Sequence[Range] | None = None,
|
||||||
|
logger: Callable[[LogType, str], None] | None = None,
|
||||||
|
) -> None: ...
|
||||||
|
@deprecated("timeout_micros is deprecated")
|
||||||
|
@overload
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
language: Language | None = None,
|
||||||
|
*,
|
||||||
|
included_ranges: Sequence[Range] | None = None,
|
||||||
|
timeout_micros: int | None = None,
|
||||||
|
logger: Callable[[LogType, str], None] | None = None,
|
||||||
|
) -> None: ...
|
||||||
|
@property
|
||||||
|
def language(self) -> Language | None: ...
|
||||||
|
@language.setter
|
||||||
|
def language(self, language: Language) -> None: ...
|
||||||
|
@language.deleter
|
||||||
|
def language(self) -> None: ...
|
||||||
|
@property
|
||||||
|
def included_ranges(self) -> list[Range]: ...
|
||||||
|
@included_ranges.setter
|
||||||
|
def included_ranges(self, ranges: Sequence[Range]) -> None: ...
|
||||||
|
@included_ranges.deleter
|
||||||
|
def included_ranges(self) -> None: ...
|
||||||
|
@deprecated("Use the progress_callback in parse()")
|
||||||
|
@property
|
||||||
|
def timeout_micros(self) -> int: ...
|
||||||
|
@deprecated("Use the progress_callback in parse()")
|
||||||
|
@timeout_micros.setter
|
||||||
|
def timeout_micros(self, timeout: int) -> None: ...
|
||||||
|
@deprecated("Use the progress_callback in parse()")
|
||||||
|
@timeout_micros.deleter
|
||||||
|
def timeout_micros(self) -> None: ...
|
||||||
|
@property
|
||||||
|
def logger(self) -> Callable[[LogType, str], None] | None: ...
|
||||||
|
@logger.setter
|
||||||
|
def logger(self, logger: Callable[[LogType, str], None]) -> None: ...
|
||||||
|
@logger.deleter
|
||||||
|
def logger(self) -> None: ...
|
||||||
|
@overload
|
||||||
|
def parse(
|
||||||
|
self,
|
||||||
|
source: ByteString,
|
||||||
|
/,
|
||||||
|
old_tree: Tree | None = None,
|
||||||
|
encoding: Literal["utf8", "utf16", "utf16le", "utf16be"] = "utf8",
|
||||||
|
) -> Tree: ...
|
||||||
|
@overload
|
||||||
|
def parse(
|
||||||
|
self,
|
||||||
|
read_callback: Callable[[int, Point], ByteString | None],
|
||||||
|
/,
|
||||||
|
old_tree: Tree | None = None,
|
||||||
|
encoding: Literal["utf8", "utf16", "utf16le", "utf16be"] = "utf8",
|
||||||
|
progress_callback: Callable[[int, bool], bool] | None = None,
|
||||||
|
) -> Tree: ...
|
||||||
|
def reset(self) -> None: ...
|
||||||
|
def print_dot_graphs(self, file: _SupportsFileno | None, /) -> None: ...
|
||||||
|
|
||||||
|
class QueryError(ValueError): ...
|
||||||
|
|
||||||
|
class QueryPredicate(Protocol):
|
||||||
|
def __call__(
|
||||||
|
self,
|
||||||
|
predicate: str,
|
||||||
|
args: list[tuple[str, Literal["capture", "string"]]],
|
||||||
|
pattern_index: int,
|
||||||
|
captures: dict[str, list[Node]],
|
||||||
|
) -> bool: ...
|
||||||
|
|
||||||
|
@final
|
||||||
|
class Query:
|
||||||
|
def __new__(cls, language: Language, source: str, /) -> Self: ...
|
||||||
|
def pattern_count(self) -> int: ...
|
||||||
|
def capture_count(self) -> int: ...
|
||||||
|
def string_count(self) -> int: ...
|
||||||
|
def start_byte_for_pattern(self, index: int, /) -> int: ...
|
||||||
|
def end_byte_for_pattern(self, index: int, /) -> int: ...
|
||||||
|
def is_pattern_rooted(self, index: int, /) -> bool: ...
|
||||||
|
def is_pattern_non_local(self, index: int, /) -> bool: ...
|
||||||
|
def is_pattern_guaranteed_at_step(self, index: int, /) -> bool: ...
|
||||||
|
def capture_name(self, index: int, /) -> str: ...
|
||||||
|
def capture_quantifier(
|
||||||
|
self,
|
||||||
|
pattern_index: int,
|
||||||
|
capture_index: int,
|
||||||
|
/
|
||||||
|
) -> Literal["", "?", "*", "+"]: ...
|
||||||
|
def string_value(self, index: int, /) -> str: ...
|
||||||
|
def disable_capture(self, name: str, /) -> None: ...
|
||||||
|
def disable_pattern(self, index: int, /) -> None: ...
|
||||||
|
def pattern_settings(self, index: int, /) -> dict[str, str | None]: ...
|
||||||
|
def pattern_assertions(self, index: int, /) -> dict[str, tuple[str | None, bool]]: ...
|
||||||
|
|
||||||
|
@final
|
||||||
|
class QueryCursor:
|
||||||
|
@overload
|
||||||
|
def __init__(self, query: Query, *, match_limit: int = 0xFFFFFFFF) -> None: ...
|
||||||
|
@deprecated("timeout_micros is deprecated")
|
||||||
|
@overload
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
query: Query,
|
||||||
|
*,
|
||||||
|
match_limit: int = 0xFFFFFFFF,
|
||||||
|
timeout_micros: int = 0
|
||||||
|
) -> None: ...
|
||||||
|
@property
|
||||||
|
def match_limit(self) -> int: ...
|
||||||
|
@match_limit.setter
|
||||||
|
def match_limit(self, limit: int) -> None: ...
|
||||||
|
@match_limit.deleter
|
||||||
|
def match_limit(self) -> None: ...
|
||||||
|
@deprecated("Use the progress_callback in matches() or captures()")
|
||||||
|
@property
|
||||||
|
def timeout_micros(self) -> int: ...
|
||||||
|
@deprecated("Use the progress_callback in matches() or captures()")
|
||||||
|
@timeout_micros.setter
|
||||||
|
def timeout_micros(self, timeout: int) -> None: ...
|
||||||
|
@property
|
||||||
|
def did_exceed_match_limit(self) -> bool: ...
|
||||||
|
def set_max_start_depth(self, depth: int, /) -> None: ...
|
||||||
|
def set_byte_range(self, start: int, end: int, /) -> None: ...
|
||||||
|
def set_point_range(
|
||||||
|
self,
|
||||||
|
start: Point | tuple[int, int],
|
||||||
|
end: Point | tuple[int, int],
|
||||||
|
/,
|
||||||
|
) -> None: ...
|
||||||
|
def captures(
|
||||||
|
self,
|
||||||
|
node: Node,
|
||||||
|
predicate: QueryPredicate | None = None,
|
||||||
|
progress_callback: Callable[[int], bool] | None = None,
|
||||||
|
/,
|
||||||
|
) -> dict[str, list[Node]]: ...
|
||||||
|
def matches(
|
||||||
|
self,
|
||||||
|
node: Node,
|
||||||
|
predicate: QueryPredicate | None = None,
|
||||||
|
progress_callback: Callable[[int], bool] | None = None,
|
||||||
|
/,
|
||||||
|
) -> list[tuple[int, dict[str, list[Node]]]]: ...
|
||||||
|
|
||||||
|
@final
|
||||||
|
class LookaheadIterator(Iterator[tuple[int, str]]):
|
||||||
|
@property
|
||||||
|
def language(self) -> Language: ...
|
||||||
|
@property
|
||||||
|
def current_symbol(self) -> int: ...
|
||||||
|
@property
|
||||||
|
def current_symbol_name(self) -> str: ...
|
||||||
|
def reset(self, state: int, /, language: Language | None = None) -> bool: ...
|
||||||
|
def names(self) -> list[str]: ...
|
||||||
|
def symbols(self) -> list[int]: ...
|
||||||
|
def __next__(self) -> tuple[int, str]: ...
|
||||||
|
|
||||||
|
@final
|
||||||
|
class Range:
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
start_point: Point | tuple[int, int],
|
||||||
|
end_point: Point | tuple[int, int],
|
||||||
|
start_byte: int,
|
||||||
|
end_byte: int,
|
||||||
|
) -> None: ...
|
||||||
|
@property
|
||||||
|
def start_point(self) -> Point: ...
|
||||||
|
@property
|
||||||
|
def end_point(self) -> Point: ...
|
||||||
|
@property
|
||||||
|
def start_byte(self) -> int: ...
|
||||||
|
@property
|
||||||
|
def end_byte(self) -> int: ...
|
||||||
|
def __eq__(self, other: Any, /) -> bool: ...
|
||||||
|
def __ne__(self, other: Any, /) -> bool: ...
|
||||||
|
def __repr__(self) -> str: ...
|
||||||
|
def __hash__(self) -> int: ...
|
||||||
|
|
||||||
|
LANGUAGE_VERSION: Final[int]
|
||||||
|
|
||||||
|
MIN_COMPATIBLE_LANGUAGE_VERSION: Final[int]
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
from typing import TypeAlias
|
||||||
|
|
||||||
|
from tree_sitter_language_pack._native import (
|
||||||
|
DownloadError,
|
||||||
|
LanguageNotFoundError,
|
||||||
|
ParseError,
|
||||||
|
ProcessConfig,
|
||||||
|
QueryError,
|
||||||
|
TreeHandle,
|
||||||
|
available_languages,
|
||||||
|
cache_dir,
|
||||||
|
clean_cache,
|
||||||
|
configure,
|
||||||
|
download,
|
||||||
|
download_all,
|
||||||
|
downloaded_languages,
|
||||||
|
get_binding,
|
||||||
|
get_language,
|
||||||
|
get_parser,
|
||||||
|
has_language,
|
||||||
|
init,
|
||||||
|
language_count,
|
||||||
|
manifest_languages,
|
||||||
|
parse_string,
|
||||||
|
process,
|
||||||
|
)
|
||||||
|
|
||||||
|
SupportedLanguage: TypeAlias = str
|
||||||
|
|
||||||
|
__all__ = [
|
||||||
|
"DownloadError",
|
||||||
|
"LanguageNotFoundError",
|
||||||
|
"ParseError",
|
||||||
|
"ProcessConfig",
|
||||||
|
"QueryError",
|
||||||
|
"SupportedLanguage",
|
||||||
|
"TreeHandle",
|
||||||
|
"available_languages",
|
||||||
|
"cache_dir",
|
||||||
|
"clean_cache",
|
||||||
|
"configure",
|
||||||
|
"download",
|
||||||
|
"download_all",
|
||||||
|
"downloaded_languages",
|
||||||
|
"get_binding",
|
||||||
|
"get_language",
|
||||||
|
"get_parser",
|
||||||
|
"has_language",
|
||||||
|
"init",
|
||||||
|
"language_count",
|
||||||
|
"manifest_languages",
|
||||||
|
"parse_string",
|
||||||
|
"process",
|
||||||
|
]
|
||||||
@@ -0,0 +1,276 @@
|
|||||||
|
from typing import Literal, TypeAlias
|
||||||
|
|
||||||
|
from tree_sitter import Language, Parser
|
||||||
|
|
||||||
|
class LanguageNotFoundError(ValueError): ...
|
||||||
|
class DownloadError(RuntimeError): ...
|
||||||
|
|
||||||
|
SupportedLanguage: TypeAlias = Literal[
|
||||||
|
"actionscript",
|
||||||
|
"ada",
|
||||||
|
"agda",
|
||||||
|
"apex",
|
||||||
|
"arduino",
|
||||||
|
"asm",
|
||||||
|
"astro",
|
||||||
|
"bash",
|
||||||
|
"batch",
|
||||||
|
"bazel",
|
||||||
|
"beancount",
|
||||||
|
"bibtex",
|
||||||
|
"bicep",
|
||||||
|
"bitbake",
|
||||||
|
"bsl",
|
||||||
|
"c",
|
||||||
|
"cairo",
|
||||||
|
"capnp",
|
||||||
|
"chatito",
|
||||||
|
"clarity",
|
||||||
|
"clojure",
|
||||||
|
"cmake",
|
||||||
|
"cobol",
|
||||||
|
"comment",
|
||||||
|
"commonlisp",
|
||||||
|
"cpon",
|
||||||
|
"cpp",
|
||||||
|
"css",
|
||||||
|
"csv",
|
||||||
|
"cuda",
|
||||||
|
"d",
|
||||||
|
"dart",
|
||||||
|
"diff",
|
||||||
|
"dockerfile",
|
||||||
|
"doxygen",
|
||||||
|
"dtd",
|
||||||
|
"elisp",
|
||||||
|
"elixir",
|
||||||
|
"elm",
|
||||||
|
"erlang",
|
||||||
|
"fennel",
|
||||||
|
"firrtl",
|
||||||
|
"fish",
|
||||||
|
"fortran",
|
||||||
|
"fsharp",
|
||||||
|
"fsharp_signature",
|
||||||
|
"func",
|
||||||
|
"gdscript",
|
||||||
|
"gitattributes",
|
||||||
|
"gitcommit",
|
||||||
|
"gitignore",
|
||||||
|
"gleam",
|
||||||
|
"glsl",
|
||||||
|
"gn",
|
||||||
|
"go",
|
||||||
|
"gomod",
|
||||||
|
"gosum",
|
||||||
|
"gradle",
|
||||||
|
"graphql",
|
||||||
|
"groovy",
|
||||||
|
"gstlaunch",
|
||||||
|
"hack",
|
||||||
|
"hare",
|
||||||
|
"haskell",
|
||||||
|
"haxe",
|
||||||
|
"hcl",
|
||||||
|
"heex",
|
||||||
|
"hlsl",
|
||||||
|
"html",
|
||||||
|
"hyprlang",
|
||||||
|
"ignorefile",
|
||||||
|
"ini",
|
||||||
|
"ispc",
|
||||||
|
"janet",
|
||||||
|
"java",
|
||||||
|
"javascript",
|
||||||
|
"jsdoc",
|
||||||
|
"json",
|
||||||
|
"jsonnet",
|
||||||
|
"julia",
|
||||||
|
"kconfig",
|
||||||
|
"kdl",
|
||||||
|
"kotlin",
|
||||||
|
"latex",
|
||||||
|
"linkerscript",
|
||||||
|
"lisp",
|
||||||
|
"llvm",
|
||||||
|
"lua",
|
||||||
|
"luadoc",
|
||||||
|
"luap",
|
||||||
|
"luau",
|
||||||
|
"magik",
|
||||||
|
"make",
|
||||||
|
"makefile",
|
||||||
|
"markdown",
|
||||||
|
"markdown_inline",
|
||||||
|
"matlab",
|
||||||
|
"mermaid",
|
||||||
|
"meson",
|
||||||
|
"netlinx",
|
||||||
|
"nim",
|
||||||
|
"ninja",
|
||||||
|
"nix",
|
||||||
|
"nqc",
|
||||||
|
"objc",
|
||||||
|
"ocaml",
|
||||||
|
"ocaml_interface",
|
||||||
|
"odin",
|
||||||
|
"org",
|
||||||
|
"pascal",
|
||||||
|
"pem",
|
||||||
|
"perl",
|
||||||
|
"pgn",
|
||||||
|
"php",
|
||||||
|
"pkl",
|
||||||
|
"po",
|
||||||
|
"pony",
|
||||||
|
"powershell",
|
||||||
|
"printf",
|
||||||
|
"prisma",
|
||||||
|
"properties",
|
||||||
|
"proto",
|
||||||
|
"psv",
|
||||||
|
"puppet",
|
||||||
|
"purescript",
|
||||||
|
"pymanifest",
|
||||||
|
"python",
|
||||||
|
"qmldir",
|
||||||
|
"qmljs",
|
||||||
|
"query",
|
||||||
|
"r",
|
||||||
|
"racket",
|
||||||
|
"re2c",
|
||||||
|
"readline",
|
||||||
|
"rego",
|
||||||
|
"requirements",
|
||||||
|
"ron",
|
||||||
|
"rst",
|
||||||
|
"ruby",
|
||||||
|
"rust",
|
||||||
|
"scala",
|
||||||
|
"scheme",
|
||||||
|
"scss",
|
||||||
|
"shell",
|
||||||
|
"smali",
|
||||||
|
"smithy",
|
||||||
|
"solidity",
|
||||||
|
"sparql",
|
||||||
|
"sql",
|
||||||
|
"squirrel",
|
||||||
|
"starlark",
|
||||||
|
"svelte",
|
||||||
|
"swift",
|
||||||
|
"tablegen",
|
||||||
|
"tcl",
|
||||||
|
"terraform",
|
||||||
|
"test",
|
||||||
|
"thrift",
|
||||||
|
"toml",
|
||||||
|
"tsv",
|
||||||
|
"tsx",
|
||||||
|
"twig",
|
||||||
|
"typescript",
|
||||||
|
"typst",
|
||||||
|
"udev",
|
||||||
|
"ungrammar",
|
||||||
|
"uxntal",
|
||||||
|
"v",
|
||||||
|
"verilog",
|
||||||
|
"vhdl",
|
||||||
|
"vim",
|
||||||
|
"vue",
|
||||||
|
"wast",
|
||||||
|
"wat",
|
||||||
|
"wgsl",
|
||||||
|
"xcompose",
|
||||||
|
"xml",
|
||||||
|
"yuck",
|
||||||
|
"zig",
|
||||||
|
]
|
||||||
|
|
||||||
|
class ParseError(RuntimeError): ...
|
||||||
|
class QueryError(ValueError): ...
|
||||||
|
|
||||||
|
class ProcessConfig:
|
||||||
|
language: str
|
||||||
|
structure: bool
|
||||||
|
imports: bool
|
||||||
|
exports: bool
|
||||||
|
comments: bool
|
||||||
|
docstrings: bool
|
||||||
|
symbols: bool
|
||||||
|
diagnostics: bool
|
||||||
|
chunk_max_size: int | None
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
language: str,
|
||||||
|
*,
|
||||||
|
structure: bool = True,
|
||||||
|
imports: bool = True,
|
||||||
|
exports: bool = True,
|
||||||
|
comments: bool = True,
|
||||||
|
docstrings: bool = True,
|
||||||
|
symbols: bool = True,
|
||||||
|
diagnostics: bool = True,
|
||||||
|
chunk_max_size: int | None = None,
|
||||||
|
) -> None: ...
|
||||||
|
@staticmethod
|
||||||
|
def all(language: str) -> ProcessConfig: ...
|
||||||
|
@staticmethod
|
||||||
|
def minimal(language: str) -> ProcessConfig: ...
|
||||||
|
|
||||||
|
class TreeHandle:
|
||||||
|
def root_node_type(self) -> str: ...
|
||||||
|
def root_child_count(self) -> int: ...
|
||||||
|
def contains_node_type(self, node_type: str) -> bool: ...
|
||||||
|
def has_error_nodes(self) -> bool: ...
|
||||||
|
def to_sexp(self) -> str: ...
|
||||||
|
def error_count(self) -> int: ...
|
||||||
|
def root_node_info(self) -> dict[str, object]: ...
|
||||||
|
def find_nodes_by_type(self, node_type: str) -> list[dict[str, object]]: ...
|
||||||
|
def named_children_info(self) -> list[dict[str, object]]: ...
|
||||||
|
def extract_text(self, start_byte: int, end_byte: int) -> str: ...
|
||||||
|
def run_query(self, language: str, query_source: str) -> list[dict[str, object]]: ...
|
||||||
|
|
||||||
|
__all__ = [
|
||||||
|
"DownloadError",
|
||||||
|
"LanguageNotFoundError",
|
||||||
|
"ParseError",
|
||||||
|
"ProcessConfig",
|
||||||
|
"QueryError",
|
||||||
|
"SupportedLanguage",
|
||||||
|
"TreeHandle",
|
||||||
|
"available_languages",
|
||||||
|
"cache_dir",
|
||||||
|
"clean_cache",
|
||||||
|
"configure",
|
||||||
|
"download",
|
||||||
|
"download_all",
|
||||||
|
"downloaded_languages",
|
||||||
|
"get_binding",
|
||||||
|
"get_language",
|
||||||
|
"get_parser",
|
||||||
|
"has_language",
|
||||||
|
"init",
|
||||||
|
"language_count",
|
||||||
|
"manifest_languages",
|
||||||
|
"parse_string",
|
||||||
|
"process",
|
||||||
|
]
|
||||||
|
|
||||||
|
def get_binding(name: SupportedLanguage) -> object: ...
|
||||||
|
def get_language(name: SupportedLanguage) -> Language: ...
|
||||||
|
def get_parser(name: SupportedLanguage) -> Parser: ...
|
||||||
|
def available_languages() -> list[str]: ...
|
||||||
|
def has_language(name: str) -> bool: ...
|
||||||
|
def language_count() -> int: ...
|
||||||
|
def parse_string(language: str, source: str) -> TreeHandle: ...
|
||||||
|
def process(source: str, config: ProcessConfig) -> dict[str, object]: ...
|
||||||
|
def init(config: dict[str, object]) -> None: ...
|
||||||
|
def configure(*, cache_dir: str | None = None) -> None: ...
|
||||||
|
def download(names: list[str]) -> int: ...
|
||||||
|
def download_all() -> int: ...
|
||||||
|
def manifest_languages() -> list[str]: ...
|
||||||
|
def downloaded_languages() -> list[str]: ...
|
||||||
|
def clean_cache() -> None: ...
|
||||||
|
def cache_dir() -> str: ...
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user