From 029f72b1a93430b24b88eb3a72c6114d9f149737 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 10 Apr 2024 22:09:20 +0200 Subject: Adding upstream version 2:9.1.0016. Signed-off-by: Daniel Baumann --- runtime/autoload/dist/json.vim | 182 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 182 insertions(+) create mode 100644 runtime/autoload/dist/json.vim (limited to 'runtime/autoload/dist/json.vim') diff --git a/runtime/autoload/dist/json.vim b/runtime/autoload/dist/json.vim new file mode 100644 index 0000000..9faa88a --- /dev/null +++ b/runtime/autoload/dist/json.vim @@ -0,0 +1,182 @@ +vim9script + +# Maintainer: Maxim Kim +# Last update: 2023-12-10 +# +# Set of functions to format/beautify JSON data structures. +# +# Could be used to reformat a minified json in a buffer (put it into ~/.vim/ftplugin/json.vim): +# import autoload 'dist/json.vim' +# setl formatexpr=json.FormatExpr() +# +# Or to get a formatted string out of vim's dict/list/string: +# vim9script +# import autoload 'dist/json.vim' +# echo json.Format({ +# "widget": { "debug": "on", "window": { "title": "Sample \"Konfabulator\" Widget", +# "name": "main_window", "width": 500, "height": 500 +# }, +# "image": { "src": "Images/Sun.png", "name": "sun1", "hOffset": 250, +# "vOffset": 250, "alignment": "center" }, +# "text": { "data": "Click Here", "size": 36, "style": "bold", "name": "text1", +# "hOffset": 250, "vOffset": 100, "alignment": "center", +# "onMouseUp": "sun1.opacity = (sun1.opacity / 100) * 90;" } } +# }) +# +# Should output: +# { +# "widget": { +# "debug": "on", +# "window": { +# "title": "Sample \"Konfabulator\" Widget", +# "name": "main_window", +# "width": 500, +# "height": 500 +# }, +# "image": { +# "src": "Images/Sun.png", +# "name": "sun1", +# "hOffset": 250, +# "vOffset": 250, +# "alignment": "center" +# }, +# "text": { +# "data": "Click Here", +# "size": 36, +# "style": "bold", +# "name": "text1", +# "hOffset": 250, +# "vOffset": 100, +# "alignment": "center", +# "onMouseUp": "sun1.opacity = (sun1.opacity / 100) * 90;" +# } +# } +# } +# +# NOTE: order of `key: value` pairs is not kept. +# +# You can also use a JSON string instead of vim's dict/list to maintain order: +# echo json.Format('{"hello": 1, "world": 2}') +# { +# "hello": 1, +# "world": 2 +# } + + +# To be able to reformat with `gq` add following to `~/.vim/ftplugin/json.vim`: +# import autoload 'dist/json.vim' +# setl formatexpr=json.FormatExpr() +export def FormatExpr(): number + FormatRange(v:lnum, v:lnum + v:count - 1) + return 0 +enddef + + +# import autoload 'dist/json.vim' +# command -range=% JSONFormat json.FormatRange(, ) +export def FormatRange(line1: number, line2: number) + var indent_base = matchstr(getline(line1), '^\s*') + var indent = &expandtab ? repeat(' ', &shiftwidth) : "\t" + + var [l1, l2] = line1 > line2 ? [line2, line1] : [line1, line2] + + var json_src = getline(l1, l2)->join() + var json_fmt = Format(json_src, {use_tabs: !&et, indent: &sw, indent_base: indent_base})->split("\n") + + exe $":{l1},{l2}d" + + if line('$') == 1 && getline(1) == '' + setline(l1, json_fmt[0]) + append(l1, json_fmt[1 : ]) + else + append(l1 - 1, json_fmt) + endif +enddef + + +# Format JSON string or dict/list as JSON +# import autoload 'dist/json.vim' +# echo json.Format('{"hello": "world"}', {use_tabs: false, indent: 2, indent_base: 0}) + +# { +# "hello": "world" +# } + +# echo json.Format({'hello': 'world'}, {use_tabs: false, indent: 2, indent_base: 0}) +# { +# "hello": "world" +# } +# +# Note, when `obj` is dict, order of the `key: value` pairs might be different: +# echo json.Format({'hello': 1, 'world': 2}) +# { +# "world": 2, +# "hello": 1 +# } +export def Format(obj: any, params: dict = {}): string + var obj_str = '' + if type(obj) == v:t_string + obj_str = obj + else + obj_str = json_encode(obj) + endif + + var indent_lvl = 0 + var indent_base = get(params, "indent_base", "") + var indent = get(params, "use_tabs", false) ? "\t" : repeat(' ', get(params, "indent", 2)) + var json_line = indent_base + var json = "" + var state = "" + for char in obj_str + if state == "" + if char =~ '[{\[]' + json_line ..= char + json ..= json_line .. "\n" + indent_lvl += 1 + json_line = indent_base .. repeat(indent, indent_lvl) + elseif char =~ '[}\]]' + if json_line !~ '^\s*$' + json ..= json_line .. "\n" + indent_lvl -= 1 + if indent_lvl < 0 + json_line = strpart(indent_base, -indent_lvl * len(indent)) + else + json_line = indent_base .. repeat(indent, indent_lvl) + endif + elseif json =~ '[{\[]\n$' + json = json[ : -2] + json_line = substitute(json_line, '^\s*', '', '') + indent_lvl -= 1 + endif + json_line ..= char + elseif char == ':' + json_line ..= char .. ' ' + elseif char == '"' + json_line ..= char + state = 'QUOTE' + elseif char == ',' + json_line ..= char + json ..= json_line .. "\n" + json_line = indent_base .. repeat(indent, indent_lvl) + elseif char !~ '\s' + json_line ..= char + endif + elseif state == "QUOTE" + json_line ..= char + if char == '\' + state = "ESCAPE" + elseif char == '"' + state = "" + endif + elseif state == "ESCAPE" + state = "QUOTE" + json_line ..= char + else + json_line ..= char + endif + endfor + if json_line !~ '^\s*$' + json ..= json_line .. "\n" + endif + return json +enddef -- cgit v1.2.3