1#!/usr/local/bin/python3.8 2# 3# Server that will accept connections from a Vim channel. 4# Run this server and then in Vim you can open the channel: 5# :let handle = ch_open('localhost:8765') 6# 7# Then Vim can send requests to the server: 8# :let response = ch_sendexpr(handle, 'hello!') 9# 10# And you can control Vim by typing a JSON message here, e.g.: 11# ["ex","echo 'hi there'"] 12# 13# There is no prompt, just type a line and press Enter. 14# To exit cleanly type "quit<Enter>". 15# 16# See ":help channel-demo" in Vim. 17# 18# This requires Python 2.6 or later. 19 20from __future__ import print_function 21import json 22import socket 23import sys 24import threading 25 26try: 27 # Python 3 28 import socketserver 29except ImportError: 30 # Python 2 31 import SocketServer as socketserver 32 33thesocket = None 34 35class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler): 36 37 def handle(self): 38 print("=== socket opened ===") 39 global thesocket 40 thesocket = self.request 41 while True: 42 try: 43 data = self.request.recv(4096).decode('utf-8') 44 except socket.error: 45 print("=== socket error ===") 46 break 47 except IOError: 48 print("=== socket closed ===") 49 break 50 if data == '': 51 print("=== socket closed ===") 52 break 53 print("received: {0}".format(data)) 54 try: 55 decoded = json.loads(data) 56 except ValueError: 57 print("json decoding failed") 58 decoded = [-1, ''] 59 60 # Send a response if the sequence number is positive. 61 # Negative numbers are used for "eval" responses. 62 if decoded[0] >= 0: 63 if decoded[1] == 'hello!': 64 response = "got it" 65 else: 66 response = "what?" 67 encoded = json.dumps([decoded[0], response]) 68 print("sending {0}".format(encoded)) 69 self.request.sendall(encoded.encode('utf-8')) 70 thesocket = None 71 72class ThreadedTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer): 73 pass 74 75if __name__ == "__main__": 76 HOST, PORT = "localhost", 8765 77 78 server = ThreadedTCPServer((HOST, PORT), ThreadedTCPRequestHandler) 79 ip, port = server.server_address 80 81 # Start a thread with the server -- that thread will then start one 82 # more thread for each request 83 server_thread = threading.Thread(target=server.serve_forever) 84 85 # Exit the server thread when the main thread terminates 86 server_thread.daemon = True 87 server_thread.start() 88 print("Server loop running in thread: ", server_thread.name) 89 90 print("Listening on port {0}".format(PORT)) 91 while True: 92 typed = sys.stdin.readline() 93 if "quit" in typed: 94 print("Goodbye!") 95 break 96 if thesocket is None: 97 print("No socket yet") 98 else: 99 print("sending {0}".format(typed)) 100 thesocket.sendall(typed.encode('utf-8')) 101 102 server.shutdown() 103 server.server_close() 104