Skip to content

Commit 3ba34c0

Browse files
DOC-5963 enabled support for C TCEs
1 parent 7aad5c7 commit 3ba34c0

File tree

7 files changed

+167
-7
lines changed

7 files changed

+167
-7
lines changed

build/components/example.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
'java-async': '//',
2929
'java-reactive': '//',
3030
'go': '//',
31+
'c': '//',
3132
'c#': '//',
3233
'c#-sync': '//',
3334
'c#-async': '//',

build/local_examples.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
'.py': 'python',
2424
'.js': 'node.js',
2525
'.go': 'go',
26+
'.c': 'c',
27+
'.h': 'c',
2628
'.cs': 'c#',
2729
'.java': 'java',
2830
'.php': 'php',
@@ -34,6 +36,7 @@
3436
'python': 'Python',
3537
'node.js': 'Node.js',
3638
'go': 'Go',
39+
'c': 'C',
3740
'c#': 'C#-Sync',
3841
'java': 'Java-Sync', # Default to sync, could be overridden
3942
'php': 'PHP',

build/tcedocs/README.md

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ There are two sections that need to updated when new languages are added.
88
1. In the `[params]` section:
99

1010
```toml
11-
clientsExamples = ["Python", "Node.js", "Java-Sync", "Lettuce-Sync", "Java-Async", "Java-Reactive", "Go", "C#-Sync", "C#-Async", "RedisVL", "PHP", "Rust-Sync", "Rust-Async"]
11+
clientsExamples = ["Python", "Node.js", "Java-Sync", "Lettuce-Sync", "Java-Async", "Java-Reactive", "Go", "C", "C#-Sync", "C#-Async", "RedisVL", "PHP", "Rust-Sync", "Rust-Async"]
1212
```
1313

1414
The order of the `clientsExamples` list matters: it's the order in which the language tabs are presented for each code example.
@@ -23,6 +23,7 @@ There are two sections that need to updated when new languages are added.
2323
"Java-Async"={quickstartSlug="lettuce"}
2424
"Java-Reactive"={quickstartSlug="lettuce"}
2525
"Go"={quickstartSlug="go"}
26+
"C"={quickstartSlug="hiredis"}
2627
"C#-Sync"={quickstartSlug="dotnet"}
2728
"C#-Async"={quickstartSlug="dotnet"}
2829
"RedisVL"={quickstartSlug="redis-vl"}
@@ -81,7 +82,8 @@ Here is an example:
8182
"lettuce_reactive",
8283
"redis_vl",
8384
"redis_rs_sync",
84-
"redis_rs_async"
85+
"redis_rs_async",
86+
"hi_redis"
8587
]
8688
```
8789

@@ -107,14 +109,18 @@ PREFIXES = {
107109
'java-async': '//',
108110
'java-reactive': '//',
109111
'go': '//',
112+
'c': '//',
110113
'c#': '//',
111114
'redisvl': '#',
112-
'php': '//'
115+
'php': '//',
116+
'rust': '//'
113117
}
114118
```
115119

116120
The `TEST_MARKER` dictionary maps programming languages to test framework annotations, which allows the parser to filter such source code lines out. The `PREFIXES` dictionary maps each language to its comment prefix. Python, for example, uses a hashtag (`#`) to start a comment.
117121

122+
⚠️ **CRITICAL**: The `PREFIXES` dictionary is **essential** for the example parser to work. If you add a new language, you **must** add an entry to this dictionary, or examples will fail to process with an "Unknown language" error. This is the most commonly missed step when adding a new language.
123+
118124
## Understand special comments in the example source code files
119125

120126
Each code example uses special comments, such as `HIDE_START` and `REMOVE_START`, to control how the examples are displayed. The following list gives an explanation:
@@ -138,6 +144,7 @@ Add a source code file to an appropriate client repo. Consult the /data/componen
138144

