Sublime Forum

Rainbow colors by JSON object level with any color scheme

#1

It recently occured that someone asked how to achieve rainbow-colored object keys in JSON files by level, so I am posting instructions here on how to achieve this with any color scheme. And also different variations.

Instructions

The following steps are needed for each variant, but the color scheme contents you want to use are different depending on which you choose.
7 levels are supported by default, with level 7+ being treated the same. It is easy to add more levels or loop them, however.

  1. Install PackageDev.

  2. With the color scheme you want to modify active, run PackageDev: Edit Current Color Scheme from the Command Pallette.

    The right view should contain something similar to this:

    {
        // http://www.sublimetext.com/docs/3/color_schemes.html
        "variables": {
        },
        "globals": {
        },
        "rules": [
        ],
    }
    
  3. On the right side of the newly opened window, add following entries to the variables map:

         "rainbow1": "red",
         "rainbow2": "blue",
         "rainbow3": "green",
         "rainbow4": "yellow",
         "rainbow5": "orange",
         "rainbow6": "purple",
         "rainbow7": "white",
         // "background": "black", // You only need this if your scheme doesn't provide it already
    
    

    These will be the base colors for the rainbow scheme. These are just some defaults I picked for showcasing. You are free to modify them as you wish, or even source them from variables on your scheme. See the documentation for details.

  4. Depending on which variant you want, insert the provided rules into the rules array.

Variant 1: Colored keys

2019-03-28_13-42-55

Rules to use
        {
            "scope": "source.json meta.mapping.key string - punctuation",
            "foreground": "var(rainbow1)",
        },
        {
            "scope": "source.json meta.mapping meta.mapping.key string - punctuation",
            "foreground": "var(rainbow2)",
        },
        {
            "scope": "source.json meta.mapping meta.mapping meta.mapping.key string - punctuation",
            "foreground": "var(rainbow3)",
        },
        {
            "scope": "source.json meta.mapping meta.mapping meta.mapping meta.mapping.key string - punctuation",
            "foreground": "var(rainbow4)",
        },
        {
            "scope": "source.json meta.mapping meta.mapping meta.mapping meta.mapping meta.mapping.key string - punctuation",
            "foreground": "var(rainbow5)",
        },
        {
            "scope": "source.json meta.mapping meta.mapping meta.mapping meta.mapping meta.mapping meta.mapping.key string - punctuation",
            "foreground": "var(rainbow6)",
        },
        {
            "scope": "source.json meta.mapping meta.mapping meta.mapping meta.mapping meta.mapping meta.mapping meta.mapping.key string - punctuation",
            "foreground": "var(rainbow7)",
        },

Variant 2: Colored keys and string values, but dimmed

2019-03-28_13-49-35

Rules to use
        {
            "scope": "source.json meta.mapping.key string - punctuation",
            "foreground": "var(rainbow1)",
        },
        {
            "scope": "source.json meta.mapping meta.mapping.key string - punctuation",
            "foreground": "var(rainbow2)",
        },
        {
            "scope": "source.json meta.mapping meta.mapping meta.mapping.key string - punctuation",
            "foreground": "var(rainbow3)",
        },
        {
            "scope": "source.json meta.mapping meta.mapping meta.mapping meta.mapping.key string - punctuation",
            "foreground": "var(rainbow4)",
        },
        {
            "scope": "source.json meta.mapping meta.mapping meta.mapping meta.mapping meta.mapping.key string - punctuation",
            "foreground": "var(rainbow5)",
        },
        {
            "scope": "source.json meta.mapping meta.mapping meta.mapping meta.mapping meta.mapping meta.mapping.key string - punctuation",
            "foreground": "var(rainbow6)",
        },
        {
            "scope": "source.json meta.mapping meta.mapping meta.mapping meta.mapping meta.mapping meta.mapping meta.mapping.key string - punctuation",
            "foreground": "var(rainbow7)",
        },
        {
            "scope": "source.json meta.mapping.value string - punctuation",
            "foreground": "color(var(rainbow1) blend(var(background) 70%)",
        },
        {
            "scope": "source.json meta.mapping meta.mapping.value string - punctuation",
            "foreground": "color(var(rainbow2) blend(var(background) 70%)",
        },
        {
            "scope": "source.json meta.mapping meta.mapping meta.mapping.value string - punctuation",
            "foreground": "color(var(rainbow3) blend(var(background) 70%)",
        },
        {
            "scope": "source.json meta.mapping meta.mapping meta.mapping meta.mapping.value string - punctuation",
            "foreground": "color(var(rainbow4) blend(var(background) 70%)",
        },
        {
            "scope": "source.json meta.mapping meta.mapping meta.mapping meta.mapping meta.mapping.value string - punctuation",
            "foreground": "color(var(rainbow5) blend(var(background) 70%)",
        },
        {
            "scope": "source.json meta.mapping meta.mapping meta.mapping meta.mapping meta.mapping meta.mapping.value string - punctuation",
            "foreground": "color(var(rainbow6) blend(var(background) 70%)",
        },
        {
            "scope": "source.json meta.mapping meta.mapping meta.mapping meta.mapping meta.mapping meta.mapping meta.mapping.value string - punctuation",
            "foreground": "color(var(rainbow7) blend(var(background) 70%)",
        },

Variant 3: Background dimming

2019-03-28_13-52-22

Rules to use
        {
            "scope": "source.json meta.mapping",
            "background": "color(var(rainbow1) blend(var(background) 14%)",
        },
        {
            "scope": "source.json meta.mapping meta.mapping",
            "background": "color(var(rainbow2) blend(var(background) 14%)",
        },
        {
            "scope": "source.json meta.mapping meta.mapping meta.mapping",
            "background": "color(var(rainbow3) blend(var(background) 14%)",
        },
        {
            "scope": "source.json meta.mapping meta.mapping meta.mapping meta.mapping",
            "background": "color(var(rainbow4) blend(var(background) 14%)",
        },
        {
            "scope": "source.json meta.mapping meta.mapping meta.mapping meta.mapping meta.mapping",
            "background": "color(var(rainbow5) blend(var(background) 14%)",
        },
        {
            "scope": "source.json meta.mapping meta.mapping meta.mapping meta.mapping meta.mapping meta.mapping",
            "background": "color(var(rainbow6) blend(var(background) 14%)",
        },
        {
            "scope": "source.json meta.mapping meta.mapping meta.mapping meta.mapping meta.mapping meta.mapping meta.mapping",
            "background": "color(var(rainbow7) blend(var(background) 14%)",
        },

More ideas?

Feel free to share your configuration. I’ll add them to the post.

Screenshot text
{
    "hi": "there",
    "this": {
        "is": "a",
        "somewhat": {
            "deeply": "nested",
            "json": {
                "object": "structure",
                "to": {
                    "showcase": "rainbow",
                    "colorization": {
                        "I": "still",
                        "need": {
                            "more": "levels",
                        }
                    }
                }
            }
        }
    }
}
7 Likes

JSON color scheme broken
BUILD 3200 json bug
Nested application of color scheme styles?
#2

Worth noting that this can only handle up to five levels, and then everything after the fifth level will be styled the same… as the fifth level. The advantage is it doesn’t require modifying the scoping at all.

For anyone who is willing to roll up their sleeves and edit the sublime-syntax itself, it’s not too too hard to get something that works in a loop. So level 1 is styled the same as level 6, level 11, level 16, and such. Right now, objects are styled in the following way (you can see this if you use PackageResourceViewer to open up the JavaScript/JSON.sublime-syntax file):

  object:
    # a JSON object
    - match: '\{'
      scope: punctuation.section.mapping.begin.json
      push:
        - meta_scope: meta.mapping.json
        - match: '\}'
          scope: punctuation.section.mapping.end.json
          pop: true
        - match: '"'
          scope: punctuation.definition.string.begin.json
          push:
            - clear_scopes: 1
            - meta_scope: meta.mapping.key.json string.quoted.double.json
            - meta_include_prototype: false
            - include: inside-string
        - match: ":"
          scope: punctuation.separator.mapping.key-value.json
          push:
            - match: '(,)|(?=\})'
              captures:
                1: invalid.illegal.expected-mapping-value.json
              pop: true
            - match: (?=\S)
              set:
                - clear_scopes: 1
                - meta_scope: meta.mapping.value.json
                - include: value
                - match: ''
                  set:
                    - match: '(,)|(?=\s*\})'
                      captures:
                        1: punctuation.separator.mapping.pair.json
                      pop: true
                    - match: '\s(?=[^\s,])|[^\s,]'
                      scope: invalid.illegal.expected-mapping-separator.json
                      pop: true
        - match: '[^\s\}]'
          scope: invalid.illegal.expected-mapping-key.json

Change the existing value and object contexts to have a numeric suffix 1, also changing all of the meta scopes within. They all currently end in .json; change this to .1.json. Then… copy them and make value2 and object2, with the meta scopes changing to .2.json. Do this again and again until you have value1 through value5, with each valueN context linking to objectN. Finally, change the include: value inside of objectN to be include: value(N + 1). So in other words, object1 should include value2, object2 should include value3, and finally object5 should include value1 (wrapping back around).

Finally, use @FichteFoll’s technique above with the color scheme, except the scopes you’re looking for are meta.mapping.1, meta.mapping.2, etc etc rather than repetitions of the meta.mapping scope. This will allow your color wheel to “wrap around the end”, ensuring that no two consecutive levels of nesting have the same styling.

Not sure if this is useful or not, but here it is if you want it.

2 Likes

#3

I wonder if anyone else had the colors disappeared after upgrading to 3.2. Previously I had nice colors for JSON files and now everything is gone. I’m using the Default Theme and Oceanic Next (SL) color scheme.

0 Likes

#4

We discussed how to properly scope mapping keys generally in all languages and JSON and Python were the first languages to be updated to that. The new scope of a mapping key is now meta.mapping.key and will be applied to the entire key part of a mapping, not just the string. The previous scope was an old hack based on the lack of a proper standard. It is likely that color schemes targeted the old scope and were not updated.

3 Likes

#5

Thanks for this @FichteFoll!

Here are my colors for the Brogrammer theme:

  "variables": {
    // "green": "#FF0000",
    "rainbow1": "#e74c3c", // Red
    "rainbow2": "#3498db", // Blue
    "rainbow3": "#2ecc71", // Green
    "rainbow4": "#f1c40f", // Yellow
    "rainbow5": "#e67e22", // Orange-Red
    "rainbow6": "#6c71c4", // Periwinkle
    "rainbow7": "#ffffff", // White
    "background": "#1a1a1a", // Dark Grey
    // The following colors were extracted from brogrammer.tmTheme
    // White: #ffffff
    // Off-White: #ecf0f1
    // Dark Grey (background): #1a1a1a
    // Light Grey: #555555
    // Medium Light Grey: #2a2a2a
    // Medium Dark Grey: #222222
    // Green: #2ecc71
    // Aqua: #1abc9c
    // Red: #e74c3c
    // Blue: #3498db
    // Yellow: #f1c40f
    // Orange-Red: #e67e22
    // Periwinkle: #6c71c4
  },

Also, here’s the example text if anyone needs it:

{"hi":"there","this":{"is":"a","somewhat":{"deeply":"nested","json":{"object":"structure","to":{"showcase":"rainbow","colorization":{"I":"still","need":{"more":"levels"}}}}}}}

1 Like