from __future__ import annotations import re from typing import Mapping from .models import ParsedConfig, Setting def _to_ini_value(setting: Setting, new_value: object) -> str: if setting.value_type == "bool": return "true" if bool(new_value) else "false" return str(new_value) def _lua_quote(value: str) -> str: # Minimal Lua string escaping for double-quoted strings. value = ( value.replace("\\", "\\\\") .replace('"', '\\"') .replace("\r", "\\r") .replace("\n", "\\n") .replace("\t", "\\t") ) return f'"{value}"' def _to_lua_value(setting: Setting, new_value: object) -> str: if setting.value_type == "bool": return "true" if bool(new_value) else "false" if setting.value_type == "int": return str(int(new_value)) if setting.value_type == "float": # Keep a plain, readable float representation. return str(float(new_value)) return _lua_quote(str(new_value)) def write_server_ini(parsed: ParsedConfig, updates: Mapping[str, object]) -> str: if parsed.source != "ini": raise ValueError("write_server_ini expects ParsedConfig(source='ini')") lines = list(parsed.lines) key_re = re.compile(r"^([A-Za-z0-9_]+)=(.*)$") for setting in parsed.settings: if setting.path not in updates: continue new_value = _to_ini_value(setting, updates[setting.path]) original = lines[setting.line_index] line_no_nl = original.rstrip("\r\n") newline = original[len(line_no_nl) :] m = key_re.match(line_no_nl) if not m: continue key = m.group(1) lines[setting.line_index] = f"{key}={new_value}{newline}" return "".join(lines) def write_sandboxvars_lua(parsed: ParsedConfig, updates: Mapping[str, object]) -> str: if parsed.source != "lua": raise ValueError("write_sandboxvars_lua expects ParsedConfig(source='lua')") lines = list(parsed.lines) for setting in parsed.settings: if setting.path not in updates: continue new_value = _to_lua_value(setting, updates[setting.path]) original = lines[setting.line_index] line_no_nl = original.rstrip("\r\n") newline = original[len(line_no_nl) :] # Replace between '=' and the final comma. eq_index = line_no_nl.find("=") comma_index = line_no_nl.rfind(",") if eq_index == -1 or comma_index == -1 or comma_index <= eq_index: continue prefix = line_no_nl[: eq_index + 1] # Preserve at least one space after '=' for readability. prefix = prefix.rstrip() + " " # Keep original indentation + key as-is. suffix = line_no_nl[comma_index:] + newline lines[setting.line_index] = f"{prefix}{new_value}{suffix}" return "".join(lines)