使用python模拟命令行终端的示例
可以对?显示帮助信息,需要立即获取输入的字符,因此需要用到termios模块
另外需要对tab键做处理,当按下tab键时可以进行自动补全
#!/usr/bin/envpython
#coding=utf-8
importos
importsys
importtty
importtermios
'''
Enter:13
Back:127
?:63
C-h:8
C-w:23
Tab:9
C-u:21
C-c:3
C-d:4
C-\:28
SPACE:32
'''
CLI_KEY_CNCR=13
CLI_KEY_BACK=127
CLI_KEY_QMARK=63
CLI_KEY_CTRLH=8
CLI_KEY_CTRLW=23
CLI_KEY_TAB=9
CLI_KEY_CTRLU=21
CLI_KEY_CTRLC=3
CLI_KEY_CTRLD=4
CLI_KEY_QUIT=28
CLI_KEY_SPACE=32
CLI_KEY_TABLEN=4
classCLI(object):
def__init__(self):
self.line=''
self.line_complete=''
self.completer_on=False
self.completer_dict={}
self.completer_dict_keys=self.completer_dict.keys()
self.completer_id=0
self.completer_cnt=len(self.completer_dict)
defgetch(self):
fd=sys.stdin.fileno()
old_settings=termios.tcgetattr(fd)
try:
tty.setraw(fd)
ch=sys.stdin.read(1)
finally:
termios.tcsetattr(fd,termios.TCSADRAIN,old_settings)
returnch
defcompleter_kw_update(self):
self.completer_dict_keys=self.completer_dict.keys()
self.completer_dict_keys.sort()
self.completer_cnt=len(self.completer_dict)
defcompleter_kw_add(self,key,word):
self.completer_dict[key]=word
self.completer_kw_update()
defcompleter_kw_clear(self):
self.completer_dict.clear()
self.completer_id_update()
defcompleter_id_update(self):
self.completer_kw_update()
ifself.completer_id0:
completer=self.completer_dict_keys[self.completer_id]
self.completer_id_update()
cnt-=1
ifword==completer[:len(word)]:
returncompleter[len(word):]
return''
defprintf(self,info=''):
sys.stdout.write(info)
defshow_spec_len_str(self,info,maxlen,spacech=''):
'displayastringofthespecifiedlength'
maxlen=maxlen
infolen=len(info)
ifmaxlen0:
ch=info[-infolen]
foriinrange(self.char_memory_len(ch)):
self.printf(info[i-infolen])
infolen-=self.char_memory_len(ch)
maxlen-=self.char_display_len(ch)
whilemaxlen>0:
self.printf(spacech)
maxlen-=self.char_display_len(spacech)
defshow_help_info(self):
ifself.completer_on:
line=self.line_complete
else:
line=self.line
lastwd=''
show_all=False
ifnotlineorline[-1]=='':
show_all=True
else:
lastwd=line.split()[-1]
ifself.completer_dict:
maxlen=max([len(info)forinfoinself.completer_dict])
else:
maxlen=12
forinfoinself.completer_dict:
ifshow_allorlastwd==info[:len(lastwd)]:
self.printf('')
self.show_spec_len_str(info,maxlen)
self.printf('')
self.printf(self.completer_dict[info])
self.printf('\r\n')
defis_chinese_char(self,ch):
returnord(ch)>127
defchar_display_len(self,ch):
ifself.is_chinese_char(ch):
return2
eliford(ch)==CLI_KEY_TAB:
returnCLI_KEY_TABLEN
else:
return1
defchar_memory_len(self,ch):
ifself.is_chinese_char(ch):
return3
else:
return1
defrm_last_char(self,line):
lastch=''
rmlen=0
iflen(line)>0:
lastch=line[-1]
self.printf('\b\b'*self.char_display_len(lastch))
rmlen=self.char_memory_len(lastch)
iflen(line)>=rmlen:
line=line[:-(rmlen)]
else:
rmlen=len(line)
line=''
returnrmlen,line
defrm_last_word(self,line):
lastwd=''
linelen=len(line)
rspacelen=linelen-len(line.rstrip())
ifnotlinelen:
returnline
lastwd=line.split()[-1]
backlen=len(lastwd)+rspacelen
rmlen=0
whilebacklen>0andline:
rmlen,line=self.rm_last_char(line)
backlen-=rmlen
returnline
defrm_one_line(self,line):
rmlen=0
whileline:
rmlen,line=self.rm_last_char(line)
returnline
defdo_line_complete_proc(self):
line=self.line
line_complete=self.line_complete
lastwd=''
self.printf('\r\n')
ifself.line_complete:
self.printf(self.line_complete)
else:
self.printf(self.line)
ifnotline:
returnline
lastwd=line.split()[-1]
completer=self.completer_wd_select(lastwd)
ifnotcompleter.strip():
self.line_complete=line
returnline
backlen=len(line_complete)-len(line)
whilebacklen>0andline_complete:
rmlen,line_complete=self.rm_last_char(line_complete)
backlen-=rmlen
self.printf(completer)
line_complete=line+completer
self.line_complete=line_complete
defdo_line_complete_end(self):
ifself.completer_on:
self.line=self.line_complete
self.line_complete=''
self.completer_on=False
defget_line(self):
self.line=''
self.line_complete=''
self.completer_on=False
whileTrue:
ch=self.getch()
ifch=='\r'orch=='\n':
self.do_line_complete_end()
self.printf('\r\n')
break
eliford(ch)==CLI_KEY_BACKorord(ch)==CLI_KEY_CTRLH:
ifself.completer_on:
rmlen,self.line_complete=self.rm_last_char(self.line_complete)
else:
rmlen,self.line=self.rm_last_char(self.line)
self.do_line_complete_end()
eliford(ch)==CLI_KEY_QMARK:
self.printf('?')
self.printf('\r\n')
self.show_help_info()
ifself.completer_on:
self.printf(self.line_complete)
else:
self.printf(self.line)
eliford(ch)==CLI_KEY_CTRLW:
ifself.completer_on:
self.line_complete=self.rm_last_word(self.line_complete)
else:
self.line=self.rm_last_word(self.line)
self.do_line_complete_end()
eliford(ch)==CLI_KEY_TAB:
self.completer_on=True
self.do_line_complete_proc()
eliford(ch)==CLI_KEY_CTRLD:
ifself.line:
returnself.line
else:
returnch
eliford(ch)==CLI_KEY_QUIT:
self.printf('\r\nInterruptedby.\r\n')
sys.exit()
eliford(ch)==CLI_KEY_CTRLU:
ifself.completer_on:
self.line_complete=self.rm_one_line(self.line_complete)
else:
self.line=self.rm_one_line(self.line)
self.do_line_complete_end()
eliford(ch)==CLI_KEY_SPACE:
self.printf(ch)
ifself.completer_on:
self.line_complete+=ch
else:
self.line+=ch
else:
self.printf(ch)
self.do_line_complete_end()
self.line+=ch
#chineseqmaskproc
iford(ch)==159andlen(self.line)>=3andself.line[-3:]=='\xef\xbc\x9f':
self.printf('\r\n')
self.line=self.line[:-3]
self.show_help_info()
self.printf(self.line)
returnself.line
defget_raw_line(self):
self.raw_line=''
whileTrue:
ch=self.getch()
ifch=='\r'orch=='\n':
self.printf('\r\n')
break
eliford(ch)==CLI_KEY_BACKorord(ch)==CLI_KEY_CTRLH:
rmlen,self.raw_line=self.rm_last_char(self.raw_line)
eliford(ch)==CLI_KEY_CTRLW:
self.raw_line=self.rm_last_word(self.raw_line)
eliford(ch)==CLI_KEY_TAB:
self.printf(''*self.char_display_len(ch))
self.raw_line+=ch
eliford(ch)==CLI_KEY_CTRLD:
ifself.raw_line:
returnself.raw_line
else:
returnch
eliford(ch)==CLI_KEY_QUIT:
self.printf('\r\nInterruptedby.\r\n')
sys.exit()
eliford(ch)==CLI_KEY_CTRLU:
self.raw_line=self.rm_one_line(self.raw_line)
else:
self.raw_line+=ch
self.printf(ch)
returnself.raw_line
deftest():
cli=CLI()
help_info={
'hello0':'sayhello0',
'hello1':'sayhello1',
'hellohello':'sayhellohello',
'hellohehe':'sayhellohehe',
'hellohi':'sayhellohi',
'你好啊':'say你好啊',
'你好吗':'say你好吗',
'你好哈':'say你好哈',
}
forkeyinhelp_info:
cli.completer_kw_add(key,help_info[key])
whileTrue:
line=cli.get_line()
iflen(line)==1andord(line[0])==CLI_KEY_CTRLD:
break
ifline=='quit':
break
print(line)
if__name__=="__main__":
test()
以上这篇使用python模拟命令行终端的示例就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持毛票票。