ruby / irb

interactive Ruby
BSD 2-Clause "Simplified" License
389 stars 119 forks source link

Public API for calculating indentation #665

Open DmitryPogrebnoy opened 1 year ago

DmitryPogrebnoy commented 1 year ago

Description

Hi! IRB in multistring expressions adds appropriate indents to the next line. However, there is no API to get the indent value for the next line.

As far as I know, right now you can only get the indentation in some hacky way via an internal API. The internal API changes frequently and so the stability of such a hacky implementation suffers. It would be great to have a public API for this. Thank you!

st0012 commented 1 year ago

Would you mind sharing your use case of it? That'll help us decide how the API could look like to better fit your needs.

DmitryPogrebnoy commented 1 year ago

This API is mainly needed to be used in the ruby-denbug-ide gem. Here is an example of how it is implemented now. This method evaluates three values for an input expression in Ruby. The method calculates whether the expression is complete, calculates the indentation size for the next line of the expression, and finds the last prompt.

Currently, the indentation calculation uses an internal API that changes from version to version. It is inconvenient to maintain it. That's why there is a need for a public API.

tompng commented 1 year ago

For now, here are some idea how to calculate indentation.

Use a formatter or a language server

I think Indent calculation is similar to code formatting. Maybe there's an API in formatter or language server.

Use a parser/tokenizer library

One way to calculate indent is to use error tolerant parser like YARP or RubyVM::AbstractSyntaxTree(ruby>=3.3). Another way is to tokenize the code and scan unclosed tokens by yourself. You can use Ripper(IRB uses it), CodeRay(Pry uses it), YARP, Parser. Here's an example https://gist.github.com/tompng/959d374826153dd3bef59232c456773a

Fork and make an indent calculation library

IRB's current indent calculation is here. It uses IRB::NestingParser which is ported from https://github.com/tompng/katakata_irb/blob/ea461ae8ffa88a9a968365cfff9b7aaa51426cc3/lib/katakata_irb/nesting_parser.rb I created a demo gem that provides indent calculation https://github.com/tompng/indent_calculator_demo