Enter-tainer / typstyle

Beautiful and reliable typst code formatter
https://enter-tainer.github.io/typstyle
Apache License 2.0
315 stars 10 forks source link

[ FEATURE ] Format #table in a human readable way #59

Open LamprosPitsillos opened 6 months ago

LamprosPitsillos commented 6 months ago

https://github.com/astrale-sharp/typstfmt/discussions/170#discussion-6548338

Would it be possible to format tables in a way that makes since while reading them ?

example

#table( columns: 2,
  table.header([ Example ], [ Name ]), [ twowords ], [ flatcase ], [ TWOWORDS ], [ UPPERCASE ], [ twoWords ], [ camelCase ], [ TwoWords ], [ PascalCase ], [ two_words ], [ snake_case ], [ TWO_WORDS ], [ SCREAMING_SNAKE_CASE ], [ two_Words ], [ camel_Snake_Case ], [ Two_Words ], [ Pascal_Snake_Case ], [ two-words ], [ kebab-case ], [ TWO-WORDS ], [ SCREAMING-KEBAB-CASE ], [ Two-Words ], [ Train-Case ], [ \_two_words ], [ INTERNAL ],table.cell(colspan:2,[hello])
)
#table(columns:2,
table.header([Formatting],[Name]),
[twowords],[flatcase],
[TWOWORDS],[UPPERCASE],
[twoWords],[camelCase],
[TwoWords],[PascalCase],
[two_words],[snake_case],
[TWO_WORDS],[SCREAMING_SNAKE_CASE],
[two_Words],[camel_Snake_Case],
[Two_Words],[Pascal_Snake_Case],
[two-words],[kebab-case],
[TWO-WORDS],[SCREAMING-KEBAB-CASE],
[Two-Words],[Train-Case],
[\_two_words],[INTERNAL],
table.cell(colspan:2,[hello])

)
Enter-tainer commented 6 months ago

tracking in #17

Enter-tainer commented 5 months ago

The initial idea is to match patterns like grid/table(columns: $n, $cells).

We may put n cells in a line if they can fit in a line. Otherwise we spread them into multiple lines.(This still doesn't sounds good. Do you have better ideas?

LamprosPitsillos commented 5 months ago

Maybe indent the leftover ones a bit?

line fits 3 cells*
table(columns : $n+3 , $cells...)

~~~~

foo bar baz
       faz loo soo saz
xoo xaz raz
       laz  baz laz

Also maybe try to include *span since it will break a lot of the logic otherwise

Enter-tainer commented 5 months ago

colspan, rowspan and cell will very likely to be not supported in the initial MVP. But i think it can be supported once we have a good framework to deal with normal tables

Myriad-Dreamin commented 5 months ago

If there is any span element (e.g. rowspan) or spreading arguments (e.g. ...row), we may expand it (default formatting for function calls).

I paste three table formatting here that looks beautiful imo:

  1. compacted:

    #table(rows=3,
    [1], [2], [3],
    [1], [2], [3],
    [1], [2], [3],
    )

    2 multiple line with parbreak separated:

    #table(rows=3,
    [1],
    [2],
    [3],
    
    [1],
    [2],
    [3],
    
    [1],
    [2],
    [3],
    )

    3 simulate the header's shape:

    #table(rows=3,
    [time],  [event],
    [notes],
    
    [ 9:00], [washing], // just align with the header
    [and other things],
    
    [12:00], [moyu],
    [and other things],
    )
Enter-tainer commented 5 months ago

Currently i have implement table format if a table:

  1. no comments
  2. no spread args
  3. no named args, or named args appears before all pos args
  4. no table/grid.header/footer/vline/hline/cell
  5. columns is int or array
Enter-tainer commented 5 months ago

i'm going to support header/footer/vline/hline in the next step

Enter-tainer commented 5 months ago

Currently i have implement table format if a table:

  1. no comments
  2. no spread args
  3. no named args, or named args appears before all pos args
  4. no function call
  5. columns is int or array

I think the limitation can be somehow loosed to follows:

  1. no comments
  2. no spread args
  3. no named args, or named args appears before all pos args
  4. no table/grid.vline/hline/cell
  5. columns is int or array

This allows header/footer usage, which will possibly help #78(Although the author doesn't provide their code yet). To format them, we can put header/footer in a single line.

Enter-tainer commented 4 months ago

Another way is that for table, we only format each args and don't change newlines, so user can freely arrange their cells. This can be a fallback code path.

Myriad-Dreamin commented 4 months ago

Inspired by https://typst.app/universe/package/pillar's string command, we may have some general macro to hint formatting to call, which could also be the intermediate structure between smart formatters and the base formatter.

  1. the macro is:

    // @typstyle:call-group=4|4+,{1,_,2},4
    // `|`: a line caused by the mid line in `call-group` macro
    // `4+`: multiple arguments are group by 4.
    #table([],[],[],[], [],[],[],[], [],[],[], [],[],[],[])

    is formatted as:

    // @typstyle:call-group=4|4+,{1,_,2},4
    #table(
    [],[],[],[],
    
    [],[],[],[],
    [],   [],[],
    [],[],[],[],
    )
    1. A smart formatter looks like, whose result is used by the base formatter:
    struct SmartFormatter;
    impl SmartFormatter {
    fn identify_dsl_calls(input: Input) -> ResultMap {
      let res = ResultMap::default();
      res.insert(LineCol(2, 0), "4|4+,{1,_,2},4");
      res
    }
    }

    An easy but powerful format is required by this approach tho.

Enter-tainer commented 4 months ago

Another way is that for table, we only format each args and don't change newlines, so user can freely arrange their cells. This can be a fallback code path.

implemented in #90