@@ -169,6 +169,28 @@ def _tier_name(tier_value):
169169 return ""
170170
171171
172+ def _truncate (text , max_len = 80 ):
173+ """Truncate text to max_len, appending '...' if needed."""
174+ if len (text ) > max_len :
175+ return text [:max_len - 3 ] + "..."
176+ return text
177+
178+
179+ # Column definitions per plugin type for verbose table output.
180+ # Each entry is (column_name, extractor_fn(info_dict) -> str).
181+ # "name" and "active" are always included and handled separately.
182+ _PLUGIN_TABLE_COLUMNS = {
183+ "probes" : [
184+ ("tier" , lambda info : _tier_name (info .get ("tier" )) if info .get ("tier" ) is not None else "" ),
185+ ("description" , lambda info : _truncate (info .get ("description" , "" ))),
186+ ],
187+ # Future plugin types can define their own extra columns here, e.g.:
188+ # "detectors": [
189+ # ("description", lambda info: _truncate(info.get("description", ""))),
190+ # ],
191+ }
192+
193+
172194def print_plugins (prefix : str , color , selected_plugins = None , verbose = 0 ):
173195 """
174196 Print plugins for a category (probes/detectors/generators/buffs).
@@ -203,8 +225,8 @@ def print_plugins(prefix: str, color, selected_plugins=None, verbose=0):
203225
204226 sorted_items = sorted (short , key = lambda x : x [0 ])
205227
206- if verbose >= 1 and prefix == "probes" :
207- _print_probes_table (sorted_items , prefix )
228+ if verbose >= 1 and prefix in _PLUGIN_TABLE_COLUMNS :
229+ _print_plugins_table (sorted_items , prefix )
208230 else :
209231 # plain text output (default)
210232 for item in sorted_items :
@@ -218,42 +240,33 @@ def print_plugins(prefix: str, color, selected_plugins=None, verbose=0):
218240 print ()
219241
220242
221- def _print_probes_table (sorted_items , prefix ):
222- """Render probes as a markdown table with name, active, tier, description ."""
243+ def _print_plugins_table (sorted_items , prefix ):
244+ """Render plugins as a markdown table with name, active, and type-specific columns ."""
223245 from py_markdown_table .markdown_table import markdown_table
224246 from garak ._plugins import plugin_info as get_plugin_info
225247
248+ extra_columns = _PLUGIN_TABLE_COLUMNS .get (prefix , [])
249+
226250 table_data = []
227251 for item in sorted_items :
228252 plugin_name , active = item [0 ], item [1 ]
229253 full_name = item [2 ] if len (item ) > 2 else None
230254
231255 is_module_header = "." not in plugin_name
232256
257+ row = {"name" : plugin_name }
258+
233259 if is_module_header :
234- active_str = "🌟"
235- tier_str = ""
236- desc_str = ""
260+ row [ "active" ] = "🌟"
261+ for col_name , _ in extra_columns :
262+ row [ col_name ] = ""
237263 else :
238- active_str = "✅" if active else "💤"
239- if full_name :
240- info = get_plugin_info (full_name )
241- tier_val = info .get ("tier" , None )
242- tier_str = _tier_name (tier_val ) if tier_val is not None else ""
243- desc_str = info .get ("description" , "" )
244- # Truncate long descriptions
245- if len (desc_str ) > 80 :
246- desc_str = desc_str [:77 ] + "..."
247- else :
248- tier_str = ""
249- desc_str = ""
250-
251- table_data .append ({
252- "name" : plugin_name ,
253- "active" : active_str ,
254- "tier" : tier_str ,
255- "description" : desc_str ,
256- })
264+ row ["active" ] = "✅" if active else "💤"
265+ info = get_plugin_info (full_name ) if full_name else {}
266+ for col_name , extractor in extra_columns :
267+ row [col_name ] = extractor (info )
268+
269+ table_data .append (row )
257270
258271 print (f"{ prefix } :" )
259272 print (
0 commit comments