scalameta / scalafmt

Code formatter for Scala
http://scalameta.org/scalafmt
Apache License 2.0
1.44k stars 276 forks source link

Configure token to align only with itself #4215

Open agolovenko opened 2 months ago

agolovenko commented 2 months ago

Hi,

I've got a question here trying to setup alignment on spark tokens. The problem I am facing that all the tokens do align with each other, which is in some cases fine.

But I'd like that some certain tokens align only with themselves. Like as and / in my example align with each other. Is there any way to configure so that:

Configuration

version                           = 3.8.3      
runner.dialect                    = scala212   

align.preset                      = more       
align.multiline                   = true       
maxColumn                         = 256        
assumeStandardLibraryStripMargin  = true       
align.stripMargin                 = true       

align.tokens."+" = [                           
  {                                            
    code = "as"                                
    owners = [                                 
      {                                        
        regex = "Term.ApplyInfix"              
      }                                        
    ]                                          
  },                                           
  {                                            
    code = "/"                                 
    owners = [                                 
      {                                        
        regex = "Term.ApplyInfix"              
      }                                        
    ]
 }
]                                         

Problem

Scalafmt formats code like this:

      .select(
        tpu          / "field1" as "field1",
        tpu          / "fd"     as "field1",
        lit("sys1") as "field1",
        tpe          / "field1" as "field1",
        bu           / "fd"     as "field1",
        lit(null)   as "field1"
      )

Expectation

I would like the formatted output to look like this:

      .select(
        tpu          / "field1" as "field1",
        tpu          / "fd"     as "field1",
        lit("sys1")             as "field1",
        tpe          / "field1" as "field1",
        bu           / "fd"     as "field1",
        lit(null)               as "field1"
      )
agolovenko commented 1 month ago

As far as I understand, this is a new feature that I request. But again, I'd appreciate some comments on this topic, so far it's been quiet here.

If it's a new feature, then I'd propose introducing alignment groups. So that the tokens would align with each other only if they a members of the same group. The existing alignment tokes like (->, %, %%) would form the default group which would be also a default value for a group for backward compatibility of configs.

The config might look like this:

align.tokens."+" = [                           
  {                                            
    group = "spark-select"
    code = "as"                                
    owners = [                                 
      {                                        
        regex = "Term.ApplyInfix"              
      }                                        
    ]                                          
  },                                           
  {    
    group = "spark-select"                                        
    code = "/"                                 
    owners = [                                 
      {                                        
        regex = "Term.ApplyInfix"              
      }                                        
    ]
 },                                           
  {    
    group = "default" // not mandatory to specify 'default' group                                      
    code = ":+"                                 
    owners = [                                 
      {                                        
        regex = "Term.ApplyInfix"              
      }                                        
    ]
 }
]  
kitbellew commented 1 month ago

@agolovenko please see https://scalameta.org/scalafmt/docs/configuration.html#alignment

some of this grouping logic is already available, via token and tree categories.

but if that is not sufficient, how would you revise the actual alignment algorithm described there?

how will you change the matching logic to handle this case:

val a = a0 / a1 :+ a2
val b = b0 :+ b1 / b2