139145
| Programming Language | GitHub Repo | Default directory |
140146
|----------------------|-----------------------------------------------------|---------------------------------------------------|
147+
| C | [hiredis](https://github.com/redis/hiredis) | `examples` |
141148
| C# | [NRedisStack](https://github.com/redis/NRedisStack) | `tests/Doc` |
142149
| Go | [go-redis](https://github.com/redis/go-redis) | `doctests` |
143150
| Java | [jedis](https://github.com/redis/jedis) | `src/test/java/io/redis/examples` |
@@ -157,6 +164,9 @@ At times, it can take quite a while to get new or updated examples through the r
157164
local_examples
158165
├── client-specific
159166
│   ├── go
167+
│ ├── c
168+
│ │ ...
169+
160170
│   │   ...
161171
│   ├── jedis
162172
│   │   ...

build/tcedocs/SPECIFICATION.md

Lines changed: 130 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1127,7 +1127,7 @@ def main():
11271127
**Client Examples Order**:
11281128
```toml
11291129
[params]
1130-
clientsExamples = ["Python", "Node.js", "Java-Sync", "Lettuce-Sync", "Java-Async", "Java-Reactive", "Go", "C#-Sync", "C#-Async", "RedisVL", "PHP", "Rust-Sync", "Rust-Async"]
1130+
clientsExamples = ["Python", "Node.js", "Java-Sync", "Lettuce-Sync", "Java-Async", "Java-Reactive", "Go", "C", "C#-Sync", "C#-Async", "RedisVL", "PHP", "Rust-Sync", "Rust-Async"]
11311131
```
11321132

11331133
This controls:
@@ -1490,9 +1490,10 @@ See [Appendix: Adding a Language](#adding-a-language) for complete step-by-step
14901490
1. ✅ Update `config.toml` (clientsExamples, clientsConfig)
14911491
2. ✅ Create component config in `data/components/`
14921492
3. ✅ Register in `data/components/index.json`
1493-
4. ✅ Add language to `PREFIXES` in `build/components/example.py`
1493+
4. ✅ Add language to `PREFIXES` in `build/components/example.py` ⚠️ **CRITICAL - DO NOT SKIP**
14941494
5. ✅ Add extension mapping in `build/local_examples.py`
14951495
6. ✅ Add test markers if needed
1496+
7. ⚠️ Check if Jupyter notebook support is needed (update `build/jupyterize/` if applicable)
14961497

14971498
### Customizing the UI
14981499

@@ -2139,3 +2140,130 @@ OK
21392140
{{< /clients-example >}}
21402141
```
21412142

2143+
2144+
## Lessons Learned: Adding the C (hiredis) Client
2145+
2146+
### Critical Discovery: The PREFIXES Dictionary
2147+
2148+
When adding the C client, a critical step was initially missed: **adding the language to the `PREFIXES` dictionary in `build/components/example.py`**.
2149+
2150+
**Why this matters**: The `PREFIXES` dictionary maps each language to its comment prefix character(s). This is used by the example parser to:
2151+
- Identify special markers like `EXAMPLE:`, `STEP_START`, `HIDE_START`, etc.
2152+
- Parse metadata from source files
2153+
- Process example files correctly
2154+
2155+
**What happens if you skip this step**:
2156+
- The example parser will fail with an error: `Unknown language "c" for example {path}`
2157+
- Examples won't be processed
2158+
- The build system will silently skip C examples
2159+
- No error message will appear in the build output (just a debug log)
2160+
2161+
**The fix**:
2162+
```python
2163+
# In build/components/example.py, add to PREFIXES dictionary:
2164+
PREFIXES = {
2165+
...
2166+
'c': '//', # C uses // for comments
2167+
...
2168+
}
2169+
```
2170+
2171+
### Complete Checklist for Adding a New Language
2172+
2173+
The original checklist was incomplete. Here's the comprehensive version:
2174+
2175+
**Configuration Files**:
2176+
1. ✅ `config.toml` - Add to `clientsExamples` list and `clientsConfig` section
2177+
2. ✅ `data/components/{language}.json` - Create component configuration
2178+
3. ✅ `data/components/index.json` - Register the component
2179+
2180+
**Build System**:
2181+
4. ✅ `build/components/example.py` - **CRITICAL**: Add to `PREFIXES` dictionary
2182+
5. ✅ `build/components/example.py` - Add to `TEST_MARKER` dictionary (if language has test annotations)
2183+
6. ✅ `build/local_examples.py` - Add file extension mapping to `EXTENSION_TO_LANGUAGE`
2184+
7. ✅ `build/local_examples.py` - Add language to `LANGUAGE_TO_CLIENT` mapping
2185+
2186+
**Optional (if Jupyter notebook support is needed)**:
2187+
8. ⚠️ `build/jupyterize/jupyterize.py` - Add to `KERNEL_SPECS` dictionary
2188+
9. ⚠️ `build/jupyterize/jupyterize_config.json` - Add language-specific boilerplate and unwrap patterns
2189+
2190+
**Documentation**:
2191+
10. ✅ `build/tcedocs/SPECIFICATION.md` - Update examples and checklist
2192+
11. ✅ `build/tcedocs/README.md` - Update tables and examples
2193+
2194+
### Pre-existing Examples
2195+
2196+
**Important**: Before adding a new language, check if examples already exist in the repository:
2197+
- Look in `local_examples/client-specific/{language}/` for local examples
2198+
- Check the client repository for remote examples
2199+
- Verify the component configuration points to the correct example directory
2200+
2201+
For C (hiredis), there was already a `landing.c` example in `local_examples/client-specific/c/` that was ready to be processed once the language was properly configured.
2202+
2203+
### Language-Specific Comment Prefixes
2204+
2205+
Different languages use different comment styles. When adding a language, ensure the correct prefix is used:
2206+
2207+
| Language | Prefix | Example |
2208+
|----------|--------|---------|
2209+
| Python | `#` | `# EXAMPLE: my_example` |
2210+
| C | `//` | `// EXAMPLE: my_example` |
2211+
| Java | `//` | `// EXAMPLE: my_example` |
2212+
| Go | `//` | `// EXAMPLE: my_example` |
2213+
| C# | `//` | `// EXAMPLE: my_example` |
2214+
| PHP | `//` | `// EXAMPLE: my_example` |
2215+
| Rust | `//` | `// EXAMPLE: my_example` |
2216+
| Node.js | `//` | `// EXAMPLE: my_example` |
2217+
2218+
**Critical**: The `PREFIXES` dictionary uses **lowercase** language names as keys, but the `Example` class converts the language to lowercase before accessing it (line 57 in `example.py`).
2219+
2220+
### Verification Steps
2221+
2222+
After adding a new language, verify the integration:
2223+
2224+
```bash
2225+
# 1. Check that the language is recognized
2226+
grep -r "c" build/components/example.py # Should find 'c': '//' in PREFIXES
2227+
2228+
# 2. Process examples
2229+
python3 build/local_examples.py
2230+
2231+
# 3. Verify examples were processed
2232+
grep -i "landing" data/examples.json | grep -i "c"
2233+
2234+
# 4. Check for errors in the build output
2235+
python3 build/make.py 2>&1 | grep -i "error\|unknown language"
2236+
2237+
# 5. Build and serve
2238+
hugo serve
2239+
```
2240+
2241+
### Common Mistakes to Avoid
2242+
2243+
1. **Forgetting the PREFIXES entry**: This is the most common mistake. The build will appear to succeed but examples won't be processed.
2244+
2245+
2. **Case sensitivity**: Language names in `PREFIXES` must be lowercase, but `clientsExamples` in `config.toml` uses proper case (e.g., `"C"` not `"c"`).
2246+
2247+
3. **Inconsistent naming**: Ensure the language name is consistent across:
2248+
- `config.toml` clientsExamples (proper case, e.g., `"C"`)
2249+
- `config.toml` clientsConfig keys (proper case, e.g., `"C"`)
2250+
- `build/local_examples.py` LANGUAGE_TO_CLIENT values (proper case, e.g., `'C'`)
2251+
- `build/components/example.py` PREFIXES keys (lowercase, e.g., `'c'`)
2252+
2253+
4. **Missing component registration**: If the component isn't registered in `data/components/index.json`, remote examples won't be fetched.
2254+
2255+
5. **Wrong file extension mapping**: Ensure the file extension correctly maps to the language name in `EXTENSION_TO_LANGUAGE`.
2256+
2257+
### Single-Variant vs Multi-Variant Languages
2258+
2259+
**Single-variant languages** (Python, Go, PHP, C):
2260+
- One client implementation per language
2261+
- No path-based client name overrides needed
2262+
- File extension mapping is straightforward
2263+
2264+
**Multi-variant languages** (Java, Rust, C#):
2265+
- Multiple client implementations (e.g., Sync, Async, Reactive)
2266+
- Require path-based client name overrides in `get_client_name_from_language_and_path()`
2267+
- More complex configuration
2268+
2269+
C is a single-variant language, so it doesn't require path-based overrides.

config.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ tagManagerId = "GTM-TKZ6J9R"
4545
gitHubRepo = "https://github.com/redis/docs"
4646

4747
# Display and sort order for client examples
48-
clientsExamples = ["Python", "Node.js", "Java-Sync", "Lettuce-Sync", "Java-Async", "Java-Reactive", "Go", "C#-Sync", "C#-Async", "RedisVL", "PHP", "Rust-Sync", "Rust-Async"]
48+
clientsExamples = ["Python", "Node.js", "Java-Sync", "Lettuce-Sync", "Java-Async", "Java-Reactive", "Go", "C", "C#-Sync", "C#-Async", "RedisVL", "PHP", "Rust-Sync", "Rust-Async"]
4949
searchService = "/convai/api/search-service"
5050
ratingsService = "/docusight/api/rate/docs"
5151

@@ -65,6 +65,7 @@ rdi_current_version = "1.15.0"
6565
"Java-Async"={quickstartSlug="lettuce"}
6666
"Java-Reactive"={quickstartSlug="lettuce"}
6767
"Go"={quickstartSlug="go"}
68+
"C"={quickstartSlug="hiredis"}
6869
"C#-Sync"={quickstartSlug="dotnet"}
6970
"C#-Async"={quickstartSlug="dotnet"}
7071
"RedisVL"={quickstartSlug="redis-vl"}

data/components/hi_redis.json

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"id": "hi_redis",
3+
"type": "client",
4+
"name": "hiredis",
5+
"language": "C",
6+
"label": "C",
7+
"repository": {
8+
"git_uri": "https://github.com/redis/hiredis"
9+
},
10+
"examples": {
11+
"git_uri": "https://github.com/redis/hiredis",
12+
"path": "examples",
13+
"pattern": "*.c"
14+
}
15+
}
16+

data/components/index.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@
1919
"lettuce_reactive",
2020
"redis_vl",
2121
"redis_rs_sync",
22-
"redis_rs_async"
22+
"redis_rs_async",
23+
"hi_redis"
2324
],
2425
"assets": [],
2526
"website": {

0 commit comments

Comments
 (0)