Support c-style comments in JSON
Debate rages about whether JSON should have comments. The specification says it shouldn't but the author of JSON suggested that if you want to use JSON for configuration, then pipe it through jsmin before parsing. So that's what we do, using a tiny JSON minifier from https://github.com/getify/JSON.minify/tree/python Closes #135
This commit is contained in:
parent
9393c1d80e
commit
d42fd51f35
8 changed files with 134 additions and 6 deletions
|
|
@ -609,6 +609,11 @@ the Getting Started section of the [Vimspector website][website].
|
||||||
For full explanation, including how to use variables, substitutions and how to
|
For full explanation, including how to use variables, substitutions and how to
|
||||||
specify exception breakpoints, see [the docs][vimspector-ref].
|
specify exception breakpoints, see [the docs][vimspector-ref].
|
||||||
|
|
||||||
|
The JSON configuration file allows C-style comments:
|
||||||
|
|
||||||
|
* `// comment to end of line ...`
|
||||||
|
* `/* inline comment ... */`
|
||||||
|
|
||||||
Current tested with the following debug adapters.
|
Current tested with the following debug adapters.
|
||||||
|
|
||||||
## C, C++, Rust, etc.
|
## C, C++, Rust, etc.
|
||||||
|
|
|
||||||
|
|
@ -110,14 +110,15 @@ But for now, consider the following example snippet:
|
||||||
{
|
{
|
||||||
"configurations": {
|
"configurations": {
|
||||||
"example-debug-configuration": {
|
"example-debug-configuration": {
|
||||||
|
// This is a single-line comment explaining the purpose
|
||||||
"adapter": "example-adapter-name",
|
"adapter": "example-adapter-name",
|
||||||
"variables": {
|
"variables": {
|
||||||
"SecretToken": {
|
"SecretToken": { // Variables should start with upper-case letters
|
||||||
"shell" : [ "cat", "${HOME}/.secret_token" ]
|
"shell" : [ "cat", "${HOME}/.secret_token" ]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"configuration": {
|
"configuration": {
|
||||||
"request": "launch",
|
"request": "launch" /* or it could be "attach" */,
|
||||||
"program": [
|
"program": [
|
||||||
"${fileBasenameNoExtension}",
|
"${fileBasenameNoExtension}",
|
||||||
"-c", "configuration_file.cfg",
|
"-c", "configuration_file.cfg",
|
||||||
|
|
@ -364,6 +365,25 @@ The following variables are provided:
|
||||||
* `${fileExtname}` - the current opened file's extension
|
* `${fileExtname}` - the current opened file's extension
|
||||||
* `${cwd}` - the current working directory of the active window on launch
|
* `${cwd}` - the current working directory of the active window on launch
|
||||||
|
|
||||||
|
## Appendix: Configuration file format
|
||||||
|
|
||||||
|
The configuration files are text files which must be UTF-8 encoded. They
|
||||||
|
contain a single JSON object, along with optional comments.
|
||||||
|
|
||||||
|
Comments are "c-style", i.e.:
|
||||||
|
|
||||||
|
* `// single line comment ...`
|
||||||
|
* `/* inline comment */`
|
||||||
|
|
||||||
|
There is much debate about whether JSON files should contain comments. I have
|
||||||
|
added them because they are useful in the context of configuration files.
|
||||||
|
Unforutnately this may mean your editor doesn't like them (they are strictly
|
||||||
|
invalid JSON) so it's up to you if you use them.
|
||||||
|
|
||||||
|
Technically, Vimspector uses [JSON
|
||||||
|
minify](https://github.com/getify/JSON.minify) to strip comments before parsing
|
||||||
|
the JSON.
|
||||||
|
|
||||||
## Appendix: Editor configuration
|
## Appendix: Editor configuration
|
||||||
|
|
||||||
If you would like some assistance with writing the JSON files, and your editor
|
If you would like some assistance with writing the JSON files, and your editor
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@ sys.path.insert( 1, os.path.join( os.path.dirname( __file__ ),
|
||||||
'python3' ) )
|
'python3' ) )
|
||||||
|
|
||||||
from vimspector import install, installer
|
from vimspector import install, installer
|
||||||
|
from vimspector.vendor.json_minify import minify
|
||||||
|
|
||||||
GADGETS = {
|
GADGETS = {
|
||||||
'vscode-cpptools': {
|
'vscode-cpptools': {
|
||||||
|
|
@ -634,7 +635,7 @@ for custom_file_name in functools.reduce( operator.add,
|
||||||
args.custom_gadget_file,
|
args.custom_gadget_file,
|
||||||
custom_files ):
|
custom_files ):
|
||||||
with open( custom_file_name, 'r' ) as custom_file:
|
with open( custom_file_name, 'r' ) as custom_file:
|
||||||
CUSTOM_GADGETS.update( json.load( custom_file ) )
|
CUSTOM_GADGETS.update( json.loads( minify( custom_file.read() ) ) )
|
||||||
|
|
||||||
|
|
||||||
failed = []
|
failed = []
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@ from vimspector import ( breakpoints,
|
||||||
stack_trace,
|
stack_trace,
|
||||||
utils,
|
utils,
|
||||||
variables )
|
variables )
|
||||||
|
from vimspector.vendor.json_minify import minify
|
||||||
|
|
||||||
VIMSPECTOR_HOME = os.path.abspath( os.path.join( os.path.dirname( __file__ ),
|
VIMSPECTOR_HOME = os.path.abspath( os.path.join( os.path.dirname( __file__ ),
|
||||||
'..',
|
'..',
|
||||||
|
|
@ -96,7 +97,8 @@ class DebugSession( object ):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
with open( gadget_config_file, 'r' ) as f:
|
with open( gadget_config_file, 'r' ) as f:
|
||||||
adapters.update( json.load( f ).get( 'adapters' ) or {} )
|
a = json.loads( minify( f.read() ) ).get( 'adapters' ) or {}
|
||||||
|
adapters.update( a )
|
||||||
|
|
||||||
for launch_config_file in PathsToAllConfigFiles( VIMSPECTOR_HOME,
|
for launch_config_file in PathsToAllConfigFiles( VIMSPECTOR_HOME,
|
||||||
current_file,
|
current_file,
|
||||||
|
|
@ -106,7 +108,7 @@ class DebugSession( object ):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
with open( launch_config_file, 'r' ) as f:
|
with open( launch_config_file, 'r' ) as f:
|
||||||
database = json.load( f )
|
database = json.loads( minify( f.read() ) )
|
||||||
adapters.update( database.get( 'adapters' ) or {} )
|
adapters.update( database.get( 'adapters' ) or {} )
|
||||||
configurations.update( database.get( 'configurations' or {} ) )
|
configurations.update( database.get( 'configurations' or {} ) )
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -221,6 +221,7 @@ def MakeSymlink( in_folder, link, pointing_to ):
|
||||||
else:
|
else:
|
||||||
os.symlink( pointing_to_relative, link_path )
|
os.symlink( pointing_to_relative, link_path )
|
||||||
|
|
||||||
|
|
||||||
def CloneRepoTo( url, ref, destination ):
|
def CloneRepoTo( url, ref, destination ):
|
||||||
RemoveIfExists( destination )
|
RemoveIfExists( destination )
|
||||||
git_in_repo = [ 'git', '-C', destination ]
|
git_in_repo = [ 'git', '-C', destination ]
|
||||||
|
|
|
||||||
97
python3/vimspector/vendor/json_minify.py
vendored
Normal file
97
python3/vimspector/vendor/json_minify.py
vendored
Normal file
|
|
@ -0,0 +1,97 @@
|
||||||
|
# Copyright © 2020 Kyle Simpson <getify@gmail.com>
|
||||||
|
#
|
||||||
|
# Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
# a copy of this software and associated documentation files (the "Software"),
|
||||||
|
# to deal in the Software without restriction, including without limitation
|
||||||
|
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
# and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
# Software is furnished to do so, subject to the following conditions:
|
||||||
|
#
|
||||||
|
# The above copyright notice and this permission notice shall be included
|
||||||
|
# in all copies or substantial portions of the Software.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||||
|
# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
||||||
|
# OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
#
|
||||||
|
|
||||||
|
"""A port of the `JSON-minify` utility to the Python language.
|
||||||
|
|
||||||
|
Based on JSON.minify.js: https://github.com/getify/JSON.minify
|
||||||
|
|
||||||
|
Contributers:
|
||||||
|
- Gerald Storer
|
||||||
|
- Contributed original version
|
||||||
|
- Felipe Machado
|
||||||
|
- Performance optimization
|
||||||
|
- Pradyun S. Gedam
|
||||||
|
- Conditions and variable names changed
|
||||||
|
- Reformatted tests and moved to separate file
|
||||||
|
- Made into a PyPI Package
|
||||||
|
"""
|
||||||
|
|
||||||
|
import re
|
||||||
|
|
||||||
|
|
||||||
|
# Vimspector modification: strip_space defaults to False; we don't actually want
|
||||||
|
# to minify - we just want to strip comments.
|
||||||
|
def minify(string, strip_space=False):
|
||||||
|
tokenizer = re.compile('"|(/\*)|(\*/)|(//)|\n|\r')
|
||||||
|
end_slashes_re = re.compile(r'(\\)*$')
|
||||||
|
|
||||||
|
in_string = False
|
||||||
|
in_multi = False
|
||||||
|
in_single = False
|
||||||
|
|
||||||
|
new_str = []
|
||||||
|
index = 0
|
||||||
|
|
||||||
|
for match in re.finditer(tokenizer, string):
|
||||||
|
|
||||||
|
if not (in_multi or in_single):
|
||||||
|
tmp = string[index:match.start()]
|
||||||
|
if not in_string and strip_space:
|
||||||
|
# replace white space as defined in standard
|
||||||
|
tmp = re.sub('[ \t\n\r]+', '', tmp)
|
||||||
|
new_str.append(tmp)
|
||||||
|
elif not strip_space:
|
||||||
|
# Replace comments with white space so that the JSON parser reports
|
||||||
|
# the correct column numbers on parsing errors.
|
||||||
|
new_str.append(' ' * (match.start() - index))
|
||||||
|
|
||||||
|
index = match.end()
|
||||||
|
val = match.group()
|
||||||
|
|
||||||
|
if val == '"' and not (in_multi or in_single):
|
||||||
|
escaped = end_slashes_re.search(string, 0, match.start())
|
||||||
|
|
||||||
|
# start of string or unescaped quote character to end string
|
||||||
|
if not in_string or (escaped is None or len(escaped.group()) % 2 == 0): # noqa
|
||||||
|
in_string = not in_string
|
||||||
|
index -= 1 # include " character in next catch
|
||||||
|
elif not (in_string or in_multi or in_single):
|
||||||
|
if val == '/*':
|
||||||
|
in_multi = True
|
||||||
|
elif val == '//':
|
||||||
|
in_single = True
|
||||||
|
elif val == '*/' and in_multi and not (in_string or in_single):
|
||||||
|
in_multi = False
|
||||||
|
if not strip_space:
|
||||||
|
new_str.append(' ' * len(val))
|
||||||
|
elif val in '\r\n' and not (in_multi or in_string) and in_single:
|
||||||
|
in_single = False
|
||||||
|
elif not ((in_multi or in_single) or (val in ' \r\n\t' and strip_space)): # noqa
|
||||||
|
new_str.append(val)
|
||||||
|
|
||||||
|
if not strip_space:
|
||||||
|
if val in '\r\n':
|
||||||
|
new_str.append(val)
|
||||||
|
elif in_multi or in_single:
|
||||||
|
new_str.append(' ' * len(val))
|
||||||
|
|
||||||
|
new_str.append(string[index:])
|
||||||
|
return ''.join(new_str)
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
{
|
{
|
||||||
"configurations": {
|
"configurations": {
|
||||||
|
// This is a comment.
|
||||||
"run legacy vscode-python": {
|
"run legacy vscode-python": {
|
||||||
"adapter": "vscode-python",
|
"adapter": "vscode-python" /* coment goes here too */,
|
||||||
"configuration": {
|
"configuration": {
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"type": "python",
|
"type": "python",
|
||||||
|
|
|
||||||
1
tox.ini
1
tox.ini
|
|
@ -1,3 +1,4 @@
|
||||||
[flake8]
|
[flake8]
|
||||||
ignore = E111,E114,E121,E125,E126,E127,E128,E129,E131,E133,E201,E202,E203,E211,E221,E222,E241,E251,E261,E303,E402,W503,W504
|
ignore = E111,E114,E121,E125,E126,E127,E128,E129,E131,E133,E201,E202,E203,E211,E221,E222,E241,E251,E261,E303,E402,W503,W504
|
||||||
max-line-length = 80
|
max-line-length = 80
|
||||||
|
exclude = python3/vimspector/vendor
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue