crystal
                                
                                 crystal copied to clipboard
                                
                                    crystal copied to clipboard
                            
                            
                            
                        Customizable Indentation in OptionParser Help Messages
Hi!
I am using Crystal to create a command line tool for myself and I've been working with OptionParser. It would be great to have more flexibility in customizing the help messages.
Here's an example:
require "option_parser"
struct Point
  property x : Float64 = 0
  property y : Float64 = 0
end
point = Point.new
OptionParser.parse do |parser|
  parser.on("-x FLOAT", "x-coordinate") { |x| point.x = x.to_f64 }
  parser.on("-y FLOAT", "y-coordinate") { |y| point.y = y.to_f64 }
  parser.on("-h", "--help", "Prints this help") { puts parser; exit }
end
p point
When I use --help, it displays as follows:
    -x FLOAT                         x-coordinate
    -y FLOAT                         y-coordinate
    -h, --help                       Prints this help
              |||||| too wide |||||||
The space between the flag and its description is excessively long.
https://github.com/crystal-lang/crystal/blob/866d51d42bdd25839b0c0010fb96948fd795c2d9/src/option_parser.cr#L319-L327
As per my understanding, the indentation is hardcoded to 33 spaces. An alternative could be reducing it to 14, for instance.
class OptionParser
  private def append_flag(flag, description)
    indent = " " * 37
    description = description.gsub("\n", "\n#{indent}")
    if flag.size >= 14
      @flags << "    #{flag}\n#{indent}#{description}"
    else
      @flags << "    #{flag}#{" " * (14 - flag.size)}#{description}"
    end
  end
end
With this change, --help would display as:
    -x FLOAT      x-coordinate
    -y FLOAT      y-coordinate
    -h, --help    Prints this help
Crystal supports open classes, but having a more configurable option would be even better.
The magic indent: 37
We could increase this to more magic 42!
I'm not sure what exactly lead to this number. But it might be some sort of convention. Or just grown out of experience. And it typically works pretty well. I don't see much point in changing it. But I suppose it would be acceptable to offer the possibility for changing it via a class property.
Hi, Thanks for taking a look at this issue.
Ruby provides two options: width and indent.
These options can be specified as keyword arguments when initializing.
OptionParser#new(banner = nil, width = 32, indent = ' ' * 4)
You can also change it later by calling methods such as summary_width
require "optparse"
opts = OptionParser.new do |opts|
  opts.on_head("-i", "--init")
  opts.on("-u", "--update")
  opts.on_tail("-h", "--help")
end
opts.summary_width     # => 32
opts.summarize
# => ["    -i, --init\n", "    -u, --update\n", "    -h, --help\n"]
opts.summary_width = 8
opts.summary_width     # =>8
opts.summarize
# => ["    -i\n", "        --init\n", "    -u\n", "        --update\n", "    -h\n", "        --help\n"]
or summary_indent.
require "optparse"
opts = OptionParser.new do |opts|
  opts.on_head("-i", "--init")
  opts.on("-u", "--update")
  opts.on_tail("-h", "--help")
end
opts.summary_indent         # => "    "
opts.summarize
# => ["    -i, --init\n", "    -u, --update\n", "    -h, --help\n"]
opts.summary_indent = "  "
opts.summary_indent         # => "  "
opts.summarize
# => ["  -i, --init\n", "  -u, --update\n", "  -h, --help\n"]
I created a ruby command line tool called YouPlot, where I used summary_width. Crystal does not need to behave the same as the Ruby language, but I am sure that some option is needed.
Other language option parsers should have similar settings, but I am not familiar with their APIs. I feel it is important to look at other languages before rushing to make them the same as Ruby. I would appreciate it if someone could look into this.