Repository: nf-core/tools

Issue:
`nf-core modules list` behaviour
I've always found the behaviour of `nf-core modules list` a bit confusing. With `nf-core list` the positional arguments filter by name / keyword. With `modules list` the positional argument is a directory. Supplying it makes the tool to a completely different thing.

Suggestion is to make `modules list <keyword>` filter in the same way as `list` (increasingly important now that we have ~200 modules) and that either:

- We have `modules list --installed <pipeline dir>`
- `modules info` (though maybe we want this to show meta info about a specific module?)
- something else

Phil


Discussion:

Resolving patch:
diff --git a/nf_core/__main__.py b/nf_core/__main__.py
--- a/nf_core/__main__.py
+++ b/nf_core/__main__.py
@@ -371,9 +371,10 @@ def modules(ctx, repository, branch):
 
 @modules.command(help_priority=1)
 @click.pass_context
+@click.argument("keywords", required=False, nargs=-1, metavar="<filter keywords>")
 @click.option("-i", "--installed", type=click.Path(exists=True), help="List modules installed in local directory")
 @click.option("-j", "--json", is_flag=True, help="Print as JSON to stdout")
-def list(ctx, installed, json):
+def list(ctx, keywords, installed, json):
     """
     List available software modules.
 
@@ -385,7 +386,7 @@ def list(ctx, installed, json):
     try:
         module_list = nf_core.modules.ModuleList(installed)
         module_list.modules_repo = ctx.obj["modules_repo_obj"]
-        print(module_list.list_modules(json))
+        print(module_list.list_modules(keywords, json))
     except UserWarning as e:
         log.critical(e)
         sys.exit(1)
diff --git a/nf_core/modules/list.py b/nf_core/modules/list.py
--- a/nf_core/modules/list.py
+++ b/nf_core/modules/list.py
@@ -14,7 +14,7 @@ class ModuleList(ModuleCommand):
     def __init__(self, pipeline_dir):
         super().__init__(pipeline_dir)
 
-    def list_modules(self, print_json=False):
+    def list_modules(self, keywords=None, print_json=False):
         """
         Get available module names from GitHub tree for repo
         and print as list to stdout
@@ -25,9 +25,24 @@ def list_modules(self, print_json=False):
         table.add_column("Module Name")
         modules = []
 
+        if keywords is None:
+            keywords = []
+
+        def pattern_msg(keywords):
+            if len(keywords) == 0:
+                return ""
+            if len(keywords) == 1:
+                return f" matching pattern '{keywords[0]}'"
+            else:
+                quoted_keywords = (f"'{key}'" for key in keywords)
+                return f" matching patterns {', '.join(quoted_keywords)}"
+
         # No pipeline given - show all remote
         if self.dir is None:
-            log.info(f"Modules available from {self.modules_repo.name} ({self.modules_repo.branch}):\n")
+            log.info(
+                f"Modules available from {self.modules_repo.name} ({self.modules_repo.branch})"
+                f"{pattern_msg(keywords)}:\n"
+            )
 
             # Get the list of available modules
             try:
@@ -37,16 +52,24 @@ def list_modules(self, print_json=False):
                 return False
 
             modules = self.modules_repo.modules_avail_module_names
+
+            # Filter the modules by keywords
+            modules = [mod for mod in modules if all(k in mod for k in keywords)]
+
             # Nothing found
             if len(modules) == 0:
-                log.info(f"No available modules found in {self.modules_repo.name} ({self.modules_repo.branch})")
+                log.info(
+                    f"No available modules found in {self.modules_repo.name} ({self.modules_repo.branch})"
+                    f"{pattern_msg(keywords)}"
+                )
                 return ""
+
             for mod in sorted(modules):
                 table.add_row(mod)
 
         # We have a pipeline - list what's installed
         else:
-            log.info(f"Modules installed in '{self.dir}':\n")
+            log.info(f"Modules installed in '{self.dir}'{pattern_msg(keywords)}:\n")
 
             # Check whether pipelines is valid
             try:
@@ -57,9 +80,13 @@ def list_modules(self, print_json=False):
             # Get installed modules
             self.get_pipeline_modules()
             modules = self.module_names
+
+            # Filter the modules by keywords
+            modules = [mod for mod in modules if all(k in mod for k in keywords)]
+
             # Nothing found
             if len(modules) == 0:
-                log.info(f"No nf-core modules found in '{self.dir}'")
+                log.info(f"No nf-core modules found in '{self.dir}'{pattern_msg(keywords)}")
                 return ""
 
             modules_json = self.load_modules_json()


Test patch: