""" Smoke test: every plugin module imports cleanly against the sublime stubs. Run with: python3 tests/test_imports.py """ import _bootstrap # sets sys.path for the imports below ROOT = _bootstrap.ROOT import vterm.utils import vterm.keys import vterm.emulator import vterm.scheme import vterm.terminal import vterm.render import vterm.commands import vterm.listeners import vterm.mouse # keymap and mousemap must parse the way sublime parses them: JSON with # // line comments import importlib import json import os import re import sys import types def load_sublime_json(name): with open(os.path.join(ROOT, name), encoding="utf-8") as f: return json.loads(re.sub(r"^\s*//.*$", "", f.read(), flags=re.M)) keymap = load_sublime_json("Default.sublime-keymap") assert len(keymap) > 100 # every printable must be bound, or sublime inserts it into the view and an app # that does not echo (vim in normal mode) leaves the character behind. Each # binding's key must also round-trip to that same character: the shift+ # form silently yields lowercase, which is why uppercase is bound literally. import string # noqa from vterm.keys import get_key_code bound = {} for entry in keymap: combo = entry["keys"][0] if len(combo) == 1 and entry["command"] == "vterm_keypress": assert combo not in bound, "{} bound twice".format(combo) bound[combo] = entry["args"] for char in string.ascii_letters + string.digits + string.punctuation: assert char in bound, "printable {!r} is not bound".format(char) produced = get_key_code(**bound[char]) assert produced == char, "{!r} would send {!r}".format(char, produced) assert get_key_code(key="space") == " ", "space must send a space" # legacy encodings by default; while the app has modifyOtherKeys on, the keys # whose modified form is ambiguous take the CSI 27 form instead. pi reads a # bare ESC CR as alt+enter and submits on it assert get_key_code(key="enter", shift=True) == "\x1b\r" assert get_key_code(key="enter", shift=True, modify_other_keys=2) == "\x1b[27;2;13~" assert get_key_code(key="space", ctrl=True, modify_other_keys=2) == "\x1b[27;5;32~" assert get_key_code(key="enter", modify_other_keys=2) == "\r", "unmodified keys stay legacy" assert get_key_code(key="c", ctrl=True, modify_other_keys=2) == "\x03", "ctrl+c stays a control byte" load_sublime_json("Default (OSX).sublime-mousemap") # scheme manager produces scopes and rules import vterm.scheme as scheme_module from vterm.scheme import scheme_manager scope = scheme_manager.scope("ff0000", "default", "b") assert scope == "vterm.ff0000.default.b", scope # every command referenced by the palette and the keymap must exist, and the # flags commands set must be the ones the renderer reads (a rename here is # otherwise only caught at runtime) import vterm.commands as commands import vterm.render as render import vterm.terminal as terminal_module from vterm.terminal import Terminal def command_class_name(name): return "".join(part.title() for part in name.split("_")) + "Command" for entry in load_sublime_json("vterm.sublime-commands") + keymap: cls = command_class_name(entry["command"]) assert hasattr(commands, cls) or hasattr(render, cls), \ "{} -> missing {}".format(entry["command"], cls) # every pending_* name mentioned in the modules must be a real Terminal # attribute, so a renamed flag cannot leave a writer pointing at nothing flags = {f for f in vars(Terminal(None)) if f.startswith("pending_")} assert flags == {"pending_clear", "pending_clear_screen", "pending_render"}, flags for module in (commands, render, terminal_module): with open(module.__file__, encoding="utf-8") as f: # (?