Repository: spack/spack

Issue:
spack list: add --tag flag
### Summary

`spack find` has a `--tag` flag that lets you filter packages containing a certain tag. We should add the same flag to `spack list`.

### Rationale

A user may want to list _all_ packages belonging to a certain category, not just _installed_ packages.

### Description

We just need to add a `--tag` flag to `spack list`, should be straightforward to copy this setting from `spack find` and add tests.

### Additional information

We're planning to add an "ml" tag to all machine learning packages. We would like a way to list these packages so that we can ensure they all have common features (maintainers, post-install tests, etc.).

### General information

- [X] I have run `spack --version` and reported the version of Spack
- [X] I have searched the issues of this repo and believe this is not a duplicate


Discussion:
Hello, can I work on this?
Yes, please do!
Yupp!, I'm actually a bit new to this and this will be my first contribution, could I please the know the names of the relevant files from the repo for this issue?
The file you'll want to edit is [`lib/spack/spack/cmd/list.py`](https://github.com/spack/spack/blob/develop/lib/spack/spack/cmd/list.py). You'll want to add a new flag in `setup_parser` and use it in `filter_by_name`. For an example of how to do this, look at [`lib/spack/spack/cmd/find.py`](https://github.com/spack/spack/blob/develop/lib/spack/spack/cmd/find.py). Specifically, [this line](https://github.com/spack/spack/blob/develop/lib/spack/spack/cmd/find.py#L64) adds the flag (only add tags), and [these lines](https://github.com/spack/spack/blob/develop/lib/spack/spack/cmd/find.py#L275,L278) use it.

To add tests, you'll want to edit [`lib/spack/spack/test/cmd/list.py`](https://github.com/spack/spack/blob/develop/lib/spack/spack/test/cmd/list.py). See [`lib/spack/spack/test/cmd/find.py`](https://github.com/spack/spack/blob/develop/lib/spack/spack/test/cmd/find.py) for examples, there are a few using tags.

Resolving patch:
diff --git a/lib/spack/spack/cmd/list.py b/lib/spack/spack/cmd/list.py
--- a/lib/spack/spack/cmd/list.py
+++ b/lib/spack/spack/cmd/list.py
@@ -16,6 +16,7 @@
 import llnl.util.tty as tty
 from llnl.util.tty.colify import colify
 
+import spack.cmd.common.arguments as arguments
 import spack.dependency
 import spack.repo
 from spack.version import VersionList
@@ -72,6 +73,7 @@ def setup_parser(subparser):
         default=False,
         help="include virtual packages in list",
     )
+    arguments.add_common_arguments(subparser, ["tags"])
 
 
 def filter_by_name(pkgs, args):
@@ -306,6 +308,11 @@ def list(parser, args):
     # Filter the set appropriately
     sorted_packages = filter_by_name(pkgs, args)
 
+    # If tags have been specified on the command line, filter by tags
+    if args.tags:
+        packages_with_tags = spack.repo.path.packages_with_tags(*args.tags)
+        sorted_packages = [p for p in sorted_packages if p in packages_with_tags]
+
     if args.update:
         # change output stream if user asked for update
         if os.path.exists(args.update):


Test patch:
diff --git a/lib/spack/spack/test/cmd/list.py b/lib/spack/spack/test/cmd/list.py
--- a/lib/spack/spack/test/cmd/list.py
+++ b/lib/spack/spack/test/cmd/list.py
@@ -84,3 +84,17 @@ def test_list_update(tmpdir, mock_packages):
     assert update_file.exists()
     with update_file.open() as f:
         assert f.read() == "empty\n"
+
+
+def test_list_tags(mock_packages):
+    output = list("--tag", "tag1")
+    assert "mpich" in output
+    assert "mpich2" in output
+
+    output = list("--tag", "tag2")
+    assert "mpich\n" in output
+    assert "mpich2" not in output
+
+    output = list("--tag", "tag3")
+    assert "mpich\n" not in output
+    assert "mpich2" in output