Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for positional arguments #59

Open
cweagans opened this issue Sep 17, 2024 · 5 comments
Open

Support for positional arguments #59

cweagans opened this issue Sep 17, 2024 · 5 comments

Comments

@cweagans
Copy link

I have a command that can be invoked like so:

my_command --foo=bar "first_arg" "second_arg"

(first_arg and second_arg are arbitrary strings)

My parser definition looks like this:

parser_definition() {
  setup ARGS
  param FOO --foo
}
eval "$(getoptions parser_definition __parse) exit 1"
__parse "$@"

echo "$FOO"

That all works great, but then I need to do something like this for the remaining positional arguments:

parse_args() {
  local var_names=("$@")
  local i=0
  for arg in $ARGS; do
    echo export ${var_names[$i]}="$arg"
    i=$((i + 1))
  done
}

eval "$(parse_args "FIRST" "SECOND")"

echo $FIRST         # outputs "first_arg"
echo $SECOND    # outputs "second_arg"

Do you think it makes sense to add a new kind of argument to the parser_definition where I can define the positional arguments too? Maybe something along these lines:

parser_definition() {
  setup ARGS
  param FOO --foo
  arg MY_ARG
  arg ANOTHER_ARG
}

I imagine that this could filter $@ to elements that do not begin with a - or --, and then $MY_ARG is assigned the value of the first arg, $ANOTHER_ARG is assigned the value of the second arg, and so forth.

There are probably other considerations for this library, but as a starting point, does this idea make sense and/or would you be interested in a PR to add something like that?

@ko1nksm
Copy link
Owner

ko1nksm commented Sep 17, 2024

It should be able to be written as follows

parser_definition() {
  setup ARGS
  param FOO --foo
}
eval "$(getoptions parser_definition __parse) exit 1"
__parse "$@"
eval "set -- $ARGS" # 👈

echo "$FOO"

FIRST="$1" SECOND="$2"

echo $FIRST         # outputs "first_arg"
echo $SECOND    # outputs "second_arg"

It could be simplified a bit more and written as follows

parser_definition() {
  setup ARGS
  param FOO --foo
}
eval "$(getoptions parser_definition) exit 1"
echo "$FOO"

FIRST="$1" SECOND="$2"

echo $FIRST         # outputs "first_arg"
echo $SECOND    # outputs "second_arg"

Perhaps documentation needs to be improved.

@cweagans
Copy link
Author

Right. I'm saying that it would be nicer if the positional args could be defined in the same parser definition function (and have the positional args loaded into the right vars), rather than doing extra stuff after calling __parse

@kkerce
Copy link

kkerce commented Sep 23, 2024

@cweagans The author can correct me if I'm wrong, but because getoptions refers to options rather than arguments, it feels as if handling arguments is out of scope. Admittedly in the realm of command-line interfaces there's often confusion or lack of strict distinction between terms like arguments, options, flags, etc. (The use of the term "argument" in the documentation of getoptions typically refers to arguments of particular options.) This document seems useful.

@cweagans
Copy link
Author

Understood. I'm asserting that the args vs options vs flags vs params argument is a distinction without a difference. Ultimately, all flags/params/options/args are going to be in $@, so why not have a simple mechanism for taking the remaining arguments and sticking them into the desired variables?

@ko1nksm
Copy link
Owner

ko1nksm commented Sep 25, 2024

As @kkerce says, the thought that the treatment of (non-option) arguments is out of scope is one reason. But, I do not think it is that far out of scope. However, In my opinion, arg is unnecessary. Because it can be implemented in one line without arg.

Although getoptions is designed to be embedded in shell scripts as a library, some people are not comfortable with the inclusion of long option parsing code. So I prefer to keep my implementation of getoptions as small as possible.

About Terms: I follow the POSIX terminology (in principle) and consider flags and options to be the same thing and flags to be historical usage.

are known as "options" (or, historically, "flags").

However, the term “operand” does not seem to be common. Therefore, I use “argument” instead of “operand” and the meaning of “argument” has become ambiguous. “argument” may be used to mean all arguments including options, or it may mean ”operand".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants