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

Blokh
Hey guys, I’ve got a huge CSV ( around 10 GB ) that needs to be processed hourly Do you guys have any suggestions what is the best prac...
New
kszambelanczyk
Hello! Could someone please give me a help/sample code, how to delete a file from s3 using waffle/waffle_ecto from Phoenix app. I creat...
New
RemyXRenard
I’m seeing that a list inside a Kino.DataTable will be interpreted as a charlist, even if the Kino.configure() is set to charlists: :as_l...
New
matt-savvy
Anyone here using Honeybadger? My Honeybadger account is being overwhelmed with noise from some bots. Seeing a lot of Bandit.HTTPError...
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
samoloth
Hi, I’ve just set up an application with ash_authentication. There is only magic link strategy for now, so there is no confirmation add o...
New
FlyingNoodle
If a change or preparation module uses Ash.Changeset.get_argument/2 or Ash.Query.get_argument/2 (or any of the other get_argument functio...
New

Other Trending Topics Top

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
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
mcass19
ExRatatui lets you cook up rich terminal UIs in Elixir, powered by Rust’s ratatui via Rustler NIFs. Build interactive terminal applicatio...
New
Damirados
Hello everyone. After busy few months I am happy to announce v0.1.0 of Emerge &amp; Solve. They are GUI (Emerge) and State management (S...
New
netoum
Corex is an accessible, unstyled UI component library for Phoenix that integrates Zag.js state machines using Vanilla JavaScript and Live...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews