"""搜索与浏览命令:list / whereused / search。""" from __future__ import annotations import argparse import logging from sapcli.client import ADTClient from sapcli.types import get_type_config, parse_object_name logger = logging.getLogger("sapcli.commands.search") # 对象类型关键字 → ADT 类型代码映射 _TYPE_FILTER_MAP: dict[str, str] = { "report": "PROG/P", "class": "CLAS/OC", "interface": "INTF/OI", "function": "FUNC/F", "functiongroup": "FUGR/F", "domain": "DOMA/DD", "dataelement": "DTEL/DE", "table": "TABL/TT", "structure": "TABL/ST", "tabletype": "TTYP", "include": "PROG/I", "cdsview": "DDLS/DF", "messageclass": "MSAG", "view": "VIEW", "searchhelp": "SHLP", "lockobject": "LOCK", "dcl": "DCLS", "ddlX": "DDLX", } def cmd_list(args: argparse.Namespace, client: ADTClient) -> None: """列出 SAP 对象。""" obj_type = getattr(args, "type", None) package = getattr(args, "package", None) prefix = getattr(args, "prefix", None) # 将友好类型名转换为 ADT 类型代码 adt_type = None if obj_type: adt_type = _TYPE_FILTER_MAP.get(obj_type, obj_type) print("=" * 60) print(" SAP ADT 对象列表") print("=" * 60) if obj_type: print(f" 类型过滤: {obj_type}") if package: print(f" 包过滤: {package}") if prefix: print(f" 名称前缀: {prefix}") print(f"\n → 正在搜索对象...") try: results = client.list_objects(obj_type=adt_type, package=package, prefix=prefix) except Exception as e: print(f" ✗ 搜索失败: {e}") return if not results: print(" ℹ 未找到匹配的对象") return print(f" ✓ 找到 {len(results)} 个对象\n") print(f" {'名称':<30s} {'类型':<12s} {'包':<15s} {'描述':<30s}") print(f" {'─' * 30} {'─' * 12} {'─' * 15} {'─' * 30}") for obj in results: name = obj.get("name", "")[:30] otype = obj.get("type", "")[:12] pkg = obj.get("package", "")[:15] desc = obj.get("description", "")[:30] print(f" {name:<30s} {otype:<12s} {pkg:<15s} {desc:<30s}") def cmd_whereused(args: argparse.Namespace, client: ADTClient) -> None: """Where-Used 引用查询。""" name: str = args.name obj_type: str | None = getattr(args, "type", None) parsed = parse_object_name(name, obj_type or "report") type_label = get_type_config(obj_type or "report").label print("=" * 60) print(" SAP ADT Where-Used 查询") print("=" * 60) print(f" 对象名称: {parsed.display_name}") if obj_type: print(f" 对象类型: {type_label}") print(f"\n → 正在查询引用关系...") adt_type = _TYPE_FILTER_MAP.get(obj_type, obj_type) if obj_type else None try: results = client.where_used(name, parsed.obj_uri, adt_type) except Exception as e: print(f" ✗ 查询失败: {e}") return if not results: print(" ℹ 未找到引用关系") return print(f" ✓ 找到 {len(results)} 个引用\n") print(f" {'名称':<30s} {'类型':<12s} {'包':<15s} {'URI':<40s}") print(f" {'─' * 30} {'─' * 12} {'─' * 15} {'─' * 40}") for ref in results: ref_name = ref.get("name", "")[:30] ref_type = ref.get("type", "")[:12] ref_pkg = ref.get("package", "")[:15] ref_uri = ref.get("uri", "")[:40] print(f" {ref_name:<30s} {ref_type:<12s} {ref_pkg:<15s} {ref_uri:<40s}") def cmd_search(args: argparse.Namespace, client: ADTClient) -> None: """源代码搜索。""" query: str = args.query obj_type: str | None = getattr(args, "type", None) # 将友好类型名转换为 ADT 类型代码 adt_type = None if obj_type: adt_type = _TYPE_FILTER_MAP.get(obj_type, obj_type) print("=" * 60) print(" SAP ADT 源代码搜索") print("=" * 60) print(f" 搜索关键词: {query}") if obj_type: print(f" 类型过滤: {obj_type}") print(f"\n → 正在搜索...") try: results = client.search_code(query, obj_type=adt_type) except Exception as e: print(f" ✗ 搜索失败: {e}") return if not results: print(" ℹ 未找到匹配的代码") return print(f" ✓ 找到 {len(results)} 个结果\n") print(f" {'名称':<30s} {'类型':<12s} {'描述':<40s}") print(f" {'─' * 30} {'─' * 12} {'─' * 40}") for obj in results: obj_name = obj.get("name", "")[:30] obj_type_val = obj.get("type", "")[:12] desc = obj.get("description", "")[:40] print(f" {obj_name:<30s} {obj_type_val:<12s} {desc:<40s}")