Eiji

Eiji

I have tried to write mix task or even generate escript binary file, but it looks like that none of those ways supports some useful shell input methods. I tried to inspect arguments simply with IO.inspect(args)

here-document (<< operator)

A here document is a special-purpose code block. It uses a form of I/O redirection to feed a command list to an interactive program or a command, such as ftp, cat, or the ex text editor.

Source: Here Documents

What I have tried:

# Escript example:
$ ./example --test <<EOL
line 1
line 2
line 3
EOL
["--test"]

# Mix task example:
mix example.demo --test <<EOL
line 1
line 2
line 3
EOL
["--test"]

here-string (<<< operator)

A here string can be considered as a stripped-down form of a here document .
It consists of nothing more than COMMAND <<< $WORD ,
where $WORD is expanded and fed to the stdin of COMMAND .

Source: Here Strings

What I have tried:

# Escript example:
./example --test <<< 5*4
["--test"]

# Mix task example:
mix example.demo --test <<< 5*4
["--test"]

Maybe I need to compile Erlang with some extra flags or maybe it’s just not supported at all?

Showing Posts 1 to 10

NobbZ

NobbZ

Heredocs/-strings are written to stdin of your application, but from the output you show, it seems as if you only inspect parsed options.

foo <<< bar is just syntactic sugar for echo bar | foo, while << is (roughly) equivalent to echo "l1\nl2\nl3\n" | foo.

Eiji

Eiji OP

To new project I have only added:

a) escript option in project function:

defmodule Example.MixProject do

  # …

  def project do
    [
      # …
      escript: [main_module: Example],
      # …
    ]
  end

  # …
end

b) Replaced lib/example.ex to shortest form:

defmodule Example, do: def main(args), do: IO.inspect(args)

c) and finally added mix task with also minimal code:

defmodule Mix.Tasks.Example.Demo do
  use Mix.Task

  def run(args), do: IO.inspect(args)
end

Not sure what exactly you mean by parsed options. As you can see I’m not using OptionParser - I’m just trying to debug everything I got in args.

NobbZ

NobbZ

Okay, you are not using OptionParser but that doesn’t matter, you are inspecting the wrong thing as I said already.

You need to read stdin.

alco

alco

Here-docs are handled by your shell. As NobbZ explained, the content of a here-doc is passed on the standard input stream to the program. Try this example:

$ elixir -e 'IO.puts IO.read(:stdio, :all)' <<EOL
> hey
> there
> EOL
hey
there
Eiji

Eiji OP

Ah, now I can see … However there is one problem with this solution.

./example --test "single line"
./example --test << EOF
multi
line
EOF

Of course we can check it like this:

last_arg = List.last(args)
all_args = if option_type(last_arg) == :string do
  args ++ [IO.read(:stdio, :all)]
else
  args
end

defp option_type("--test"), do: :string
defp option_type(_option), do: nil

but what to do if user by mistake will not pass << operator?

$ elixir -e 'IO.puts IO.read(:stdio, :all)'
abc
def
EOF
EOL

In my opinion expected behavior (for app - not for IO.read/2 :exclamation:) here would be raise describing problem, but I’m not sure how I could make a check for using << operator … I do not even see an option for setting timeout in documentation (at least not for IO.read/2 which means it will collect input until user would terminate app, right?

Note: Of course I could use \n, but it’s extra requirement for end-user - not really problem for me.

NobbZ

NobbZ

No program will ever see << except for the shell, which then does some magic to turn it into the started programs stdin.

This is by design.

If --test option expects further data from stdin document as such in your programs manual, if it does not, then do not try to do stdin magic.

alco

alco

My code snippet was meant to demonstrate how a here-document’s content is passed on the standard input to the program. I wasn’t proposing a solution because I don’t know the requirements of what you’re trying to achieve.

If you want your program to take user input which may span more than one line, you may want to read the input one line at a time and stop upon encountering an empty line. Alternatively, using IO.read(:stdio, :all) is also fine, in my opinion. It reads everything up to the end of input which can be signaled in several different ways.

When a program is invoked in a shell, users should know that they can signal the end of input by pressing Ctrl-D on an empty line. This is just a way to let the shell know there won’t be any more input from the user, so that it can close the input pipe connected to the running program at which point the running program will encounter the EOF/end-of-input if it’s reading from stdin.

The same outcome can be achieved by using shell pipes:

$ echo "This is my input." | elixir -e 'IO.puts IO.read(:stdio, :all)'
This is my input.

or by using shell’s stream redirection to read from a file:

$ echo "This is my input." >foo

$ elixir -e 'IO.puts IO.read(:stdio, :all)' <foo
This is my input.

If you’re still looking for help, then I’d like to ask you to rephrase your question because the way it’s currently formulated doesn’t explain what the actual problem you’re trying to solve is.

Eiji

Eiji OP

I was just looking if there is any way to pass multi line argument value instead of using \n or \ character at end of each line which are not handy and requires to pass/edit data manually. I have found such here-* syntactic sugar in BASH

./example --test << EOF
multi line content goes here …
EOF

Notice that here we have only prefix --test << EOF and suffix EOF for such value i.e. value is not changed and it could be just copied. Single line have only prefix (--test), but it’s much easier that other solutions. Simple example of use case here is multi line JSON parsing, so end-user could use such option by simply copying JSON data - without any need to replace new line with \n or adding \ at end of each data line (just imagine huge prettified JSON).

NobbZ

NobbZ

Have you tried this:

$ ./example "multi
line"
Eiji

Eiji OP

I wonder how I could forget about so simple way. :smiley:
It’s always darkest before dawn. :077:

Where Next? Top

Trending in Questions Top

stjefim
Hello! Suppose you are building workflow (order / task / payment) processing system with the following requirements: Each workflow con...
New
water
I’m aware of 2 such projects, are there others? git: GitHub - team-alembic/realworld: A fullstack Phoenix LiveView application with back...
New
itzmidinesh
Hi all, I’m working on a Phoenix project where I need to make external HTTP requests and I’m trying to choose between Req and HTTPoison....
New
peck
Hi everyone. My team and I have been working on a fairly modest app based around video streaming and chat, but we’ve landed a customer t...
New
leoschweizer
Hi, we run different LLM models across a cluster, with each node loading a configurable subset. Model-specific queues let nodes consume ...
New
csmr
Hi all, I’m new here and would like to hear peoples views on my Elixir/Phoenix based game-engine! :smiley: Mutonex gamedesign was finish...
New
Stef-Verniers
Hello I’ve been coding in Elixir for almost two years now because of my current job where we implemented Elixir in our application. But ...
New

Other Trending Topics Top

dominicletz
Hey there, I haven’t seen a list of useful Elixir specific skills for the popular AI tools yet so I’m starting one here with my first. ...
New
mudasobwa
I fully migrated to my own harness from Anthropic/Gemini and I think it’s time to share it. Welcome DSH, the DeepSeek Harness, fully writ...
New
KristerV
Hey. Is there anyone here who creates agents in their apps? Not talking about using agents, but creating them. I’m finding it pretty diff...
New
OndrejValenta
(I just needed to vent somewhere and LinkedIn is full of hope, or hype, I’m not sure which exactly) AI dream has many faces, but general...
New
webofbits
With AI doing more of the implementation work, I’ve been wondering how much coding I should deliberately keep doing myself. My main conc...
#ai
New
kip
In 2021 I started a new library called Tempo with the objective of modelling time as a set of intervals - not as instants. In 2022 I gave...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews