docs: Documentar setSilent() y descripciones extendidas v0.2.4
- setSilent(): carga masiva sin disparar observers - Formato extendido auto_validate: opcion=descripcion - Genera comentarios multilínea en archivo config - 100% compatible hacia atrás 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
3dd835eb51
commit
da50ebfc75
2 changed files with 150 additions and 17 deletions
100
CLAUDE.md
100
CLAUDE.md
|
|
@ -26,7 +26,7 @@ PATH=/mnt/cello2/arno/re/recode/zig/zig-0.15.2/zig-x86_64-linux-0.15.2:$PATH zig
|
||||||
| Campo | Valor |
|
| Campo | Valor |
|
||||||
|-------|-------|
|
|-------|-------|
|
||||||
| **Nombre** | zcatconfig |
|
| **Nombre** | zcatconfig |
|
||||||
| **Version** | v0.2.3 |
|
| **Version** | v0.2.4 |
|
||||||
| **Fecha inicio** | 2025-12-17 |
|
| **Fecha inicio** | 2025-12-17 |
|
||||||
| **Estado** | FUNCIONAL - Integrado en zsimifactu (arquitectura 3 fuentes) |
|
| **Estado** | FUNCIONAL - Integrado en zsimifactu (arquitectura 3 fuentes) |
|
||||||
| **Lenguaje** | Zig 0.15.2 |
|
| **Lenguaje** | Zig 0.15.2 |
|
||||||
|
|
@ -321,6 +321,103 @@ const separator_pos = blk: {
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## setSilent() - Carga masiva sin observers (v0.2.4)
|
||||||
|
|
||||||
|
### Problema
|
||||||
|
|
||||||
|
Al cargar config desde BD, cada `set()` dispara observers que escriben de vuelta a BD → loop infinito de logs.
|
||||||
|
|
||||||
|
### Solución
|
||||||
|
|
||||||
|
`setSilent()` establece valores SIN notificar observers:
|
||||||
|
|
||||||
|
```zig
|
||||||
|
// Cargar desde BD sin disparar observers
|
||||||
|
var stmt = try db.prepare("SELECT config_key, config_value FROM config_backup");
|
||||||
|
while (try stmt.step()) {
|
||||||
|
const key = stmt.columnText(0) orelse continue;
|
||||||
|
const value = stmt.columnText(1) orelse continue;
|
||||||
|
// Usar setSilent en vez de set
|
||||||
|
manager.setSilent(key, value) catch continue;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### API
|
||||||
|
|
||||||
|
```zig
|
||||||
|
/// Establece valor SIN notificar observers
|
||||||
|
/// Útil para carga masiva desde BD
|
||||||
|
pub fn setSilent(self: *Self, key: []const u8, value: []const u8) ConfigError!void
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## DESCRIPCIONES EXTENDIDAS EN ARCHIVO CONFIG (v0.2.4)
|
||||||
|
|
||||||
|
### Problema
|
||||||
|
|
||||||
|
El archivo de configuración mostraba opciones pero no explicaba qué hacía cada una:
|
||||||
|
|
||||||
|
```
|
||||||
|
@validacion_nif_modo: Estricto # Modo validación NIF [Estricto,Permisivo,Desactivado]
|
||||||
|
```
|
||||||
|
|
||||||
|
El usuario ve las opciones pero no sabe qué significa cada una.
|
||||||
|
|
||||||
|
### Solución: Formato extendido en auto_validate
|
||||||
|
|
||||||
|
En `config_variables`, usar formato `opcion=descripcion`:
|
||||||
|
|
||||||
|
```zig
|
||||||
|
// Formato simple (sin descripciones):
|
||||||
|
.{ "mi_var", .string, .cat, "Op1,Op2,Op3", "Descripción", ... }
|
||||||
|
|
||||||
|
// Formato extendido (con descripciones):
|
||||||
|
.{ "mi_var", .string, .cat, "Op1=Hace X,Op2=Hace Y,Op3=Hace Z", "Descripción", ... }
|
||||||
|
```
|
||||||
|
|
||||||
|
### Resultado en archivo config
|
||||||
|
|
||||||
|
**Formato simple** (sin `=`):
|
||||||
|
```
|
||||||
|
@mi_var: Op1 # Descripción [Op1,Op2,Op3]
|
||||||
|
```
|
||||||
|
|
||||||
|
**Formato extendido** (con `=`):
|
||||||
|
```
|
||||||
|
# Descripción
|
||||||
|
# Op1: Hace X
|
||||||
|
# Op2: Hace Y
|
||||||
|
# Op3: Hace Z
|
||||||
|
@mi_var: Op1
|
||||||
|
```
|
||||||
|
|
||||||
|
### Ejemplo real
|
||||||
|
|
||||||
|
```zig
|
||||||
|
// En config_unified.zig:
|
||||||
|
.{ "validacion_nif_modo", .string, Cat.validaciones,
|
||||||
|
"Estricto=Bloquea guardar si NIF inválido,Permisivo=Avisa pero permite guardar,Desactivado=Sin validación",
|
||||||
|
"Modo validación NIF", false, "# VALIDACIONES" },
|
||||||
|
```
|
||||||
|
|
||||||
|
Genera:
|
||||||
|
```
|
||||||
|
# Modo validación NIF
|
||||||
|
# Estricto: Bloquea guardar si NIF inválido
|
||||||
|
# Permisivo: Avisa pero permite guardar
|
||||||
|
# Desactivado: Sin validación
|
||||||
|
@validacion_nif_modo: Estricto
|
||||||
|
```
|
||||||
|
|
||||||
|
### Compatibilidad
|
||||||
|
|
||||||
|
- Si `auto_validate` NO contiene `=` → formato simple (actual)
|
||||||
|
- Si `auto_validate` contiene `=` → formato extendido (nuevo)
|
||||||
|
- 100% compatible con archivos existentes
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## EQUIPO
|
## EQUIPO
|
||||||
|
|
||||||
- **Usuario (R.Eugenio)**: Desarrollador principal
|
- **Usuario (R.Eugenio)**: Desarrollador principal
|
||||||
|
|
@ -332,6 +429,7 @@ const separator_pos = blk: {
|
||||||
|
|
||||||
| Fecha | Version | Commit | Cambios |
|
| Fecha | Version | Commit | Cambios |
|
||||||
|-------|---------|--------|---------|
|
|-------|---------|--------|---------|
|
||||||
|
| 2025-12-25 | v0.2.4 | `3dd835e` | setSilent() + descripciones extendidas en archivo config |
|
||||||
| 2025-12-18 | v0.2.3 | `957767d` | validateIntRange/Float fix: rangos negativos `"-100-100"` |
|
| 2025-12-18 | v0.2.3 | `957767d` | validateIntRange/Float fix: rangos negativos `"-100-100"` |
|
||||||
| 2025-12-18 | v0.2.2 | `0ef5efd` | initDeferred(): control manual sin auto-crear archivo |
|
| 2025-12-18 | v0.2.2 | `0ef5efd` | initDeferred(): control manual sin auto-crear archivo |
|
||||||
| 2025-12-18 | v0.2.1 | - | FileWatcher, loadFromString, updateMtime |
|
| 2025-12-18 | v0.2.1 | - | FileWatcher, loadFromString, updateMtime |
|
||||||
|
|
|
||||||
|
|
@ -563,7 +563,41 @@ pub fn save(
|
||||||
const value_len = value.len;
|
const value_len = value.len;
|
||||||
const total_len = key_len + 2 + value_len;
|
const total_len = key_len + 2 + value_len;
|
||||||
|
|
||||||
// Construir comentario con opciones válidas si existen
|
// Verificar si tiene descripciones extendidas (formato "opcion=desc,opcion2=desc2")
|
||||||
|
const has_descriptions = if (v.auto_validate) |valid|
|
||||||
|
std.mem.indexOf(u8, valid, "=") != null
|
||||||
|
else
|
||||||
|
false;
|
||||||
|
|
||||||
|
if (has_descriptions) {
|
||||||
|
// Formato extendido: comentarios multilínea
|
||||||
|
// # Descripción de la variable
|
||||||
|
// # Opcion1: Descripción 1
|
||||||
|
// # Opcion2: Descripción 2
|
||||||
|
// @variable: valor
|
||||||
|
var desc_line: [256]u8 = undefined;
|
||||||
|
const desc_text = std.fmt.bufPrint(&desc_line, "# {s}\n", .{v.description}) catch "";
|
||||||
|
try file.writeAll(desc_text);
|
||||||
|
|
||||||
|
// Parsear opciones con descripciones
|
||||||
|
var options_iter = std.mem.splitScalar(u8, v.auto_validate.?, ',');
|
||||||
|
while (options_iter.next()) |option_desc| {
|
||||||
|
if (std.mem.indexOf(u8, option_desc, "=")) |eq_pos| {
|
||||||
|
const opt_name = option_desc[0..eq_pos];
|
||||||
|
const opt_desc = option_desc[eq_pos + 1 ..];
|
||||||
|
const opt_line = std.fmt.bufPrint(&desc_line, "# {s}: {s}\n", .{ opt_name, opt_desc }) catch "";
|
||||||
|
try file.writeAll(opt_line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Escribir variable sin comentario inline
|
||||||
|
const line = std.fmt.bufPrint(&line_buf, "{s}: {s}\n", .{
|
||||||
|
v.config_key,
|
||||||
|
value,
|
||||||
|
}) catch unreachable;
|
||||||
|
try file.writeAll(line);
|
||||||
|
} else {
|
||||||
|
// Formato simple: comentario inline con opciones entre corchetes
|
||||||
var comment_buf: [256]u8 = undefined;
|
var comment_buf: [256]u8 = undefined;
|
||||||
const comment: []const u8 = if (v.auto_validate) |valid|
|
const comment: []const u8 = if (v.auto_validate) |valid|
|
||||||
std.fmt.bufPrint(&comment_buf, "{s} [{s}]", .{ v.description, valid }) catch v.description
|
std.fmt.bufPrint(&comment_buf, "{s} [{s}]", .{ v.description, valid }) catch v.description
|
||||||
|
|
@ -577,16 +611,17 @@ pub fn save(
|
||||||
value,
|
value,
|
||||||
spaces(padding),
|
spaces(padding),
|
||||||
comment,
|
comment,
|
||||||
}) catch unreachable; // Buffer 1024 es suficiente
|
}) catch unreachable;
|
||||||
try file.writeAll(line);
|
try file.writeAll(line);
|
||||||
} else {
|
} else {
|
||||||
const line = std.fmt.bufPrint(&line_buf, "{s}: {s}\n", .{
|
const line = std.fmt.bufPrint(&line_buf, "{s}: {s}\n", .{
|
||||||
v.config_key,
|
v.config_key,
|
||||||
value,
|
value,
|
||||||
}) catch unreachable; // Buffer 1024 es suficiente
|
}) catch unreachable;
|
||||||
try file.writeAll(line);
|
try file.writeAll(line);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
try file.writeAll("\n");
|
try file.writeAll("\n");
|
||||||
try file.writeAll("# ============================================================================\n");
|
try file.writeAll("# ============================================================================\n");
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue