def start(self, host='localhost', port='4001'): coro = asyncio.start_server(self.handler_factory.handler(), host, port, loop=self.loop) self.server = self.loop.run_until_complete(coro) ghost_log.p('server listen on {}:{}'.format(host, port))
def stop_server(): if (int(vim.eval('exists("g:channel")')) == 1 and vim.eval('ch_status(g:channel)') == "open"): ghost_log.p('closing channel') vim.command('call ch_close(g:channel)') ghost_log.p('stopping server') single_server.stop_server()
async def send(self, message): '''send a message to vim ''' if self.writer: self.writer.write(message.encode()) await self.writer.drain() else: ghost_log.p('error: vim channel not connected')
async def send(self, buf_name, text, selection): ''' find the corresponding websocket and send ''' for ws, info in self.connections.items(): if info['name'] == buf_name: resp = info['template'] resp['text'] = text ghost_log.p('server -> browser, text len {}'.format(len(text))) ghost_log.p2('server -> browser, {}'.format(json.dumps(resp))) await ws.send(json.dumps(resp))
async def coro(json_from_vim): buf_name = json_from_vim['buf_name'] msg = json_from_vim['text'] ws_man = self.ws_manager_wr() if not ws_man: ghost_log.p( 'warning: no connection to browswer, ignore msg from vim') return ghost_log.p2('vim -> server, {}'.format(json_from_vim)) ghost_log.p('vim -> server, text len {}'.format(len(msg))) await ws_man.send(buf_name, msg, None)
def stop_server(): '''todo: check if the server is running stopping the server and stop the server thread ''' global st if st == None: ghost_log.p("server not started yet") return st.stop() ghost_log.p("server stoped") st = None
def start_server(): '''todo: check if the server is alreayd running start the http and websocket server in separate thread so it is not blocking here ''' global st if st != None: ghost_log.p("server already started") return True st = server_thread.ServerThread() ret = st.start() if not ret: st = None return ret
def update_text(name, lines, selections): _is_updating_from_remote = True if int(vim.eval('buffer_exists("{}")'.format(name))) == 1: vim.command('buf ' + name) else: vim.command('enew') vim.command('file ' + name) # todo : if current buffer is not the `name`d buffer, switch it vim.command(':b ' + name) mode = vim.eval('mode()') if not mode == 'n': ghost_log.p('mode', mode) vim.command('call feedkeys("\<esc>")') vim.command(":redraw") vim.current.buffer[:] = lines.split('\n') vim.command(":redraw") vim.command(":call cursor({})".format(selections)) _is_updating_from_remote = False
async def ws_handler(websocket, path): flag_first_message = True while True: try: msg = await websocket.recv() json_msg = json.loads(msg) # todo: add exception handling if flag_first_message: global _buf_idx buf_name = 'GhostText_{}.txt'.format(_buf_idx) _buf_idx = _buf_idx + 1 # on first message, create a map ghost_log.p('add buf_name {}'.format(buf_name)) self.connections[websocket] = { 'name': buf_name, 'template': json_msg } flag_first_message = False await self.rx_coro(buf_name, json_msg) except websockets.exceptions.ConnectionClosed: break ghost_log.p('remove buf_name {}'.format( self.connections[websocket]['name'])) del self.connections[websocket] ghost_log.p("connection closed")
def text_changed_from_vim(): name = os.path.basename(vim.current.buffer.name) if not name.startswith("GhostText"): return if _is_updating_from_remote: return ghost_log.p('text changed from vim') text = '\n'.join(vim.current.buffer) # vim.command() selections = [{'start': 1, 'end': 1}] json_dict = json.dumps({ 'buf_name': name, 'text': text, 'selections': selections }) if (int(vim.eval('exists("g:channel")')) == 1 and vim.eval('ch_status(g:channel)') == "open"): cmd = ':call ch_sendraw(g:channel,{})'.format(json.dumps(json_dict)) vim.command(cmd)
def start_server(): if not single_server.start_server(): return for _ in range(3): time.sleep(.1) vim.command("let g:channel = ch_open('localhost:4002')") if vim.eval('ch_status(g:channel)') == "open": ghost_log.p('GhostText for vim started') return ghost_log.p('could not open channel to localhost:4002, retry...') ghost_log.p('fail to start GhostText for vim')
async def channel_handler(reader, writer): ghost_log.p('vim channel connected') if not self.writer == None: ghost_log.p('error, only one vim channel connection allowed') return self.writer = writer while True: # todo: to allow abitry length of jason data = await reader.read(1024 * 1024) if not data: break try: json_data = json.loads(data.decode()) except ValueError: ghost_log.p("json decoding failed") continue # todo: send to remote via websocket await self.channel_rx_coro(json_data) ghost_log.p('vim channel closed') writer.close() self.writer = None
async def coro(buf_name, msg_from_browser): ''' msg_from_browser is the json from browser ''' ghost_log.p2('server <- browser, {}'.format(msg_from_browser)) text = msg_from_browser['text'] ghost_log.p('server <- browser, text len {}'.format(len(text))) try: cursor_pos = msg_from_browser['selections'][0]['end'] pos = _cursor_pos(text, cursor_pos) except: pos = (1, 1) chnl = self.channel_wr() if not chnl: ghost_log.p( 'error: no connection to vim, ignore msg from browser') return # using the name to update text in vim cmd = json.dumps( ["call", "GhostTextUpdateText", [buf_name, text, list(pos)]]) ghost_log.p2('vim <- server, {}'.format(cmd)) ghost_log.p('vim <- server, text len {}'.format(len(text))) await chnl.send(cmd)
def close(self): self.server.close() ghost_log.p('websocket server requested to close') self.loop.run_until_complete(self.server.wait_closed()) ghost_log.p('websocket server all closed')
def start(self, host='localhost', port='8765'): start_server = websockets.serve(self.ws_manager.handler(), host, port) self.server = self.loop.run_until_complete(start_server) ghost_log.p('websockets server listen on {}:{}'.format(host, port))