improved error message and connection handling

This commit is contained in:
lilydjwg 2017-04-15 12:45:13 +08:00
parent be04ddd01c
commit e70e870b97

View file

@ -5,50 +5,78 @@ import vim
import socket import socket
import struct import struct
FCITX_STATUS = struct.pack('i', 0)
FCITX_OPEN = struct.pack('i', 1 | (1 << 16))
FCITX_CLOSE = struct.pack('i', 1)
INT_SIZE = struct.calcsize('i')
fcitxsocketfile = vim.eval('s:fcitxsocketfile') fcitxsocketfile = vim.eval('s:fcitxsocketfile')
if fcitxsocketfile[0] == '@': # abstract socket class FcitxComm(object):
fcitxsocketfile = '\x00' + fcitxsocketfile[1:] STATUS = struct.pack('i', 0)
ACTIVATE = struct.pack('i', 1 | (1 << 16))
DEACTIVATE = struct.pack('i', 1)
INT_SIZE = struct.calcsize('i')
def fcitxtalk(command=None): def __init__(self, socketfile):
sock = socket.socket(socket.AF_UNIX) if socketfile[0] == '@': # abstract socket
sock.settimeout(0.5) socketfile = '\x00' + socketfile[1:]
try: self.socketfile = socketfile
sock.connect(fcitxsocketfile) self.sock = None
except (socket.error, socket.timeout):
vim.command('echohl WarningMsg | echo "fcitx.vim: socket connection error" | echohl NONE') def status(self):
return return self._with_reconnect(self._status) == 2
try:
if not command: def activate(self):
sock.send(FCITX_STATUS) self._with_reconnect(self._command, self.ACTIVATE)
return struct.unpack('i', sock.recv(INT_SIZE))[0]
elif command == 'c': def deactivate(self):
sock.send(FCITX_CLOSE) self._with_reconnect(self._command, self.DEACTIVATE)
elif command == 'o':
sock.send(FCITX_OPEN) def _error(self, e):
else: estr = str(e).replace('"', r'\"')
raise ValueError('unknown fcitx command') file = self.socketfile.replace('"', r'\"')
except (struct.error, socket.timeout): vim.command('echohl WarningMsg | echo "fcitx.vim: socket %s error: %s" | echohl NONE' % (file, estr))
# if there's a proxy of some kind, connect and send *will* succeed when
# fcitx isn't there. def _connect(self):
vim.command('echohl WarningMsg | echo "fcitx.vim: socket error" | echohl NONE') self.sock = sock = socket.socket(socket.AF_UNIX)
return sock.settimeout(0.5)
finally: try:
sock.close() sock.connect(self.socketfile)
return True
except (socket.error, socket.timeout, struct.error) as e:
self._error(e)
return False
def _with_reconnect(self, func, *args, **kwargs):
if self.sock is None:
if not self._connect():
return
for _ in range(2):
try:
return func(*args, **kwargs)
except (socket.error, socket.timeout) as e:
if self._connect():
continue
else:
return
self._error(e)
def _status(self):
self.sock.send(self.STATUS)
return struct.unpack('i', self.sock.recv(self.INT_SIZE))[0]
def _command(self, cmd):
self.sock.send(cmd)
Fcitx = FcitxComm(fcitxsocketfile)
def fcitx2en(): def fcitx2en():
if fcitxtalk() == 2: if Fcitx.status():
vim.command('let b:inputtoggle = 1') vim.command('let b:inputtoggle = 1')
fcitxtalk('c') Fcitx.deactivate()
def fcitx2zh(): def fcitx2zh():
if vim.eval('exists("b:inputtoggle")') == '1': if vim.eval('exists("b:inputtoggle")') == '1':
if vim.eval('b:inputtoggle') == '1': if vim.eval('b:inputtoggle') == '1':
fcitxtalk('o') Fcitx.activate()
vim.command('let b:inputtoggle = 0') vim.command('let b:inputtoggle = 0')
else: else:
vim.command('let b:inputtoggle = 0') vim.command('let b:inputtoggle = 0')