Skip to content

Commit 0c897e2

Browse files
Merge pull request #2456 from redis/command-version-8.4
Add Redis commands reference pages for versions 8.0, 8.…
2 parents 21ef013 + 3a688e0 commit 0c897e2

File tree

7 files changed

+34832
-0
lines changed

7 files changed

+34832
-0
lines changed
Lines changed: 271 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,271 @@
1+
#!/usr/bin/env python3
2+
"""
3+
Generate comprehensive Redis commands reference pages for specific versions.
4+
Reads all command markdown files and creates a single page with collapsible sections.
5+
"""
6+
7+
import os
8+
import re
9+
import sys
10+
from pathlib import Path
11+
from collections import defaultdict
12+
import yaml
13+
14+
# Command group display names and order
15+
GROUP_ORDER = [
16+
('string', 'String commands'),
17+
('hash', 'Hash commands'),
18+
('list', 'List commands'),
19+
('set', 'Set commands'),
20+
('sorted-set', 'Sorted set commands'),
21+
('stream', 'Stream commands'),
22+
('bitmap', 'Bitmap commands'),
23+
('hyperloglog', 'HyperLogLog commands'),
24+
('geo', 'Geospatial commands'),
25+
('json', 'JSON commands'),
26+
('search', 'Search commands'),
27+
('timeseries', 'Time series commands'),
28+
('bloom', 'Probabilistic commands'),
29+
('vector_set', 'Vector set commands'),
30+
('pubsub', 'Pub/Sub commands'),
31+
('transactions', 'Transaction commands'),
32+
('scripting', 'Scripting commands'),
33+
('connection', 'Connection commands'),
34+
('server', 'Server commands'),
35+
('cluster', 'Cluster commands'),
36+
('generic', 'Generic commands'),
37+
]
38+
39+
def parse_frontmatter(content):
40+
"""Extract YAML frontmatter from markdown content."""
41+
match = re.match(r'^---\s*\n(.*?)\n---\s*\n', content, re.DOTALL)
42+
if match:
43+
try:
44+
return yaml.safe_load(match.group(1))
45+
except yaml.YAMLError:
46+
return {}
47+
return {}
48+
49+
def get_command_files():
50+
"""Get all command markdown files."""
51+
commands_dir = Path('content/commands')
52+
return list(commands_dir.glob('*.md'))
53+
54+
def parse_command_file(filepath):
55+
"""Parse a command file and extract relevant information."""
56+
with open(filepath, 'r', encoding='utf-8') as f:
57+
content = f.read()
58+
59+
frontmatter = parse_frontmatter(content)
60+
61+
# Skip hidden commands and container commands
62+
if frontmatter.get('hidden', False):
63+
return None
64+
65+
return {
66+
'name': frontmatter.get('title', ''),
67+
'link': frontmatter.get('linkTitle', ''),
68+
'summary': frontmatter.get('summary', frontmatter.get('description', '')),
69+
'syntax': frontmatter.get('syntax_fmt', ''),
70+
'complexity': frontmatter.get('complexity', ''),
71+
'since': frontmatter.get('since', ''),
72+
'group': frontmatter.get('group', 'generic'),
73+
'filepath': filepath.stem,
74+
}
75+
76+
def version_compare(version_str):
77+
"""Convert version string to tuple for comparison."""
78+
if not version_str:
79+
return (0, 0, 0)
80+
# Handle versions like "8.4.0", "1.0.0", etc.
81+
parts = version_str.split('.')
82+
try:
83+
return tuple(int(p) for p in parts[:3])
84+
except (ValueError, IndexError):
85+
return (0, 0, 0)
86+
87+
def is_new_in_version(since_version, target_version):
88+
"""Check if command was introduced in the target version."""
89+
since_tuple = version_compare(since_version)
90+
target_tuple = version_compare(target_version)
91+
# Check if it's exactly the target version (major.minor match)
92+
return since_tuple[:2] == target_tuple[:2]
93+
94+
def is_available_in_version(since_version, target_version):
95+
"""Check if command is available in the target version (introduced in or before)."""
96+
return version_compare(since_version) <= version_compare(target_version)
97+
98+
def generate_command_entry(cmd, target_version):
99+
"""Generate HTML for a single command entry."""
100+
is_new = is_new_in_version(cmd['since'], target_version)
101+
version_display = target_version.rsplit('.', 1)[0] # "8.4.0" -> "8.4"
102+
new_badge = f' <span style="color: #e74c3c;">⭐ New in {version_display}</span>' if is_new else ''
103+
104+
# Clean up syntax for display
105+
syntax = cmd['syntax'].replace('_', ' ').replace('\\n', ' ')
106+
107+
entry = f'''<details>
108+
<summary><strong><a href="/commands/{cmd['filepath']}/">{cmd['name']}</a></strong> - {cmd['summary']}{new_badge}</summary>
109+
110+
**Syntax:** `{syntax}`
111+
112+
**Description:** {cmd['summary']}
113+
114+
**Complexity:** {cmd['complexity']}
115+
116+
**Since:** {cmd['since']}
117+
118+
</details>
119+
120+
'''
121+
return entry
122+
123+
def generate_page_content(commands_by_group, target_version):
124+
"""Generate the complete page content."""
125+
content = []
126+
127+
version_display = target_version.rsplit('.', 1)[0] # "8.4.0" -> "8.4"
128+
129+
# Calculate weight based on version (higher version = lower weight = appears first)
130+
# Weight mapping: 8.4->1, 8.2->2, 8.0->3, 7.4->4, 7.2->5, 6.2->6
131+
version_weights = {
132+
'8.4': 1,
133+
'8.2': 2,
134+
'8.0': 3,
135+
'7.4': 4,
136+
'7.2': 5,
137+
'6.2': 6,
138+
}
139+
weight = version_weights.get(version_display, 10)
140+
141+
# Header
142+
content.append(f'''---
143+
title: Redis {version_display} Commands Reference
144+
linkTitle: Redis {version_display} Commands
145+
description: Complete list of all Redis commands available in version {version_display}, organized by functional group
146+
summary: Complete list of all Redis commands available in version {version_display}, organized by functional group
147+
layout: single
148+
type: develop
149+
categories:
150+
- docs
151+
- develop
152+
- stack
153+
- oss
154+
- rs
155+
- rc
156+
- kubernetes
157+
- clients
158+
weight: {weight}
159+
---
160+
161+
This page provides a comprehensive reference of all Redis commands available in Redis {version_display}, organized by functional group. Each command includes its description and syntax in a collapsible section for easy navigation.
162+
163+
{{{{< note >}}}}
164+
Redis {version_display} includes all commands from previous versions plus new commands introduced in {version_display}. Commands marked with **⭐ New in {version_display}** were added in this release.
165+
{{{{< /note >}}}}
166+
167+
## Quick Navigation
168+
169+
''')
170+
171+
# Table of contents
172+
for group_key, group_name in GROUP_ORDER:
173+
if group_key in commands_by_group:
174+
anchor = group_name.lower().replace(' ', '-').replace('/', '')
175+
content.append(f'- [{group_name}](#{anchor})\n')
176+
177+
content.append('\n---\n\n')
178+
179+
# Generate sections for each group
180+
for group_key, group_name in GROUP_ORDER:
181+
if group_key not in commands_by_group:
182+
continue
183+
184+
commands = sorted(commands_by_group[group_key], key=lambda x: x['name'])
185+
186+
# Section header
187+
anchor = group_name.lower().replace(' ', '-').replace('/', '')
188+
content.append(f'## {group_name}\n\n')
189+
190+
# Group description
191+
group_descriptions = {
192+
'string': 'String commands operate on string values, the most basic Redis data type.',
193+
'hash': 'Hash commands operate on hash data structures, which map string fields to string values.',
194+
'list': 'List commands operate on lists of strings, ordered by insertion order.',
195+
'set': 'Set commands operate on unordered collections of unique strings.',
196+
'sorted-set': 'Sorted set commands operate on sets of unique strings ordered by a score.',
197+
'stream': 'Stream commands operate on append-only log data structures.',
198+
'bitmap': 'Bitmap commands operate on strings as arrays of bits.',
199+
'hyperloglog': 'HyperLogLog commands provide probabilistic cardinality estimation.',
200+
'geo': 'Geospatial commands operate on geographic coordinates.',
201+
'json': 'JSON commands operate on JSON data structures.',
202+
'search': 'Search commands provide full-text search and secondary indexing.',
203+
'timeseries': 'Time series commands operate on time-series data.',
204+
'bloom': 'Probabilistic data structure commands (Bloom filters, Cuckoo filters, etc.).',
205+
'vector_set': 'Vector set commands operate on vector data structures for similarity search and range queries.',
206+
'pubsub': 'Pub/Sub commands enable message passing between clients.',
207+
'transactions': 'Transaction commands enable atomic execution of command groups.',
208+
'scripting': 'Scripting commands enable server-side Lua script execution.',
209+
'connection': 'Connection commands manage client connections.',
210+
'server': 'Server commands provide server management and introspection.',
211+
'cluster': 'Cluster commands manage Redis Cluster operations.',
212+
'generic': 'Generic commands work across all data types.',
213+
}
214+
215+
if group_key in group_descriptions:
216+
content.append(f'{group_descriptions[group_key]}\n\n')
217+
218+
# Add commands
219+
for cmd in commands:
220+
content.append(generate_command_entry(cmd, target_version))
221+
222+
content.append('\n')
223+
224+
return ''.join(content)
225+
226+
def main():
227+
"""Main function to generate the commands page."""
228+
# Get target version from command line argument or default to 8.4.0
229+
if len(sys.argv) > 1:
230+
target_version = sys.argv[1]
231+
if not target_version.count('.') == 2:
232+
target_version = f"{target_version}.0"
233+
else:
234+
target_version = "8.4.0"
235+
236+
version_display = target_version.rsplit('.', 1)[0] # "8.4.0" -> "8.4"
237+
238+
print(f"Generating Redis {version_display} commands reference page...")
239+
print("Parsing command files...")
240+
241+
commands_by_group = defaultdict(list)
242+
total_commands = 0
243+
new_commands = 0
244+
245+
for filepath in get_command_files():
246+
cmd_data = parse_command_file(filepath)
247+
if cmd_data and is_available_in_version(cmd_data['since'], target_version):
248+
commands_by_group[cmd_data['group']].append(cmd_data)
249+
total_commands += 1
250+
if is_new_in_version(cmd_data['since'], target_version):
251+
new_commands += 1
252+
253+
print(f"Found {total_commands} commands ({new_commands} new in {version_display})")
254+
print(f"Organized into {len(commands_by_group)} groups")
255+
256+
# Generate page content
257+
print("Generating page content...")
258+
content = generate_page_content(commands_by_group, target_version)
259+
260+
# Write to file
261+
output_file = Path(f'content/commands/redis-{version_display.replace(".", "-")}-commands.md')
262+
with open(output_file, 'w', encoding='utf-8') as f:
263+
f.write(content)
264+
265+
print(f"✅ Generated {output_file}")
266+
print(f" Total commands: {total_commands}")
267+
print(f" New in {version_display}: {new_commands}")
268+
269+
if __name__ == '__main__':
270+
main()
271+

0 commit comments

Comments
 (0)