Writing a ersatz for a makefile using 'option_parser'

I’m trying to substitute a makefile with a CLI, using ‘option_parser’ to parse the options and launch the commands, however using backticks commands to that end only works when the executable which is launched returns immediately, otherwise, the result of the operation is only displayed when the process is stopped.

Is there a better alternative?

Here is an excerpt from the Makefile:

cla: src/cla.cr
	crystal build src/cla.cr

init : # inits the installation of the required libs (shards)
	shards install

init_svelte :
	npm create vite@latest svelte --template svelte-ts
	cd svelte && npm install

svelte_dev :
	cd svelte && npm run dev

dev : src/main.cr # dev
	RUCKSACK_MODE=0 DEBUG=true DEVELOP=true crystal build -Dpreview_mt ./src/main.cr
	./main&

Here is the corresponding excerpt from the Crystal CLI code:

  # init
  parser.on "-i", "--init", "Install Crystal dependencies" do
    cmd = `shards install`
    puts cmd
    exit
  end

  # Svelte dev
  parser.on "-d", "--dev", "Start Svelte dev server (dev phase)" do
    cmd = `cd svelte && npm run dev`
    puts cmd
    exit
  end

  # dev
  parser.on "-c", "--compile", "Compiles app (dev phase)" do
    cmd = `RUCKSACK_MODE=0 DEBUG=true DEVELOP=true crystal build -Dpreview_mt ./src/main.cr`
    puts cmd
    cmd = `./main&`
    puts cmd
    exit
  end
``

Alternative formulation:

How can I run the executable corresponding to:

# hello.cr
i = 0
while true
  i+=1
  sleep(0.1)
  p "next step : #{i}"
end

Using an alternative to :slight_smile:

require "option_parser"

if ARGV.size == 0
  puts %('./cla -h' for help)
end

option_parser = OptionParser.parse do |parser|
  parser.banner = "cla : command-line for CrystApp:\n--------------------------------"

  parser.on "-v", "--version", "Show version" do
    puts "version 1.0"
    exit
  end

  parser.on "-h", "--help", "Show help" do
    puts parser
    exit
  end

  parser.on "-r", "--run", "runs the hello executable" do
    cmd = `./hello`
    puts cmd
    exit
  end

  parser.missing_option do |option_flag|
    STDERR.puts "ERROR: #{option_flag} is missing something."
    STDERR.puts ""
    STDERR.puts parser
    exit(1)
  end
  parser.invalid_option do |option_flag|
    STDERR.puts "ERROR: #{option_flag} is not a valid option."
    STDERR.puts parser
    exit(1)
  end
end

The code using the options parser will run the other exec, but the output will not be displayed.

I guess I’ill have to use some more sophisticated IPC, any ideas, examples of how that’s done in Crystal?

I have tried:

    stdout = IO::Memory.new
    process = Process.new("./hello", [""], output: stdout)
    status = process.wait
    output = stdout.to_s

but I get the error:

In /opt/homebrew/Cellar/crystal/1.7.2/share/crystal/src/IO.cr:62:3

 62 | DEFAULT_BUFFER_SIZE = 32768
      ^------------------
Error: already initialized constant IO::DEFAULT_BUFFER_SIZE
make: *** [hello] Error 1

at compilation time.

try this: Process.run("your_command", output: :inherit)

1 Like

Thanks, I tried and also tried:

    stdout = IO::Memory.new
    process = Process.new("ls -lAF", [""], output: stdout)
    status = process.wait
    output = stdout.to_s
    exit

[quote="npn, post:4, topic:5329"]
Process.run("your_command", output: :inherit")
[/quote]

but I’m having an issue with processes on my machine, I filed an issue:

Thank you, it works now !

:grinning: