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

katta
I having some trouble figuring out if I have set myself too strict of standards for my production server. Currently I can handle 75% of r...
New
brecabral
Documentation While reading the Scoped Routes section, I noticed that the documentation currently refers to a problem without explainin...
New
nseaSeb
Hello, I know there is an approach for handling lists that allows for optimized traversal, but I can’t recall the specific method (somet...
New
achenet
Hello, I’m trying to build a basic Phoenix web-app, and I’d like to use Tailwind. However, when I launch mix phx.server, I get an error...
New
kpanic
Hi everyone, I am toying with the idea of building a “match maker” for giving personal help to people that wants to start coding. I sta...
New
velrest
So my question is quite simple and i have found no conclusive answer on forum, google or AI. Should we use :erlang.float for Integer to ...
New
asweet-confluent
I recently noticed that Elixir’s Logger defaults its primary log level to :debug when no :logger, :level application configuration is pre...
New

Other Trending Topics Top

GenericJam
Edit: 2026 May 15 - This post is archived. Mob is alive!! Main docs: mob v0.7.11 — Documentation A bit of explanation for the slightly c...
New
JesseHerrick
Hey, I’m Jesse and I’m the main contributor behind Dexter, a full-featured, lightning-fast Elixir LSP optimized for large codebases. It s...
New
mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
garrison
Hobbes is a low-level distributed database for the Elixir programming language. Hobbes provides a simple, safe, and scalable storage lay...
New
mhanberg
Hi everyone! The first release candidate for the Expert language server project is now available! We’ve published a press release detai...
New
budgie
A little off-topic, but I feel like people here have a good head on their shoulders. I used to be quite good at making software. Was luc...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews