Command Line Arguments
You're going to write a program that prints the words you give it.
No program runs in isolation, so these inputs are going to be given as additional values when you start the program. These "command line arguments" are a common element used when starting programs to change its behavior depending on what you feed it.
This is the first step toward making usable programs.
You've already been using command line arguments! When you've been running
alr
on the terminal, you are running the Alire program and the things which
follow are command line arguments.
Objectives
- Write a code comment.
- Use command line arguments.
- Create a
for
loop.
Start a new project
Let's start another project.
$ alr init --bin command_line_arguments
$ cd command_line_arguments
You'll notice this time that the name of the gpr
file is now
command_line_arguments.gpr
and that the only .adb
file is now called
command_line_arguments.adb
. Open up command_line_arguments.adb
to get
started.
Remembering from last time
See if you can print a hello message with what you learned from the last lesson.
Remember, you want to print a line of text and that capability is within Ada's
Text Input/Output package of Ada.Text_IO
. Bring that package in as a
dependency using with
and then print a hello message.
What you have should look something along the lines of this:
with Ada.Text_IO;
procedure Calculate_Sum is
begin
Ada.Text_IO.Put_Line ("Hello, World!");
end Calculate_Sum;
Comments in code
Most programming languages have a way of writing things in your code that the computer will ignore. Usually these are called "comments." Programmers use them to write notes for themselves for other programmers in the code to describe why things are done a certain way, indicate tricky spots, or remind themselves of additional work to do.
Ada comments start with two dashes (negative signs) and continue to the end of the line, and so are called "line comments". Your text editor might highlight the comment a different color to show that it's a comment.
I'm going to annotate the above program with comments -- none of the things I added change the meaning of the program, from the computer's point of view.
-- This is the context clause.
-- We're describing how we depend on the Ada package, and in particular,
-- the Text_IO package inside of the Ada package. The period (also called a
-- "full stop") indicates that the thing on the right is contained in the
-- thing on the left.
with Ada.Text_IO;
-- Our program starts here.
procedure Hello_Lucy is
-- This is where we'd describe places to save information, called
-- "variables" if they can change, and "constants" if they cannot.
-- There's a few other things we can put here which we won't talk about
-- yet.
begin -- The program begins executing statements here
Ada.Text_IO.Put_Line ("Hello, World!"); -- Say hello to the world
end Hello_Lucy; -- end of the program
-- This line is after the program.
Making the command line available
The command line elements are available in the Command_Line
package
within the Ada
package. Make that package available by adding a with
in the context clause, at the start of your program.
with Ada.Command_Line;
There's two functions that you care about in the Ada.Command_Line
package.
One called Argument_Count
, which gives the number of arguments fed to the
program, and another called Argument
that gives you back the argument based
on a number you give it.
Using every argument by looping
You want to loop over all of the arguments, starting at the first one, and then
each until you've printed all of them. To do this, you'll use a for
loop.
This is a type of "control flow statement" that repeats the steps inside a specific
number of times.
Roughly, something like this:
for Next in First_Value .. Last_Value loop
-- these steps
-- happen until
-- the count
-- reaches the value
end loop;
This is what it breaks down to:
for
- this loop is going to run over a bunch of individual itemsNext
- the name of the item which is changing each round the loop runsin
- you're looping over a number of values, given by a range.First_Value
- the first number in the sequence..
- this indicates a range from the value on the left, to the value on the right.Last_Value
- the last value in the sequence.loop
- what follows are the step which will happen every round the loop is runend loop;
- indicates the end of the loop
You want to start at the number 1 for the first argument, with the last value
begin the total number of arguments, Ada.Command_Line.Argument_Count.
The
next value being used with be available with the identifier, Next
.
for Next in 1 .. Ada.Command_Line.Argument_Count loop
end loop;
This doesn't do anything yet. You'll want to print the argument. Instead of
giving Put_Line
a greeting in double quotes, you'll just pass the "index" as
a "parameter" to the Argument
function.
with Ada.Command_Line;
with Ada.Text_IO;
procedure Command_Line_Arguments is
begin
for Next in 1 .. Ada.Command_Line.Argument_Count loop
Ada.Text_IO.Put_Line (Ada.Command_Line.Argument (Next));
end loop;
end Command_Line_Arguments;
If you try to run this program, nothing seems to happen though!
$ alr run
alr run
Note: Building command_line_arguments/command_line_arguments.gpr...
Compile
[Ada] command_line_arguments.adb
Bind
[gprbind] command_line_arguments.bexch
[Ada] command_line_arguments.ali
Link
[link] command_line_arguments.adb
Build finished successfully in 1.07 seconds.
You're running your program by telling Alire to run the program for you. You provided the "run" command line argument to Alire, but it used that and didn't tell your program anything.
If you've been paying extra attention, you've noticed that a directory with
the funny name of bin/
appears after you run alr build
or alr run
. This
is where the executable for our program is actually hiding, it'll be called
command_line_arguments
on Linux or Mac, or command_line_arguments.exe
on
Windows. You can try running this program directly with some extra words to
print:
$ ./bin/command_line_arguments.exe will Ada print these words?
The .
at the front means "the current directory." Terminals use this to
indicate that the program being run is relative to your current location.
If you're on Windows, you'll be using back slashes (\
) instead of forward
slashes (/
).
will
Ada
print
these
words?
Command line arguments with Alire
OK, so we know that it works, but how do you make it work when you run it via Alire? It's a good bet that Alire is looking at the command line arguments given to it and that there's probably a way to pass along the arguments to the program it's running.
You can ask Alire about what it can do with the run
command , with:
$ alr help run
SUMMARY
Launch an executable built by the release
USAGE
alr run [options] [executable] [--args=ARGS] [--skip-build] | [--list]
OPTIONS
-a (--args=ARGS) Arguments to pass through (quote them if more than one)
--list List executables produced by current release
-s (--skip-build) Skip building step
GLOBAL OPTIONS
-c (--config=ARG) Override configuration folder location
-f (--force) Keep going after a recoverable troublesome situation
-h (--help) Display general or command-specific help
-n (--non-interactive) Assume default answers for all user prompts
--no-color Disables colors in output
--no-tty Disables control characters in output
--prefer-oldest Prefer oldest versions instead of newest when resolving dependencies
--version Displays version and exits
-q Limit output to errors
-v Be more verbose (use twice for extra detail)
-d (--debug[]) Enable debug-specific log messages
DESCRIPTION
Compiles the crate (unless --skip-build is specified) and then executes the
default or given resulting executable.
With --list, a list of declared executables is produced instead of invoking
the compiler, and its location (if already built) is given.
That ARGS
looks promising, this is how you'd use it. You need to put your
arguments inside double quotes so the terminal feeds all of them to your
program as a whole.
$ alr run --args="will Ada print these words?"
Note: Building command_line_arguments/command_line_arguments.gpr...
gprbuild: "command_line_arguments.exe" up to date
Build finished successfully in 0.69 seconds.
will
Ada
print
these
words?
Neat!
As a little exercise, how would you print them backwards?
You want to flip the two values at the end of the range, but the way ranges
are written in Ada, you can't actually do it that way. It'd be nice if you
could just tell it to reverse
the order... and you can!
If we just add a reverse
to that for loop...
for Next in reverse 1 .. Ada.Command_Line.Argument_Count loop
It prints in reverse!
Note: Building command_line_arguments/command_line_arguments.gpr...
Compile
[Ada] command_line_arguments.adb
Bind
[gprbind] command_line_arguments.bexch
[Ada] command_line_arguments.ali
Link
[link] command_line_arguments.adb
Build finished successfully in 1.10 seconds.
words?
these
print
Ada
will
Recap
- Code comments lets us add notes to our programs that the computer ignores. In Ada, these start with two dashes and then everything until the end of the line is ignored:
-- This is a code comment! Everything after the dashes is ignored.
- Command line arguments let you feed a program data when you start it. When you run your program directly, you'd write:
$ ./bin/my_program these are some command line arguments
When running with Alire, it's a little special since you're asking Alire to hand off those arguments, so you put them in quotes:
$ alr run --args="will Ada print these words?"
- For loops can be used to do the same steps a certain number of times, given
by a range. You can reverse the order by adding the word
reverse
.
for Next in First_Value .. Last_Value loop
-- Do these steps.
end loop;
Need help?
Go to the Ada language gitter if you have questions or need help.