@hupan56/wlkj 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/cli.js +213 -0
- package/package.json +11 -0
- package/templates/cli.js +198 -0
- package/templates/qoder/commands/wl-code.md +43 -0
- package/templates/qoder/commands/wl-commit.md +30 -0
- package/templates/qoder/commands/wl-init.md +80 -0
- package/templates/qoder/commands/wl-insight.md +51 -0
- package/templates/qoder/commands/wl-prd.md +199 -0
- package/templates/qoder/commands/wl-report.md +166 -0
- package/templates/qoder/commands/wl-search.md +52 -0
- package/templates/qoder/commands/wl-spec.md +18 -0
- package/templates/qoder/commands/wl-status.md +51 -0
- package/templates/qoder/commands/wl-task.md +71 -0
- package/templates/qoder/commands/wl-test.md +42 -0
- package/templates/qoder/config.toml +5 -0
- package/templates/qoder/config.yaml +141 -0
- package/templates/qoder/hooks/inject-workflow-state.py +117 -0
- package/templates/qoder/hooks/session-start.py +204 -0
- package/templates/qoder/rules/wl-pipeline.md +105 -0
- package/templates/qoder/scripts/add_session.py +245 -0
- package/templates/qoder/scripts/benchmark.py +209 -0
- package/templates/qoder/scripts/build_style_index.py +268 -0
- package/templates/qoder/scripts/code_index.py +41 -0
- package/templates/qoder/scripts/collect_prds.py +31 -0
- package/templates/qoder/scripts/common/__init__.py +0 -0
- package/templates/qoder/scripts/common/active_task.py +230 -0
- package/templates/qoder/scripts/common/atomicio.py +172 -0
- package/templates/qoder/scripts/common/developer.py +161 -0
- package/templates/qoder/scripts/common/eval_api.py +144 -0
- package/templates/qoder/scripts/common/feishu.py +278 -0
- package/templates/qoder/scripts/common/filelock.py +211 -0
- package/templates/qoder/scripts/common/identity.py +285 -0
- package/templates/qoder/scripts/common/mentions.py +134 -0
- package/templates/qoder/scripts/common/paths.py +311 -0
- package/templates/qoder/scripts/common/reqid.py +218 -0
- package/templates/qoder/scripts/common/search_engine.py +205 -0
- package/templates/qoder/scripts/common/task_utils.py +342 -0
- package/templates/qoder/scripts/common/terms.py +234 -0
- package/templates/qoder/scripts/common/utf8.py +38 -0
- package/templates/qoder/scripts/context_pack.py +196 -0
- package/templates/qoder/scripts/eval_prd.py +225 -0
- package/templates/qoder/scripts/export.py +487 -0
- package/templates/qoder/scripts/git_sync.py +1087 -0
- package/templates/qoder/scripts/handoff.py +22 -0
- package/templates/qoder/scripts/init_developer.py +76 -0
- package/templates/qoder/scripts/init_doctor.py +527 -0
- package/templates/qoder/scripts/install_qoderwork.py +339 -0
- package/templates/qoder/scripts/learn.py +67 -0
- package/templates/qoder/scripts/notify.py +5 -0
- package/templates/qoder/scripts/parse_prds.py +33 -0
- package/templates/qoder/scripts/report.py +281 -0
- package/templates/qoder/scripts/role.py +39 -0
- package/templates/qoder/scripts/run_weekly_update.bat +17 -0
- package/templates/qoder/scripts/run_weekly_update.sh +20 -0
- package/templates/qoder/scripts/search_index.py +352 -0
- package/templates/qoder/scripts/setup.py +453 -0
- package/templates/qoder/scripts/setup_weekly_cron.bat +22 -0
- package/templates/qoder/scripts/setup_weekly_cron.sh +19 -0
- package/templates/qoder/scripts/status.py +389 -0
- package/templates/qoder/scripts/syncgate.py +330 -0
- package/templates/qoder/scripts/task.py +954 -0
- package/templates/qoder/scripts/team.py +29 -0
- package/templates/qoder/scripts/team_sync.py +419 -0
- package/templates/qoder/scripts/workspace_init.py +102 -0
- package/templates/qoder/settings.json +53 -0
- package/templates/qoder/skills/design-review/SKILL.md +25 -0
- package/templates/qoder/skills/prd-generator/SKILL.md +180 -0
- package/templates/qoder/skills/prd-review/SKILL.md +36 -0
- package/templates/qoder/skills/prototype-generator/SKILL.md +141 -0
- package/templates/qoder/skills/spec-coder/SKILL.md +69 -0
- package/templates/qoder/skills/spec-generator/SKILL.md +67 -0
- package/templates/qoder/skills/test-generator/SKILL.md +72 -0
- package/templates/qoder/skills/wl-commit/SKILL.md +76 -0
- package/templates/qoder/skills/wl-init/SKILL.md +67 -0
- package/templates/qoder/skills/wl-insight/SKILL.md +81 -0
- package/templates/qoder/skills/wl-report/SKILL.md +87 -0
- package/templates/qoder/skills/wl-search/SKILL.md +75 -0
- package/templates/qoder/skills/wl-status/SKILL.md +61 -0
- package/templates/qoder/skills/wl-task/SKILL.md +58 -0
- package/templates/qoder/templates/prd-full-template.md +103 -0
- package/templates/qoder/templates/prd-quick-template.md +69 -0
- package/templates/qoder/templates/prototype-app.html +344 -0
- package/templates/qoder/templates/prototype-web.html +310 -0
- package/templates/root/AGENTS.md +182 -0
- package/templates/root/README-pipeline.md +56 -0
- package/templates/root/ROLES.md +85 -0
- package/templates/root//346/226/260/346/211/213/346/214/207/345/215/227.md +186 -0
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""
|
|
4
|
+
Search knowledge index with platform filtering and PRD search.
|
|
5
|
+
|
|
6
|
+
Usage:
|
|
7
|
+
python search_index.py 保险 --platform web
|
|
8
|
+
python search_index.py 保险 --platform app
|
|
9
|
+
python search_index.py --prd 保险
|
|
10
|
+
python search_index.py --style table [--platform web]
|
|
11
|
+
python search_index.py --field nickName
|
|
12
|
+
python search_index.py --api salary
|
|
13
|
+
python search_index.py --components
|
|
14
|
+
python search_index.py --modules
|
|
15
|
+
python search_index.py --list
|
|
16
|
+
python search_index.py --vben
|
|
17
|
+
"""
|
|
18
|
+
import os, json, sys
|
|
19
|
+
|
|
20
|
+
# UTF-8 stdio (防御性: stdout 被捕获时不崩溃)
|
|
21
|
+
try:
|
|
22
|
+
sys.stdout.reconfigure(encoding='utf-8', errors='replace')
|
|
23
|
+
except (AttributeError, TypeError, OSError, IOError):
|
|
24
|
+
try:
|
|
25
|
+
sys.stdout.reconfigure(encoding='utf-8')
|
|
26
|
+
except Exception:
|
|
27
|
+
pass
|
|
28
|
+
|
|
29
|
+
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
|
30
|
+
from common.terms import CN_MAP, BUSINESS_PATH_MAP, CN_TO_EN, get_platform_map
|
|
31
|
+
PLATFORM_MAP = get_platform_map()
|
|
32
|
+
|
|
33
|
+
BASE = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
|
34
|
+
INDEX_DIR = os.path.join(BASE, 'data', 'index')
|
|
35
|
+
|
|
36
|
+
# Substring matching against keys shorter than this produces too much noise
|
|
37
|
+
MIN_FUZZY_LEN = 4
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def load_index(filename, hint=''):
|
|
41
|
+
path = os.path.join(INDEX_DIR, filename)
|
|
42
|
+
if not os.path.isfile(path):
|
|
43
|
+
print('{} not found.{}'.format(filename, ' ' + hint if hint else ''))
|
|
44
|
+
return None
|
|
45
|
+
try:
|
|
46
|
+
with open(path, encoding='utf-8') as f:
|
|
47
|
+
return json.load(f)
|
|
48
|
+
except (json.JSONDecodeError, OSError) as e:
|
|
49
|
+
print('ERROR: failed to read {}: {}'.format(filename, e))
|
|
50
|
+
return None
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def filter_by_platform(files, platform=None):
|
|
54
|
+
if not platform:
|
|
55
|
+
return files
|
|
56
|
+
target = PLATFORM_MAP.get(platform.lower(), platform)
|
|
57
|
+
return [f for f in files if target.lower() in f.lower()]
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def _match_keyword(query_word, kw):
|
|
61
|
+
"""Match a query word against an index keyword without short-key noise."""
|
|
62
|
+
w, k = query_word.lower(), kw.lower()
|
|
63
|
+
if w == k:
|
|
64
|
+
return True
|
|
65
|
+
if len(k) >= MIN_FUZZY_LEN and k in w:
|
|
66
|
+
return True
|
|
67
|
+
if len(w) >= MIN_FUZZY_LEN and w in k:
|
|
68
|
+
return True
|
|
69
|
+
return False
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def search_keywords(query, platform=None):
|
|
73
|
+
ki = load_index('keyword-index.json', hint='Run: python git_sync.py')
|
|
74
|
+
if ki is None:
|
|
75
|
+
return
|
|
76
|
+
|
|
77
|
+
# Expand Chinese query via the shared term maps (same maps used at build time)
|
|
78
|
+
words = []
|
|
79
|
+
if query in CN_MAP:
|
|
80
|
+
words.extend(CN_MAP[query].split())
|
|
81
|
+
if query in BUSINESS_PATH_MAP:
|
|
82
|
+
words.extend(p.strip('/-').lower() for p in BUSINESS_PATH_MAP[query])
|
|
83
|
+
if words:
|
|
84
|
+
words = sorted(set(w.lower() for w in words))
|
|
85
|
+
print('Chinese: {} -> English: {}'.format(query, ' '.join(words)))
|
|
86
|
+
else:
|
|
87
|
+
words = [query.lower()]
|
|
88
|
+
if platform:
|
|
89
|
+
print('Platform: {} -> {}'.format(platform, PLATFORM_MAP.get(platform.lower(), platform)))
|
|
90
|
+
print()
|
|
91
|
+
|
|
92
|
+
# 性能优化 A2: 用倒排索引缩小候选集 (从 O(all_keys) 降到 O(命中数))
|
|
93
|
+
try:
|
|
94
|
+
from common.search_engine import get_inverted_index, search_keywords_fast
|
|
95
|
+
from common.paths import get_repo_root
|
|
96
|
+
inverted = get_inverted_index(str(get_repo_root()))
|
|
97
|
+
kw_matches = search_keywords_fast(words, inverted, ki)
|
|
98
|
+
except Exception:
|
|
99
|
+
# 回退: 全扫描
|
|
100
|
+
kw_matches = {}
|
|
101
|
+
for word in words:
|
|
102
|
+
for kw, files in ki.items():
|
|
103
|
+
if _match_keyword(word, kw):
|
|
104
|
+
kw_matches[kw] = files
|
|
105
|
+
|
|
106
|
+
# 按平台过滤 + 分组
|
|
107
|
+
matches = {}
|
|
108
|
+
for kw, files in kw_matches.items():
|
|
109
|
+
for f in filter_by_platform(files, platform):
|
|
110
|
+
p = f.split('/')[0] if '/' in f else f.split('\\')[0]
|
|
111
|
+
matches.setdefault(p, {}).setdefault(kw, [])
|
|
112
|
+
if f not in matches[p][kw]:
|
|
113
|
+
matches[p][kw].append(f)
|
|
114
|
+
|
|
115
|
+
if not matches:
|
|
116
|
+
print('No matches for: {}'.format(query))
|
|
117
|
+
return
|
|
118
|
+
|
|
119
|
+
total = 0
|
|
120
|
+
for proj, kws in sorted(matches.items()):
|
|
121
|
+
count = sum(len(fs) for fs in kws.values())
|
|
122
|
+
total += count
|
|
123
|
+
print('[{}] {} files'.format(proj, count))
|
|
124
|
+
for kw, fs in sorted(kws.items(), key=lambda x: len(x[1]), reverse=True)[:5]:
|
|
125
|
+
for f in fs[:3]:
|
|
126
|
+
parts = f.replace('\\', '/').split('/')
|
|
127
|
+
short = '/'.join(parts[:2]) + '/.../' + '/'.join(parts[-2:]) if len(parts) > 5 else '/'.join(parts)
|
|
128
|
+
print(' ' + short)
|
|
129
|
+
print()
|
|
130
|
+
print('Total: {} matches'.format(total))
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
def search_prds(query):
|
|
134
|
+
prd_index = load_index('prd-index.json', hint='Run: python git_sync.py --prd-only')
|
|
135
|
+
if prd_index is None:
|
|
136
|
+
return
|
|
137
|
+
q = query.lower()
|
|
138
|
+
|
|
139
|
+
matches = []
|
|
140
|
+
for prd_file, prd in prd_index.items():
|
|
141
|
+
score = 0
|
|
142
|
+
title = prd.get('title', '').lower()
|
|
143
|
+
keywords = [kw.lower() for kw in prd.get('keywords', [])]
|
|
144
|
+
cn_terms = [t.lower() for t in prd.get('cn_terms', [])]
|
|
145
|
+
|
|
146
|
+
if q in title:
|
|
147
|
+
score += 10
|
|
148
|
+
if q in keywords or q in cn_terms:
|
|
149
|
+
score += 5
|
|
150
|
+
if q in CN_TO_EN and CN_TO_EN[q] in keywords:
|
|
151
|
+
score += 3
|
|
152
|
+
for kw in keywords:
|
|
153
|
+
if q in kw or kw in q:
|
|
154
|
+
score += 2
|
|
155
|
+
|
|
156
|
+
if score > 0:
|
|
157
|
+
matches.append((score, prd_file, prd))
|
|
158
|
+
|
|
159
|
+
if not matches:
|
|
160
|
+
print('No PRDs matching: {}'.format(query))
|
|
161
|
+
return
|
|
162
|
+
|
|
163
|
+
matches.sort(key=lambda x: x[0], reverse=True)
|
|
164
|
+
|
|
165
|
+
print('PRDs matching: {} ({} found)'.format(query, len(matches)))
|
|
166
|
+
print()
|
|
167
|
+
for score, prd_file, prd in matches[:10]:
|
|
168
|
+
title = prd.get('title', prd_file)[:60]
|
|
169
|
+
features = len(prd.get('features', []))
|
|
170
|
+
related = sum(len(fs) for fs in prd.get('related_code', {}).values())
|
|
171
|
+
print(' {} - {}'.format(prd_file, title))
|
|
172
|
+
print(' Features: {}, Related code: {} files'.format(features, related))
|
|
173
|
+
if prd.get('related_code'):
|
|
174
|
+
for proj, files in list(prd['related_code'].items())[:2]:
|
|
175
|
+
print(' -> {}: {} files'.format(proj, len(files)))
|
|
176
|
+
print()
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
def search_style(style_type, platform=None):
|
|
180
|
+
"""Find pages of a given UI type (table/form/detail/modal/dashboard)."""
|
|
181
|
+
si = load_index('style-index.json', hint='Run: python build_style_index.py')
|
|
182
|
+
if si is None:
|
|
183
|
+
return
|
|
184
|
+
q = style_type.lower()
|
|
185
|
+
projects = si.get('projects', {})
|
|
186
|
+
if platform:
|
|
187
|
+
target = PLATFORM_MAP.get(platform.lower(), platform)
|
|
188
|
+
projects = {p: v for p, v in projects.items() if p.lower() == target.lower()}
|
|
189
|
+
|
|
190
|
+
found_any = False
|
|
191
|
+
for proj, pdata in sorted(projects.items()):
|
|
192
|
+
page_types = pdata.get('page_types', {})
|
|
193
|
+
examples = pdata.get('page_examples', {})
|
|
194
|
+
hit_types = [pt for pt in page_types if q in pt.lower()]
|
|
195
|
+
if not hit_types:
|
|
196
|
+
continue
|
|
197
|
+
found_any = True
|
|
198
|
+
for pt in hit_types:
|
|
199
|
+
print('[{}] {}: {} pages'.format(proj, pt, page_types[pt]))
|
|
200
|
+
for f in examples.get(pt, [])[:8]:
|
|
201
|
+
print(' ' + f)
|
|
202
|
+
if not examples.get(pt):
|
|
203
|
+
print(' (no examples stored - run: python build_style_index.py)')
|
|
204
|
+
print()
|
|
205
|
+
|
|
206
|
+
if not found_any:
|
|
207
|
+
known = sorted({pt for v in si.get('projects', {}).values()
|
|
208
|
+
for pt in v.get('page_types', {})})
|
|
209
|
+
print('No style matches for: {}'.format(style_type))
|
|
210
|
+
print('Known page types: {}'.format(', '.join(known)))
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
def search_field(field_name):
|
|
214
|
+
"""Search field usage in style-index.json field_map."""
|
|
215
|
+
si = load_index('style-index.json', hint='Run: python build_style_index.py')
|
|
216
|
+
if si is None:
|
|
217
|
+
return
|
|
218
|
+
fm = si.get('field_map', {})
|
|
219
|
+
matches = {f: i for f, i in fm.items() if field_name.lower() in f.lower()}
|
|
220
|
+
if not matches:
|
|
221
|
+
print('No fields matching: {}'.format(field_name))
|
|
222
|
+
return
|
|
223
|
+
print('Fields matching: {} ({} found)'.format(field_name, len(matches)))
|
|
224
|
+
for field, info in sorted(matches.items())[:10]:
|
|
225
|
+
titles = ', '.join(info.get('titles', []))
|
|
226
|
+
print(' {} -> {} (used {}x)'.format(field, titles, info.get('count', '?')))
|
|
227
|
+
for f in info.get('sample_files', [])[:3]:
|
|
228
|
+
print(' ' + f)
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
def search_api(query):
|
|
232
|
+
"""Search API endpoints in api-index.json."""
|
|
233
|
+
ai = load_index('api-index.json', hint='Run: python git_sync.py --index-only')
|
|
234
|
+
if ai is None:
|
|
235
|
+
return
|
|
236
|
+
q = query.lower()
|
|
237
|
+
matches = {ep: f for ep, f in ai.items() if q in ep.lower() or q in f.lower()}
|
|
238
|
+
if not matches:
|
|
239
|
+
print('No APIs matching: {}'.format(query))
|
|
240
|
+
return
|
|
241
|
+
print('APIs matching: {} ({} found)'.format(query, len(matches)))
|
|
242
|
+
for ep, f in sorted(matches.items())[:20]:
|
|
243
|
+
print(' {} -> {}'.format(ep, f))
|
|
244
|
+
if len(matches) > 20:
|
|
245
|
+
print(' ... and {} more'.format(len(matches) - 20))
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
def show_modules():
|
|
249
|
+
"""Show project overview from module-map.json."""
|
|
250
|
+
mm = load_index('module-map.json', hint='Run: python git_sync.py --index-only')
|
|
251
|
+
if mm is None:
|
|
252
|
+
return
|
|
253
|
+
print('=== Project Modules ===')
|
|
254
|
+
print()
|
|
255
|
+
for proj, info in sorted(mm.items()):
|
|
256
|
+
files = info.get('files', 0)
|
|
257
|
+
files = len(files) if isinstance(files, list) else files
|
|
258
|
+
print('[{}] files: {}, classes: {}, apis: {}'.format(
|
|
259
|
+
proj, files, info.get('classes', 0), info.get('apis', 0)))
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
def show_top_keywords():
|
|
263
|
+
"""Show top keywords by file count."""
|
|
264
|
+
ki = load_index('keyword-index.json', hint='Run: python git_sync.py')
|
|
265
|
+
if ki is None:
|
|
266
|
+
return
|
|
267
|
+
top = sorted(ki.items(), key=lambda x: len(x[1]), reverse=True)[:50]
|
|
268
|
+
print('=== Top 50 Keywords (by file count) ===')
|
|
269
|
+
print()
|
|
270
|
+
for kw, files in top:
|
|
271
|
+
print(' {} {}'.format(kw.ljust(30), len(files)))
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
def show_components():
|
|
275
|
+
meta = load_index('style-meta.json', hint='Run: python build_style_index.py')
|
|
276
|
+
if meta is None:
|
|
277
|
+
return
|
|
278
|
+
print('=== UI Components Usage ===')
|
|
279
|
+
print()
|
|
280
|
+
print('Ant Design Vue (import counts):')
|
|
281
|
+
for comp, count in meta.get('common_components', {}).items():
|
|
282
|
+
print(' {} {}'.format(comp.ljust(20), str(count).ljust(5)))
|
|
283
|
+
print()
|
|
284
|
+
print('Form Components (usage in schemas):')
|
|
285
|
+
for comp, count in sorted(meta.get('form_components', {}).items(), key=lambda x: x[1], reverse=True)[:20]:
|
|
286
|
+
print(' {} {}'.format(comp.ljust(20), str(count).ljust(5)))
|
|
287
|
+
|
|
288
|
+
|
|
289
|
+
def show_vben():
|
|
290
|
+
data = load_index('vben-style-reference.json')
|
|
291
|
+
if data is None:
|
|
292
|
+
return
|
|
293
|
+
print('=== Vben Admin Design Tokens ===')
|
|
294
|
+
print()
|
|
295
|
+
for section, values in data.items():
|
|
296
|
+
print('[{}]'.format(section))
|
|
297
|
+
if isinstance(values, dict):
|
|
298
|
+
for key, val in values.items():
|
|
299
|
+
print(' {}: {}'.format(key, val))
|
|
300
|
+
print()
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
def print_usage():
|
|
304
|
+
print('Usage:')
|
|
305
|
+
print(' search_index.py <keyword> [--platform web|app] - Search code')
|
|
306
|
+
print(' search_index.py --prd <keyword> - Search PRDs')
|
|
307
|
+
print(' search_index.py --style <type> [--platform p] - UI patterns (table/form/detail/modal/dashboard)')
|
|
308
|
+
print(' search_index.py --field <name> - Field usage')
|
|
309
|
+
print(' search_index.py --api <keyword> - API endpoints')
|
|
310
|
+
print(' search_index.py --components - UI components')
|
|
311
|
+
print(' search_index.py --modules - Project overview')
|
|
312
|
+
print(' search_index.py --list - Top 50 keywords')
|
|
313
|
+
print(' search_index.py --vben - Vben design tokens')
|
|
314
|
+
print()
|
|
315
|
+
print('Platform: web/pc/管理端 -> fywl-ui, app/mobile/h5/移动端 -> Carmg-H5')
|
|
316
|
+
|
|
317
|
+
|
|
318
|
+
if __name__ == '__main__':
|
|
319
|
+
platform = None
|
|
320
|
+
args = sys.argv[1:]
|
|
321
|
+
if '--platform' in args:
|
|
322
|
+
idx = args.index('--platform')
|
|
323
|
+
if idx + 1 < len(args):
|
|
324
|
+
platform = args[idx + 1]
|
|
325
|
+
args = args[:idx] + args[idx+2:]
|
|
326
|
+
else:
|
|
327
|
+
args = args[:idx]
|
|
328
|
+
|
|
329
|
+
if len(args) < 1:
|
|
330
|
+
print_usage()
|
|
331
|
+
elif args[0] == '--prd' and len(args) >= 2:
|
|
332
|
+
search_prds(args[1])
|
|
333
|
+
elif args[0] == '--style' and len(args) >= 2:
|
|
334
|
+
search_style(args[1], platform)
|
|
335
|
+
elif args[0] == '--field' and len(args) >= 2:
|
|
336
|
+
search_field(args[1])
|
|
337
|
+
elif args[0] == '--api' and len(args) >= 2:
|
|
338
|
+
search_api(args[1])
|
|
339
|
+
elif args[0] == '--components':
|
|
340
|
+
show_components()
|
|
341
|
+
elif args[0] == '--modules':
|
|
342
|
+
show_modules()
|
|
343
|
+
elif args[0] == '--list':
|
|
344
|
+
show_top_keywords()
|
|
345
|
+
elif args[0] == '--vben':
|
|
346
|
+
show_vben()
|
|
347
|
+
elif args[0].startswith('--'):
|
|
348
|
+
print('Unknown option: {}'.format(args[0]))
|
|
349
|
+
print()
|
|
350
|
+
print_usage()
|
|
351
|
+
else:
|
|
352
|
+
search_keywords(args[0], platform)
|