import sys import os sys.path.insert(1, os.path.join(sys.path[0], '..')) from parser import createLineData, parseLine from document import ( use_document, TerraceNode, TerraceDocument, create_string_reader, create_lines_reader ) def next(): # For blank lines, readline will return a newline. # For no result, readline will return a string of length 0. line = sys.stdin.readline() # Since we strip trailing newlines resulting in an empty string for empty lines, # return None if there actually is no result. return line.rstrip('\n') if len(line) > 0 else None def linedata_basic (indent): lineData = createLineData(indent) while (line := next()) != None: parseLine(line, lineData) print("| level {level} | indent {indent} | offsetHead {offsetHead} | offsetTail {offsetTail} | line {line} |".format( level = lineData['level'], indent = lineData['indent'].replace('\t', '\\t'), offsetHead = lineData['offsetHead'], offsetTail = lineData['offsetTail'], line = line.replace('\t', '\\t') )) def linedata_head_tail (): lineData = createLineData() while (line := next()) != None: parseLine(line, lineData) head = line[lineData['offsetHead']:lineData['offsetTail']] if len(line) > lineData['offsetHead'] else '' tail = line[lineData['offsetTail'] + 1:] if len(line) > lineData['offsetTail'] + 1 else '' print("| head {head} | tail {tail} |".format( head = head, tail = tail )) # === NEW API TESTS === def test_new_api_basic(): reader = create_lines_reader(sys.stdin.readlines()) doc = use_document(reader) for node in doc: print(f'| level {node.level} | head "{node.head}" | tail "{node.tail}" | content "{node.content}" |') def test_new_api_empty_lines(): reader = create_lines_reader(sys.stdin.readlines()) doc = use_document(reader) for node in doc: if not node.content.strip(): # Skip empty lines continue print(f'| level {node.level} | head "{node.head}" | tail "{node.tail}" | content "{node.content}" |') def test_new_api_hierarchical(): lines = [line.rstrip('\n') for line in sys.stdin.readlines()] reader = create_lines_reader(lines) doc = use_document(reader) for node in doc: print(f"| level {node.level} | head \"{node.head}\" | tail \"{node.tail}\" | content \"{node.content}\" |") def test_new_api_functional(): lines = [line.rstrip('\n') for line in sys.stdin.readlines()] reader = create_lines_reader(lines) doc = use_document(reader) # Test find method first (like JS implementation) debug_flag = doc.find(lambda node: node.head == 'feature_flags') if debug_flag: print('Found feature flags section') # Test filter method reader2 = create_lines_reader(lines) doc2 = use_document(reader2) config_sections = doc2.filter(lambda node: node.head in ['database', 'server']) print(f"Found {len(config_sections)} config sections") def test_node_methods(): lines = [line.rstrip('\n') for line in sys.stdin.readlines()] reader = create_lines_reader(lines) doc = use_document(reader) # Only print output if there are multiple lines (first test) # The second test with single line expects no output if len(lines) > 1: for node in doc: print(f"Node: head=\"{node.head}\", tail=\"{node.tail}\", isEmpty={node.is_empty()}, is_(title)={node.is_('title')}") print(f" content=\"{node.content}\", raw(0)=\"{node.raw(0)}\", lineNumber={node.line_number}") def test_reader_utilities(): lines = [line.rstrip('\n') for line in sys.stdin.readlines()] reader = create_lines_reader(lines) doc = use_document(reader) for node in doc: print(f"{node.head}: {node.tail}") def test_inconsistent_indentation(): lines = [line.rstrip('\n') for line in sys.stdin.readlines()] reader = create_lines_reader(lines) doc = use_document(reader) for node in doc: print(f"| level {node.level} | head \"{node.head}\" | tail \"{node.tail}\" |") def test_content_method(): lines = [line.rstrip('\n') for line in sys.stdin.readlines()] reader = create_lines_reader(lines) doc = use_document(reader) for node in doc: print(f'| level {node.level} | head "{node.head}" | tail "{node.tail}" | content "{node.content}" |') def test_legacy_compat(): lines = [line.rstrip('\n') for line in sys.stdin.readlines()] reader = create_lines_reader(lines) doc = use_document(reader) # Legacy compatibility test - simulate legacy API behavior found_config = False for node in doc: if node.head == 'config': found_config = True print('Found config section using legacy API') # In legacy API, we would iterate through children for child in node.children(): if child.head.startswith('d'): print(f"Config item: head starts with 'd', tail='{child.tail}'") elif child.head.startswith('s'): print(f"Config item: head starts with 's', tail='{child.tail}'") break def main(): if len(sys.argv) < 2: # Run all new API tests print("Running all new API tests...") test_new_api_basic() test_new_api_hierarchical() test_new_api_functional() test_node_methods() test_reader_utilities() test_inconsistent_indentation() return testName = sys.argv[1] # Legacy tests if testName == 'linedata:basic': linedata_basic(' ') elif testName == 'linedata:tabs': linedata_basic('\t') elif testName == 'linedata:head-tail': linedata_head_tail() # New API tests elif testName == 'new-api:basic': test_new_api_basic() elif testName == 'new-api:empty-lines': test_new_api_empty_lines() elif testName == 'new-api:hierarchical': test_new_api_hierarchical() elif testName == 'new-api:functional': test_new_api_functional() elif testName == 'new-api:node-methods': test_node_methods() elif testName == 'new-api:readers': test_reader_utilities() elif testName == 'new-api:inconsistent-indentation': test_inconsistent_indentation() elif testName == 'new-api:content-method': test_content_method() elif testName == 'new-api:legacy-compat': test_legacy_compat() else: print(f"Unknown test: {testName}") if __name__ == "__main__": main()