CppCXY / EmmyLuaCodeStyle

fast, powerful, and feature-rich Lua formatting and checking tool.
MIT License
140 stars 27 forks source link

feat: 支持范围禁用格式化 #96

Closed JuanZoran closed 1 year ago

JuanZoran commented 1 year ago

大部分时间,格式化的效果都令人满意,但是有时缩进和对齐是奇怪的,大部分其他格式化都支持通过注释来禁止一段代码块格式化,比如 -- stylua ignore -- LuaFormatter off 如果这个工具也可以添加类似的注释符来支持自定义格式化块,那就完美了

CppCXY commented 1 year ago

以前某个版本是有的, 后面在0.18到1.0的升级过程中我没有实现这个特性. 因为我更倾向于实现目标格式而不是屏蔽这里的格式. (主要是我觉得加个这样的注释太丑了

JuanZoran commented 1 year ago

貌似是---@format disable之类的? 我还把这个一段代码作为了一个snippet,后来发现不奏效了,我以为是我记错了,这个功能其实还是挺重要的,不同情况的代码同一的格式化选项并不能适用于所有选项,现在在床上,等我明天提供一些目前格式化情况有些奇怪的例子

JuanZoran commented 1 year ago

如果大佬有余力的话,还是建议加回这一个功能吧,目前其他的格式化用着还是不如这个项目,目前的痛点就是没有disable的选项了

CppCXY commented 1 year ago

当时是实现的两个---@format disable 屏蔽该语句在当前作用域之下的所有格式化还有个是---@format disable-next 仅仅屏蔽下一个语句的格式化, 这种实现常见于eslint, clang-format. 我觉得用注释括起来的范围是邪道.

JuanZoran commented 1 year ago

考虑有以下代码:

    local width =
        window and window:is_valid() and
            (opts.auto_resize and
                math.max(
                    math.min(opts.width, util.display_width(lines) + opts.padding),
                    math.min(data.str:width(), opts.split_width)
                )
            or opts.width)
        or math.min(opts.width, util.display_width(lines) + opts.padding)

这是我个人倾向于的结果, 但是不管如何配置格式化, 都会被格式化成这样

    local width =
        window and window:is_valid() and
        (opts.auto_resize and
        math.max(
            math.min(opts.width, util.display_width(lines) + opts.padding),
            math.min(data.str:width(), opts.split_width)
        )
        or opts.width)
        or math.min(opts.width, util.display_width(lines) + opts.padding)

我觉得这样的格式化, 反而让代码的可读性降低了, 同样的情况还有在对齐上... 这个需求还是很重要的....或者大佬没有有兴趣及写出一个贡献文档, 我有空了贡献一下代码也行

JuanZoran commented 1 year ago

对齐的情况, 比如定义一大串keymap:

local keys = {

    { '<C-k>',         '<Cmd>DapStepInto<CR>',                            desc = "Step Into"         },
    { '<leader>eo',    '<Cmd>DapStepOut<CR>',                             desc = "Step Out"          },
    { '<leader>eO',    '<Cmd>DapStepOver<CR>',                            desc = "Step Over"         },
    { '<leader>er',    '<Cmd>DapToggleRepl<CR>',                          desc = "Toggle Repl"       },
    { '<leader>et',    '<Cmd>DapTerminate<CR>',                           desc = "Terminate"         },
    { '<leader>ee',    '<Cmd>DapToggleBreakpoint<CR>',                    desc = "Toggle Breakpoint" },
    { "<leader>e<Cr>", function() require('osv').run_this() end,          desc = "Start To Debug"    },
    { "<C-i>",         function() require 'dap'.step_back() end,          desc = "Step Back"         },
    { "<leader>eh",    function() require 'dap'.run_to_cursor() end,      desc = "Run to Cursor"     },
    { "<leader>eq",    function() require 'dap'.close() end,              desc = "Quit"              },
    { "<leader>eg",    function() require 'dap'.session() end,            desc = "Get Session"       },
    { "<leader>ec",    function() require 'dap'.continue() end,           desc = "Continue"          },
    { "<leader>ep",    function() require 'dap'.pause.toggle() end,       desc = "Pause"             },
    { "<leader>eh",    function() require 'dap.ui.widgets'.hover() end,   desc = "Hover"             },
    { "<leader>eu",    function() require 'dap.ui.widgets'.preview() end, desc = "Preview"           },
}

已经对齐右括号的情况下, 进行格式化就会打破右括号的格式化, 变成这样:

    { '<C-k>',         '<Cmd>DapStepInto<CR>',                            desc = 'Step Into' },
    { '<leader>eo',    '<Cmd>DapStepOut<CR>',                             desc = 'Step Out' },
    { '<leader>eO',    '<Cmd>DapStepOver<CR>',                            desc = 'Step Over' },
    { '<leader>er',    '<Cmd>DapToggleRepl<CR>',                          desc = 'Toggle Repl' },
    { '<leader>et',    '<Cmd>DapTerminate<CR>',                           desc = 'Terminate' },
    { '<leader>ee',    '<Cmd>DapToggleBreakpoint<CR>',                    desc = 'Toggle Breakpoint' },
    { '<leader>e<Cr>', function() require 'osv'.run_this() end,           desc = 'Start To Debug' },
    { '<C-i>',         function() require 'dap'.step_back() end,          desc = 'Step Back' },
    { '<leader>eh',    function() require 'dap'.run_to_cursor() end,      desc = 'Run to Cursor' },
    { '<leader>eq',    function() require 'dap'.close() end,              desc = 'Quit' },
    { '<leader>eg',    function() require 'dap'.session() end,            desc = 'Get Session' },
    { '<leader>ec',    function() require 'dap'.continue() end,           desc = 'Continue' },
    { '<leader>ep',    function() require 'dap'.pause.toggle() end,       desc = 'Pause' },
    { '<leader>eh',    function() require 'dap.ui.widgets'.hover() end,   desc = 'Hover' },
    { '<leader>eu',    function() require 'dap.ui.widgets'.preview() end, desc = 'Preview' },
CppCXY commented 1 year ago

对齐的情况, 比如定义一大串keymap:

local keys = {

    { '<C-k>',         '<Cmd>DapStepInto<CR>',                            desc = "Step Into"         },
    { '<leader>eo',    '<Cmd>DapStepOut<CR>',                             desc = "Step Out"          },
    { '<leader>eO',    '<Cmd>DapStepOver<CR>',                            desc = "Step Over"         },
    { '<leader>er',    '<Cmd>DapToggleRepl<CR>',                          desc = "Toggle Repl"       },
    { '<leader>et',    '<Cmd>DapTerminate<CR>',                           desc = "Terminate"         },
    { '<leader>ee',    '<Cmd>DapToggleBreakpoint<CR>',                    desc = "Toggle Breakpoint" },
    { "<leader>e<Cr>", function() require('osv').run_this() end,          desc = "Start To Debug"    },
    { "<C-i>",         function() require 'dap'.step_back() end,          desc = "Step Back"         },
    { "<leader>eh",    function() require 'dap'.run_to_cursor() end,      desc = "Run to Cursor"     },
    { "<leader>eq",    function() require 'dap'.close() end,              desc = "Quit"              },
    { "<leader>eg",    function() require 'dap'.session() end,            desc = "Get Session"       },
    { "<leader>ec",    function() require 'dap'.continue() end,           desc = "Continue"          },
    { "<leader>ep",    function() require 'dap'.pause.toggle() end,       desc = "Pause"             },
    { "<leader>eh",    function() require 'dap.ui.widgets'.hover() end,   desc = "Hover"             },
    { "<leader>eu",    function() require 'dap.ui.widgets'.preview() end, desc = "Preview"           },
}

已经对齐右括号的情况下, 进行格式化就会打破右括号的格式化, 变成这样:

    { '<C-k>',         '<Cmd>DapStepInto<CR>',                            desc = 'Step Into' },
    { '<leader>eo',    '<Cmd>DapStepOut<CR>',                             desc = 'Step Out' },
    { '<leader>eO',    '<Cmd>DapStepOver<CR>',                            desc = 'Step Over' },
    { '<leader>er',    '<Cmd>DapToggleRepl<CR>',                          desc = 'Toggle Repl' },
    { '<leader>et',    '<Cmd>DapTerminate<CR>',                           desc = 'Terminate' },
    { '<leader>ee',    '<Cmd>DapToggleBreakpoint<CR>',                    desc = 'Toggle Breakpoint' },
    { '<leader>e<Cr>', function() require 'osv'.run_this() end,           desc = 'Start To Debug' },
    { '<C-i>',         function() require 'dap'.step_back() end,          desc = 'Step Back' },
    { '<leader>eh',    function() require 'dap'.run_to_cursor() end,      desc = 'Run to Cursor' },
    { '<leader>eq',    function() require 'dap'.close() end,              desc = 'Quit' },
    { '<leader>eg',    function() require 'dap'.session() end,            desc = 'Get Session' },
    { '<leader>ec',    function() require 'dap'.continue() end,           desc = 'Continue' },
    { '<leader>ep',    function() require 'dap'.pause.toggle() end,       desc = 'Pause' },
    { '<leader>eh',    function() require 'dap.ui.widgets'.hover() end,   desc = 'Hover' },
    { '<leader>eu',    function() require 'dap.ui.widgets'.preview() end, desc = 'Preview' },

这个可以加个选项让括号也参与对齐

JuanZoran commented 1 year ago

对齐的情况, 比如定义一大串keymap:

local keys = {

    { '<C-k>',         '<Cmd>DapStepInto<CR>',                            desc = "Step Into"         },
    { '<leader>eo',    '<Cmd>DapStepOut<CR>',                             desc = "Step Out"          },
    { '<leader>eO',    '<Cmd>DapStepOver<CR>',                            desc = "Step Over"         },
    { '<leader>er',    '<Cmd>DapToggleRepl<CR>',                          desc = "Toggle Repl"       },
    { '<leader>et',    '<Cmd>DapTerminate<CR>',                           desc = "Terminate"         },
    { '<leader>ee',    '<Cmd>DapToggleBreakpoint<CR>',                    desc = "Toggle Breakpoint" },
    { "<leader>e<Cr>", function() require('osv').run_this() end,          desc = "Start To Debug"    },
    { "<C-i>",         function() require 'dap'.step_back() end,          desc = "Step Back"         },
    { "<leader>eh",    function() require 'dap'.run_to_cursor() end,      desc = "Run to Cursor"     },
    { "<leader>eq",    function() require 'dap'.close() end,              desc = "Quit"              },
    { "<leader>eg",    function() require 'dap'.session() end,            desc = "Get Session"       },
    { "<leader>ec",    function() require 'dap'.continue() end,           desc = "Continue"          },
    { "<leader>ep",    function() require 'dap'.pause.toggle() end,       desc = "Pause"             },
    { "<leader>eh",    function() require 'dap.ui.widgets'.hover() end,   desc = "Hover"             },
    { "<leader>eu",    function() require 'dap.ui.widgets'.preview() end, desc = "Preview"           },
}

已经对齐右括号的情况下, 进行格式化就会打破右括号的格式化, 变成这样:

    { '<C-k>',         '<Cmd>DapStepInto<CR>',                            desc = 'Step Into' },
    { '<leader>eo',    '<Cmd>DapStepOut<CR>',                             desc = 'Step Out' },
    { '<leader>eO',    '<Cmd>DapStepOver<CR>',                            desc = 'Step Over' },
    { '<leader>er',    '<Cmd>DapToggleRepl<CR>',                          desc = 'Toggle Repl' },
    { '<leader>et',    '<Cmd>DapTerminate<CR>',                           desc = 'Terminate' },
    { '<leader>ee',    '<Cmd>DapToggleBreakpoint<CR>',                    desc = 'Toggle Breakpoint' },
    { '<leader>e<Cr>', function() require 'osv'.run_this() end,           desc = 'Start To Debug' },
    { '<C-i>',         function() require 'dap'.step_back() end,          desc = 'Step Back' },
    { '<leader>eh',    function() require 'dap'.run_to_cursor() end,      desc = 'Run to Cursor' },
    { '<leader>eq',    function() require 'dap'.close() end,              desc = 'Quit' },
    { '<leader>eg',    function() require 'dap'.session() end,            desc = 'Get Session' },
    { '<leader>ec',    function() require 'dap'.continue() end,           desc = 'Continue' },
    { '<leader>ep',    function() require 'dap'.pause.toggle() end,       desc = 'Pause' },
    { '<leader>eh',    function() require 'dap.ui.widgets'.hover() end,   desc = 'Hover' },
    { '<leader>eu',    function() require 'dap.ui.widgets'.preview() end, desc = 'Preview' },

这个可以加个选项让括号也参与对齐

已有的选项可以做到吗,但是这样的情况不这一种把,还有等号对齐,有底部有一个很长的,就会全部对齐到那个最长的,还有一些其他的问题,为什么不考虑恢复---@format disable呢

CppCXY commented 1 year ago

考虑有以下代码:

    local width =
        window and window:is_valid() and
            (opts.auto_resize and
                math.max(
                    math.min(opts.width, util.display_width(lines) + opts.padding),
                    math.min(data.str:width(), opts.split_width)
                )
            or opts.width)
        or math.min(opts.width, util.display_width(lines) + opts.padding)

这是我个人倾向于的结果, 但是不管如何配置格式化, 都会被格式化成这样

    local width =
        window and window:is_valid() and
        (opts.auto_resize and
        math.max(
            math.min(opts.width, util.display_width(lines) + opts.padding),
            math.min(data.str:width(), opts.split_width)
        )
        or opts.width)
        or math.min(opts.width, util.display_width(lines) + opts.padding)

我把这段代码改成js和C++拿去格式化都没有看到相同的格式, 那这应该属于个人喜好了.

我觉得这样的格式化, 反而让代码的可读性降低了, 同样的情况还有在对齐上... 这个需求还是很重要的....或者大佬没有有兴趣及写出一个贡献文档, 我有空了贡献一下代码也行

实现这个特性的主要问题是:

  1. parser只处理了lua语法, 要实现---@format disable-next就需要实现对注解的解析, 这个复杂性比较大. sumneko lua都是做的二次分析再绑定的注释.
  2. 以前为什么能实现这个特性, 是因为现在和以前代码几乎都不一样了, 以前属于是大力出奇迹了, 代码里面全是workaround, 实现方式我都看不下去.
  3. 当然对于这个现在如何实现我心里是有一些想法的, 如果你能提出符合我想法的parser方式, 那也不是不能实现.
CppCXY commented 1 year ago

对齐的情况, 比如定义一大串keymap:

local keys = {

    { '<C-k>',         '<Cmd>DapStepInto<CR>',                            desc = "Step Into"         },
    { '<leader>eo',    '<Cmd>DapStepOut<CR>',                             desc = "Step Out"          },
    { '<leader>eO',    '<Cmd>DapStepOver<CR>',                            desc = "Step Over"         },
    { '<leader>er',    '<Cmd>DapToggleRepl<CR>',                          desc = "Toggle Repl"       },
    { '<leader>et',    '<Cmd>DapTerminate<CR>',                           desc = "Terminate"         },
    { '<leader>ee',    '<Cmd>DapToggleBreakpoint<CR>',                    desc = "Toggle Breakpoint" },
    { "<leader>e<Cr>", function() require('osv').run_this() end,          desc = "Start To Debug"    },
    { "<C-i>",         function() require 'dap'.step_back() end,          desc = "Step Back"         },
    { "<leader>eh",    function() require 'dap'.run_to_cursor() end,      desc = "Run to Cursor"     },
    { "<leader>eq",    function() require 'dap'.close() end,              desc = "Quit"              },
    { "<leader>eg",    function() require 'dap'.session() end,            desc = "Get Session"       },
    { "<leader>ec",    function() require 'dap'.continue() end,           desc = "Continue"          },
    { "<leader>ep",    function() require 'dap'.pause.toggle() end,       desc = "Pause"             },
    { "<leader>eh",    function() require 'dap.ui.widgets'.hover() end,   desc = "Hover"             },
    { "<leader>eu",    function() require 'dap.ui.widgets'.preview() end, desc = "Preview"           },
}

已经对齐右括号的情况下, 进行格式化就会打破右括号的格式化, 变成这样:

    { '<C-k>',         '<Cmd>DapStepInto<CR>',                            desc = 'Step Into' },
    { '<leader>eo',    '<Cmd>DapStepOut<CR>',                             desc = 'Step Out' },
    { '<leader>eO',    '<Cmd>DapStepOver<CR>',                            desc = 'Step Over' },
    { '<leader>er',    '<Cmd>DapToggleRepl<CR>',                          desc = 'Toggle Repl' },
    { '<leader>et',    '<Cmd>DapTerminate<CR>',                           desc = 'Terminate' },
    { '<leader>ee',    '<Cmd>DapToggleBreakpoint<CR>',                    desc = 'Toggle Breakpoint' },
    { '<leader>e<Cr>', function() require 'osv'.run_this() end,           desc = 'Start To Debug' },
    { '<C-i>',         function() require 'dap'.step_back() end,          desc = 'Step Back' },
    { '<leader>eh',    function() require 'dap'.run_to_cursor() end,      desc = 'Run to Cursor' },
    { '<leader>eq',    function() require 'dap'.close() end,              desc = 'Quit' },
    { '<leader>eg',    function() require 'dap'.session() end,            desc = 'Get Session' },
    { '<leader>ec',    function() require 'dap'.continue() end,           desc = 'Continue' },
    { '<leader>ep',    function() require 'dap'.pause.toggle() end,       desc = 'Pause' },
    { '<leader>eh',    function() require 'dap.ui.widgets'.hover() end,   desc = 'Hover' },
    { '<leader>eu',    function() require 'dap.ui.widgets'.preview() end, desc = 'Preview' },

这个可以加个选项让括号也参与对齐

已有的选项可以做到吗,但是这样的情况不这一种把,还有等号对齐,有底部有一个很长的,就会全部对齐到那个最长的,还有一些其他的问题,为什么不考虑恢复---@Format disable呢

没有现成的选项, 整个对齐是连续的算法, 如果你觉得底部那个太长了,就让他和上面的代码间隔2行

CppCXY commented 1 year ago

当前算法貌似会清理表内的空行, 这是一个BUG

JuanZoran commented 1 year ago

考虑有以下代码:

    local width =
        window and window:is_valid() and
            (opts.auto_resize and
                math.max(
                    math.min(opts.width, util.display_width(lines) + opts.padding),
                    math.min(data.str:width(), opts.split_width)
                )
            or opts.width)
        or math.min(opts.width, util.display_width(lines) + opts.padding)

这是我个人倾向于的结果, 但是不管如何配置格式化, 都会被格式化成这样

    local width =
        window and window:is_valid() and
        (opts.auto_resize and
        math.max(
            math.min(opts.width, util.display_width(lines) + opts.padding),
            math.min(data.str:width(), opts.split_width)
        )
        or opts.width)
        or math.min(opts.width, util.display_width(lines) + opts.padding)

我把这段代码改成js和C++拿去格式化都没有看到相同的格式, 那这应该属于个人喜好了.

我觉得这样的格式化, 反而让代码的可读性降低了, 同样的情况还有在对齐上... 这个需求还是很重要的....或者大佬没有有兴趣及写出一个贡献文档, 我有空了贡献一下代码也行

实现这个特性的主要问题是:

  1. parser只处理了lua语法, 要实现---@format disable-next就需要实现对注解的解析, 这个复杂性比较大. sumneko lua都是做的二次分析再绑定的注释.
  2. 以前为什么能实现这个特性, 是因为现在和以前代码几乎都不一样了, 以前属于是大力出奇迹了, 代码里面全是workaround, 实现方式我都看不下去.
  3. 当然对于这个现在如何实现我心里是有一些想法的, 如果你能提出符合我想法的parser方式, 那也不是不能实现.

好吧,有空读一下代码,再想想有没有优雅一点的解决方式吧

JuanZoran commented 1 year ago

大佬有没有考虑做一个contributing.md, 写一下仓库结构和主要思想, 我有兴趣贡献一些代码

CppCXY commented 1 year ago

大佬有没有考虑做一个contributing.md, 写一下仓库结构和主要思想, 我有兴趣贡献一些代码

你先看一下代码吧. 从parser 看起, CodeService 是全部逻辑, 一般测试可以用Test2这个项目. 代码格式参考clang-format, 别的也没啥了.

JuanZoran commented 1 year ago

---@format disable生效了, 但是貌似---@format enable没有作用, 是没有支持吗

CppCXY commented 1 year ago

没说要有啊, ---@format disable 影响的范围是当前作用域内,该语句之下, 粒度更小的是 ---@format disable-next 影响下一个非注释语句

CppCXY commented 1 year ago

也就是可以这样用

local t = {}
function f()
    ---@format disable
    local t =123
    ddd =123
end

local c = 123
JuanZoran commented 1 year ago

好吧, 感谢