Skip to content

Comments

Fix handling of double dashes -- in crystal eval command#15477

Merged
straight-shoota merged 5 commits intocrystal-lang:masterfrom
kojix2:eval
Feb 22, 2025
Merged

Fix handling of double dashes -- in crystal eval command#15477
straight-shoota merged 5 commits intocrystal-lang:masterfrom
kojix2:eval

Conversation

@kojix2
Copy link
Contributor

@kojix2 kojix2 commented Feb 14, 2025

This is the main part of the pull request #15474


The purpose of this pull request is to pass arguments after a double dash to the program when using the eval command.

crystal eval 'puts ARGV' -- meow neigh

Expected behavior

["meow", "neigh"]

Actual behavior

syntax error in eval:1
Error: unexpected token: "meow"

Workaround

By using two double dashes, you can pass arguments to the program as expected.

crystal eval 'puts ARGV' -- -- meow neigh

The reason for this behavior is that the OptionParser stops at -- by default, and removes --.
You need to use unknown_args to distinguish between arguments that were before -- and arguments that were after --.

This issue was reported to the forum.

@straight-shoota straight-shoota added kind:bug A bug in the code. Does not apply to documentation, specs, etc. topic:compiler:cli labels Feb 14, 2025
kojix2 and others added 2 commits February 14, 2025 23:27
Co-authored-by: Johannes Müller <straightshoota@gmail.com>
Co-authored-by: Johannes Müller <straightshoota@gmail.com>
@straight-shoota
Copy link
Member

Ah now the code fails because program_source is a closure.
In other situations like that we introduce a separate local variable (e.g. opt_program_source) as the closured var and then assign it to the actual variable after the block.

@kojix2
Copy link
Contributor Author

kojix2 commented Feb 14, 2025

I tried the following code, but it did not work. It is nighttime in Japan. Good night.

# Implementation of the `crystal eval` command

class Crystal::Command
  private def eval
    compiler = new_compiler
    program_source = ""
    opt_program_source = nil
    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|
        opt_program_source = before_dash.join " "
        program_args = after_dash
      end
    end
  
    if opt_program_source.nil?
      program_source = STDIN.gets_to_end
    else
      program_source = opt_program_source
    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
In src/compiler/crystal/command/eval.cr:25:45

 25 | sources = [Compiler::Source.new("eval", program_source)]
                                              ^-------------
Error: expected argument #2 to 'Crystal::Compiler::Source.new' to be String, not (String | Nil)

Overloads are:
 - Crystal::Compiler::Source.new(filename : String, code : String)
make: *** [Makefile:247: .build/crystal] Error 1

@straight-shoota
Copy link
Member

I pushed a commit with the change I had in mind.

@straight-shoota straight-shoota added this to the 1.16.0 milestone Feb 20, 2025
@straight-shoota straight-shoota merged commit e740642 into crystal-lang:master Feb 22, 2025
32 checks passed
@kojix2 kojix2 deleted the eval branch February 23, 2025 06:37
kojix2 added a commit to kojix2/crystal that referenced this pull request Feb 23, 2025
…-lang#15477)

This allow to pass arguments after a double dash to the program when using the `eval` command.

```console
$ crystal eval 'puts ARGV' -- meow neigh
["meow", "neigh"]
```

Previously this caused a parser error (`Error: unexpected token: "meow"`) because the arguments after `--` were still considered code fragments.

This could be worked around by two double dashes, but it should really work with just a single one.

The reason for this behavior was that the `OptionParser` stops at `--` by default, and removes `--`. 
We need to use `unknown_args` to distinguish between arguments that were before `--` and arguments that were after `--`.

Co-authored-by: Johannes Müller <straightshoota@gmail.com>
Fixes: https://forum.crystal-lang.org/t/how-to-use-the-double-hyphen-in-the-eval-subcommand-of-crystal/7742
@straight-shoota
Copy link
Member

This change caused a regression, see #15654

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

kind:bug A bug in the code. Does not apply to documentation, specs, etc. topic:compiler:cli

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants