【问题标题】:How to auto format JSON on save in Vim如何在 Vim 中保存时自动格式化 JSON
【发布时间】:2014-11-30 14:10:03
【问题描述】:

说实话go 宠坏了我。通过go,我已经习惯了由我的编辑器 (vim) 强制执行的严格格式标准,并且几乎被团队中和世界各地的其他人所接受和遵循。

我想以相同的方式在保存时格式化 JSON 文件。

问题:如何在 vim 中保存时自动格式化/缩进/lint json 文件。

【问题讨论】:

标签: json vim format lint


【解决方案1】:

在 vim.org 上搜索 JSON 插件返回以下内容:

jdaddy.vim : JSON manipulation and pretty printing

描述如下:

gqaj“漂亮的打印”(换行/缩进/排序键/否则清理) 光标下的 JSON 结构。

如果它符合您期望的格式,那么您可以创建一个autocmd BufWritePre 以在保存时进行格式化。

【讨论】:

    【解决方案2】:

    在一个命令中,试试这个:

    execute '%!python -m json.tool' | w  
    

    然后您可以添加自己的键绑定,使其更简单的击键。当然,要让它工作,你需要在你的机器上安装 Python。

    【讨论】:

    • | w 这里的目的是什么?为什么不只是::%!python -m json.tool
    • |w 只是保存缓冲区,没有它,您将获得 json 格式,但更改将不会保存。这取决于我猜你想要什么。
    • 啊,对了,我明白了,我很困惑,因为我认为它是通过管道进入 bash w 命令的。但是,是的,:write 是有道理的。干杯!
    • 太棒了!默认使用 vim!
    • 我不断收到Error occured at line 1,但是当我在命令行将同一个文件放入 json.tool 时,它可以工作。我不明白为什么。
    【解决方案3】:

    感谢 mMontu 和 Jose B,这就是我最终要做的:

    警告这将覆盖您的缓冲区。因此,如果您打开一个已经存在语法错误的 json 文件,您将丢失整个文件(或可能会丢失)。

    将此行添加到您的~/.vimrc

    " Ali: to indent json files on save
    autocmd FileType json autocmd BufWritePre <buffer> %!python -m json.tool
    

    当然,你需要在你的机器上安装 python。

    编辑:如果你的 json 有错误,下一个不应该覆盖你的缓冲区。这使它成为正确的答案,但由于我对 Vim 脚本或 shell 没有很好的掌握,所以我将它作为一个实验性的东西来呈现,如果你感到幸运,你可以尝试一下。它也可能取决于您的外壳。你被警告了。

    " Ali: to indent json files on save
    autocmd FileType json autocmd BufWritePre <buffer> %!python -m json.tool 2>/dev/null || echo <buffer>
    

    【讨论】:

    • 如果 json 格式不正确,有没有办法更新它以防止写入缓冲区。在帮助窗口之一中引发错误的奖励积分。
    • 使用格式良好的 json 对其进行测试会引发错误。我没有足够的 vim 脚本来调试错误,因此我在这里问。不检查是否删除缓冲区的第一个响应非常适合格式良好的 json。
    • @NeoZenith 错误是什么?你用的是什么外壳?在什么操作系统上?什么 Vim 版本?
    • OS: OSX 10.10.5, VimVer:7.4 ErrMsg: 意外标记')'@附近的语法错误987654324@
    【解决方案4】:

    如果您热衷于使用外部工具并且正在使用 json 进行一些工作,我建议您使用 jq:

    https://stedolan.github.io/jq/

    然后,您可以在 vim 中执行:%!jq .,它将用 jq 的输出替换当前缓冲区。

    【讨论】:

    • 对于正在寻找 Windows 方式的人,请将单引号更改为双引号::%!jq "." 假设您下载了 jq 的 windows 版本,并将其从 jq-win64.exe 重命名为 jq.exe (类似 32 位版本)。另外,请确保它在您的路径中。
    • 我不必在.:%! jq . 为我工作或:%! jq --indent 4 . 周围加上引号
    • 我更喜欢 jq 而不是 python 命令,因为 python 可能会根据编码更改内容。例如。 {"test": "ü"} 其中"ü":%!python -m json.tool 之后变为"\u00fc"
    【解决方案5】:

    Vim 自动格式化

    https://github.com/Chiel92/vim-autoformat

    有这个 Vim 插件支持多种自动格式和缩进方案,以及使用每个文件类型的自定义格式化程序进行扩展。

    https://github.com/Chiel92/vim-autoformat#default-formatprograms

    注意:

    您需要安装nodejsjs-beautify,因为vim-autoformat 使用它们作为默认的外部工具。

    npm install -g js-beautify

    【讨论】:

      【解决方案6】:

      你可以搜索'vim-json-line-format'插件,在Normal mode打开一个文件,将光标移到json行,使用&lt;leader&gt;pj打印格式化的json,使用&lt;leader&gt;wj可以将文本更改为格式化的 json。 无效的json无法格式化!

      【讨论】:

        【解决方案7】:

        %!python -m json.tool

        %!python -c "import json, sys, collections; print json.dumps(json.load(sys.stdin, object_pairs_hook=collections.OrderedDict), ensure_ascii=False, indent=4)"

        你可以把它添加到你的 vimrc 中:

        com! FormatJSON %!python -m json.tool

        你可以使用:FormatJson格式的json文件

        【讨论】:

        • 非常有用,你保存了我的VIM
        • 如果你想禁用ensure_ascii或者使用你自己的indent,你可以使用com! FormatJSON %!python -m json.tool --no-ensure-ascii --indent 4。正如python -m json.tool --help 建议的那样。
        【解决方案8】:

        这是我的解决方案。它没有完全解决“保存时”的问题部分,但如果您在保存之前执行此操作,它将输出错误,您可以在保存之前修复。

        另外,它只依赖于一个外部工具——jq——它已经成为了 unix shell JSON 处理工具的黄金标准。并且您可能已经安装了(仅限 macOS 和 Linux/Unix;想知道这在 Windows 中会如何表现)

        基本上就是:

        ggVG!jq '.'
        

        这将突出显示整个 JSON 文档,然后通过 jq 运行它,它将解析它的正确性,重新格式化它(例如修复任何缩进等),并将输出返回到 Vim 编辑器。

        如果您只想解析文档的一部分,可以通过按vV 手动突出显示该部分,然后运行

        !jq '.'
        

        这样做的好处是您可以通过这种方式修复文档的小节。

        【讨论】:

        • 更快—:%!jq '.'
        • @D.BenKnoble 是的,我在较早的答案中看到了这一点,但直到我已经输入了 95% 的我自己的答案才看到它。所以我还是提交了我的答案。
        • 你甚至不必把点,它是隐含的
        【解决方案9】:

        我做了一些整理(虽然其中一些与 vim 无关)并自己在neovim上编写脚本!

        解决方案1:neovim

        1-1:自己写脚本

        Neovim 允许通过将 Python 文件或包放在 rplugin/python3/ 中的 runtimepath 文件夹中来定义 Python3 插件)

        就我而言

        - init.vim
        - rplugin/python3/[your_py_file_set].py
        - rplugin/python3/fmt_file.py
        

        fmt_file.py 如下

        # rplugin/python3/fmt_file.py
        
        import pynvim
        import json
        
        
        @pynvim.plugin
        class Plugin:
            __slots__ = ('vim',)
        
            def __init__(self, vim):
                self.vim = vim
        
            @pynvim.command('FormatJson', nargs='*', range='')
            def format_json(self, args, rg):
                """
                USAGE::
        
                    :FormatJson
                """
                try:
                    buf = self.vim.current.buffer
                    json_content: str = '\n'.join(buf[:])
                    dict_content: dict = json.loads(json_content)
                    new_content: str = json.dumps(dict_content, indent=4, sort_keys=True)
                    buf[:] = new_content.split('\n')
                except Exception as e:
                    self.vim.current.line = str(e)
        

        然后在Nvim 内运行一次::UpdateRemotePlugins,以生成必要的 Vimscript 以使您的插件可用。 (你最好重启 neovim

        然后,您打开要格式化的 JSON 文件并在命令中键入::FormatJson。全部完成。


        别忘了告诉 vim 你的 python 在哪里

        " init.vim
        
        let g:python3_host_prog = '...\python.exe''
        

        pip install pynvim

        1-2:使用tool.py

        ​​>

        tool.py 位于Lib/json/tool.py 上的位置

        :%!python -m json.tool

        解决方案2:命令行

        如果你已经安装了python,可以打开命令行:

        python -m json.tool "test.json" >> "output.json"
        

        解决方案3:蟒蛇

        我为这些事情写了一个简单的脚本。

        """
        USAGE::
        
            python fmt_file.py fmt-json "C:\test\test.json"
            python fmt_file.py fmt-json "C:\test\test.json"  --out_path="abc.json"
            python fmt_file.py fmt-json "test.json"  --out_path="abc.json"
        """
        
        import click  # pip install click
        from click.types import File
        import json
        from pathlib import Path
        
        
        @click.group('json')
        def gj():
            ...
        
        
        @gj.command('fmt-json')
        @click.argument('file_obj', type=click.File('r', encoding='utf-8'))
        @click.option('--out_path', default=None, type=Path, help='output path')
        def format_json(file_obj: File, out_path: Path):
            new_content = ''
            with file_obj as f:
                buf_list = [_ for _ in f]
                if buf_list:
                    json_content: str = '\n'.join(buf_list)
                    dict_content: dict = json.loads(json_content)
                    new_content: str = json.dumps(dict_content, indent=4, sort_keys=True)
        
            if new_content:
                with open(out_path if out_path else Path('./temp.temp_temp.json'),
                          'w', encoding='utf-8') as f:
                    f.write(new_content)
        
        
        def main():
            for register_group in (gj,):
                register_group()
        
        
        if __name__ == '__main__':
            main()
        

        【讨论】:

          【解决方案10】:

          另一种解决方案是使用coc-format-json

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2012-06-13
            • 2018-08-05
            • 1970-01-01
            • 2017-10-07
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多