Adam,
Here are more details on my proposal.
This is still a bit rough, but hopefully there is enough
here to make the idea more specific for everybody.
SYNTAX
======
% gradle [ -<short_flag> | --<long_flag> ]* \
[ [+]?<task> -<task>* ]* \
[ <subproj_path> \
[ [+|-]?<task_within_subproj> ]+
]*
Given:
* means "any number of times" (including none)
+ means "at least one"
? means "zero or one"
| means "or"
[...] denotes a logical grouping
<...> denotes a placeholder for a name
(e.g: <task> could be the task named "test")
EXAMPLES
========
[1] Use quiet flag (in either its short or long form),
and run task moo:
% gradle -q moo
% gradle --quiet moo
[2] Run the tasks egg, hen, foo, and bar:
% gradle egg bar
[3] Run egg task (skipping the hen task this normally implies),
and also run the bar task:
% gradle egg -hen bar
% gradle +egg -hen +bar # same as: egg -hen bar
Note that when you use '-', sometimes using the decorative '+'
makes it easy to see what's going on. However, This '+' is
just
there to make things more readable; being sloppy should have
no ill consequences:
% gradle +egg -hen bar # same as: egg -hen bar
% gradle egg -hen +bar # same as: egg -hen bar
[4] Use -q and -s flag, run moo, but skip cow.
Note: Flags can be grouped and flag order doesn't
matter. Because all flags must appear before
tasks, and skipped tags can't appear prior to
tasks (or subproject paths), there's never any
ambiguity about whether something that starts
with a '-' is a flag or a task.
% gradle -q -s moo -cow
% gradle -qs moo -cow
% gradle -sq moo -cow
% gradle -q -s moo -cow
% gradle -qs +moo -cow
% gradle -sq +moo -cow
[5] Run moo in the main project, and
within the /foo/bar project run hello and dew but skip chew and
within the /egg/hen project run sun and fun:
% gradle -q moo /foo/bar hello -dew chew /egg/hen fun sun
[6] Run the /abc dir task.
Note: you don't usually need to run dir tasks from the
command line, but if that's necessary, you can do
so by prefixing their name with ':'.
% gradle :/abc
[7] Run the abc/def dir task and the moo task:
% gradle :abc/def moo
[8] Run the moo task and the abc/def dir task
... and within the foo/bar project:
run the egg task and the xxx/yyy dir task
but not the xxx/zzz dir task
... and within the foo/zoo project:
run the fun task
... and in the top-level project,
run the crazy_example task:
% gradle :abc/def foo/bar egg :xxx/yyy -:/xxx/zzz \
foo/zoo fun \
/ crazy_example
DEFINITIONS
===========
Let:
<short_flag> A single-letter flag (or a group of them)
Example #1: '-q'
Example #2: '-qs'
<long_flag> A multi-letter flag
Example: '--quiet'
<subproj_path> The absolute or relative path to a subproject.
A <subproj_path> is string containing at least
one '/' character, and does not begin with
'+', '-', or ":'. Further, it must not
contain
the substrings: '/+', '/-', or '/:'.
Example #1: foo/bar
Example #2: foo/bar/
Example #3: /foo/bar
Example #4: /foo/bar/
<task> A task name. Task names may be prefixed
by '-', which indicates a skipped task.
The '+' prefix is purely decorative, but
may make it easier for a human reader to
see that a task name is being specified,
and that it is not skipped.
Example #1: moo
Example #2: +moo
Example #3: -moo
Advanced usage: dir tasks on the command line
You don't need to run dir tasks directly on
the command line very often, but if you
needed
to to that, you'd prefix the dir task by
':'.
Thus, to run the dir task /x/y but not /x/
z,
you could say: % gradle :/x/y -:/x/z
or equivalently: % gradle +:/x/y -:/x/z
DETAILS
=======
Let's discect the following syntax pattern bit by bit:
% gradle [ -<short_flag> | --<long_flag> ]* \
[ [+]?<task> -<task>* ]* \
[ <subproj_path> \
[ [+|-]?<task_within_subproj> ]+
]*
o [ -<short_flag> | --<long_flag> ]*
Short flags and long flags may appear in any order,
and you may have any number of them (including none);
however, they must come first.
o [ [+]?<task> -<task>* ]*
You may any number of tasks that don't have a project
name prefixing them (including no tasks); however, if
you do supply a list, at least one non-skipped task
must come first. If you do have a non-skipped task,
the '+' is entirely optional.
o [ <subproj_path> [ [+|-]?<task_within_subproj> ]+ ]*
You may supply any nubmer of tuples of the form:
<subproj_path> [ [+|-]?<task_within_subproj> ]+
However, if you do supply a <subproj_path>, you must
specify at least one task within it. These tasks
may be skipped or non-skipped (and again, if non-skipped
the '+' is purely optional).
The first command line argument is optional and specifies the current
project. It can be either the project directory, a build file, or a
project path. If not specified, it defaults to the current
directory. It
is a shortcut for (or replacement for) the --project-dir and --
buildfile
command-line options.
The proposal allows for an arbitrary number
of top-level tasks (including none) followed by
an arbitrary number of project & task tuples
(including none).
One thing I like very much is -test instead of -Dskip.test
:)
Thanks.
Me too. How would we distinguish between these task exclusions and
command-line options? Would we keep the system property stuff? Does
-test exclude the dependencies of the test task as well?
The only case where this is could ever be a problem
as far a human reader's ability to parse the command
line goes is when you've got 1-letter skipped tasks
and short (1-letter flags). As 1-letter tasks are rare,
and skipping them even more so, I don't consider this
a practical usability issue.
It would NEVER be a problem for the command line parser
because at least one non-skipped tasks must precede
an excluded task, and all flags must precede all tasks.
Thus, suppose one day, gradle were to add the short flag -x,
and some user had two tasks x and y where y dependsOn x.
Now consider the following:
% gradle -x y -x
This means:
Run gradle with the -x flag
and execute the y task
but skip the x task.
Due to the ordering constraint on tasks, if you said:
% gradle -x -x y
That would mean:
Run gradle with the -x flag
and the -x flag (!!!)
and execute the y task
Most flags make no sense when doubled up, but some do
(like -v -v means "very verbose" on some programs).
That said, I think that the ordering constraint
that you can't have a negated tasks first in the list
after the flags isn't particularly bad because people
tend to think "this, but not that", rather than
"not that but this".
Hence, the case of people accidentally putting a negated
task first after the flags isn't likely to happen in
real life very often... so the nice aspects of this
syntax (brevity & expressiveness) seem to greatly outweigh
the chance of real-world confusion over what's an task name
and what's a flag.
Programmatically, if you have a subproject '/x/y'
a task named 'z' within this subproject could
have the absolute name: /x/y/+z
Note that because dir tasks are prefixed with ':'
the relative dir task foo/bar within project /x/y
would have the absolute name: /x/y/+:foo/bar
and the absolute dir task /foo/bar within prject /x/y
would have the absolute name: /x/y/+:/foo/bar
My guess is that in the real world, people probably won't
do stuff much more complex than example [5], but I wanted
to make sure nothing blows up in the more convoluted cases
(hence the overkill). When it comes to the userguide,
I'd probably want to re-work the explanation to make the
99% case leap out more... but this is for you!
Let me know what you think.
Cheers,
-Jon
---------------------------------------------------------------------
To unsubscribe from this list, please visit:
http://xircles.codehaus.org/manage_email