app
Codex
Public Made by Adomby adom
Codex in Adom Hydrogen: ecosystem setup, dock dashboard and live engineering demos.
main
John Lauer
Keep Codex turns running across editor reloads; fix hidden-tab startup and composer fade in the optional package
4307d94
1mo ago
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
"""Edit one top-level JSONC setting while preserving comments and other bytes."""
import json
import re
def masked(text):
# Keep offsets unchanged while removing comments and trailing commas.
pattern = r'"(?:\\.|[^"\\])*"|//[^\n]*|/\*[\s\S]*?\*/'
clean = re.sub(pattern, lambda m: m[0] if m[0].startswith('"') else
''.join('\n' if c == '\n' else ' ' for c in m[0]), text)
return re.sub(r'"(?:\\.|[^"\\])*"|,(?=\s*[}\]])',
lambda m: ' ' if m[0] == ',' else m[0], clean)
def entries(text):
clean = masked(text)
parsed = json.loads(clean)
if not isinstance(parsed, dict):
raise ValueError('VS Code settings must be an object')
decoder = json.JSONDecoder()
pos = clean.index('{') + 1
found = []
while True:
while clean[pos].isspace() or clean[pos] == ',': pos += 1
if clean[pos] == '}': break
start = pos
key, pos = decoder.raw_decode(clean, pos)
while clean[pos].isspace(): pos += 1
if clean[pos] != ':': raise ValueError('Expected setting colon')
pos += 1
while clean[pos].isspace(): pos += 1
value_start = pos
value, pos = decoder.raw_decode(clean, pos)
found.append((key, value, start, value_start, pos))
if len({e[0] for e in found}) != len(found):
raise ValueError('Duplicate settings keys; preserving file for review')
return found, pos
def change(text, key, value=None, remove=False):
items, closing = entries(text)
match = next((e for e in items if e[0] == key), None)
if match:
_, old, start, begin, end = match
if not remove:
return text[:begin] + json.dumps(value) + text[end:]
# Remove the property and its following comma if present; otherwise
# remove the preceding separator. Preserve comments between properties.
clean = re.sub(r'"(?:\\.|[^"\\])*"|//[^\n]*|/\*[\s\S]*?\*/',
lambda m: m[0] if m[0].startswith('"') else ' ' * len(m[0]), text)
after = end
while clean[after].isspace(): after += 1
if clean[after] == ',':
return text[:start] + text[end:after] + text[after + 1:]
before = start - 1
while clean[before].isspace(): before -= 1
if clean[before] == ',':
return text[:before] + text[before + 1:start] + text[end:]
return text[:start] + text[end:]
if remove: return text
# Insert immediately after the last value, keeping trailing comments and
# an existing trailing comma attached to the resulting last property.
at = items[-1][4] if items else text.index('{') + 1
addition = (',' if items else '') + '\n ' + json.dumps(key) + ': ' + json.dumps(value)
return text[:at] + addition + text[at:]