Search code examples
jsonsublimetext3sublime-text-pluginsublimerepl

Why does Sublime Text 3 allow comments in JSON configuration files?


Using comments in JSON configuration files in Sublime Text can make JSON objects unable to be decoded. Here is my story.

I newly installed SublimeREPL plugin in my Sublime Text 3. Soon I discovered it ran Python2.7 instead of 3.5 in default, so I added my own Python3.5 configuration files according to SublimeREPL Docs to make it support Python3.5.

My Packages/SublimeREPL/config/Python3.5/Main.sublime-menu JSON config file looks like this:

[
 {
    "id": "tools",
    "children":
    [{
        "caption": "SublimeREPL",
        "mnemonic": "R",
        "id": "SublimeREPL",
        "children":
        [
            {"caption": "Python3.5",
            "id": "Python3.5",

             "children":[
                {"command": "repl_open",
                 "caption": "Python3.5",
                 "id": "repl_python3.5",
                 "mnemonic": "P",
                 "args": {
                    "type": "subprocess",
                    "encoding": "utf8",
                    "cmd": ["python3", "-i", "-u"],
                    "cwd": "$file_path",
                    "syntax": "Packages/Python/Python.tmLanguage",
                    "external_id": "python3",
                    "extend_env": {"PYTHONIOENCODING": "utf-8"}
                    }
                },
                // run files
                {"command": "repl_open",
                 "caption": "Python3.5 - RUN current file",
                 "id": "repl_python3.5_run",
                 "mnemonic": "R",
                 "args": {
                    "type": "subprocess",
                    "encoding": "utf8",
                    "cmd": ["python3", "-u", "$file_basename"],
                    "cwd": "$file_path",
                    "syntax": "Packages/Python/Python.tmLanguage",
                    "external_id": "python3",
                    "extend_env": {"PYTHONIOENCODING": "utf-8"}
                    }
                }
            ]}
        ]
    }]
}]

Note there is a comment // run files in this file. This config works fine from the menu bar tools->SublimeREPL->Python3.5. However,when I tried to bind the F5 key with repl_python3.5_run to have easier access to 3.5,the following exception was thrown in the console:

Traceback (most recent call last):

  File "./python3.3/json/decoder.py", line 367, in raw_decode
StopIteration

During handling of the above exception, another exception occurred:

Traceback (most recent call last):

File "/opt/sublime_text/sublime_plugin.py", line 551, in run_
    return self.run(**args)

File "/home/ubuntu/.config/sublime-text-3/Packages/SublimeREPL/run_existing_command.py", line 32, in run
    json_cmd = self._find_cmd(id, path)

File "/home/ubuntu/.config/sublime-text-3/Packages/SublimeREPL/run_existing_command.py", line 41, in _find_cmd
    return self._find_cmd_in_file(id, file)

 File "/home/ubuntu/.config/sublime-text-3/Packages/SublimeREPL/run_existing_command.py", line 53, in _find_cmd_in_file
    data = json.loads(bytes)

 File "./python3.3/json/__init__.py", line 316, in loads

 File "./python3.3/json/decoder.py", line 351, in decode

 File "./python3.3/json/decoder.py", line 369, in raw_decode

ValueError: No JSON object could be decoded

After I removed the // run files comment. The F5 key works fine.It's exactly the comment that causes the problem. Sublime Text uses JSON as config files,lots of config files come with // style comments. As we know, comments are removed from JSON by design.

Then how can sublime text allow comments in config files, is it using a pipe? If it is, how can my key binding fail?


Solution

  • Sublime itself (the core program, not plugins like SublimeREPL) uses an internal JSON library for parsing config files like .sublime-settings, .sublime-menu, .sublime-build, etc. This (most likely customized) parser allows comments.

    However, plugins are run through a version of Python (currently 3.3.6 for the dev builds) linked to the Sublime plugin_host executable. Any plugin that imports the standard library's json module (such as run_existing_command.py has to obey the restrictions of that module, and that includes failing to recognize JavaScript-style comments like // in JSON.

    One workaround to this would be to import an external module like commentjson that strips various types of comments, including //, before passing the data on to the standard json module. Since it is a pure Python module, you could just copy the source directory into the main SublimeREPL dir, then edit run_existing_command.py appropriately - change line 6 to import commentjson as json and you're all set.