【分享】修复yaml-mode格式化问题

一直以来 yaml-mode 都有一个问题,在使用 (indent-region (point-min) (point-max)) 时已经格式好的内容总是会得到错误的缩进,比如一个简单的配置

test1: "val"
test2:
  - "val1"
  - "val2"
test3:
  test4: "val4"

在调用 indent-regin 后就会变成

test1: "val"
test2:
  - "val1"
  - "val2"
  test3:
    test4: "val4"

而我又总是手痒,写好的配置文件总是会忍不住 indent-region 一番,结果本来正确的格式立马变得各种乱七八糟,当初为了解决这个问题,还专门为 yaml-mode 激活了 lsp-mode, 并且使用 lsp-format-buffer 来进行处理。

本来一切都还正常,但最近发现了另外一个问题,如果在 org-mode 中插入 yaml 的代码片段,调用 indent-region 还是还有之前的问题, org-mode 中又无法直接调用 lsp-format-buffer, 所以专门研究了一下 yaml-mode

发现 yaml-mode 只是定义了 indent-line-function 变量,没有定义 indent-region-function, 导致调用 indent-region 时其实是逐行调用 yaml-indent-line, 这里面有一个计算当前缩进的 yaml-compute-indentation 函数,计算方式有些简单粗暴,如果上一行是一个 hash key, 当前行的缩进就是上一行的缩进加 yaml-indent-offset 的值, 这里并没有判断当前行是新建行还是已经有相关内容,如果是新建行那么缩进就是对的,如果是已有的内容就是错的,所以我修改了这一部分逻辑,如果是 已有内容并且当前行的缩进小于上一行 则不进行处理, 比如:

  - "val2"
test3:

虽然增加的判断逻辑很简单,但至少在使用 indent-region 时已经格式好的内容就不会出现混乱的情况了, 也不用专门为 yaml 文件激活一个 lsp 进程。

目前处理的方式还是采用 advice + letf 形式,否则需要修改很多内容,有兴趣的同道可以参考一下

直接去提pr呀,上次我也提了一个,不过维护者要等很久才修。

如果是提pr就不是加一个当前缩进小于上一行缩进判断逻辑这么简单了,说不准还需要复制一份indent-region-line-by-line 的代码,这个有时间再理一下 :joy: