def chapter_to_tape(entries, chara_set, bg_set, timeline_set, bgm_set): tape = [] dialogue_color = MONOLOGUE_COLOR bg_color = BG_NONE_COLOR timeline_color = BG_NONE_COLOR bgm_color = BGM_NONE_COLOR for code, chara_name, _ in entries: if chara_name: chara_set.add(chara_name) dialogue_color = str_to_color(chara_name) else: dialogue_color = MONOLOGUE_COLOR if code: for func_name, args, _ in walk_functions(code): if (func_name in [ 'show', 'trans', 'trans2', 'trans_fade', 'trans_left', 'trans_right', 'trans_up', 'trans_down' ] and args and get_node_name(args[0]) == 'bg' and isinstance(args[1], astnodes.String)): bg_name = normalize_bg_name(args[1].s) bg_set.add(bg_name) bg_color = str_to_color(bg_name) elif (func_name == 'show_loop' and args and get_node_name(args[0]) == 'bg'): bg_name = normalize_bg_name(args[1].fields[0].value.s) bg_set.add(bg_name) bg_color = str_to_color(bg_name) elif (func_name == 'hide' and args and get_node_name(args[0]) == 'bg'): bg_color = BG_NONE_COLOR elif func_name == 'timeline': timeline_name = args[0].s timeline_set.add(timeline_name) timeline_color = str_to_color(timeline_name) elif func_name == 'timeline_hide': timeline_color = BG_NONE_COLOR elif (func_name in ['play', 'fade_in'] and args and get_node_name(args[0]) == 'bgm'): bgm_name = args[1].s bgm_set.add(bgm_name) bgm_color = str_to_color(bgm_name) elif (func_name in ['stop', 'fade_out'] and args and get_node_name(args[0]) == 'bgm'): bgm_color = BGM_NONE_COLOR if bg_color != BG_NONE_COLOR: _bg_color = bg_color else: _bg_color = timeline_color tape.append((dialogue_color, _bg_color, bgm_color)) return tape
def do_chapter(entries, bg_list): for code, _, _ in entries: if not code: continue for func_name, args, _ in walk_functions(code): if (func_name in [ 'show', 'trans', 'trans2', 'trans_fade', 'trans_left', 'trans_right', 'trans_up', 'trans_down' ] and args and get_node_name(args[0]).startswith('bg') and isinstance(args[1], astnodes.String)): bg_name = args[1].s if bg_name not in bg_list: bg_list.append(bg_name) elif (func_name == 'show_loop' and args and get_node_name(args[0]).startswith('bg')): for field in args[1].fields: bg_name = field.value.s if bg_name not in bg_list: bg_list.append(bg_name)
def parse_code(code, f): bg_name = None bgm_name = None for func_name, args, _ in walk_functions(code): if (func_name in [ 'show', 'trans', 'trans2', 'trans_fade', 'trans_left', 'trans_right', 'trans_up', 'trans_down' ] and args and get_node_name(args[0]) == 'bg' and isinstance(args[1], astnodes.String) and not args[1].s.startswith('chapter')): bg_name = args[1].s elif (func_name == 'show_loop' and args and get_node_name(args[0]) == 'bg'): bg_name = args[1].fields[0].value.s elif func_name == 'timeline': bg_name = args[0].s elif (func_name in ['play', 'fade_in'] and args and get_node_name(args[0]) == 'bgm'): bgm_name = args[1].s return bg_name, bgm_name
def check_code(code, line_num, anim_persist_tracked): for c in code: if is_special_char(c): print(f'Line {line_num}: special character U+{ord(c):04X} in code') if 'TODO' in code: print(f'Line {line_num}: TODO in code') check_anim_persist_override = False check_show = False check_trans = False try: for func_name, args, env in walk_functions(code): arg_names = [get_node_name(x) for x in args] for name in [func_name] + arg_names: if name == 'anim_persist_begin': if anim_persist_tracked: print( f'Line {line_num}: anim_persist_begin() not match') else: anim_persist_tracked = True if env: check_anim_persist_override = True if 'anim_persist' in env: print( f'Line {line_num}: anim_persist_begin() in anim_persist' ) elif name == 'anim_persist_end': if anim_persist_tracked: anim_persist_tracked = False else: print(f'Line {line_num}: anim_persist_end() not match') if env: check_anim_persist_override = True if 'anim_persist' in env: print( f'Line {line_num}: anim_persist_end() in anim_persist' ) if func_name == 'anim': if env: print(f'Line {line_num}: anim in anon function') elif func_name == 'anim_persist': if not anim_persist_tracked: print(f'Line {line_num}: anim_persist not tracked') if check_anim_persist_override and not env: print( f'Line {line_num}: anim_persist overridden by anim_persist_begin() or anim_persist_end()' ) if 'anim_persist' in env: print(f'Line {line_num}: anim_persist in anim_persist') elif func_name == 'show': if (not env and args and arg_names[0] != 'extra_text'): check_show = True elif 'trans' in func_name: if (len(args) >= 2 and arg_names[0] == 'cam' and not isinstance(args[1], astnodes.Nil)): check_trans = True except Exception as e: print(f'Line {line_num}: error when parsing code: {e}') if check_show and check_trans: print(f'Line {line_num}: show() outside of trans()') return anim_persist_tracked
def main(): with open(in_filename, 'r', encoding='utf-8') as f: chapters = parse_chapters(f) bg_name_to_pos_set = {} bg_name_to_cam_pos_set = {} for chapter_name, entries, _, _ in chapters: print(chapter_name) now_bg_name = None now_bg_pos = update_pos(None, None, DEFAULT_BG_POS) now_cam_pos = update_pos(None, None, DEFAULT_CAM_POS) for code, _, _ in entries: if not code: continue for func_name, args, _ in walk_functions(code): if (func_name == 'show' and args and get_node_name(args[0]) == 'bg' and isinstance(args[1], astnodes.String)): now_bg_name = normalize_bg_name(args[1].s) if len(args) >= 3: now_bg_pos = update_pos(now_bg_pos, parse_table(args[2]), DEFAULT_BG_POS) dict_set_add(bg_name_to_pos_set, now_bg_name, now_bg_pos) dict_set_add(bg_name_to_cam_pos_set, now_bg_name, now_cam_pos) elif (func_name in [ 'trans', 'trans2', 'trans_fade', 'trans_left', 'trans_right', 'trans_up', 'trans_down' ] and args and get_node_name(args[0]) == 'bg' and isinstance(args[1], astnodes.String)): now_bg_name = normalize_bg_name(args[1].s) dict_set_add(bg_name_to_pos_set, now_bg_name, now_bg_pos) dict_set_add(bg_name_to_cam_pos_set, now_bg_name, now_cam_pos) elif (func_name == 'show_loop' and args and get_node_name(args[0]) == 'bg'): now_bg_name = normalize_bg_name(args[1].fields[0].value.s) dict_set_add(bg_name_to_pos_set, now_bg_name, now_bg_pos) dict_set_add(bg_name_to_cam_pos_set, now_bg_name, now_cam_pos) elif (func_name == 'hide' and args and get_node_name(args[0]) == 'bg'): now_bg_name = None elif (func_name == 'move' and args and get_node_name(args[0]) == 'bg'): now_bg_pos = update_pos(now_bg_pos, parse_table(args[1]), DEFAULT_BG_POS) dict_set_add(bg_name_to_pos_set, now_bg_name, now_bg_pos) elif (func_name == 'move' and args and get_node_name(args[0]) == 'cam'): now_cam_pos = update_pos(now_cam_pos, parse_table(args[1]), DEFAULT_CAM_POS) dict_set_add(bg_name_to_cam_pos_set, now_bg_name, now_cam_pos) print() keys = [x for x in bg_name_to_pos_set.keys() if x] for k in sorted(keys): print(k) print('pos:') for pos in sorted(bg_name_to_pos_set[k], key=typed_item): print(pos) print('cam_pos:') for pos in sorted(bg_name_to_cam_pos_set[k], key=typed_item): print(pos) print()
def lint_file(in_filename): with open(in_filename, 'r', encoding='utf-8') as f: chapters = parse_chapters(f, keep_line_num=True) for chapter_name, entries, _, _ in chapters: print(chapter_name) anim_persist_tracked = True for code, chara_name, dialogue, line_num in entries: if code and not dialogue: print(f'Line {line_num}: code block with empty dialogue') if code: for line in code.splitlines(): if not line: print(f'Line {line_num}: empty line in code block') check_show = False check_trans = False check_anim_persist_override = False try: for func_name, args, env in walk_functions(code): if func_name == 'anim': if env: print( f'Line {line_num}: anim in anon function') elif func_name == 'anim_persist_begin': anim_persist_tracked = True if env: check_anim_persist_override = True elif func_name == 'anim_persist_end': if anim_persist_tracked: anim_persist_tracked = False else: print( f'Line {line_num}: anim_persist_end() not match' ) if env: check_anim_persist_override = True elif func_name == 'anim_persist': if 'anim_persist' in env: print( f'Line {line_num}: anim_persist in anim_persist' ) if not anim_persist_tracked: print( f'Line {line_num}: anim_persist not tracked' ) if check_anim_persist_override and not env: print( f'Line {line_num}: anim_persist overridden by anim_persist_begin() or anim_persist_end()' ) if func_name == 'show': if (not env and args and get_node_name(args[0]) != 'extra_text'): check_show = True elif 'trans' in func_name: if (len(args) >= 2 and get_node_name(args[0]) == 'cam' and not isinstance(args[1], astnodes.Nil)): check_trans = True except Exception as e: print(f'Line {line_num}: error when parsing code: {e}') if check_show and check_trans: print(f'Line {line_num}: show() outside of trans()') if dialogue: normal_dialogue = normalize_dialogue(dialogue) if chara_name: if not normal_dialogue.startswith('“'): print( f'Line {line_num}: dialogue not start with quotation mark' ) if not normal_dialogue.endswith('”'): print( f'Line {line_num}: dialogue not end with quotation mark' ) else: match = re.compile('.*?:“.*?”').fullmatch(normal_dialogue) if match: print(f'Line {line_num}: quote with single colon') # if len(normal_dialogue) > 54: # print( # f'Line {line_num}: normal_dialogue longer than 54 chars' # ) if any(x in normal_dialogue for x in ',.?!;:\'"()'): print(f'Line {line_num}: half width punctuation') match = re.compile('(TODO:(.*?):.*?)').search(normal_dialogue) if match: print(f'Line {line_num}: TODO: {match.group(1)} found') elif 'TODO' in normal_dialogue: print(f'Line {line_num}: TODO found')