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

feature request: add auto-indent (`gg=G` / `indentexpr`) as special formatter

Open chrisgrieser opened this issue 1 year ago • 8 comments

Did you check existing requests?

  • [X] I have searched the existing issues

Describe the feature

For some filetypes without formatters available, I found using a simple mapping to run gg=G useful to get at least some auto-formatting. It would be nice, if gg=G was available as a dedicated formatter for conform.nvim, similar to other special formatters like squeeze_blank or trim_newlines.

Provide background

It's another useful addition for the fallback filetype ["_"]. There are some filetypes where you either through treesitter or through "old vim" information on how to auto-indent (I believe it's opt.indentexpr?), but no formatter tooling. .scm files (treesitter query files) are one example.

What is the significance of this feature?

nice to have

Additional details

No response

chrisgrieser avatar Dec 28 '23 23:12 chrisgrieser

These two can be considered:

  • Indent formatter w.r.t. indentexpr (what OP requested)
  • The built-in formatter (gw), w.r.t. formatoptions

in the abstraction. Related to #269

wookayin avatar Jan 08 '24 12:01 wookayin

I have written my custom formatter for this:

  opts = {
    formatters_by_ft = {
      gitconfig = { 'trim_whitespace', 'trim_newlines', 'my_auto_indent' },
    },
    formatters = {
      -- Custom formatter to auto indent buffer.
      my_auto_indent = {
        format = function(_, _, _, callback)
          vim.cmd.normal('m`gg=G``')
          callback()
        end,
      },
    },
  },

tigion avatar Sep 09 '24 10:09 tigion

@tigion

Well that was easier than expected. Good idea! Minor modification, the snippet should use

vim.cmd.normal { "m`gg=G``", bang = true }

I'd suggest adding this one as built-in formatter via PR?

chrisgrieser avatar Sep 09 '24 10:09 chrisgrieser

I think it still needs to be checked whether an area is selected and then only take = for this.

I only used it for the complete buffer so far.

tigion avatar Sep 09 '24 15:09 tigion

Now with selection support in visual mode:

      my_auto_indent = {
        format = function(_, ctx, _, callback)
          -- save cursor position in ` mark -> indent -> restore cursor position
          if ctx.range == nil then
            -- no range, use whole buffer
            vim.cmd.normal({ 'm`gg=G``', bang = true })
          else
            -- use range
            vim.cmd.normal({ 'm`=``', bang = true })
          end
          callback()
        end,
      },

Why is bang = true needed?

tigion avatar Sep 10 '24 07:09 tigion

Why is bang = true needed?

Without, any remapping for = or gg or m the user has well change the behavior of the normal command. See :h normal.

chrisgrieser avatar Sep 10 '24 10:09 chrisgrieser

A shorter version:

      -- Custom formatter to auto indent buffer.
      -- - Indents with neovim's builtin indentation `=`.
      -- - Saves and restores cursor position in ` mark.
      my_auto_indent = {
        format = function(_, ctx, _, callback)
          -- no range, use whole buffer otherwise use selection
          local cmd = ctx.range == nil and 'gg=G' or '='
          vim.cmd.normal({ 'm`' .. cmd .. '``', bang = true })
          callback()
        end,
      },

tigion avatar Sep 11 '24 05:09 tigion