In Crystal, you can use the eval subcommand to run small pieces of code as one-liners.
crystal eval 'puts "Hello world"'
The implementation of this eval subcommand is very small, consisting of just 32 lines. Looking at the implementation, you can see that the eval subcommand uses “–”, or double hyphens, as a delimiter.
However, this behaves slightly differently to what I expected. Because parse_with_crystal_opts consumes “–”.
crystal eval 'puts ARGV' -- -- meow neigh
["meow", "neigh"]
As I understand it, the Crystal run command is a little simpler. The options before the “–” are options for the Crystal compiler, and the options after the “–” are options for the program.
In the eval subcommand, if two double hyphens are required to pass arguments to the program, what is the purpose of the space between the first and second double hyphens?
After a few more observations of this behavior, I thought that this might indeed be unintentional.
When OptionParser parses command line arguments, it removes the double dash by default. This makes it impossible to distinguish between arguments that were before the double-dash and arguments that were after the double-dash.
I asked ChatGPT to read the OptionParser code, and found that I could use the unknown_args method.
class Crystal::Command
private def eval
compiler = new_compiler
program_source = ""
program_args = [] of String
parse_with_crystal_opts do |opts|
opts.banner = "Usage: crystal eval [options] [source]\n\nOptions:"
setup_simple_compiler_options compiler, opts
opts.unknown_args do |before_dash, after_dash| #### HERE!!
program_source = before_dash.join(";") # ";" is better than " " ?
program_args = after_dash
end
end
if program_source.empty?
program_source = STDIN.gets_to_end
end
sources = [Compiler::Source.new("eval", program_source)]
output_filename = Crystal.temp_executable "eval"
compiler.compile sources, output_filename
execute output_filename, program_args, compiler
end
end
I want to create a pull request once I am sure everything is OK.
However, I am not sure where and what kind of test code to write in this case.
I recently noticed that Crystal one-liners work well for processing large files, ranging from tens to hundreds of gigabytes. In these cases, Crystal’s compilation time is not a major concern, and since one-liners are small, they compile quickly. This makes it a suitable use case for Crystal.
Based on this, I have been adding a few options to the eval command to make one-liners more convenient. This is an experimental and personal tool, not intended for pull requests.
During this work, I came across the issue related to double dashes.