Branch: refs/heads/master
Author: Jiří Techet <techet(a)gmail.com>
Committer: GitHub <noreply(a)github.com>
Date: Sun, 26 Jan 2025 21:10:53 UTC
Commit: 7ec34de3badeecafe459276bfd01465a849e058c
https://github.com/geany/geany-plugins/commit/7ec34de3badeecafe459276bfd014…
Log Message:
-----------
Merge pull request #1331 from techee/lsp
Add LSP plugin
Modified Paths:
--------------
MAINTAINERS
Makefile.am
README
build/geany-plugins.nsi
build/lsp.m4
configure.ac
lsp/AUTHORS
lsp/COPYING
lsp/ChangeLog
lsp/Makefile.am
lsp/NEWS
lsp/README
lsp/data/Makefile.am
lsp/data/lsp.conf
lsp/deps/Makefile.am
lsp/deps/json-glib/json-array.c
lsp/deps/json-glib/json-builder.c
lsp/deps/json-glib/json-builder.h
lsp/deps/json-glib/json-debug.c
lsp/deps/json-glib/json-debug.h
lsp/deps/json-glib/json-enum-types.c
lsp/deps/json-glib/json-enum-types.h
lsp/deps/json-glib/json-gboxed.c
lsp/deps/json-glib/json-generator.c
lsp/deps/json-glib/json-generator.h
lsp/deps/json-glib/json-glib.h
lsp/deps/json-glib/json-gobject-private.h
lsp/deps/json-glib/json-gobject.c
lsp/deps/json-glib/json-gobject.h
lsp/deps/json-glib/json-gvariant.c
lsp/deps/json-glib/json-gvariant.h
lsp/deps/json-glib/json-node.c
lsp/deps/json-glib/json-object.c
lsp/deps/json-glib/json-parser.c
lsp/deps/json-glib/json-parser.h
lsp/deps/json-glib/json-path.c
lsp/deps/json-glib/json-path.h
lsp/deps/json-glib/json-reader.c
lsp/deps/json-glib/json-reader.h
lsp/deps/json-glib/json-scanner.c
lsp/deps/json-glib/json-scanner.h
lsp/deps/json-glib/json-serializable.c
lsp/deps/json-glib/json-types-private.h
lsp/deps/json-glib/json-types.h
lsp/deps/json-glib/json-utils.c
lsp/deps/json-glib/json-utils.h
lsp/deps/json-glib/json-value.c
lsp/deps/json-glib/json-version-macros.h
lsp/deps/json-glib/json-version.h
lsp/deps/jsonrpc-glib/jsonrpc-client.c
lsp/deps/jsonrpc-glib/jsonrpc-client.h
lsp/deps/jsonrpc-glib/jsonrpc-glib.h
lsp/deps/jsonrpc-glib/jsonrpc-input-stream-private.h
lsp/deps/jsonrpc-glib/jsonrpc-input-stream.c
lsp/deps/jsonrpc-glib/jsonrpc-input-stream.h
lsp/deps/jsonrpc-glib/jsonrpc-marshalers.c
lsp/deps/jsonrpc-glib/jsonrpc-marshalers.h
lsp/deps/jsonrpc-glib/jsonrpc-message.c
lsp/deps/jsonrpc-glib/jsonrpc-message.h
lsp/deps/jsonrpc-glib/jsonrpc-output-stream.c
lsp/deps/jsonrpc-glib/jsonrpc-output-stream.h
lsp/deps/jsonrpc-glib/jsonrpc-server.c
lsp/deps/jsonrpc-glib/jsonrpc-server.h
lsp/deps/jsonrpc-glib/jsonrpc-version-macros.h
lsp/deps/jsonrpc-glib/jsonrpc-version.h
lsp/src/Makefile.am
lsp/src/lsp-autocomplete.c
lsp/src/lsp-autocomplete.h
lsp/src/lsp-code-lens.c
lsp/src/lsp-code-lens.h
lsp/src/lsp-command.c
lsp/src/lsp-command.h
lsp/src/lsp-diagnostics.c
lsp/src/lsp-diagnostics.h
lsp/src/lsp-extension.c
lsp/src/lsp-extension.h
lsp/src/lsp-format.c
lsp/src/lsp-format.h
lsp/src/lsp-goto-anywhere.c
lsp/src/lsp-goto-anywhere.h
lsp/src/lsp-goto-panel.c
lsp/src/lsp-goto-panel.h
lsp/src/lsp-goto.c
lsp/src/lsp-goto.h
lsp/src/lsp-highlight.c
lsp/src/lsp-highlight.h
lsp/src/lsp-hover.c
lsp/src/lsp-hover.h
lsp/src/lsp-log.c
lsp/src/lsp-log.h
lsp/src/lsp-main.c
lsp/src/lsp-progress.c
lsp/src/lsp-progress.h
lsp/src/lsp-rename.c
lsp/src/lsp-rename.h
lsp/src/lsp-rpc.c
lsp/src/lsp-rpc.h
lsp/src/lsp-selection-range.c
lsp/src/lsp-selection-range.h
lsp/src/lsp-semtokens.c
lsp/src/lsp-semtokens.h
lsp/src/lsp-server.c
lsp/src/lsp-server.h
lsp/src/lsp-signature.c
lsp/src/lsp-signature.h
lsp/src/lsp-symbol-kinds.c
lsp/src/lsp-symbol-kinds.h
lsp/src/lsp-symbol-tree.c
lsp/src/lsp-symbol-tree.h
lsp/src/lsp-symbol.c
lsp/src/lsp-symbol.h
lsp/src/lsp-symbols.c
lsp/src/lsp-symbols.h
lsp/src/lsp-sync.c
lsp/src/lsp-sync.h
lsp/src/lsp-utils.c
lsp/src/lsp-utils.h
lsp/src/lsp-workspace-folders.c
lsp/src/lsp-workspace-folders.h
lsp/src/spawn/lspunixinputstream.c
lsp/src/spawn/lspunixinputstream.h
lsp/src/spawn/lspunixoutputstream.c
lsp/src/spawn/lspunixoutputstream.h
lsp/src/spawn/spawn.c
lsp/src/spawn/spawn.h
po/POTFILES.in
po/POTFILES.skip
Modified: MAINTAINERS
7 lines changed, 7 insertions(+), 0 deletions(-)
===================================================================
@@ -194,6 +194,13 @@ M: Frank Lanitz <frank(a)frank.uvena.de>
W: http://plugins.geany.org/lipsum.html
S: Maintained
+lsp
+P: Jiří Techet <techet(a)gmail.com>
+g: @techee
+M: Jiří Techet <techet(a)gmail.com>
+W: http://plugins.geany.org/lsp.html
+S: Maintained
+
markdown
P: Matthew Brush <matt(a)geany.org>
g: @codebrainz
Modified: Makefile.am
4 lines changed, 4 insertions(+), 0 deletions(-)
===================================================================
@@ -109,6 +109,10 @@ if ENABLE_LIPSUM
SUBDIRS += lipsum
endif
+if ENABLE_LSP
+SUBDIRS += lsp
+endif
+
if ENABLE_MARKDOWN
SUBDIRS += markdown
endif
Modified: README
1 lines changed, 1 insertions(+), 0 deletions(-)
===================================================================
@@ -71,6 +71,7 @@ Available plugins are:
* ``latex`` -- the LaTeX plugin
* ``lineoperations`` -- simple line functions that can be applied to an open file
* ``lipsum`` -- the Lipsum plugin
+* ``lsp`` -- the LSP plugin
* ``markdown`` -- the Markdown plugin
* ``overview``-- the overview plugin
* ``pairtaghighlighter`` -- the PairTagHighlighter plugin
Modified: build/geany-plugins.nsi
1 lines changed, 1 insertions(+), 0 deletions(-)
===================================================================
@@ -198,6 +198,7 @@ Section Uninstall
Delete "$INSTDIR\lib\geany\keyrecord.dll"
Delete "$INSTDIR\lib\geany\lipsum.dll"
Delete "$INSTDIR\lib\geany\lineoperations.dll"
+ Delete "$INSTDIR\lib\geany\lsp.dll"
Delete "$INSTDIR\lib\geany\overview.dll"
Delete "$INSTDIR\lib\geany\pairtaghighlighter.dll"
Delete "$INSTDIR\lib\geany\pohelper.dll"
Modified: build/lsp.m4
39 lines changed, 39 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,39 @@
+AC_DEFUN([GP_CHECK_LSP],
+[
+ GP_ARG_DISABLE([LSP], [auto])
+
+ JSON_GLIB_PACKAGE_NAME=json-glib-1.0
+ JSON_GLIB_VERSION=1.10
+ JSONRPC_GLIB_PACKAGE_NAME=jsonrpc-glib-1.0
+ JSONRPC_GLIB_VERSION=3.44
+
+ AC_ARG_ENABLE(system-jsonrpc,
+ AC_HELP_STRING([--enable-system-jsonrpc],
+ [Force using system json-glib and jsonrpc-glib libraries for the LSP plugin. [[default=no]]]),,
+ enable_system_jsonrpc=no)
+
+ PKG_CHECK_MODULES([SYSTEM_JSONRPC],
+ [${JSON_GLIB_PACKAGE_NAME} >= ${JSON_GLIB_VERSION}
+ ${JSONRPC_GLIB_PACKAGE_NAME} >= ${JSONRPC_GLIB_VERSION}],
+ have_system_jsonrpc=yes
+ echo "Required system versions of json-glib and jsonrpc-glib found - using them.",
+ have_system_jsonrpc=no
+ echo "Required system versions of json-glib and jsonrpc-glib not found - using builtin versions.")
+
+ AS_IF([test x"$enable_system_jsonrpc" = "xyes" || test x"$have_system_jsonrpc" = "xyes"],
+ [GP_CHECK_PLUGIN_DEPS([LSP], [LSP],
+ [${JSON_GLIB_PACKAGE_NAME} >= ${JSON_GLIB_VERSION}
+ ${JSONRPC_GLIB_PACKAGE_NAME} >= ${JSONRPC_GLIB_VERSION}])],
+ [])
+
+ AM_CONDITIONAL(ENABLE_BUILTIN_JSONRPC, [ test x"$have_system_jsonrpc" = "xno" ])
+
+ GP_COMMIT_PLUGIN_STATUS([LSP])
+
+ AC_CONFIG_FILES([
+ lsp/Makefile
+ lsp/deps/Makefile
+ lsp/src/Makefile
+ lsp/data/Makefile
+ ])
+])
Modified: configure.ac
1 lines changed, 1 insertions(+), 0 deletions(-)
===================================================================
@@ -55,6 +55,7 @@ GP_CHECK_GITCHANGEBAR
GP_CHECK_KEYRECORD
GP_CHECK_LINEOPERATIONS
GP_CHECK_LIPSUM
+GP_CHECK_LSP
GP_CHECK_MARKDOWN
GP_CHECK_OVERVIEW
GP_CHECK_PAIRTAGHIGHLIGHTER
Modified: lsp/AUTHORS
1 lines changed, 1 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1 @@
+Jiří Techet <techet(a)gmail.com>
Modified: lsp/COPYING
340 lines changed, 340 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 51 Franklin St, 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 Library 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 St, 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 Library General
+Public License instead of this License.
Modified: lsp/ChangeLog
0 lines changed, 0 insertions(+), 0 deletions(-)
===================================================================
No diff available, check online
Modified: lsp/Makefile.am
4 lines changed, 4 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,4 @@
+include $(top_srcdir)/build/vars.auxfiles.mk
+
+SUBDIRS = deps src data
+plugin = lsp
Modified: lsp/NEWS
0 lines changed, 0 insertions(+), 0 deletions(-)
===================================================================
No diff available, check online
Modified: lsp/README
288 lines changed, 288 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,288 @@
+===
+LSP
+===
+
+.. contents::
+
+About
+=====
+
+LSP Client is a language server protocol client plugin that allows to run multiple
+language servers for various programming languages, making their functionality
+accessible to Geany.
+
+Configuration
+=============
+
+The plugin does not come bundled with any language server; these must
+be installed independently of the plugin. For installation and configuration
+instructions, please refer to the documentation of the specific servers you plan
+to use, as some may have specific requirements. Note that many language servers,
+such as ``clangd``, ``pylsp``, and ``gopls``, are often packaged by Linux
+distributions, making them easy to install and use.
+
+You can configure servers and other settings using the User configuration file,
+accessible from::
+
+ Tools->LSP Client->User configuration
+
+This file provides extensive information about all the settings options, so be
+sure to refer to it for more details. The default configuration file comes with
+pre-configured values for several language servers; other servers have to be
+added manually.
+
+By default, the LSP plugin is disabled unless explicitly enabled for a
+project under
+
+::
+
+ Project->Properties->LSP Client
+
+This behavior can be controlled by the first three configuration options in
+the ``[all]`` section of the configuration file.
+
+Language servers are started lazily, meaning they only launch when you switch
+a tab to a file with a filetype that has a corresponding LSP server configured.
+After the initial handshake between the client and server, you can check the
+result under
+
+::
+
+ Tools->LSP Client->Server Initialize Responses
+
+This file also provides information about the capabilities offered by the server;
+for more details, refer to:
+
+https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/
+
+In addition to the User configuration file, you can also create a per-project
+configuration file (which can also be shared by multiple projects). This file
+can be configured under the
+
+::
+
+ Project->Properties->LSP Client
+
+tab.
+
+Furthermore, the plugin offers a range of customizable keybindings, which can be
+configured from::
+
+ Edit->Preferences->Keybindings->LSP Client
+
+Usage
+=====
+
+This section provides an overview of the individual LSP features supported by
+the plugin, along with guidance on how to use them. You can enable or disable
+each feature in the configuration file, where you can also customize certain
+aspects of their behavior.
+
+Please note that not all language servers support every feature. For more
+information on the specific features supported by a language server, consult
+the server's documentation.
+
+Autocompletion
+--------------
+
+Autocompletion works similarly to Geany's autocompletion feature. You can
+configure keybindings triggering the autocompletion popup.
+
+Function signagure
+------------------
+
+When you type an open brace after a function name, the plugin displays the
+function's signature in a popup window similarly to Geany's behavior.
+
+Diagnostic messages
+-------------------
+
+LSP diagnostic messages typically include error messages or warnings from
+compilers, as well as messages from linters. These messages are highlighted in
+the code; the exact style of highlighting can be configured to suit your
+preferences. When you hover over the highlighted part with your mouse cursor,
+a popup window appears, providing additional details about the issue. It is
+also possible to display all diagnostic messages received from the server in
+the message window.
+
+Code actions
+------------
+
+Some servers offer auto-fixes of certain issues or various refactoring options.
+For instance, the ``clangd`` server displays ``fix available`` next to the issue
+in the hover popup window. To perform the auto-fix, right-click the line with
+the issue and select the corresponding option from the Commands submenu. This
+popup can also be invoked by a keybinding.
+
+Code lenses
+-----------
+
+Code lenses are executable commands that are specific to a particular piece of
+code. As Geany's Scintilla component limitations prevent these commands
+from being clickable and executable directly in the editor, they are accessible
+through the Commands submenu of the context menu, similarly to code actions.
+
+Semantic token type highlighting
+--------------------------------
+
+Language servers that provide semantic token support can be used to highlight
+types, such as class names, in the code. You can customize various aspects of
+how the results are visualized in the editor through the configuration file.
+
+Hover popup
+-----------
+
+The language server can be configured to display a popup window with detailed
+information about the symbol under the mouse cursor. However, as this feature
+can be slightly annoying, it is disabled by default. Alternatively, you can
+access this feature through a keybinding.
+
+Symbol tree
+-----------
+
+The LSP symbol tree tab in the sidebar, separate from Geany's Symbols tab,
+shows document symbols in a similar manner to the Geany's symbol tree feature.
+
+Go to symbol definition/declaration
+-----------------------------------
+
+Similarly to Geany, you can navigate to the symbol definition/declaration
+by control-clicking it in the document or by using the corresponding keybinding.
+This feature is also available from the context menu.
+
+Go to type definition
+---------------------
+
+This feature enables quick navigation to the definition of the type associated
+with the symbol under the cursor, such as the type of a variable. You can also
+access this feature from the context menu.
+
+Swap header/source
+------------------
+
+This is a non-standard clangd extension allowing quick swapping between a
+source file and the corresponding header. This feature is not supported by
+any other language server.
+
+Find references
+---------------
+
+This feature finds all references of the symbol under the cursor in the project.
+This feature is also accessible from the context menu.
+
+Find implementations
+--------------------
+
+This feature allows you to locate all classes that implement the interface under
+the cursor.
+
+Navigation to document/project symbols, files, and line numbers
+---------------------------------------------------------------
+
+The plugin provides a simple, VSCode-style panel for navigating your project.
+The
+
+::
+
+ Tools->LSP Client->Go to Anywhere
+
+command offers four types of navigation options:
+
+- Open files by typing their name directly in the entry
+- Navigate to symbols in the current document by prefixing the query with ``@``
+- Navigate to symbols across the entire project by prefixing the query with ``#``
+- Jump to a specific line in the current document by prefixing the query with ``:``
+
+The other related queries in the LSP Client menu (also accessible via a keybinding)
+simply pre-fill the prefix for you, but otherwise function identically.
+
+Code formatting
+---------------
+
+The code formatting feature allows you to format either the entire document or
+a selected portion of code, depending on the LSP server's support for this
+functionality. You can access this feature from the context menu.
+
+Identical symbol highlighting
+-----------------------------
+
+When you click on a symbol in the document, this feature highlights all its
+occurrences in the document. You can customize the highlighting style to your
+preference by configuring it in the configuration file. Also, it is possible
+to disable this feature to be performed automatically, but, instead, manually
+through a keybinding.
+
+Smart selection expanding/shrinking
+-----------------------------------
+
+This feature allows to expand the current text selection to contain the next
+upper syntactic element such as a parent block in programming languages or a
+parent tag in XML. Selection shrinking works in the opposite direction.
+
+Document symbol renaming
+------------------------
+
+This feature leverages the identical symbol highlighting described above to
+select all symbol occurrences, create multiple cursors at their positions in the
+document, and rename them simultaneously as you type. You can also access this
+feature from the context menu.
+
+Project-wide renaming
+---------------------
+
+After selecting Rename in Project from the context menu or the plugin menu,
+you can rename all symbols in the project.
+
+**Warning:** This feature has a potential to modify many files and language
+servers may not be completely reliable when performing the rename so be very
+cautious when using it. The plugin does not perform any additional
+checks and does not show any preview of the changes so it is best to use this
+feature only after committing all modified files so you can
+easily revert to a working state if needed. Since this is potentially a
+dangerous operation, to prevent accidental renames, the "Rename" button in the
+dialog is not selected by defalut and simply pressing enter just cancels the
+dialog.
+
+Limitations
+===========
+
+By design, the plugin communicates over stdin/stdout only, is responsible
+for launching and terminating the language server process, and supports only
+a single language server per file type.
+
+All of these limitations are addressed by the LSP proxy project available at
+https://github.com/techee/lsp-proxy and related issues should be directed there.
+
+License
+=======
+
+Geany LSP Client is distributed 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. A copy of this license
+can be found in the file COPYING included with the source code of this
+program.
+
+Downloads
+=========
+
+Geany LSP Client can be downloaded from the development repository available
+at https://github.com/techee/geany-lsp/. In addition, it is also distributed
+as part of the combined Geany Plugins release. For more information and
+downloads, please visit https://plugins.geany.org/geany-plugins/
+
+Development Code
+================
+
+Get the code from::
+
+ git clone https://github.com/techee/geany-lsp.git
+
+Ideas, questions, patches and bug reports
+=========================================
+
+Please direct all questions, bug reports and patches to the development
+repository at https://github.com/techee/geany-lsp/ and open the corresponding
+bug report or pull request there.
+
+2023-2024 by Jiří Techet
+techet(at)gmail(dot)com
Modified: lsp/data/Makefile.am
5 lines changed, 5 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,5 @@
+include $(top_srcdir)/build/vars.docs.mk
+
+plugin = lsp
+
+dist_plugindata_DATA = lsp.conf
Modified: lsp/data/lsp.conf
534 lines changed, 534 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,534 @@
+# The global configuration file, accessible through
+# Tools->LSP Client->Global Configuration, defines default values for various
+# configuration options.
+#
+# When accessing the user configuration file using
+# Tools->LSP Client->User Configuration, a copy of the global configuration file
+# is created in user's configuration directory in which users can override
+# various settings from the global configuration file.
+#
+# In addition, it is possible to create a project-wide configuration file used
+# for a single project or shared by multiple projects whose path can be
+# specified under Project->Properties->LSP Client->Configuration file. When such
+# a file is defined and the project is configured to use the project
+# configuration, this configuration file overrides the global configuration
+# instead of the user configuration file.
+#
+# Each configuration file may contain the [all] section which contains settings
+# common for all language servers, and several filetype-specific sections
+# containing settings specific for the given filetype. The names of these
+# sections are identical to the names defined in
+# Tools->Configuration Files->filetype_extensions.conf; for instance [Python]
+# for the Python programming language (case sensitive). Most of the options can
+# appear both in the [all] section and the filetype-specific sections except for
+# a few that make only sense in the filetype-specific section, like e.g. the
+# 'cmd' option containing the command that starts the server. Any option defined
+# in the filetype-specific section overrides identically named option defined in
+# the [all] section for that particular language server.
+#
+# Not all LSP features are supported by all LSP servers. To learn more about
+# what features are supported by the particular server you are trying to use,
+# you can check the result of the initial client-server handshake by going to
+# Tools->LSP Client->Server Initialize Responses (the server must be running
+# to see any result).
+#
+# All servers are automatically restarted when any of the configuration files
+# changes. Servers are started lazily after a tab is switched to a document for
+# which a server is configured (this means that restart typically means shutdown
+# of all servers after which they are started as needed).
+
+
+[all]
+# Defines whether the plugin should be enabled automatically for new or existing
+# projects (that have not yet been configured to use LSP). This option
+# is only valid in the [all] section
+enable_by_default=false
+# Defines whether the server should be used when no project is open. Servers
+# may not work correctly without a project because most of them need to know
+# the path to the project directory which corresponds to the path defined under
+# Project->Properties->Base path. This option can be partially overridden
+# by project_root_marker_patterns, see below
+use_without_project=false
+# Defines whether the server should be used for files whose path is not within
+# the project directory. This option can be partially overridden by
+# project_root_marker_patterns, see below
+use_outside_project_dir=false
+# A semicolon-separated list of glob patterns of files that are typically stored
+# inside the root directory of the project. Language servers supporting
+# changeNotifications of workspaceFolders (these two values should appear inside
+# the server initialize response) can use these marker files to detect root
+# project directories of open files. Starting from the open file directory,
+# the plugin goes up in the directory structure and tests whether a file
+# matching project_root_marker_patterns exists - if it does, such a directory
+# is considered to be the root directory of the project. This allows to
+# detect projects without any Geany project open and allows the plugin to work
+# on multiple projects simultaneously. Typically, the pattern contains
+# files/directories such as .git, configure.ac, go.mod, etc. If a pattern is
+# found, use_without_project and use_outside_project_dir are ignored
+project_root_marker_patterns=
+# In additon to standard identifier characters a-zA-Z0-9_, this configuration
+# option allows adding extra characters that can appear inside identifiers.
+# For instance $- will add '$' and '-' to the above set.
+extra_identifier_characters=
+# Some servers require that the initialization options configuration is sent
+# using workspace/didChangeConfiguration instead of the initialize request.
+# This option does this right after the initialize request completes.
+send_did_change_configuration=false
+
+# The number of keybindings that can be assigned to LSP code action commands.
+# This option is valid only within the [all] section and changing the value
+# requires either the plugin reload or Geany restart
+command_keybinding_num=5
+# When the keybinding Command 1 is invoked, it checks whether the
+# command_1_regex matches any of the items from the Commands submenu of the
+# context menu. The first matched entry is executed. For convenience, regex
+# matches are case insensitive. Up to command_keybinding_num command keybindings
+# can be specified this way
+command_1_regex=
+# Regex specifying which of the commands present in the context menu under the
+# Commands submenu will be automatically performed on save. If multiple entries
+# match, all of them will be performed. For convenience, regex matches are case
+# insensitive
+command_on_save_regex=
+
+# When the filetype-specific 'rpc_log' settings is defined, this option
+# specifies whether the log should contain all details including method
+# parameters, or just the method name and type of the communication
+rpc_log_full=false
+# Show server's stderr in Geany's stderr (when started from terminal)
+show_server_stderr=false
+# Tracing level of the server (when supported). When enabled, tracing messages
+# are logged into stdout. Valid values are 'off', 'messages', 'verbose'
+trace_value=off
+# Enables or disables telemetry notification logging to stdout
+telemetry_notifications=false
+
+# Whether LSP should be used for autocompletion
+autocomplete_enable=true
+# Servers return the label that can be shown in the autocompletion popup for
+# individual autocompletion entries, or it is possible to use just the text that
+# gets inserted when selecting the entry. See also autocomplete_use_snippets.
+autocomplete_use_label=true
+# Whether snippets should be shown in the autocompletion list. Snippet support
+# is only partial so things may not work as expected. When snippets are enabled,
+# it is recommended to use autocomplete_use_label=true, otherwise snippet
+# tab stops and other snippet information is shown in the autocompletion popup.
+autocomplete_use_snippets=false
+# Maximum number of autocompletion entries shown in the popup window (including
+# those that will only get visible after scrolling the contents)
+autocomplete_window_max_entries=20
+# Maximum number of autocompletion entries shown without scrolling (defining the
+# actual height of the popup)
+autocomplete_window_max_displayed=8
+# The maximum width of the autocompletion popup in displayed characters
+autocomplete_window_max_width=60
+# Whether to automatically apply additional edits defined for the autocompletion
+# entry. These are typically imports of the modules where the inserted symbol is
+# defined
+autocomplete_apply_additional_edits=false
+# Semicolon separated list of character sequences which can trigger
+# autocompletion. Normally, the server defines these but this option can be used
+# to further restrict the list only to some sequences if the server-provided
+# value does not work well (e.g. when server's trigger chars for autocompletion
+# clash with signature trigger chars - Rust server for instance uses '(' for
+# both and omitting '(' in autocomplete sequences shows signature instead)
+autocomplete_trigger_sequences=
+# Semicolon separated list of words that make the autocompletion popup hide.
+# This is useful for instance for languages like Pascal that use keywords
+# 'begin' and 'end' which are typically followed by a newline where typing enter
+# after these words might select some unwanted word from the autocompletion list.
+autocomplete_hide_after_words=
+# Whether to perform autocompletion inside strings
+autocomplete_in_strings=false
+# Show documentation (if available) of selected item in autocompletion popup
+# in Geany status bar
+autocomplete_show_documentation=true
+
+# Whether LSP should be used to display diagnostic messages. Typically these are
+# compiler errors or warnings
+diagnostics_enable=true
+# Semicolon-separated glob patterns specifying files for which diagnostic
+# messages are not shown. Useful when the server has a problem with some files
+diagnostics_disable_for=
+# For the statusbar issue number indicator, consider only issues of the
+# configured severity or highler. Valid values are: 1 (error), 2 (warning),
+# 3 (info), 4 (hint). E.g. setting this value to 2 will show issue number
+# for errors and warnings only.
+diagnostics_statusbar_severity=2
+# Defines the style of error diagnostics - visual style such as underline, and
+# its color. Empty value means that diagnostic messages of the given severity
+# are not displayed.
+# The first number is the "indicator index" of Scintilla - each style should
+# have a unique value from 8 to 31. Can be changed when the value clashes with
+# some other plugin.
+# The remaining values correspond to
+# SCI_INDICSETFORE; SCI_INDICSETALPHA; SCI_INDICSETOUTLINEALPHA; SCI_INDICSETSTYLE
+# - see Scintilla documentation for more information
+diagnostics_error_style=13;#ff3030;70;255;1
+# Defines the style of warning diagnostics
+diagnostics_warning_style=14;#ee00ee;70;255;1
+# Defines the style of information diagnostics
+diagnostics_info_style=15;#909090;70;255;14
+# Defines the style of hint diagnostics
+diagnostics_hint_style=16;#909090;70;255;14
+
+# Whether LSP should be used to show a popup with details when hovering over
+# symbols.
+hover_enable=false
+# Maximum number of lines of the popup window
+hover_popup_max_lines=20
+# Maximum number of paragraphs shown in the popup window
+hover_popup_max_paragraphs=1000
+
+# Whether LSP should be used to show function parameter signatures e.g. after
+# typing '('
+signature_enable=true
+
+# Whether LSP should be used for going to symbol definition/declaration
+goto_enable=true
+
+# Whether LSP should be used for displaying symbols in the sidebar (in a tab
+# separate from normal Geany symbols)
+document_symbols_enable=true
+# The label used for the LSP symbols tab. When left empty, the tab is not
+# displayed. This option is only valid in the [all] section
+document_symbols_tab_label=LSP Symbols
+
+# Whether LSP should be used for highlighting semantic tokens in the editor,
+# such as types. Most servers don't support this feature so disabled by default.
+semantic_tokens_enable=false
+# Always perform "full" semantic token request instead of using "delta"
+# requests. Can be used when servers don't support delta tokens correctly
+semantic_tokens_force_full=false
+# Semicolon-separated list of semantic tokens that should be highlighted as
+# types. For valid values, see
+# https://microsoft.github.io/language-server-protocol/specifications/lsp/3.1…
+semantic_tokens_types=type;class;enum;interface;struct
+# When not empty, Scintilla indicators are used for highlighting semantic
+# token types. See diagnostics_error_style for more details about the valid
+# values. Note that because of Scintilla limitations, this value cannot be bold
+#semantic_tokens_type_style=17;#00007f;255;255;17
+semantic_tokens_type_style=
+# When not using semantic_tokens_type_style, this indicates the index in the
+# Scintilla lexer used for custom keywords. This feature is supported only by
+# some lexers like C/C++ and derived lexers. When using this method, the
+# value can be bold but all the occurrences of the given word in the document
+# is highlighted regardless of the context in which it is used
+semantic_tokens_lexer_kw_index=3
+
+# Whether LSP should be used for highlighting all other uses of a variable under
+# cursor.
+highlighting_enable=true
+# Indicator style used for highlighting - see diagnostics_error_style
+highlighting_style=18;#b0b0b0;90;255;8
+
+# Whether LSP should be used for "code lenses" showing commands available
+# for the given line. After right-clicking the line with the code lens, these
+# commands are available in the Commands submenu.
+code_lens_enable=true
+# Defines the foreground and the background color of the code lens indicator.
+code_lens_style=#000000;#ffffa0
+
+# JSON file containing formatting options defined in
+# https://microsoft.github.io/language-server-protocol/specifications/lsp/3.1…
+# e.g. { "tabSize": 4, "insertSpaces": false }. Supported only by some language
+# servers.
+#formatting_options_file=/home/some_user/my_formatting_config_file.json
+formatting_options_file=
+# Like above but with the JSON placed directly into the value. When both
+# formatting_options_file and formatting_options are specified, the JSON from
+# formatting_options_file is used
+formatting_options={ "tabSize": 4, "insertSpaces": false }
+# Defines whether the LSP code-formatting feature should be auto-performed
+# on every save
+format_on_save=false
+
+# Show progress bar for work in progress server operations. Can be disabled
+# when servers do not correctly terminate progress notifications.
+progress_bar_enable=true
+
+# Enable non-standard clangd extension allowing to swap between C/C++ headers
+# and sources. Only usable for clangd, it does not work with other servers.
+swap_header_source_enable=false
+
+
+# This is a dummy language server configuration describing the available
+# language-specific options. Most of the configuration options from the [all]
+# section can be used here as well.
+# For an extensive list of various servers and their configurations, check
+# https://github.com/neovim/nvim-lspconfig/blob/master/doc/configs.md
+# While the configuration options names of neovim differ from Geany, the
+# general concepts are similar and applicable here.
+[DummyLanguage]
+# The command (including parameters and possibly also the full path) used to
+# start the LSP server. Instead of starting a new server, it is also possible to
+# reuse other language's server using the 'use' option - see the C++
+# configuration
+cmd=srvcmd
+# The server can be started with additional environment variables (such as foo
+# with the value bar, and foo1 with the value bar1 like in the example below).
+env=foo=bar;foo1=bar1
+# File containing initialization options of the server. The server is
+# automatically restarted when this file is modified from within Geany
+initialization_options_file=/home/some_user/init_options.json
+# Like above but with the JSON placed directly into the value. When both
+# initialization_options_file and formatting_options are specified, the JSON
+# from initialization_options_file is used
+initialization_options={"compilationDatabasePath": "/home/some_user/"}
+# When defined, performs logging to the specified file where all RPC
+# communication between the client plugin and the server will be stored (can
+# also be 'stdout' or 'stderr')
+rpc_log=stdout
+# Additional files and their mappings to LSP language IDs for which the server
+# is used as well. The Nth item in the list is always a LSP language ID and the
+# (N+1)th item is a glob pattern defining files for which the language ID is
+# used
+lang_id_mappings=dummylanguage;*.dummy
+
+
+[C]
+# By default, clangd expects compile_commands.json inside the 'build' directory
+# of your project. You can create it using either 'meson setup build' if your
+# project uses meson or e.g. using:
+# mkdir build; bear --output build/compile_commands.json -- make
+# if your project uses some other build tool (you need to install the bear tool
+# first). The compile_commands.json file has to be manually regenerated when
+# the build is modified in any way, such as a file is added/removed.
+cmd=clangd
+swap_header_source_enable=true
+autocomplete_in_strings=true
+autocomplete_use_label=false
+semantic_tokens_enable=true
+#initialization_options={"compilationDatabasePath": "/home/some_user/my_project/my_builddir"}
+formatting_options={ "tabSize": 4, "insertSpaces": false }
+command_1_regex=Apply fix:.*
+#rpc_log=stdout
+#rpc_log_full=true
+#show_server_stderr=true
+
+
+[C++]
+# Don't start a new server but reuse the server defined for some other language
+# instead (C server used for C++ in this case)
+use=C
+
+
+[CSS]
+cmd=vscode-css-language-server --stdio
+extra_identifier_characters=-
+send_did_change_configuration=true
+autocomplete_use_snippets=true
+use_without_project=true
+use_outside_project_dir=true
+#rpc_log=stdout
+#rpc_log_full=true
+#show_server_stderr=true
+
+
+[Dart]
+cmd=dart language-server --protocol=lsp
+# everything except ( which conflicts with signature help
+autocomplete_trigger_sequences=.;=;$;";';{;/;:
+semantic_tokens_enable=true
+#rpc_log=stdout
+#rpc_log_full=true
+#show_server_stderr=true
+
+
+[Go]
+cmd=gopls
+autocomplete_apply_additional_edits=true
+lang_id_mappings=go.mod;go.mod;go.sum;go.sum;gotmpl;*tmpl
+semantic_tokens_enable=true
+semantic_tokens_type_style=17;#00007f;255;255;17
+format_on_save=true
+command_on_save_regex=Organize Imports
+progress_bar_enable=false
+#rpc_log=stdout
+#rpc_log_full=true
+#show_server_stderr=true
+
+
+[Haskell]
+cmd=haskell-language-server-wrapper --lsp
+# Full semantic tokens work but are kind of useless as Scintilla already
+# highlights types
+semantic_tokens_enable=false
+#semantic_tokens_force_full=true
+#initialization_options={"plugin": {"semanticTokens": {"config": { }, "globalOn": true}}}
+#semantic_tokens_type_style=17;#00007f;255;255;17
+#rpc_log=stdout
+#rpc_log_full=true
+#show_server_stderr=true
+
+
+[HTML]
+cmd=vscode-html-language-server --stdio
+extra_identifier_characters=&
+send_did_change_configuration=true
+autocomplete_use_snippets=true
+use_without_project=true
+use_outside_project_dir=true
+#rpc_log=stdout
+#rpc_log_full=true
+#show_server_stderr=true
+
+
+[Java]
+cmd=jdtls
+autocomplete_use_label=false
+#semantic_tokens_enable=true
+#rpc_log=stdout
+#rpc_log_full=true
+#show_server_stderr=true
+
+
+[JSON]
+cmd=vscode-json-languageserver --stdio
+#initialization_options={"provideFormatter": true, "json": { "schemas": [ { "fileMatch": [ "*.json"], "url": "file:///home/parallels/schema.json"}]}}
+send_did_change_configuration=true
+autocomplete_use_snippets=true
+use_without_project=true
+use_outside_project_dir=true
+#formatting_options={ "tabSize": 4, "insertSpaces": true }
+#rpc_log=stdout
+#rpc_log_full=true
+#show_server_stderr=true
+
+
+[LaTeX]
+cmd=texlab
+autocomplete_use_snippets=true
+extra_identifier_characters=:
+use_without_project=true
+use_outside_project_dir=true
+#rpc_log=stdout
+#rpc_log_full=true
+#show_server_stderr=true
+
+
+[Lua]
+cmd=lua-language-server
+autocomplete_use_label=false
+autocomplete_hide_after_words=do;then;true;false;end;else
+use_outside_project_dir=true
+use_without_project=true
+#rpc_log=stdout
+#rpc_log_full=true
+#show_server_stderr=true
+
+
+[Nix]
+cmd=nil
+use_without_project=true
+use_outside_project_dir=true
+extra_identifier_characters=-'
+#rpc_log=stdout
+#rpc_log_full=true
+#show_server_stderr=true
+
+
+[PHP]
+# Note: Server returns highlighting indices off by 1 and highlighting doesn't work
+cmd=phpactor.phar language-server
+autocomplete_trigger_sequences=:;>;$;[;@;';\;\\
+extra_identifier_characters=$
+#rpc_log=stdout
+#rpc_log_full=true
+#show_server_stderr=true
+
+
+[Python]
+# pip install pyright (or: pipx install pyright)
+cmd=pyright-langserver --stdio
+cmd=pyright-langserver --stdio
+# alternatively pylsp, jedi, ruff
+#cmd=pylsp
+#cmd=jedi-language-server
+#cmd=ruff server
+use_outside_project_dir=true
+use_without_project=true
+#rpc_log=stdout
+#rpc_log_full=true
+#show_server_stderr=true
+
+
+[Ruby]
+cmd=solargraph stdio
+#rpc_log=stdout
+#rpc_log_full=true
+#show_server_stderr=true
+
+
+[Rust]
+cmd=rust-analyzer
+semantic_tokens_enable=true
+autocomplete_trigger_sequences=:;.;'
+#rpc_log=stdout
+#rpc_log_full=true
+#show_server_stderr=true
+
+
+[Sh]
+cmd=bash-language-server start
+autocomplete_use_snippets=true
+use_outside_project_dir=true
+use_without_project=true
+#rpc_log=stdout
+#rpc_log_full=true
+#show_server_stderr=true
+
+
+[TypeScript]
+cmd=typescript-language-server --stdio
+semantic_tokens_enable=true
+use_outside_project_dir=true
+use_without_project=true
+#rpc_log=stdout
+#rpc_log_full=true
+#show_server_stderr=true
+
+
+[Javascript]
+use=TypeScript
+
+
+[XML]
+cmd=lemminx
+autocomplete_use_snippets=true
+diagnostics_statusbar_severity=4
+use_without_project=true
+use_outside_project_dir=true
+autocomplete_in_strings=true
+# see https://github.com/eclipse/lemminx/blob/main/docs/Configuration.md
+#initialization_options_file=/home/some_user/init_options.json
+#formatting_options={ "tabSize": 4, "insertSpaces": true }
+#rpc_log=stdout
+#rpc_log_full=true
+#show_server_stderr=true
+
+
+[YAML]
+cmd=yaml-language-server --stdio
+#initialization_options={"yaml": {"schemas": { "/home/parallels/schema.json": "*"}}}
+use_without_project=true
+use_outside_project_dir=true
+#formatting_options={ "tabSize": 4, "insertSpaces": true }
+#rpc_log=stdout
+#rpc_log_full=true
+#show_server_stderr=true
+
+
+[Zig]
+cmd=zls
+semantic_tokens_enable=true
+#autocomplete_use_snippets=true
+#rpc_log=stdout
+#rpc_log_full=true
+#show_server_stderr=true
+
+
+# TODO: help needed! Only the above defined language servers have been tested
+# (lightly). If you know some other working language server or find a problem
+# with the settings above, please open an issue report or a pull request
+# on Github.
Modified: lsp/deps/Makefile.am
78 lines changed, 78 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,78 @@
+include $(top_srcdir)/build/vars.build.mk
+
+noinst_LTLIBRARIES = libjsonrpc.la
+
+json_glib_srcs = \
+ json-glib/json-array.c \
+ json-glib/json-builder.c \
+ json-glib/json-builder.h \
+ json-glib/json-debug.c \
+ json-glib/json-debug.h \
+ json-glib/json-enum-types.c \
+ json-glib/json-enum-types.h \
+ json-glib/json-gboxed.c \
+ json-glib/json-generator.c \
+ json-glib/json-generator.h \
+ json-glib/json-glib.h \
+ json-glib/json-gobject.c \
+ json-glib/json-gobject.h \
+ json-glib/json-gobject-private.h \
+ json-glib/json-gvariant.c \
+ json-glib/json-gvariant.h \
+ json-glib/json-node.c \
+ json-glib/json-object.c \
+ json-glib/json-parser.c \
+ json-glib/json-parser.h \
+ json-glib/json-path.c \
+ json-glib/json-path.h \
+ json-glib/json-reader.c \
+ json-glib/json-reader.h \
+ json-glib/json-scanner.c \
+ json-glib/json-scanner.h \
+ json-glib/json-serializable.c \
+ json-glib/json-types.h \
+ json-glib/json-types-private.h \
+ json-glib/json-utils.c \
+ json-glib/json-utils.h \
+ json-glib/json-value.c \
+ json-glib/json-version.h \
+ json-glib/json-version-macros.h
+
+jsonrpc_glib_srcs = \
+ jsonrpc-glib/jsonrpc-client.c \
+ jsonrpc-glib/jsonrpc-client.h \
+ jsonrpc-glib/jsonrpc-glib.h \
+ jsonrpc-glib/jsonrpc-input-stream.c \
+ jsonrpc-glib/jsonrpc-input-stream.h \
+ jsonrpc-glib/jsonrpc-input-stream-private.h \
+ jsonrpc-glib/jsonrpc-marshalers.c \
+ jsonrpc-glib/jsonrpc-marshalers.h \
+ jsonrpc-glib/jsonrpc-message.c \
+ jsonrpc-glib/jsonrpc-message.h \
+ jsonrpc-glib/jsonrpc-output-stream.c \
+ jsonrpc-glib/jsonrpc-output-stream.h \
+ jsonrpc-glib/jsonrpc-server.c \
+ jsonrpc-glib/jsonrpc-server.h \
+ jsonrpc-glib/jsonrpc-version.h \
+ jsonrpc-glib/jsonrpc-version-macros.h
+
+if ENABLE_BUILTIN_JSONRPC
+
+libjsonrpc_la_SOURCES = \
+ $(json_glib_srcs) \
+ $(jsonrpc_glib_srcs)
+
+libjsonrpc_la_CPPFLAGS = $(AM_CPPFLAGS) \
+ -DG_LOG_DOMAIN=\"LSP\" \
+ -DJSON_COMPILATION \
+ -DJSONRPC_GLIB_COMPILATION \
+ -I$(top_srcdir)/lsp/deps/json-glib \
+ -I$(top_srcdir)/lsp/deps/jsonrpc-glib
+libjsonrpc_la_CFLAGS = $(AM_CFLAGS)
+
+# do not enable cppcheck for json-glib or jsonrpc-glib as it generates lots of
+# false positives and it's not "our" code anyway
+#
+# include $(top_srcdir)/build/cppcheck.mk
+
+endif
Modified: lsp/deps/json-glib/json-array.c
838 lines changed, 838 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,838 @@
+/* json-array.c - JSON array implementation
+ *
+ * This file is part of JSON-GLib
+ * Copyright (C) 2007 OpenedHand Ltd.
+ * Copyright (C) 2009 Intel Corp.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author:
+ * Emmanuele Bassi <ebassi(a)linux.intel.com>
+ */
+
+#include "config.h"
+
+#include "json-types-private.h"
+
+/**
+ * JsonArray:
+ *
+ * `JsonArray` is the representation of the array type inside JSON.
+ *
+ * A `JsonArray` contains [struct(a)Json.Node] elements, which may contain
+ * fundamental types, other arrays or objects.
+ *
+ * Since arrays can be arbitrarily big, copying them can be expensive; for
+ * this reason, they are reference counted. You can control the lifetime of
+ * a `JsonArray` using [method(a)Json.Array.ref] and [method(a)Json.Array.unref].
+ *
+ * To append an element, use [method(a)Json.Array.add_element].
+ *
+ * To extract an element at a given index, use [method(a)Json.Array.get_element].
+ *
+ * To retrieve the entire array in list form, use [method(a)Json.Array.get_elements].
+ *
+ * To retrieve the length of the array, use [method(a)Json.Array.get_length].
+ */
+
+G_DEFINE_BOXED_TYPE (JsonArray, json_array, json_array_ref, json_array_unref);
+
+/**
+ * json_array_new: (constructor)
+ *
+ * Creates a new array.
+ *
+ * Return value: (transfer full): the newly created array
+ */
+JsonArray *
+json_array_new (void)
+{
+ JsonArray *array;
+
+ array = g_slice_new0 (JsonArray);
+
+ array->ref_count = 1;
+ array->elements = g_ptr_array_new ();
+
+ return array;
+}
+
+/**
+ * json_array_sized_new: (constructor)
+ * @n_elements: number of slots to pre-allocate
+ *
+ * Creates a new array with `n_elements` slots already allocated.
+ *
+ * Return value: (transfer full): the newly created array
+ */
+JsonArray *
+json_array_sized_new (guint n_elements)
+{
+ JsonArray *array;
+
+ array = g_slice_new0 (JsonArray);
+
+ array->ref_count = 1;
+ array->elements = g_ptr_array_sized_new (n_elements);
+
+ return array;
+}
+
+/**
+ * json_array_ref:
+ * @array: the array to reference
+ *
+ * Acquires a reference on the given array.
+ *
+ * Return value: (transfer none): the passed array, with the reference count
+ * increased by one
+ */
+JsonArray *
+json_array_ref (JsonArray *array)
+{
+ g_return_val_if_fail (array != NULL, NULL);
+ g_return_val_if_fail (array->ref_count > 0, NULL);
+
+ array->ref_count++;
+
+ return array;
+}
+
+/**
+ * json_array_unref:
+ * @array: the array to unreference
+ *
+ * Releases a reference on the given array.
+ *
+ * If the reference count reaches zero, the array is destroyed and all
+ * its allocated resources are freed.
+ */
+void
+json_array_unref (JsonArray *array)
+{
+ g_return_if_fail (array != NULL);
+ g_return_if_fail (array->ref_count > 0);
+
+ if (--array->ref_count == 0)
+ {
+ guint i;
+
+ for (i = 0; i < array->elements->len; i++)
+ json_node_unref (g_ptr_array_index (array->elements, i));
+
+ g_ptr_array_free (array->elements, TRUE);
+ array->elements = NULL;
+
+ g_slice_free (JsonArray, array);
+ }
+}
+
+/**
+ * json_array_seal:
+ * @array: the array to seal
+ *
+ * Seals the given array, making it immutable to further changes.
+ *
+ * This function will recursively seal all elements in the array too.
+ *
+ * If the `array` is already immutable, this is a no-op.
+ *
+ * Since: 1.2
+ */
+void
+json_array_seal (JsonArray *array)
+{
+ guint i;
+
+ g_return_if_fail (array != NULL);
+ g_return_if_fail (array->ref_count > 0);
+
+ if (array->immutable)
+ return;
+
+ /* Propagate to all members. */
+ for (i = 0; i < array->elements->len; i++)
+ json_node_seal (g_ptr_array_index (array->elements, i));
+
+ array->immutable_hash = json_array_hash (array);
+ array->immutable = TRUE;
+}
+
+/**
+ * json_array_is_immutable:
+ * @array: a JSON array
+ *
+ * Check whether the given `array` has been marked as immutable by calling
+ * [method(a)Json.Array.seal] on it.
+ *
+ * Since: 1.2
+ * Returns: %TRUE if the array is immutable
+ */
+gboolean
+json_array_is_immutable (JsonArray *array)
+{
+ g_return_val_if_fail (array != NULL, FALSE);
+ g_return_val_if_fail (array->ref_count > 0, FALSE);
+
+ return array->immutable;
+}
+
+/**
+ * json_array_get_elements:
+ * @array: a JSON array
+ *
+ * Retrieves all the elements of an array as a list of nodes.
+ *
+ * Return value: (element-type JsonNode) (transfer container) (nullable): the elements
+ * of the array
+ */
+GList *
+json_array_get_elements (JsonArray *array)
+{
+ GList *retval;
+ guint i;
+
+ g_return_val_if_fail (array != NULL, NULL);
+
+ retval = NULL;
+ for (i = 0; i < array->elements->len; i++)
+ retval = g_list_prepend (retval,
+ g_ptr_array_index (array->elements, i));
+
+ return g_list_reverse (retval);
+}
+
+/**
+ * json_array_dup_element:
+ * @array: a JSON array
+ * @index_: the index of the element to retrieve
+ *
+ * Retrieves a copy of the element at the given position in the array.
+ *
+ * Return value: (transfer full): a copy of the element at the given position
+ *
+ * Since: 0.6
+ */
+JsonNode *
+json_array_dup_element (JsonArray *array,
+ guint index_)
+{
+ JsonNode *retval;
+
+ g_return_val_if_fail (array != NULL, NULL);
+ g_return_val_if_fail (index_ < array->elements->len, NULL);
+
+ retval = json_array_get_element (array, index_);
+ if (!retval)
+ return NULL;
+
+ return json_node_copy (retval);
+}
+
+/**
+ * json_array_get_element:
+ * @array: a JSON array
+ * @index_: the index of the element to retrieve
+ *
+ * Retrieves the element at the given position in the array.
+ *
+ * Return value: (transfer none): the element at the given position
+ */
+JsonNode *
+json_array_get_element (JsonArray *array,
+ guint index_)
+{
+ g_return_val_if_fail (array != NULL, NULL);
+ g_return_val_if_fail (index_ < array->elements->len, NULL);
+
+ return g_ptr_array_index (array->elements, index_);
+}
+
+/**
+ * json_array_get_int_element:
+ * @array: a JSON array
+ * @index_: the index of the element to retrieve
+ *
+ * Conveniently retrieves the integer value of the element at the given
+ * position inside an array.
+ *
+ * See also: [method(a)Json.Array.get_element], [method(a)Json.Node.get_int]
+ *
+ * Return value: the integer value
+ *
+ * Since: 0.8
+ */
+gint64
+json_array_get_int_element (JsonArray *array,
+ guint index_)
+{
+ JsonNode *node;
+
+ g_return_val_if_fail (array != NULL, 0);
+ g_return_val_if_fail (index_ < array->elements->len, 0);
+
+ node = g_ptr_array_index (array->elements, index_);
+ g_return_val_if_fail (node != NULL, 0);
+ g_return_val_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_VALUE, 0);
+
+ return json_node_get_int (node);
+}
+
+/**
+ * json_array_get_double_element:
+ * @array: a JSON array
+ * @index_: the index of the element to retrieve
+ *
+ * Conveniently retrieves the floating point value of the element at
+ * the given position inside an array.
+ *
+ * See also: [method(a)Json.Array.get_element], [method(a)Json.Node.get_double]
+ *
+ * Return value: the floating point value
+ *
+ * Since: 0.8
+ */
+gdouble
+json_array_get_double_element (JsonArray *array,
+ guint index_)
+{
+ JsonNode *node;
+
+ g_return_val_if_fail (array != NULL, 0.0);
+ g_return_val_if_fail (index_ < array->elements->len, 0.0);
+
+ node = g_ptr_array_index (array->elements, index_);
+ g_return_val_if_fail (node != NULL, 0.0);
+ g_return_val_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_VALUE, 0.0);
+
+ return json_node_get_double (node);
+}
+
+/**
+ * json_array_get_boolean_element:
+ * @array: a JSON array
+ * @index_: the index of the element to retrieve
+ *
+ * Conveniently retrieves the boolean value of the element at the given
+ * position inside an array.
+ *
+ * See also: [method(a)Json.Array.get_element], [method(a)Json.Node.get_boolean]
+ *
+ * Return value: the boolean value
+ *
+ * Since: 0.8
+ */
+gboolean
+json_array_get_boolean_element (JsonArray *array,
+ guint index_)
+{
+ JsonNode *node;
+
+ g_return_val_if_fail (array != NULL, FALSE);
+ g_return_val_if_fail (index_ < array->elements->len, FALSE);
+
+ node = g_ptr_array_index (array->elements, index_);
+ g_return_val_if_fail (node != NULL, FALSE);
+ g_return_val_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_VALUE, FALSE);
+
+ return json_node_get_boolean (node);
+}
+
+/**
+ * json_array_get_string_element:
+ * @array: a JSON array
+ * @index_: the index of the element to retrieve
+ *
+ * Conveniently retrieves the string value of the element at the given
+ * position inside an array.
+ *
+ * See also: [method(a)Json.Array.get_element], [method(a)Json.Node.get_string]
+ *
+ * Return value: (transfer none): the string value
+ *
+ * Since: 0.8
+ */
+const gchar *
+json_array_get_string_element (JsonArray *array,
+ guint index_)
+{
+ JsonNode *node;
+
+ g_return_val_if_fail (array != NULL, NULL);
+ g_return_val_if_fail (index_ < array->elements->len, NULL);
+
+ node = g_ptr_array_index (array->elements, index_);
+ g_return_val_if_fail (node != NULL, NULL);
+ g_return_val_if_fail (JSON_NODE_HOLDS_VALUE (node) || JSON_NODE_HOLDS_NULL (node), NULL);
+
+ if (JSON_NODE_HOLDS_NULL (node))
+ return NULL;
+
+ return json_node_get_string (node);
+}
+
+/**
+ * json_array_get_null_element:
+ * @array: a JSON array
+ * @index_: the index of the element to retrieve
+ *
+ * Conveniently checks whether the element at the given position inside the
+ * array contains a `null` value.
+ *
+ * See also: [method(a)Json.Array.get_element], [method(a)Json.Node.is_null]
+ *
+ * Return value: `TRUE` if the element is `null`
+ *
+ * Since: 0.8
+ */
+gboolean
+json_array_get_null_element (JsonArray *array,
+ guint index_)
+{
+ JsonNode *node;
+
+ g_return_val_if_fail (array != NULL, FALSE);
+ g_return_val_if_fail (index_ < array->elements->len, FALSE);
+
+ node = g_ptr_array_index (array->elements, index_);
+ g_return_val_if_fail (node != NULL, FALSE);
+
+ if (JSON_NODE_HOLDS_NULL (node))
+ return TRUE;
+
+ if (JSON_NODE_HOLDS_ARRAY (node))
+ return json_node_get_array (node) == NULL;
+
+ if (JSON_NODE_HOLDS_OBJECT (node))
+ return json_node_get_object (node) == NULL;
+
+ return FALSE;
+}
+
+/**
+ * json_array_get_array_element:
+ * @array: a JSON array
+ * @index_: the index of the element to retrieve
+ *
+ * Conveniently retrieves the array at the given position inside an array.
+ *
+ * See also: [method(a)Json.Array.get_element], [method(a)Json.Node.get_array]
+ *
+ * Return value: (transfer none): the array
+ *
+ * Since: 0.8
+ */
+JsonArray *
+json_array_get_array_element (JsonArray *array,
+ guint index_)
+{
+ JsonNode *node;
+
+ g_return_val_if_fail (array != NULL, NULL);
+ g_return_val_if_fail (index_ < array->elements->len, NULL);
+
+ node = g_ptr_array_index (array->elements, index_);
+ g_return_val_if_fail (node != NULL, NULL);
+ g_return_val_if_fail (JSON_NODE_HOLDS_ARRAY (node) || JSON_NODE_HOLDS_NULL (node), NULL);
+
+ if (JSON_NODE_HOLDS_NULL (node))
+ return NULL;
+
+ return json_node_get_array (node);
+}
+
+/**
+ * json_array_get_object_element:
+ * @array: a JSON array
+ * @index_: the index of the element to retrieve
+ *
+ * Conveniently retrieves the object at the given position inside an array.
+ *
+ * See also: [method(a)Json.Array.get_element], [method(a)Json.Node.get_object]
+ *
+ * Return value: (transfer none): the object
+ *
+ * Since: 0.8
+ */
+JsonObject *
+json_array_get_object_element (JsonArray *array,
+ guint index_)
+{
+ JsonNode *node;
+
+ g_return_val_if_fail (array != NULL, NULL);
+ g_return_val_if_fail (index_ < array->elements->len, NULL);
+
+ node = g_ptr_array_index (array->elements, index_);
+ g_return_val_if_fail (node != NULL, NULL);
+ g_return_val_if_fail (JSON_NODE_HOLDS_OBJECT (node) || JSON_NODE_HOLDS_NULL (node), NULL);
+
+ if (JSON_NODE_HOLDS_NULL (node))
+ return NULL;
+
+ return json_node_get_object (node);
+}
+
+/**
+ * json_array_get_length:
+ * @array: a JSON array
+ *
+ * Retrieves the length of the given array
+ *
+ * Return value: the length of the array
+ */
+guint
+json_array_get_length (JsonArray *array)
+{
+ g_return_val_if_fail (array != NULL, 0);
+
+ return array->elements->len;
+}
+
+/**
+ * json_array_add_element:
+ * @array: a JSON array
+ * @node: (transfer full): the element to add
+ *
+ * Appends the given `node` inside an array.
+ */
+void
+json_array_add_element (JsonArray *array,
+ JsonNode *node)
+{
+ g_return_if_fail (array != NULL);
+ g_return_if_fail (node != NULL);
+
+ g_ptr_array_add (array->elements, node);
+}
+
+/**
+ * json_array_add_int_element:
+ * @array: a JSON array
+ * @value: the integer value to add
+ *
+ * Conveniently adds the given integer value into an array.
+ *
+ * See also: [method(a)Json.Array.add_element], [method(a)Json.Node.set_int]
+ *
+ * Since: 0.8
+ */
+void
+json_array_add_int_element (JsonArray *array,
+ gint64 value)
+{
+ g_return_if_fail (array != NULL);
+
+ json_array_add_element (array, json_node_init_int (json_node_alloc (), value));
+}
+
+/**
+ * json_array_add_double_element:
+ * @array: a JSON array
+ * @value: the floating point value to add
+ *
+ * Conveniently adds the given floating point value into an array.
+ *
+ * See also: [method(a)Json.Array.add_element], [method(a)Json.Node.set_double]
+ *
+ * Since: 0.8
+ */
+void
+json_array_add_double_element (JsonArray *array,
+ gdouble value)
+{
+ g_return_if_fail (array != NULL);
+
+ json_array_add_element (array, json_node_init_double (json_node_alloc (), value));
+}
+
+/**
+ * json_array_add_boolean_element:
+ * @array: a JSON array
+ * @value: the boolean value to add
+ *
+ * Conveniently adds the given boolean value into an array.
+ *
+ * See also: [method(a)Json.Array.add_element], [method(a)Json.Node.set_boolean]
+ *
+ * Since: 0.8
+ */
+void
+json_array_add_boolean_element (JsonArray *array,
+ gboolean value)
+{
+ g_return_if_fail (array != NULL);
+
+ json_array_add_element (array, json_node_init_boolean (json_node_alloc (), value));
+}
+
+/**
+ * json_array_add_string_element:
+ * @array: a JSON array
+ * @value: the string value to add
+ *
+ * Conveniently adds the given string value into an array.
+ *
+ * See also: [method(a)Json.Array.add_element], [method(a)Json.Node.set_string]
+ *
+ * Since: 0.8
+ */
+void
+json_array_add_string_element (JsonArray *array,
+ const gchar *value)
+{
+ JsonNode *node;
+
+ g_return_if_fail (array != NULL);
+
+ node = json_node_alloc ();
+
+ if (value != NULL)
+ json_node_init_string (node, value);
+ else
+ json_node_init_null (node);
+
+ json_array_add_element (array, node);
+}
+
+/**
+ * json_array_add_null_element:
+ * @array: a JSON array
+ *
+ * Conveniently adds a `null` element into an array
+ *
+ * See also: [method(a)Json.Array.add_element], `JSON_NODE_NULL`
+ *
+ * Since: 0.8
+ */
+void
+json_array_add_null_element (JsonArray *array)
+{
+ g_return_if_fail (array != NULL);
+
+ json_array_add_element (array, json_node_init_null (json_node_alloc ()));
+}
+
+/**
+ * json_array_add_array_element:
+ * @array: a JSON array
+ * @value: (nullable) (transfer full): the array to add
+ *
+ * Conveniently adds an array element into an array.
+ *
+ * If `value` is `NULL`, a `null` element will be added instead.
+ *
+ * See also: [method(a)Json.Array.add_element], [method(a)Json.Node.take_array]
+ *
+ * Since: 0.8
+ */
+void
+json_array_add_array_element (JsonArray *array,
+ JsonArray *value)
+{
+ JsonNode *node;
+
+ g_return_if_fail (array != NULL);
+
+ node = json_node_alloc ();
+
+ if (value != NULL)
+ {
+ json_node_init_array (node, value);
+ json_array_unref (value);
+ }
+ else
+ json_node_init_null (node);
+
+ json_array_add_element (array, node);
+}
+
+/**
+ * json_array_add_object_element:
+ * @array: a JSON array
+ * @value: (transfer full) (nullable): the object to add
+ *
+ * Conveniently adds an object into an array.
+ *
+ * If `value` is `NULL`, a `null` element will be added instead.
+ *
+ * See also: [method(a)Json.Array.add_element], [method(a)Json.Node.take_object]
+ *
+ * Since: 0.8
+ */
+void
+json_array_add_object_element (JsonArray *array,
+ JsonObject *value)
+{
+ JsonNode *node;
+
+ g_return_if_fail (array != NULL);
+
+ node = json_node_alloc ();
+
+ if (value != NULL)
+ {
+ json_node_init_object (node, value);
+ json_object_unref (value);
+ }
+ else
+ json_node_init_null (node);
+
+ json_array_add_element (array, node);
+}
+
+/**
+ * json_array_remove_element:
+ * @array: a JSON array
+ * @index_: the position of the element to be removed
+ *
+ * Removes the element at the given position inside an array.
+ *
+ * This function will release the reference held on the element.
+ */
+void
+json_array_remove_element (JsonArray *array,
+ guint index_)
+{
+ g_return_if_fail (array != NULL);
+ g_return_if_fail (index_ < array->elements->len);
+
+ json_node_unref (g_ptr_array_remove_index (array->elements, index_));
+}
+
+/**
+ * json_array_foreach_element:
+ * @array: a JSON array
+ * @func: (scope call): the function to be called on each element
+ * @data: (closure): data to be passed to the function
+ *
+ * Iterates over all elements of an array, and calls a function on
+ * each one of them.
+ *
+ * It is safe to change the value of an element of the array while
+ * iterating over it, but it is not safe to add or remove elements
+ * from the array.
+ *
+ * Since: 0.8
+ */
+void
+json_array_foreach_element (JsonArray *array,
+ JsonArrayForeach func,
+ gpointer data)
+{
+ g_return_if_fail (array != NULL);
+ g_return_if_fail (func != NULL);
+
+ for (guint i = 0; i < array->elements->len; i++)
+ {
+ JsonNode *element_node;
+
+ element_node = g_ptr_array_index (array->elements, i);
+
+ (* func) (array, i, element_node, data);
+ }
+}
+
+/**
+ * json_array_hash:
+ * @key: (type JsonArray) (not nullable): a JSON array to hash
+ *
+ * Calculates a hash value for the given `key`.
+ *
+ * The hash is calculated over the array and all its elements, recursively.
+ *
+ * If the array is immutable, this is a fast operation; otherwise, it scales
+ * proportionally with the length of the array.
+ *
+ * Returns: hash value for the key
+ * Since: 1.2
+ */
+guint
+json_array_hash (gconstpointer key)
+{
+ JsonArray *array; /* unowned */
+ guint hash = 0;
+ guint i;
+
+ g_return_val_if_fail (key != NULL, 0);
+
+ array = (JsonArray *) key;
+
+ /* If the array is immutable, we can use the calculated hash. */
+ if (array->immutable)
+ return array->immutable_hash;
+
+ /* Otherwise, calculate the hash. */
+ for (i = 0; i < array->elements->len; i++)
+ {
+ JsonNode *node = g_ptr_array_index (array->elements, i);
+ hash ^= (i ^ json_node_hash (node));
+ }
+
+ return hash;
+}
+
+/**
+ * json_array_equal:
+ * @a: (type JsonArray) (not nullable): a JSON array
+ * @b: (type JsonArray) (not nullable): another JSON array
+ *
+ * Check whether two arrays are equal.
+ *
+ * Equality is defined as:
+ *
+ * - the array have the same number of elements
+ * - the values of elements in corresponding positions are equal
+ *
+ * Returns: `TRUE` if the arrays are equal, and `FALSE` otherwise
+ * Since: 1.2
+ */
+gboolean
+json_array_equal (gconstpointer a,
+ gconstpointer b)
+{
+ JsonArray *array_a, *array_b; /* unowned */
+ guint length_a, length_b, i;
+
+ g_return_val_if_fail (a != NULL, FALSE);
+ g_return_val_if_fail (b != NULL, FALSE);
+
+ array_a = (JsonArray *) a;
+ array_b = (JsonArray *) b;
+
+ /* Identity comparison. */
+ if (array_a == array_b)
+ return TRUE;
+
+ /* Check lengths. */
+ length_a = json_array_get_length (array_a);
+ length_b = json_array_get_length (array_b);
+
+ if (length_a != length_b)
+ return FALSE;
+
+ /* Check elements. */
+ for (i = 0; i < length_a; i++)
+ {
+ JsonNode *child_a, *child_b; /* unowned */
+
+ child_a = json_array_get_element (array_a, i);
+ child_b = json_array_get_element (array_b, i);
+
+ if (!json_node_equal (child_a, child_b))
+ return FALSE;
+ }
+
+ return TRUE;
+}
Modified: lsp/deps/json-glib/json-builder.c
845 lines changed, 845 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,845 @@
+/* json-generator.c - JSON tree builder
+ *
+ * This file is part of JSON-GLib
+ * Copyright (C) 2010 Luca Bruno <lethalman88(a)gmail.com>
+ * Copyright (C) 2015 Collabora Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author:
+ * Luca Bruno <lethalman88(a)gmail.com>
+ * Philip Withnall <philip.withnall(a)collabora.co.uk>
+ */
+
+/**
+ * JsonBuilder:
+ *
+ * `JsonBuilder` provides an object for generating a JSON tree.
+ *
+ * The root of the JSON tree can be either a [struct(a)Json.Object] or a [struct(a)Json.Array].
+ * Thus the first call must necessarily be either
+ * [method(a)Json.Builder.begin_object] or [method(a)Json.Builder.begin_array].
+ *
+ * For convenience to language bindings, most `JsonBuilder` method return the
+ * instance, making it easy to chain function calls.
+ *
+ * ## Using `JsonBuilder`
+ *
+ * ```c
+ * g_autoptr(JsonBuilder) builder = json_builder_new ();
+ *
+ * json_builder_begin_object (builder);
+ *
+ * json_builder_set_member_name (builder, "url");
+ * json_builder_add_string_value (builder, "http://www.gnome.org/img/flash/two-thirty.png");
+ *
+ * json_builder_set_member_name (builder, "size");
+ * json_builder_begin_array (builder);
+ * json_builder_add_int_value (builder, 652);
+ * json_builder_add_int_value (builder, 242);
+ * json_builder_end_array (builder);
+ *
+ * json_builder_end_object (builder);
+ *
+ * g_autoptr(JsonNode) root = json_builder_get_root (builder);
+ *
+ * g_autoptr(JsonGenerator) gen = json_generator_new ();
+ * json_generator_set_root (gen, root);
+ * g_autofree char *str = json_generator_to_data (gen, NULL);
+ *
+ * // str now contains the following JSON data
+ * // { "url" : "http://www.gnome.org/img/flash/two-thirty.png", "size" : [ 652, 242 ] }
+ * ```
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "json-types-private.h"
+
+#include "json-builder.h"
+
+struct _JsonBuilderPrivate
+{
+ GQueue *stack;
+ JsonNode *root;
+ gboolean immutable;
+};
+
+enum
+{
+ PROP_IMMUTABLE = 1,
+ PROP_LAST
+};
+
+static GParamSpec *builder_props[PROP_LAST] = { NULL, };
+
+typedef enum
+{
+ JSON_BUILDER_MODE_OBJECT,
+ JSON_BUILDER_MODE_ARRAY,
+ JSON_BUILDER_MODE_MEMBER
+} JsonBuilderMode;
+
+typedef struct
+{
+ JsonBuilderMode mode;
+
+ union
+ {
+ JsonObject *object;
+ JsonArray *array;
+ } data;
+ gchar *member_name;
+} JsonBuilderState;
+
+static void
+json_builder_state_free (JsonBuilderState *state)
+{
+ if (G_LIKELY (state))
+ {
+ switch (state->mode)
+ {
+ case JSON_BUILDER_MODE_OBJECT:
+ case JSON_BUILDER_MODE_MEMBER:
+ json_object_unref (state->data.object);
+ g_free (state->member_name);
+ state->data.object = NULL;
+ state->member_name = NULL;
+ break;
+
+ case JSON_BUILDER_MODE_ARRAY:
+ json_array_unref (state->data.array);
+ state->data.array = NULL;
+ break;
+
+ default:
+ g_assert_not_reached ();
+ }
+
+ g_slice_free (JsonBuilderState, state);
+ }
+}
+
+G_DEFINE_TYPE_WITH_PRIVATE (JsonBuilder, json_builder, G_TYPE_OBJECT)
+
+static void
+json_builder_free_all_state (JsonBuilder *builder)
+{
+ JsonBuilderState *state;
+
+ while (!g_queue_is_empty (builder->priv->stack))
+ {
+ state = g_queue_pop_head (builder->priv->stack);
+ json_builder_state_free (state);
+ }
+
+ if (builder->priv->root)
+ {
+ json_node_unref (builder->priv->root);
+ builder->priv->root = NULL;
+ }
+}
+
+static void
+json_builder_finalize (GObject *gobject)
+{
+ JsonBuilderPrivate *priv = json_builder_get_instance_private ((JsonBuilder *) gobject);
+
+ json_builder_free_all_state (JSON_BUILDER (gobject));
+
+ g_queue_free (priv->stack);
+ priv->stack = NULL;
+
+ G_OBJECT_CLASS (json_builder_parent_class)->finalize (gobject);
+}
+
+static void
+json_builder_set_property (GObject *gobject,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ JsonBuilderPrivate *priv = JSON_BUILDER (gobject)->priv;
+
+ switch (prop_id)
+ {
+ case PROP_IMMUTABLE:
+ /* Construct-only. */
+ priv->immutable = g_value_get_boolean (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+json_builder_get_property (GObject *gobject,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ JsonBuilderPrivate *priv = JSON_BUILDER (gobject)->priv;
+
+ switch (prop_id)
+ {
+ case PROP_IMMUTABLE:
+ g_value_set_boolean (value, priv->immutable);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+json_builder_class_init (JsonBuilderClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ /**
+ * JsonBuilder:immutable:
+ *
+ * Whether the tree should be immutable when created.
+ *
+ * Making the output immutable on creation avoids the expense
+ * of traversing it to make it immutable later.
+ *
+ * Since: 1.2
+ */
+ builder_props[PROP_IMMUTABLE] =
+ g_param_spec_boolean ("immutable",
+ "Immutable Output",
+ "Whether the builder output is immutable.",
+ FALSE,
+ G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
+
+ gobject_class->set_property = json_builder_set_property;
+ gobject_class->get_property = json_builder_get_property;
+ gobject_class->finalize = json_builder_finalize;
+
+ g_object_class_install_properties (gobject_class, PROP_LAST, builder_props);
+}
+
+static void
+json_builder_init (JsonBuilder *builder)
+{
+ JsonBuilderPrivate *priv = json_builder_get_instance_private (builder);
+
+ builder->priv = priv;
+
+ priv->stack = g_queue_new ();
+ priv->root = NULL;
+}
+
+static inline JsonBuilderMode
+json_builder_current_mode (JsonBuilder *builder)
+{
+ JsonBuilderState *state = g_queue_peek_head (builder->priv->stack);
+ return state->mode;
+}
+
+static inline gboolean
+json_builder_is_valid_add_mode (JsonBuilder *builder)
+{
+ JsonBuilderMode mode = json_builder_current_mode (builder);
+ return mode == JSON_BUILDER_MODE_MEMBER || mode == JSON_BUILDER_MODE_ARRAY;
+}
+
+/**
+ * json_builder_new:
+ *
+ * Creates a new `JsonBuilder`.
+ *
+ * You can use this object to generate a JSON tree and obtain the root node.
+ *
+ * Return value: the newly created builder instance
+ */
+JsonBuilder *
+json_builder_new (void)
+{
+ return g_object_new (JSON_TYPE_BUILDER, NULL);
+}
+
+/**
+ * json_builder_new_immutable: (constructor)
+ *
+ * Creates a new, immutable `JsonBuilder` instance.
+ *
+ * It is equivalent to setting the [property@Json.Builder:immutable] property
+ * set to `TRUE` at construction time.
+ *
+ * Since: 1.2
+ * Returns: (transfer full): the newly create builder instance
+ */
+JsonBuilder *
+json_builder_new_immutable (void)
+{
+ return g_object_new (JSON_TYPE_BUILDER, "immutable", TRUE, NULL);
+}
+
+/**
+ * json_builder_get_root:
+ * @builder: a builder
+ *
+ * Returns the root of the currently constructed tree.
+ *
+ * if the build is incomplete (ie: if there are any opened objects, or any
+ * open object members and array elements) then this function will return
+ * `NULL`.
+ *
+ * Return value: (nullable) (transfer full): the root node
+ */
+JsonNode *
+json_builder_get_root (JsonBuilder *builder)
+{
+ JsonNode *root = NULL;
+
+ g_return_val_if_fail (JSON_IS_BUILDER (builder), NULL);
+
+ if (builder->priv->root)
+ root = json_node_copy (builder->priv->root);
+
+ /* Sanity check. */
+ g_assert (!builder->priv->immutable ||
+ root == NULL ||
+ json_node_is_immutable (root));
+
+ return root;
+}
+
+/**
+ * json_builder_reset:
+ * @builder: a builder
+ *
+ * Resets the state of the builder back to its initial state.
+ */
+void
+json_builder_reset (JsonBuilder *builder)
+{
+ g_return_if_fail (JSON_IS_BUILDER (builder));
+
+ json_builder_free_all_state (builder);
+}
+
+/**
+ * json_builder_begin_object:
+ * @builder: a builder
+ *
+ * Opens an object inside the given builder.
+ *
+ * You can add a new member to the object by using [method(a)Json.Builder.set_member_name],
+ * followed by [method(a)Json.Builder.add_value].
+ *
+ * Once you added all members to the object, you must call [method(a)Json.Builder.end_object]
+ * to close the object.
+ *
+ * If the builder is in an inconsistent state, this function will return `NULL`.
+ *
+ * Return value: (nullable) (transfer none): the builder instance
+ */
+JsonBuilder *
+json_builder_begin_object (JsonBuilder *builder)
+{
+ JsonObject *object;
+ JsonBuilderState *state;
+ JsonBuilderState *cur_state;
+
+ g_return_val_if_fail (JSON_IS_BUILDER (builder), NULL);
+ g_return_val_if_fail (builder->priv->root == NULL, NULL);
+ g_return_val_if_fail (g_queue_is_empty (builder->priv->stack) || json_builder_is_valid_add_mode (builder), NULL);
+
+ object = json_object_new ();
+ cur_state = g_queue_peek_head (builder->priv->stack);
+ if (cur_state)
+ {
+ switch (cur_state->mode)
+ {
+ case JSON_BUILDER_MODE_ARRAY:
+ json_array_add_object_element (cur_state->data.array, json_object_ref (object));
+ break;
+
+ case JSON_BUILDER_MODE_MEMBER:
+ json_object_set_object_member (cur_state->data.object, cur_state->member_name, json_object_ref (object));
+ g_free (cur_state->member_name);
+ cur_state->member_name = NULL;
+ cur_state->mode = JSON_BUILDER_MODE_OBJECT;
+ break;
+
+ default:
+ g_assert_not_reached ();
+ }
+ }
+
+ state = g_slice_new (JsonBuilderState);
+ state->data.object = object;
+ state->member_name = NULL;
+ state->mode = JSON_BUILDER_MODE_OBJECT;
+ g_queue_push_head (builder->priv->stack, state);
+
+ return builder;
+}
+
+/**
+ * json_builder_end_object:
+ * @builder: a builder
+ *
+ * Closes the object inside the given builder that was opened by the most
+ * recent call to [method(a)Json.Builder.begin_object].
+ *
+ * This function cannot be called after [method(a)Json.Builder.set_member_name].
+ *
+ * Return value: (nullable) (transfer none): the builder instance
+ */
+JsonBuilder *
+json_builder_end_object (JsonBuilder *builder)
+{
+ JsonBuilderState *state;
+
+ g_return_val_if_fail (JSON_IS_BUILDER (builder), NULL);
+ g_return_val_if_fail (!g_queue_is_empty (builder->priv->stack), NULL);
+ g_return_val_if_fail (json_builder_current_mode (builder) == JSON_BUILDER_MODE_OBJECT, NULL);
+
+ state = g_queue_pop_head (builder->priv->stack);
+
+ if (builder->priv->immutable)
+ json_object_seal (state->data.object);
+
+ if (g_queue_is_empty (builder->priv->stack))
+ {
+ builder->priv->root = json_node_new (JSON_NODE_OBJECT);
+ json_node_take_object (builder->priv->root, json_object_ref (state->data.object));
+
+ if (builder->priv->immutable)
+ json_node_seal (builder->priv->root);
+ }
+
+ json_builder_state_free (state);
+
+ return builder;
+}
+
+/**
+ * json_builder_begin_array:
+ * @builder: a builder
+ *
+ * Opens an array inside the given builder.
+ *
+ * You can add a new element to the array by using [method(a)Json.Builder.add_value].
+ *
+ * Once you added all elements to the array, you must call
+ * [method(a)Json.Builder.end_array] to close the array.
+ *
+ * Return value: (nullable) (transfer none): the builder instance
+ */
+JsonBuilder *
+json_builder_begin_array (JsonBuilder *builder)
+{
+ JsonArray *array;
+ JsonBuilderState *state;
+ JsonBuilderState *cur_state;
+
+ g_return_val_if_fail (JSON_IS_BUILDER (builder), NULL);
+ g_return_val_if_fail (builder->priv->root == NULL, NULL);
+ g_return_val_if_fail (g_queue_is_empty (builder->priv->stack) || json_builder_is_valid_add_mode (builder), NULL);
+
+ array = json_array_new ();
+ cur_state = g_queue_peek_head (builder->priv->stack);
+ if (cur_state)
+ {
+ switch (cur_state->mode)
+ {
+ case JSON_BUILDER_MODE_ARRAY:
+ json_array_add_array_element (cur_state->data.array, json_array_ref (array));
+ break;
+
+ case JSON_BUILDER_MODE_MEMBER:
+ json_object_set_array_member (cur_state->data.object, cur_state->member_name, json_array_ref (array));
+ g_free (cur_state->member_name);
+ cur_state->member_name = NULL;
+ cur_state->mode = JSON_BUILDER_MODE_OBJECT;
+ break;
+
+ default:
+ g_assert_not_reached ();
+ }
+ }
+
+ state = g_slice_new (JsonBuilderState);
+ state->data.array = array;
+ state->mode = JSON_BUILDER_MODE_ARRAY;
+ g_queue_push_head (builder->priv->stack, state);
+
+ return builder;
+}
+
+/**
+ * json_builder_end_array:
+ * @builder: a builder
+ *
+ * Closes the array inside the given builder that was opened by the most
+ * recent call to [method(a)Json.Builder.begin_array].
+ *
+ * This function cannot be called after [method(a)Json.Builder.set_member_name].
+ *
+ * Return value: (nullable) (transfer none): the builder instance
+ */
+JsonBuilder *
+json_builder_end_array (JsonBuilder *builder)
+{
+ JsonBuilderState *state;
+
+ g_return_val_if_fail (JSON_IS_BUILDER (builder), NULL);
+ g_return_val_if_fail (!g_queue_is_empty (builder->priv->stack), NULL);
+ g_return_val_if_fail (json_builder_current_mode (builder) == JSON_BUILDER_MODE_ARRAY, NULL);
+
+ state = g_queue_pop_head (builder->priv->stack);
+
+ if (builder->priv->immutable)
+ json_array_seal (state->data.array);
+
+ if (g_queue_is_empty (builder->priv->stack))
+ {
+ builder->priv->root = json_node_new (JSON_NODE_ARRAY);
+ json_node_take_array (builder->priv->root, json_array_ref (state->data.array));
+
+ if (builder->priv->immutable)
+ json_node_seal (builder->priv->root);
+ }
+
+ json_builder_state_free (state);
+
+ return builder;
+}
+
+/**
+ * json_builder_set_member_name:
+ * @builder: a builder
+ * @member_name: the name of the member
+ *
+ * Sets the name of the member in an object.
+ *
+ * This function must be followed by of these functions:
+ *
+ * - [method(a)Json.Builder.add_value], to add a scalar value to the member
+ * - [method(a)Json.Builder.begin_object], to add an object to the member
+ * - [method(a)Json.Builder.begin_array], to add an array to the member
+ *
+ * This function can only be called within an open object.
+ *
+ * Return value: (nullable) (transfer none): the builder instance
+ */
+JsonBuilder *
+json_builder_set_member_name (JsonBuilder *builder,
+ const gchar *member_name)
+{
+ JsonBuilderState *state;
+
+ g_return_val_if_fail (JSON_IS_BUILDER (builder), NULL);
+ g_return_val_if_fail (member_name != NULL, NULL);
+ g_return_val_if_fail (!g_queue_is_empty (builder->priv->stack), NULL);
+ g_return_val_if_fail (json_builder_current_mode (builder) == JSON_BUILDER_MODE_OBJECT, NULL);
+
+ state = g_queue_peek_head (builder->priv->stack);
+ state->member_name = g_strdup (member_name);
+ state->mode = JSON_BUILDER_MODE_MEMBER;
+
+ return builder;
+}
+
+/**
+ * json_builder_add_value:
+ * @builder: a builder
+ * @node: (transfer full): the value of the member or element
+ *
+ * Adds a value to the currently open object member or array.
+ *
+ * If called after [method(a)Json.Builder.set_member_name], sets the given node
+ * as the value of the current member in the open object; otherwise, the node
+ * is appended to the elements of the open array.
+ *
+ * The builder will take ownership of the node.
+ *
+ * Return value: (nullable) (transfer none): the builder instance
+ */
+JsonBuilder *
+json_builder_add_value (JsonBuilder *builder,
+ JsonNode *node)
+{
+ JsonBuilderState *state;
+
+ g_return_val_if_fail (JSON_IS_BUILDER (builder), NULL);
+ g_return_val_if_fail (node != NULL, NULL);
+ g_return_val_if_fail (!g_queue_is_empty (builder->priv->stack), NULL);
+ g_return_val_if_fail (json_builder_is_valid_add_mode (builder), NULL);
+
+ state = g_queue_peek_head (builder->priv->stack);
+
+ if (builder->priv->immutable)
+ json_node_seal (node);
+
+ switch (state->mode)
+ {
+ case JSON_BUILDER_MODE_MEMBER:
+ json_object_set_member (state->data.object, state->member_name, node);
+ g_free (state->member_name);
+ state->member_name = NULL;
+ state->mode = JSON_BUILDER_MODE_OBJECT;
+ break;
+
+ case JSON_BUILDER_MODE_ARRAY:
+ json_array_add_element (state->data.array, node);
+ break;
+
+ default:
+ g_assert_not_reached ();
+ }
+
+ return builder;
+}
+
+/**
+ * json_builder_add_int_value:
+ * @builder: a builder
+ * @value: the value of the member or element
+ *
+ * Adds an integer value to the currently open object member or array.
+ *
+ * If called after [method(a)Json.Builder.set_member_name], sets the given value
+ * as the value of the current member in the open object; otherwise, the value
+ * is appended to the elements of the open array.
+ *
+ * See also: [method(a)Json.Builder.add_value]
+ *
+ * Return value: (nullable) (transfer none): the builder instance
+ */
+JsonBuilder *
+json_builder_add_int_value (JsonBuilder *builder,
+ gint64 value)
+{
+ JsonBuilderState *state;
+
+ g_return_val_if_fail (JSON_IS_BUILDER (builder), NULL);
+ g_return_val_if_fail (!g_queue_is_empty (builder->priv->stack), NULL);
+ g_return_val_if_fail (json_builder_is_valid_add_mode (builder), NULL);
+
+ state = g_queue_peek_head (builder->priv->stack);
+ switch (state->mode)
+ {
+ case JSON_BUILDER_MODE_MEMBER:
+ json_object_set_int_member (state->data.object, state->member_name, value);
+ g_free (state->member_name);
+ state->member_name = NULL;
+ state->mode = JSON_BUILDER_MODE_OBJECT;
+ break;
+
+ case JSON_BUILDER_MODE_ARRAY:
+ json_array_add_int_element (state->data.array, value);
+ break;
+
+ default:
+ g_assert_not_reached ();
+ }
+
+ return builder;
+}
+
+/**
+ * json_builder_add_double_value:
+ * @builder: a builder
+ * @value: the value of the member or element
+ *
+ * Adds a floating point value to the currently open object member or array.
+ *
+ * If called after [method(a)Json.Builder.set_member_name], sets the given value
+ * as the value of the current member in the open object; otherwise, the value
+ * is appended to the elements of the open array.
+ *
+ * See also: [method(a)Json.Builder.add_value]
+ *
+ * Return value: (nullable) (transfer none): the builder instance
+ */
+JsonBuilder *
+json_builder_add_double_value (JsonBuilder *builder,
+ gdouble value)
+{
+ JsonBuilderState *state;
+
+ g_return_val_if_fail (JSON_IS_BUILDER (builder), NULL);
+ g_return_val_if_fail (!g_queue_is_empty (builder->priv->stack), NULL);
+ g_return_val_if_fail (json_builder_is_valid_add_mode (builder), NULL);
+
+ sta@@ Diff output truncated at 100000 characters. @@
--------------
This E-Mail was brought to you by github_commit_mail.py (Source: https://github.com/geany/infrastructure).
Branch: refs/heads/master
Author: Jiří Techet <techet(a)gmail.com>
Committer: Jiří Techet <techet(a)gmail.com>
Date: Sun, 26 Jan 2025 20:44:23 UTC
Commit: e3849d8d92c915051b326a36eb0504e8ca2e012b
https://github.com/geany/geany-plugins/commit/e3849d8d92c915051b326a36eb050…
Log Message:
-----------
Add LSP plugin
Modified Paths:
--------------
MAINTAINERS
Makefile.am
README
build/geany-plugins.nsi
build/lsp.m4
configure.ac
lsp/AUTHORS
lsp/COPYING
lsp/ChangeLog
lsp/Makefile.am
lsp/NEWS
lsp/README
lsp/data/Makefile.am
lsp/data/lsp.conf
lsp/deps/Makefile.am
lsp/deps/json-glib/json-array.c
lsp/deps/json-glib/json-builder.c
lsp/deps/json-glib/json-builder.h
lsp/deps/json-glib/json-debug.c
lsp/deps/json-glib/json-debug.h
lsp/deps/json-glib/json-enum-types.c
lsp/deps/json-glib/json-enum-types.h
lsp/deps/json-glib/json-gboxed.c
lsp/deps/json-glib/json-generator.c
lsp/deps/json-glib/json-generator.h
lsp/deps/json-glib/json-glib.h
lsp/deps/json-glib/json-gobject-private.h
lsp/deps/json-glib/json-gobject.c
lsp/deps/json-glib/json-gobject.h
lsp/deps/json-glib/json-gvariant.c
lsp/deps/json-glib/json-gvariant.h
lsp/deps/json-glib/json-node.c
lsp/deps/json-glib/json-object.c
lsp/deps/json-glib/json-parser.c
lsp/deps/json-glib/json-parser.h
lsp/deps/json-glib/json-path.c
lsp/deps/json-glib/json-path.h
lsp/deps/json-glib/json-reader.c
lsp/deps/json-glib/json-reader.h
lsp/deps/json-glib/json-scanner.c
lsp/deps/json-glib/json-scanner.h
lsp/deps/json-glib/json-serializable.c
lsp/deps/json-glib/json-types-private.h
lsp/deps/json-glib/json-types.h
lsp/deps/json-glib/json-utils.c
lsp/deps/json-glib/json-utils.h
lsp/deps/json-glib/json-value.c
lsp/deps/json-glib/json-version-macros.h
lsp/deps/json-glib/json-version.h
lsp/deps/jsonrpc-glib/jsonrpc-client.c
lsp/deps/jsonrpc-glib/jsonrpc-client.h
lsp/deps/jsonrpc-glib/jsonrpc-glib.h
lsp/deps/jsonrpc-glib/jsonrpc-input-stream-private.h
lsp/deps/jsonrpc-glib/jsonrpc-input-stream.c
lsp/deps/jsonrpc-glib/jsonrpc-input-stream.h
lsp/deps/jsonrpc-glib/jsonrpc-marshalers.c
lsp/deps/jsonrpc-glib/jsonrpc-marshalers.h
lsp/deps/jsonrpc-glib/jsonrpc-message.c
lsp/deps/jsonrpc-glib/jsonrpc-message.h
lsp/deps/jsonrpc-glib/jsonrpc-output-stream.c
lsp/deps/jsonrpc-glib/jsonrpc-output-stream.h
lsp/deps/jsonrpc-glib/jsonrpc-server.c
lsp/deps/jsonrpc-glib/jsonrpc-server.h
lsp/deps/jsonrpc-glib/jsonrpc-version-macros.h
lsp/deps/jsonrpc-glib/jsonrpc-version.h
lsp/src/Makefile.am
lsp/src/lsp-autocomplete.c
lsp/src/lsp-autocomplete.h
lsp/src/lsp-code-lens.c
lsp/src/lsp-code-lens.h
lsp/src/lsp-command.c
lsp/src/lsp-command.h
lsp/src/lsp-diagnostics.c
lsp/src/lsp-diagnostics.h
lsp/src/lsp-extension.c
lsp/src/lsp-extension.h
lsp/src/lsp-format.c
lsp/src/lsp-format.h
lsp/src/lsp-goto-anywhere.c
lsp/src/lsp-goto-anywhere.h
lsp/src/lsp-goto-panel.c
lsp/src/lsp-goto-panel.h
lsp/src/lsp-goto.c
lsp/src/lsp-goto.h
lsp/src/lsp-highlight.c
lsp/src/lsp-highlight.h
lsp/src/lsp-hover.c
lsp/src/lsp-hover.h
lsp/src/lsp-log.c
lsp/src/lsp-log.h
lsp/src/lsp-main.c
lsp/src/lsp-progress.c
lsp/src/lsp-progress.h
lsp/src/lsp-rename.c
lsp/src/lsp-rename.h
lsp/src/lsp-rpc.c
lsp/src/lsp-rpc.h
lsp/src/lsp-selection-range.c
lsp/src/lsp-selection-range.h
lsp/src/lsp-semtokens.c
lsp/src/lsp-semtokens.h
lsp/src/lsp-server.c
lsp/src/lsp-server.h
lsp/src/lsp-signature.c
lsp/src/lsp-signature.h
lsp/src/lsp-symbol-kinds.c
lsp/src/lsp-symbol-kinds.h
lsp/src/lsp-symbol-tree.c
lsp/src/lsp-symbol-tree.h
lsp/src/lsp-symbol.c
lsp/src/lsp-symbol.h
lsp/src/lsp-symbols.c
lsp/src/lsp-symbols.h
lsp/src/lsp-sync.c
lsp/src/lsp-sync.h
lsp/src/lsp-utils.c
lsp/src/lsp-utils.h
lsp/src/lsp-workspace-folders.c
lsp/src/lsp-workspace-folders.h
lsp/src/spawn/lspunixinputstream.c
lsp/src/spawn/lspunixinputstream.h
lsp/src/spawn/lspunixoutputstream.c
lsp/src/spawn/lspunixoutputstream.h
lsp/src/spawn/spawn.c
lsp/src/spawn/spawn.h
po/POTFILES.in
po/POTFILES.skip
Modified: MAINTAINERS
7 lines changed, 7 insertions(+), 0 deletions(-)
===================================================================
@@ -194,6 +194,13 @@ M: Frank Lanitz <frank(a)frank.uvena.de>
W: http://plugins.geany.org/lipsum.html
S: Maintained
+lsp
+P: Jiří Techet <techet(a)gmail.com>
+g: @techee
+M: Jiří Techet <techet(a)gmail.com>
+W: http://plugins.geany.org/lsp.html
+S: Maintained
+
markdown
P: Matthew Brush <matt(a)geany.org>
g: @codebrainz
Modified: Makefile.am
4 lines changed, 4 insertions(+), 0 deletions(-)
===================================================================
@@ -109,6 +109,10 @@ if ENABLE_LIPSUM
SUBDIRS += lipsum
endif
+if ENABLE_LSP
+SUBDIRS += lsp
+endif
+
if ENABLE_MARKDOWN
SUBDIRS += markdown
endif
Modified: README
1 lines changed, 1 insertions(+), 0 deletions(-)
===================================================================
@@ -71,6 +71,7 @@ Available plugins are:
* ``latex`` -- the LaTeX plugin
* ``lineoperations`` -- simple line functions that can be applied to an open file
* ``lipsum`` -- the Lipsum plugin
+* ``lsp`` -- the LSP plugin
* ``markdown`` -- the Markdown plugin
* ``overview``-- the overview plugin
* ``pairtaghighlighter`` -- the PairTagHighlighter plugin
Modified: build/geany-plugins.nsi
1 lines changed, 1 insertions(+), 0 deletions(-)
===================================================================
@@ -198,6 +198,7 @@ Section Uninstall
Delete "$INSTDIR\lib\geany\keyrecord.dll"
Delete "$INSTDIR\lib\geany\lipsum.dll"
Delete "$INSTDIR\lib\geany\lineoperations.dll"
+ Delete "$INSTDIR\lib\geany\lsp.dll"
Delete "$INSTDIR\lib\geany\overview.dll"
Delete "$INSTDIR\lib\geany\pairtaghighlighter.dll"
Delete "$INSTDIR\lib\geany\pohelper.dll"
Modified: build/lsp.m4
39 lines changed, 39 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,39 @@
+AC_DEFUN([GP_CHECK_LSP],
+[
+ GP_ARG_DISABLE([LSP], [auto])
+
+ JSON_GLIB_PACKAGE_NAME=json-glib-1.0
+ JSON_GLIB_VERSION=1.10
+ JSONRPC_GLIB_PACKAGE_NAME=jsonrpc-glib-1.0
+ JSONRPC_GLIB_VERSION=3.44
+
+ AC_ARG_ENABLE(system-jsonrpc,
+ AC_HELP_STRING([--enable-system-jsonrpc],
+ [Force using system json-glib and jsonrpc-glib libraries for the LSP plugin. [[default=no]]]),,
+ enable_system_jsonrpc=no)
+
+ PKG_CHECK_MODULES([SYSTEM_JSONRPC],
+ [${JSON_GLIB_PACKAGE_NAME} >= ${JSON_GLIB_VERSION}
+ ${JSONRPC_GLIB_PACKAGE_NAME} >= ${JSONRPC_GLIB_VERSION}],
+ have_system_jsonrpc=yes
+ echo "Required system versions of json-glib and jsonrpc-glib found - using them.",
+ have_system_jsonrpc=no
+ echo "Required system versions of json-glib and jsonrpc-glib not found - using builtin versions.")
+
+ AS_IF([test x"$enable_system_jsonrpc" = "xyes" || test x"$have_system_jsonrpc" = "xyes"],
+ [GP_CHECK_PLUGIN_DEPS([LSP], [LSP],
+ [${JSON_GLIB_PACKAGE_NAME} >= ${JSON_GLIB_VERSION}
+ ${JSONRPC_GLIB_PACKAGE_NAME} >= ${JSONRPC_GLIB_VERSION}])],
+ [])
+
+ AM_CONDITIONAL(ENABLE_BUILTIN_JSONRPC, [ test x"$have_system_jsonrpc" = "xno" ])
+
+ GP_COMMIT_PLUGIN_STATUS([LSP])
+
+ AC_CONFIG_FILES([
+ lsp/Makefile
+ lsp/deps/Makefile
+ lsp/src/Makefile
+ lsp/data/Makefile
+ ])
+])
Modified: configure.ac
1 lines changed, 1 insertions(+), 0 deletions(-)
===================================================================
@@ -55,6 +55,7 @@ GP_CHECK_GITCHANGEBAR
GP_CHECK_KEYRECORD
GP_CHECK_LINEOPERATIONS
GP_CHECK_LIPSUM
+GP_CHECK_LSP
GP_CHECK_MARKDOWN
GP_CHECK_OVERVIEW
GP_CHECK_PAIRTAGHIGHLIGHTER
Modified: lsp/AUTHORS
1 lines changed, 1 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1 @@
+Jiří Techet <techet(a)gmail.com>
Modified: lsp/COPYING
340 lines changed, 340 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 51 Franklin St, 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 Library 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 St, 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 Library General
+Public License instead of this License.
Modified: lsp/ChangeLog
0 lines changed, 0 insertions(+), 0 deletions(-)
===================================================================
No diff available, check online
Modified: lsp/Makefile.am
4 lines changed, 4 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,4 @@
+include $(top_srcdir)/build/vars.auxfiles.mk
+
+SUBDIRS = deps src data
+plugin = lsp
Modified: lsp/NEWS
0 lines changed, 0 insertions(+), 0 deletions(-)
===================================================================
No diff available, check online
Modified: lsp/README
288 lines changed, 288 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,288 @@
+===
+LSP
+===
+
+.. contents::
+
+About
+=====
+
+LSP Client is a language server protocol client plugin that allows to run multiple
+language servers for various programming languages, making their functionality
+accessible to Geany.
+
+Configuration
+=============
+
+The plugin does not come bundled with any language server; these must
+be installed independently of the plugin. For installation and configuration
+instructions, please refer to the documentation of the specific servers you plan
+to use, as some may have specific requirements. Note that many language servers,
+such as ``clangd``, ``pylsp``, and ``gopls``, are often packaged by Linux
+distributions, making them easy to install and use.
+
+You can configure servers and other settings using the User configuration file,
+accessible from::
+
+ Tools->LSP Client->User configuration
+
+This file provides extensive information about all the settings options, so be
+sure to refer to it for more details. The default configuration file comes with
+pre-configured values for several language servers; other servers have to be
+added manually.
+
+By default, the LSP plugin is disabled unless explicitly enabled for a
+project under
+
+::
+
+ Project->Properties->LSP Client
+
+This behavior can be controlled by the first three configuration options in
+the ``[all]`` section of the configuration file.
+
+Language servers are started lazily, meaning they only launch when you switch
+a tab to a file with a filetype that has a corresponding LSP server configured.
+After the initial handshake between the client and server, you can check the
+result under
+
+::
+
+ Tools->LSP Client->Server Initialize Responses
+
+This file also provides information about the capabilities offered by the server;
+for more details, refer to:
+
+https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/
+
+In addition to the User configuration file, you can also create a per-project
+configuration file (which can also be shared by multiple projects). This file
+can be configured under the
+
+::
+
+ Project->Properties->LSP Client
+
+tab.
+
+Furthermore, the plugin offers a range of customizable keybindings, which can be
+configured from::
+
+ Edit->Preferences->Keybindings->LSP Client
+
+Usage
+=====
+
+This section provides an overview of the individual LSP features supported by
+the plugin, along with guidance on how to use them. You can enable or disable
+each feature in the configuration file, where you can also customize certain
+aspects of their behavior.
+
+Please note that not all language servers support every feature. For more
+information on the specific features supported by a language server, consult
+the server's documentation.
+
+Autocompletion
+--------------
+
+Autocompletion works similarly to Geany's autocompletion feature. You can
+configure keybindings triggering the autocompletion popup.
+
+Function signagure
+------------------
+
+When you type an open brace after a function name, the plugin displays the
+function's signature in a popup window similarly to Geany's behavior.
+
+Diagnostic messages
+-------------------
+
+LSP diagnostic messages typically include error messages or warnings from
+compilers, as well as messages from linters. These messages are highlighted in
+the code; the exact style of highlighting can be configured to suit your
+preferences. When you hover over the highlighted part with your mouse cursor,
+a popup window appears, providing additional details about the issue. It is
+also possible to display all diagnostic messages received from the server in
+the message window.
+
+Code actions
+------------
+
+Some servers offer auto-fixes of certain issues or various refactoring options.
+For instance, the ``clangd`` server displays ``fix available`` next to the issue
+in the hover popup window. To perform the auto-fix, right-click the line with
+the issue and select the corresponding option from the Commands submenu. This
+popup can also be invoked by a keybinding.
+
+Code lenses
+-----------
+
+Code lenses are executable commands that are specific to a particular piece of
+code. As Geany's Scintilla component limitations prevent these commands
+from being clickable and executable directly in the editor, they are accessible
+through the Commands submenu of the context menu, similarly to code actions.
+
+Semantic token type highlighting
+--------------------------------
+
+Language servers that provide semantic token support can be used to highlight
+types, such as class names, in the code. You can customize various aspects of
+how the results are visualized in the editor through the configuration file.
+
+Hover popup
+-----------
+
+The language server can be configured to display a popup window with detailed
+information about the symbol under the mouse cursor. However, as this feature
+can be slightly annoying, it is disabled by default. Alternatively, you can
+access this feature through a keybinding.
+
+Symbol tree
+-----------
+
+The LSP symbol tree tab in the sidebar, separate from Geany's Symbols tab,
+shows document symbols in a similar manner to the Geany's symbol tree feature.
+
+Go to symbol definition/declaration
+-----------------------------------
+
+Similarly to Geany, you can navigate to the symbol definition/declaration
+by control-clicking it in the document or by using the corresponding keybinding.
+This feature is also available from the context menu.
+
+Go to type definition
+---------------------
+
+This feature enables quick navigation to the definition of the type associated
+with the symbol under the cursor, such as the type of a variable. You can also
+access this feature from the context menu.
+
+Swap header/source
+------------------
+
+This is a non-standard clangd extension allowing quick swapping between a
+source file and the corresponding header. This feature is not supported by
+any other language server.
+
+Find references
+---------------
+
+This feature finds all references of the symbol under the cursor in the project.
+This feature is also accessible from the context menu.
+
+Find implementations
+--------------------
+
+This feature allows you to locate all classes that implement the interface under
+the cursor.
+
+Navigation to document/project symbols, files, and line numbers
+---------------------------------------------------------------
+
+The plugin provides a simple, VSCode-style panel for navigating your project.
+The
+
+::
+
+ Tools->LSP Client->Go to Anywhere
+
+command offers four types of navigation options:
+
+- Open files by typing their name directly in the entry
+- Navigate to symbols in the current document by prefixing the query with ``@``
+- Navigate to symbols across the entire project by prefixing the query with ``#``
+- Jump to a specific line in the current document by prefixing the query with ``:``
+
+The other related queries in the LSP Client menu (also accessible via a keybinding)
+simply pre-fill the prefix for you, but otherwise function identically.
+
+Code formatting
+---------------
+
+The code formatting feature allows you to format either the entire document or
+a selected portion of code, depending on the LSP server's support for this
+functionality. You can access this feature from the context menu.
+
+Identical symbol highlighting
+-----------------------------
+
+When you click on a symbol in the document, this feature highlights all its
+occurrences in the document. You can customize the highlighting style to your
+preference by configuring it in the configuration file. Also, it is possible
+to disable this feature to be performed automatically, but, instead, manually
+through a keybinding.
+
+Smart selection expanding/shrinking
+-----------------------------------
+
+This feature allows to expand the current text selection to contain the next
+upper syntactic element such as a parent block in programming languages or a
+parent tag in XML. Selection shrinking works in the opposite direction.
+
+Document symbol renaming
+------------------------
+
+This feature leverages the identical symbol highlighting described above to
+select all symbol occurrences, create multiple cursors at their positions in the
+document, and rename them simultaneously as you type. You can also access this
+feature from the context menu.
+
+Project-wide renaming
+---------------------
+
+After selecting Rename in Project from the context menu or the plugin menu,
+you can rename all symbols in the project.
+
+**Warning:** This feature has a potential to modify many files and language
+servers may not be completely reliable when performing the rename so be very
+cautious when using it. The plugin does not perform any additional
+checks and does not show any preview of the changes so it is best to use this
+feature only after committing all modified files so you can
+easily revert to a working state if needed. Since this is potentially a
+dangerous operation, to prevent accidental renames, the "Rename" button in the
+dialog is not selected by defalut and simply pressing enter just cancels the
+dialog.
+
+Limitations
+===========
+
+By design, the plugin communicates over stdin/stdout only, is responsible
+for launching and terminating the language server process, and supports only
+a single language server per file type.
+
+All of these limitations are addressed by the LSP proxy project available at
+https://github.com/techee/lsp-proxy and related issues should be directed there.
+
+License
+=======
+
+Geany LSP Client is distributed 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. A copy of this license
+can be found in the file COPYING included with the source code of this
+program.
+
+Downloads
+=========
+
+Geany LSP Client can be downloaded from the development repository available
+at https://github.com/techee/geany-lsp/. In addition, it is also distributed
+as part of the combined Geany Plugins release. For more information and
+downloads, please visit https://plugins.geany.org/geany-plugins/
+
+Development Code
+================
+
+Get the code from::
+
+ git clone https://github.com/techee/geany-lsp.git
+
+Ideas, questions, patches and bug reports
+=========================================
+
+Please direct all questions, bug reports and patches to the development
+repository at https://github.com/techee/geany-lsp/ and open the corresponding
+bug report or pull request there.
+
+2023-2024 by Jiří Techet
+techet(at)gmail(dot)com
Modified: lsp/data/Makefile.am
5 lines changed, 5 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,5 @@
+include $(top_srcdir)/build/vars.docs.mk
+
+plugin = lsp
+
+dist_plugindata_DATA = lsp.conf
Modified: lsp/data/lsp.conf
534 lines changed, 534 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,534 @@
+# The global configuration file, accessible through
+# Tools->LSP Client->Global Configuration, defines default values for various
+# configuration options.
+#
+# When accessing the user configuration file using
+# Tools->LSP Client->User Configuration, a copy of the global configuration file
+# is created in user's configuration directory in which users can override
+# various settings from the global configuration file.
+#
+# In addition, it is possible to create a project-wide configuration file used
+# for a single project or shared by multiple projects whose path can be
+# specified under Project->Properties->LSP Client->Configuration file. When such
+# a file is defined and the project is configured to use the project
+# configuration, this configuration file overrides the global configuration
+# instead of the user configuration file.
+#
+# Each configuration file may contain the [all] section which contains settings
+# common for all language servers, and several filetype-specific sections
+# containing settings specific for the given filetype. The names of these
+# sections are identical to the names defined in
+# Tools->Configuration Files->filetype_extensions.conf; for instance [Python]
+# for the Python programming language (case sensitive). Most of the options can
+# appear both in the [all] section and the filetype-specific sections except for
+# a few that make only sense in the filetype-specific section, like e.g. the
+# 'cmd' option containing the command that starts the server. Any option defined
+# in the filetype-specific section overrides identically named option defined in
+# the [all] section for that particular language server.
+#
+# Not all LSP features are supported by all LSP servers. To learn more about
+# what features are supported by the particular server you are trying to use,
+# you can check the result of the initial client-server handshake by going to
+# Tools->LSP Client->Server Initialize Responses (the server must be running
+# to see any result).
+#
+# All servers are automatically restarted when any of the configuration files
+# changes. Servers are started lazily after a tab is switched to a document for
+# which a server is configured (this means that restart typically means shutdown
+# of all servers after which they are started as needed).
+
+
+[all]
+# Defines whether the plugin should be enabled automatically for new or existing
+# projects (that have not yet been configured to use LSP). This option
+# is only valid in the [all] section
+enable_by_default=false
+# Defines whether the server should be used when no project is open. Servers
+# may not work correctly without a project because most of them need to know
+# the path to the project directory which corresponds to the path defined under
+# Project->Properties->Base path. This option can be partially overridden
+# by project_root_marker_patterns, see below
+use_without_project=false
+# Defines whether the server should be used for files whose path is not within
+# the project directory. This option can be partially overridden by
+# project_root_marker_patterns, see below
+use_outside_project_dir=false
+# A semicolon-separated list of glob patterns of files that are typically stored
+# inside the root directory of the project. Language servers supporting
+# changeNotifications of workspaceFolders (these two values should appear inside
+# the server initialize response) can use these marker files to detect root
+# project directories of open files. Starting from the open file directory,
+# the plugin goes up in the directory structure and tests whether a file
+# matching project_root_marker_patterns exists - if it does, such a directory
+# is considered to be the root directory of the project. This allows to
+# detect projects without any Geany project open and allows the plugin to work
+# on multiple projects simultaneously. Typically, the pattern contains
+# files/directories such as .git, configure.ac, go.mod, etc. If a pattern is
+# found, use_without_project and use_outside_project_dir are ignored
+project_root_marker_patterns=
+# In additon to standard identifier characters a-zA-Z0-9_, this configuration
+# option allows adding extra characters that can appear inside identifiers.
+# For instance $- will add '$' and '-' to the above set.
+extra_identifier_characters=
+# Some servers require that the initialization options configuration is sent
+# using workspace/didChangeConfiguration instead of the initialize request.
+# This option does this right after the initialize request completes.
+send_did_change_configuration=false
+
+# The number of keybindings that can be assigned to LSP code action commands.
+# This option is valid only within the [all] section and changing the value
+# requires either the plugin reload or Geany restart
+command_keybinding_num=5
+# When the keybinding Command 1 is invoked, it checks whether the
+# command_1_regex matches any of the items from the Commands submenu of the
+# context menu. The first matched entry is executed. For convenience, regex
+# matches are case insensitive. Up to command_keybinding_num command keybindings
+# can be specified this way
+command_1_regex=
+# Regex specifying which of the commands present in the context menu under the
+# Commands submenu will be automatically performed on save. If multiple entries
+# match, all of them will be performed. For convenience, regex matches are case
+# insensitive
+command_on_save_regex=
+
+# When the filetype-specific 'rpc_log' settings is defined, this option
+# specifies whether the log should contain all details including method
+# parameters, or just the method name and type of the communication
+rpc_log_full=false
+# Show server's stderr in Geany's stderr (when started from terminal)
+show_server_stderr=false
+# Tracing level of the server (when supported). When enabled, tracing messages
+# are logged into stdout. Valid values are 'off', 'messages', 'verbose'
+trace_value=off
+# Enables or disables telemetry notification logging to stdout
+telemetry_notifications=false
+
+# Whether LSP should be used for autocompletion
+autocomplete_enable=true
+# Servers return the label that can be shown in the autocompletion popup for
+# individual autocompletion entries, or it is possible to use just the text that
+# gets inserted when selecting the entry. See also autocomplete_use_snippets.
+autocomplete_use_label=true
+# Whether snippets should be shown in the autocompletion list. Snippet support
+# is only partial so things may not work as expected. When snippets are enabled,
+# it is recommended to use autocomplete_use_label=true, otherwise snippet
+# tab stops and other snippet information is shown in the autocompletion popup.
+autocomplete_use_snippets=false
+# Maximum number of autocompletion entries shown in the popup window (including
+# those that will only get visible after scrolling the contents)
+autocomplete_window_max_entries=20
+# Maximum number of autocompletion entries shown without scrolling (defining the
+# actual height of the popup)
+autocomplete_window_max_displayed=8
+# The maximum width of the autocompletion popup in displayed characters
+autocomplete_window_max_width=60
+# Whether to automatically apply additional edits defined for the autocompletion
+# entry. These are typically imports of the modules where the inserted symbol is
+# defined
+autocomplete_apply_additional_edits=false
+# Semicolon separated list of character sequences which can trigger
+# autocompletion. Normally, the server defines these but this option can be used
+# to further restrict the list only to some sequences if the server-provided
+# value does not work well (e.g. when server's trigger chars for autocompletion
+# clash with signature trigger chars - Rust server for instance uses '(' for
+# both and omitting '(' in autocomplete sequences shows signature instead)
+autocomplete_trigger_sequences=
+# Semicolon separated list of words that make the autocompletion popup hide.
+# This is useful for instance for languages like Pascal that use keywords
+# 'begin' and 'end' which are typically followed by a newline where typing enter
+# after these words might select some unwanted word from the autocompletion list.
+autocomplete_hide_after_words=
+# Whether to perform autocompletion inside strings
+autocomplete_in_strings=false
+# Show documentation (if available) of selected item in autocompletion popup
+# in Geany status bar
+autocomplete_show_documentation=true
+
+# Whether LSP should be used to display diagnostic messages. Typically these are
+# compiler errors or warnings
+diagnostics_enable=true
+# Semicolon-separated glob patterns specifying files for which diagnostic
+# messages are not shown. Useful when the server has a problem with some files
+diagnostics_disable_for=
+# For the statusbar issue number indicator, consider only issues of the
+# configured severity or highler. Valid values are: 1 (error), 2 (warning),
+# 3 (info), 4 (hint). E.g. setting this value to 2 will show issue number
+# for errors and warnings only.
+diagnostics_statusbar_severity=2
+# Defines the style of error diagnostics - visual style such as underline, and
+# its color. Empty value means that diagnostic messages of the given severity
+# are not displayed.
+# The first number is the "indicator index" of Scintilla - each style should
+# have a unique value from 8 to 31. Can be changed when the value clashes with
+# some other plugin.
+# The remaining values correspond to
+# SCI_INDICSETFORE; SCI_INDICSETALPHA; SCI_INDICSETOUTLINEALPHA; SCI_INDICSETSTYLE
+# - see Scintilla documentation for more information
+diagnostics_error_style=13;#ff3030;70;255;1
+# Defines the style of warning diagnostics
+diagnostics_warning_style=14;#ee00ee;70;255;1
+# Defines the style of information diagnostics
+diagnostics_info_style=15;#909090;70;255;14
+# Defines the style of hint diagnostics
+diagnostics_hint_style=16;#909090;70;255;14
+
+# Whether LSP should be used to show a popup with details when hovering over
+# symbols.
+hover_enable=false
+# Maximum number of lines of the popup window
+hover_popup_max_lines=20
+# Maximum number of paragraphs shown in the popup window
+hover_popup_max_paragraphs=1000
+
+# Whether LSP should be used to show function parameter signatures e.g. after
+# typing '('
+signature_enable=true
+
+# Whether LSP should be used for going to symbol definition/declaration
+goto_enable=true
+
+# Whether LSP should be used for displaying symbols in the sidebar (in a tab
+# separate from normal Geany symbols)
+document_symbols_enable=true
+# The label used for the LSP symbols tab. When left empty, the tab is not
+# displayed. This option is only valid in the [all] section
+document_symbols_tab_label=LSP Symbols
+
+# Whether LSP should be used for highlighting semantic tokens in the editor,
+# such as types. Most servers don't support this feature so disabled by default.
+semantic_tokens_enable=false
+# Always perform "full" semantic token request instead of using "delta"
+# requests. Can be used when servers don't support delta tokens correctly
+semantic_tokens_force_full=false
+# Semicolon-separated list of semantic tokens that should be highlighted as
+# types. For valid values, see
+# https://microsoft.github.io/language-server-protocol/specifications/lsp/3.1…
+semantic_tokens_types=type;class;enum;interface;struct
+# When not empty, Scintilla indicators are used for highlighting semantic
+# token types. See diagnostics_error_style for more details about the valid
+# values. Note that because of Scintilla limitations, this value cannot be bold
+#semantic_tokens_type_style=17;#00007f;255;255;17
+semantic_tokens_type_style=
+# When not using semantic_tokens_type_style, this indicates the index in the
+# Scintilla lexer used for custom keywords. This feature is supported only by
+# some lexers like C/C++ and derived lexers. When using this method, the
+# value can be bold but all the occurrences of the given word in the document
+# is highlighted regardless of the context in which it is used
+semantic_tokens_lexer_kw_index=3
+
+# Whether LSP should be used for highlighting all other uses of a variable under
+# cursor.
+highlighting_enable=true
+# Indicator style used for highlighting - see diagnostics_error_style
+highlighting_style=18;#b0b0b0;90;255;8
+
+# Whether LSP should be used for "code lenses" showing commands available
+# for the given line. After right-clicking the line with the code lens, these
+# commands are available in the Commands submenu.
+code_lens_enable=true
+# Defines the foreground and the background color of the code lens indicator.
+code_lens_style=#000000;#ffffa0
+
+# JSON file containing formatting options defined in
+# https://microsoft.github.io/language-server-protocol/specifications/lsp/3.1…
+# e.g. { "tabSize": 4, "insertSpaces": false }. Supported only by some language
+# servers.
+#formatting_options_file=/home/some_user/my_formatting_config_file.json
+formatting_options_file=
+# Like above but with the JSON placed directly into the value. When both
+# formatting_options_file and formatting_options are specified, the JSON from
+# formatting_options_file is used
+formatting_options={ "tabSize": 4, "insertSpaces": false }
+# Defines whether the LSP code-formatting feature should be auto-performed
+# on every save
+format_on_save=false
+
+# Show progress bar for work in progress server operations. Can be disabled
+# when servers do not correctly terminate progress notifications.
+progress_bar_enable=true
+
+# Enable non-standard clangd extension allowing to swap between C/C++ headers
+# and sources. Only usable for clangd, it does not work with other servers.
+swap_header_source_enable=false
+
+
+# This is a dummy language server configuration describing the available
+# language-specific options. Most of the configuration options from the [all]
+# section can be used here as well.
+# For an extensive list of various servers and their configurations, check
+# https://github.com/neovim/nvim-lspconfig/blob/master/doc/configs.md
+# While the configuration options names of neovim differ from Geany, the
+# general concepts are similar and applicable here.
+[DummyLanguage]
+# The command (including parameters and possibly also the full path) used to
+# start the LSP server. Instead of starting a new server, it is also possible to
+# reuse other language's server using the 'use' option - see the C++
+# configuration
+cmd=srvcmd
+# The server can be started with additional environment variables (such as foo
+# with the value bar, and foo1 with the value bar1 like in the example below).
+env=foo=bar;foo1=bar1
+# File containing initialization options of the server. The server is
+# automatically restarted when this file is modified from within Geany
+initialization_options_file=/home/some_user/init_options.json
+# Like above but with the JSON placed directly into the value. When both
+# initialization_options_file and formatting_options are specified, the JSON
+# from initialization_options_file is used
+initialization_options={"compilationDatabasePath": "/home/some_user/"}
+# When defined, performs logging to the specified file where all RPC
+# communication between the client plugin and the server will be stored (can
+# also be 'stdout' or 'stderr')
+rpc_log=stdout
+# Additional files and their mappings to LSP language IDs for which the server
+# is used as well. The Nth item in the list is always a LSP language ID and the
+# (N+1)th item is a glob pattern defining files for which the language ID is
+# used
+lang_id_mappings=dummylanguage;*.dummy
+
+
+[C]
+# By default, clangd expects compile_commands.json inside the 'build' directory
+# of your project. You can create it using either 'meson setup build' if your
+# project uses meson or e.g. using:
+# mkdir build; bear --output build/compile_commands.json -- make
+# if your project uses some other build tool (you need to install the bear tool
+# first). The compile_commands.json file has to be manually regenerated when
+# the build is modified in any way, such as a file is added/removed.
+cmd=clangd
+swap_header_source_enable=true
+autocomplete_in_strings=true
+autocomplete_use_label=false
+semantic_tokens_enable=true
+#initialization_options={"compilationDatabasePath": "/home/some_user/my_project/my_builddir"}
+formatting_options={ "tabSize": 4, "insertSpaces": false }
+command_1_regex=Apply fix:.*
+#rpc_log=stdout
+#rpc_log_full=true
+#show_server_stderr=true
+
+
+[C++]
+# Don't start a new server but reuse the server defined for some other language
+# instead (C server used for C++ in this case)
+use=C
+
+
+[CSS]
+cmd=vscode-css-language-server --stdio
+extra_identifier_characters=-
+send_did_change_configuration=true
+autocomplete_use_snippets=true
+use_without_project=true
+use_outside_project_dir=true
+#rpc_log=stdout
+#rpc_log_full=true
+#show_server_stderr=true
+
+
+[Dart]
+cmd=dart language-server --protocol=lsp
+# everything except ( which conflicts with signature help
+autocomplete_trigger_sequences=.;=;$;";';{;/;:
+semantic_tokens_enable=true
+#rpc_log=stdout
+#rpc_log_full=true
+#show_server_stderr=true
+
+
+[Go]
+cmd=gopls
+autocomplete_apply_additional_edits=true
+lang_id_mappings=go.mod;go.mod;go.sum;go.sum;gotmpl;*tmpl
+semantic_tokens_enable=true
+semantic_tokens_type_style=17;#00007f;255;255;17
+format_on_save=true
+command_on_save_regex=Organize Imports
+progress_bar_enable=false
+#rpc_log=stdout
+#rpc_log_full=true
+#show_server_stderr=true
+
+
+[Haskell]
+cmd=haskell-language-server-wrapper --lsp
+# Full semantic tokens work but are kind of useless as Scintilla already
+# highlights types
+semantic_tokens_enable=false
+#semantic_tokens_force_full=true
+#initialization_options={"plugin": {"semanticTokens": {"config": { }, "globalOn": true}}}
+#semantic_tokens_type_style=17;#00007f;255;255;17
+#rpc_log=stdout
+#rpc_log_full=true
+#show_server_stderr=true
+
+
+[HTML]
+cmd=vscode-html-language-server --stdio
+extra_identifier_characters=&
+send_did_change_configuration=true
+autocomplete_use_snippets=true
+use_without_project=true
+use_outside_project_dir=true
+#rpc_log=stdout
+#rpc_log_full=true
+#show_server_stderr=true
+
+
+[Java]
+cmd=jdtls
+autocomplete_use_label=false
+#semantic_tokens_enable=true
+#rpc_log=stdout
+#rpc_log_full=true
+#show_server_stderr=true
+
+
+[JSON]
+cmd=vscode-json-languageserver --stdio
+#initialization_options={"provideFormatter": true, "json": { "schemas": [ { "fileMatch": [ "*.json"], "url": "file:///home/parallels/schema.json"}]}}
+send_did_change_configuration=true
+autocomplete_use_snippets=true
+use_without_project=true
+use_outside_project_dir=true
+#formatting_options={ "tabSize": 4, "insertSpaces": true }
+#rpc_log=stdout
+#rpc_log_full=true
+#show_server_stderr=true
+
+
+[LaTeX]
+cmd=texlab
+autocomplete_use_snippets=true
+extra_identifier_characters=:
+use_without_project=true
+use_outside_project_dir=true
+#rpc_log=stdout
+#rpc_log_full=true
+#show_server_stderr=true
+
+
+[Lua]
+cmd=lua-language-server
+autocomplete_use_label=false
+autocomplete_hide_after_words=do;then;true;false;end;else
+use_outside_project_dir=true
+use_without_project=true
+#rpc_log=stdout
+#rpc_log_full=true
+#show_server_stderr=true
+
+
+[Nix]
+cmd=nil
+use_without_project=true
+use_outside_project_dir=true
+extra_identifier_characters=-'
+#rpc_log=stdout
+#rpc_log_full=true
+#show_server_stderr=true
+
+
+[PHP]
+# Note: Server returns highlighting indices off by 1 and highlighting doesn't work
+cmd=phpactor.phar language-server
+autocomplete_trigger_sequences=:;>;$;[;@;';\;\\
+extra_identifier_characters=$
+#rpc_log=stdout
+#rpc_log_full=true
+#show_server_stderr=true
+
+
+[Python]
+# pip install pyright (or: pipx install pyright)
+cmd=pyright-langserver --stdio
+cmd=pyright-langserver --stdio
+# alternatively pylsp, jedi, ruff
+#cmd=pylsp
+#cmd=jedi-language-server
+#cmd=ruff server
+use_outside_project_dir=true
+use_without_project=true
+#rpc_log=stdout
+#rpc_log_full=true
+#show_server_stderr=true
+
+
+[Ruby]
+cmd=solargraph stdio
+#rpc_log=stdout
+#rpc_log_full=true
+#show_server_stderr=true
+
+
+[Rust]
+cmd=rust-analyzer
+semantic_tokens_enable=true
+autocomplete_trigger_sequences=:;.;'
+#rpc_log=stdout
+#rpc_log_full=true
+#show_server_stderr=true
+
+
+[Sh]
+cmd=bash-language-server start
+autocomplete_use_snippets=true
+use_outside_project_dir=true
+use_without_project=true
+#rpc_log=stdout
+#rpc_log_full=true
+#show_server_stderr=true
+
+
+[TypeScript]
+cmd=typescript-language-server --stdio
+semantic_tokens_enable=true
+use_outside_project_dir=true
+use_without_project=true
+#rpc_log=stdout
+#rpc_log_full=true
+#show_server_stderr=true
+
+
+[Javascript]
+use=TypeScript
+
+
+[XML]
+cmd=lemminx
+autocomplete_use_snippets=true
+diagnostics_statusbar_severity=4
+use_without_project=true
+use_outside_project_dir=true
+autocomplete_in_strings=true
+# see https://github.com/eclipse/lemminx/blob/main/docs/Configuration.md
+#initialization_options_file=/home/some_user/init_options.json
+#formatting_options={ "tabSize": 4, "insertSpaces": true }
+#rpc_log=stdout
+#rpc_log_full=true
+#show_server_stderr=true
+
+
+[YAML]
+cmd=yaml-language-server --stdio
+#initialization_options={"yaml": {"schemas": { "/home/parallels/schema.json": "*"}}}
+use_without_project=true
+use_outside_project_dir=true
+#formatting_options={ "tabSize": 4, "insertSpaces": true }
+#rpc_log=stdout
+#rpc_log_full=true
+#show_server_stderr=true
+
+
+[Zig]
+cmd=zls
+semantic_tokens_enable=true
+#autocomplete_use_snippets=true
+#rpc_log=stdout
+#rpc_log_full=true
+#show_server_stderr=true
+
+
+# TODO: help needed! Only the above defined language servers have been tested
+# (lightly). If you know some other working language server or find a problem
+# with the settings above, please open an issue report or a pull request
+# on Github.
Modified: lsp/deps/Makefile.am
78 lines changed, 78 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,78 @@
+include $(top_srcdir)/build/vars.build.mk
+
+noinst_LTLIBRARIES = libjsonrpc.la
+
+json_glib_srcs = \
+ json-glib/json-array.c \
+ json-glib/json-builder.c \
+ json-glib/json-builder.h \
+ json-glib/json-debug.c \
+ json-glib/json-debug.h \
+ json-glib/json-enum-types.c \
+ json-glib/json-enum-types.h \
+ json-glib/json-gboxed.c \
+ json-glib/json-generator.c \
+ json-glib/json-generator.h \
+ json-glib/json-glib.h \
+ json-glib/json-gobject.c \
+ json-glib/json-gobject.h \
+ json-glib/json-gobject-private.h \
+ json-glib/json-gvariant.c \
+ json-glib/json-gvariant.h \
+ json-glib/json-node.c \
+ json-glib/json-object.c \
+ json-glib/json-parser.c \
+ json-glib/json-parser.h \
+ json-glib/json-path.c \
+ json-glib/json-path.h \
+ json-glib/json-reader.c \
+ json-glib/json-reader.h \
+ json-glib/json-scanner.c \
+ json-glib/json-scanner.h \
+ json-glib/json-serializable.c \
+ json-glib/json-types.h \
+ json-glib/json-types-private.h \
+ json-glib/json-utils.c \
+ json-glib/json-utils.h \
+ json-glib/json-value.c \
+ json-glib/json-version.h \
+ json-glib/json-version-macros.h
+
+jsonrpc_glib_srcs = \
+ jsonrpc-glib/jsonrpc-client.c \
+ jsonrpc-glib/jsonrpc-client.h \
+ jsonrpc-glib/jsonrpc-glib.h \
+ jsonrpc-glib/jsonrpc-input-stream.c \
+ jsonrpc-glib/jsonrpc-input-stream.h \
+ jsonrpc-glib/jsonrpc-input-stream-private.h \
+ jsonrpc-glib/jsonrpc-marshalers.c \
+ jsonrpc-glib/jsonrpc-marshalers.h \
+ jsonrpc-glib/jsonrpc-message.c \
+ jsonrpc-glib/jsonrpc-message.h \
+ jsonrpc-glib/jsonrpc-output-stream.c \
+ jsonrpc-glib/jsonrpc-output-stream.h \
+ jsonrpc-glib/jsonrpc-server.c \
+ jsonrpc-glib/jsonrpc-server.h \
+ jsonrpc-glib/jsonrpc-version.h \
+ jsonrpc-glib/jsonrpc-version-macros.h
+
+if ENABLE_BUILTIN_JSONRPC
+
+libjsonrpc_la_SOURCES = \
+ $(json_glib_srcs) \
+ $(jsonrpc_glib_srcs)
+
+libjsonrpc_la_CPPFLAGS = $(AM_CPPFLAGS) \
+ -DG_LOG_DOMAIN=\"LSP\" \
+ -DJSON_COMPILATION \
+ -DJSONRPC_GLIB_COMPILATION \
+ -I$(top_srcdir)/lsp/deps/json-glib \
+ -I$(top_srcdir)/lsp/deps/jsonrpc-glib
+libjsonrpc_la_CFLAGS = $(AM_CFLAGS)
+
+# do not enable cppcheck for json-glib or jsonrpc-glib as it generates lots of
+# false positives and it's not "our" code anyway
+#
+# include $(top_srcdir)/build/cppcheck.mk
+
+endif
Modified: lsp/deps/json-glib/json-array.c
838 lines changed, 838 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,838 @@
+/* json-array.c - JSON array implementation
+ *
+ * This file is part of JSON-GLib
+ * Copyright (C) 2007 OpenedHand Ltd.
+ * Copyright (C) 2009 Intel Corp.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author:
+ * Emmanuele Bassi <ebassi(a)linux.intel.com>
+ */
+
+#include "config.h"
+
+#include "json-types-private.h"
+
+/**
+ * JsonArray:
+ *
+ * `JsonArray` is the representation of the array type inside JSON.
+ *
+ * A `JsonArray` contains [struct(a)Json.Node] elements, which may contain
+ * fundamental types, other arrays or objects.
+ *
+ * Since arrays can be arbitrarily big, copying them can be expensive; for
+ * this reason, they are reference counted. You can control the lifetime of
+ * a `JsonArray` using [method(a)Json.Array.ref] and [method(a)Json.Array.unref].
+ *
+ * To append an element, use [method(a)Json.Array.add_element].
+ *
+ * To extract an element at a given index, use [method(a)Json.Array.get_element].
+ *
+ * To retrieve the entire array in list form, use [method(a)Json.Array.get_elements].
+ *
+ * To retrieve the length of the array, use [method(a)Json.Array.get_length].
+ */
+
+G_DEFINE_BOXED_TYPE (JsonArray, json_array, json_array_ref, json_array_unref);
+
+/**
+ * json_array_new: (constructor)
+ *
+ * Creates a new array.
+ *
+ * Return value: (transfer full): the newly created array
+ */
+JsonArray *
+json_array_new (void)
+{
+ JsonArray *array;
+
+ array = g_slice_new0 (JsonArray);
+
+ array->ref_count = 1;
+ array->elements = g_ptr_array_new ();
+
+ return array;
+}
+
+/**
+ * json_array_sized_new: (constructor)
+ * @n_elements: number of slots to pre-allocate
+ *
+ * Creates a new array with `n_elements` slots already allocated.
+ *
+ * Return value: (transfer full): the newly created array
+ */
+JsonArray *
+json_array_sized_new (guint n_elements)
+{
+ JsonArray *array;
+
+ array = g_slice_new0 (JsonArray);
+
+ array->ref_count = 1;
+ array->elements = g_ptr_array_sized_new (n_elements);
+
+ return array;
+}
+
+/**
+ * json_array_ref:
+ * @array: the array to reference
+ *
+ * Acquires a reference on the given array.
+ *
+ * Return value: (transfer none): the passed array, with the reference count
+ * increased by one
+ */
+JsonArray *
+json_array_ref (JsonArray *array)
+{
+ g_return_val_if_fail (array != NULL, NULL);
+ g_return_val_if_fail (array->ref_count > 0, NULL);
+
+ array->ref_count++;
+
+ return array;
+}
+
+/**
+ * json_array_unref:
+ * @array: the array to unreference
+ *
+ * Releases a reference on the given array.
+ *
+ * If the reference count reaches zero, the array is destroyed and all
+ * its allocated resources are freed.
+ */
+void
+json_array_unref (JsonArray *array)
+{
+ g_return_if_fail (array != NULL);
+ g_return_if_fail (array->ref_count > 0);
+
+ if (--array->ref_count == 0)
+ {
+ guint i;
+
+ for (i = 0; i < array->elements->len; i++)
+ json_node_unref (g_ptr_array_index (array->elements, i));
+
+ g_ptr_array_free (array->elements, TRUE);
+ array->elements = NULL;
+
+ g_slice_free (JsonArray, array);
+ }
+}
+
+/**
+ * json_array_seal:
+ * @array: the array to seal
+ *
+ * Seals the given array, making it immutable to further changes.
+ *
+ * This function will recursively seal all elements in the array too.
+ *
+ * If the `array` is already immutable, this is a no-op.
+ *
+ * Since: 1.2
+ */
+void
+json_array_seal (JsonArray *array)
+{
+ guint i;
+
+ g_return_if_fail (array != NULL);
+ g_return_if_fail (array->ref_count > 0);
+
+ if (array->immutable)
+ return;
+
+ /* Propagate to all members. */
+ for (i = 0; i < array->elements->len; i++)
+ json_node_seal (g_ptr_array_index (array->elements, i));
+
+ array->immutable_hash = json_array_hash (array);
+ array->immutable = TRUE;
+}
+
+/**
+ * json_array_is_immutable:
+ * @array: a JSON array
+ *
+ * Check whether the given `array` has been marked as immutable by calling
+ * [method(a)Json.Array.seal] on it.
+ *
+ * Since: 1.2
+ * Returns: %TRUE if the array is immutable
+ */
+gboolean
+json_array_is_immutable (JsonArray *array)
+{
+ g_return_val_if_fail (array != NULL, FALSE);
+ g_return_val_if_fail (array->ref_count > 0, FALSE);
+
+ return array->immutable;
+}
+
+/**
+ * json_array_get_elements:
+ * @array: a JSON array
+ *
+ * Retrieves all the elements of an array as a list of nodes.
+ *
+ * Return value: (element-type JsonNode) (transfer container) (nullable): the elements
+ * of the array
+ */
+GList *
+json_array_get_elements (JsonArray *array)
+{
+ GList *retval;
+ guint i;
+
+ g_return_val_if_fail (array != NULL, NULL);
+
+ retval = NULL;
+ for (i = 0; i < array->elements->len; i++)
+ retval = g_list_prepend (retval,
+ g_ptr_array_index (array->elements, i));
+
+ return g_list_reverse (retval);
+}
+
+/**
+ * json_array_dup_element:
+ * @array: a JSON array
+ * @index_: the index of the element to retrieve
+ *
+ * Retrieves a copy of the element at the given position in the array.
+ *
+ * Return value: (transfer full): a copy of the element at the given position
+ *
+ * Since: 0.6
+ */
+JsonNode *
+json_array_dup_element (JsonArray *array,
+ guint index_)
+{
+ JsonNode *retval;
+
+ g_return_val_if_fail (array != NULL, NULL);
+ g_return_val_if_fail (index_ < array->elements->len, NULL);
+
+ retval = json_array_get_element (array, index_);
+ if (!retval)
+ return NULL;
+
+ return json_node_copy (retval);
+}
+
+/**
+ * json_array_get_element:
+ * @array: a JSON array
+ * @index_: the index of the element to retrieve
+ *
+ * Retrieves the element at the given position in the array.
+ *
+ * Return value: (transfer none): the element at the given position
+ */
+JsonNode *
+json_array_get_element (JsonArray *array,
+ guint index_)
+{
+ g_return_val_if_fail (array != NULL, NULL);
+ g_return_val_if_fail (index_ < array->elements->len, NULL);
+
+ return g_ptr_array_index (array->elements, index_);
+}
+
+/**
+ * json_array_get_int_element:
+ * @array: a JSON array
+ * @index_: the index of the element to retrieve
+ *
+ * Conveniently retrieves the integer value of the element at the given
+ * position inside an array.
+ *
+ * See also: [method(a)Json.Array.get_element], [method(a)Json.Node.get_int]
+ *
+ * Return value: the integer value
+ *
+ * Since: 0.8
+ */
+gint64
+json_array_get_int_element (JsonArray *array,
+ guint index_)
+{
+ JsonNode *node;
+
+ g_return_val_if_fail (array != NULL, 0);
+ g_return_val_if_fail (index_ < array->elements->len, 0);
+
+ node = g_ptr_array_index (array->elements, index_);
+ g_return_val_if_fail (node != NULL, 0);
+ g_return_val_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_VALUE, 0);
+
+ return json_node_get_int (node);
+}
+
+/**
+ * json_array_get_double_element:
+ * @array: a JSON array
+ * @index_: the index of the element to retrieve
+ *
+ * Conveniently retrieves the floating point value of the element at
+ * the given position inside an array.
+ *
+ * See also: [method(a)Json.Array.get_element], [method(a)Json.Node.get_double]
+ *
+ * Return value: the floating point value
+ *
+ * Since: 0.8
+ */
+gdouble
+json_array_get_double_element (JsonArray *array,
+ guint index_)
+{
+ JsonNode *node;
+
+ g_return_val_if_fail (array != NULL, 0.0);
+ g_return_val_if_fail (index_ < array->elements->len, 0.0);
+
+ node = g_ptr_array_index (array->elements, index_);
+ g_return_val_if_fail (node != NULL, 0.0);
+ g_return_val_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_VALUE, 0.0);
+
+ return json_node_get_double (node);
+}
+
+/**
+ * json_array_get_boolean_element:
+ * @array: a JSON array
+ * @index_: the index of the element to retrieve
+ *
+ * Conveniently retrieves the boolean value of the element at the given
+ * position inside an array.
+ *
+ * See also: [method(a)Json.Array.get_element], [method(a)Json.Node.get_boolean]
+ *
+ * Return value: the boolean value
+ *
+ * Since: 0.8
+ */
+gboolean
+json_array_get_boolean_element (JsonArray *array,
+ guint index_)
+{
+ JsonNode *node;
+
+ g_return_val_if_fail (array != NULL, FALSE);
+ g_return_val_if_fail (index_ < array->elements->len, FALSE);
+
+ node = g_ptr_array_index (array->elements, index_);
+ g_return_val_if_fail (node != NULL, FALSE);
+ g_return_val_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_VALUE, FALSE);
+
+ return json_node_get_boolean (node);
+}
+
+/**
+ * json_array_get_string_element:
+ * @array: a JSON array
+ * @index_: the index of the element to retrieve
+ *
+ * Conveniently retrieves the string value of the element at the given
+ * position inside an array.
+ *
+ * See also: [method(a)Json.Array.get_element], [method(a)Json.Node.get_string]
+ *
+ * Return value: (transfer none): the string value
+ *
+ * Since: 0.8
+ */
+const gchar *
+json_array_get_string_element (JsonArray *array,
+ guint index_)
+{
+ JsonNode *node;
+
+ g_return_val_if_fail (array != NULL, NULL);
+ g_return_val_if_fail (index_ < array->elements->len, NULL);
+
+ node = g_ptr_array_index (array->elements, index_);
+ g_return_val_if_fail (node != NULL, NULL);
+ g_return_val_if_fail (JSON_NODE_HOLDS_VALUE (node) || JSON_NODE_HOLDS_NULL (node), NULL);
+
+ if (JSON_NODE_HOLDS_NULL (node))
+ return NULL;
+
+ return json_node_get_string (node);
+}
+
+/**
+ * json_array_get_null_element:
+ * @array: a JSON array
+ * @index_: the index of the element to retrieve
+ *
+ * Conveniently checks whether the element at the given position inside the
+ * array contains a `null` value.
+ *
+ * See also: [method(a)Json.Array.get_element], [method(a)Json.Node.is_null]
+ *
+ * Return value: `TRUE` if the element is `null`
+ *
+ * Since: 0.8
+ */
+gboolean
+json_array_get_null_element (JsonArray *array,
+ guint index_)
+{
+ JsonNode *node;
+
+ g_return_val_if_fail (array != NULL, FALSE);
+ g_return_val_if_fail (index_ < array->elements->len, FALSE);
+
+ node = g_ptr_array_index (array->elements, index_);
+ g_return_val_if_fail (node != NULL, FALSE);
+
+ if (JSON_NODE_HOLDS_NULL (node))
+ return TRUE;
+
+ if (JSON_NODE_HOLDS_ARRAY (node))
+ return json_node_get_array (node) == NULL;
+
+ if (JSON_NODE_HOLDS_OBJECT (node))
+ return json_node_get_object (node) == NULL;
+
+ return FALSE;
+}
+
+/**
+ * json_array_get_array_element:
+ * @array: a JSON array
+ * @index_: the index of the element to retrieve
+ *
+ * Conveniently retrieves the array at the given position inside an array.
+ *
+ * See also: [method(a)Json.Array.get_element], [method(a)Json.Node.get_array]
+ *
+ * Return value: (transfer none): the array
+ *
+ * Since: 0.8
+ */
+JsonArray *
+json_array_get_array_element (JsonArray *array,
+ guint index_)
+{
+ JsonNode *node;
+
+ g_return_val_if_fail (array != NULL, NULL);
+ g_return_val_if_fail (index_ < array->elements->len, NULL);
+
+ node = g_ptr_array_index (array->elements, index_);
+ g_return_val_if_fail (node != NULL, NULL);
+ g_return_val_if_fail (JSON_NODE_HOLDS_ARRAY (node) || JSON_NODE_HOLDS_NULL (node), NULL);
+
+ if (JSON_NODE_HOLDS_NULL (node))
+ return NULL;
+
+ return json_node_get_array (node);
+}
+
+/**
+ * json_array_get_object_element:
+ * @array: a JSON array
+ * @index_: the index of the element to retrieve
+ *
+ * Conveniently retrieves the object at the given position inside an array.
+ *
+ * See also: [method(a)Json.Array.get_element], [method(a)Json.Node.get_object]
+ *
+ * Return value: (transfer none): the object
+ *
+ * Since: 0.8
+ */
+JsonObject *
+json_array_get_object_element (JsonArray *array,
+ guint index_)
+{
+ JsonNode *node;
+
+ g_return_val_if_fail (array != NULL, NULL);
+ g_return_val_if_fail (index_ < array->elements->len, NULL);
+
+ node = g_ptr_array_index (array->elements, index_);
+ g_return_val_if_fail (node != NULL, NULL);
+ g_return_val_if_fail (JSON_NODE_HOLDS_OBJECT (node) || JSON_NODE_HOLDS_NULL (node), NULL);
+
+ if (JSON_NODE_HOLDS_NULL (node))
+ return NULL;
+
+ return json_node_get_object (node);
+}
+
+/**
+ * json_array_get_length:
+ * @array: a JSON array
+ *
+ * Retrieves the length of the given array
+ *
+ * Return value: the length of the array
+ */
+guint
+json_array_get_length (JsonArray *array)
+{
+ g_return_val_if_fail (array != NULL, 0);
+
+ return array->elements->len;
+}
+
+/**
+ * json_array_add_element:
+ * @array: a JSON array
+ * @node: (transfer full): the element to add
+ *
+ * Appends the given `node` inside an array.
+ */
+void
+json_array_add_element (JsonArray *array,
+ JsonNode *node)
+{
+ g_return_if_fail (array != NULL);
+ g_return_if_fail (node != NULL);
+
+ g_ptr_array_add (array->elements, node);
+}
+
+/**
+ * json_array_add_int_element:
+ * @array: a JSON array
+ * @value: the integer value to add
+ *
+ * Conveniently adds the given integer value into an array.
+ *
+ * See also: [method(a)Json.Array.add_element], [method(a)Json.Node.set_int]
+ *
+ * Since: 0.8
+ */
+void
+json_array_add_int_element (JsonArray *array,
+ gint64 value)
+{
+ g_return_if_fail (array != NULL);
+
+ json_array_add_element (array, json_node_init_int (json_node_alloc (), value));
+}
+
+/**
+ * json_array_add_double_element:
+ * @array: a JSON array
+ * @value: the floating point value to add
+ *
+ * Conveniently adds the given floating point value into an array.
+ *
+ * See also: [method(a)Json.Array.add_element], [method(a)Json.Node.set_double]
+ *
+ * Since: 0.8
+ */
+void
+json_array_add_double_element (JsonArray *array,
+ gdouble value)
+{
+ g_return_if_fail (array != NULL);
+
+ json_array_add_element (array, json_node_init_double (json_node_alloc (), value));
+}
+
+/**
+ * json_array_add_boolean_element:
+ * @array: a JSON array
+ * @value: the boolean value to add
+ *
+ * Conveniently adds the given boolean value into an array.
+ *
+ * See also: [method(a)Json.Array.add_element], [method(a)Json.Node.set_boolean]
+ *
+ * Since: 0.8
+ */
+void
+json_array_add_boolean_element (JsonArray *array,
+ gboolean value)
+{
+ g_return_if_fail (array != NULL);
+
+ json_array_add_element (array, json_node_init_boolean (json_node_alloc (), value));
+}
+
+/**
+ * json_array_add_string_element:
+ * @array: a JSON array
+ * @value: the string value to add
+ *
+ * Conveniently adds the given string value into an array.
+ *
+ * See also: [method(a)Json.Array.add_element], [method(a)Json.Node.set_string]
+ *
+ * Since: 0.8
+ */
+void
+json_array_add_string_element (JsonArray *array,
+ const gchar *value)
+{
+ JsonNode *node;
+
+ g_return_if_fail (array != NULL);
+
+ node = json_node_alloc ();
+
+ if (value != NULL)
+ json_node_init_string (node, value);
+ else
+ json_node_init_null (node);
+
+ json_array_add_element (array, node);
+}
+
+/**
+ * json_array_add_null_element:
+ * @array: a JSON array
+ *
+ * Conveniently adds a `null` element into an array
+ *
+ * See also: [method(a)Json.Array.add_element], `JSON_NODE_NULL`
+ *
+ * Since: 0.8
+ */
+void
+json_array_add_null_element (JsonArray *array)
+{
+ g_return_if_fail (array != NULL);
+
+ json_array_add_element (array, json_node_init_null (json_node_alloc ()));
+}
+
+/**
+ * json_array_add_array_element:
+ * @array: a JSON array
+ * @value: (nullable) (transfer full): the array to add
+ *
+ * Conveniently adds an array element into an array.
+ *
+ * If `value` is `NULL`, a `null` element will be added instead.
+ *
+ * See also: [method(a)Json.Array.add_element], [method(a)Json.Node.take_array]
+ *
+ * Since: 0.8
+ */
+void
+json_array_add_array_element (JsonArray *array,
+ JsonArray *value)
+{
+ JsonNode *node;
+
+ g_return_if_fail (array != NULL);
+
+ node = json_node_alloc ();
+
+ if (value != NULL)
+ {
+ json_node_init_array (node, value);
+ json_array_unref (value);
+ }
+ else
+ json_node_init_null (node);
+
+ json_array_add_element (array, node);
+}
+
+/**
+ * json_array_add_object_element:
+ * @array: a JSON array
+ * @value: (transfer full) (nullable): the object to add
+ *
+ * Conveniently adds an object into an array.
+ *
+ * If `value` is `NULL`, a `null` element will be added instead.
+ *
+ * See also: [method(a)Json.Array.add_element], [method(a)Json.Node.take_object]
+ *
+ * Since: 0.8
+ */
+void
+json_array_add_object_element (JsonArray *array,
+ JsonObject *value)
+{
+ JsonNode *node;
+
+ g_return_if_fail (array != NULL);
+
+ node = json_node_alloc ();
+
+ if (value != NULL)
+ {
+ json_node_init_object (node, value);
+ json_object_unref (value);
+ }
+ else
+ json_node_init_null (node);
+
+ json_array_add_element (array, node);
+}
+
+/**
+ * json_array_remove_element:
+ * @array: a JSON array
+ * @index_: the position of the element to be removed
+ *
+ * Removes the element at the given position inside an array.
+ *
+ * This function will release the reference held on the element.
+ */
+void
+json_array_remove_element (JsonArray *array,
+ guint index_)
+{
+ g_return_if_fail (array != NULL);
+ g_return_if_fail (index_ < array->elements->len);
+
+ json_node_unref (g_ptr_array_remove_index (array->elements, index_));
+}
+
+/**
+ * json_array_foreach_element:
+ * @array: a JSON array
+ * @func: (scope call): the function to be called on each element
+ * @data: (closure): data to be passed to the function
+ *
+ * Iterates over all elements of an array, and calls a function on
+ * each one of them.
+ *
+ * It is safe to change the value of an element of the array while
+ * iterating over it, but it is not safe to add or remove elements
+ * from the array.
+ *
+ * Since: 0.8
+ */
+void
+json_array_foreach_element (JsonArray *array,
+ JsonArrayForeach func,
+ gpointer data)
+{
+ g_return_if_fail (array != NULL);
+ g_return_if_fail (func != NULL);
+
+ for (guint i = 0; i < array->elements->len; i++)
+ {
+ JsonNode *element_node;
+
+ element_node = g_ptr_array_index (array->elements, i);
+
+ (* func) (array, i, element_node, data);
+ }
+}
+
+/**
+ * json_array_hash:
+ * @key: (type JsonArray) (not nullable): a JSON array to hash
+ *
+ * Calculates a hash value for the given `key`.
+ *
+ * The hash is calculated over the array and all its elements, recursively.
+ *
+ * If the array is immutable, this is a fast operation; otherwise, it scales
+ * proportionally with the length of the array.
+ *
+ * Returns: hash value for the key
+ * Since: 1.2
+ */
+guint
+json_array_hash (gconstpointer key)
+{
+ JsonArray *array; /* unowned */
+ guint hash = 0;
+ guint i;
+
+ g_return_val_if_fail (key != NULL, 0);
+
+ array = (JsonArray *) key;
+
+ /* If the array is immutable, we can use the calculated hash. */
+ if (array->immutable)
+ return array->immutable_hash;
+
+ /* Otherwise, calculate the hash. */
+ for (i = 0; i < array->elements->len; i++)
+ {
+ JsonNode *node = g_ptr_array_index (array->elements, i);
+ hash ^= (i ^ json_node_hash (node));
+ }
+
+ return hash;
+}
+
+/**
+ * json_array_equal:
+ * @a: (type JsonArray) (not nullable): a JSON array
+ * @b: (type JsonArray) (not nullable): another JSON array
+ *
+ * Check whether two arrays are equal.
+ *
+ * Equality is defined as:
+ *
+ * - the array have the same number of elements
+ * - the values of elements in corresponding positions are equal
+ *
+ * Returns: `TRUE` if the arrays are equal, and `FALSE` otherwise
+ * Since: 1.2
+ */
+gboolean
+json_array_equal (gconstpointer a,
+ gconstpointer b)
+{
+ JsonArray *array_a, *array_b; /* unowned */
+ guint length_a, length_b, i;
+
+ g_return_val_if_fail (a != NULL, FALSE);
+ g_return_val_if_fail (b != NULL, FALSE);
+
+ array_a = (JsonArray *) a;
+ array_b = (JsonArray *) b;
+
+ /* Identity comparison. */
+ if (array_a == array_b)
+ return TRUE;
+
+ /* Check lengths. */
+ length_a = json_array_get_length (array_a);
+ length_b = json_array_get_length (array_b);
+
+ if (length_a != length_b)
+ return FALSE;
+
+ /* Check elements. */
+ for (i = 0; i < length_a; i++)
+ {
+ JsonNode *child_a, *child_b; /* unowned */
+
+ child_a = json_array_get_element (array_a, i);
+ child_b = json_array_get_element (array_b, i);
+
+ if (!json_node_equal (child_a, child_b))
+ return FALSE;
+ }
+
+ return TRUE;
+}
Modified: lsp/deps/json-glib/json-builder.c
845 lines changed, 845 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,845 @@
+/* json-generator.c - JSON tree builder
+ *
+ * This file is part of JSON-GLib
+ * Copyright (C) 2010 Luca Bruno <lethalman88(a)gmail.com>
+ * Copyright (C) 2015 Collabora Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author:
+ * Luca Bruno <lethalman88(a)gmail.com>
+ * Philip Withnall <philip.withnall(a)collabora.co.uk>
+ */
+
+/**
+ * JsonBuilder:
+ *
+ * `JsonBuilder` provides an object for generating a JSON tree.
+ *
+ * The root of the JSON tree can be either a [struct(a)Json.Object] or a [struct(a)Json.Array].
+ * Thus the first call must necessarily be either
+ * [method(a)Json.Builder.begin_object] or [method(a)Json.Builder.begin_array].
+ *
+ * For convenience to language bindings, most `JsonBuilder` method return the
+ * instance, making it easy to chain function calls.
+ *
+ * ## Using `JsonBuilder`
+ *
+ * ```c
+ * g_autoptr(JsonBuilder) builder = json_builder_new ();
+ *
+ * json_builder_begin_object (builder);
+ *
+ * json_builder_set_member_name (builder, "url");
+ * json_builder_add_string_value (builder, "http://www.gnome.org/img/flash/two-thirty.png");
+ *
+ * json_builder_set_member_name (builder, "size");
+ * json_builder_begin_array (builder);
+ * json_builder_add_int_value (builder, 652);
+ * json_builder_add_int_value (builder, 242);
+ * json_builder_end_array (builder);
+ *
+ * json_builder_end_object (builder);
+ *
+ * g_autoptr(JsonNode) root = json_builder_get_root (builder);
+ *
+ * g_autoptr(JsonGenerator) gen = json_generator_new ();
+ * json_generator_set_root (gen, root);
+ * g_autofree char *str = json_generator_to_data (gen, NULL);
+ *
+ * // str now contains the following JSON data
+ * // { "url" : "http://www.gnome.org/img/flash/two-thirty.png", "size" : [ 652, 242 ] }
+ * ```
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "json-types-private.h"
+
+#include "json-builder.h"
+
+struct _JsonBuilderPrivate
+{
+ GQueue *stack;
+ JsonNode *root;
+ gboolean immutable;
+};
+
+enum
+{
+ PROP_IMMUTABLE = 1,
+ PROP_LAST
+};
+
+static GParamSpec *builder_props[PROP_LAST] = { NULL, };
+
+typedef enum
+{
+ JSON_BUILDER_MODE_OBJECT,
+ JSON_BUILDER_MODE_ARRAY,
+ JSON_BUILDER_MODE_MEMBER
+} JsonBuilderMode;
+
+typedef struct
+{
+ JsonBuilderMode mode;
+
+ union
+ {
+ JsonObject *object;
+ JsonArray *array;
+ } data;
+ gchar *member_name;
+} JsonBuilderState;
+
+static void
+json_builder_state_free (JsonBuilderState *state)
+{
+ if (G_LIKELY (state))
+ {
+ switch (state->mode)
+ {
+ case JSON_BUILDER_MODE_OBJECT:
+ case JSON_BUILDER_MODE_MEMBER:
+ json_object_unref (state->data.object);
+ g_free (state->member_name);
+ state->data.object = NULL;
+ state->member_name = NULL;
+ break;
+
+ case JSON_BUILDER_MODE_ARRAY:
+ json_array_unref (state->data.array);
+ state->data.array = NULL;
+ break;
+
+ default:
+ g_assert_not_reached ();
+ }
+
+ g_slice_free (JsonBuilderState, state);
+ }
+}
+
+G_DEFINE_TYPE_WITH_PRIVATE (JsonBuilder, json_builder, G_TYPE_OBJECT)
+
+static void
+json_builder_free_all_state (JsonBuilder *builder)
+{
+ JsonBuilderState *state;
+
+ while (!g_queue_is_empty (builder->priv->stack))
+ {
+ state = g_queue_pop_head (builder->priv->stack);
+ json_builder_state_free (state);
+ }
+
+ if (builder->priv->root)
+ {
+ json_node_unref (builder->priv->root);
+ builder->priv->root = NULL;
+ }
+}
+
+static void
+json_builder_finalize (GObject *gobject)
+{
+ JsonBuilderPrivate *priv = json_builder_get_instance_private ((JsonBuilder *) gobject);
+
+ json_builder_free_all_state (JSON_BUILDER (gobject));
+
+ g_queue_free (priv->stack);
+ priv->stack = NULL;
+
+ G_OBJECT_CLASS (json_builder_parent_class)->finalize (gobject);
+}
+
+static void
+json_builder_set_property (GObject *gobject,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ JsonBuilderPrivate *priv = JSON_BUILDER (gobject)->priv;
+
+ switch (prop_id)
+ {
+ case PROP_IMMUTABLE:
+ /* Construct-only. */
+ priv->immutable = g_value_get_boolean (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+json_builder_get_property (GObject *gobject,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ JsonBuilderPrivate *priv = JSON_BUILDER (gobject)->priv;
+
+ switch (prop_id)
+ {
+ case PROP_IMMUTABLE:
+ g_value_set_boolean (value, priv->immutable);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+json_builder_class_init (JsonBuilderClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ /**
+ * JsonBuilder:immutable:
+ *
+ * Whether the tree should be immutable when created.
+ *
+ * Making the output immutable on creation avoids the expense
+ * of traversing it to make it immutable later.
+ *
+ * Since: 1.2
+ */
+ builder_props[PROP_IMMUTABLE] =
+ g_param_spec_boolean ("immutable",
+ "Immutable Output",
+ "Whether the builder output is immutable.",
+ FALSE,
+ G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
+
+ gobject_class->set_property = json_builder_set_property;
+ gobject_class->get_property = json_builder_get_property;
+ gobject_class->finalize = json_builder_finalize;
+
+ g_object_class_install_properties (gobject_class, PROP_LAST, builder_props);
+}
+
+static void
+json_builder_init (JsonBuilder *builder)
+{
+ JsonBuilderPrivate *priv = json_builder_get_instance_private (builder);
+
+ builder->priv = priv;
+
+ priv->stack = g_queue_new ();
+ priv->root = NULL;
+}
+
+static inline JsonBuilderMode
+json_builder_current_mode (JsonBuilder *builder)
+{
+ JsonBuilderState *state = g_queue_peek_head (builder->priv->stack);
+ return state->mode;
+}
+
+static inline gboolean
+json_builder_is_valid_add_mode (JsonBuilder *builder)
+{
+ JsonBuilderMode mode = json_builder_current_mode (builder);
+ return mode == JSON_BUILDER_MODE_MEMBER || mode == JSON_BUILDER_MODE_ARRAY;
+}
+
+/**
+ * json_builder_new:
+ *
+ * Creates a new `JsonBuilder`.
+ *
+ * You can use this object to generate a JSON tree and obtain the root node.
+ *
+ * Return value: the newly created builder instance
+ */
+JsonBuilder *
+json_builder_new (void)
+{
+ return g_object_new (JSON_TYPE_BUILDER, NULL);
+}
+
+/**
+ * json_builder_new_immutable: (constructor)
+ *
+ * Creates a new, immutable `JsonBuilder` instance.
+ *
+ * It is equivalent to setting the [property@Json.Builder:immutable] property
+ * set to `TRUE` at construction time.
+ *
+ * Since: 1.2
+ * Returns: (transfer full): the newly create builder instance
+ */
+JsonBuilder *
+json_builder_new_immutable (void)
+{
+ return g_object_new (JSON_TYPE_BUILDER, "immutable", TRUE, NULL);
+}
+
+/**
+ * json_builder_get_root:
+ * @builder: a builder
+ *
+ * Returns the root of the currently constructed tree.
+ *
+ * if the build is incomplete (ie: if there are any opened objects, or any
+ * open object members and array elements) then this function will return
+ * `NULL`.
+ *
+ * Return value: (nullable) (transfer full): the root node
+ */
+JsonNode *
+json_builder_get_root (JsonBuilder *builder)
+{
+ JsonNode *root = NULL;
+
+ g_return_val_if_fail (JSON_IS_BUILDER (builder), NULL);
+
+ if (builder->priv->root)
+ root = json_node_copy (builder->priv->root);
+
+ /* Sanity check. */
+ g_assert (!builder->priv->immutable ||
+ root == NULL ||
+ json_node_is_immutable (root));
+
+ return root;
+}
+
+/**
+ * json_builder_reset:
+ * @builder: a builder
+ *
+ * Resets the state of the builder back to its initial state.
+ */
+void
+json_builder_reset (JsonBuilder *builder)
+{
+ g_return_if_fail (JSON_IS_BUILDER (builder));
+
+ json_builder_free_all_state (builder);
+}
+
+/**
+ * json_builder_begin_object:
+ * @builder: a builder
+ *
+ * Opens an object inside the given builder.
+ *
+ * You can add a new member to the object by using [method(a)Json.Builder.set_member_name],
+ * followed by [method(a)Json.Builder.add_value].
+ *
+ * Once you added all members to the object, you must call [method(a)Json.Builder.end_object]
+ * to close the object.
+ *
+ * If the builder is in an inconsistent state, this function will return `NULL`.
+ *
+ * Return value: (nullable) (transfer none): the builder instance
+ */
+JsonBuilder *
+json_builder_begin_object (JsonBuilder *builder)
+{
+ JsonObject *object;
+ JsonBuilderState *state;
+ JsonBuilderState *cur_state;
+
+ g_return_val_if_fail (JSON_IS_BUILDER (builder), NULL);
+ g_return_val_if_fail (builder->priv->root == NULL, NULL);
+ g_return_val_if_fail (g_queue_is_empty (builder->priv->stack) || json_builder_is_valid_add_mode (builder), NULL);
+
+ object = json_object_new ();
+ cur_state = g_queue_peek_head (builder->priv->stack);
+ if (cur_state)
+ {
+ switch (cur_state->mode)
+ {
+ case JSON_BUILDER_MODE_ARRAY:
+ json_array_add_object_element (cur_state->data.array, json_object_ref (object));
+ break;
+
+ case JSON_BUILDER_MODE_MEMBER:
+ json_object_set_object_member (cur_state->data.object, cur_state->member_name, json_object_ref (object));
+ g_free (cur_state->member_name);
+ cur_state->member_name = NULL;
+ cur_state->mode = JSON_BUILDER_MODE_OBJECT;
+ break;
+
+ default:
+ g_assert_not_reached ();
+ }
+ }
+
+ state = g_slice_new (JsonBuilderState);
+ state->data.object = object;
+ state->member_name = NULL;
+ state->mode = JSON_BUILDER_MODE_OBJECT;
+ g_queue_push_head (builder->priv->stack, state);
+
+ return builder;
+}
+
+/**
+ * json_builder_end_object:
+ * @builder: a builder
+ *
+ * Closes the object inside the given builder that was opened by the most
+ * recent call to [method(a)Json.Builder.begin_object].
+ *
+ * This function cannot be called after [method(a)Json.Builder.set_member_name].
+ *
+ * Return value: (nullable) (transfer none): the builder instance
+ */
+JsonBuilder *
+json_builder_end_object (JsonBuilder *builder)
+{
+ JsonBuilderState *state;
+
+ g_return_val_if_fail (JSON_IS_BUILDER (builder), NULL);
+ g_return_val_if_fail (!g_queue_is_empty (builder->priv->stack), NULL);
+ g_return_val_if_fail (json_builder_current_mode (builder) == JSON_BUILDER_MODE_OBJECT, NULL);
+
+ state = g_queue_pop_head (builder->priv->stack);
+
+ if (builder->priv->immutable)
+ json_object_seal (state->data.object);
+
+ if (g_queue_is_empty (builder->priv->stack))
+ {
+ builder->priv->root = json_node_new (JSON_NODE_OBJECT);
+ json_node_take_object (builder->priv->root, json_object_ref (state->data.object));
+
+ if (builder->priv->immutable)
+ json_node_seal (builder->priv->root);
+ }
+
+ json_builder_state_free (state);
+
+ return builder;
+}
+
+/**
+ * json_builder_begin_array:
+ * @builder: a builder
+ *
+ * Opens an array inside the given builder.
+ *
+ * You can add a new element to the array by using [method(a)Json.Builder.add_value].
+ *
+ * Once you added all elements to the array, you must call
+ * [method(a)Json.Builder.end_array] to close the array.
+ *
+ * Return value: (nullable) (transfer none): the builder instance
+ */
+JsonBuilder *
+json_builder_begin_array (JsonBuilder *builder)
+{
+ JsonArray *array;
+ JsonBuilderState *state;
+ JsonBuilderState *cur_state;
+
+ g_return_val_if_fail (JSON_IS_BUILDER (builder), NULL);
+ g_return_val_if_fail (builder->priv->root == NULL, NULL);
+ g_return_val_if_fail (g_queue_is_empty (builder->priv->stack) || json_builder_is_valid_add_mode (builder), NULL);
+
+ array = json_array_new ();
+ cur_state = g_queue_peek_head (builder->priv->stack);
+ if (cur_state)
+ {
+ switch (cur_state->mode)
+ {
+ case JSON_BUILDER_MODE_ARRAY:
+ json_array_add_array_element (cur_state->data.array, json_array_ref (array));
+ break;
+
+ case JSON_BUILDER_MODE_MEMBER:
+ json_object_set_array_member (cur_state->data.object, cur_state->member_name, json_array_ref (array));
+ g_free (cur_state->member_name);
+ cur_state->member_name = NULL;
+ cur_state->mode = JSON_BUILDER_MODE_OBJECT;
+ break;
+
+ default:
+ g_assert_not_reached ();
+ }
+ }
+
+ state = g_slice_new (JsonBuilderState);
+ state->data.array = array;
+ state->mode = JSON_BUILDER_MODE_ARRAY;
+ g_queue_push_head (builder->priv->stack, state);
+
+ return builder;
+}
+
+/**
+ * json_builder_end_array:
+ * @builder: a builder
+ *
+ * Closes the array inside the given builder that was opened by the most
+ * recent call to [method(a)Json.Builder.begin_array].
+ *
+ * This function cannot be called after [method(a)Json.Builder.set_member_name].
+ *
+ * Return value: (nullable) (transfer none): the builder instance
+ */
+JsonBuilder *
+json_builder_end_array (JsonBuilder *builder)
+{
+ JsonBuilderState *state;
+
+ g_return_val_if_fail (JSON_IS_BUILDER (builder), NULL);
+ g_return_val_if_fail (!g_queue_is_empty (builder->priv->stack), NULL);
+ g_return_val_if_fail (json_builder_current_mode (builder) == JSON_BUILDER_MODE_ARRAY, NULL);
+
+ state = g_queue_pop_head (builder->priv->stack);
+
+ if (builder->priv->immutable)
+ json_array_seal (state->data.array);
+
+ if (g_queue_is_empty (builder->priv->stack))
+ {
+ builder->priv->root = json_node_new (JSON_NODE_ARRAY);
+ json_node_take_array (builder->priv->root, json_array_ref (state->data.array));
+
+ if (builder->priv->immutable)
+ json_node_seal (builder->priv->root);
+ }
+
+ json_builder_state_free (state);
+
+ return builder;
+}
+
+/**
+ * json_builder_set_member_name:
+ * @builder: a builder
+ * @member_name: the name of the member
+ *
+ * Sets the name of the member in an object.
+ *
+ * This function must be followed by of these functions:
+ *
+ * - [method(a)Json.Builder.add_value], to add a scalar value to the member
+ * - [method(a)Json.Builder.begin_object], to add an object to the member
+ * - [method(a)Json.Builder.begin_array], to add an array to the member
+ *
+ * This function can only be called within an open object.
+ *
+ * Return value: (nullable) (transfer none): the builder instance
+ */
+JsonBuilder *
+json_builder_set_member_name (JsonBuilder *builder,
+ const gchar *member_name)
+{
+ JsonBuilderState *state;
+
+ g_return_val_if_fail (JSON_IS_BUILDER (builder), NULL);
+ g_return_val_if_fail (member_name != NULL, NULL);
+ g_return_val_if_fail (!g_queue_is_empty (builder->priv->stack), NULL);
+ g_return_val_if_fail (json_builder_current_mode (builder) == JSON_BUILDER_MODE_OBJECT, NULL);
+
+ state = g_queue_peek_head (builder->priv->stack);
+ state->member_name = g_strdup (member_name);
+ state->mode = JSON_BUILDER_MODE_MEMBER;
+
+ return builder;
+}
+
+/**
+ * json_builder_add_value:
+ * @builder: a builder
+ * @node: (transfer full): the value of the member or element
+ *
+ * Adds a value to the currently open object member or array.
+ *
+ * If called after [method(a)Json.Builder.set_member_name], sets the given node
+ * as the value of the current member in the open object; otherwise, the node
+ * is appended to the elements of the open array.
+ *
+ * The builder will take ownership of the node.
+ *
+ * Return value: (nullable) (transfer none): the builder instance
+ */
+JsonBuilder *
+json_builder_add_value (JsonBuilder *builder,
+ JsonNode *node)
+{
+ JsonBuilderState *state;
+
+ g_return_val_if_fail (JSON_IS_BUILDER (builder), NULL);
+ g_return_val_if_fail (node != NULL, NULL);
+ g_return_val_if_fail (!g_queue_is_empty (builder->priv->stack), NULL);
+ g_return_val_if_fail (json_builder_is_valid_add_mode (builder), NULL);
+
+ state = g_queue_peek_head (builder->priv->stack);
+
+ if (builder->priv->immutable)
+ json_node_seal (node);
+
+ switch (state->mode)
+ {
+ case JSON_BUILDER_MODE_MEMBER:
+ json_object_set_member (state->data.object, state->member_name, node);
+ g_free (state->member_name);
+ state->member_name = NULL;
+ state->mode = JSON_BUILDER_MODE_OBJECT;
+ break;
+
+ case JSON_BUILDER_MODE_ARRAY:
+ json_array_add_element (state->data.array, node);
+ break;
+
+ default:
+ g_assert_not_reached ();
+ }
+
+ return builder;
+}
+
+/**
+ * json_builder_add_int_value:
+ * @builder: a builder
+ * @value: the value of the member or element
+ *
+ * Adds an integer value to the currently open object member or array.
+ *
+ * If called after [method(a)Json.Builder.set_member_name], sets the given value
+ * as the value of the current member in the open object; otherwise, the value
+ * is appended to the elements of the open array.
+ *
+ * See also: [method(a)Json.Builder.add_value]
+ *
+ * Return value: (nullable) (transfer none): the builder instance
+ */
+JsonBuilder *
+json_builder_add_int_value (JsonBuilder *builder,
+ gint64 value)
+{
+ JsonBuilderState *state;
+
+ g_return_val_if_fail (JSON_IS_BUILDER (builder), NULL);
+ g_return_val_if_fail (!g_queue_is_empty (builder->priv->stack), NULL);
+ g_return_val_if_fail (json_builder_is_valid_add_mode (builder), NULL);
+
+ state = g_queue_peek_head (builder->priv->stack);
+ switch (state->mode)
+ {
+ case JSON_BUILDER_MODE_MEMBER:
+ json_object_set_int_member (state->data.object, state->member_name, value);
+ g_free (state->member_name);
+ state->member_name = NULL;
+ state->mode = JSON_BUILDER_MODE_OBJECT;
+ break;
+
+ case JSON_BUILDER_MODE_ARRAY:
+ json_array_add_int_element (state->data.array, value);
+ break;
+
+ default:
+ g_assert_not_reached ();
+ }
+
+ return builder;
+}
+
+/**
+ * json_builder_add_double_value:
+ * @builder: a builder
+ * @value: the value of the member or element
+ *
+ * Adds a floating point value to the currently open object member or array.
+ *
+ * If called after [method(a)Json.Builder.set_member_name], sets the given value
+ * as the value of the current member in the open object; otherwise, the value
+ * is appended to the elements of the open array.
+ *
+ * See also: [method(a)Json.Builder.add_value]
+ *
+ * Return value: (nullable) (transfer none): the builder instance
+ */
+JsonBuilder *
+json_builder_add_double_value (JsonBuilder *builder,
+ gdouble value)
+{
+ JsonBuilderState *state;
+
+ g_return_val_if_fail (JSON_IS_BUILDER (builder), NULL);
+ g_return_val_if_fail (!g_queue_is_empty (builder->priv->stack), NULL);
+ g_return_val_if_fail (json_builder_is_valid_add_mode (builder), NULL);
+
+ sta@@ Diff output truncated at 100000 characters. @@
--------------
This E-Mail was brought to you by github_commit_mail.py (Source: https://github.com/geany/infrastructure).