consync 2.1.0__tar.gz → 2.2.1__tar.gz

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.
Files changed (73) hide show
  1. {consync-2.1.0 → consync-2.2.1}/PKG-INFO +64 -12
  2. {consync-2.1.0 → consync-2.2.1}/README.md +63 -11
  3. {consync-2.1.0 → consync-2.2.1}/consync/config.py +47 -8
  4. {consync-2.1.0 → consync-2.2.1}/pyproject.toml +1 -1
  5. {consync-2.1.0 → consync-2.2.1}/.github/CODEOWNERS +0 -0
  6. {consync-2.1.0 → consync-2.2.1}/.github/copilot-instructions.md +0 -0
  7. {consync-2.1.0 → consync-2.2.1}/.github/dependabot.yml +0 -0
  8. {consync-2.1.0 → consync-2.2.1}/.github/workflows/ci.yml +0 -0
  9. {consync-2.1.0 → consync-2.2.1}/.github/workflows/codeql.yml +0 -0
  10. {consync-2.1.0 → consync-2.2.1}/.github/workflows/publish.yml +0 -0
  11. {consync-2.1.0 → consync-2.2.1}/.github/workflows/release.yml +0 -0
  12. {consync-2.1.0 → consync-2.2.1}/.gitignore +0 -0
  13. {consync-2.1.0 → consync-2.2.1}/CLAUDE.md +0 -0
  14. {consync-2.1.0 → consync-2.2.1}/CONTRIBUTING.md +0 -0
  15. {consync-2.1.0 → consync-2.2.1}/FAQ.md +0 -0
  16. {consync-2.1.0 → consync-2.2.1}/LICENSE +0 -0
  17. {consync-2.1.0 → consync-2.2.1}/SECURITY.md +0 -0
  18. {consync-2.1.0 → consync-2.2.1}/TODO.md +0 -0
  19. {consync-2.1.0 → consync-2.2.1}/assets/demo.gif +0 -0
  20. {consync-2.1.0 → consync-2.2.1}/assets/demo.tape +0 -0
  21. {consync-2.1.0 → consync-2.2.1}/consync/__init__.py +0 -0
  22. {consync-2.1.0 → consync-2.2.1}/consync/backup.py +0 -0
  23. {consync-2.1.0 → consync-2.2.1}/consync/cli.py +0 -0
  24. {consync-2.1.0 → consync-2.2.1}/consync/hooks.py +0 -0
  25. {consync-2.1.0 → consync-2.2.1}/consync/lock.py +0 -0
  26. {consync-2.1.0 → consync-2.2.1}/consync/logging_config.py +0 -0
  27. {consync-2.1.0 → consync-2.2.1}/consync/models.py +0 -0
  28. {consync-2.1.0 → consync-2.2.1}/consync/parsers/__init__.py +0 -0
  29. {consync-2.1.0 → consync-2.2.1}/consync/parsers/c_header.py +0 -0
  30. {consync-2.1.0 → consync-2.2.1}/consync/parsers/c_struct_table.py +0 -0
  31. {consync-2.1.0 → consync-2.2.1}/consync/parsers/csv_parser.py +0 -0
  32. {consync-2.1.0 → consync-2.2.1}/consync/parsers/json_parser.py +0 -0
  33. {consync-2.1.0 → consync-2.2.1}/consync/parsers/toml_parser.py +0 -0
  34. {consync-2.1.0 → consync-2.2.1}/consync/parsers/xlsx.py +0 -0
  35. {consync-2.1.0 → consync-2.2.1}/consync/precision.py +0 -0
  36. {consync-2.1.0 → consync-2.2.1}/consync/renderers/__init__.py +0 -0
  37. {consync-2.1.0 → consync-2.2.1}/consync/renderers/c_header.py +0 -0
  38. {consync-2.1.0 → consync-2.2.1}/consync/renderers/c_struct_table.py +0 -0
  39. {consync-2.1.0 → consync-2.2.1}/consync/renderers/csharp.py +0 -0
  40. {consync-2.1.0 → consync-2.2.1}/consync/renderers/csv_renderer.py +0 -0
  41. {consync-2.1.0 → consync-2.2.1}/consync/renderers/json_renderer.py +0 -0
  42. {consync-2.1.0 → consync-2.2.1}/consync/renderers/python_const.py +0 -0
  43. {consync-2.1.0 → consync-2.2.1}/consync/renderers/rust_const.py +0 -0
  44. {consync-2.1.0 → consync-2.2.1}/consync/renderers/verilog.py +0 -0
  45. {consync-2.1.0 → consync-2.2.1}/consync/renderers/vhdl.py +0 -0
  46. {consync-2.1.0 → consync-2.2.1}/consync/state.py +0 -0
  47. {consync-2.1.0 → consync-2.2.1}/consync/sync.py +0 -0
  48. {consync-2.1.0 → consync-2.2.1}/consync/validators.py +0 -0
  49. {consync-2.1.0 → consync-2.2.1}/consync/watcher.py +0 -0
  50. {consync-2.1.0 → consync-2.2.1}/examples/fpga/.consync.yaml +0 -0
  51. {consync-2.1.0 → consync-2.2.1}/examples/fpga/design_params.csv +0 -0
  52. {consync-2.1.0 → consync-2.2.1}/examples/hardware/.consync.yaml +0 -0
  53. {consync-2.1.0 → consync-2.2.1}/examples/hardware/constants.csv +0 -0
  54. {consync-2.1.0 → consync-2.2.1}/examples/multilang/.consync.yaml +0 -0
  55. {consync-2.1.0 → consync-2.2.1}/examples/multilang/constants.json +0 -0
  56. {consync-2.1.0 → consync-2.2.1}/npm/.npmrc +0 -0
  57. {consync-2.1.0 → consync-2.2.1}/npm/LICENSE +0 -0
  58. {consync-2.1.0 → consync-2.2.1}/npm/README.md +0 -0
  59. {consync-2.1.0 → consync-2.2.1}/npm/bin/consync.js +0 -0
  60. {consync-2.1.0 → consync-2.2.1}/npm/package.json +0 -0
  61. {consync-2.1.0 → consync-2.2.1}/npm/scripts/install.js +0 -0
  62. {consync-2.1.0 → consync-2.2.1}/tests/__init__.py +0 -0
  63. {consync-2.1.0 → consync-2.2.1}/tests/test_arrays.py +0 -0
  64. {consync-2.1.0 → consync-2.2.1}/tests/test_bidirectional.py +0 -0
  65. {consync-2.1.0 → consync-2.2.1}/tests/test_c_struct_table.py +0 -0
  66. {consync-2.1.0 → consync-2.2.1}/tests/test_cli.py +0 -0
  67. {consync-2.1.0 → consync-2.2.1}/tests/test_comprehensive_sync.py +0 -0
  68. {consync-2.1.0 → consync-2.2.1}/tests/test_embedded.py +0 -0
  69. {consync-2.1.0 → consync-2.2.1}/tests/test_parsers.py +0 -0
  70. {consync-2.1.0 → consync-2.2.1}/tests/test_precision.py +0 -0
  71. {consync-2.1.0 → consync-2.2.1}/tests/test_renderers.py +0 -0
  72. {consync-2.1.0 → consync-2.2.1}/tests/test_safety.py +0 -0
  73. {consync-2.1.0 → consync-2.2.1}/tests/test_sync.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: consync
