diff --git a/README.md b/README.md index 5170aec..c77b22b 100644 --- a/README.md +++ b/README.md @@ -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 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. ## C, C++, Rust, etc. diff --git a/docs/configuration.md b/docs/configuration.md index 67e7665..4f67739 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -110,14 +110,15 @@ But for now, consider the following example snippet: { "configurations": { "example-debug-configuration": { + // This is a single-line comment explaining the purpose "adapter": "example-adapter-name", "variables": { - "SecretToken": { + "SecretToken": { // Variables should start with upper-case letters "shell" : [ "cat", "${HOME}/.secret_token" ] } }, "configuration": { - "request": "launch", + "request": "launch" /* or it could be "attach" */, "program": [ "${fileBasenameNoExtension}", "-c", "configuration_file.cfg", @@ -364,6 +365,25 @@ The following variables are provided: * `${fileExtname}` - the current opened file's extension * `${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 If you would like some assistance with writing the JSON files, and your editor diff --git a/install_gadget.py b/install_gadget.py index 4ecc4b6..5d474c4 100755 --- a/install_gadget.py +++ b/install_gadget.py @@ -36,6 +36,7 @@ sys.path.insert( 1, os.path.join( os.path.dirname( __file__ ), 'python3' ) ) from vimspector import install, installer +from vimspector.vendor.json_minify import minify GADGETS = { 'vscode-cpptools': { @@ -634,7 +635,7 @@ for custom_file_name in functools.reduce( operator.add, args.custom_gadget_file, custom_files ): 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 = [] diff --git a/python3/vimspector/debug_session.py b/python3/vimspector/debug_session.py index 8212ab1..fb03f41 100644 --- a/python3/vimspector/debug_session.py +++ b/python3/vimspector/debug_session.py @@ -31,6 +31,7 @@ from vimspector import ( breakpoints, stack_trace, utils, variables ) +from vimspector.vendor.json_minify import minify VIMSPECTOR_HOME = os.path.abspath( os.path.join( os.path.dirname( __file__ ), '..', @@ -96,7 +97,8 @@ class DebugSession( object ): continue 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, current_file, @@ -106,7 +108,7 @@ class DebugSession( object ): continue with open( launch_config_file, 'r' ) as f: - database = json.load( f ) + database = json.loads( minify( f.read() ) ) adapters.update( database.get( 'adapters' ) or {} ) configurations.update( database.get( 'configurations' or {} ) ) diff --git a/python3/vimspector/installer.py b/python3/vimspector/installer.py index 1553098..bca5084 100644 --- a/python3/vimspector/installer.py +++ b/python3/vimspector/installer.py @@ -221,6 +221,7 @@ def MakeSymlink( in_folder, link, pointing_to ): else: os.symlink( pointing_to_relative, link_path ) + def CloneRepoTo( url, ref, destination ): RemoveIfExists( destination ) git_in_repo = [ 'git', '-C', destination ] diff --git a/python3/vimspector/vendor/json_minify.py b/python3/vimspector/vendor/json_minify.py new file mode 100644 index 0000000..6b78901 --- /dev/null +++ b/python3/vimspector/vendor/json_minify.py @@ -0,0 +1,97 @@ +# Copyright © 2020 Kyle Simpson +# +# 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) diff --git a/support/test/python/simple_python/.vimspector.json b/support/test/python/simple_python/.vimspector.json index 5cb036c..f585ca6 100644 --- a/support/test/python/simple_python/.vimspector.json +++ b/support/test/python/simple_python/.vimspector.json @@ -1,7 +1,8 @@ { "configurations": { + // This is a comment. "run legacy vscode-python": { - "adapter": "vscode-python", + "adapter": "vscode-python" /* coment goes here too */, "configuration": { "request": "launch", "type": "python", diff --git a/tox.ini b/tox.ini index dbd9626..7a6c06e 100644 --- a/tox.ini +++ b/tox.ini @@ -1,3 +1,4 @@ [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 max-line-length = 80 +exclude = python3/vimspector/vendor