Use classes for managing vim interaction

Create classes for interacting with vim, a base class with common
methods, a class for interacting via screen, and one for interacting on
Windows.

At startup time an instance of one of these classes is created, and that
object is passed to all of the tests instead of the session.

I haven't been able to get UltiSnips working in vim on Windows to really
test this, but I have verified that vim interactions still work.
This commit is contained in:
Aaron Schrab 2012-08-08 18:08:29 -04:00
parent 461a475d2a
commit fc22af0d1e

195
test.py
View File

@ -39,8 +39,6 @@ import sys
from textwrap import dedent from textwrap import dedent
WIN = platform.system() == "Windows"
# Some constants for better reading # Some constants for better reading
BS = '\x7f' BS = '\x7f'
ESC = '\x1b' ESC = '\x1b'
@ -63,102 +61,96 @@ EA = "#" # Expand anonymous
COMPL_KW = chr(24)+chr(14) COMPL_KW = chr(24)+chr(14)
COMPL_ACCEPT = chr(25) COMPL_ACCEPT = chr(25)
class VimInterface:
def focus(title=None):
pass
################ windows ################ def send_keystrokes(self, str, sleeptime):
"""
Send the keystrokes to vim via screen. Pause after each char, so
vim can handle this
"""
for c in str:
self.send(c)
time.sleep(sleeptime)
if WIN: class VimInterfaceScreen(VimInterface):
# import windows specific modules def __init__(self, session):
import win32com.client, win32gui self.session = session
shell = win32com.client.Dispatch("WScript.Shell")
def focus_win(title=None): def send(self, s):
if not shell.AppActivate(title or "- GVIM"): s = s.replace("'", r"'\''")
raise Exception("Failed to switch to GVim window") cmd = "screen -x %s -X stuff '%s'" % (self.session, s)
time.sleep(1) if sys.version_info >= (3,0):
cmd = cmd.encode("utf-8")
os.system(cmd)
def is_focused(title=None): class VimInterfaceWindows(VimInterface):
cur_title = win32gui.GetWindowText(win32gui.GetForegroundWindow()) BRACES = re.compile("([}{])")
if (title or "- GVIM") in cur_title: WIN_ESCAPES = ["+", "^", "%", "~", "[", "]", "<", ">", "(", ")"]
return True WIN_REPLACES = [
return False (BS, "{BS}"),
(ARR_L, "{LEFT}"),
(ARR_R, "{RIGHT}"),
(ARR_U, "{UP}"),
(ARR_D, "{DOWN}"),
("\t", "{TAB}"),
("\n", "~"),
(ESC, "{ESC}"),
BRACES = re.compile("([}{])") # On my system ` waits for a second keystroke, so `+SPACE = "`". On
WIN_ESCAPES = ["+", "^", "%", "~", "[", "]", "<", ">", "(", ")"] # most systems, `+Space = "` ". I work around this, by sending the host
WIN_REPLACES = [ # ` as `+_+BS. Awkward, but the only way I found to get this working.
(BS, "{BS}"), ("`", "`_{BS}"),
(ARR_L, "{LEFT}"), ("´", "´_{BS}"),
(ARR_R, "{RIGHT}"), ("{^}", "{^}_{BS}"),
(ARR_U, "{UP}"), ]
(ARR_D, "{DOWN}"),
("\t", "{TAB}"),
("\n", "~"),
(ESC, "{ESC}"),
# On my system ` waits for a second keystroke, so `+SPACE = "`". On def __init__(self):
# most systems, `+Space = "` ". I work around this, by sending the host self.seq_buf = []
# ` as `+_+BS. Awkward, but the only way I found to get this working. # import windows specific modules
("`", "`_{BS}"), import win32com.client, win32gui
("´", "´_{BS}"), self.win32gui = win32gui
("{^}", "{^}_{BS}"), self.shell = win32com.client.Dispatch("WScript.Shell")
]
def convert_keys(keys):
keys = BRACES.sub(r"{\1}", keys)
for k in WIN_ESCAPES:
keys = keys.replace(k, "{%s}" % k)
for f, r in WIN_REPLACES:
keys = keys.replace(f, r)
return keys
SEQ_BUF = [] def is_focused(self, title=None):
def send_win(keys, session): cur_title = self.win32gui.GetWindowText(self.win32gui.GetForegroundWindow())
global SEQ_BUF if (title or "- GVIM") in cur_title:
SEQ_BUF.append(keys) return True
seq = "".join(SEQ_BUF) return False
for f in SEQUENCES: def focus(self, title=None):
if f.startswith(seq) and f != seq: if not self.shell.AppActivate(title or "- GVIM"):
return raise Exception("Failed to switch to GVim window")
SEQ_BUF = [] time.sleep(1)
seq = convert_keys(seq) def convert_keys(self, keys):
keys = self.BRACES.sub(r"{\1}", keys)
for k in self.WIN_ESCAPES:
keys = keys.replace(k, "{%s}" % k)
for f, r in self.WIN_REPLACES:
keys = keys.replace(f, r)
return keys
if not is_focused(): def send(self, keys):
time.sleep(2) self.seq_buf.append(keys)
focus() seq = "".join(self.seq_buf)
if not is_focused():
# This is the only way I can find to stop test execution
raise KeyboardInterrupt("Failed to focus GVIM")
shell.SendKeys(seq) for f in SEQUENCES:
if f.startswith(seq) and f != seq:
return
self.seq_buf = []
################ end windows ################ seq = self.convert_keys(seq)
def send_screen(s, session): if not self.is_focused():
s = s.replace("'", r"'\''") time.sleep(2)
cmd = "screen -x %s -X stuff '%s'" % (session, s) self.focus()
if sys.version_info >= (3,0): if not self.is_focused():
cmd = cmd.encode("utf-8") # This is the only way I can find to stop test execution
os.system(cmd) raise KeyboardInterrupt("Failed to focus GVIM")
self.shell.SendKeys(seq)
def send(s, session):
if WIN:
send_win(s, session)
else:
send_screen(s, session)
def focus(title=None):
if WIN:
focus_win(title=title)
def send_keystrokes(str, session, sleeptime):
"""
Send the keystrokes to vim via screen. Pause after each char, so
vim can handle this
"""
for c in str:
send(c, session)
time.sleep(sleeptime)
class _VimTest(unittest.TestCase): class _VimTest(unittest.TestCase):
snippets = ("dummy", "donotdefine") snippets = ("dummy", "donotdefine")
@ -176,7 +168,7 @@ class _VimTest(unittest.TestCase):
skip_on_mac = False skip_on_mac = False
def send(self,s): def send(self,s):
send(s, self.session) self.vim.send(s)
def send_py(self,s): def send_py(self,s):
if sys.version_info < (3,0): if sys.version_info < (3,0):
@ -185,7 +177,7 @@ class _VimTest(unittest.TestCase):
self.send(":py3 << EOF\n%s\nEOF\n" % s) self.send(":py3 << EOF\n%s\nEOF\n" % s)
def send_keystrokes(self,s): def send_keystrokes(self,s):
send_keystrokes(s, self.session, self.sleeptime) self.vim.send_keystrokes(s, self.sleeptime)
def check_output(self): def check_output(self):
wanted = self.text_before + '\n\n' + self.wanted + \ wanted = self.text_before + '\n\n' + self.wanted + \
@ -2924,40 +2916,45 @@ if __name__ == '__main__':
test_loader = unittest.TestLoader() test_loader = unittest.TestLoader()
all_test_suites = test_loader.loadTestsFromModule(__import__("test")) all_test_suites = test_loader.loadTestsFromModule(__import__("test"))
focus() if platform.system() == "Windows":
vim = VimInterfaceWindows()
else:
vim = VimInterfaceScreen(options.session)
vim.focus()
# Ensure we are not running in VI-compatible mode. # Ensure we are not running in VI-compatible mode.
send(""":set nocompatible\n""", options.session) vim.send(""":set nocompatible\n""")
# Do not mess with the X clipboard # Do not mess with the X clipboard
send(""":set clipboard=""\n""", options.session) vim.send(""":set clipboard=""\n""")
# Set encoding and fileencodings # Set encoding and fileencodings
send(""":set encoding=utf-8\n""", options.session) vim.send(""":set encoding=utf-8\n""")
send(""":set fileencoding=utf-8\n""", options.session) vim.send(""":set fileencoding=utf-8\n""")
# Tell vim not to complain about quitting without writing # Tell vim not to complain about quitting without writing
send(""":set buftype=nofile\n""", options.session) vim.send(""":set buftype=nofile\n""")
# Ensure runtimepath includes only Vim's own runtime files # Ensure runtimepath includes only Vim's own runtime files
# and those of the UltiSnips directory under test ('.'). # and those of the UltiSnips directory under test ('.').
send(""":set runtimepath=$VIMRUNTIME,.\n""", options.session) vim.send(""":set runtimepath=$VIMRUNTIME,.\n""")
# Set the options # Set the options
send(""":let g:UltiSnipsExpandTrigger="<tab>"\n""", options.session) vim.send(""":let g:UltiSnipsExpandTrigger="<tab>"\n""")
send(""":let g:UltiSnipsJumpForwardTrigger="?"\n""", options.session) vim.send(""":let g:UltiSnipsJumpForwardTrigger="?"\n""")
send(""":let g:UltiSnipsJumpBackwardTrigger="+"\n""", options.session) vim.send(""":let g:UltiSnipsJumpBackwardTrigger="+"\n""")
send(""":let g:UltiSnipsListSnippets="@"\n""", options.session) vim.send(""":let g:UltiSnipsListSnippets="@"\n""")
# Now, source our runtime # Now, source our runtime
send(":so plugin/UltiSnips.vim\n", options.session) vim.send(":so plugin/UltiSnips.vim\n")
time.sleep(2) # Parsing and initializing UltiSnips takes a while. time.sleep(2) # Parsing and initializing UltiSnips takes a while.
# Inform all test case which screen session to use # Inform all test case which screen session to use
suite = unittest.TestSuite() suite = unittest.TestSuite()
for s in all_test_suites: for s in all_test_suites:
for test in s: for test in s:
test.session = options.session test.vim = vim
test.interrupt = options.interrupt test.interrupt = options.interrupt
if len(selected_tests): if len(selected_tests):
id = test.id().split('.')[1] id = test.id().split('.')[1]