3
- Version: 2.1.0
3
+ Version: 2.2.1
4
4
  Summary: Bidirectional sync between spreadsheets and source code constants — with full decimal precision.
5
5
  Project-URL: Homepage, https://github.com/naveenkumarbaskaran/consync
6
6
  Project-URL: Repository, https://github.com/naveenkumarbaskaran/consync
@@ -70,10 +70,11 @@ Keep a single source of truth for hardware constants (resistor values, timing pa
70
70
  │ Parsers │ │ State │ │ Renderers │
71
71
  │ │ │ Tracker │ │ │
72
72
  │ • xlsx │ │ │ │ • c_header │
73
- │ • csv │ │ MD5 hashes │ │ • csharp
74
- │ • json │ │ per-mapping │ │ • python
75
- │ • toml │ │ in .json │ │ • rust
76
- │ • c_header │ │ │ │ • verilog
73
+ │ • csv │ │ MD5 hashes │ │ • c_struct_table
74
+ │ • json │ │ per-mapping │ │ • csharp
75
+ │ • toml │ │ in .json │ │ • python
76
+ │ • c_header │ │ │ │ • rust
77
+ │ • c_struct_table │ │ │ │ • verilog │
77
78
  └────────┬────────┘ └──────┬──────┘ │ • vhdl │
78
79
  │ │ │ • json │
79
80
  │ │ │ • csv │
@@ -152,6 +153,12 @@ mappings:
152
153
  direction: both
153
154
  precision: 17
154
155
  header_guard: HW_CONSTANTS_H
156
+
157
+ # Or for C struct tables → Excel:
158
+ # - source: MotorParams.c
159
+ # target: MotorParams.xlsx
160
+ # direction: both
161
+ # format: c_struct_table
155
162
  ```
156
163
 
157
164
  ### 2. Sync
@@ -200,17 +207,19 @@ consync install-hook
200
207
 
201
208
  | Format | Extension | Notes |
202
209
  |--------|-----------|-------|
203
- | Excel | `.xlsx` | Auto-detects column headers |
210
+ | Excel | `.xlsx` | Auto-detects flat or table layout (multi-variant) |
204
211
  | CSV | `.csv`, `.tsv` | Auto-detects delimiter |
205
- | JSON | `.json` | Flat, array, or nested |
212
+ | JSON | `.json` | Flat, array, nested, or structured (`_meta` + `constants`) |
206
213
  | TOML | `.toml` | Flat or table-with-metadata |
207
214
  | C Header | `.h` | Parses `const`, `#define`, hex/int/float |
215
+ | C Struct Table | `.c` | Multi-variant `#if`/`#elif` struct arrays (Bosch-style) |
208
216
 
209
217
  ### Targets (output)
210
218
 
211
219
  | Format | Extension | Features |
212
220
  |--------|-----------|----------|
213
221
  | C Header | `.h` | `const` or `#define`, `static`, `stdint.h` types, hex |
222
+ | C Struct Table | `.c` | In-place update of multi-variant struct arrays (minimal diffs) |
214
223
  | C# | `.cs` | `namespace`, `public static class`, XML doc comments |
215
224
  | Python | `.py` | Type annotations (`float`/`int`), inline comments |
216
225
  | Rust | `.rs` | `pub const`, `f64`/`i64`, doc comments |
@@ -218,6 +227,7 @@ consync install-hook
218
227
  | VHDL | `.vhd` | Package with `ieee.math_real`, typed constants |
219
228
  | JSON | `.json` | Structured with `_meta` header |
220
229
  | CSV | `.csv` | Round-trip back to spreadsheet |
230
+ | Excel | `.xlsx` | Multi-sheet table layout (one sheet per variant) |
221
231
 
222
232
  ---
223
233
 
@@ -225,7 +235,36 @@ consync install-hook
225
235
 
226
236
  **Don't have a spreadsheet yet?** consync can create one from your existing source files.
227
237
 
228
- If you already have a C header with constants and want to start tracking it:
238
+ ### C Struct Table Excel (multi-variant motor parameters)
239
+
240
+ Have a complex C file with `#if`/`#elif` struct arrays and want an Excel for your team to review/edit?
241
+
242
+ ```yaml
243
+ # .consync.yaml
244
+ mappings:
245
+ - source: RBPSC_HWVariantParameter.c # Existing C file with struct arrays
246
+ target: RBPSC_HWVariantParameter.xlsx # Excel will be created on first sync
247
+ direction: both # Edit C or Excel — both stay in sync
248
+ format: c_struct_table # Parses #if/#elif multi-variant tables
249
+ precision: 17
250
+ ```
251
+
252
+ ```bash
253
+ consync sync
254
+ # ✅ RBPSC_HWVariantParameter.c ↔ RBPSC_HWVariantParameter.xlsx: 160 constants synced (source → target)
255
+ ```
256
+
257
+ consync parses the C file — handling nested `{{...}}` initializers, `#if`/`#elif` variant blocks, float suffixes (`1.0F`), hex (`0xFF`), expressions — and generates a multi-sheet Excel with one sheet per variant (BWA, EMB, DPB, etc.).
258
+
259
+ After that, edit either side:
260
+ - **Edit Excel** → values sync back into the C file (in-place, minimal diffs)
261
+ - **Edit C file** → Excel updates on next `consync sync`
262
+
263
+ > **Note:** The `format: c_struct_table` field tells consync to use the struct-table parser for the `.c` file instead of the default `c_header` parser. The `.xlsx` target format is auto-detected.
264
+
265
+ ### C Header → CSV/JSON (simple constants)
266
+
267
+ If you have a simpler C header with `const`/`#define` declarations:
229
268
 
230
269
  ```yaml
231
270
  # .consync.yaml
@@ -242,7 +281,7 @@ consync sync
242
281
 
243
282
  consync parses the existing `.h` file, extracts all constants (name, value, unit, description from comments), and writes a fresh CSV. From that point forward, you have a spreadsheet to share with your EE team.
244
283
 
245
- **Works with any parseable target:** `.h`, `.json`, `.csv`, `.toml` — anything consync has a parser for can bootstrap a new source.
284
+ **Works with any parseable format:** `.h`, `.c`, `.json`, `.csv`, `.toml` — anything consync has a parser for can bootstrap a new source.
246
285
 
247
286
  ---
248
287
 
@@ -407,17 +446,30 @@ consync tracks file hashes in `.consync.state.json` to detect which side changed
407
446
  ```yaml
408
447
  # .consync.yaml
409
448
  mappings:
410
- - source: constants.xlsx # source file path (xlsx/csv/json/toml/h)
411
- target: hw_constants.h # target file path (h/cs/py/rs/v/vhd/json/csv)
449
+ - source: constants.xlsx # source file path (xlsx/csv/json/toml/h/c)
450
+ target: hw_constants.h # target file path (h/cs/py/rs/v/vhd/json/csv/xlsx)
412
451
  direction: both # source_to_target | target_to_source | both
413
452
  precision: 17 # significant digits (1-17, default: 17)
414
453
 
454
+ # ─── Format override ───
455
+ # format: c_struct_table # Override auto-detected format for the matching side.
456
+ # # Useful when .c needs c_struct_table instead of c_header.
457
+ # # Auto-assigned to whichever side's extension matches.
458
+ # source_format: xlsx # Explicit source format (overrides auto-detect)
459
+ # target_format: c_header # Explicit target format (overrides auto-detect)
460
+
415
461
  # ─── C Header options ───
416
462
  header_guard: HW_CONSTANTS_H # #ifndef guard name
417
463
  output_style: const # const (default) | define
418
464
  static_const: true # adds 'static' keyword (default: false)
419
465
  typed_ints: true # use stdint.h types (default: false)
420
466
 
467
+ # ─── C Struct Table options ───
468
+ # parser_options:
469
+ # variant: DPB # Select specific #elif variant (or "all")
470
+ # table_var: PSC_HWVarParLUT # Struct array variable name (auto-detected)
471
+ # fields: [R_Phase, L_d, L_q, Psi, J, Imax, Tmax] # Field names (auto-detected)
472
+
421
473
  # ─── C# options ───
422
474
  namespace: MyCompany.Firmware # C# namespace
423
475
  class_name: EcuConstants # C# class name (default: Constants)
@@ -581,7 +633,7 @@ Each entry records: timestamp, user, direction, files, all constant names+values
581
633
  git clone https://github.com/naveenkumarbaskaran/consync.git
582
634
  cd consync
583
635
  pip install -e ".[dev]"
584
- pytest # 151 tests
636
+ pytest # 261 tests
585
637
  ```
586
638
 
587
639
  ---
@@ -35,10 +35,11 @@ Keep a single source of truth for hardware constants (resistor values, timing pa
35
35
  │ Parsers │ │ State │ │ Renderers │
36
36
  │ │ │ Tracker │ │ │
37
37
  │ • xlsx │ │ │ │ • c_header │
38
- │ • csv │ │ MD5 hashes │ │ • csharp
39
- │ • json │ │ per-mapping │ │ • python
40
- │ • toml │ │ in .json │ │ • rust
41
- │ • c_header │ │ │ │ • verilog
38
+ │ • csv │ │ MD5 hashes │ │ • c_struct_table
39
+ │ • json │ │ per-mapping │ │ • csharp
40
+ │ • toml │ │ in .json │ │ • python
41
+ │ • c_header │ │ │ │ • rust
42
+ │ • c_struct_table │ │ │ │ • verilog │
42
43
  └────────┬────────┘ └──────┬──────┘ │ • vhdl │
43
44
  │ │ │ • json │
44
45
  │ │ │ • csv │
@@ -117,6 +118,12 @@ mappings:
117
118
  direction: both
118
119
  precision: 17
119
120
  header_guard: HW_CONSTANTS_H
121
+
122
+ # Or for C struct tables → Excel:
123
+ # - source: MotorParams.c
124
+ # target: MotorParams.xlsx
125
+ # direction: both
126
+ # format: c_struct_table
120
127
  ```
121
128
 
122
129
  ### 2. Sync
@@ -165,17 +172,19 @@ consync install-hook
165
172
 
166
173
  | Format | Extension | Notes |
167
174
  |--------|-----------|-------|
168
- | Excel | `.xlsx` | Auto-detects column headers |
175
+ | Excel | `.xlsx` | Auto-detects flat or table layout (multi-variant) |
169
176
  | CSV | `.csv`, `.tsv` | Auto-detects delimiter |
170
- | JSON | `.json` | Flat, array, or nested |
177
+ | JSON | `.json` | Flat, array, nested, or structured (`_meta` + `constants`) |
171
178
  | TOML | `.toml` | Flat or table-with-metadata |
172
179
  | C Header | `.h` | Parses `const`, `#define`, hex/int/float |
180
+ | C Struct Table | `.c` | Multi-variant `#if`/`#elif` struct arrays (Bosch-style) |
173
181
 
174
182
  ### Targets (output)
175
183
 
176
184
  | Format | Extension | Features |
177
185
  |--------|-----------|----------|
178
186
  | C Header | `.h` | `const` or `#define`, `static`, `stdint.h` types, hex |
187
+ | C Struct Table | `.c` | In-place update of multi-variant struct arrays (minimal diffs) |
179
188
  | C# | `.cs` | `namespace`, `public static class`, XML doc comments |
180
189
  | Python | `.py` | Type annotations (`float`/`int`), inline comments |
181
190
  | Rust | `.rs` | `pub const`, `f64`/`i64`, doc comments |
@@ -183,6 +192,7 @@ consync install-hook
183
192
  | VHDL | `.vhd` | Package with `ieee.math_real`, typed constants |
184
193
  | JSON | `.json` | Structured with `_meta` header |
185
194
  | CSV | `.csv` | Round-trip back to spreadsheet |
195
+ | Excel | `.xlsx` | Multi-sheet table layout (one sheet per variant) |
186
196
 
187
197
  ---
188
198
 
@@ -190,7 +200,36 @@ consync install-hook
190
200
 
191
201
  **Don't have a spreadsheet yet?** consync can create one from your existing source files.
192
202
 
193
- If you already have a C header with constants and want to start tracking it:
203
+ ### C Struct Table Excel (multi-variant motor parameters)
204
+
205
+ Have a complex C file with `#if`/`#elif` struct arrays and want an Excel for your team to review/edit?
206
+
207
+ ```yaml
208
+ # .consync.yaml
209
+ mappings:
210
+ - source: RBPSC_HWVariantParameter.c # Existing C file with struct arrays
211
+ target: RBPSC_HWVariantParameter.xlsx # Excel will be created on first sync
212
+ direction: both # Edit C or Excel — both stay in sync
213
+ format: c_struct_table # Parses #if/#elif multi-variant tables
214
+ precision: 17
215
+ ```
216
+
217
+ ```bash
218
+ consync sync
219
+ # ✅ RBPSC_HWVariantParameter.c ↔ RBPSC_HWVariantParameter.xlsx: 160 constants synced (source → target)
220
+ ```
221
+
222
+ consync parses the C file — handling nested `{{...}}` initializers, `#if`/`#elif` variant blocks, float suffixes (`1.0F`), hex (`0xFF`), expressions — and generates a multi-sheet Excel with one sheet per variant (BWA, EMB, DPB, etc.).
223
+
224
+ After that, edit either side:
225
+ - **Edit Excel** → values sync back into the C file (in-place, minimal diffs)
226
+ - **Edit C file** → Excel updates on next `consync sync`
227
+
228
+ > **Note:** The `format: c_struct_table` field tells consync to use the struct-table parser for the `.c` file instead of the default `c_header` parser. The `.xlsx` target format is auto-detected.
229
+
230
+ ### C Header → CSV/JSON (simple constants)
231
+
232
+ If you have a simpler C header with `const`/`#define` declarations:
194
233
 
195
234
  ```yaml
196
235
  # .consync.yaml
@@ -207,7 +246,7 @@ consync sync
207
246
 
208
247
  consync parses the existing `.h` file, extracts all constants (name, value, unit, description from comments), and writes a fresh CSV. From that point forward, you have a spreadsheet to share with your EE team.
209
248
 
210
- **Works with any parseable target:** `.h`, `.json`, `.csv`, `.toml` — anything consync has a parser for can bootstrap a new source.
249
+ **Works with any parseable format:** `.h`, `.c`, `.json`, `.csv`, `.toml` — anything consync has a parser for can bootstrap a new source.
211
250
 
212
251
  ---
213
252
 
@@ -372,17 +411,30 @@ consync tracks file hashes in `.consync.state.json` to detect which side changed
372
411
  ```yaml
373
412
  # .consync.yaml
374
413
  mappings:
375
- - source: constants.xlsx # source file path (xlsx/csv/json/toml/h)
376
- target: hw_constants.h # target file path (h/cs/py/rs/v/vhd/json/csv)
414
+ - source: constants.xlsx # source file path (xlsx/csv/json/toml/h/c)
415
+ target: hw_constants.h # target file path (h/cs/py/rs/v/vhd/json/csv/xlsx)
377
416
  direction: both # source_to_target | target_to_source | both
378
417
  precision: 17 # significant digits (1-17, default: 17)
379
418
 
419
+ # ─── Format override ───
420
+ # format: c_struct_table # Override auto-detected format for the matching side.
421
+ # # Useful when .c needs c_struct_table instead of c_header.
422
+ # # Auto-assigned to whichever side's extension matches.
423
+ # source_format: xlsx # Explicit source format (overrides auto-detect)
424
+ # target_format: c_header # Explicit target format (overrides auto-detect)
425
+
380
426
  # ─── C Header options ───
381
427
  header_guard: HW_CONSTANTS_H # #ifndef guard name
382
428
  output_style: const # const (default) | define
383
429
  static_const: true # adds 'static' keyword (default: false)
384
430
  typed_ints: true # use stdint.h types (default: false)
385
431
 
432
+ # ─── C Struct Table options ───
433
+ # parser_options:
434
+ # variant: DPB # Select specific #elif variant (or "all")
435
+ # table_var: PSC_HWVarParLUT # Struct array variable name (auto-detected)
436
+ # fields: [R_Phase, L_d, L_q, Psi, J, Imax, Tmax] # Field names (auto-detected)
437
+
386
438
  # ─── C# options ───
387
439
  namespace: MyCompany.Firmware # C# namespace
388
440
  class_name: EcuConstants # C# class name (default: Constants)
@@ -546,7 +598,7 @@ Each entry records: timestamp, user, direction, files, all constant names+values
546
598
  git clone https://github.com/naveenkumarbaskaran/consync.git
547
599
  cd consync
548
600
  pip install -e ".[dev]"
549
- pytest # 151 tests
601
+ pytest # 261 tests
550
602
  ```
551
603
 
552
604
  ---
@@ -80,6 +80,26 @@ def _parse_direction(raw: str) -> SyncDirection:
80
80
  return mapping[normalized]
81
81
 
82
82
 
83
+ def _format_matches_extension(format_name: str, filepath: str) -> bool:
84
+ """Check if a format name is compatible with a file's extension."""
85
+ ext = Path(filepath).suffix.lower()
86
+ # Map format names to compatible extensions
87
+ FORMAT_COMPATIBLE_EXTENSIONS: dict[str, set[str]] = {
88
+ "c_header": {".c", ".h", ".hpp", ".hh"},
89
+ "c_struct_table": {".c", ".h", ".hpp", ".hh"},
90
+ "xlsx": {".xlsx", ".xls"},
91
+ "csv": {".csv"},
92
+ "json": {".json"},
93
+ "verilog": {".v", ".sv"},
94
+ "vhdl": {".vhd", ".vhdl"},
95
+ "python": {".py"},
96
+ "rust": {".rs"},
97
+ "csharp": {".cs"},
98
+ }
99
+ compatible = FORMAT_COMPATIBLE_EXTENSIONS.get(format_name, set())
100
+ return ext in compatible
101
+
102
+
83
103
  def _parse_mapping(raw: dict[str, Any], config_dir: Path) -> MappingConfig:
84
104
  """Parse a single mapping entry from YAML."""
85
105
  source = raw.get("source", "")
@@ -90,8 +110,19 @@ def _parse_mapping(raw: dict[str, Any], config_dir: Path) -> MappingConfig:
90
110
  if not target:
91
111
  raise ValueError("Each mapping must have a 'target' field.")
92
112
 
113
+ generic_format = raw.get("format", "")
93
114
  source_format = raw.get("source_format", "") or raw.get("format_source", "")
94
- target_format = raw.get("target_format", "") or raw.get("format_target", "") or raw.get("format", "")
115
+ target_format = raw.get("target_format", "") or raw.get("format_target", "")
116
+
117
+ # If generic 'format' is specified, assign it to the side whose extension matches
118
+ if generic_format:
119
+ if not source_format and _format_matches_extension(generic_format, source):
120
+ source_format = generic_format
121
+ elif not target_format and _format_matches_extension(generic_format, target):
122
+ target_format = generic_format
123
+ elif not target_format:
124
+ # Legacy fallback: assign to target_format (backward compat)
125
+ target_format = generic_format
95
126
 
96
127
  # Auto-detect formats if not specified
97
128
  if not source_format:
@@ -178,23 +209,31 @@ def generate_default_config() -> str:
178
209
  # Sync constants between spreadsheets and source code with full decimal precision.
179
210
 
180
211
  mappings:
212
+ # ─── Pattern 1: Spreadsheet → Code ───
213
+ # Excel is the source of truth, code is generated from it.
181
214
  - source: constants.xlsx # Where constants are defined (spreadsheet)
182
215
  target: include/constants.h # Generated code file
183
216
  direction: both # source_to_target | target_to_source | both
184
217
  precision: 17 # Significant digits (17 = full IEEE 754 double)
185
218
  header_guard: HW_CONSTANTS_H # C header include guard
186
219
 
220
+ # ─── Pattern 2: C struct table → Excel ───
221
+ # Existing C file with struct arrays — generate Excel for review/editing.
222
+ # - source: MotorParams.c # Existing C file with struct array
223
+ # target: MotorParams.xlsx # Excel generated from C (created if missing)
224
+ # direction: both # Edit either side, sync keeps them matched
225
+ # format: c_struct_table # Parser for #if/#elif struct arrays
226
+ # precision: 17
227
+
228
+ # ─── Pattern 3: Code → Spreadsheet (bootstrap) ───
229
+ # - source: params.csv # Will be created from your existing code
230
+ # target: legacy/params.h # Already exists
231
+ # direction: target_to_source # First sync creates the CSV from the .h
232
+
187
233
  # Optional:
188
234
  # prefix: "" # Prefix all constant names (e.g., "HW_")
189
235
  # uppercase_names: true # Force UPPER_CASE names in output
190
236
 
191
- # Add more mappings as needed:
192
- # - source: parameters.xlsx
193
- # target: src/params.v
194
- # direction: source_to_target
195
- # precision: 12
196
- # module_name: design_params
197
-
198
237
  # Global settings:
199
238
  # state_file: .consync.state.json # Track sync state (gitignore this)
200
239
  # watch_debounce: 2.0 # Seconds to wait before re-syncing
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "consync"
7
- version = "2.1.0"
7
+ version = "2.2.1"
8
8
  description = "Bidirectional sync between spreadsheets and source code constants — with full decimal precision."
9
9
  readme = "README.md"
10
10
  license = {text = "MIT"}
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes