mirror of
https://github.com/littlecodersh/ItChat.git
synced 2026-10-18 06:30:32 +08:00
229 lines
7.8 KiB
Python
229 lines
7.8 KiB
Python
#coding=utf8
|
|
import thread, time, sys, os, platform
|
|
|
|
try:
|
|
import termios, tty
|
|
termios.tcgetattr, termios.tcsetattr
|
|
import threading
|
|
OS = 'Linux'
|
|
except (ImportError, AttributeError):
|
|
try:
|
|
import msvcrt
|
|
OS = 'Windows'
|
|
except ImportError:
|
|
raise Exception('Mac is currently not supported')
|
|
OS = 'Mac'
|
|
else:
|
|
getch = msvcrt.getwch
|
|
else:
|
|
def fn():
|
|
try:
|
|
fd = sys.stdin.fileno()
|
|
old_settings = termios.tcgetattr(fd)
|
|
tty.setraw(fd)
|
|
ch = sys.stdin.read(1)
|
|
except:
|
|
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
|
|
raise Exception
|
|
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
|
|
return ch
|
|
getch = fn
|
|
|
|
CMD_HISTORY = 30
|
|
|
|
class ChatLikeCMD():
|
|
def __init__(self, header = 'LittleCoder', symbol = '>', inPip = None, inputMaintain = False):
|
|
self.strBuff = []
|
|
self.cmdBuff = []
|
|
self.historyCmd = -1
|
|
self.cursor = 0
|
|
self.inPip = [] if inPip == None else inPip
|
|
self.outPip = []
|
|
self.isLaunch = False
|
|
self.isPause = False
|
|
self.header = header
|
|
self.symbol = symbol
|
|
self.inputMaintain = inputMaintain
|
|
def reprint_input(self):
|
|
sys.stdout.write(self.header + self.symbol)
|
|
if self.strBuff:
|
|
for i in self.strBuff: sys.stdout.write(i)
|
|
sys.stdout.flush()
|
|
def getch(self):
|
|
c = getch()
|
|
return c if c != '\r' else '\n'
|
|
def get_history_command(self, direction):
|
|
if direction == 'UP':
|
|
if self.historyCmd < CMD_HISTORY - 1 and self.historyCmd < len(self.cmdBuff) - 1: self.historyCmd += 1
|
|
else:
|
|
if self.historyCmd == 0: return ''
|
|
if self.historyCmd > 0: self.historyCmd -= 1
|
|
if -1 < self.historyCmd < len(self.cmdBuff): return self.cmdBuff[self.historyCmd]
|
|
def output_command(self, s):
|
|
self.outPip.append(s if isinstance(s, unicode) else s.decode(sys.stdin.encoding))
|
|
if len(self.cmdBuff) >= CMD_HISTORY: self.cmdBuff = self.cmdBuff[::-1].pop()[::-1]
|
|
self.cmdBuff.append(s)
|
|
def print_thread(self):
|
|
while self.isLaunch:
|
|
if self.inPip:
|
|
sys.stdout.write('\r' + ' ' * 50 + '\r')
|
|
sys.stdout.flush()
|
|
print self.inPip.pop()
|
|
# linux special
|
|
sys.stdout.write('\r')
|
|
sys.stdout.flush()
|
|
self.reprint_input()
|
|
time.sleep(0.01)
|
|
def fast_input_test(self):
|
|
timer = threading.Timer(0.001, thread.interrupt_main)
|
|
c = None
|
|
try:
|
|
timer.start()
|
|
c = getch()
|
|
except:
|
|
pass
|
|
timer.cancel()
|
|
return c
|
|
def process_direction_char(self, c):
|
|
if OS == 'Windows':
|
|
if ord(c) == 72:
|
|
c = 'A'
|
|
elif ord(c) == 80:
|
|
c = 'B'
|
|
elif ord(c) == 77:
|
|
c = 'C'
|
|
elif ord(c) == 75:
|
|
c = 'D'
|
|
if ord(c) == 68: # LEFT
|
|
self.process_char('\b')
|
|
return
|
|
# cursor bugs
|
|
if self.cursor > 0:
|
|
if OS == 'Windows':
|
|
sys.stdout.write(chr(224) + chr(75))
|
|
else:
|
|
sys.stdout.write(chr(27) + '[C')
|
|
self.cursor -= 1
|
|
elif ord(c) == 67: # RIGHT
|
|
return
|
|
# cursor bugs
|
|
if self.cursor < len(self.strBuff):
|
|
if OS == 'Windows':
|
|
sys.stdout.write(chr(224) + chr(77))
|
|
else:
|
|
sys.stdout.write(chr(27) + '[D')
|
|
self.cursor += 1
|
|
elif ord(c) == 65: # UP
|
|
hc = self.get_history_command('UP')
|
|
if not hc is None:
|
|
self.strBuff = [i for i in hc]
|
|
self.cursor = len(hc)
|
|
sys.stdout.write('\r' + ' ' * 50 + '\r')
|
|
self.reprint_input()
|
|
elif ord(c) == 66: # DOWN
|
|
hc = self.get_history_command('DOWN')
|
|
if not hc is None:
|
|
self.strBuff = [i for i in hc]
|
|
self.cursor = len(hc)
|
|
sys.stdout.write('\r' + ' ' * 50 + '\r')
|
|
self.reprint_input()
|
|
else:
|
|
raise Exception(c)
|
|
def process_char(self, c):
|
|
if ord(c) == 27: # Esc
|
|
if OS == 'Linux':
|
|
fitc1 = self.fast_input_test()
|
|
if ord(fitc1) == 91:
|
|
fitc2 = self.fast_input_test()
|
|
if 65 <= ord(fitc2) <= 68:
|
|
self.process_direction_char(fitc2)
|
|
return
|
|
sys.stdout.write('\r' + ' ' * 50 + '\r')
|
|
sys.stdout.flush()
|
|
self.reprint_input()
|
|
self.outPip.append(c)
|
|
time.sleep(0.02)
|
|
if 'fitc1' in dir():
|
|
self.process_char(fitc1)
|
|
self.cursor += 1
|
|
if 'fitc2' in dir():
|
|
self.process_char(fitc2)
|
|
self.cursor += 1
|
|
elif ord(c) == 3: # Ctrl+C
|
|
self.stop()
|
|
self.isPause = True
|
|
if raw_input('Exit?(y) ') == 'y':
|
|
sys.stdout.write('Command Line Exit')
|
|
else:
|
|
self.start()
|
|
self.isPause = False
|
|
elif ord(c) in (8, 127): # Backspace
|
|
if self.strBuff:
|
|
if ord(self.strBuff[-1]) < 128:
|
|
sys.stdout.write('\b \b')
|
|
else:
|
|
sys.stdout.write('\b\b \b')
|
|
if OS == 'Linux':
|
|
self.strBuff.pop()
|
|
self.strBuff.pop()
|
|
self.strBuff.pop()
|
|
self.cursor -= 1
|
|
elif c == '\n':
|
|
if self.strBuff:
|
|
if self.inputMaintain:
|
|
sys.stdout.write(c)
|
|
else:
|
|
sys.stdout.write('\r' + ' ' * 50 + '\r')
|
|
sys.stdout.flush()
|
|
self.reprint_input()
|
|
self.output_command(''.join(self.strBuff))
|
|
self.strBuff = []
|
|
self.historyCmd = -1
|
|
elif ord(c) == 224: # Windows direction
|
|
if OS == 'Windows':
|
|
direction = self.getch()
|
|
self.process_direction_char(direction)
|
|
else:
|
|
sys.stdout.write(c)
|
|
sys.stdout.flush()
|
|
self.strBuff.append(c)
|
|
self.cursor += 1
|
|
def command_thread(self):
|
|
c = None
|
|
while self.isLaunch:
|
|
c = self.getch()
|
|
self.process_char(c)
|
|
time.sleep(0.01)
|
|
def start(self):
|
|
self.isLaunch = True
|
|
thread.start_new_thread(self.print_thread, ())
|
|
self.reprint_input()
|
|
thread.start_new_thread(self.command_thread, ())
|
|
def stop(self):
|
|
sys.stdout.write('\r' + ' ' * 50 + '\r')
|
|
sys.stdout.flush()
|
|
self.isLaunch = False
|
|
def print_line(self, msg = None):
|
|
self.inPip.append(msg)
|
|
def clear(self):
|
|
os.system('cls' if platform.system() == 'Windows' else 'clear')
|
|
self.reprint_input()
|
|
def get_command_pip(self):
|
|
return self.outPip
|
|
def set_header(self, header):
|
|
self.header = header
|
|
|
|
if __name__ == '__main__':
|
|
c = ChatLikeCMD()
|
|
s = c.get_command_pip()
|
|
c.start()
|
|
def loopinput(c):
|
|
while True:
|
|
c.print_line('LOOP INPUT......')
|
|
time.sleep(3)
|
|
thread.start_new_thread(loopinput, (c,))
|
|
while c.isLaunch or c.isPause:
|
|
if s:
|
|
c.print_line(s.pop())
|
|
time.sleep(0.01)
|