Koihik / LuaFormatter

Code formatter for Lua
Apache License 2.0
681 stars 85 forks source link

Disable table inlining #174

Open Shatur opened 3 years ago

Shatur commented 3 years ago

Hi! Thank you a lot for the awesome formatter. I have a question. Is there a way to disable table inlining? For example, I have the following peace of code:

require('lualine').setup{
  options = {
    theme = zephyr_status,
    section_separators = {},
    component_separators = {'|', '|'},
  }
}

That transforms to the following:

require('lualine').setup {
  options = {theme = zephyr_status, section_separators = {}, component_separators = {'|', '|'}}
  }
}

I know about -- LuaFormatter off, but I have a lot of such places. So, maybe there is a way to disable the feature?

Koihik commented 3 years ago

It seems that 'column_limit' in your configuration is large. In fact, many different thresholds have been tried before to determine whether the table should be inline or not. Such as 'characters in table greater than 20', 'fields in table greater than 3'... These rules can lead to some strange formatted results. Now, the rule is to inline table as much as possible, unless 'column_limit' is exceeded.

Shatur commented 3 years ago

Now, the rule is to inline table as much as possible, unless 'column_limit' is exceeded.

Could we have an option to disable this behavior?

Koihik commented 3 years ago

Now, the rule is to inline table as much as possible, unless 'column_limit' is exceeded.

Could we have an option to disable this behavior?

Then the above example will become this:

require('lualine').setup {
    options = {
        theme = zephyr_status,
        section_separators = {},
        component_separators = {
            '|',
            '|'
        }
    }
}
Shatur commented 3 years ago

Then the above example will become this:

I meant to add an option to completely disable table inlining / deinlining. Is it possible?

sandersantema commented 3 years ago

I'd like to see this as well given that I personally find code formatted with a liberal use of vertical space to be a lot more readable.

Take the following example:

    use {'kassio/neoterm', config = [[require('plugins.config.neoterm')]]}
    use {'easymotion/vim-easymotion', keys = {'<Plug>(easymotion-prefix)'}}
    use {
      'christoomey/vim-tmux-navigator',
      keys = {'<C-h>', '<C-j>', '<C-k>', '<C-l>'}
    }
    use {'triglav/vim-visual-increment', opt = true, keys = {{'v', '<C-a>'}}}
    use 'romainl/vim-cool'
    use {'will133/vim-dirdiff', opt = true, cmd = 'DirDiff'}
    use {'dstein64/vim-startuptime', opt = true, cmd = 'StartupTime'}

Personally I think the following code is a lot more comprehensible:

    use {
      'kassio/neoterm',
      config = [[require('plugins.config.neoterm')]]
    }
    use {
      'easymotion/vim-easymotion',
      keys = {'<Plug>(easymotion-prefix)'}
    }
    use {
      'christoomey/vim-tmux-navigator',
      keys = {'<C-h>', '<C-j>', '<C-k>', '<C-l>'}
    }
    use {
      'triglav/vim-visual-increment',
      keys = {{'v', '<C-a>'}},
      opt = true
    }
    use 'romainl/vim-cool'
    use {
      'will133/vim-dirdiff',
      opt = true,
      cmd = 'DirDiff'
    }
    use {
      'dstein64/vim-startuptime',
      opt = true,
      cmd = 'StartupTime'
    }

Other formatters who have similar behavior (which I know of) are ormolu (haskell) and black (python). Ormolu is a particularly nice example, it's not completely automatic and wouldn't for instance format component_separators = {'|', '|'}, until you put an enter in the code such as:

component_separators = {
    '|', '|'},

after which it would format the code to:

 component_separators = {
            '|',
            '|'
        }

This means it has a high degree of user freedom without the need for any configuration.

If I understand correctly the problem currently is figuring out whether a table should be inlined or not. I can think of two solutions to solve this although I don't know about the feasibility to implement these.

  1. Replicate the ormolu behavior, automatically format tables according to the current behaviour and additionally format tables after the user has put a newline in the table.
  2. Add more options to determine whether a table should be inlined or not, for instance:
    • The length of table elements
    • The level of nested tables, given that it is more likely that a table which isn't nested shouldn't be inline and one which is should.
    • The number of items in a table, it is likely that a table containing one item should be inlined while one containing lots shouldn't

I think the second option would be a lot less feasible and furthermore hard to configure for the user to get the desired behavior. Some of the metrics to determine whether a table should be inlined are for instance only useful as a part of an overall score which should cross a threshold. Say you for instance have a table with 4 items with the maximum length of a given item being two, you'd want this table to be inlined, while you'd want a table containing 4 items but with a minimum length of a given item being 8 to be spread out over multiple lines.

Koihik commented 3 years ago

Related to #177 @sandersantema This way is the best, but it's a bit complex to program. We will consider implement it in future.

Shatur commented 3 years ago

Other formatters who have similar behavior (which I know of) are ormolu (haskell) and black (python).

Clang Tidy (C++) have also the same behavior.

tim-hilt commented 2 years ago

Chiming in to give support for this issue! Couldn't that be achieved with a regex? Something like "break after every comma, that is not inside of a pair of quotes"?