conform.nvim icon indicating copy to clipboard operation
conform.nvim copied to clipboard

Documentation: Simple recipe/example for custom formatter as a function

Open caleskog opened this issue 1 year ago • 2 comments

I was working with C++ and OpenMP, and I stumbled upon an annoying non-optional behavior of clang-format regarding pragmas. I looked into the documentation for clang-format, but it was impossible to change it. So I tried to fix it using comform.nvim instead. Essentially, I want to indent the #pragma omp ... lines so it matches the rest of the code.

Problem: The problem is that there is almost no documentation for custom formatters as functions. One can look at the injected.lua code, but it is cluttered with code specific to that formatter.

Suggestion: Adding a recipe for a simple function-based formatter. This hack solution for the clang-format issue is inspired by the GitHub repo: MedicineYeh/p-clang-format.

require('conform').setup({
  formatters = {
    ['clang-fmt-pre'] = {
      ---Replace all `#pragma omp ...` with `//#pragma omp ...`
        format = function(self, ctx, lines, callback)
          -- Use this variable if options should be possible
          local _ = self.options
          local format_erros = nil
          local formatted_lines = vim.deepcopy(lines)
          local pattern = '^%s*#pragma omp'
          for i, line in ipairs(lines) do
            if line:match(pattern) then
              local fmt_line = line:gsub(pattern, '//#pragma omp')
              formatted_lines[i] = fmt_line
          end
        end
      callback(format_erros, formatted_lines)
      end
    },
    ['clang-fmt-post'] = {
      ---Replace all `//#pragma omp ...` with `#pragma omp ...`
      format = function(self, ctx, lines, callback)
        -- Use this variable if options should be possible
        local _ = self.options
        local format_erros = nil
        local formatted_lines = vim.deepcopy(lines)
        local pattern = '//%s#pragma omp'
        for i, line in ipairs(formatted_lines) do
          if line:match(pattern) then
            formatted_lines[i] = line:gsub(pattern, '#pragma omp')
          end
        end
      callback(format_erros, formatted_lines)
      end,
    },
  },
  formatters_by_ft = {
    cpp = { 'clang-fmt-pre', 'clang-format', 'clang-fmt-post' },
  },
)}

caleskog avatar Jul 23 '24 15:07 caleskog

In 2270fa1 I refactored trim_whitespace and trim_newlines to use the lua function format instead of awk. Would those serve as sufficient examples?

stevearc avatar Jul 23 '24 16:07 stevearc

Yes, they are perfect. Might be good to reference those two in the README.md, too, so it's easy to find. Like including it under the Options section. As the format option is not mentioned.

caleskog avatar Jul 23 '24 17:07 caleskog